summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra/config.cpp3
-rw-r--r--src/citra/default_ini.h3
-rw-r--r--src/citra_qt/config.cpp4
-rw-r--r--src/citra_qt/debugger/disassembler.cpp4
-rw-r--r--src/core/CMakeLists.txt16
-rw-r--r--src/core/arm/arm_interface.h6
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp49
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h14
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp74
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp536
-rw-r--r--src/core/arm/interpreter/arm_interpreter.cpp51
-rw-r--r--src/core/arm/interpreter/arm_interpreter.h6
-rw-r--r--src/core/arm/interpreter/armemu.cpp772
-rw-r--r--src/core/arm/interpreter/armsupp.cpp110
-rw-r--r--src/core/arm/skyeye_common/armdefs.h11
-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.cpp1925
-rw-r--r--src/core/file_sys/archive_backend.h152
-rw-r--r--src/core/file_sys/archive_romfs.cpp34
-rw-r--r--src/core/file_sys/archive_romfs.h8
-rw-r--r--src/core/file_sys/archive_savedata.cpp2
-rw-r--r--src/core/file_sys/archive_systemsavedata.h2
-rw-r--r--src/core/file_sys/directory_romfs.cpp10
-rw-r--r--src/core/file_sys/disk_archive.cpp10
-rw-r--r--src/core/file_sys/disk_archive.h16
-rw-r--r--src/core/file_sys/file_romfs.cpp32
-rw-r--r--src/core/hle/hle.cpp8
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp7
-rw-r--r--src/core/hle/kernel/event.cpp15
-rw-r--r--src/core/hle/kernel/kernel.cpp124
-rw-r--r--src/core/hle/kernel/kernel.h196
-rw-r--r--src/core/hle/kernel/mutex.cpp11
-rw-r--r--src/core/hle/kernel/semaphore.cpp9
-rw-r--r--src/core/hle/kernel/session.h4
-rw-r--r--src/core/hle/kernel/shared_memory.cpp11
-rw-r--r--src/core/hle/kernel/thread.cpp27
-rw-r--r--src/core/hle/kernel/thread.h3
-rw-r--r--src/core/hle/service/ac_u.cpp3
-rw-r--r--src/core/hle/service/ac_u.h6
-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.h4
-rw-r--r--src/core/hle/service/am_net.cpp3
-rw-r--r--src/core/hle/service/am_net.h6
-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.cpp3
-rw-r--r--src/core/hle/service/apt_u.h7
-rw-r--r--src/core/hle/service/boss_u.cpp19
-rw-r--r--src/core/hle/service/boss_u.h20
-rw-r--r--src/core/hle/service/cecd_u.h4
-rw-r--r--src/core/hle/service/cfg/cfg_i.cpp69
-rw-r--r--src/core/hle/service/cfg/cfg_i.h6
-rw-r--r--src/core/hle/service/cfg/cfg_u.cpp4
-rw-r--r--src/core/hle/service/cfg/cfg_u.h6
-rw-r--r--src/core/hle/service/csnd_snd.cpp3
-rw-r--r--src/core/hle/service/csnd_snd.h6
-rw-r--r--src/core/hle/service/dsp_dsp.cpp3
-rw-r--r--src/core/hle/service/dsp_dsp.h6
-rw-r--r--src/core/hle/service/err_f.cpp18
-rw-r--r--src/core/hle/service/err_f.h20
-rw-r--r--src/core/hle/service/frd_u.cpp34
-rw-r--r--src/core/hle/service/frd_u.h20
-rw-r--r--src/core/hle/service/fs/archive.cpp10
-rw-r--r--src/core/hle/service/fs/fs_user.cpp3
-rw-r--r--src/core/hle/service/fs/fs_user.h7
-rw-r--r--src/core/hle/service/gsp_gpu.cpp3
-rw-r--r--src/core/hle/service/gsp_gpu.h8
-rw-r--r--src/core/hle/service/hid_user.cpp4
-rw-r--r--src/core/hle/service/hid_user.h8
-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.cpp3
-rw-r--r--src/core/hle/service/ir_rst.h6
-rw-r--r--src/core/hle/service/ir_u.cpp3
-rw-r--r--src/core/hle/service/ir_u.h6
-rw-r--r--src/core/hle/service/ldr_ro.cpp1
-rw-r--r--src/core/hle/service/ldr_ro.h4
-rw-r--r--src/core/hle/service/mic_u.cpp3
-rw-r--r--src/core/hle/service/mic_u.h6
-rw-r--r--src/core/hle/service/ndm_u.cpp3
-rw-r--r--src/core/hle/service/ndm_u.h8
-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.h4
-rw-r--r--src/core/hle/service/nwm_uds.cpp3
-rw-r--r--src/core/hle/service/nwm_uds.h6
-rw-r--r--src/core/hle/service/pm_app.cpp3
-rw-r--r--src/core/hle/service/pm_app.h6
-rw-r--r--src/core/hle/service/ptm_u.cpp3
-rw-r--r--src/core/hle/service/ptm_u.h6
-rw-r--r--src/core/hle/service/service.cpp17
-rw-r--r--src/core/hle/service/service.h5
-rw-r--r--src/core/hle/service/soc_u.cpp3
-rw-r--r--src/core/hle/service/soc_u.h6
-rw-r--r--src/core/hle/service/srv.cpp3
-rw-r--r--src/core/hle/service/srv.h9
-rw-r--r--src/core/hle/service/ssl_c.cpp3
-rw-r--r--src/core/hle/service/ssl_c.h8
-rw-r--r--src/core/hle/svc.cpp30
-rw-r--r--src/core/hw/gpu.cpp71
-rw-r--r--src/core/hw/gpu.h1
-rw-r--r--src/core/settings.h1
-rw-r--r--src/video_core/clipper.cpp77
-rw-r--r--src/video_core/command_processor.cpp5
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp51
-rw-r--r--src/video_core/pica.h20
-rw-r--r--src/video_core/rasterizer.cpp28
-rw-r--r--src/video_core/vertex_shader.cpp12
110 files changed, 2934 insertions, 2976 deletions
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index b9d6441be..2bf0dff35 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -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/default_ini.h b/src/citra/default_ini.h
index a281c536f..f41020f7b 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -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_qt/config.cpp b/src/citra_qt/config.cpp
index 0fea8e4f9..1596c08d7 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -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/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/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c00fc3493..fdd97c184 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -32,8 +32,10 @@ set(SRCS
32 hle/kernel/shared_memory.cpp 32 hle/kernel/shared_memory.cpp
33 hle/kernel/thread.cpp 33 hle/kernel/thread.cpp
34 hle/service/ac_u.cpp 34 hle/service/ac_u.cpp
35 hle/service/act_u.cpp
35 hle/service/am_app.cpp 36 hle/service/am_app.cpp
36 hle/service/am_net.cpp 37 hle/service/am_net.cpp
38 hle/service/apt_a.cpp
37 hle/service/apt_u.cpp 39 hle/service/apt_u.cpp
38 hle/service/boss_u.cpp 40 hle/service/boss_u.cpp
39 hle/service/cecd_u.cpp 41 hle/service/cecd_u.cpp
@@ -43,17 +45,19 @@ set(SRCS
43 hle/service/csnd_snd.cpp 45 hle/service/csnd_snd.cpp
44 hle/service/dsp_dsp.cpp 46 hle/service/dsp_dsp.cpp
45 hle/service/err_f.cpp 47 hle/service/err_f.cpp
48 hle/service/frd_u.cpp
46 hle/service/fs/archive.cpp 49 hle/service/fs/archive.cpp
47 hle/service/fs/fs_user.cpp 50 hle/service/fs/fs_user.cpp
48 hle/service/frd_u.cpp
49 hle/service/gsp_gpu.cpp 51 hle/service/gsp_gpu.cpp
50 hle/service/hid_user.cpp 52 hle/service/hid_user.cpp
53 hle/service/http_c.cpp
51 hle/service/ir_rst.cpp 54 hle/service/ir_rst.cpp
52 hle/service/ir_u.cpp 55 hle/service/ir_u.cpp
53 hle/service/ldr_ro.cpp 56 hle/service/ldr_ro.cpp
54 hle/service/mic_u.cpp 57 hle/service/mic_u.cpp
55 hle/service/nim_aoc.cpp
56 hle/service/ndm_u.cpp 58 hle/service/ndm_u.cpp
59 hle/service/news_u.cpp
60 hle/service/nim_aoc.cpp
57 hle/service/nwm_uds.cpp 61 hle/service/nwm_uds.cpp
58 hle/service/pm_app.cpp 62 hle/service/pm_app.cpp
59 hle/service/ptm_u.cpp 63 hle/service/ptm_u.cpp
@@ -118,8 +122,10 @@ set(HEADERS
118 hle/kernel/shared_memory.h 122 hle/kernel/shared_memory.h
119 hle/kernel/thread.h 123 hle/kernel/thread.h
120 hle/service/ac_u.h 124 hle/service/ac_u.h
125 hle/service/act_u.h
121 hle/service/am_app.h 126 hle/service/am_app.h
122 hle/service/am_net.h 127 hle/service/am_net.h
128 hle/service/apt_a.h
123 hle/service/apt_u.h 129 hle/service/apt_u.h
124 hle/service/boss_u.h 130 hle/service/boss_u.h
125 hle/service/cecd_u.h 131 hle/service/cecd_u.h
@@ -129,17 +135,19 @@ set(HEADERS
129 hle/service/csnd_snd.h 135 hle/service/csnd_snd.h
130 hle/service/dsp_dsp.h 136 hle/service/dsp_dsp.h
131 hle/service/err_f.h 137 hle/service/err_f.h
138 hle/service/frd_u.h
132 hle/service/fs/archive.h 139 hle/service/fs/archive.h
133 hle/service/fs/fs_user.h 140 hle/service/fs/fs_user.h
134 hle/service/frd_u.h
135 hle/service/gsp_gpu.h 141 hle/service/gsp_gpu.h
136 hle/service/hid_user.h 142 hle/service/hid_user.h
143 hle/service/http_c.h
137 hle/service/ir_rst.h 144 hle/service/ir_rst.h
138 hle/service/ir_u.h 145 hle/service/ir_u.h
139 hle/service/ldr_ro.h 146 hle/service/ldr_ro.h
140 hle/service/mic_u.h 147 hle/service/mic_u.h
141 hle/service/nim_aoc.h
142 hle/service/ndm_u.h 148 hle/service/ndm_u.h
149 hle/service/news_u.h
150 hle/service/nim_aoc.h
143 hle/service/nwm_uds.h 151 hle/service/nwm_uds.h
144 hle/service/pm_app.h 152 hle/service/pm_app.h
145 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 c59355339..3b7209418 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -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/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index 6d4fb1b48..a838fd25a 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -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 6fa2a0ba7..7284dcd07 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -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..551bb77a6 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp
@@ -28,9 +28,40 @@
28#include "core/arm/dyncom/arm_dyncom_dec.h" 28#include "core/arm/dyncom/arm_dyncom_dec.h"
29 29
30const ISEITEM arm_instruction[] = { 30const ISEITEM arm_instruction[] = {
31 #define VFP_DECODE 31 {"vmla", 4, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0},
32 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 32 {"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 33 {"vnmla", 4, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0},
34 {"vnmla", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
35 {"vnmls", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
36 {"vnmul", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
37 {"vmul", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
38 {"vadd", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
39 {"vsub", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
40 {"vdiv", 5, ARMVFP2, 23, 27, 0x1D, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
41 {"vmov(i)", 4, ARMVFP3, 23, 27, 0x1D, 20, 21, 0x3, 9, 11, 0x5, 4, 7, 0},
42 {"vmov(r)", 5, ARMVFP3, 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 1, 4, 4, 0},
43 {"vabs", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
44 {"vneg", 5, ARMVFP2, 23, 27, 0x1D, 17, 21, 0x18, 9, 11, 0x5, 6, 7, 1, 4, 4, 0},
45 {"vsqrt", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x31, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
46 {"vcmp", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x34, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
47 {"vcmp2", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x35, 9, 11, 0x5, 0, 6, 0x40},
48 {"vcvt(bds)", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x37, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
49 {"vcvt(bff)", 6, ARMVFP3, 23, 27, 0x1D, 19, 21, 0x7, 17, 17, 0x1, 9, 11,5, 6, 6, 1},
50 {"vcvt(bfi)", 5, ARMVFP2, 23, 27, 0x1D, 19, 21, 0x7, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
51 {"vmovbrs", 3, ARMVFP2, 21, 27, 0x70, 8, 11, 0xA, 0, 6, 0x10},
52 {"vmsr", 2, ARMVFP2, 20, 27, 0xEE, 0, 11, 0xA10},
53 {"vmovbrc", 4, ARMVFP2, 23, 27, 0x1C, 20, 20, 0x0, 8, 11, 0xB, 0,4,0x10},
54 {"vmrs", 2, ARMVFP2, 20, 27, 0xEF, 0, 11, 0xA10},
55 {"vmovbcr", 4, ARMVFP2, 24, 27, 0xE, 20, 20, 1, 8, 11, 0xB, 0,4,0x10},
56 {"vmovbrrss", 3, ARMVFP2, 21, 27, 0x62, 8, 11, 0xA, 4, 4, 1},
57 {"vmovbrrd", 3, ARMVFP2, 21, 27, 0x62, 6, 11, 0x2C, 4, 4, 1},
58 {"vstr", 3, ARMVFP2, 24, 27, 0xD, 20, 21, 0, 9, 11,5},
59 {"vpush", 3, ARMVFP2, 23, 27, 0x1A, 16, 21, 0x2D, 9, 11,5},
60 {"vstm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 0, 9, 11,5},
61 {"vpop", 3, ARMVFP2, 23, 27, 0x19, 16, 21, 0x3D, 9, 11,5},
62 {"vldr", 3, ARMVFP2, 24, 27, 0xD, 20, 21, 1, 9, 11,5},
63 {"vldm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 1, 9, 11,5},
64
34 {"srs" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000001, 16, 20, 0x0000000d, 8, 11, 0x00000005}, 65 {"srs" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000001, 16, 20, 0x0000000d, 8, 11, 0x00000005},
35 {"rfe" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000000, 20, 20, 0x00000001, 8, 11, 0x0000000a}, 66 {"rfe" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000000, 20, 20, 0x00000001, 8, 11, 0x0000000a},
36 {"bkpt" , 2 , 3 , 20, 31, 0x00000e12, 4, 7, 0x00000007}, 67 {"bkpt" , 2 , 3 , 20, 31, 0x00000e12, 4, 7, 0x00000007},
@@ -187,9 +218,40 @@ const ISEITEM arm_instruction[] = {
187}; 218};
188 219
189const ISEITEM arm_exclusion_code[] = { 220const ISEITEM arm_exclusion_code[] = {
190 #define VFP_DECODE_EXCLUSION 221 {"vmla", 0, ARMVFP2, 0},
191 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 222 {"vmls", 0, ARMVFP2, 0},
192 #undef VFP_DECODE_EXCLUSION 223 {"vnmla", 0, ARMVFP2, 0},
224 {"vnmla", 0, ARMVFP2, 0},
225 {"vnmls", 0, ARMVFP2, 0},
226 {"vnmul", 0, ARMVFP2, 0},
227 {"vmul", 0, ARMVFP2, 0},
228 {"vadd", 0, ARMVFP2, 0},
229 {"vsub", 0, ARMVFP2, 0},
230 {"vdiv", 0, ARMVFP2, 0},
231 {"vmov(i)", 0, ARMVFP3, 0},
232 {"vmov(r)", 0, ARMVFP3, 0},
233 {"vabs", 0, ARMVFP2, 0},
234 {"vneg", 0, ARMVFP2, 0},
235 {"vsqrt", 0, ARMVFP2, 0},
236 {"vcmp", 0, ARMVFP2, 0},
237 {"vcmp2", 0, ARMVFP2, 0},
238 {"vcvt(bff)", 0, ARMVFP3, 4, 4, 1},
239 {"vcvt(bds)", 0, ARMVFP2, 0},
240 {"vcvt(bfi)", 0, ARMVFP2, 0},
241 {"vmovbrs", 0, ARMVFP2, 0},
242 {"vmsr", 0, ARMVFP2, 0},
243 {"vmovbrc", 0, ARMVFP2, 0},
244 {"vmrs", 0, ARMVFP2, 0},
245 {"vmovbcr", 0, ARMVFP2, 0},
246 {"vmovbrrss", 0, ARMVFP2, 0},
247 {"vmovbrrd", 0, ARMVFP2, 0},
248 {"vstr", 0, ARMVFP2, 0},
249 {"vpush", 0, ARMVFP2, 0},
250 {"vstm", 0, ARMVFP2, 0},
251 {"vpop", 0, ARMVFP2, 0},
252 {"vldr", 0, ARMVFP2, 0},
253 {"vldm", 0, ARMVFP2, 0},
254
193 {"srs" , 0 , 6 , 0}, 255 {"srs" , 0 , 6 , 0},
194 {"rfe" , 0 , 6 , 0}, 256 {"rfe" , 0 , 6 , 0},
195 {"bkpt" , 0 , 3 , 0}, 257 {"bkpt" , 0 , 3 , 0},
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 460001b1a..f58b4731a 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -1427,6 +1427,13 @@ typedef struct _blx_1_thumb {
1427 unsigned int instr; 1427 unsigned int instr;
1428}blx_1_thumb; 1428}blx_1_thumb;
1429 1429
1430typedef struct _pkh_inst {
1431 u32 Rm;
1432 u32 Rn;
1433 u32 Rd;
1434 u8 imm;
1435} pkh_inst;
1436
1430typedef arm_inst * ARM_INST_PTR; 1437typedef arm_inst * ARM_INST_PTR;
1431 1438
1432#define CACHE_BUFFER_SIZE (64 * 1024 * 2000) 1439#define CACHE_BUFFER_SIZE (64 * 1024 * 2000)
@@ -2376,8 +2383,30 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index)
2376 } 2383 }
2377 return inst_base; 2384 return inst_base;
2378} 2385}
2379ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("PKHBT"); } 2386
2380ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("PKHTB"); } 2387ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index)
2388{
2389 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst));
2390 pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
2391
2392 inst_base->cond = BITS(inst, 28, 31);
2393 inst_base->idx = index;
2394 inst_base->br = NON_BRANCH;
2395 inst_base->load_r15 = 0;
2396
2397 inst_cream->Rd = BITS(inst, 12, 15);
2398 inst_cream->Rn = BITS(inst, 16, 19);
2399 inst_cream->Rm = BITS(inst, 0, 3);
2400 inst_cream->imm = BITS(inst, 7, 11);
2401
2402 return inst_base;
2403}
2404
2405ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index)
2406{
2407 return INTERPRETER_TRANSLATE(pkhbt)(inst, index);
2408}
2409
2381ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) 2410ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index)
2382{ 2411{
2383 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst)); 2412 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst));
@@ -2390,8 +2419,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index)
2390 return inst_base; 2419 return inst_base;
2391} 2420}
2392ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD"); } 2421ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD"); }
2393ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD8"); } 2422ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index)
2394ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
2395{ 2423{
2396 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 2424 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
2397 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 2425 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
@@ -2409,21 +2437,28 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
2409 2437
2410 return inst_base; 2438 return inst_base;
2411} 2439}
2440ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
2441{
2442 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2443}
2412ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) 2444ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index)
2413{ 2445{
2414 return INTERPRETER_TRANSLATE(qadd16)(inst, index); 2446 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2415} 2447}
2416ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDADD"); } 2448ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDADD"); }
2417ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDSUB"); } 2449ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDSUB"); }
2418ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB"); } 2450ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB"); }
2419ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB8"); } 2451ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index)
2452{
2453 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2454}
2420ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) 2455ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index)
2421{ 2456{
2422 return INTERPRETER_TRANSLATE(qadd16)(inst, index); 2457 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2423} 2458}
2424ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) 2459ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index)
2425{ 2460{
2426 return INTERPRETER_TRANSLATE(qadd16)(inst, index); 2461 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2427} 2462}
2428ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) 2463ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index)
2429{ 2464{
@@ -3086,15 +3121,47 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index)
3086 inst_base->load_r15 = 1; 3121 inst_base->load_r15 = 1;
3087 return inst_base; 3122 return inst_base;
3088} 3123}
3089ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADD16"); }
3090ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADD8"); } 3124ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADD8"); }
3125ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADD16"); }
3091ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADDSUBX"); } 3126ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADDSUBX"); }
3092ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHADD16"); } 3127ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index)
3093ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHADD8"); } 3128{
3094ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHADDSUBX"); } 3129 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
3095ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB16"); } 3130 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
3096ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB8"); } 3131
3097ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUBADDX"); } 3132 inst_base->cond = BITS(inst, 28, 31);
3133 inst_base->idx = index;
3134 inst_base->br = NON_BRANCH;
3135 inst_base->load_r15 = 0;
3136
3137 inst_cream->op1 = BITS(inst, 20, 21);
3138 inst_cream->op2 = BITS(inst, 5, 7);
3139 inst_cream->Rm = BITS(inst, 0, 3);
3140 inst_cream->Rn = BITS(inst, 16, 19);
3141 inst_cream->Rd = BITS(inst, 12, 15);
3142
3143 return inst_base;
3144}
3145ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index)
3146{
3147 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
3148}
3149ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index)
3150{
3151 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
3152}
3153ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index)
3154{
3155 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
3156}
3157ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index)
3158{
3159 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
3160}
3161ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index)
3162{
3163 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
3164}
3098ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) 3165ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index)
3099{ 3166{
3100 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst)); 3167 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst));
@@ -3217,23 +3284,93 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index)
3217 return inst_base; 3284 return inst_base;
3218} 3285}
3219 3286
3220ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADD16"); } 3287ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index)
3221ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADD8"); } 3288{
3222ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADDSUBX"); } 3289 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
3223ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUB16"); } 3290 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
3224ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUB8"); } 3291
3225ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUBADDX"); } 3292 inst_base->cond = BITS(inst, 28, 31);
3226ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAD8"); } 3293 inst_base->idx = index;
3227ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USADA8"); } 3294 inst_base->br = NON_BRANCH;
3295 inst_base->load_r15 = 0;
3296
3297 inst_cream->Rm = BITS(inst, 0, 3);
3298 inst_cream->Rn = BITS(inst, 16, 19);
3299 inst_cream->Rd = BITS(inst, 12, 15);
3300 inst_cream->op1 = BITS(inst, 20, 21);
3301 inst_cream->op2 = BITS(inst, 5, 7);
3302
3303 return inst_base;
3304}
3305ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index)
3306{
3307 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
3308}
3309ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index)
3310{
3311 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
3312}
3313ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index)
3314{
3315 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
3316}
3317ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index)
3318{
3319 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
3320}
3321ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index)
3322{
3323 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
3324}
3325ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index)
3326{
3327 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
3328 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
3329
3330 inst_base->cond = BITS(inst, 28, 31);
3331 inst_base->idx = index;
3332 inst_base->br = NON_BRANCH;
3333 inst_base->load_r15 = 0;
3334
3335 inst_cream->op1 = BITS(inst, 20, 24);
3336 inst_cream->op2 = BITS(inst, 5, 7);
3337 inst_cream->Rm = BITS(inst, 8, 11);
3338 inst_cream->Rn = BITS(inst, 0, 3);
3339 inst_cream->Ra = BITS(inst, 12, 15);
3340
3341 return inst_base;
3342}
3343ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index)
3344{
3345 return INTERPRETER_TRANSLATE(usada8)(inst, index);
3346}
3228ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT"); } 3347ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT"); }
3229ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT16"); } 3348ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT16"); }
3230ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB16"); } 3349ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB16"); }
3231ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB8"); } 3350ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB8"); }
3232ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUBADDX"); } 3351ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUBADDX"); }
3233ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UXTAB16"); }
3234ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UXTB16"); }
3235 3352
3353ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index)
3354{
3355 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
3356 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
3357
3358 inst_base->cond = BITS(inst, 28, 31);
3359 inst_base->idx = index;
3360 inst_base->br = NON_BRANCH;
3361 inst_base->load_r15 = 0;
3362
3363 inst_cream->Rm = BITS(inst, 0, 3);
3364 inst_cream->Rn = BITS(inst, 16, 19);
3365 inst_cream->Rd = BITS(inst, 12, 15);
3366 inst_cream->rotate = BITS(inst, 10, 11);
3236 3367
3368 return inst_base;
3369}
3370ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index)
3371{
3372 return INTERPRETER_TRANSLATE(uxtab16)(inst, index);
3373}
3237 3374
3238/* Floating point VFPv3 structures and instructions */ 3375/* Floating point VFPv3 structures and instructions */
3239 3376
@@ -3250,9 +3387,40 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) { UN
3250typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int); 3387typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int);
3251 3388
3252const transop_fp_t arm_instruction_trans[] = { 3389const transop_fp_t arm_instruction_trans[] = {
3253 #define VFP_INTERPRETER_TABLE 3390 INTERPRETER_TRANSLATE(vmla),
3254 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 3391 INTERPRETER_TRANSLATE(vmls),
3255 #undef VFP_INTERPRETER_TABLE 3392 INTERPRETER_TRANSLATE(vnmla),
3393 INTERPRETER_TRANSLATE(vnmla),
3394 INTERPRETER_TRANSLATE(vnmls),
3395 INTERPRETER_TRANSLATE(vnmul),
3396 INTERPRETER_TRANSLATE(vmul),
3397 INTERPRETER_TRANSLATE(vadd),
3398 INTERPRETER_TRANSLATE(vsub),
3399 INTERPRETER_TRANSLATE(vdiv),
3400 INTERPRETER_TRANSLATE(vmovi),
3401 INTERPRETER_TRANSLATE(vmovr),
3402 INTERPRETER_TRANSLATE(vabs),
3403 INTERPRETER_TRANSLATE(vneg),
3404 INTERPRETER_TRANSLATE(vsqrt),
3405 INTERPRETER_TRANSLATE(vcmp),
3406 INTERPRETER_TRANSLATE(vcmp2),
3407 INTERPRETER_TRANSLATE(vcvtbds),
3408 INTERPRETER_TRANSLATE(vcvtbff),
3409 INTERPRETER_TRANSLATE(vcvtbfi),
3410 INTERPRETER_TRANSLATE(vmovbrs),
3411 INTERPRETER_TRANSLATE(vmsr),
3412 INTERPRETER_TRANSLATE(vmovbrc),
3413 INTERPRETER_TRANSLATE(vmrs),
3414 INTERPRETER_TRANSLATE(vmovbcr),
3415 INTERPRETER_TRANSLATE(vmovbrrss),
3416 INTERPRETER_TRANSLATE(vmovbrrd),
3417 INTERPRETER_TRANSLATE(vstr),
3418 INTERPRETER_TRANSLATE(vpush),
3419 INTERPRETER_TRANSLATE(vstm),
3420 INTERPRETER_TRANSLATE(vpop),
3421 INTERPRETER_TRANSLATE(vldr),
3422 INTERPRETER_TRANSLATE(vldm),
3423
3256 INTERPRETER_TRANSLATE(srs), 3424 INTERPRETER_TRANSLATE(srs),
3257 INTERPRETER_TRANSLATE(rfe), 3425 INTERPRETER_TRANSLATE(rfe),
3258 INTERPRETER_TRANSLATE(bkpt), 3426 INTERPRETER_TRANSLATE(bkpt),
@@ -3976,7 +4144,7 @@ unsigned InterpreterMainLoop(ARMul_State* state)
3976 case 124: goto PKHTB_INST; \ 4144 case 124: goto PKHTB_INST; \
3977 case 125: goto PKHBT_INST; \ 4145 case 125: goto PKHBT_INST; \
3978 case 126: goto SMUL_INST; \ 4146 case 126: goto SMUL_INST; \
3979 case 127: goto SMLAL_INST; \ 4147 case 127: goto SMLALXY_INST; \
3980 case 128: goto SMLA_INST; \ 4148 case 128: goto SMLA_INST; \
3981 case 129: goto MCRR_INST; \ 4149 case 129: goto MCRR_INST; \
3982 case 130: goto MRRC_INST; \ 4150 case 130: goto MRRC_INST; \
@@ -4093,10 +4261,12 @@ unsigned InterpreterMainLoop(ARMul_State* state)
4093 // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback 4261 // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback
4094 // to a clunky switch statement. 4262 // to a clunky switch statement.
4095#if defined __GNUC__ || defined __clang__ 4263#if defined __GNUC__ || defined __clang__
4096 void *InstLabel[] = { 4264 void *InstLabel[] = {
4097 #define VFP_INTERPRETER_LABEL 4265 &&VMLA_INST, &&VMLS_INST, &&VNMLA_INST, &&VNMLA_INST, &&VNMLS_INST, &&VNMUL_INST, &&VMUL_INST, &&VADD_INST, &&VSUB_INST,
4098 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 4266 &&VDIV_INST, &&VMOVI_INST, &&VMOVR_INST, &&VABS_INST, &&VNEG_INST, &&VSQRT_INST, &&VCMP_INST, &&VCMP2_INST, &&VCVTBDS_INST,
4099 #undef VFP_INTERPRETER_LABEL 4267 &&VCVTBFF_INST, &&VCVTBFI_INST, &&VMOVBRS_INST, &&VMSR_INST, &&VMOVBRC_INST, &&VMRS_INST, &&VMOVBCR_INST, &&VMOVBRRSS_INST,
4268 &&VMOVBRRD_INST, &&VSTR_INST, &&VPUSH_INST, &&VSTM_INST, &&VPOP_INST, &&VLDR_INST, &&VLDM_INST,
4269
4100 &&SRS_INST,&&RFE_INST,&&BKPT_INST,&&BLX_INST,&&CPS_INST,&&PLD_INST,&&SETEND_INST,&&CLREX_INST,&&REV16_INST,&&USAD8_INST,&&SXTB_INST, 4270 &&SRS_INST,&&RFE_INST,&&BKPT_INST,&&BLX_INST,&&CPS_INST,&&PLD_INST,&&SETEND_INST,&&CLREX_INST,&&REV16_INST,&&USAD8_INST,&&SXTB_INST,
4101 &&UXTB_INST,&&SXTH_INST,&&SXTB16_INST,&&UXTH_INST,&&UXTB16_INST,&&CPY_INST,&&UXTAB_INST,&&SSUB8_INST,&&SHSUB8_INST,&&SSUBADDX_INST, 4271 &&UXTB_INST,&&SXTH_INST,&&SXTB16_INST,&&UXTH_INST,&&UXTB16_INST,&&CPY_INST,&&UXTAB_INST,&&SSUB8_INST,&&SHSUB8_INST,&&SSUBADDX_INST,
4102 &&STREX_INST,&&STREXB_INST,&&SWP_INST,&&SWPB_INST,&&SSUB16_INST,&&SSAT16_INST,&&SHSUBADDX_INST,&&QSUBADDX_INST,&&SHADDSUBX_INST, 4272 &&STREX_INST,&&STREXB_INST,&&SWP_INST,&&SWPB_INST,&&SSUB16_INST,&&SSAT16_INST,&&SHSUBADDX_INST,&&QSUBADDX_INST,&&SHADDSUBX_INST,
@@ -4106,7 +4276,7 @@ unsigned InterpreterMainLoop(ARMul_State* state)
4106 &&UHADD16_INST,&&UADDSUBX_INST,&&UADD8_INST,&&UADD16_INST,&&SXTAH_INST,&&SXTAB16_INST,&&QADD8_INST,&&BXJ_INST,&&CLZ_INST,&&UXTAH_INST, 4276 &&UHADD16_INST,&&UADDSUBX_INST,&&UADD8_INST,&&UADD16_INST,&&SXTAH_INST,&&SXTAB16_INST,&&QADD8_INST,&&BXJ_INST,&&CLZ_INST,&&UXTAH_INST,
4107 &&BX_INST,&&REV_INST,&&BLX_INST,&&REVSH_INST,&&QADD_INST,&&QADD16_INST,&&QADDSUBX_INST,&&LDREX_INST,&&QDADD_INST,&&QDSUB_INST, 4277 &&BX_INST,&&REV_INST,&&BLX_INST,&&REVSH_INST,&&QADD_INST,&&QADD16_INST,&&QADDSUBX_INST,&&LDREX_INST,&&QDADD_INST,&&QDSUB_INST,
4108 &&QSUB_INST,&&LDREXB_INST,&&QSUB8_INST,&&QSUB16_INST,&&SMUAD_INST,&&SMMUL_INST,&&SMUSD_INST,&&SMLSD_INST,&&SMLSLD_INST,&&SMMLA_INST, 4278 &&QSUB_INST,&&LDREXB_INST,&&QSUB8_INST,&&QSUB16_INST,&&SMUAD_INST,&&SMMUL_INST,&&SMUSD_INST,&&SMLSD_INST,&&SMLSLD_INST,&&SMMLA_INST,
4109 &&SMMLS_INST,&&SMLALD_INST,&&SMLAD_INST,&&SMLAW_INST,&&SMULW_INST,&&PKHTB_INST,&&PKHBT_INST,&&SMUL_INST,&&SMLAL_INST,&&SMLA_INST, 4279 &&SMMLS_INST,&&SMLALD_INST,&&SMLAD_INST,&&SMLAW_INST,&&SMULW_INST,&&PKHTB_INST,&&PKHBT_INST,&&SMUL_INST,&&SMLALXY_INST,&&SMLA_INST,
4110 &&MCRR_INST,&&MRRC_INST,&&CMP_INST,&&TST_INST,&&TEQ_INST,&&CMN_INST,&&SMULL_INST,&&UMULL_INST,&&UMLAL_INST,&&SMLAL_INST,&&MUL_INST, 4280 &&MCRR_INST,&&MRRC_INST,&&CMP_INST,&&TST_INST,&&TEQ_INST,&&CMN_INST,&&SMULL_INST,&&UMULL_INST,&&UMLAL_INST,&&SMLAL_INST,&&MUL_INST,
4111 &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST, 4281 &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST,
4112 &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST, 4282 &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST,
@@ -4130,7 +4300,7 @@ unsigned InterpreterMainLoop(ARMul_State* state)
4130 DISPATCH: 4300 DISPATCH:
4131 { 4301 {
4132 if (!cpu->NirqSig) { 4302 if (!cpu->NirqSig) {
4133 if (!(cpu->Cpsr & 0x80)) { 4303 if (!(cpu->Cpsr & 0x80)) {
4134 goto END; 4304 goto END;
4135 } 4305 }
4136 } 4306 }
@@ -5575,8 +5745,34 @@ unsigned InterpreterMainLoop(ARMul_State* state)
5575 FETCH_INST; 5745 FETCH_INST;
5576 GOTO_NEXT_INST; 5746 GOTO_NEXT_INST;
5577 } 5747 }
5748
5578 PKHBT_INST: 5749 PKHBT_INST:
5750 {
5751 INC_ICOUNTER;
5752 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5753 pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
5754 RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000);
5755 }
5756 cpu->Reg[15] += GET_INST_SIZE(cpu);
5757 INC_PC(sizeof(pkh_inst));
5758 FETCH_INST;
5759 GOTO_NEXT_INST;
5760 }
5761
5579 PKHTB_INST: 5762 PKHTB_INST:
5763 {
5764 INC_ICOUNTER;
5765 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5766 pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
5767 int shift_imm = inst_cream->imm ? inst_cream->imm : 31;
5768 RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000);
5769 }
5770 cpu->Reg[15] += GET_INST_SIZE(cpu);
5771 INC_PC(sizeof(pkh_inst));
5772 FETCH_INST;
5773 GOTO_NEXT_INST;
5774 }
5775
5580 PLD_INST: 5776 PLD_INST:
5581 { 5777 {
5582 INC_ICOUNTER; 5778 INC_ICOUNTER;
@@ -5587,55 +5783,60 @@ unsigned InterpreterMainLoop(ARMul_State* state)
5587 GOTO_NEXT_INST; 5783 GOTO_NEXT_INST;
5588 } 5784 }
5589 QADD_INST: 5785 QADD_INST:
5590 QADD8_INST:
5591 5786
5787 QADD8_INST:
5592 QADD16_INST: 5788 QADD16_INST:
5593 QADDSUBX_INST: 5789 QADDSUBX_INST:
5790 QSUB8_INST:
5594 QSUB16_INST: 5791 QSUB16_INST:
5595 QSUBADDX_INST: 5792 QSUBADDX_INST:
5596 { 5793 {
5597 INC_ICOUNTER; 5794 INC_ICOUNTER;
5598 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { 5795 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5599 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 5796 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
5600 const s16 rm_lo = (RM & 0xFFFF); 5797 const u16 rm_lo = (RM & 0xFFFF);
5601 const s16 rm_hi = ((RM >> 16) & 0xFFFF); 5798 const u16 rm_hi = ((RM >> 16) & 0xFFFF);
5602 const s16 rn_lo = (RN & 0xFFFF); 5799 const u16 rn_lo = (RN & 0xFFFF);
5603 const s16 rn_hi = ((RN >> 16) & 0xFFFF); 5800 const u16 rn_hi = ((RN >> 16) & 0xFFFF);
5604 const u8 op2 = inst_cream->op2; 5801 const u8 op2 = inst_cream->op2;
5605 5802
5606 s32 lo_result = 0; 5803 u16 lo_result = 0;
5607 s32 hi_result = 0; 5804 u16 hi_result = 0;
5608 5805
5609 // QADD16 5806 // QADD16
5610 if (op2 == 0x00) { 5807 if (op2 == 0x00) {
5611 lo_result = (rn_lo + rm_lo); 5808 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
5612 hi_result = (rn_hi + rm_hi); 5809 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
5613 } 5810 }
5614 // QASX 5811 // QASX
5615 else if (op2 == 0x01) { 5812 else if (op2 == 0x01) {
5616 lo_result = (rn_lo - rm_hi); 5813 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
5617 hi_result = (rn_hi + rm_lo); 5814 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
5618 } 5815 }
5619 // QSAX 5816 // QSAX
5620 else if (op2 == 0x02) { 5817 else if (op2 == 0x02) {
5621 lo_result = (rn_lo + rm_hi); 5818 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
5622 hi_result = (rn_hi - rm_lo); 5819 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
5623 } 5820 }
5624 // QSUB16 5821 // QSUB16
5625 else if (op2 == 0x03) { 5822 else if (op2 == 0x03) {
5626 lo_result = (rn_lo - rm_lo); 5823 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
5627 hi_result = (rn_hi - rm_hi); 5824 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
5825 }
5826 // QADD8
5827 else if (op2 == 0x04) {
5828 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
5829 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
5830 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
5831 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
5832 }
5833 // QSUB8
5834 else if (op2 == 0x07) {
5835 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
5836 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
5837 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
5838 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
5628 } 5839 }
5629
5630 if (lo_result > 0x7FFF)
5631 lo_result = 0x7FFF;
5632 else if (lo_result < -0x8000)
5633 lo_result = -0x8000;
5634
5635 if (hi_result > 0x7FFF)
5636 hi_result = 0x7FFF;
5637 else if (hi_result < -0x8000)
5638 hi_result = -0x8000;
5639 5840
5640 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); 5841 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
5641 } 5842 }
@@ -5649,7 +5850,6 @@ unsigned InterpreterMainLoop(ARMul_State* state)
5649 QDADD_INST: 5850 QDADD_INST:
5650 QDSUB_INST: 5851 QDSUB_INST:
5651 QSUB_INST: 5852 QSUB_INST:
5652 QSUB8_INST:
5653 REV_INST: 5853 REV_INST:
5654 { 5854 {
5655 INC_ICOUNTER; 5855 INC_ICOUNTER;
@@ -6622,15 +6822,95 @@ unsigned InterpreterMainLoop(ARMul_State* state)
6622 FETCH_INST; 6822 FETCH_INST;
6623 GOTO_NEXT_INST; 6823 GOTO_NEXT_INST;
6624 } 6824 }
6625 UADD16_INST:
6626 UADD8_INST: 6825 UADD8_INST:
6826 UADD16_INST:
6627 UADDSUBX_INST: 6827 UADDSUBX_INST:
6628 UHADD16_INST: 6828
6629 UHADD8_INST: 6829 UHADD8_INST:
6830 UHADD16_INST:
6630 UHADDSUBX_INST: 6831 UHADDSUBX_INST:
6631 UHSUB16_INST:
6632 UHSUB8_INST:
6633 UHSUBADDX_INST: 6832 UHSUBADDX_INST:
6833 UHSUB8_INST:
6834 UHSUB16_INST:
6835 {
6836 INC_ICOUNTER;
6837 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6838 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
6839
6840 const u32 rm_val = RM;
6841 const u32 rn_val = RN;
6842 const u8 op2 = inst_cream->op2;
6843
6844
6845 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03)
6846 {
6847 u32 lo_val = 0;
6848 u32 hi_val = 0;
6849
6850 // UHADD16
6851 if (op2 == 0x00) {
6852 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
6853 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
6854 }
6855 // UHASX
6856 else if (op2 == 0x01) {
6857 lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
6858 hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
6859 }
6860 // UHSAX
6861 else if (op2 == 0x02) {
6862 lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
6863 hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
6864 }
6865 // UHSUB16
6866 else if (op2 == 0x03) {
6867 lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
6868 hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
6869 }
6870
6871 lo_val >>= 1;
6872 hi_val >>= 1;
6873
6874 RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
6875 }
6876 else if (op2 == 0x04 || op2 == 0x07) {
6877 u32 sum1;
6878 u32 sum2;
6879 u32 sum3;
6880 u32 sum4;
6881
6882 // UHADD8
6883 if (op2 == 0x04) {
6884 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
6885 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
6886 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
6887 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
6888 }
6889 // UHSUB8
6890 else {
6891 sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
6892 sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
6893 sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
6894 sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
6895 }
6896
6897 sum1 >>= 1;
6898 sum2 >>= 1;
6899 sum3 >>= 1;
6900 sum4 >>= 1;
6901
6902 RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24);
6903 }
6904
6905 }
6906
6907 cpu->Reg[15] += GET_INST_SIZE(cpu);
6908 INC_PC(sizeof(generic_arm_inst));
6909 FETCH_INST;
6910 GOTO_NEXT_INST;
6911 }
6912
6913
6634 UMAAL_INST: 6914 UMAAL_INST:
6635 { 6915 {
6636 INC_ICOUNTER; 6916 INC_ICOUNTER;
@@ -6764,21 +7044,143 @@ unsigned InterpreterMainLoop(ARMul_State* state)
6764 goto DISPATCH; 7044 goto DISPATCH;
6765 } 7045 }
6766 7046
6767 UQADD16_INST:
6768 UQADD8_INST: 7047 UQADD8_INST:
7048 UQADD16_INST:
6769 UQADDSUBX_INST: 7049 UQADDSUBX_INST:
6770 UQSUB16_INST:
6771 UQSUB8_INST: 7050 UQSUB8_INST:
7051 UQSUB16_INST:
6772 UQSUBADDX_INST: 7052 UQSUBADDX_INST:
7053 {
7054 INC_ICOUNTER;
7055
7056 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
7057 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
7058
7059 const u8 op2 = inst_cream->op2;
7060 const u32 rm_val = RM;
7061 const u32 rn_val = RN;
7062
7063 u16 lo_val = 0;
7064 u16 hi_val = 0;
7065
7066 // UQADD16
7067 if (op2 == 0x00) {
7068 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
7069 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
7070 }
7071 // UQASX
7072 else if (op2 == 0x01) {
7073 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
7074 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
7075 }
7076 // UQSAX
7077 else if (op2 == 0x02) {
7078 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
7079 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
7080 }
7081 // UQSUB16
7082 else if (op2 == 0x03) {
7083 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF);
7084 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
7085 }
7086 // UQADD8
7087 else if (op2 == 0x04) {
7088 lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) |
7089 ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8;
7090 hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) |
7091 ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8;
7092 }
7093 // UQSUB8
7094 else {
7095 lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) |
7096 ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8;
7097 hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) |
7098 ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8;
7099 }
7100
7101 RD = ((lo_val & 0xFFFF) | hi_val << 16);
7102 }
7103
7104 cpu->Reg[15] += GET_INST_SIZE(cpu);
7105 INC_PC(sizeof(generic_arm_inst));
7106 FETCH_INST;
7107 GOTO_NEXT_INST;
7108 }
7109
6773 USAD8_INST: 7110 USAD8_INST:
6774 USADA8_INST: 7111 USADA8_INST:
7112 {
7113 INC_ICOUNTER;
7114
7115 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
7116 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
7117
7118 const u8 ra_idx = inst_cream->Ra;
7119 const u32 rm_val = RM;
7120 const u32 rn_val = RN;
7121
7122 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
7123 const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
7124 const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
7125 const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
7126
7127 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
7128
7129 // Op is USADA8 if true.
7130 if (ra_idx != 15)
7131 finalDif += cpu->Reg[ra_idx];
7132
7133 RD = finalDif;
7134 }
7135
7136 cpu->Reg[15] += GET_INST_SIZE(cpu);
7137 INC_PC(sizeof(generic_arm_inst));
7138 FETCH_INST;
7139 GOTO_NEXT_INST;
7140 }
7141
6775 USAT_INST: 7142 USAT_INST:
6776 USAT16_INST: 7143 USAT16_INST:
6777 USUB16_INST: 7144 USUB16_INST:
6778 USUB8_INST: 7145 USUB8_INST:
6779 USUBADDX_INST: 7146 USUBADDX_INST:
7147
6780 UXTAB16_INST: 7148 UXTAB16_INST:
6781 UXTB16_INST: 7149 UXTB16_INST:
7150 {
7151 INC_ICOUNTER;
7152
7153 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
7154 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
7155
7156 const u8 rn_idx = inst_cream->Rn;
7157 const u32 rm_val = RM;
7158 const u32 rotation = inst_cream->rotate * 8;
7159 const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
7160
7161 // UXTB16, otherwise UXTAB16
7162 if (rn_idx == 15) {
7163 RD = rotated_rm & 0x00FF00FF;
7164 }
7165 else {
7166 const u32 rn_val = RN;
7167
7168 const u8 lo_rotated = (rotated_rm & 0xFF);
7169 const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
7170
7171 const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
7172 const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
7173
7174 RD = ((hi_result << 16) | (lo_result & 0xFFFF));
7175 }
7176 }
7177
7178 cpu->Reg[15] += GET_INST_SIZE(cpu);
7179 INC_PC(sizeof(uxtab_inst));
7180 FETCH_INST;
7181 GOTO_NEXT_INST;
7182 }
7183
6782 #define VFP_INTERPRETER_IMPL 7184 #define VFP_INTERPRETER_IMPL
6783 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 7185 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
6784 #undef VFP_INTERPRETER_IMPL 7186 #undef VFP_INTERPRETER_IMPL
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp
index be04fc1a1..80ebc359e 100644
--- a/src/core/arm/interpreter/arm_interpreter.cpp
+++ b/src/core/arm/interpreter/arm_interpreter.cpp
@@ -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 b685215a0..019dad5df 100644
--- a/src/core/arm/interpreter/arm_interpreter.h
+++ b/src/core/arm/interpreter/arm_interpreter.h
@@ -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 b2f671f94..b9c2aa6c2 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -3100,7 +3100,6 @@ mainswitch:
3100 break; 3100 break;
3101 3101
3102 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */ 3102 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
3103 //ichfly PKHBT PKHTB todo check this
3104 if ((instr & 0x70) == 0x10) { //pkhbt 3103 if ((instr & 0x70) == 0x10) { //pkhbt
3105 u8 idest = BITS(12, 15); 3104 u8 idest = BITS(12, 15);
3106 u8 rfis = BITS(16, 19); 3105 u8 rfis = BITS(16, 19);
@@ -3109,18 +3108,11 @@ mainswitch:
3109 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);
3110 break; 3109 break;
3111 } else if ((instr & 0x70) == 0x50) { //pkhtb 3110 } else if ((instr & 0x70) == 0x50) { //pkhtb
3112 const u8 rd_idx = BITS(12, 15); 3111 u8 rd_idx = BITS(12, 15);
3113 const u8 rn_idx = BITS(16, 19); 3112 u8 rn_idx = BITS(16, 19);
3114 const u8 rm_idx = BITS(0, 3); 3113 u8 rm_idx = BITS(0, 3);
3115 const u8 imm5 = BITS(7, 11); 3114 u8 imm5 = BITS(7, 11) ? BITS(7, 11) : 31;
3116 3115 state->Reg[rd_idx] = ((static_cast<s32>(state->Reg[rm_idx]) >> imm5) & 0xFFFF) | ((state->Reg[rn_idx]) & 0xFFFF0000);
3117 ARMword val;
3118 if (imm5 >= 32)
3119 val = (state->Reg[rm_idx] >> 31);
3120 else
3121 val = (state->Reg[rm_idx] >> imm5);
3122
3123 state->Reg[rd_idx] = (val & 0xFFFF) | ((state->Reg[rn_idx]) & 0xFFFF0000);
3124 break; 3116 break;
3125 } else if (BIT (4)) { 3117 } else if (BIT (4)) {
3126#ifdef MODE32 3118#ifdef MODE32
@@ -5863,22 +5855,21 @@ L_stm_s_takeabort:
5863 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); 5855 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
5864 5856
5865 if (lo_result >= 0) { 5857 if (lo_result >= 0) {
5866 state->Cpsr |= (1 << 16); 5858 state->GEFlag |= (1 << 16);
5867 state->Cpsr |= (1 << 17); 5859 state->GEFlag |= (1 << 17);
5868 } else { 5860 } else {
5869 state->Cpsr &= ~(1 << 16); 5861 state->GEFlag &= ~(1 << 16);
5870 state->Cpsr &= ~(1 << 17); 5862 state->GEFlag &= ~(1 << 17);
5871 } 5863 }
5872 5864
5873 if (hi_result >= 0) { 5865 if (hi_result >= 0) {
5874 state->Cpsr |= (1 << 18); 5866 state->GEFlag |= (1 << 18);
5875 state->Cpsr |= (1 << 19); 5867 state->GEFlag |= (1 << 19);
5876 } else { 5868 } else {
5877 state->Cpsr &= ~(1 << 18); 5869 state->GEFlag &= ~(1 << 18);
5878 state->Cpsr &= ~(1 << 19); 5870 state->GEFlag &= ~(1 << 19);
5879 } 5871 }
5880 5872
5881 ARMul_CPSRAltered(state);
5882 return 1; 5873 return 1;
5883 } 5874 }
5884 // SADD8/SSUB8 5875 // SADD8/SSUB8
@@ -5903,24 +5894,24 @@ L_stm_s_takeabort:
5903 hi_val2 = (u8)(((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF)); 5894 hi_val2 = (u8)(((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF));
5904 5895
5905 if (lo_val1 & 0x80) 5896 if (lo_val1 & 0x80)
5906 state->Cpsr |= (1 << 16); 5897 state->GEFlag |= (1 << 16);
5907 else 5898 else
5908 state->Cpsr &= ~(1 << 16); 5899 state->GEFlag &= ~(1 << 16);
5909 5900
5910 if (lo_val2 & 0x80) 5901 if (lo_val2 & 0x80)
5911 state->Cpsr |= (1 << 17); 5902 state->GEFlag |= (1 << 17);
5912 else 5903 else
5913 state->Cpsr &= ~(1 << 17); 5904 state->GEFlag &= ~(1 << 17);
5914 5905
5915 if (hi_val1 & 0x80) 5906 if (hi_val1 & 0x80)
5916 state->Cpsr |= (1 << 18); 5907 state->GEFlag |= (1 << 18);
5917 else 5908 else
5918 state->Cpsr &= ~(1 << 18); 5909 state->GEFlag &= ~(1 << 18);
5919 5910
5920 if (hi_val2 & 0x80) 5911 if (hi_val2 & 0x80)
5921 state->Cpsr |= (1 << 19); 5912 state->GEFlag |= (1 << 19);
5922 else 5913 else
5923 state->Cpsr &= ~(1 << 19); 5914 state->GEFlag &= ~(1 << 19);
5924 } 5915 }
5925 // SSUB8 5916 // SSUB8
5926 else { 5917 else {
@@ -5930,27 +5921,26 @@ L_stm_s_takeabort:
5930 hi_val2 = (u8)(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF)); 5921 hi_val2 = (u8)(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF));
5931 5922
5932 if (!(lo_val1 & 0x80)) 5923 if (!(lo_val1 & 0x80))
5933 state->Cpsr |= (1 << 16); 5924 state->GEFlag |= (1 << 16);
5934 else 5925 else
5935 state->Cpsr &= ~(1 << 16); 5926 state->GEFlag &= ~(1 << 16);
5936 5927
5937 if (!(lo_val2 & 0x80)) 5928 if (!(lo_val2 & 0x80))
5938 state->Cpsr |= (1 << 17); 5929 state->GEFlag |= (1 << 17);
5939 else 5930 else
5940 state->Cpsr &= ~(1 << 17); 5931 state->GEFlag &= ~(1 << 17);
5941 5932
5942 if (!(hi_val1 & 0x80)) 5933 if (!(hi_val1 & 0x80))
5943 state->Cpsr |= (1 << 18); 5934 state->GEFlag |= (1 << 18);
5944 else 5935 else
5945 state->Cpsr &= ~(1 << 18); 5936 state->GEFlag &= ~(1 << 18);
5946 5937
5947 if (!(hi_val2 & 0x80)) 5938 if (!(hi_val2 & 0x80))
5948 state->Cpsr |= (1 << 19); 5939 state->GEFlag |= (1 << 19);
5949 else 5940 else
5950 state->Cpsr &= ~(1 << 19); 5941 state->GEFlag &= ~(1 << 19);
5951 } 5942 }
5952 5943
5953 ARMul_CPSRAltered(state);
5954 state->Reg[rd_idx] = (lo_val1 | lo_val2 << 8 | hi_val1 << 16 | hi_val2 << 24); 5944 state->Reg[rd_idx] = (lo_val1 | lo_val2 << 8 | hi_val1 << 16 | hi_val2 << 24);
5955 return 1; 5945 return 1;
5956 } 5946 }
@@ -5958,56 +5948,58 @@ L_stm_s_takeabort:
5958 printf("Unhandled v6 insn: %08x", instr); 5948 printf("Unhandled v6 insn: %08x", instr);
5959 } 5949 }
5960 break; 5950 break;
5961 case 0x62: // QADD16, QASX, QSAX, and QSUB16 5951 case 0x62: // QADD16, QASX, QSAX, QSUB16, QADD8, and QSUB8
5962 if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 ||
5963 (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70)
5964 { 5952 {
5953 const u8 op2 = BITS(5, 7);
5954
5965 const u8 rd_idx = BITS(12, 15); 5955 const u8 rd_idx = BITS(12, 15);
5966 const u8 rn_idx = BITS(16, 19); 5956 const u8 rn_idx = BITS(16, 19);
5967 const u8 rm_idx = BITS(0, 3); 5957 const u8 rm_idx = BITS(0, 3);
5968 const s16 rm_lo = (state->Reg[rm_idx] & 0xFFFF); 5958 const u16 rm_lo = (state->Reg[rm_idx] & 0xFFFF);
5969 const s16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF); 5959 const u16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF);
5970 const s16 rn_lo = (state->Reg[rn_idx] & 0xFFFF); 5960 const u16 rn_lo = (state->Reg[rn_idx] & 0xFFFF);
5971 const s16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF); 5961 const u16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF);
5972 5962
5973 s32 lo_result; 5963 u16 lo_result = 0;
5974 s32 hi_result; 5964 u16 hi_result = 0;
5975 5965
5976 // QADD16 5966 // QADD16
5977 if ((instr & 0xFF0) == 0xf10) { 5967 if (op2 == 0x00) {
5978 lo_result = (rn_lo + rm_lo); 5968 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
5979 hi_result = (rn_hi + rm_hi); 5969 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
5980 } 5970 }
5981 // QASX 5971 // QASX
5982 else if ((instr & 0xFF0) == 0xf30) { 5972 else if (op2 == 0x01) {
5983 lo_result = (rn_lo - rm_hi); 5973 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
5984 hi_result = (rn_hi + rm_lo); 5974 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
5985 } 5975 }
5986 // QSAX 5976 // QSAX
5987 else if ((instr & 0xFF0) == 0xf50) { 5977 else if (op2 == 0x02) {
5988 lo_result = (rn_lo + rm_hi); 5978 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
5989 hi_result = (rn_hi - rm_lo); 5979 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
5990 } 5980 }
5991 // QSUB16 5981 // QSUB16
5992 else { 5982 else if (op2 == 0x03) {
5993 lo_result = (rn_lo - rm_lo); 5983 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
5994 hi_result = (rn_hi - rm_hi); 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;
5995 } 5999 }
5996
5997 if (lo_result > 0x7FFF)
5998 lo_result = 0x7FFF;
5999 else if (lo_result < -0x8000)
6000 lo_result = -0x8000;
6001
6002 if (hi_result > 0x7FFF)
6003 hi_result = 0x7FFF;
6004 else if (hi_result < -0x8000)
6005 hi_result = -0x8000;
6006 6000
6007 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); 6001 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
6008 return 1; 6002 return 1;
6009 } else {
6010 printf("Unhandled v6 insn: %08x", BITS(20, 27));
6011 } 6003 }
6012 break; 6004 break;
6013 case 0x63: 6005 case 0x63:
@@ -6029,31 +6021,30 @@ L_stm_s_takeabort:
6029 h2 = ((u16)(from >> 16) - (u16)(to >> 16)); 6021 h2 = ((u16)(from >> 16) - (u16)(to >> 16));
6030 6022
6031 if (!(h1 & 0xffff0000)) 6023 if (!(h1 & 0xffff0000))
6032 state->Cpsr |= (3 << 16); 6024 state->GEFlag |= (3 << 16);
6033 else 6025 else
6034 state->Cpsr &= ~(3 << 16); 6026 state->GEFlag &= ~(3 << 16);
6035 6027
6036 if (!(h2 & 0xffff0000)) 6028 if (!(h2 & 0xffff0000))
6037 state->Cpsr |= (3 << 18); 6029 state->GEFlag |= (3 << 18);
6038 else 6030 else
6039 state->Cpsr &= ~(3 << 18); 6031 state->GEFlag &= ~(3 << 18);
6040 } 6032 }
6041 else { // UADD16 6033 else { // UADD16
6042 h1 = ((u16)from + (u16)to); 6034 h1 = ((u16)from + (u16)to);
6043 h2 = ((u16)(from >> 16) + (u16)(to >> 16)); 6035 h2 = ((u16)(from >> 16) + (u16)(to >> 16));
6044 6036
6045 if (h1 & 0xffff0000) 6037 if (h1 & 0xffff0000)
6046 state->Cpsr |= (3 << 16); 6038 state->GEFlag |= (3 << 16);
6047 else 6039 else
6048 state->Cpsr &= ~(3 << 16); 6040 state->GEFlag &= ~(3 << 16);
6049 6041
6050 if (h2 & 0xffff0000) 6042 if (h2 & 0xffff0000)
6051 state->Cpsr |= (3 << 18); 6043 state->GEFlag |= (3 << 18);
6052 else 6044 else
6053 state->Cpsr &= ~(3 << 18); 6045 state->GEFlag &= ~(3 << 18);
6054 } 6046 }
6055 6047
6056 ARMul_CPSRAltered(state);
6057 state->Reg[rd] = (u32)((h1 & 0xffff) | ((h2 & 0xffff) << 16)); 6048 state->Reg[rd] = (u32)((h1 & 0xffff) | ((h2 & 0xffff) << 16));
6058 return 1; 6049 return 1;
6059 } 6050 }
@@ -6068,24 +6059,24 @@ L_stm_s_takeabort:
6068 b4 = ((u8)(from >> 24) - (u8)(to >> 24)); 6059 b4 = ((u8)(from >> 24) - (u8)(to >> 24));
6069 6060
6070 if (!(b1 & 0xffffff00)) 6061 if (!(b1 & 0xffffff00))
6071 state->Cpsr |= (1 << 16); 6062 state->GEFlag |= (1 << 16);
6072 else 6063 else
6073 state->Cpsr &= ~(1 << 16); 6064 state->GEFlag &= ~(1 << 16);
6074 6065
6075 if (!(b2 & 0xffffff00)) 6066 if (!(b2 & 0xffffff00))
6076 state->Cpsr |= (1 << 17); 6067 state->GEFlag |= (1 << 17);
6077 else 6068 else
6078 state->Cpsr &= ~(1 << 17); 6069 state->GEFlag &= ~(1 << 17);
6079 6070
6080 if (!(b3 & 0xffffff00)) 6071 if (!(b3 & 0xffffff00))
6081 state->Cpsr |= (1 << 18); 6072 state->GEFlag |= (1 << 18);
6082 else 6073 else
6083 state->Cpsr &= ~(1 << 18); 6074 state->GEFlag &= ~(1 << 18);
6084 6075
6085 if (!(b4 & 0xffffff00)) 6076 if (!(b4 & 0xffffff00))
6086 state->Cpsr |= (1 << 19); 6077 state->GEFlag |= (1 << 19);
6087 else 6078 else
6088 state->Cpsr &= ~(1 << 19); 6079 state->GEFlag &= ~(1 << 19);
6089 } 6080 }
6090 else { // UADD8 6081 else { // UADD8
6091 b1 = ((u8)from + (u8)to); 6082 b1 = ((u8)from + (u8)to);
@@ -6094,57 +6085,156 @@ L_stm_s_takeabort:
6094 b4 = ((u8)(from >> 24) + (u8)(to >> 24)); 6085 b4 = ((u8)(from >> 24) + (u8)(to >> 24));
6095 6086
6096 if (b1 & 0xffffff00) 6087 if (b1 & 0xffffff00)
6097 state->Cpsr |= (1 << 16); 6088 state->GEFlag |= (1 << 16);
6098 else 6089 else
6099 state->Cpsr &= ~(1 << 16); 6090 state->GEFlag &= ~(1 << 16);
6100 6091
6101 if (b2 & 0xffffff00) 6092 if (b2 & 0xffffff00)
6102 state->Cpsr |= (1 << 17); 6093 state->GEFlag |= (1 << 17);
6103 else 6094 else
6104 state->Cpsr &= ~(1 << 17); 6095 state->GEFlag &= ~(1 << 17);
6105 6096
6106 if (b3 & 0xffffff00) 6097 if (b3 & 0xffffff00)
6107 state->Cpsr |= (1 << 18); 6098 state->GEFlag |= (1 << 18);
6108 else 6099 else
6109 state->Cpsr &= ~(1 << 18); 6100 state->GEFlag &= ~(1 << 18);
6110 6101
6111 if (b4 & 0xffffff00) 6102 if (b4 & 0xffffff00)
6112 state->Cpsr |= (1 << 19); 6103 state->GEFlag |= (1 << 19);
6113 else 6104 else
6114 state->Cpsr &= ~(1 << 19); 6105 state->GEFlag &= ~(1 << 19);
6115 } 6106 }
6116 6107
6117 ARMul_CPSRAltered(state);
6118 state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24); 6108 state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24);
6119 return 1; 6109 return 1;
6120 } 6110 }
6121 } 6111 }
6122 printf("Unhandled v6 insn: uasx/usax\n"); 6112 printf("Unhandled v6 insn: uasx/usax\n");
6123 break; 6113 break;
6124 case 0x66: 6114 case 0x66: // UQADD16, UQASX, UQSAX, UQSUB16, UQADD8, and UQSUB8
6125 if ((instr & 0x0FF00FF0) == 0x06600FF0) { //uqsub8 6115 {
6126 u32 rd = (instr >> 12) & 0xF; 6116 const u8 rd_idx = BITS(12, 15);
6127 u32 rm = (instr >> 16) & 0xF; 6117 const u8 rm_idx = BITS(0, 3);
6128 u32 rn = (instr >> 0) & 0xF; 6118 const u8 rn_idx = BITS(16, 19);
6129 u32 subfrom = state->Reg[rm]; 6119 const u8 op2 = BITS(5, 7);
6130 u32 tosub = state->Reg[rn]; 6120 const u32 rm_val = state->Reg[rm_idx];
6131 6121 const u32 rn_val = state->Reg[rn_idx];
6132 u8 b1 = (u8)((u8)(subfrom)-(u8)(tosub)); 6122
6133 if (b1 > (u8)(subfrom)) b1 = 0; 6123 u16 lo_val = 0;
6134 u8 b2 = (u8)((u8)(subfrom >> 8) - (u8)(tosub >> 8)); 6124 u16 hi_val = 0;
6135 if (b2 > (u8)(subfrom >> 8)) b2 = 0; 6125
6136 u8 b3 = (u8)((u8)(subfrom >> 16) - (u8)(tosub >> 16)); 6126 // UQADD16
6137 if (b3 > (u8)(subfrom >> 16)) b3 = 0; 6127 if (op2 == 0x00) {
6138 u8 b4 = (u8)((u8)(subfrom >> 24) - (u8)(tosub >> 24)); 6128 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
6139 if (b4 > (u8)(subfrom >> 24)) b4 = 0; 6129 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
6140 state->Reg[rd] = (u32)(b1 | b2 << 8 | b3 << 16 | b4 << 24); 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 }
6160
6161 state->Reg[rd_idx] = ((lo_val & 0xFFFF) | hi_val << 16);
6141 return 1; 6162 return 1;
6142 } else {
6143 printf ("Unhandled v6 insn: uqsub16\n");
6144 } 6163 }
6145 break; 6164 break;
6146 case 0x67: 6165 case 0x67: // UHADD16, UHASX, UHSAX, UHSUB16, UHADD8, and UHSUB8.
6147 printf ("Unhandled v6 insn: uhadd/uhsub\n"); 6166 {
6167 const u8 op2 = BITS(5, 7);
6168
6169 const u8 rm_idx = BITS(0, 3);
6170 const u8 rn_idx = BITS(16, 19);
6171 const u8 rd_idx = BITS(12, 15);
6172
6173 const u32 rm_val = state->Reg[rm_idx];
6174 const u32 rn_val = state->Reg[rn_idx];
6175
6176 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03)
6177 {
6178 u32 lo_val = 0;
6179 u32 hi_val = 0;
6180
6181 // UHADD16
6182 if (op2 == 0x00) {
6183 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
6184 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
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 }
6201
6202 lo_val >>= 1;
6203 hi_val >>= 1;
6204
6205 state->Reg[rd_idx] = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
6206 return 1;
6207 }
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;
6236 }
6237 }
6148 break; 6238 break;
6149 case 0x68: 6239 case 0x68:
6150 { 6240 {
@@ -6176,130 +6266,94 @@ L_stm_s_takeabort:
6176 return 1; 6266 return 1;
6177 } 6267 }
6178 } 6268 }
6179 printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); 6269 printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n");
6180 break; 6270 break;
6181 case 0x6a: {
6182 ARMword Rm;
6183 int ror = -1;
6184
6185 switch (BITS(4, 11)) {
6186 case 0x07:
6187 ror = 0;
6188 break;
6189 case 0x47:
6190 ror = 8;
6191 break;
6192 case 0x87:
6193 ror = 16;
6194 break;
6195 case 0xc7:
6196 ror = 24;
6197 break;
6198
6199 case 0x01:
6200 case 0xf3:
6201 //ichfly
6202 //SSAT16
6203 {
6204 const u8 rd_idx = BITS(12, 15);
6205 const u8 rn_idx = BITS(0, 3);
6206 const u8 num_bits = BITS(16, 19) + 1;
6207 const s16 min = -(0x8000 >> (16 - num_bits));
6208 const s16 max = (0x7FFF >> (16 - num_bits));
6209 s16 rn_lo = (state->Reg[rn_idx]);
6210 s16 rn_hi = (state->Reg[rn_idx] >> 16);
6211
6212 if (rn_lo > max) {
6213 rn_lo = max;
6214 state->Cpsr |= (1 << 27);
6215 } else if (rn_lo < min) {
6216 rn_lo = min;
6217 state->Cpsr |= (1 << 27);
6218 }
6219
6220 if (rn_hi > max) {
6221 rn_hi = max;
6222 state->Cpsr |= (1 << 27);
6223 } else if (rn_hi < min) {
6224 rn_hi = min;
6225 state->Cpsr |= (1 << 27);
6226 }
6227
6228 ARMul_CPSRAltered(state);
6229 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16);
6230 return 1;
6231 }
6232 6271
6233 default: 6272 case 0x6a: // SSAT, SSAT16, SXTB, and SXTAB
6234 break; 6273 {
6235 } 6274 const u8 op2 = BITS(5, 7);
6236 6275
6237 if (ror == -1) { 6276 // SSAT16
6238 if (BITS(4, 6) == 0x7) { 6277 if (op2 == 0x01) {
6239 printf("Unhandled v6 insn: ssat\n"); 6278 const u8 rd_idx = BITS(12, 15);
6240 return 0; 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;
6241 } 6292 }
6242 break;
6243 }
6244 6293
6245 Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFF) & 0xFF); 6294 if (rn_hi > max) {
6246 if (Rm & 0x80) 6295 rn_hi = max;
6247 Rm |= 0xffffff00; 6296 SETQ;
6297 } else if (rn_hi < min) {
6298 rn_hi = min;
6299 SETQ;
6300 }
6248 6301
6249 if (BITS(16, 19) == 0xf) 6302 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16);
6250 /* SXTB */ 6303 return 1;
6251 state->Reg[BITS(12, 15)] = Rm; 6304 }
6252 else 6305 else if (op2 == 0x03) {
6253 /* SXTAB */ 6306 const u8 rotation = BITS(10, 11) * 8;
6254 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm; 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;
6255 6316
6256 return 1; 6317 return 1;
6318 }
6319 else {
6320 printf("Unimplemented op: SSAT");
6321 }
6257 } 6322 }
6258 case 0x6b: 6323 break;
6324
6325 case 0x6b: // REV, REV16, SXTH, and SXTAH
6259 { 6326 {
6260 ARMword Rm; 6327 const u8 op2 = BITS(5, 7);
6261 int ror = -1;
6262
6263 switch (BITS(4, 11)) {
6264 case 0x07:
6265 ror = 0;
6266 break;
6267 case 0x47:
6268 ror = 8;
6269 break;
6270 case 0x87:
6271 ror = 16;
6272 break;
6273 case 0xc7:
6274 ror = 24;
6275 break;
6276
6277 case 0xf3: // REV
6278 DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24);
6279 return 1;
6280 case 0xfb: // REV16
6281 DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8);
6282 return 1;
6283 default:
6284 break;
6285 }
6286 6328
6287 if (ror == -1) 6329 // REV
6288 break; 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;
6289 6341
6290 Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFFFF) & 0xFFFF); 6342 u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF);
6291 if (Rm & 0x8000) 6343 if (rm & 0x8000)
6292 Rm |= 0xffff0000; 6344 rm |= 0xffff0000;
6293 6345
6294 if (BITS(16, 19) == 0xf) 6346 // SXTH, otherwise SXTAH
6295 /* SXTH */ 6347 if (BITS(16, 19) == 15)
6296 state->Reg[BITS(12, 15)] = Rm; 6348 state->Reg[BITS(12, 15)] = rm;
6297 else 6349 else
6298 /* SXTAH */ 6350 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
6299 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm;
6300 6351
6301 return 1; 6352 return 1;
6353 }
6302 } 6354 }
6355 break;
6356
6303 case 0x6c: // UXTB16 and UXTAB16 6357 case 0x6c: // UXTB16 and UXTAB16
6304 { 6358 {
6305 const u8 rm_idx = BITS(0, 3); 6359 const u8 rm_idx = BITS(0, 3);
@@ -6327,133 +6381,84 @@ L_stm_s_takeabort:
6327 return 1; 6381 return 1;
6328 } 6382 }
6329 break; 6383 break;
6330 case 0x6e: { 6384 case 0x6e: // USAT, USAT16, UXTB, and UXTAB
6331 ARMword Rm; 6385 {
6332 int ror = -1; 6386 const u8 op2 = BITS(5, 7);
6333
6334 switch (BITS(4, 11)) {
6335 case 0x07:
6336 ror = 0;
6337 break;
6338 case 0x47:
6339 ror = 8;
6340 break;
6341 case 0x87:
6342 ror = 16;
6343 break;
6344 case 0xc7:
6345 ror = 24;
6346 break;
6347
6348 case 0x01:
6349 case 0xf3:
6350 //ichfly
6351 //USAT16
6352 {
6353 const u8 rd_idx = BITS(12, 15);
6354 const u8 rn_idx = BITS(0, 3);
6355 const u8 num_bits = BITS(16, 19);
6356 const s16 max = 0xFFFF >> (16 - num_bits);
6357 s16 rn_lo = (state->Reg[rn_idx]);
6358 s16 rn_hi = (state->Reg[rn_idx] >> 16);
6359
6360 if (max < rn_lo) {
6361 rn_lo = max;
6362 state->Cpsr |= (1 << 27);
6363 } else if (rn_lo < 0) {
6364 rn_lo = 0;
6365 state->Cpsr |= (1 << 27);
6366 }
6367
6368 if (max < rn_hi) {
6369 rn_hi = max;
6370 state->Cpsr |= (1 << 27);
6371 } else if (rn_hi < 0) {
6372 rn_hi = 0;
6373 state->Cpsr |= (1 << 27);
6374 }
6375
6376 ARMul_CPSRAltered(state);
6377 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF);
6378 return 1;
6379 }
6380
6381 default:
6382 break;
6383 }
6384 6387
6385 if (ror == -1) { 6388 // USAT16
6386 if (BITS(4, 6) == 0x7) { 6389 if (op2 == 0x01) {
6387 printf("Unhandled v6 insn: usat\n"); 6390 const u8 rd_idx = BITS(12, 15);
6388 return 0; 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;
6389 } 6411 }
6390 break; 6412
6413 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF);
6414 return 1;
6391 } 6415 }
6392 6416 else if (op2 == 0x03) {
6393 Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFF) & 0xFF); 6417 const u8 rotate = BITS(10, 11) * 8;
6394 6418 const u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFF) & 0xFF);
6395 if (BITS(16, 19) == 0xf) 6419
6420 if (BITS(16, 19) == 0xf)
6396 /* UXTB */ 6421 /* UXTB */
6397 state->Reg[BITS(12, 15)] = Rm; 6422 state->Reg[BITS(12, 15)] = rm;
6398 else 6423 else
6399 /* UXTAB */ 6424 /* UXTAB */
6400 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm; 6425 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
6401
6402 return 1;
6403 }
6404 6426
6405 case 0x6f: { 6427 return 1;
6406 ARMword Rm;
6407 int ror = -1;
6408
6409 switch (BITS(4, 11)) {
6410 case 0x07:
6411 ror = 0;
6412 break;
6413 case 0x47:
6414 ror = 8;
6415 break;
6416 case 0x87:
6417 ror = 16;
6418 break;
6419 case 0xc7:
6420 ror = 24;
6421 break;
6422
6423 case 0xfb: // REVSH
6424 {
6425 DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8);
6426 if (DEST & 0x8000)
6427 DEST |= 0xffff0000;
6428 return 1;
6429 }
6430 default:
6431 break;
6432 } 6428 }
6429 else {
6430 printf("Unimplemented op: USAT");
6431 }
6432 }
6433 break;
6433 6434
6434 if (ror == -1) 6435 case 0x6f: // UXTH, UXTAH, and REVSH.
6435 break; 6436 {
6436 6437 const u8 op2 = BITS(5, 7);
6437 Rm = ((state->Reg[BITS(0, 3)] >> ror) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - ror)) & 0xFFFF) & 0xFFFF);
6438 6438
6439 /* UXT */ 6439 // REVSH
6440 /* state->Reg[BITS (12, 15)] = Rm; */ 6440 if (op2 == 0x05) {
6441 /* dyf add */ 6441 DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8);
6442 if (BITS(16, 19) == 0xf) { 6442 if (DEST & 0x8000)
6443 state->Reg[BITS(12, 15)] = Rm; 6443 DEST |= 0xffff0000;
6444 } 6444 return 1;
6445 else {
6446 /* UXTAH */
6447 /* state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm; */
6448 // printf("rd is %x rn is %x rm is %x rotate is %x\n", state->Reg[BITS (12, 15)], state->Reg[BITS (16, 19)]
6449 // , Rm, BITS(10, 11));
6450 // printf("icounter is %lld\n", state->NumInstrs);
6451 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + Rm;
6452 // printf("rd is %x\n", state->Reg[BITS (12, 15)]);
6453 // exit(-1);
6454 } 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 }
6455 6459
6456 return 1; 6460 return 1;
6461 }
6457 } 6462 }
6458 case 0x70: 6463 case 0x70:
6459 // ichfly 6464 // ichfly
@@ -6503,11 +6508,70 @@ L_stm_s_takeabort:
6503 return 1; 6508 return 1;
6504 } 6509 }
6505 break; 6510 break;
6506 case 0x74: 6511 case 0x74: // SMLALD and SMLSLD
6507 printf ("Unhandled v6 insn: smlald/smlsld\n"); 6512 {
6513 const u8 rm_idx = BITS(8, 11);
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));
6538 }
6539
6540 state->Reg[rdlo_idx] = (result & 0xFFFFFFFF);
6541 state->Reg[rdhi_idx] = ((result >> 32) & 0xFFFFFFFF);
6542 return 1;
6543 }
6508 break; 6544 break;
6509 case 0x75: 6545 case 0x75: // SMMLA, SMMUL, and SMMLS
6510 printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); 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);
6552
6553 const u32 rm_val = state->Reg[rm_idx];
6554 const u32 rn_val = state->Reg[rn_idx];
6555
6556 // Assume SMMUL by default.
6557 s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val;
6558
6559 if (ra_idx != 15) {
6560 const u32 ra_val = state->Reg[ra_idx];
6561
6562 // SMMLA, otherwise SMMLS
6563 if (BIT(6) == 0)
6564 result += ((s64)ra_val << 32);
6565 else
6566 result = ((s64)ra_val << 32) - result;
6567 }
6568
6569 if (do_round)
6570 result += 0x80000000;
6571
6572 state->Reg[rd_idx] = ((result >> 32) & 0xFFFFFFFF);
6573 return 1;
6574 }
6511 break; 6575 break;
6512 case 0x78: 6576 case 0x78:
6513 if (BITS(20, 24) == 0x18) 6577 if (BITS(20, 24) == 0x18)
@@ -6519,10 +6583,10 @@ L_stm_s_takeabort:
6519 const u32 rm_val = state->Reg[rm_idx]; 6583 const u32 rm_val = state->Reg[rm_idx];
6520 const u32 rn_val = state->Reg[rn_idx]; 6584 const u32 rn_val = state->Reg[rn_idx];
6521 6585
6522 const u8 diff1 = (u8)std::labs((rn_val & 0xFF) - (rm_val & 0xFF)); 6586 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
6523 const u8 diff2 = (u8)std::labs(((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF)); 6587 const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
6524 const u8 diff3 = (u8)std::labs(((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF)); 6588 const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
6525 const u8 diff4 = (u8)std::labs(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF)); 6589 const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
6526 6590
6527 u32 finalDif = (diff1 + diff2 + diff3 + diff4); 6591 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
6528 6592
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 6774f8a74..8b3661c8f 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -392,6 +392,15 @@ ARMul_NthReg (ARMword instr, unsigned number)
392 return (bit - 1); 392 return (bit - 1);
393} 393}
394 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
395/* 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. */
396 405
397void 406void
@@ -469,6 +478,107 @@ ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
469 ASSIGNV (SubOverflow (a, b, result)); 478 ASSIGNV (SubOverflow (a, b, result));
470} 479}
471 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
472/* 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
473 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
474 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 34eb5aaf7..0f2bcbdb1 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -790,6 +790,17 @@ extern void ARMul_FixSPSR(ARMul_State*, ARMword, ARMword);
790extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...); 790extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...);
791extern void ARMul_SelectProcessor(ARMul_State*, unsigned); 791extern void ARMul_SelectProcessor(ARMul_State*, unsigned);
792 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);
803
793#define DIFF_LOG 0 804#define DIFF_LOG 0
794#define SAVE_LOG 0 805#define SAVE_LOG 0
795 806
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..2320449b6 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,7 +54,7 @@ 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; 59 INC_ICOUNTER;
75 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 60 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -77,7 +62,7 @@ VFPLABEL_INST:
77 62
78 DBG("VMLA :\n"); 63 DBG("VMLA :\n");
79 64
80 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 65 vmla_inst *inst_cream = (vmla_inst *)inst_base->component;
81 66
82 int ret; 67 int ret;
83 68
@@ -89,22 +74,17 @@ VFPLABEL_INST:
89 CHECK_VFP_CDP_RET; 74 CHECK_VFP_CDP_RET;
90 } 75 }
91 cpu->Reg[15] += GET_INST_SIZE(cpu); 76 cpu->Reg[15] += GET_INST_SIZE(cpu);
92 INC_PC(sizeof(vfpinstr_inst)); 77 INC_PC(sizeof(vmla_inst));
93 FETCH_INST; 78 FETCH_INST;
94 GOTO_NEXT_INST; 79 GOTO_NEXT_INST;
95} 80}
96#endif 81#endif
97#ifdef VFP_CDP_TRANS 82
98if ((OPC_1 & 0xB) == 0 && (OPC_2 & 0x2) == 0)
99{
100 DBG("VMLA :\n");
101}
102#endif
103#ifdef VFP_DYNCOM_TABLE 83#ifdef VFP_DYNCOM_TABLE
104DYNCOM_FILL_ACTION(vfpinstr), 84DYNCOM_FILL_ACTION(vmla),
105#endif 85#endif
106#ifdef VFP_DYNCOM_TAG 86#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) 87int DYNCOM_TAG(vmla)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
108{ 88{
109 int instr_size = INSTR_SIZE; 89 int instr_size = INSTR_SIZE;
110 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 90 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -114,7 +94,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
114} 94}
115#endif 95#endif
116#ifdef VFP_DYNCOM_TRANS 96#ifdef VFP_DYNCOM_TRANS
117int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 97int 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__); 98 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
119 //arch_arm_undef(cpu, bb, instr); 99 //arch_arm_undef(cpu, bb, instr);
120 int m; 100 int m;
@@ -168,41 +148,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
168 return No_exp; 148 return No_exp;
169} 149}
170#endif 150#endif
171#undef vfpinstr
172#undef vfpinstr_inst
173#undef VFPLABEL_INST
174 151
175/* ----------------------------------------------------------------------- */ 152/* ----------------------------------------------------------------------- */
176/* VNMLS */ 153/* VNMLS */
177/* cond 1110 0D00 Vn-- Vd-- 101X N1M0 Vm-- */ 154/* 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 155#ifdef VFP_INTERPRETER_STRUCT
194typedef struct _vmls_inst { 156typedef struct _vmls_inst {
195 unsigned int instr; 157 unsigned int instr;
196 unsigned int dp_operation; 158 unsigned int dp_operation;
197} vfpinstr_inst; 159} vmls_inst;
198#endif 160#endif
199#ifdef VFP_INTERPRETER_TRANS 161#ifdef VFP_INTERPRETER_TRANS
200ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 162ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index)
201{ 163{
202 VFP_DEBUG_TRANSLATE; 164 VFP_DEBUG_TRANSLATE;
203 165
204 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 166 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmls_inst));
205 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 167 vmls_inst *inst_cream = (vmls_inst *)inst_base->component;
206 168
207 inst_base->cond = BITS(inst, 28, 31); 169 inst_base->cond = BITS(inst, 28, 31);
208 inst_base->idx = index; 170 inst_base->idx = index;
@@ -216,7 +178,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
216} 178}
217#endif 179#endif
218#ifdef VFP_INTERPRETER_IMPL 180#ifdef VFP_INTERPRETER_IMPL
219VFPLABEL_INST: 181VMLS_INST:
220{ 182{
221 INC_ICOUNTER; 183 INC_ICOUNTER;
222 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 184 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -224,7 +186,7 @@ VFPLABEL_INST:
224 186
225 DBG("VMLS :\n"); 187 DBG("VMLS :\n");
226 188
227 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 189 vmls_inst *inst_cream = (vmls_inst *)inst_base->component;
228 190
229 int ret; 191 int ret;
230 192
@@ -236,22 +198,17 @@ VFPLABEL_INST:
236 CHECK_VFP_CDP_RET; 198 CHECK_VFP_CDP_RET;
237 } 199 }
238 cpu->Reg[15] += GET_INST_SIZE(cpu); 200 cpu->Reg[15] += GET_INST_SIZE(cpu);
239 INC_PC(sizeof(vfpinstr_inst)); 201 INC_PC(sizeof(vmls_inst));
240 FETCH_INST; 202 FETCH_INST;
241 GOTO_NEXT_INST; 203 GOTO_NEXT_INST;
242} 204}
243#endif 205#endif
244#ifdef VFP_CDP_TRANS 206
245if ((OPC_1 & 0xB) == 0 && (OPC_2 & 0x2) == 2)
246{
247 DBG("VMLS :\n");
248}
249#endif
250#ifdef VFP_DYNCOM_TABLE 207#ifdef VFP_DYNCOM_TABLE
251DYNCOM_FILL_ACTION(vfpinstr), 208DYNCOM_FILL_ACTION(vmls),
252#endif 209#endif
253#ifdef VFP_DYNCOM_TAG 210#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) 211int DYNCOM_TAG(vmls)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
255{ 212{
256 int instr_size = INSTR_SIZE; 213 int instr_size = INSTR_SIZE;
257 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 214 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -261,7 +218,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
261} 218}
262#endif 219#endif
263#ifdef VFP_DYNCOM_TRANS 220#ifdef VFP_DYNCOM_TRANS
264int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 221int 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__); 222 DBG("\t\tin %s VMLS instruction is executed out of here.\n", __FUNCTION__);
266 //arch_arm_undef(cpu, bb, instr); 223 //arch_arm_undef(cpu, bb, instr);
267 int m; 224 int m;
@@ -315,47 +272,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
315 return No_exp; 272 return No_exp;
316} 273}
317#endif 274#endif
318#undef vfpinstr
319#undef vfpinstr_inst
320#undef VFPLABEL_INST
321 275
322/* ----------------------------------------------------------------------- */ 276/* ----------------------------------------------------------------------- */
323/* VNMLA */ 277/* VNMLA */
324/* cond 1110 0D01 Vn-- Vd-- 101X N1M0 Vm-- */ 278/* 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 279#ifdef VFP_INTERPRETER_STRUCT
347typedef struct _vnmla_inst { 280typedef struct _vnmla_inst {
348 unsigned int instr; 281 unsigned int instr;
349 unsigned int dp_operation; 282 unsigned int dp_operation;
350} vfpinstr_inst; 283} vnmla_inst;
351#endif 284#endif
352#ifdef VFP_INTERPRETER_TRANS 285#ifdef VFP_INTERPRETER_TRANS
353ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 286ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index)
354{ 287{
355 VFP_DEBUG_TRANSLATE; 288 VFP_DEBUG_TRANSLATE;
356 289
357 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 290 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmla_inst));
358 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 291 vnmla_inst *inst_cream = (vnmla_inst *)inst_base->component;
359 292
360 inst_base->cond = BITS(inst, 28, 31); 293 inst_base->cond = BITS(inst, 28, 31);
361 inst_base->idx = index; 294 inst_base->idx = index;
@@ -369,7 +302,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
369} 302}
370#endif 303#endif
371#ifdef VFP_INTERPRETER_IMPL 304#ifdef VFP_INTERPRETER_IMPL
372VFPLABEL_INST: 305VNMLA_INST:
373{ 306{
374 INC_ICOUNTER; 307 INC_ICOUNTER;
375 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 308 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -377,7 +310,7 @@ VFPLABEL_INST:
377 310
378 DBG("VNMLA :\n"); 311 DBG("VNMLA :\n");
379 312
380 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 313 vnmla_inst *inst_cream = (vnmla_inst *)inst_base->component;
381 314
382 int ret; 315 int ret;
383 316
@@ -389,23 +322,18 @@ VFPLABEL_INST:
389 CHECK_VFP_CDP_RET; 322 CHECK_VFP_CDP_RET;
390 } 323 }
391 cpu->Reg[15] += GET_INST_SIZE(cpu); 324 cpu->Reg[15] += GET_INST_SIZE(cpu);
392 INC_PC(sizeof(vfpinstr_inst)); 325 INC_PC(sizeof(vnmla_inst));
393 FETCH_INST; 326 FETCH_INST;
394 GOTO_NEXT_INST; 327 GOTO_NEXT_INST;
395} 328}
396#endif 329#endif
397#ifdef VFP_CDP_TRANS 330
398if ((OPC_1 & 0xB) == 1 && (OPC_2 & 0x2) == 2)
399{
400 DBG("VNMLA :\n");
401}
402#endif
403#ifdef VFP_DYNCOM_TABLE 331#ifdef VFP_DYNCOM_TABLE
404DYNCOM_FILL_ACTION(vfpinstr), 332DYNCOM_FILL_ACTION(vnmla),
405DYNCOM_FILL_ACTION(vfpinstr), 333DYNCOM_FILL_ACTION(vnmla),
406#endif 334#endif
407#ifdef VFP_DYNCOM_TAG 335#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) 336int DYNCOM_TAG(vnmla)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
409{ 337{
410 int instr_size = INSTR_SIZE; 338 int instr_size = INSTR_SIZE;
411 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 339 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -415,7 +343,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
415} 343}
416#endif 344#endif
417#ifdef VFP_DYNCOM_TRANS 345#ifdef VFP_DYNCOM_TRANS
418int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 346int 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__); 347 DBG("\t\tin %s VNMLA instruction is executed out of here.\n", __FUNCTION__);
420 //arch_arm_undef(cpu, bb, instr); 348 //arch_arm_undef(cpu, bb, instr);
421 int m; 349 int m;
@@ -469,41 +397,24 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
469 return No_exp; 397 return No_exp;
470} 398}
471#endif 399#endif
472#undef vfpinstr
473#undef vfpinstr_inst
474#undef VFPLABEL_INST
475 400
476/* ----------------------------------------------------------------------- */ 401/* ----------------------------------------------------------------------- */
477/* VNMLS */ 402/* VNMLS */
478/* cond 1110 0D01 Vn-- Vd-- 101X N0M0 Vm-- */ 403/* cond 1110 0D01 Vn-- Vd-- 101X N0M0 Vm-- */
479#define vfpinstr vnmls 404
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 405#ifdef VFP_INTERPRETER_STRUCT
495typedef struct _vnmls_inst { 406typedef struct _vnmls_inst {
496 unsigned int instr; 407 unsigned int instr;
497 unsigned int dp_operation; 408 unsigned int dp_operation;
498} vfpinstr_inst; 409} vnmls_inst;
499#endif 410#endif
500#ifdef VFP_INTERPRETER_TRANS 411#ifdef VFP_INTERPRETER_TRANS
501ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 412ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index)
502{ 413{
503 VFP_DEBUG_TRANSLATE; 414 VFP_DEBUG_TRANSLATE;
504 415
505 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 416 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmls_inst));
506 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 417 vnmls_inst *inst_cream = (vnmls_inst *)inst_base->component;
507 418
508 inst_base->cond = BITS(inst, 28, 31); 419 inst_base->cond = BITS(inst, 28, 31);
509 inst_base->idx = index; 420 inst_base->idx = index;
@@ -517,7 +428,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
517} 428}
518#endif 429#endif
519#ifdef VFP_INTERPRETER_IMPL 430#ifdef VFP_INTERPRETER_IMPL
520VFPLABEL_INST: 431VNMLS_INST:
521{ 432{
522 INC_ICOUNTER; 433 INC_ICOUNTER;
523 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 434 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -525,7 +436,7 @@ VFPLABEL_INST:
525 436
526 DBG("VNMLS :\n"); 437 DBG("VNMLS :\n");
527 438
528 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 439 vnmls_inst *inst_cream = (vnmls_inst *)inst_base->component;
529 440
530 int ret; 441 int ret;
531 442
@@ -537,22 +448,17 @@ VFPLABEL_INST:
537 CHECK_VFP_CDP_RET; 448 CHECK_VFP_CDP_RET;
538 } 449 }
539 cpu->Reg[15] += GET_INST_SIZE(cpu); 450 cpu->Reg[15] += GET_INST_SIZE(cpu);
540 INC_PC(sizeof(vfpinstr_inst)); 451 INC_PC(sizeof(vnmls_inst));
541 FETCH_INST; 452 FETCH_INST;
542 GOTO_NEXT_INST; 453 GOTO_NEXT_INST;
543} 454}
544#endif 455#endif
545#ifdef VFP_CDP_TRANS 456
546if ((OPC_1 & 0xB) == 1 && (OPC_2 & 0x2) == 0)
547{
548 DBG("VNMLS :\n");
549}
550#endif
551#ifdef VFP_DYNCOM_TABLE 457#ifdef VFP_DYNCOM_TABLE
552DYNCOM_FILL_ACTION(vfpinstr), 458DYNCOM_FILL_ACTION(vnmls),
553#endif 459#endif
554#ifdef VFP_DYNCOM_TAG 460#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) 461int DYNCOM_TAG(vnmls)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
556{ 462{
557 int instr_size = INSTR_SIZE; 463 int instr_size = INSTR_SIZE;
558 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 464 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -562,7 +468,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
562} 468}
563#endif 469#endif
564#ifdef VFP_DYNCOM_TRANS 470#ifdef VFP_DYNCOM_TRANS
565int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 471int 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__); 472 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
567 //arch_arm_undef(cpu, bb, instr); 473 //arch_arm_undef(cpu, bb, instr);
568 int m; 474 int m;
@@ -616,41 +522,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
616 return No_exp; 522 return No_exp;
617} 523}
618#endif 524#endif
619#undef vfpinstr
620#undef vfpinstr_inst
621#undef VFPLABEL_INST
622 525
623/* ----------------------------------------------------------------------- */ 526/* ----------------------------------------------------------------------- */
624/* VNMUL */ 527/* VNMUL */
625/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */ 528/* 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 529#ifdef VFP_INTERPRETER_STRUCT
642typedef struct _vnmul_inst { 530typedef struct _vnmul_inst {
643 unsigned int instr; 531 unsigned int instr;
644 unsigned int dp_operation; 532 unsigned int dp_operation;
645} vfpinstr_inst; 533} vnmul_inst;
646#endif 534#endif
647#ifdef VFP_INTERPRETER_TRANS 535#ifdef VFP_INTERPRETER_TRANS
648ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 536ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index)
649{ 537{
650 VFP_DEBUG_TRANSLATE; 538 VFP_DEBUG_TRANSLATE;
651 539
652 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 540 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmul_inst));
653 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 541 vnmul_inst *inst_cream = (vnmul_inst *)inst_base->component;
654 542
655 inst_base->cond = BITS(inst, 28, 31); 543 inst_base->cond = BITS(inst, 28, 31);
656 inst_base->idx = index; 544 inst_base->idx = index;
@@ -664,7 +552,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
664} 552}
665#endif 553#endif
666#ifdef VFP_INTERPRETER_IMPL 554#ifdef VFP_INTERPRETER_IMPL
667VFPLABEL_INST: 555VNMUL_INST:
668{ 556{
669 INC_ICOUNTER; 557 INC_ICOUNTER;
670 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 558 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -672,7 +560,7 @@ VFPLABEL_INST:
672 560
673 DBG("VNMUL :\n"); 561 DBG("VNMUL :\n");
674 562
675 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 563 vnmul_inst *inst_cream = (vnmul_inst *)inst_base->component;
676 564
677 int ret; 565 int ret;
678 566
@@ -684,22 +572,17 @@ VFPLABEL_INST:
684 CHECK_VFP_CDP_RET; 572 CHECK_VFP_CDP_RET;
685 } 573 }
686 cpu->Reg[15] += GET_INST_SIZE(cpu); 574 cpu->Reg[15] += GET_INST_SIZE(cpu);
687 INC_PC(sizeof(vfpinstr_inst)); 575 INC_PC(sizeof(vnmul_inst));
688 FETCH_INST; 576 FETCH_INST;
689 GOTO_NEXT_INST; 577 GOTO_NEXT_INST;
690} 578}
691#endif 579#endif
692#ifdef VFP_CDP_TRANS 580
693if ((OPC_1 & 0xB) == 2 && (OPC_2 & 0x2) == 2)
694{
695 DBG("VNMUL :\n");
696}
697#endif
698#ifdef VFP_DYNCOM_TABLE 581#ifdef VFP_DYNCOM_TABLE
699DYNCOM_FILL_ACTION(vfpinstr), 582DYNCOM_FILL_ACTION(vnmul),
700#endif 583#endif
701#ifdef VFP_DYNCOM_TAG 584#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) 585int DYNCOM_TAG(vnmul)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
703{ 586{
704 int instr_size = INSTR_SIZE; 587 int instr_size = INSTR_SIZE;
705 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 588 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -709,7 +592,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
709} 592}
710#endif 593#endif
711#ifdef VFP_DYNCOM_TRANS 594#ifdef VFP_DYNCOM_TRANS
712int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 595int 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__); 596 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
714 //arch_arm_undef(cpu, bb, instr); 597 //arch_arm_undef(cpu, bb, instr);
715 int m; 598 int m;
@@ -753,41 +636,24 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
753 return No_exp; 636 return No_exp;
754} 637}
755#endif 638#endif
756#undef vfpinstr 639
757#undef vfpinstr_inst
758#undef VFPLABEL_INST
759 640
760/* ----------------------------------------------------------------------- */ 641/* ----------------------------------------------------------------------- */
761/* VMUL */ 642/* VMUL */
762/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */ 643/* 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 644#ifdef VFP_INTERPRETER_STRUCT
779typedef struct _vmul_inst { 645typedef struct _vmul_inst {
780 unsigned int instr; 646 unsigned int instr;
781 unsigned int dp_operation; 647 unsigned int dp_operation;
782} vfpinstr_inst; 648} vmul_inst;
783#endif 649#endif
784#ifdef VFP_INTERPRETER_TRANS 650#ifdef VFP_INTERPRETER_TRANS
785ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 651ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index)
786{ 652{
787 VFP_DEBUG_TRANSLATE; 653 VFP_DEBUG_TRANSLATE;
788 654
789 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 655 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmul_inst));
790 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 656 vmul_inst *inst_cream = (vmul_inst *)inst_base->component;
791 657
792 inst_base->cond = BITS(inst, 28, 31); 658 inst_base->cond = BITS(inst, 28, 31);
793 inst_base->idx = index; 659 inst_base->idx = index;
@@ -801,7 +667,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
801} 667}
802#endif 668#endif
803#ifdef VFP_INTERPRETER_IMPL 669#ifdef VFP_INTERPRETER_IMPL
804VFPLABEL_INST: 670VMUL_INST:
805{ 671{
806 INC_ICOUNTER; 672 INC_ICOUNTER;
807 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 673 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -809,7 +675,7 @@ VFPLABEL_INST:
809 675
810 DBG("VMUL :\n"); 676 DBG("VMUL :\n");
811 677
812 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 678 vmul_inst *inst_cream = (vmul_inst *)inst_base->component;
813 679
814 int ret; 680 int ret;
815 681
@@ -821,22 +687,17 @@ VFPLABEL_INST:
821 CHECK_VFP_CDP_RET; 687 CHECK_VFP_CDP_RET;
822 } 688 }
823 cpu->Reg[15] += GET_INST_SIZE(cpu); 689 cpu->Reg[15] += GET_INST_SIZE(cpu);
824 INC_PC(sizeof(vfpinstr_inst)); 690 INC_PC(sizeof(vmul_inst));
825 FETCH_INST; 691 FETCH_INST;
826 GOTO_NEXT_INST; 692 GOTO_NEXT_INST;
827} 693}
828#endif 694#endif
829#ifdef VFP_CDP_TRANS 695
830if ((OPC_1 & 0xB) == 2 && (OPC_2 & 0x2) == 0)
831{
832 DBG("VMUL :\n");
833}
834#endif
835#ifdef VFP_DYNCOM_TABLE 696#ifdef VFP_DYNCOM_TABLE
836DYNCOM_FILL_ACTION(vfpinstr), 697DYNCOM_FILL_ACTION(vmul),
837#endif 698#endif
838#ifdef VFP_DYNCOM_TAG 699#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) 700int DYNCOM_TAG(vmul)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
840{ 701{
841 int instr_size = INSTR_SIZE; 702 int instr_size = INSTR_SIZE;
842 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 703 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -846,7 +707,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
846} 707}
847#endif 708#endif
848#ifdef VFP_DYNCOM_TRANS 709#ifdef VFP_DYNCOM_TRANS
849int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 710int 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__); 711 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
851 //printf("\n\n\t\tin %s instruction is executed out.\n\n", __FUNCTION__); 712 //printf("\n\n\t\tin %s instruction is executed out.\n\n", __FUNCTION__);
852 //arch_arm_undef(cpu, bb, instr); 713 //arch_arm_undef(cpu, bb, instr);
@@ -904,41 +765,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
904 return No_exp; 765 return No_exp;
905} 766}
906#endif 767#endif
907#undef vfpinstr
908#undef vfpinstr_inst
909#undef VFPLABEL_INST
910 768
911/* ----------------------------------------------------------------------- */ 769/* ----------------------------------------------------------------------- */
912/* VADD */ 770/* VADD */
913/* cond 1110 0D11 Vn-- Vd-- 101X N0M0 Vm-- */ 771/* 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 772#ifdef VFP_INTERPRETER_STRUCT
930typedef struct _vadd_inst { 773typedef struct _vadd_inst {
931 unsigned int instr; 774 unsigned int instr;
932 unsigned int dp_operation; 775 unsigned int dp_operation;
933} vfpinstr_inst; 776} vadd_inst;
934#endif 777#endif
935#ifdef VFP_INTERPRETER_TRANS 778#ifdef VFP_INTERPRETER_TRANS
936ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 779ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index)
937{ 780{
938 VFP_DEBUG_TRANSLATE; 781 VFP_DEBUG_TRANSLATE;
939 782
940 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 783 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vadd_inst));
941 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 784 vadd_inst *inst_cream = (vadd_inst *)inst_base->component;
942 785
943 inst_base->cond = BITS(inst, 28, 31); 786 inst_base->cond = BITS(inst, 28, 31);
944 inst_base->idx = index; 787 inst_base->idx = index;
@@ -952,7 +795,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
952} 795}
953#endif 796#endif
954#ifdef VFP_INTERPRETER_IMPL 797#ifdef VFP_INTERPRETER_IMPL
955VFPLABEL_INST: 798VADD_INST:
956{ 799{
957 INC_ICOUNTER; 800 INC_ICOUNTER;
958 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 801 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -960,7 +803,7 @@ VFPLABEL_INST:
960 803
961 DBG("VADD :\n"); 804 DBG("VADD :\n");
962 805
963 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 806 vadd_inst *inst_cream = (vadd_inst *)inst_base->component;
964 807
965 int ret; 808 int ret;
966 809
@@ -972,22 +815,17 @@ VFPLABEL_INST:
972 CHECK_VFP_CDP_RET; 815 CHECK_VFP_CDP_RET;
973 } 816 }
974 cpu->Reg[15] += GET_INST_SIZE(cpu); 817 cpu->Reg[15] += GET_INST_SIZE(cpu);
975 INC_PC(sizeof(vfpinstr_inst)); 818 INC_PC(sizeof(vadd_inst));
976 FETCH_INST; 819 FETCH_INST;
977 GOTO_NEXT_INST; 820 GOTO_NEXT_INST;
978} 821}
979#endif 822#endif
980#ifdef VFP_CDP_TRANS 823
981if ((OPC_1 & 0xB) == 3 && (OPC_2 & 0x2) == 0)
982{
983 DBG("VADD :\n");
984}
985#endif
986#ifdef VFP_DYNCOM_TABLE 824#ifdef VFP_DYNCOM_TABLE
987DYNCOM_FILL_ACTION(vfpinstr), 825DYNCOM_FILL_ACTION(vadd),
988#endif 826#endif
989#ifdef VFP_DYNCOM_TAG 827#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) 828int DYNCOM_TAG(vadd)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
991{ 829{
992 int instr_size = INSTR_SIZE; 830 int instr_size = INSTR_SIZE;
993 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 831 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -997,7 +835,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
997} 835}
998#endif 836#endif
999#ifdef VFP_DYNCOM_TRANS 837#ifdef VFP_DYNCOM_TRANS
1000int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 838int 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__); 839 DBG("\t\tin %s instruction will implement out of JIT.\n", __FUNCTION__);
1002 //arch_arm_undef(cpu, bb, instr); 840 //arch_arm_undef(cpu, bb, instr);
1003 int m; 841 int m;
@@ -1049,41 +887,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1049 return No_exp; 887 return No_exp;
1050} 888}
1051#endif 889#endif
1052#undef vfpinstr
1053#undef vfpinstr_inst
1054#undef VFPLABEL_INST
1055 890
1056/* ----------------------------------------------------------------------- */ 891/* ----------------------------------------------------------------------- */
1057/* VSUB */ 892/* VSUB */
1058/* cond 1110 0D11 Vn-- Vd-- 101X N1M0 Vm-- */ 893/* 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 894#ifdef VFP_INTERPRETER_STRUCT
1075typedef struct _vsub_inst { 895typedef struct _vsub_inst {
1076 unsigned int instr; 896 unsigned int instr;
1077 unsigned int dp_operation; 897 unsigned int dp_operation;
1078} vfpinstr_inst; 898} vsub_inst;
1079#endif 899#endif
1080#ifdef VFP_INTERPRETER_TRANS 900#ifdef VFP_INTERPRETER_TRANS
1081ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 901ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index)
1082{ 902{
1083 VFP_DEBUG_TRANSLATE; 903 VFP_DEBUG_TRANSLATE;
1084 904
1085 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 905 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vsub_inst));
1086 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 906 vsub_inst *inst_cream = (vsub_inst *)inst_base->component;
1087 907
1088 inst_base->cond = BITS(inst, 28, 31); 908 inst_base->cond = BITS(inst, 28, 31);
1089 inst_base->idx = index; 909 inst_base->idx = index;
@@ -1097,7 +917,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1097} 917}
1098#endif 918#endif
1099#ifdef VFP_INTERPRETER_IMPL 919#ifdef VFP_INTERPRETER_IMPL
1100VFPLABEL_INST: 920VSUB_INST:
1101{ 921{
1102 INC_ICOUNTER; 922 INC_ICOUNTER;
1103 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 923 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -1105,7 +925,7 @@ VFPLABEL_INST:
1105 925
1106 DBG("VSUB :\n"); 926 DBG("VSUB :\n");
1107 927
1108 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 928 vsub_inst *inst_cream = (vsub_inst *)inst_base->component;
1109 929
1110 int ret; 930 int ret;
1111 931
@@ -1117,22 +937,16 @@ VFPLABEL_INST:
1117 CHECK_VFP_CDP_RET; 937 CHECK_VFP_CDP_RET;
1118 } 938 }
1119 cpu->Reg[15] += GET_INST_SIZE(cpu); 939 cpu->Reg[15] += GET_INST_SIZE(cpu);
1120 INC_PC(sizeof(vfpinstr_inst)); 940 INC_PC(sizeof(vsub_inst));
1121 FETCH_INST; 941 FETCH_INST;
1122 GOTO_NEXT_INST; 942 GOTO_NEXT_INST;
1123} 943}
1124#endif 944#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 945#ifdef VFP_DYNCOM_TABLE
1132DYNCOM_FILL_ACTION(vfpinstr), 946DYNCOM_FILL_ACTION(vsub),
1133#endif 947#endif
1134#ifdef VFP_DYNCOM_TAG 948#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) 949int DYNCOM_TAG(vsub)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1136{ 950{
1137 int instr_size = INSTR_SIZE; 951 int instr_size = INSTR_SIZE;
1138 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc); 952 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
@@ -1141,7 +955,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1141} 955}
1142#endif 956#endif
1143#ifdef VFP_DYNCOM_TRANS 957#ifdef VFP_DYNCOM_TRANS
1144int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 958int 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); 959 DBG("\t\tin %s instr=0x%x, instruction is executed out of JIT.\n", __FUNCTION__, instr);
1146 //arch_arm_undef(cpu, bb, instr); 960 //arch_arm_undef(cpu, bb, instr);
1147 int m; 961 int m;
@@ -1193,41 +1007,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1193 return No_exp; 1007 return No_exp;
1194} 1008}
1195#endif 1009#endif
1196#undef vfpinstr
1197#undef vfpinstr_inst
1198#undef VFPLABEL_INST
1199 1010
1200/* ----------------------------------------------------------------------- */ 1011/* ----------------------------------------------------------------------- */
1201/* VDIV */ 1012/* VDIV */
1202/* cond 1110 1D00 Vn-- Vd-- 101X N0M0 Vm-- */ 1013/* 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 1014#ifdef VFP_INTERPRETER_STRUCT
1219typedef struct _vdiv_inst { 1015typedef struct _vdiv_inst {
1220 unsigned int instr; 1016 unsigned int instr;
1221 unsigned int dp_operation; 1017 unsigned int dp_operation;
1222} vfpinstr_inst; 1018} vdiv_inst;
1223#endif 1019#endif
1224#ifdef VFP_INTERPRETER_TRANS 1020#ifdef VFP_INTERPRETER_TRANS
1225ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1021ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index)
1226{ 1022{
1227 VFP_DEBUG_TRANSLATE; 1023 VFP_DEBUG_TRANSLATE;
1228 1024
1229 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1025 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vdiv_inst));
1230 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1026 vdiv_inst *inst_cream = (vdiv_inst *)inst_base->component;
1231 1027
1232 inst_base->cond = BITS(inst, 28, 31); 1028 inst_base->cond = BITS(inst, 28, 31);
1233 inst_base->idx = index; 1029 inst_base->idx = index;
@@ -1241,7 +1037,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1241} 1037}
1242#endif 1038#endif
1243#ifdef VFP_INTERPRETER_IMPL 1039#ifdef VFP_INTERPRETER_IMPL
1244VFPLABEL_INST: 1040VDIV_INST:
1245{ 1041{
1246 INC_ICOUNTER; 1042 INC_ICOUNTER;
1247 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1043 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -1249,7 +1045,7 @@ VFPLABEL_INST:
1249 1045
1250 DBG("VDIV :\n"); 1046 DBG("VDIV :\n");
1251 1047
1252 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1048 vdiv_inst *inst_cream = (vdiv_inst *)inst_base->component;
1253 1049
1254 int ret; 1050 int ret;
1255 1051
@@ -1261,22 +1057,17 @@ VFPLABEL_INST:
1261 CHECK_VFP_CDP_RET; 1057 CHECK_VFP_CDP_RET;
1262 } 1058 }
1263 cpu->Reg[15] += GET_INST_SIZE(cpu); 1059 cpu->Reg[15] += GET_INST_SIZE(cpu);
1264 INC_PC(sizeof(vfpinstr_inst)); 1060 INC_PC(sizeof(vdiv_inst));
1265 FETCH_INST; 1061 FETCH_INST;
1266 GOTO_NEXT_INST; 1062 GOTO_NEXT_INST;
1267} 1063}
1268#endif 1064#endif
1269#ifdef VFP_CDP_TRANS 1065
1270if ((OPC_1 & 0xB) == 0xA && (OPC_2 & 0x2) == 0)
1271{
1272 DBG("VDIV :\n");
1273}
1274#endif
1275#ifdef VFP_DYNCOM_TABLE 1066#ifdef VFP_DYNCOM_TABLE
1276DYNCOM_FILL_ACTION(vfpinstr), 1067DYNCOM_FILL_ACTION(vdiv),
1277#endif 1068#endif
1278#ifdef VFP_DYNCOM_TAG 1069#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) 1070int DYNCOM_TAG(vdiv)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1280{ 1071{
1281 int instr_size = INSTR_SIZE; 1072 int instr_size = INSTR_SIZE;
1282 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1073 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -1286,7 +1077,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1286} 1077}
1287#endif 1078#endif
1288#ifdef VFP_DYNCOM_TRANS 1079#ifdef VFP_DYNCOM_TRANS
1289int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1080int 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__); 1081 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1291 //arch_arm_undef(cpu, bb, instr); 1082 //arch_arm_undef(cpu, bb, instr);
1292 int m; 1083 int m;
@@ -1338,43 +1129,25 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1338 return No_exp; 1129 return No_exp;
1339} 1130}
1340#endif 1131#endif
1341#undef vfpinstr
1342#undef vfpinstr_inst
1343#undef VFPLABEL_INST
1344 1132
1345/* ----------------------------------------------------------------------- */ 1133/* ----------------------------------------------------------------------- */
1346/* VMOVI move immediate */ 1134/* VMOVI move immediate */
1347/* cond 1110 1D11 im4H Vd-- 101X 0000 im4L */ 1135/* cond 1110 1D11 im4H Vd-- 101X 0000 im4L */
1348/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */ 1136/* 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 1137#ifdef VFP_INTERPRETER_STRUCT
1365typedef struct _vmovi_inst { 1138typedef struct _vmovi_inst {
1366 unsigned int single; 1139 unsigned int single;
1367 unsigned int d; 1140 unsigned int d;
1368 unsigned int imm; 1141 unsigned int imm;
1369} vfpinstr_inst; 1142} vmovi_inst;
1370#endif 1143#endif
1371#ifdef VFP_INTERPRETER_TRANS 1144#ifdef VFP_INTERPRETER_TRANS
1372ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1145ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index)
1373{ 1146{
1374 VFP_DEBUG_TRANSLATE; 1147 VFP_DEBUG_TRANSLATE;
1375 1148
1376 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1149 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovi_inst));
1377 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1150 vmovi_inst *inst_cream = (vmovi_inst *)inst_base->component;
1378 1151
1379 inst_base->cond = BITS(inst, 28, 31); 1152 inst_base->cond = BITS(inst, 28, 31);
1380 inst_base->idx = index; 1153 inst_base->idx = index;
@@ -1392,62 +1165,28 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1392} 1165}
1393#endif 1166#endif
1394#ifdef VFP_INTERPRETER_IMPL 1167#ifdef VFP_INTERPRETER_IMPL
1395VFPLABEL_INST: 1168VMOVI_INST:
1396{ 1169{
1397 INC_ICOUNTER; 1170 INC_ICOUNTER;
1398 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1171 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1399 CHECK_VFP_ENABLED; 1172 CHECK_VFP_ENABLED;
1400 1173
1401 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1174 vmovi_inst *inst_cream = (vmovi_inst *)inst_base->component;
1402 1175
1403 VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm); 1176 VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm);
1404 } 1177 }
1405 cpu->Reg[15] += GET_INST_SIZE(cpu); 1178 cpu->Reg[15] += GET_INST_SIZE(cpu);
1406 INC_PC(sizeof(vfpinstr_inst)); 1179 INC_PC(sizeof(vmovi_inst));
1407 FETCH_INST; 1180 FETCH_INST;
1408 GOTO_NEXT_INST; 1181 GOTO_NEXT_INST;
1409} 1182}
1410#endif 1183#endif
1411#ifdef VFP_CDP_TRANS 1184
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 1185#ifdef VFP_DYNCOM_TABLE
1447DYNCOM_FILL_ACTION(vfpinstr), 1186DYNCOM_FILL_ACTION(vmovi),
1448#endif 1187#endif
1449#ifdef VFP_DYNCOM_TAG 1188#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) 1189int DYNCOM_TAG(vmovi)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1451{ 1190{
1452 int instr_size = INSTR_SIZE; 1191 int instr_size = INSTR_SIZE;
1453 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1192 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -1456,7 +1195,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1456} 1195}
1457#endif 1196#endif
1458#ifdef VFP_DYNCOM_TRANS 1197#ifdef VFP_DYNCOM_TRANS
1459int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1198int 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__); 1199 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1461 //arch_arm_undef(cpu, bb, instr); 1200 //arch_arm_undef(cpu, bb, instr);
1462 int single = (BIT(8) == 0); 1201 int single = (BIT(8) == 0);
@@ -1482,44 +1221,26 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1482 return No_exp; 1221 return No_exp;
1483} 1222}
1484#endif 1223#endif
1485#undef vfpinstr
1486#undef vfpinstr_inst
1487#undef VFPLABEL_INST
1488 1224
1489/* ----------------------------------------------------------------------- */ 1225/* ----------------------------------------------------------------------- */
1490/* VMOVR move register */ 1226/* VMOVR move register */
1491/* cond 1110 1D11 0000 Vd-- 101X 01M0 Vm-- */ 1227/* cond 1110 1D11 0000 Vd-- 101X 01M0 Vm-- */
1492/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */ 1228/* 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 1229#ifdef VFP_INTERPRETER_STRUCT
1509typedef struct _vmovr_inst { 1230typedef struct _vmovr_inst {
1510 unsigned int single; 1231 unsigned int single;
1511 unsigned int d; 1232 unsigned int d;
1512 unsigned int m; 1233 unsigned int m;
1513} vfpinstr_inst; 1234} vmovr_inst;
1514#endif 1235#endif
1515#ifdef VFP_INTERPRETER_TRANS 1236#ifdef VFP_INTERPRETER_TRANS
1516ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1237ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index)
1517{ 1238{
1518 VFP_DEBUG_TRANSLATE; 1239 VFP_DEBUG_TRANSLATE;
1519 VFP_DEBUG_UNTESTED(VMOVR); 1240 VFP_DEBUG_UNTESTED(VMOVR);
1520 1241
1521 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1242 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovr_inst));
1522 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1243 vmovr_inst *inst_cream = (vmovr_inst *)inst_base->component;
1523 1244
1524 inst_base->cond = BITS(inst, 28, 31); 1245 inst_base->cond = BITS(inst, 28, 31);
1525 inst_base->idx = index; 1246 inst_base->idx = index;
@@ -1533,56 +1254,28 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1533} 1254}
1534#endif 1255#endif
1535#ifdef VFP_INTERPRETER_IMPL 1256#ifdef VFP_INTERPRETER_IMPL
1536VFPLABEL_INST: 1257VMOVR_INST:
1537{ 1258{
1538 INC_ICOUNTER; 1259 INC_ICOUNTER;
1539 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1260 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1540 CHECK_VFP_ENABLED; 1261 CHECK_VFP_ENABLED;
1541 1262
1542 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1263 vmovr_inst *inst_cream = (vmovr_inst *)inst_base->component;
1543 1264
1544 VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m); 1265 VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m);
1545 } 1266 }
1546 cpu->Reg[15] += GET_INST_SIZE(cpu); 1267 cpu->Reg[15] += GET_INST_SIZE(cpu);
1547 INC_PC(sizeof(vfpinstr_inst)); 1268 INC_PC(sizeof(vmovr_inst));
1548 FETCH_INST; 1269 FETCH_INST;
1549 GOTO_NEXT_INST; 1270 GOTO_NEXT_INST;
1550} 1271}
1551#endif 1272#endif
1552#ifdef VFP_CDP_TRANS 1273
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 1274#ifdef VFP_DYNCOM_TABLE
1582DYNCOM_FILL_ACTION(vfpinstr), 1275DYNCOM_FILL_ACTION(vmovr),
1583#endif 1276#endif
1584#ifdef VFP_DYNCOM_TAG 1277#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) 1278int DYNCOM_TAG(vmovr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1586{ 1279{
1587 int instr_size = INSTR_SIZE; 1280 int instr_size = INSTR_SIZE;
1588 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc); 1281 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
@@ -1594,7 +1287,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1594} 1287}
1595#endif 1288#endif
1596#ifdef VFP_DYNCOM_TRANS 1289#ifdef VFP_DYNCOM_TRANS
1597int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1290int DYNCOM_TRANS(vmovr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1598 DBG("\t\tin %s VMOV \n", __FUNCTION__); 1291 DBG("\t\tin %s VMOV \n", __FUNCTION__);
1599 int single = BIT(8) == 0; 1292 int single = BIT(8) == 0;
1600 int d = (single ? BITS(12,15)<<1 | BIT(22) : BIT(22) << 4 | BITS(12,15)); 1293 int d = (single ? BITS(12,15)<<1 | BIT(22) : BIT(22) << 4 | BITS(12,15));
@@ -1613,41 +1306,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1613 return No_exp; 1306 return No_exp;
1614} 1307}
1615#endif 1308#endif
1616#undef vfpinstr
1617#undef vfpinstr_inst
1618#undef VFPLABEL_INST
1619 1309
1620/* ----------------------------------------------------------------------- */ 1310/* ----------------------------------------------------------------------- */
1621/* VABS */ 1311/* VABS */
1622/* cond 1110 1D11 0000 Vd-- 101X 11M0 Vm-- */ 1312/* 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 1313#ifdef VFP_INTERPRETER_STRUCT
1639typedef struct _vabs_inst { 1314typedef struct _vabs_inst {
1640 unsigned int instr; 1315 unsigned int instr;
1641 unsigned int dp_operation; 1316 unsigned int dp_operation;
1642} vfpinstr_inst; 1317} vabs_inst;
1643#endif 1318#endif
1644#ifdef VFP_INTERPRETER_TRANS 1319#ifdef VFP_INTERPRETER_TRANS
1645ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1320ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index)
1646{ 1321{
1647 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VABS); 1322 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VABS);
1648 1323
1649 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1324 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vabs_inst));
1650 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1325 vabs_inst *inst_cream = (vabs_inst *)inst_base->component;
1651 1326
1652 inst_base->cond = BITS(inst, 28, 31); 1327 inst_base->cond = BITS(inst, 28, 31);
1653 inst_base->idx = index; 1328 inst_base->idx = index;
@@ -1661,7 +1336,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1661} 1336}
1662#endif 1337#endif
1663#ifdef VFP_INTERPRETER_IMPL 1338#ifdef VFP_INTERPRETER_IMPL
1664VFPLABEL_INST: 1339VABS_INST:
1665{ 1340{
1666 INC_ICOUNTER; 1341 INC_ICOUNTER;
1667 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1342 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -1669,7 +1344,7 @@ VFPLABEL_INST:
1669 1344
1670 DBG("VABS :\n"); 1345 DBG("VABS :\n");
1671 1346
1672 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1347 vabs_inst *inst_cream = (vabs_inst *)inst_base->component;
1673 1348
1674 int ret; 1349 int ret;
1675 1350
@@ -1681,22 +1356,17 @@ VFPLABEL_INST:
1681 CHECK_VFP_CDP_RET; 1356 CHECK_VFP_CDP_RET;
1682 } 1357 }
1683 cpu->Reg[15] += GET_INST_SIZE(cpu); 1358 cpu->Reg[15] += GET_INST_SIZE(cpu);
1684 INC_PC(sizeof(vfpinstr_inst)); 1359 INC_PC(sizeof(vabs_inst));
1685 FETCH_INST; 1360 FETCH_INST;
1686 GOTO_NEXT_INST; 1361 GOTO_NEXT_INST;
1687} 1362}
1688#endif 1363#endif
1689#ifdef VFP_CDP_TRANS 1364
1690if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x7) == 6)
1691{
1692 DBG("VABS :\n");
1693}
1694#endif
1695#ifdef VFP_DYNCOM_TABLE 1365#ifdef VFP_DYNCOM_TABLE
1696DYNCOM_FILL_ACTION(vfpinstr), 1366DYNCOM_FILL_ACTION(vabs),
1697#endif 1367#endif
1698#ifdef VFP_DYNCOM_TAG 1368#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) 1369int DYNCOM_TAG(vabs)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1700{ 1370{
1701 int instr_size = INSTR_SIZE; 1371 int instr_size = INSTR_SIZE;
1702 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1372 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -1706,7 +1376,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1706} 1376}
1707#endif 1377#endif
1708#ifdef VFP_DYNCOM_TRANS 1378#ifdef VFP_DYNCOM_TRANS
1709int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1379int 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__); 1380 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1711 //arch_arm_undef(cpu, bb, instr); 1381 //arch_arm_undef(cpu, bb, instr);
1712 int single = BIT(8) == 0; 1382 int single = BIT(8) == 0;
@@ -1744,42 +1414,24 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1744 return No_exp; 1414 return No_exp;
1745} 1415}
1746#endif 1416#endif
1747#undef vfpinstr
1748#undef vfpinstr_inst
1749#undef VFPLABEL_INST
1750 1417
1751/* ----------------------------------------------------------------------- */ 1418/* ----------------------------------------------------------------------- */
1752/* VNEG */ 1419/* VNEG */
1753/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */ 1420/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */
1754#define vfpinstr vneg 1421
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 1422#ifdef VFP_INTERPRETER_STRUCT
1771typedef struct _vneg_inst { 1423typedef struct _vneg_inst {
1772 unsigned int instr; 1424 unsigned int instr;
1773 unsigned int dp_operation; 1425 unsigned int dp_operation;
1774} vfpinstr_inst; 1426} vneg_inst;
1775#endif 1427#endif
1776#ifdef VFP_INTERPRETER_TRANS 1428#ifdef VFP_INTERPRETER_TRANS
1777ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1429ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index)
1778{ 1430{
1779 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VNEG); 1431 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VNEG);
1780 1432
1781 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1433 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vneg_inst));
1782 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1434 vneg_inst *inst_cream = (vneg_inst *)inst_base->component;
1783 1435
1784 inst_base->cond = BITS(inst, 28, 31); 1436 inst_base->cond = BITS(inst, 28, 31);
1785 inst_base->idx = index; 1437 inst_base->idx = index;
@@ -1793,7 +1445,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1793} 1445}
1794#endif 1446#endif
1795#ifdef VFP_INTERPRETER_IMPL 1447#ifdef VFP_INTERPRETER_IMPL
1796VFPLABEL_INST: 1448VNEG_INST:
1797{ 1449{
1798 INC_ICOUNTER; 1450 INC_ICOUNTER;
1799 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1451 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -1801,7 +1453,7 @@ VFPLABEL_INST:
1801 1453
1802 DBG("VNEG :\n"); 1454 DBG("VNEG :\n");
1803 1455
1804 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1456 vneg_inst *inst_cream = (vneg_inst *)inst_base->component;
1805 1457
1806 int ret; 1458 int ret;
1807 1459
@@ -1813,22 +1465,17 @@ VFPLABEL_INST:
1813 CHECK_VFP_CDP_RET; 1465 CHECK_VFP_CDP_RET;
1814 } 1466 }
1815 cpu->Reg[15] += GET_INST_SIZE(cpu); 1467 cpu->Reg[15] += GET_INST_SIZE(cpu);
1816 INC_PC(sizeof(vfpinstr_inst)); 1468 INC_PC(sizeof(vneg_inst));
1817 FETCH_INST; 1469 FETCH_INST;
1818 GOTO_NEXT_INST; 1470 GOTO_NEXT_INST;
1819} 1471}
1820#endif 1472#endif
1821#ifdef VFP_CDP_TRANS 1473
1822if ((OPC_1 & 0xB) == 0xB && CRn == 1 && (OPC_2 & 0x7) == 2)
1823{
1824 DBG("VNEG :\n");
1825}
1826#endif
1827#ifdef VFP_DYNCOM_TABLE 1474#ifdef VFP_DYNCOM_TABLE
1828DYNCOM_FILL_ACTION(vfpinstr), 1475DYNCOM_FILL_ACTION(vneg),
1829#endif 1476#endif
1830#ifdef VFP_DYNCOM_TAG 1477#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) 1478int DYNCOM_TAG(vneg)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1832{ 1479{
1833 int instr_size = INSTR_SIZE; 1480 int instr_size = INSTR_SIZE;
1834 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1481 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -1838,7 +1485,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1838} 1485}
1839#endif 1486#endif
1840#ifdef VFP_DYNCOM_TRANS 1487#ifdef VFP_DYNCOM_TRANS
1841int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1488int 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__); 1489 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1843 //arch_arm_undef(cpu, bb, instr); 1490 //arch_arm_undef(cpu, bb, instr);
1844 int single = BIT(8) == 0; 1491 int single = BIT(8) == 0;
@@ -1876,41 +1523,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1876 return No_exp; 1523 return No_exp;
1877} 1524}
1878#endif 1525#endif
1879#undef vfpinstr
1880#undef vfpinstr_inst
1881#undef VFPLABEL_INST
1882 1526
1883/* ----------------------------------------------------------------------- */ 1527/* ----------------------------------------------------------------------- */
1884/* VSQRT */ 1528/* VSQRT */
1885/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */ 1529/* 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 1530#ifdef VFP_INTERPRETER_STRUCT
1902typedef struct _vsqrt_inst { 1531typedef struct _vsqrt_inst {
1903 unsigned int instr; 1532 unsigned int instr;
1904 unsigned int dp_operation; 1533 unsigned int dp_operation;
1905} vfpinstr_inst; 1534} vsqrt_inst;
1906#endif 1535#endif
1907#ifdef VFP_INTERPRETER_TRANS 1536#ifdef VFP_INTERPRETER_TRANS
1908ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1537ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index)
1909{ 1538{
1910 VFP_DEBUG_TRANSLATE; 1539 VFP_DEBUG_TRANSLATE;
1911 1540
1912 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1541 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vsqrt_inst));
1913 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1542 vsqrt_inst *inst_cream = (vsqrt_inst *)inst_base->component;
1914 1543
1915 inst_base->cond = BITS(inst, 28, 31); 1544 inst_base->cond = BITS(inst, 28, 31);
1916 inst_base->idx = index; 1545 inst_base->idx = index;
@@ -1924,7 +1553,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1924} 1553}
1925#endif 1554#endif
1926#ifdef VFP_INTERPRETER_IMPL 1555#ifdef VFP_INTERPRETER_IMPL
1927VFPLABEL_INST: 1556VSQRT_INST:
1928{ 1557{
1929 INC_ICOUNTER; 1558 INC_ICOUNTER;
1930 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1559 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -1932,7 +1561,7 @@ VFPLABEL_INST:
1932 1561
1933 DBG("VSQRT :\n"); 1562 DBG("VSQRT :\n");
1934 1563
1935 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1564 vsqrt_inst *inst_cream = (vsqrt_inst *)inst_base->component;
1936 1565
1937 int ret; 1566 int ret;
1938 1567
@@ -1944,22 +1573,17 @@ VFPLABEL_INST:
1944 CHECK_VFP_CDP_RET; 1573 CHECK_VFP_CDP_RET;
1945 } 1574 }
1946 cpu->Reg[15] += GET_INST_SIZE(cpu); 1575 cpu->Reg[15] += GET_INST_SIZE(cpu);
1947 INC_PC(sizeof(vfpinstr_inst)); 1576 INC_PC(sizeof(vsqrt_inst));
1948 FETCH_INST; 1577 FETCH_INST;
1949 GOTO_NEXT_INST; 1578 GOTO_NEXT_INST;
1950} 1579}
1951#endif 1580#endif
1952#ifdef VFP_CDP_TRANS 1581
1953if ((OPC_1 & 0xB) == 0xB && CRn == 1 && (OPC_2 & 0x7) == 6)
1954{
1955 DBG("VSQRT :\n");
1956}
1957#endif
1958#ifdef VFP_DYNCOM_TABLE 1582#ifdef VFP_DYNCOM_TABLE
1959DYNCOM_FILL_ACTION(vfpinstr), 1583DYNCOM_FILL_ACTION(vsqrt),
1960#endif 1584#endif
1961#ifdef VFP_DYNCOM_TAG 1585#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) 1586int DYNCOM_TAG(vsqrt)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1963{ 1587{
1964 int instr_size = INSTR_SIZE; 1588 int instr_size = INSTR_SIZE;
1965 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1589 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -1969,7 +1593,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1969} 1593}
1970#endif 1594#endif
1971#ifdef VFP_DYNCOM_TRANS 1595#ifdef VFP_DYNCOM_TRANS
1972int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1596int 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__); 1597 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1974 //arch_arm_undef(cpu, bb, instr); 1598 //arch_arm_undef(cpu, bb, instr);
1975 int dp_op = (BIT(8) == 1); 1599 int dp_op = (BIT(8) == 1);
@@ -1995,41 +1619,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1995 return No_exp; 1619 return No_exp;
1996} 1620}
1997#endif 1621#endif
1998#undef vfpinstr
1999#undef vfpinstr_inst
2000#undef VFPLABEL_INST
2001 1622
2002/* ----------------------------------------------------------------------- */ 1623/* ----------------------------------------------------------------------- */
2003/* VCMP VCMPE */ 1624/* VCMP VCMPE */
2004/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 1 */ 1625/* 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 1626#ifdef VFP_INTERPRETER_STRUCT
2021typedef struct _vcmp_inst { 1627typedef struct _vcmp_inst {
2022 unsigned int instr; 1628 unsigned int instr;
2023 unsigned int dp_operation; 1629 unsigned int dp_operation;
2024} vfpinstr_inst; 1630} vcmp_inst;
2025#endif 1631#endif
2026#ifdef VFP_INTERPRETER_TRANS 1632#ifdef VFP_INTERPRETER_TRANS
2027ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1633ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index)
2028{ 1634{
2029 VFP_DEBUG_TRANSLATE; 1635 VFP_DEBUG_TRANSLATE;
2030 1636
2031 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1637 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp_inst));
2032 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1638 vcmp_inst *inst_cream = (vcmp_inst *)inst_base->component;
2033 1639
2034 inst_base->cond = BITS(inst, 28, 31); 1640 inst_base->cond = BITS(inst, 28, 31);
2035 inst_base->idx = index; 1641 inst_base->idx = index;
@@ -2043,7 +1649,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2043} 1649}
2044#endif 1650#endif
2045#ifdef VFP_INTERPRETER_IMPL 1651#ifdef VFP_INTERPRETER_IMPL
2046VFPLABEL_INST: 1652VCMP_INST:
2047{ 1653{
2048 INC_ICOUNTER; 1654 INC_ICOUNTER;
2049 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1655 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -2051,7 +1657,7 @@ VFPLABEL_INST:
2051 1657
2052 DBG("VCMP(1) :\n"); 1658 DBG("VCMP(1) :\n");
2053 1659
2054 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1660 vcmp_inst *inst_cream = (vcmp_inst *)inst_base->component;
2055 1661
2056 int ret; 1662 int ret;
2057 1663
@@ -2063,22 +1669,17 @@ VFPLABEL_INST:
2063 CHECK_VFP_CDP_RET; 1669 CHECK_VFP_CDP_RET;
2064 } 1670 }
2065 cpu->Reg[15] += GET_INST_SIZE(cpu); 1671 cpu->Reg[15] += GET_INST_SIZE(cpu);
2066 INC_PC(sizeof(vfpinstr_inst)); 1672 INC_PC(sizeof(vcmp_inst));
2067 FETCH_INST; 1673 FETCH_INST;
2068 GOTO_NEXT_INST; 1674 GOTO_NEXT_INST;
2069} 1675}
2070#endif 1676#endif
2071#ifdef VFP_CDP_TRANS 1677
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 1678#ifdef VFP_DYNCOM_TABLE
2078DYNCOM_FILL_ACTION(vfpinstr), 1679DYNCOM_FILL_ACTION(vcmp),
2079#endif 1680#endif
2080#ifdef VFP_DYNCOM_TAG 1681#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) 1682int DYNCOM_TAG(vcmp)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2082{ 1683{
2083 int instr_size = INSTR_SIZE; 1684 int instr_size = INSTR_SIZE;
2084 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc); 1685 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
@@ -2087,7 +1688,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2087} 1688}
2088#endif 1689#endif
2089#ifdef VFP_DYNCOM_TRANS 1690#ifdef VFP_DYNCOM_TRANS
2090int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1691int 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__); 1692 DBG("\t\tin %s instruction is executed out of JIT.\n", __FUNCTION__);
2092 //arch_arm_undef(cpu, bb, instr); 1693 //arch_arm_undef(cpu, bb, instr);
2093 int dp_op = (BIT(8) == 1); 1694 int dp_op = (BIT(8) == 1);
@@ -2141,41 +1742,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
2141 return No_exp; 1742 return No_exp;
2142} 1743}
2143#endif 1744#endif
2144#undef vfpinstr
2145#undef vfpinstr_inst
2146#undef VFPLABEL_INST
2147 1745
2148/* ----------------------------------------------------------------------- */ 1746/* ----------------------------------------------------------------------- */
2149/* VCMP VCMPE */ 1747/* VCMP VCMPE */
2150/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 2 */ 1748/* 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 1749#ifdef VFP_INTERPRETER_STRUCT
2167typedef struct _vcmp2_inst { 1750typedef struct _vcmp2_inst {
2168 unsigned int instr; 1751 unsigned int instr;
2169 unsigned int dp_operation; 1752 unsigned int dp_operation;
2170} vfpinstr_inst; 1753} vcmp2_inst;
2171#endif 1754#endif
2172#ifdef VFP_INTERPRETER_TRANS 1755#ifdef VFP_INTERPRETER_TRANS
2173ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1756ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index)
2174{ 1757{
2175 VFP_DEBUG_TRANSLATE; 1758 VFP_DEBUG_TRANSLATE;
2176 1759
2177 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1760 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp2_inst));
2178 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1761 vcmp2_inst *inst_cream = (vcmp2_inst *)inst_base->component;
2179 1762
2180 inst_base->cond = BITS(inst, 28, 31); 1763 inst_base->cond = BITS(inst, 28, 31);
2181 inst_base->idx = index; 1764 inst_base->idx = index;
@@ -2189,7 +1772,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2189} 1772}
2190#endif 1773#endif
2191#ifdef VFP_INTERPRETER_IMPL 1774#ifdef VFP_INTERPRETER_IMPL
2192VFPLABEL_INST: 1775VCMP2_INST:
2193{ 1776{
2194 INC_ICOUNTER; 1777 INC_ICOUNTER;
2195 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1778 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -2197,7 +1780,7 @@ VFPLABEL_INST:
2197 1780
2198 DBG("VCMP(2) :\n"); 1781 DBG("VCMP(2) :\n");
2199 1782
2200 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1783 vcmp2_inst *inst_cream = (vcmp2_inst *)inst_base->component;
2201 1784
2202 int ret; 1785 int ret;
2203 1786
@@ -2209,22 +1792,17 @@ VFPLABEL_INST:
2209 CHECK_VFP_CDP_RET; 1792 CHECK_VFP_CDP_RET;
2210 } 1793 }
2211 cpu->Reg[15] += GET_INST_SIZE(cpu); 1794 cpu->Reg[15] += GET_INST_SIZE(cpu);
2212 INC_PC(sizeof(vfpinstr_inst)); 1795 INC_PC(sizeof(vcmp2_inst));
2213 FETCH_INST; 1796 FETCH_INST;
2214 GOTO_NEXT_INST; 1797 GOTO_NEXT_INST;
2215} 1798}
2216#endif 1799#endif
2217#ifdef VFP_CDP_TRANS 1800
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 1801#ifdef VFP_DYNCOM_TABLE
2224DYNCOM_FILL_ACTION(vfpinstr), 1802DYNCOM_FILL_ACTION(vcmp2),
2225#endif 1803#endif
2226#ifdef VFP_DYNCOM_TAG 1804#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) 1805int DYNCOM_TAG(vcmp2)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2228{ 1806{
2229 int instr_size = INSTR_SIZE; 1807 int instr_size = INSTR_SIZE;
2230 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc); 1808 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
@@ -2233,7 +1811,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2233} 1811}
2234#endif 1812#endif
2235#ifdef VFP_DYNCOM_TRANS 1813#ifdef VFP_DYNCOM_TRANS
2236int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1814int 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__); 1815 DBG("\t\tin %s instruction will executed out of JIT.\n", __FUNCTION__);
2238 //arch_arm_undef(cpu, bb, instr); 1816 //arch_arm_undef(cpu, bb, instr);
2239 int dp_op = (BIT(8) == 1); 1817 int dp_op = (BIT(8) == 1);
@@ -2287,41 +1865,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
2287 return No_exp; 1865 return No_exp;
2288} 1866}
2289#endif 1867#endif
2290#undef vfpinstr
2291#undef vfpinstr_inst
2292#undef VFPLABEL_INST
2293 1868
2294/* ----------------------------------------------------------------------- */ 1869/* ----------------------------------------------------------------------- */
2295/* VCVTBDS between double and single */ 1870/* VCVTBDS between double and single */
2296/* cond 1110 1D11 0111 Vd-- 101X 11M0 Vm-- */ 1871/* 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 1872#ifdef VFP_INTERPRETER_STRUCT
2313typedef struct _vcvtbds_inst { 1873typedef struct _vcvtbds_inst {
2314 unsigned int instr; 1874 unsigned int instr;
2315 unsigned int dp_operation; 1875 unsigned int dp_operation;
2316} vfpinstr_inst; 1876} vcvtbds_inst;
2317#endif 1877#endif
2318#ifdef VFP_INTERPRETER_TRANS 1878#ifdef VFP_INTERPRETER_TRANS
2319ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1879ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index)
2320{ 1880{
2321 VFP_DEBUG_TRANSLATE; 1881 VFP_DEBUG_TRANSLATE;
2322 1882
2323 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1883 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbds_inst));
2324 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1884 vcvtbds_inst *inst_cream = (vcvtbds_inst *)inst_base->component;
2325 1885
2326 inst_base->cond = BITS(inst, 28, 31); 1886 inst_base->cond = BITS(inst, 28, 31);
2327 inst_base->idx = index; 1887 inst_base->idx = index;
@@ -2335,7 +1895,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2335} 1895}
2336#endif 1896#endif
2337#ifdef VFP_INTERPRETER_IMPL 1897#ifdef VFP_INTERPRETER_IMPL
2338VFPLABEL_INST: 1898VCVTBDS_INST:
2339{ 1899{
2340 INC_ICOUNTER; 1900 INC_ICOUNTER;
2341 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1901 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -2343,7 +1903,7 @@ VFPLABEL_INST:
2343 1903
2344 DBG("VCVT(BDS) :\n"); 1904 DBG("VCVT(BDS) :\n");
2345 1905
2346 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1906 vcvtbds_inst *inst_cream = (vcvtbds_inst *)inst_base->component;
2347 1907
2348 int ret; 1908 int ret;
2349 1909
@@ -2355,22 +1915,17 @@ VFPLABEL_INST:
2355 CHECK_VFP_CDP_RET; 1915 CHECK_VFP_CDP_RET;
2356 } 1916 }
2357 cpu->Reg[15] += GET_INST_SIZE(cpu); 1917 cpu->Reg[15] += GET_INST_SIZE(cpu);
2358 INC_PC(sizeof(vfpinstr_inst)); 1918 INC_PC(sizeof(vcvtbds_inst));
2359 FETCH_INST; 1919 FETCH_INST;
2360 GOTO_NEXT_INST; 1920 GOTO_NEXT_INST;
2361} 1921}
2362#endif 1922#endif
2363#ifdef VFP_CDP_TRANS 1923
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 1924#ifdef VFP_DYNCOM_TABLE
2370DYNCOM_FILL_ACTION(vfpinstr), 1925DYNCOM_FILL_ACTION(vcvtbds),
2371#endif 1926#endif
2372#ifdef VFP_DYNCOM_TAG 1927#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) 1928int DYNCOM_TAG(vcvtbds)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2374{ 1929{
2375 int instr_size = INSTR_SIZE; 1930 int instr_size = INSTR_SIZE;
2376 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc); 1931 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
@@ -2379,7 +1934,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2379} 1934}
2380#endif 1935#endif
2381#ifdef VFP_DYNCOM_TRANS 1936#ifdef VFP_DYNCOM_TRANS
2382int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1937int 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__); 1938 DBG("\t\tin %s instruction is executed out.\n", __FUNCTION__);
2384 //arch_arm_undef(cpu, bb, instr); 1939 //arch_arm_undef(cpu, bb, instr);
2385 int dp_op = (BIT(8) == 1); 1940 int dp_op = (BIT(8) == 1);
@@ -2407,41 +1962,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
2407 return No_exp; 1962 return No_exp;
2408} 1963}
2409#endif 1964#endif
2410#undef vfpinstr
2411#undef vfpinstr_inst
2412#undef VFPLABEL_INST
2413 1965
2414/* ----------------------------------------------------------------------- */ 1966/* ----------------------------------------------------------------------- */
2415/* VCVTBFF between floating point and fixed point */ 1967/* VCVTBFF between floating point and fixed point */
2416/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */ 1968/* 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 1969#ifdef VFP_INTERPRETER_STRUCT
2433typedef struct _vcvtbff_inst { 1970typedef struct _vcvtbff_inst {
2434 unsigned int instr; 1971 unsigned int instr;
2435 unsigned int dp_operation; 1972 unsigned int dp_operation;
2436} vfpinstr_inst; 1973} vcvtbff_inst;
2437#endif 1974#endif
2438#ifdef VFP_INTERPRETER_TRANS 1975#ifdef VFP_INTERPRETER_TRANS
2439ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1976ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index)
2440{ 1977{
2441 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VCVTBFF); 1978 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VCVTBFF);
2442 1979
2443 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1980 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbff_inst));
2444 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1981 vcvtbff_inst *inst_cream = (vcvtbff_inst *)inst_base->component;
2445 1982
2446 inst_base->cond = BITS(inst, 28, 31); 1983 inst_base->cond = BITS(inst, 28, 31);
2447 inst_base->idx = index; 1984 inst_base->idx = index;
@@ -2455,7 +1992,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2455} 1992}
2456#endif 1993#endif
2457#ifdef VFP_INTERPRETER_IMPL 1994#ifdef VFP_INTERPRETER_IMPL
2458VFPLABEL_INST: 1995VCVTBFF_INST:
2459{ 1996{
2460 INC_ICOUNTER; 1997 INC_ICOUNTER;
2461 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1998 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -2463,7 +2000,7 @@ VFPLABEL_INST:
2463 2000
2464 DBG("VCVT(BFF) :\n"); 2001 DBG("VCVT(BFF) :\n");
2465 2002
2466 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2003 vcvtbff_inst *inst_cream = (vcvtbff_inst *)inst_base->component;
2467 2004
2468 int ret; 2005 int ret;
2469 2006
@@ -2475,22 +2012,17 @@ VFPLABEL_INST:
2475 CHECK_VFP_CDP_RET; 2012 CHECK_VFP_CDP_RET;
2476 } 2013 }
2477 cpu->Reg[15] += GET_INST_SIZE(cpu); 2014 cpu->Reg[15] += GET_INST_SIZE(cpu);
2478 INC_PC(sizeof(vfpinstr_inst)); 2015 INC_PC(sizeof(vcvtbff_inst));
2479 FETCH_INST; 2016 FETCH_INST;
2480 GOTO_NEXT_INST; 2017 GOTO_NEXT_INST;
2481} 2018}
2482#endif 2019#endif
2483#ifdef VFP_CDP_TRANS 2020
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 2021#ifdef VFP_DYNCOM_TABLE
2490DYNCOM_FILL_ACTION(vfpinstr), 2022DYNCOM_FILL_ACTION(vcvtbff),
2491#endif 2023#endif
2492#ifdef VFP_DYNCOM_TAG 2024#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) 2025int DYNCOM_TAG(vcvtbff)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2494{ 2026{
2495 int instr_size = INSTR_SIZE; 2027 int instr_size = INSTR_SIZE;
2496 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2028 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -2499,47 +2031,29 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2499} 2031}
2500#endif 2032#endif
2501#ifdef VFP_DYNCOM_TRANS 2033#ifdef VFP_DYNCOM_TRANS
2502int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2034int 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__); 2035 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2504 arch_arm_undef(cpu, bb, instr); 2036 arch_arm_undef(cpu, bb, instr);
2505 return No_exp; 2037 return No_exp;
2506} 2038}
2507#endif 2039#endif
2508#undef vfpinstr
2509#undef vfpinstr_inst
2510#undef VFPLABEL_INST
2511 2040
2512/* ----------------------------------------------------------------------- */ 2041/* ----------------------------------------------------------------------- */
2513/* VCVTBFI between floating point and integer */ 2042/* VCVTBFI between floating point and integer */
2514/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */ 2043/* 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 2044#ifdef VFP_INTERPRETER_STRUCT
2531typedef struct _vcvtbfi_inst { 2045typedef struct _vcvtbfi_inst {
2532 unsigned int instr; 2046 unsigned int instr;
2533 unsigned int dp_operation; 2047 unsigned int dp_operation;
2534} vfpinstr_inst; 2048} vcvtbfi_inst;
2535#endif 2049#endif
2536#ifdef VFP_INTERPRETER_TRANS 2050#ifdef VFP_INTERPRETER_TRANS
2537ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2051ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index)
2538{ 2052{
2539 VFP_DEBUG_TRANSLATE; 2053 VFP_DEBUG_TRANSLATE;
2540 2054
2541 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2055 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbfi_inst));
2542 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2056 vcvtbfi_inst *inst_cream = (vcvtbfi_inst *)inst_base->component;
2543 2057
2544 inst_base->cond = BITS(inst, 28, 31); 2058 inst_base->cond = BITS(inst, 28, 31);
2545 inst_base->idx = index; 2059 inst_base->idx = index;
@@ -2554,7 +2068,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2554} 2068}
2555#endif 2069#endif
2556#ifdef VFP_INTERPRETER_IMPL 2070#ifdef VFP_INTERPRETER_IMPL
2557VFPLABEL_INST: 2071VCVTBFI_INST:
2558{ 2072{
2559 INC_ICOUNTER; 2073 INC_ICOUNTER;
2560 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2074 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -2562,7 +2076,7 @@ VFPLABEL_INST:
2562 2076
2563 DBG("VCVT(BFI) :\n"); 2077 DBG("VCVT(BFI) :\n");
2564 2078
2565 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2079 vcvtbfi_inst *inst_cream = (vcvtbfi_inst *)inst_base->component;
2566 2080
2567 int ret; 2081 int ret;
2568 2082
@@ -2574,22 +2088,17 @@ VFPLABEL_INST:
2574 CHECK_VFP_CDP_RET; 2088 CHECK_VFP_CDP_RET;
2575 } 2089 }
2576 cpu->Reg[15] += GET_INST_SIZE(cpu); 2090 cpu->Reg[15] += GET_INST_SIZE(cpu);
2577 INC_PC(sizeof(vfpinstr_inst)); 2091 INC_PC(sizeof(vcvtbfi_inst));
2578 FETCH_INST; 2092 FETCH_INST;
2579 GOTO_NEXT_INST; 2093 GOTO_NEXT_INST;
2580} 2094}
2581#endif 2095#endif
2582#ifdef VFP_CDP_TRANS 2096
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 2097#ifdef VFP_DYNCOM_TABLE
2589DYNCOM_FILL_ACTION(vfpinstr), 2098DYNCOM_FILL_ACTION(vcvtbfi),
2590#endif 2099#endif
2591#ifdef VFP_DYNCOM_TAG 2100#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) 2101int DYNCOM_TAG(vcvtbfi)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2593{ 2102{
2594 int instr_size = INSTR_SIZE; 2103 int instr_size = INSTR_SIZE;
2595 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2104 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -2600,7 +2109,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2600} 2109}
2601#endif 2110#endif
2602#ifdef VFP_DYNCOM_TRANS 2111#ifdef VFP_DYNCOM_TRANS
2603int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2112int 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__); 2113 DBG("\t\tin %s, instruction will be executed out of JIT.\n", __FUNCTION__);
2605 //arch_arm_undef(cpu, bb, instr); 2114 //arch_arm_undef(cpu, bb, instr);
2606 unsigned int opc2 = BITS(16,18); 2115 unsigned int opc2 = BITS(16,18);
@@ -2694,9 +2203,6 @@ int vcvtbfi_instr_impl(arm_core_t* cpu, uint32 instr){
2694 return 0; 2203 return 0;
2695} 2204}
2696#endif 2205#endif
2697#undef vfpinstr
2698#undef vfpinstr_inst
2699#undef VFPLABEL_INST
2700 2206
2701/* ----------------------------------------------------------------------- */ 2207/* ----------------------------------------------------------------------- */
2702/* MRC / MCR instructions */ 2208/* MRC / MCR instructions */
@@ -2707,35 +2213,20 @@ int vcvtbfi_instr_impl(arm_core_t* cpu, uint32 instr){
2707/* VMOVBRS between register and single precision */ 2213/* VMOVBRS between register and single precision */
2708/* cond 1110 000o Vn-- Rt-- 1010 N001 0000 */ 2214/* cond 1110 000o Vn-- Rt-- 1010 N001 0000 */
2709/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */ 2215/* 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 2216#ifdef VFP_INTERPRETER_STRUCT
2726typedef struct _vmovbrs_inst { 2217typedef struct _vmovbrs_inst {
2727 unsigned int to_arm; 2218 unsigned int to_arm;
2728 unsigned int t; 2219 unsigned int t;
2729 unsigned int n; 2220 unsigned int n;
2730} vfpinstr_inst; 2221} vmovbrs_inst;
2731#endif 2222#endif
2732#ifdef VFP_INTERPRETER_TRANS 2223#ifdef VFP_INTERPRETER_TRANS
2733ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2224ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index)
2734{ 2225{
2735 VFP_DEBUG_TRANSLATE; 2226 VFP_DEBUG_TRANSLATE;
2736 2227
2737 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2228 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrs_inst));
2738 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2229 vmovbrs_inst *inst_cream = (vmovbrs_inst *)inst_base->component;
2739 2230
2740 inst_base->cond = BITS(inst, 28, 31); 2231 inst_base->cond = BITS(inst, 28, 31);
2741 inst_base->idx = index; 2232 inst_base->idx = index;
@@ -2750,61 +2241,28 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2750} 2241}
2751#endif 2242#endif
2752#ifdef VFP_INTERPRETER_IMPL 2243#ifdef VFP_INTERPRETER_IMPL
2753VFPLABEL_INST: 2244VMOVBRS_INST:
2754{ 2245{
2755 INC_ICOUNTER; 2246 INC_ICOUNTER;
2756 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2247 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2757 CHECK_VFP_ENABLED; 2248 CHECK_VFP_ENABLED;
2758 2249
2759 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2250 vmovbrs_inst *inst_cream = (vmovbrs_inst *)inst_base->component;
2760 2251
2761 VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t])); 2252 VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t]));
2762 } 2253 }
2763 cpu->Reg[15] += GET_INST_SIZE(cpu); 2254 cpu->Reg[15] += GET_INST_SIZE(cpu);
2764 INC_PC(sizeof(vfpinstr_inst)); 2255 INC_PC(sizeof(vmovbrs_inst));
2765 FETCH_INST; 2256 FETCH_INST;
2766 GOTO_NEXT_INST; 2257 GOTO_NEXT_INST;
2767} 2258}
2768#endif 2259#endif
2769#ifdef VFP_MRC_TRANS 2260
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 2261#ifdef VFP_DYNCOM_TABLE
2804DYNCOM_FILL_ACTION(vfpinstr), 2262DYNCOM_FILL_ACTION(vmovbrs),
2805#endif 2263#endif
2806#ifdef VFP_DYNCOM_TAG 2264#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) 2265int DYNCOM_TAG(vmovbrs)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2808{ 2266{
2809 int instr_size = INSTR_SIZE; 2267 int instr_size = INSTR_SIZE;
2810 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2268 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -2813,7 +2271,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2813} 2271}
2814#endif 2272#endif
2815#ifdef VFP_DYNCOM_TRANS 2273#ifdef VFP_DYNCOM_TRANS
2816int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2274int DYNCOM_TRANS(vmovbrs)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2817 DBG("VMOV(BRS) :\n"); 2275 DBG("VMOV(BRS) :\n");
2818 int to_arm = BIT(20) == 1; 2276 int to_arm = BIT(20) == 1;
2819 int t = BITS(12, 15); 2277 int t = BITS(12, 15);
@@ -2832,42 +2290,24 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
2832 return No_exp; 2290 return No_exp;
2833} 2291}
2834#endif 2292#endif
2835#undef vfpinstr
2836#undef vfpinstr_inst
2837#undef VFPLABEL_INST
2838 2293
2839/* ----------------------------------------------------------------------- */ 2294/* ----------------------------------------------------------------------- */
2840/* VMSR */ 2295/* VMSR */
2841/* cond 1110 1110 reg- Rt-- 1010 0001 0000 */ 2296/* cond 1110 1110 reg- Rt-- 1010 0001 0000 */
2842/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */ 2297/* 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 2298#ifdef VFP_INTERPRETER_STRUCT
2859typedef struct _vmsr_inst { 2299typedef struct _vmsr_inst {
2860 unsigned int reg; 2300 unsigned int reg;
2861 unsigned int Rd; 2301 unsigned int Rd;
2862} vfpinstr_inst; 2302} vmsr_inst;
2863#endif 2303#endif
2864#ifdef VFP_INTERPRETER_TRANS 2304#ifdef VFP_INTERPRETER_TRANS
2865ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2305ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index)
2866{ 2306{
2867 VFP_DEBUG_TRANSLATE; 2307 VFP_DEBUG_TRANSLATE;
2868 2308
2869 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2309 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmsr_inst));
2870 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2310 vmsr_inst *inst_cream = (vmsr_inst *)inst_base->component;
2871 2311
2872 inst_base->cond = BITS(inst, 28, 31); 2312 inst_base->cond = BITS(inst, 28, 31);
2873 inst_base->idx = index; 2313 inst_base->idx = index;
@@ -2881,7 +2321,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2881} 2321}
2882#endif 2322#endif
2883#ifdef VFP_INTERPRETER_IMPL 2323#ifdef VFP_INTERPRETER_IMPL
2884VFPLABEL_INST: 2324VMSR_INST:
2885{ 2325{
2886 INC_ICOUNTER; 2326 INC_ICOUNTER;
2887 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2327 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -2890,43 +2330,22 @@ VFPLABEL_INST:
2890 /* Exceptions must be checked, according to v7 ref manual */ 2330 /* Exceptions must be checked, according to v7 ref manual */
2891 CHECK_VFP_ENABLED; 2331 CHECK_VFP_ENABLED;
2892 2332
2893 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2333 vmsr_inst *inst_cream = (vmsr_inst *)inst_base->component;
2894 2334
2895 VMSR(cpu, inst_cream->reg, inst_cream->Rd); 2335 VMSR(cpu, inst_cream->reg, inst_cream->Rd);
2896 } 2336 }
2897 cpu->Reg[15] += GET_INST_SIZE(cpu); 2337 cpu->Reg[15] += GET_INST_SIZE(cpu);
2898 INC_PC(sizeof(vfpinstr_inst)); 2338 INC_PC(sizeof(vmsr_inst));
2899 FETCH_INST; 2339 FETCH_INST;
2900 GOTO_NEXT_INST; 2340 GOTO_NEXT_INST;
2901} 2341}
2902#endif 2342#endif
2903#ifdef VFP_MCR_TRANS 2343
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 2344#ifdef VFP_DYNCOM_TABLE
2926DYNCOM_FILL_ACTION(vfpinstr), 2345DYNCOM_FILL_ACTION(vmsr),
2927#endif 2346#endif
2928#ifdef VFP_DYNCOM_TAG 2347#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) 2348int DYNCOM_TAG(vmsr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2930{ 2349{
2931 int instr_size = INSTR_SIZE; 2350 int instr_size = INSTR_SIZE;
2932 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2351 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -2936,7 +2355,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2936} 2355}
2937#endif 2356#endif
2938#ifdef VFP_DYNCOM_TRANS 2357#ifdef VFP_DYNCOM_TRANS
2939int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2358int 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__); 2359 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2941 //arch_arm_undef(cpu, bb, instr); 2360 //arch_arm_undef(cpu, bb, instr);
2942 DBG("VMSR :"); 2361 DBG("VMSR :");
@@ -2969,44 +2388,26 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
2969 return No_exp; 2388 return No_exp;
2970} 2389}
2971#endif 2390#endif
2972#undef vfpinstr
2973#undef vfpinstr_inst
2974#undef VFPLABEL_INST
2975 2391
2976/* ----------------------------------------------------------------------- */ 2392/* ----------------------------------------------------------------------- */
2977/* VMOVBRC register to scalar */ 2393/* VMOVBRC register to scalar */
2978/* cond 1110 0XX0 Vd-- Rt-- 1011 DXX1 0000 */ 2394/* cond 1110 0XX0 Vd-- Rt-- 1011 DXX1 0000 */
2979/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */ 2395/* 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 2396#ifdef VFP_INTERPRETER_STRUCT
2996typedef struct _vmovbrc_inst { 2397typedef struct _vmovbrc_inst {
2997 unsigned int esize; 2398 unsigned int esize;
2998 unsigned int index; 2399 unsigned int index;
2999 unsigned int d; 2400 unsigned int d;
3000 unsigned int t; 2401 unsigned int t;
3001} vfpinstr_inst; 2402} vmovbrc_inst;
3002#endif 2403#endif
3003#ifdef VFP_INTERPRETER_TRANS 2404#ifdef VFP_INTERPRETER_TRANS
3004ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2405ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index)
3005{ 2406{
3006 VFP_DEBUG_TRANSLATE; 2407 VFP_DEBUG_TRANSLATE;
3007 2408
3008 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2409 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrc_inst));
3009 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2410 vmovbrc_inst *inst_cream = (vmovbrc_inst *)inst_base->component;
3010 2411
3011 inst_base->cond = BITS(inst, 28, 31); 2412 inst_base->cond = BITS(inst, 28, 31);
3012 inst_base->idx = index; 2413 inst_base->idx = index;
@@ -3023,34 +2424,28 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3023} 2424}
3024#endif 2425#endif
3025#ifdef VFP_INTERPRETER_IMPL 2426#ifdef VFP_INTERPRETER_IMPL
3026VFPLABEL_INST: 2427VMOVBRC_INST:
3027{ 2428{
3028 INC_ICOUNTER; 2429 INC_ICOUNTER;
3029 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2430 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3030 CHECK_VFP_ENABLED; 2431 CHECK_VFP_ENABLED;
3031 2432
3032 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2433 vmovbrc_inst *inst_cream = (vmovbrc_inst *)inst_base->component;
3033 2434
3034 VFP_DEBUG_UNIMPLEMENTED(VMOVBRC); 2435 VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
3035 } 2436 }
3036 cpu->Reg[15] += GET_INST_SIZE(cpu); 2437 cpu->Reg[15] += GET_INST_SIZE(cpu);
3037 INC_PC(sizeof(vfpinstr_inst)); 2438 INC_PC(sizeof(vmovbrc_inst));
3038 FETCH_INST; 2439 FETCH_INST;
3039 GOTO_NEXT_INST; 2440 GOTO_NEXT_INST;
3040} 2441}
3041#endif 2442#endif
3042#ifdef VFP_MCR_TRANS 2443
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 2444#ifdef VFP_DYNCOM_TABLE
3050DYNCOM_FILL_ACTION(vfpinstr), 2445DYNCOM_FILL_ACTION(vmovbrc),
3051#endif 2446#endif
3052#ifdef VFP_DYNCOM_TAG 2447#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) 2448int DYNCOM_TAG(vmovbrc)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3054{ 2449{
3055 int instr_size = INSTR_SIZE; 2450 int instr_size = INSTR_SIZE;
3056 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2451 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -3059,48 +2454,30 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3059} 2454}
3060#endif 2455#endif
3061#ifdef VFP_DYNCOM_TRANS 2456#ifdef VFP_DYNCOM_TRANS
3062int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2457int 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__); 2458 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3064 arch_arm_undef(cpu, bb, instr); 2459 arch_arm_undef(cpu, bb, instr);
3065 return No_exp; 2460 return No_exp;
3066} 2461}
3067#endif 2462#endif
3068#undef vfpinstr
3069#undef vfpinstr_inst
3070#undef VFPLABEL_INST
3071 2463
3072/* ----------------------------------------------------------------------- */ 2464/* ----------------------------------------------------------------------- */
3073/* VMRS */ 2465/* VMRS */
3074/* cond 1110 1111 CRn- Rt-- 1010 0001 0000 */ 2466/* cond 1110 1111 CRn- Rt-- 1010 0001 0000 */
3075/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */ 2467/* 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 2468#ifdef VFP_INTERPRETER_STRUCT
3092typedef struct _vmrs_inst { 2469typedef struct _vmrs_inst {
3093 unsigned int reg; 2470 unsigned int reg;
3094 unsigned int Rt; 2471 unsigned int Rt;
3095} vfpinstr_inst; 2472} vmrs_inst;
3096#endif 2473#endif
3097#ifdef VFP_INTERPRETER_TRANS 2474#ifdef VFP_INTERPRETER_TRANS
3098ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2475ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index)
3099{ 2476{
3100 VFP_DEBUG_TRANSLATE; 2477 VFP_DEBUG_TRANSLATE;
3101 2478
3102 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2479 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmrs_inst));
3103 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2480 vmrs_inst *inst_cream = (vmrs_inst *)inst_base->component;
3104 2481
3105 inst_base->cond = BITS(inst, 28, 31); 2482 inst_base->cond = BITS(inst, 28, 31);
3106 inst_base->idx = index; 2483 inst_base->idx = index;
@@ -3109,12 +2486,12 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3109 2486
3110 inst_cream->reg = BITS(inst, 16, 19); 2487 inst_cream->reg = BITS(inst, 16, 19);
3111 inst_cream->Rt = BITS(inst, 12, 15); 2488 inst_cream->Rt = BITS(inst, 12, 15);
3112 2489
3113 return inst_base; 2490 return inst_base;
3114} 2491}
3115#endif 2492#endif
3116#ifdef VFP_INTERPRETER_IMPL 2493#ifdef VFP_INTERPRETER_IMPL
3117VFPLABEL_INST: 2494VMRS_INST:
3118{ 2495{
3119 INC_ICOUNTER; 2496 INC_ICOUNTER;
3120 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2497 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -3123,7 +2500,7 @@ VFPLABEL_INST:
3123 /* Exceptions must be checked, according to v7 ref manual */ 2500 /* Exceptions must be checked, according to v7 ref manual */
3124 CHECK_VFP_ENABLED; 2501 CHECK_VFP_ENABLED;
3125 2502
3126 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2503 vmrs_inst *inst_cream = (vmrs_inst *)inst_base->component;
3127 2504
3128 DBG("VMRS :"); 2505 DBG("VMRS :");
3129 2506
@@ -3170,67 +2547,17 @@ VFPLABEL_INST:
3170 } 2547 }
3171 } 2548 }
3172 cpu->Reg[15] += GET_INST_SIZE(cpu); 2549 cpu->Reg[15] += GET_INST_SIZE(cpu);
3173 INC_PC(sizeof(vfpinstr_inst)); 2550 INC_PC(sizeof(vmrs_inst));
3174 FETCH_INST; 2551 FETCH_INST;
3175 GOTO_NEXT_INST; 2552 GOTO_NEXT_INST;
3176} 2553}
3177#endif 2554#endif
3178#ifdef VFP_MRC_TRANS 2555
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 2556#ifdef VFP_DYNCOM_TABLE
3230DYNCOM_FILL_ACTION(vfpinstr), 2557DYNCOM_FILL_ACTION(vmrs),
3231#endif 2558#endif
3232#ifdef VFP_DYNCOM_TAG 2559#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) 2560int DYNCOM_TAG(vmrs)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3234{ 2561{
3235 int instr_size = INSTR_SIZE; 2562 int instr_size = INSTR_SIZE;
3236 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2563 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -3241,7 +2568,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3241} 2568}
3242#endif 2569#endif
3243#ifdef VFP_DYNCOM_TRANS 2570#ifdef VFP_DYNCOM_TRANS
3244int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2571int 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__); 2572 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3246 //arch_arm_undef(cpu, bb, instr); 2573 //arch_arm_undef(cpu, bb, instr);
3247 2574
@@ -3292,44 +2619,26 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
3292 return No_exp; 2619 return No_exp;
3293} 2620}
3294#endif 2621#endif
3295#undef vfpinstr
3296#undef vfpinstr_inst
3297#undef VFPLABEL_INST
3298 2622
3299/* ----------------------------------------------------------------------- */ 2623/* ----------------------------------------------------------------------- */
3300/* VMOVBCR scalar to register */ 2624/* VMOVBCR scalar to register */
3301/* cond 1110 XXX1 Vd-- Rt-- 1011 NXX1 0000 */ 2625/* cond 1110 XXX1 Vd-- Rt-- 1011 NXX1 0000 */
3302/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MCR */ 2626/* 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 2627#ifdef VFP_INTERPRETER_STRUCT
3319typedef struct _vmovbcr_inst { 2628typedef struct _vmovbcr_inst {
3320 unsigned int esize; 2629 unsigned int esize;
3321 unsigned int index; 2630 unsigned int index;
3322 unsigned int d; 2631 unsigned int d;
3323 unsigned int t; 2632 unsigned int t;
3324} vfpinstr_inst; 2633} vmovbcr_inst;
3325#endif 2634#endif
3326#ifdef VFP_INTERPRETER_TRANS 2635#ifdef VFP_INTERPRETER_TRANS
3327ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2636ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index)
3328{ 2637{
3329 VFP_DEBUG_TRANSLATE; 2638 VFP_DEBUG_TRANSLATE;
3330 2639
3331 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2640 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbcr_inst));
3332 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2641 vmovbcr_inst *inst_cream = (vmovbcr_inst *)inst_base->component;
3333 2642
3334 inst_base->cond = BITS(inst, 28, 31); 2643 inst_base->cond = BITS(inst, 28, 31);
3335 inst_base->idx = index; 2644 inst_base->idx = index;
@@ -3346,34 +2655,28 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3346} 2655}
3347#endif 2656#endif
3348#ifdef VFP_INTERPRETER_IMPL 2657#ifdef VFP_INTERPRETER_IMPL
3349VFPLABEL_INST: 2658VMOVBCR_INST:
3350{ 2659{
3351 INC_ICOUNTER; 2660 INC_ICOUNTER;
3352 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2661 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3353 CHECK_VFP_ENABLED; 2662 CHECK_VFP_ENABLED;
3354 2663
3355 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2664 vmovbcr_inst *inst_cream = (vmovbcr_inst *)inst_base->component;
3356 2665
3357 VFP_DEBUG_UNIMPLEMENTED(VMOVBCR); 2666 VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
3358 } 2667 }
3359 cpu->Reg[15] += GET_INST_SIZE(cpu); 2668 cpu->Reg[15] += GET_INST_SIZE(cpu);
3360 INC_PC(sizeof(vfpinstr_inst)); 2669 INC_PC(sizeof(vmovbcr_inst));
3361 FETCH_INST; 2670 FETCH_INST;
3362 GOTO_NEXT_INST; 2671 GOTO_NEXT_INST;
3363} 2672}
3364#endif 2673#endif
3365#ifdef VFP_MCR_TRANS 2674
3366if (CoProc == 11 && CRm == 0)
3367{
3368 VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
3369 return ARMul_DONE;
3370}
3371#endif
3372#ifdef VFP_DYNCOM_TABLE 2675#ifdef VFP_DYNCOM_TABLE
3373DYNCOM_FILL_ACTION(vfpinstr), 2676DYNCOM_FILL_ACTION(vmovbcr),
3374#endif 2677#endif
3375#ifdef VFP_DYNCOM_TAG 2678#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) 2679int DYNCOM_TAG(vmovbcr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3377{ 2680{
3378 int instr_size = INSTR_SIZE; 2681 int instr_size = INSTR_SIZE;
3379 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2682 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -3382,15 +2685,12 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3382} 2685}
3383#endif 2686#endif
3384#ifdef VFP_DYNCOM_TRANS 2687#ifdef VFP_DYNCOM_TRANS
3385int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2688int 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__); 2689 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3387 arch_arm_undef(cpu, bb, instr); 2690 arch_arm_undef(cpu, bb, instr);
3388 return No_exp; 2691 return No_exp;
3389} 2692}
3390#endif 2693#endif
3391#undef vfpinstr
3392#undef vfpinstr_inst
3393#undef VFPLABEL_INST
3394 2694
3395/* ----------------------------------------------------------------------- */ 2695/* ----------------------------------------------------------------------- */
3396/* MRRC / MCRR instructions */ 2696/* MRRC / MCRR instructions */
@@ -3401,36 +2701,21 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
3401/* VMOVBRRSS between 2 registers to 2 singles */ 2701/* VMOVBRRSS between 2 registers to 2 singles */
3402/* cond 1100 010X Rt2- Rt-- 1010 00X1 Vm-- */ 2702/* cond 1100 010X Rt2- Rt-- 1010 00X1 Vm-- */
3403/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */ 2703/* 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 2704#ifdef VFP_INTERPRETER_STRUCT
3420typedef struct _vmovbrrss_inst { 2705typedef struct _vmovbrrss_inst {
3421 unsigned int to_arm; 2706 unsigned int to_arm;
3422 unsigned int t; 2707 unsigned int t;
3423 unsigned int t2; 2708 unsigned int t2;
3424 unsigned int m; 2709 unsigned int m;
3425} vfpinstr_inst; 2710} vmovbrrss_inst;
3426#endif 2711#endif
3427#ifdef VFP_INTERPRETER_TRANS 2712#ifdef VFP_INTERPRETER_TRANS
3428ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2713ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int index)
3429{ 2714{
3430 VFP_DEBUG_TRANSLATE; 2715 VFP_DEBUG_TRANSLATE;
3431 2716
3432 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2717 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrss_inst));
3433 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2718 vmovbrrss_inst *inst_cream = (vmovbrrss_inst *)inst_base->component;
3434 2719
3435 inst_base->cond = BITS(inst, 28, 31); 2720 inst_base->cond = BITS(inst, 28, 31);
3436 inst_base->idx = index; 2721 inst_base->idx = index;
@@ -3446,41 +2731,27 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3446} 2731}
3447#endif 2732#endif
3448#ifdef VFP_INTERPRETER_IMPL 2733#ifdef VFP_INTERPRETER_IMPL
3449VFPLABEL_INST: 2734VMOVBRRSS_INST:
3450{ 2735{
3451 INC_ICOUNTER; 2736 INC_ICOUNTER;
3452 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2737 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3453 CHECK_VFP_ENABLED; 2738 CHECK_VFP_ENABLED;
3454 2739
3455 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2740 vmovbrrss_inst *inst_cream = (vmovbrrss_inst *)inst_base->component;
3456 2741
3457 VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS); 2742 VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS);
3458 } 2743 }
3459 cpu->Reg[15] += GET_INST_SIZE(cpu); 2744 cpu->Reg[15] += GET_INST_SIZE(cpu);
3460 INC_PC(sizeof(vfpinstr_inst)); 2745 INC_PC(sizeof(vmovbrrss_inst));
3461 FETCH_INST; 2746 FETCH_INST;
3462 GOTO_NEXT_INST; 2747 GOTO_NEXT_INST;
3463} 2748}
3464#endif 2749#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 2750#ifdef VFP_DYNCOM_TABLE
3480DYNCOM_FILL_ACTION(vfpinstr), 2751DYNCOM_FILL_ACTION(vmovbrrss),
3481#endif 2752#endif
3482#ifdef VFP_DYNCOM_TAG 2753#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) 2754int DYNCOM_TAG(vmovbrrss)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3484{ 2755{
3485 int instr_size = INSTR_SIZE; 2756 int instr_size = INSTR_SIZE;
3486 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2757 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -3489,50 +2760,32 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3489} 2760}
3490#endif 2761#endif
3491#ifdef VFP_DYNCOM_TRANS 2762#ifdef VFP_DYNCOM_TRANS
3492int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2763int 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__); 2764 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3494 arch_arm_undef(cpu, bb, instr); 2765 arch_arm_undef(cpu, bb, instr);
3495 return No_exp; 2766 return No_exp;
3496} 2767}
3497#endif 2768#endif
3498#undef vfpinstr
3499#undef vfpinstr_inst
3500#undef VFPLABEL_INST
3501 2769
3502/* ----------------------------------------------------------------------- */ 2770/* ----------------------------------------------------------------------- */
3503/* VMOVBRRD between 2 registers and 1 double */ 2771/* VMOVBRRD between 2 registers and 1 double */
3504/* cond 1100 010X Rt2- Rt-- 1011 00X1 Vm-- */ 2772/* cond 1100 010X Rt2- Rt-- 1011 00X1 Vm-- */
3505/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */ 2773/* 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 2774#ifdef VFP_INTERPRETER_STRUCT
3522typedef struct _vmovbrrd_inst { 2775typedef struct _vmovbrrd_inst {
3523 unsigned int to_arm; 2776 unsigned int to_arm;
3524 unsigned int t; 2777 unsigned int t;
3525 unsigned int t2; 2778 unsigned int t2;
3526 unsigned int m; 2779 unsigned int m;
3527} vfpinstr_inst; 2780} vmovbrrd_inst;
3528#endif 2781#endif
3529#ifdef VFP_INTERPRETER_TRANS 2782#ifdef VFP_INTERPRETER_TRANS
3530ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2783ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index)
3531{ 2784{
3532 VFP_DEBUG_TRANSLATE; 2785 VFP_DEBUG_TRANSLATE;
3533 2786
3534 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2787 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrd_inst));
3535 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2788 vmovbrrd_inst *inst_cream = (vmovbrrd_inst *)inst_base->component;
3536 2789
3537 inst_base->cond = BITS(inst, 28, 31); 2790 inst_base->cond = BITS(inst, 28, 31);
3538 inst_base->idx = index; 2791 inst_base->idx = index;
@@ -3548,63 +2801,29 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3548} 2801}
3549#endif 2802#endif
3550#ifdef VFP_INTERPRETER_IMPL 2803#ifdef VFP_INTERPRETER_IMPL
3551VFPLABEL_INST: 2804VMOVBRRD_INST:
3552{ 2805{
3553 INC_ICOUNTER; 2806 INC_ICOUNTER;
3554 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2807 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3555 CHECK_VFP_ENABLED; 2808 CHECK_VFP_ENABLED;
3556 2809
3557 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2810 vmovbrrd_inst *inst_cream = (vmovbrrd_inst *)inst_base->component;
3558 2811
3559 VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, 2812 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])); 2813 &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2]));
3561 } 2814 }
3562 cpu->Reg[15] += GET_INST_SIZE(cpu); 2815 cpu->Reg[15] += GET_INST_SIZE(cpu);
3563 INC_PC(sizeof(vfpinstr_inst)); 2816 INC_PC(sizeof(vmovbrrd_inst));
3564 FETCH_INST; 2817 FETCH_INST;
3565 GOTO_NEXT_INST; 2818 GOTO_NEXT_INST;
3566} 2819}
3567#endif 2820#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 2821
3602#endif
3603#ifdef VFP_DYNCOM_TABLE 2822#ifdef VFP_DYNCOM_TABLE
3604DYNCOM_FILL_ACTION(vfpinstr), 2823DYNCOM_FILL_ACTION(vmovbrrd),
3605#endif 2824#endif
3606#ifdef VFP_DYNCOM_TAG 2825#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) 2826int DYNCOM_TAG(vmovbrrd)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3608{ 2827{
3609 int instr_size = INSTR_SIZE; 2828 int instr_size = INSTR_SIZE;
3610 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2829 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -3615,7 +2834,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3615} 2834}
3616#endif 2835#endif
3617#ifdef VFP_DYNCOM_TRANS 2836#ifdef VFP_DYNCOM_TRANS
3618int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2837int 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__); 2838 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3620 //arch_arm_undef(cpu, bb, instr); 2839 //arch_arm_undef(cpu, bb, instr);
3621 int to_arm = BIT(20) == 1; 2840 int to_arm = BIT(20) == 1;
@@ -3633,9 +2852,6 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
3633 return No_exp; 2852 return No_exp;
3634} 2853}
3635#endif 2854#endif
3636#undef vfpinstr
3637#undef vfpinstr_inst
3638#undef VFPLABEL_INST
3639 2855
3640/* ----------------------------------------------------------------------- */ 2856/* ----------------------------------------------------------------------- */
3641/* LDC/STC between 2 registers and 1 double */ 2857/* LDC/STC between 2 registers and 1 double */
@@ -3645,21 +2861,6 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
3645/* ----------------------------------------------------------------------- */ 2861/* ----------------------------------------------------------------------- */
3646/* VSTR */ 2862/* VSTR */
3647/* cond 1101 UD00 Rn-- Vd-- 101X imm8 imm8 */ 2863/* 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 2864#ifdef VFP_INTERPRETER_STRUCT
3664typedef struct _vstr_inst { 2865typedef struct _vstr_inst {
3665 unsigned int single; 2866 unsigned int single;
@@ -3667,15 +2868,15 @@ typedef struct _vstr_inst {
3667 unsigned int d; 2868 unsigned int d;
3668 unsigned int imm32; 2869 unsigned int imm32;
3669 unsigned int add; 2870 unsigned int add;
3670} vfpinstr_inst; 2871} vstr_inst;
3671#endif 2872#endif
3672#ifdef VFP_INTERPRETER_TRANS 2873#ifdef VFP_INTERPRETER_TRANS
3673ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2874ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index)
3674{ 2875{
3675 VFP_DEBUG_TRANSLATE; 2876 VFP_DEBUG_TRANSLATE;
3676 2877
3677 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2878 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vstr_inst));
3678 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2879 vstr_inst *inst_cream = (vstr_inst *)inst_base->component;
3679 2880
3680 inst_base->cond = BITS(inst, 28, 31); 2881 inst_base->cond = BITS(inst, 28, 31);
3681 inst_base->idx = index; 2882 inst_base->idx = index;
@@ -3692,13 +2893,13 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3692} 2893}
3693#endif 2894#endif
3694#ifdef VFP_INTERPRETER_IMPL 2895#ifdef VFP_INTERPRETER_IMPL
3695VFPLABEL_INST: 2896VSTR_INST:
3696{ 2897{
3697 INC_ICOUNTER; 2898 INC_ICOUNTER;
3698 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2899 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3699 CHECK_VFP_ENABLED; 2900 CHECK_VFP_ENABLED;
3700 2901
3701 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2902 vstr_inst *inst_cream = (vstr_inst *)inst_base->component;
3702 2903
3703 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]); 2904 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); 2905 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32);
@@ -3736,65 +2937,12 @@ VFPLABEL_INST:
3736 GOTO_NEXT_INST; 2937 GOTO_NEXT_INST;
3737} 2938}
3738#endif 2939#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 2940
3790 return -1;
3791}
3792#endif
3793#ifdef VFP_DYNCOM_TABLE 2941#ifdef VFP_DYNCOM_TABLE
3794DYNCOM_FILL_ACTION(vfpinstr), 2942DYNCOM_FILL_ACTION(vstr),
3795#endif 2943#endif
3796#ifdef VFP_DYNCOM_TAG 2944#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) 2945int DYNCOM_TAG(vstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3798{ 2946{
3799 int instr_size = INSTR_SIZE; 2947 int instr_size = INSTR_SIZE;
3800 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc); 2948 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
@@ -3807,7 +2955,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3807} 2955}
3808#endif 2956#endif
3809#ifdef VFP_DYNCOM_TRANS 2957#ifdef VFP_DYNCOM_TRANS
3810int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2958int DYNCOM_TRANS(vstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3811 int single = BIT(8) == 0; 2959 int single = BIT(8) == 0;
3812 int add = BIT(23); 2960 int add = BIT(23);
3813 int imm32 = BITS(0,7) << 2; 2961 int imm32 = BITS(0,7) << 2;
@@ -3853,43 +3001,25 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
3853 return No_exp; 3001 return No_exp;
3854} 3002}
3855#endif 3003#endif
3856#undef vfpinstr
3857#undef vfpinstr_inst
3858#undef VFPLABEL_INST
3859 3004
3860/* ----------------------------------------------------------------------- */ 3005/* ----------------------------------------------------------------------- */
3861/* VPUSH */ 3006/* VPUSH */
3862/* cond 1101 0D10 1101 Vd-- 101X imm8 imm8 */ 3007/* 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 3008#ifdef VFP_INTERPRETER_STRUCT
3879typedef struct _vpush_inst { 3009typedef struct _vpush_inst {
3880 unsigned int single; 3010 unsigned int single;
3881 unsigned int d; 3011 unsigned int d;
3882 unsigned int imm32; 3012 unsigned int imm32;
3883 unsigned int regs; 3013 unsigned int regs;
3884} vfpinstr_inst; 3014} vpush_inst;
3885#endif 3015#endif
3886#ifdef VFP_INTERPRETER_TRANS 3016#ifdef VFP_INTERPRETER_TRANS
3887ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 3017ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index)
3888{ 3018{
3889 VFP_DEBUG_TRANSLATE; 3019 VFP_DEBUG_TRANSLATE;
3890 3020
3891 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 3021 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vpush_inst));
3892 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3022 vpush_inst *inst_cream = (vpush_inst *)inst_base->component;
3893 3023
3894 inst_base->cond = BITS(inst, 28, 31); 3024 inst_base->cond = BITS(inst, 28, 31);
3895 inst_base->idx = index; 3025 inst_base->idx = index;
@@ -3905,7 +3035,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3905} 3035}
3906#endif 3036#endif
3907#ifdef VFP_INTERPRETER_IMPL 3037#ifdef VFP_INTERPRETER_IMPL
3908VFPLABEL_INST: 3038VPUSH_INST:
3909{ 3039{
3910 INC_ICOUNTER; 3040 INC_ICOUNTER;
3911 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3041 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -3913,7 +3043,7 @@ VFPLABEL_INST:
3913 3043
3914 int i; 3044 int i;
3915 3045
3916 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3046 vpush_inst *inst_cream = (vpush_inst *)inst_base->component;
3917 3047
3918 DBG("VPUSH :\n"); 3048 DBG("VPUSH :\n");
3919 3049
@@ -3958,66 +3088,11 @@ VFPLABEL_INST:
3958 GOTO_NEXT_INST; 3088 GOTO_NEXT_INST;
3959} 3089}
3960#endif 3090#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 3091#ifdef VFP_DYNCOM_TABLE
4017DYNCOM_FILL_ACTION(vfpinstr), 3092DYNCOM_FILL_ACTION(vpush),
4018#endif 3093#endif
4019#ifdef VFP_DYNCOM_TAG 3094#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) 3095int DYNCOM_TAG(vpush)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4021{ 3096{
4022 int instr_size = INSTR_SIZE; 3097 int instr_size = INSTR_SIZE;
4023 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc); 3098 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
@@ -4030,7 +3105,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
4030} 3105}
4031#endif 3106#endif
4032#ifdef VFP_DYNCOM_TRANS 3107#ifdef VFP_DYNCOM_TRANS
4033int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 3108int DYNCOM_TRANS(vpush)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4034 int single = BIT(8) == 0; 3109 int single = BIT(8) == 0;
4035 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4)); 3110 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4));
4036 int imm32 = BITS(0, 7)<<2; 3111 int imm32 = BITS(0, 7)<<2;
@@ -4087,28 +3162,10 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4087 return No_exp; 3162 return No_exp;
4088} 3163}
4089#endif 3164#endif
4090#undef vfpinstr
4091#undef vfpinstr_inst
4092#undef VFPLABEL_INST
4093 3165
4094/* ----------------------------------------------------------------------- */ 3166/* ----------------------------------------------------------------------- */
4095/* VSTM */ 3167/* VSTM */
4096/* cond 110P UDW0 Rn-- Vd-- 101X imm8 imm8 */ 3168/* 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 3169#ifdef VFP_INTERPRETER_STRUCT
4113typedef struct _vstm_inst { 3170typedef struct _vstm_inst {
4114 unsigned int single; 3171 unsigned int single;
@@ -4118,15 +3175,15 @@ typedef struct _vstm_inst {
4118 unsigned int n; 3175 unsigned int n;
4119 unsigned int imm32; 3176 unsigned int imm32;
4120 unsigned int regs; 3177 unsigned int regs;
4121} vfpinstr_inst; 3178} vstm_inst;
4122#endif 3179#endif
4123#ifdef VFP_INTERPRETER_TRANS 3180#ifdef VFP_INTERPRETER_TRANS
4124ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 3181ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index)
4125{ 3182{
4126 VFP_DEBUG_TRANSLATE; 3183 VFP_DEBUG_TRANSLATE;
4127 3184
4128 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 3185 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vstm_inst));
4129 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3186 vstm_inst *inst_cream = (vstm_inst *)inst_base->component;
4130 3187
4131 inst_base->cond = BITS(inst, 28, 31); 3188 inst_base->cond = BITS(inst, 28, 31);
4132 inst_base->idx = index; 3189 inst_base->idx = index;
@@ -4145,7 +3202,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4145} 3202}
4146#endif 3203#endif
4147#ifdef VFP_INTERPRETER_IMPL 3204#ifdef VFP_INTERPRETER_IMPL
4148VFPLABEL_INST: /* encoding 1 */ 3205VSTM_INST: /* encoding 1 */
4149{ 3206{
4150 INC_ICOUNTER; 3207 INC_ICOUNTER;
4151 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3208 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -4153,7 +3210,7 @@ VFPLABEL_INST: /* encoding 1 */
4153 3210
4154 int i; 3211 int i;
4155 3212
4156 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3213 vstm_inst *inst_cream = (vstm_inst *)inst_base->component;
4157 3214
4158 addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32); 3215 addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32);
4159 DBG("VSTM : addr[%x]\n", addr); 3216 DBG("VSTM : addr[%x]\n", addr);
@@ -4203,69 +3260,12 @@ VFPLABEL_INST: /* encoding 1 */
4203 GOTO_NEXT_INST; 3260 GOTO_NEXT_INST;
4204} 3261}
4205#endif 3262#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 3263
4261 return -1;
4262}
4263#endif
4264#ifdef VFP_DYNCOM_TABLE 3264#ifdef VFP_DYNCOM_TABLE
4265DYNCOM_FILL_ACTION(vfpinstr), 3265DYNCOM_FILL_ACTION(vstm),
4266#endif 3266#endif
4267#ifdef VFP_DYNCOM_TAG 3267#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) 3268int DYNCOM_TAG(vstm)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4269{ 3269{
4270 int instr_size = INSTR_SIZE; 3270 int instr_size = INSTR_SIZE;
4271 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 3271 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -4280,7 +3280,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
4280} 3280}
4281#endif 3281#endif
4282#ifdef VFP_DYNCOM_TRANS 3282#ifdef VFP_DYNCOM_TRANS
4283int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 3283int DYNCOM_TRANS(vstm)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4284 //arch_arm_undef(cpu, bb, instr); 3284 //arch_arm_undef(cpu, bb, instr);
4285 int single = BIT(8) == 0; 3285 int single = BIT(8) == 0;
4286 int add = BIT(23); 3286 int add = BIT(23);
@@ -4356,43 +3356,25 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4356 return No_exp; 3356 return No_exp;
4357} 3357}
4358#endif 3358#endif
4359#undef vfpinstr
4360#undef vfpinstr_inst
4361#undef VFPLABEL_INST
4362 3359
4363/* ----------------------------------------------------------------------- */ 3360/* ----------------------------------------------------------------------- */
4364/* VPOP */ 3361/* VPOP */
4365/* cond 1100 1D11 1101 Vd-- 101X imm8 imm8 */ 3362/* 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 3363#ifdef VFP_INTERPRETER_STRUCT
4382typedef struct _vpop_inst { 3364typedef struct _vpop_inst {
4383 unsigned int single; 3365 unsigned int single;
4384 unsigned int d; 3366 unsigned int d;
4385 unsigned int imm32; 3367 unsigned int imm32;
4386 unsigned int regs; 3368 unsigned int regs;
4387} vfpinstr_inst; 3369} vpop_inst;
4388#endif 3370#endif
4389#ifdef VFP_INTERPRETER_TRANS 3371#ifdef VFP_INTERPRETER_TRANS
4390ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 3372ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index)
4391{ 3373{
4392 VFP_DEBUG_TRANSLATE; 3374 VFP_DEBUG_TRANSLATE;
4393 3375
4394 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 3376 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vpop_inst));
4395 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3377 vpop_inst *inst_cream = (vpop_inst *)inst_base->component;
4396 3378
4397 inst_base->cond = BITS(inst, 28, 31); 3379 inst_base->cond = BITS(inst, 28, 31);
4398 inst_base->idx = index; 3380 inst_base->idx = index;
@@ -4408,7 +3390,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4408} 3390}
4409#endif 3391#endif
4410#ifdef VFP_INTERPRETER_IMPL 3392#ifdef VFP_INTERPRETER_IMPL
4411VFPLABEL_INST: 3393VPOP_INST:
4412{ 3394{
4413 INC_ICOUNTER; 3395 INC_ICOUNTER;
4414 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3396 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -4417,7 +3399,7 @@ VFPLABEL_INST:
4417 int i; 3399 int i;
4418 unsigned int value1, value2; 3400 unsigned int value1, value2;
4419 3401
4420 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3402 vpop_inst *inst_cream = (vpop_inst *)inst_base->component;
4421 3403
4422 DBG("VPOP :\n"); 3404 DBG("VPOP :\n");
4423 3405
@@ -4468,70 +3450,12 @@ VFPLABEL_INST:
4468 GOTO_NEXT_INST; 3450 GOTO_NEXT_INST;
4469} 3451}
4470#endif 3452#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 3453
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 3454#ifdef VFP_DYNCOM_TABLE
4531DYNCOM_FILL_ACTION(vfpinstr), 3455DYNCOM_FILL_ACTION(vpop),
4532#endif 3456#endif
4533#ifdef VFP_DYNCOM_TAG 3457#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) 3458int DYNCOM_TAG(vpop)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4535{ 3459{
4536 int instr_size = INSTR_SIZE; 3460 int instr_size = INSTR_SIZE;
4537 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 3461 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -4547,7 +3471,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
4547} 3471}
4548#endif 3472#endif
4549#ifdef VFP_DYNCOM_TRANS 3473#ifdef VFP_DYNCOM_TRANS
4550int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 3474int DYNCOM_TRANS(vpop)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4551 DBG("\t\tin %s instruction .\n", __FUNCTION__); 3475 DBG("\t\tin %s instruction .\n", __FUNCTION__);
4552 //arch_arm_undef(cpu, bb, instr); 3476 //arch_arm_undef(cpu, bb, instr);
4553 int single = BIT(8) == 0; 3477 int single = BIT(8) == 0;
@@ -4611,28 +3535,10 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4611 return No_exp; 3535 return No_exp;
4612} 3536}
4613#endif 3537#endif
4614#undef vfpinstr
4615#undef vfpinstr_inst
4616#undef VFPLABEL_INST
4617 3538
4618/* ----------------------------------------------------------------------- */ 3539/* ----------------------------------------------------------------------- */
4619/* VLDR */ 3540/* VLDR */
4620/* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */ 3541/* 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 3542#ifdef VFP_INTERPRETER_STRUCT
4637typedef struct _vldr_inst { 3543typedef struct _vldr_inst {
4638 unsigned int single; 3544 unsigned int single;
@@ -4640,15 +3546,15 @@ typedef struct _vldr_inst {
4640 unsigned int d; 3546 unsigned int d;
4641 unsigned int imm32; 3547 unsigned int imm32;
4642 unsigned int add; 3548 unsigned int add;
4643} vfpinstr_inst; 3549} vldr_inst;
4644#endif 3550#endif
4645#ifdef VFP_INTERPRETER_TRANS 3551#ifdef VFP_INTERPRETER_TRANS
4646ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 3552ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index)
4647{ 3553{
4648 VFP_DEBUG_TRANSLATE; 3554 VFP_DEBUG_TRANSLATE;
4649 3555
4650 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 3556 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vldr_inst));
4651 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3557 vldr_inst *inst_cream = (vldr_inst *)inst_base->component;
4652 3558
4653 inst_base->cond = BITS(inst, 28, 31); 3559 inst_base->cond = BITS(inst, 28, 31);
4654 inst_base->idx = index; 3560 inst_base->idx = index;
@@ -4665,13 +3571,13 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4665} 3571}
4666#endif 3572#endif
4667#ifdef VFP_INTERPRETER_IMPL 3573#ifdef VFP_INTERPRETER_IMPL
4668VFPLABEL_INST: 3574VLDR_INST:
4669{ 3575{
4670 INC_ICOUNTER; 3576 INC_ICOUNTER;
4671 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3577 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4672 CHECK_VFP_ENABLED; 3578 CHECK_VFP_ENABLED;
4673 3579
4674 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3580 vldr_inst *inst_cream = (vldr_inst *)inst_base->component;
4675 3581
4676 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]); 3582 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); 3583 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32);
@@ -4710,69 +3616,12 @@ VFPLABEL_INST:
4710 GOTO_NEXT_INST; 3616 GOTO_NEXT_INST;
4711} 3617}
4712#endif 3618#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 3619
4768 return -1;
4769}
4770#endif
4771#ifdef VFP_DYNCOM_TABLE 3620#ifdef VFP_DYNCOM_TABLE
4772DYNCOM_FILL_ACTION(vfpinstr), 3621DYNCOM_FILL_ACTION(vldr),
4773#endif 3622#endif
4774#ifdef VFP_DYNCOM_TAG 3623#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) 3624int DYNCOM_TAG(vldr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4776{ 3625{
4777 int instr_size = INSTR_SIZE; 3626 int instr_size = INSTR_SIZE;
4778 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 3627 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -4788,7 +3637,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
4788} 3637}
4789#endif 3638#endif
4790#ifdef VFP_DYNCOM_TRANS 3639#ifdef VFP_DYNCOM_TRANS
4791int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 3640int DYNCOM_TRANS(vldr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4792 int single = BIT(8) == 0; 3641 int single = BIT(8) == 0;
4793 int add = BIT(23); 3642 int add = BIT(23);
4794 int wback = BIT(21); 3643 int wback = BIT(21);
@@ -4846,28 +3695,10 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4846 return No_exp; 3695 return No_exp;
4847} 3696}
4848#endif 3697#endif
4849#undef vfpinstr
4850#undef vfpinstr_inst
4851#undef VFPLABEL_INST
4852 3698
4853/* ----------------------------------------------------------------------- */ 3699/* ----------------------------------------------------------------------- */
4854/* VLDM */ 3700/* VLDM */
4855/* cond 110P UDW1 Rn-- Vd-- 101X imm8 imm8 */ 3701/* 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 3702#ifdef VFP_INTERPRETER_STRUCT
4872typedef struct _vldm_inst { 3703typedef struct _vldm_inst {
4873 unsigned int single; 3704 unsigned int single;
@@ -4877,15 +3708,15 @@ typedef struct _vldm_inst {
4877 unsigned int n; 3708 unsigned int n;
4878 unsigned int imm32; 3709 unsigned int imm32;
4879 unsigned int regs; 3710 unsigned int regs;
4880} vfpinstr_inst; 3711} vldm_inst;
4881#endif 3712#endif
4882#ifdef VFP_INTERPRETER_TRANS 3713#ifdef VFP_INTERPRETER_TRANS
4883ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 3714ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index)
4884{ 3715{
4885 VFP_DEBUG_TRANSLATE; 3716 VFP_DEBUG_TRANSLATE;
4886 3717
4887 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 3718 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vldm_inst));
4888 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3719 vldm_inst *inst_cream = (vldm_inst *)inst_base->component;
4889 3720
4890 inst_base->cond = BITS(inst, 28, 31); 3721 inst_base->cond = BITS(inst, 28, 31);
4891 inst_base->idx = index; 3722 inst_base->idx = index;
@@ -4904,7 +3735,7 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4904} 3735}
4905#endif 3736#endif
4906#ifdef VFP_INTERPRETER_IMPL 3737#ifdef VFP_INTERPRETER_IMPL
4907VFPLABEL_INST: 3738VLDM_INST:
4908{ 3739{
4909 INC_ICOUNTER; 3740 INC_ICOUNTER;
4910 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3741 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
@@ -4912,7 +3743,7 @@ VFPLABEL_INST:
4912 3743
4913 int i; 3744 int i;
4914 3745
4915 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3746 vldm_inst *inst_cream = (vldm_inst *)inst_base->component;
4916 3747
4917 addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32); 3748 addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32);
4918 DBG("VLDM : addr[%x]\n", addr); 3749 DBG("VLDM : addr[%x]\n", addr);
@@ -4952,74 +3783,17 @@ VFPLABEL_INST:
4952 3783
4953 } 3784 }
4954 cpu->Reg[15] += GET_INST_SIZE(cpu); 3785 cpu->Reg[15] += GET_INST_SIZE(cpu);
4955 INC_PC(sizeof(vfpinstr_inst)); 3786 INC_PC(sizeof(vldm_inst));
4956 FETCH_INST; 3787 FETCH_INST;
4957 GOTO_NEXT_INST; 3788 GOTO_NEXT_INST;
4958} 3789}
4959#endif 3790#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 3791
5015 return -1;
5016}
5017#endif
5018#ifdef VFP_DYNCOM_TABLE 3792#ifdef VFP_DYNCOM_TABLE
5019DYNCOM_FILL_ACTION(vfpinstr), 3793DYNCOM_FILL_ACTION(vldm),
5020#endif 3794#endif
5021#ifdef VFP_DYNCOM_TAG 3795#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) 3796int DYNCOM_TAG(vldm)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
5023{ 3797{
5024 int instr_size = INSTR_SIZE; 3798 int instr_size = INSTR_SIZE;
5025 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 3799 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -5034,7 +3808,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
5034} 3808}
5035#endif 3809#endif
5036#ifdef VFP_DYNCOM_TRANS 3810#ifdef VFP_DYNCOM_TRANS
5037int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 3811int DYNCOM_TRANS(vldm)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
5038 int single = BIT(8) == 0; 3812 int single = BIT(8) == 0;
5039 int add = BIT(23); 3813 int add = BIT(23);
5040 int wback = BIT(21); 3814 int wback = BIT(21);
@@ -5110,14 +3884,3 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
5110 return No_exp; 3884 return No_exp;
5111} 3885}
5112#endif 3886#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/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h
index e2979be17..e153917ea 100644
--- a/src/core/file_sys/archive_backend.h
+++ b/src/core/file_sys/archive_backend.h
@@ -40,40 +40,37 @@ union Mode {
40class Path { 40class Path {
41public: 41public:
42 42
43 Path(): 43 Path() : type(Invalid) {
44 type(Invalid)
45 {
46 } 44 }
47 45
48 Path(const char* path): 46 Path(const char* path) : type(Char), string(path) {
49 type(Char), string(path)
50 {
51 } 47 }
52 48
53 Path(LowPathType type, u32 size, u32 pointer): 49 Path(LowPathType type, u32 size, u32 pointer) : type(type) {
54 type(type)
55 {
56 switch (type) { 50 switch (type) {
57 case Binary: 51 case Binary:
58 { 52 {
59 u8* data = Memory::GetPointer(pointer); 53 u8* data = Memory::GetPointer(pointer);
60 binary = std::vector<u8>(data, data + size); 54 binary = std::vector<u8>(data, data + size);
61 break; 55 break;
62 } 56 }
63 case Char: 57
64 { 58 case Char:
65 const char* data = reinterpret_cast<const char*>(Memory::GetPointer(pointer)); 59 {
66 string = std::string(data, size - 1); // Data is always null-terminated. 60 const char* data = reinterpret_cast<const char*>(Memory::GetPointer(pointer));
67 break; 61 string = std::string(data, size - 1); // Data is always null-terminated.
68 } 62 break;
69 case Wchar: 63 }
70 { 64
71 const char16_t* data = reinterpret_cast<const char16_t*>(Memory::GetPointer(pointer)); 65 case Wchar:
72 u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated. 66 {
73 break; 67 const char16_t* data = reinterpret_cast<const char16_t*>(Memory::GetPointer(pointer));
74 } 68 u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated.
75 default: 69 break;
76 break; 70 }
71
72 default:
73 break;
77 } 74 }
78 } 75 }
79 76
@@ -104,66 +101,64 @@ public:
104 return "[Char: " + AsString() + ']'; 101 return "[Char: " + AsString() + ']';
105 case Wchar: 102 case Wchar:
106 return "[Wchar: " + AsString() + ']'; 103 return "[Wchar: " + AsString() + ']';
107 default:
108 // TODO(yuriks): Add assert
109 LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!");
110 return {};
111 } 104 }
112 } 105 }
113 106
114 const std::string AsString() const { 107 const std::string AsString() const {
115 switch (GetType()) { 108 switch (GetType()) {
116 case Char: 109 case Char:
117 return string; 110 return string;
118 case Wchar: 111 case Wchar:
119 return Common::UTF16ToUTF8(u16str); 112 return Common::UTF16ToUTF8(u16str);
120 case Empty: 113 case Empty:
121 return {}; 114 return {};
122 default: 115 case Invalid:
123 // TODO(yuriks): Add assert 116 case Binary:
124 LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); 117 // TODO(yuriks): Add assert
125 return {}; 118 LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!");
119 return {};
126 } 120 }
127 } 121 }
128 122
129 const std::u16string AsU16Str() const { 123 const std::u16string AsU16Str() const {
130 switch (GetType()) { 124 switch (GetType()) {
131 case Char: 125 case Char:
132 return Common::UTF8ToUTF16(string); 126 return Common::UTF8ToUTF16(string);
133 case Wchar: 127 case Wchar:
134 return u16str; 128 return u16str;
135 case Empty: 129 case Empty:
136 return {}; 130 return {};
137 default: 131 case Invalid:
138 // TODO(yuriks): Add assert 132 case Binary:
139 LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!"); 133 // TODO(yuriks): Add assert
140 return {}; 134 LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!");
135 return {};
141 } 136 }
142 } 137 }
143 138
144 const std::vector<u8> AsBinary() const { 139 const std::vector<u8> AsBinary() const {
145 switch (GetType()) { 140 switch (GetType()) {
146 case Binary: 141 case Binary:
147 return binary; 142 return binary;
148 case Char: 143 case Char:
149 return std::vector<u8>(string.begin(), string.end()); 144 return std::vector<u8>(string.begin(), string.end());
150 case Wchar: 145 case Wchar:
151 { 146 {
152 // use two u8 for each character of u16str 147 // use two u8 for each character of u16str
153 std::vector<u8> to_return(u16str.size() * 2); 148 std::vector<u8> to_return(u16str.size() * 2);
154 for (size_t i = 0; i < u16str.size(); ++i) { 149 for (size_t i = 0; i < u16str.size(); ++i) {
155 u16 tmp_char = u16str.at(i); 150 u16 tmp_char = u16str.at(i);
156 to_return[i*2] = (tmp_char & 0xFF00) >> 8; 151 to_return[i*2] = (tmp_char & 0xFF00) >> 8;
157 to_return[i*2 + 1] = (tmp_char & 0x00FF); 152 to_return[i*2 + 1] = (tmp_char & 0x00FF);
158 }
159 return to_return;
160 } 153 }
161 case Empty: 154 return to_return;
162 return {}; 155 }
163 default: 156 case Empty:
164 // TODO(yuriks): Add assert 157 return {};
165 LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); 158 case Invalid:
166 return {}; 159 // TODO(yuriks): Add assert
160 LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!");
161 return {};
167 } 162 }
168 } 163 }
169 164
@@ -176,7 +171,8 @@ private:
176 171
177class ArchiveBackend : NonCopyable { 172class ArchiveBackend : NonCopyable {
178public: 173public:
179 virtual ~ArchiveBackend() { } 174 virtual ~ArchiveBackend() {
175 }
180 176
181 /** 177 /**
182 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) 178 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.)
@@ -196,7 +192,7 @@ public:
196 * @param path Path relative to the archive 192 * @param path Path relative to the archive
197 * @return Whether the file could be deleted 193 * @return Whether the file could be deleted
198 */ 194 */
199 virtual bool DeleteFile(const FileSys::Path& path) const = 0; 195 virtual bool DeleteFile(const Path& path) const = 0;
200 196
201 /** 197 /**
202 * Rename a File specified by its path 198 * Rename a File specified by its path
@@ -204,14 +200,14 @@ public:
204 * @param dest_path Destination path relative to the archive 200 * @param dest_path Destination path relative to the archive
205 * @return Whether rename succeeded 201 * @return Whether rename succeeded
206 */ 202 */
207 virtual bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const = 0; 203 virtual bool RenameFile(const Path& src_path, const Path& dest_path) const = 0;
208 204
209 /** 205 /**
210 * Delete a directory specified by its path 206 * Delete a directory specified by its path
211 * @param path Path relative to the archive 207 * @param path Path relative to the archive
212 * @return Whether the directory could be deleted 208 * @return Whether the directory could be deleted
213 */ 209 */
214 virtual bool DeleteDirectory(const FileSys::Path& path) const = 0; 210 virtual bool DeleteDirectory(const Path& path) const = 0;
215 211
216 /** 212 /**
217 * Create a file specified by its path 213 * Create a file specified by its path
@@ -234,7 +230,7 @@ public:
234 * @param dest_path Destination path relative to the archive 230 * @param dest_path Destination path relative to the archive
235 * @return Whether rename succeeded 231 * @return Whether rename succeeded
236 */ 232 */
237 virtual bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const = 0; 233 virtual bool RenameDirectory(const Path& src_path, const Path& dest_path) const = 0;
238 234
239 /** 235 /**
240 * Open a directory specified by its path 236 * Open a directory specified by its path
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp
index ced0794ef..fdaf73179 100644
--- a/src/core/file_sys/archive_romfs.cpp
+++ b/src/core/file_sys/archive_romfs.cpp
@@ -23,37 +23,21 @@ Archive_RomFS::Archive_RomFS(const Loader::AppLoader& app_loader) {
23 } 23 }
24} 24}
25 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<FileBackend> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const { 26std::unique_ptr<FileBackend> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const {
33 return Common::make_unique<File_RomFS>(this); 27 return Common::make_unique<File_RomFS>(this);
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}
@@ -64,26 +48,16 @@ ResultCode Archive_RomFS::CreateFile(const Path& path, u32 size) const {
64 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent); 48 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent);
65} 49}
66 50
67/**
68 * Create a directory specified by its path
69 * @param path Path relative to the archive
70 * @return Whether the directory could be created
71 */
72bool Archive_RomFS::CreateDirectory(const Path& path) const { 51bool Archive_RomFS::CreateDirectory(const Path& path) const {
73 LOG_WARNING(Service_FS, "Attempted to create a directory in ROMFS."); 52 LOG_WARNING(Service_FS, "Attempted to create a directory in ROMFS.");
74 return false; 53 return false;
75} 54}
76 55
77bool 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 {
78 LOG_WARNING(Service_FS, "Attempted to rename a file within ROMFS."); 57 LOG_WARNING(Service_FS, "Attempted to rename a file within ROMFS.");
79 return false; 58 return false;
80} 59}
81 60
82/**
83 * Open a directory specified by its path
84 * @param path Path relative to the archive
85 * @return Opened directory, or nullptr
86 */
87std::unique_ptr<DirectoryBackend> Archive_RomFS::OpenDirectory(const Path& path) const { 61std::unique_ptr<DirectoryBackend> Archive_RomFS::OpenDirectory(const Path& path) const {
88 return Common::make_unique<Directory_RomFS>(); 62 return Common::make_unique<Directory_RomFS>();
89} 63}
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h
index 2fafd0d2a..5e918f92d 100644
--- a/src/core/file_sys/archive_romfs.h
+++ b/src/core/file_sys/archive_romfs.h
@@ -36,7 +36,7 @@ public:
36 * @param path Path relative to the archive 36 * @param path Path relative to the archive
37 * @return Whether the file could be deleted 37 * @return Whether the file could be deleted
38 */ 38 */
39 bool DeleteFile(const FileSys::Path& path) const override; 39 bool DeleteFile(const Path& path) const override;
40 40
41 /** 41 /**
42 * Rename a File specified by its path 42 * Rename a File specified by its path
@@ -44,14 +44,14 @@ public:
44 * @param dest_path Destination path relative to the archive 44 * @param dest_path Destination path relative to the archive
45 * @return Whether rename succeeded 45 * @return Whether rename succeeded
46 */ 46 */
47 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;
48 48
49 /** 49 /**
50 * Delete a directory specified by its path 50 * Delete a directory specified by its path
51 * @param path Path relative to the archive 51 * @param path Path relative to the archive
52 * @return Whether the directory could be deleted 52 * @return Whether the directory could be deleted
53 */ 53 */
54 bool DeleteDirectory(const FileSys::Path& path) const override; 54 bool DeleteDirectory(const Path& path) const override;
55 55
56 /** 56 /**
57 * Create a file specified by its path 57 * Create a file specified by its path
@@ -74,7 +74,7 @@ public:
74 * @param dest_path Destination path relative to the archive 74 * @param dest_path Destination path relative to the archive
75 * @return Whether rename succeeded 75 * @return Whether rename succeeded
76 */ 76 */
77 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;
78 78
79 /** 79 /**
80 * Open a directory specified by its path 80 * Open a directory specified by its path
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp
index cb4a80f5b..97853567c 100644
--- a/src/core/file_sys/archive_savedata.cpp
+++ b/src/core/file_sys/archive_savedata.cpp
@@ -16,7 +16,7 @@
16 16
17namespace FileSys { 17namespace FileSys {
18 18
19Archive_SaveData::Archive_SaveData(const std::string& mount_point, u64 program_id) 19Archive_SaveData::Archive_SaveData(const std::string& mount_point, u64 program_id)
20 : DiskArchive(mount_point + Common::StringFromFormat("%016X", program_id) + DIR_SEP) { 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()); 21 LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str());
22} 22}
diff --git a/src/core/file_sys/archive_systemsavedata.h b/src/core/file_sys/archive_systemsavedata.h
index 443e27091..55d85193c 100644
--- a/src/core/file_sys/archive_systemsavedata.h
+++ b/src/core/file_sys/archive_systemsavedata.h
@@ -15,7 +15,7 @@
15namespace FileSys { 15namespace FileSys {
16 16
17/// File system interface to the SystemSaveData archive 17/// File system interface to the SystemSaveData archive
18/// TODO(Subv): This archive should point to a location in the NAND, 18/// TODO(Subv): This archive should point to a location in the NAND,
19/// specifically nand:/data/<ID0>/sysdata/<SaveID-Low>/<SaveID-High> 19/// specifically nand:/data/<ID0>/sysdata/<SaveID-Low>/<SaveID-High>
20class Archive_SystemSaveData final : public DiskArchive { 20class Archive_SystemSaveData final : public DiskArchive {
21public: 21public:
diff --git a/src/core/file_sys/directory_romfs.cpp b/src/core/file_sys/directory_romfs.cpp
index 0b95f9b65..e130aca17 100644
--- a/src/core/file_sys/directory_romfs.cpp
+++ b/src/core/file_sys/directory_romfs.cpp
@@ -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/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp
index 1689a1a91..0197f727d 100644
--- a/src/core/file_sys/disk_archive.cpp
+++ b/src/core/file_sys/disk_archive.cpp
@@ -23,15 +23,15 @@ std::unique_ptr<FileBackend> DiskArchive::OpenFile(const Path& path, const Mode
23 return std::unique_ptr<FileBackend>(file); 23 return std::unique_ptr<FileBackend>(file);
24} 24}
25 25
26bool DiskArchive::DeleteFile(const FileSys::Path& path) const { 26bool DiskArchive::DeleteFile(const Path& path) const {
27 return FileUtil::Delete(GetMountPoint() + path.AsString()); 27 return FileUtil::Delete(GetMountPoint() + path.AsString());
28} 28}
29 29
30bool DiskArchive::RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const { 30bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const {
31 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString()); 31 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
32} 32}
33 33
34bool DiskArchive::DeleteDirectory(const FileSys::Path& path) const { 34bool DiskArchive::DeleteDirectory(const Path& path) const {
35 return FileUtil::DeleteDir(GetMountPoint() + path.AsString()); 35 return FileUtil::DeleteDir(GetMountPoint() + path.AsString());
36} 36}
37 37
@@ -60,7 +60,7 @@ bool DiskArchive::CreateDirectory(const Path& path) const {
60 return FileUtil::CreateDir(GetMountPoint() + path.AsString()); 60 return FileUtil::CreateDir(GetMountPoint() + path.AsString());
61} 61}
62 62
63bool DiskArchive::RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const { 63bool DiskArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const {
64 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString()); 64 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
65} 65}
66 66
@@ -85,7 +85,7 @@ DiskFile::DiskFile(const DiskArchive* archive, const Path& path, const Mode mode
85 85
86bool DiskFile::Open() { 86bool DiskFile::Open() {
87 if (!mode.create_flag && !FileUtil::Exists(path)) { 87 if (!mode.create_flag && !FileUtil::Exists(path)) {
88 LOG_ERROR(Service_FS, "Non-existing file %s cant be open without mode create.", path.c_str()); 88 LOG_ERROR(Service_FS, "Non-existing file %s can't be open without mode create.", path.c_str());
89 return false; 89 return false;
90 } 90 }
91 91
diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h
index 6c9b689e0..018ebd2ed 100644
--- a/src/core/file_sys/disk_archive.h
+++ b/src/core/file_sys/disk_archive.h
@@ -16,8 +16,8 @@
16namespace FileSys { 16namespace FileSys {
17 17
18/** 18/**
19 * Helper which implements a backend accessing the host machine's filesystem. 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 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. 21 * base directory on the host filesystem and override any required functionality.
22 */ 22 */
23class DiskArchive : public ArchiveBackend { 23class DiskArchive : public ArchiveBackend {
@@ -26,12 +26,12 @@ public:
26 26
27 virtual std::string GetName() const = 0; 27 virtual std::string GetName() const = 0;
28 std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override; 28 std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override;
29 bool DeleteFile(const FileSys::Path& path) const override; 29 bool DeleteFile(const Path& path) const override;
30 bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override; 30 bool RenameFile(const Path& src_path, const Path& dest_path) const override;
31 bool DeleteDirectory(const FileSys::Path& path) const override; 31 bool DeleteDirectory(const Path& path) const override;
32 ResultCode CreateFile(const Path& path, u32 size) const override; 32 ResultCode CreateFile(const Path& path, u32 size) const override;
33 bool CreateDirectory(const Path& path) const override; 33 bool CreateDirectory(const Path& path) const override;
34 bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_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; 35 std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override;
36 36
37 /** 37 /**
@@ -50,7 +50,7 @@ class DiskFile : public FileBackend {
50public: 50public:
51 DiskFile(); 51 DiskFile();
52 DiskFile(const DiskArchive* archive, const Path& path, const Mode mode); 52 DiskFile(const DiskArchive* archive, const Path& path, const Mode mode);
53 53
54 ~DiskFile() override { 54 ~DiskFile() override {
55 Close(); 55 Close();
56 } 56 }
@@ -61,7 +61,7 @@ public:
61 size_t GetSize() const override; 61 size_t GetSize() const override;
62 bool SetSize(const u64 size) const override; 62 bool SetSize(const u64 size) const override;
63 bool Close() const override; 63 bool Close() const override;
64 64
65 void Flush() const override { 65 void Flush() const override {
66 file->Flush(); 66 file->Flush();
67 } 67 }
diff --git a/src/core/file_sys/file_romfs.cpp b/src/core/file_sys/file_romfs.cpp
index e79936407..7467d6d31 100644
--- a/src/core/file_sys/file_romfs.cpp
+++ b/src/core/file_sys/file_romfs.cpp
@@ -12,62 +12,30 @@
12 12
13namespace FileSys { 13namespace FileSys {
14 14
15/**
16 * Open the file
17 * @return true if the file opened correctly
18 */
19bool File_RomFS::Open() { 15bool File_RomFS::Open() {
20 return true; 16 return true;
21} 17}
22 18
23/**
24 * Read data from the file
25 * @param offset Offset in bytes to start reading data from
26 * @param length Length in bytes of data to read from file
27 * @param buffer Buffer to read data into
28 * @return Number of bytes read
29 */
30size_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 {
31 LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length); 20 LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length);
32 memcpy(buffer, &archive->raw_data[(u32)offset], length); 21 memcpy(buffer, &archive->raw_data[(u32)offset], length);
33 return length; 22 return length;
34} 23}
35 24
36/**
37 * Write data to the file
38 * @param offset Offset in bytes to start writing data to
39 * @param length Length in bytes of data to write to file
40 * @param flush The flush parameters (0 == do not flush)
41 * @param buffer Buffer to read data from
42 * @return Number of bytes written
43 */
44size_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 {
45 LOG_WARNING(Service_FS, "Attempted to write to ROMFS."); 26 LOG_WARNING(Service_FS, "Attempted to write to ROMFS.");
46 return 0; 27 return 0;
47} 28}
48 29
49/**
50 * Get the size of the file in bytes
51 * @return Size of the file in bytes
52 */
53size_t File_RomFS::GetSize() const { 30size_t File_RomFS::GetSize() const {
54 return sizeof(u8) * archive->raw_data.size(); 31 return sizeof(u8) * archive->raw_data.size();
55} 32}
56 33
57/**
58 * Set the size of the file in bytes
59 * @param size New size of the file
60 * @return true if successful
61 */
62bool File_RomFS::SetSize(const u64 size) const { 34bool File_RomFS::SetSize(const u64 size) const {
63 LOG_WARNING(Service_FS, "Attempted to set the size of ROMFS"); 35 LOG_WARNING(Service_FS, "Attempted to set the size of ROMFS");
64 return false; 36 return false;
65} 37}
66 38
67/**
68 * Close the file
69 * @return true if the file closed correctly
70 */
71bool File_RomFS::Close() const { 39bool File_RomFS::Close() const {
72 return false; 40 return false;
73} 41}
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp
index 2d314a4cf..33ac12507 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -43,7 +43,15 @@ void CallSVC(u32 opcode) {
43 43
44void Reschedule(const char *reason) { 44void Reschedule(const char *reason) {
45 _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
46 Core::g_app_core->PrepareReschedule(); 53 Core::g_app_core->PrepareReschedule();
54
47 g_reschedule = true; 55 g_reschedule = true;
48} 56}
49 57
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 77491900a..38705e3cd 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -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/event.cpp b/src/core/hle/kernel/event.cpp
index 4de3fab3c..e43c3ee4e 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -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/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 5fd06046e..e59ed1b57 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -13,77 +13,93 @@
13namespace Kernel { 13namespace Kernel {
14 14
15Handle g_main_thread = 0; 15Handle g_main_thread = 0;
16ObjectPool g_object_pool; 16HandleTable g_handle_table;
17u64 g_program_id = 0; 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;
61} 56}
62 57
63Object* &ObjectPool::operator [](Handle handle) 58ResultCode HandleTable::Close(Handle handle) {
64{ 59 if (!IsValid(handle))
65 _dbg_assert_msg_(Kernel, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ"); 60 return ERR_INVALID_HANDLE;
66 return pool[handle - HANDLE_OFFSET]; 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;
67} 71}
68 72
69void ObjectPool::List() { 73bool HandleTable::IsValid(Handle handle) const {
70 for (int i = 0; i < MAX_COUNT; i++) { 74 size_t slot = GetSlot(handle);
71 if (occupied[i]) { 75 u16 generation = GetGeneration(handle);
72 if (pool[i]) { 76
73 LOG_DEBUG(Kernel, "KO %i: %s \"%s\"", i + HANDLE_OFFSET, pool[i]->GetTypeName().c_str(), 77 return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
74 pool[i]->GetName().c_str());
75 }
76 }
77 }
78} 78}
79 79
80int ObjectPool::GetCount() const { 80Object* HandleTable::GetGeneric(Handle handle) const {
81 return std::count(occupied.begin(), occupied.end(), true); 81 if (handle == CurrentThread) {
82 // TODO(yuriks) Directly return the pointer once this is possible.
83 handle = GetCurrentThreadHandle();
84 } else if (handle == CurrentProcess) {
85 LOG_ERROR(Kernel, "Current process (%08X) pseudo-handle not supported", CurrentProcess);
86 return nullptr;
87 }
88
89 if (!IsValid(handle)) {
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
@@ -95,7 +111,7 @@ void Init() {
95void Shutdown() { 111void Shutdown() {
96 Kernel::ThreadingShutdown(); 112 Kernel::ThreadingShutdown();
97 113
98 g_object_pool.Clear(); // Free all kernel objects 114 g_handle_table.Clear(); // Free all kernel objects
99} 115}
100 116
101/** 117/**
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 32258d5a0..7f86fd07d 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -12,13 +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
17// From kernel.h. Declarations duplicated here to avoid a circular header dependency. 19// TODO: Verify code
18class Thread; 20const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
19Thread* GetCurrentThread(); 21 ErrorSummary::OutOfResource, ErrorLevel::Temporary);
22// TOOD: Verify code
23const ResultCode ERR_INVALID_HANDLE = InvalidHandle(ErrorModule::Kernel);
20 24
21enum KernelHandle { 25enum KernelHandle : Handle {
22 CurrentThread = 0xFFFF8000, 26 CurrentThread = 0xFFFF8000,
23 CurrentProcess = 0xFFFF8001, 27 CurrentProcess = 0xFFFF8001,
24}; 28};
@@ -41,10 +45,10 @@ enum {
41 DEFAULT_STACK_SIZE = 0x4000, 45 DEFAULT_STACK_SIZE = 0x4000,
42}; 46};
43 47
44class ObjectPool; 48class HandleTable;
45 49
46class Object : NonCopyable { 50class Object : NonCopyable {
47 friend class ObjectPool; 51 friend class HandleTable;
48 u32 handle; 52 u32 handle;
49public: 53public:
50 virtual ~Object() {} 54 virtual ~Object() {}
@@ -61,106 +65,130 @@ public:
61 LOG_ERROR(Kernel, "(UNIMPLEMENTED)"); 65 LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
62 return UnimplementedFunction(ErrorModule::Kernel); 66 return UnimplementedFunction(ErrorModule::Kernel);
63 } 67 }
64};
65 68
66class ObjectPool : NonCopyable { 69private:
67public: 70 friend void intrusive_ptr_add_ref(Object*);
68 ObjectPool(); 71 friend void intrusive_ptr_release(Object*);
69 ~ObjectPool() {}
70 72
71 // Allocates a handle within the range and inserts the object into the map. 73 unsigned int ref_count = 0;
72 Handle Create(Object* obj, int range_bottom=INITIAL_NEXT_ID, int range_top=0x7FFFFFFF); 74};
73 75
74 static Object* CreateByIDType(int type); 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}
75 80
76 template <class T> 81inline void intrusive_ptr_release(Object* object) {
77 void Destroy(Handle handle) { 82 if (--object->ref_count == 0) {
78 if (Get<T>(handle)) { 83 delete object;
79 occupied[handle - HANDLE_OFFSET] = false;
80 delete pool[handle - HANDLE_OFFSET];
81 }
82 } 84 }
85}
83 86
84 bool IsValid(Handle handle) const; 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 {
111public:
112 HandleTable();
85 113
86 template <class T> 114 /**
87 T* Get(Handle handle) { 115 * Allocates a handle for the given object.
88 if (handle == CurrentThread) { 116 * @return The created Handle or one of the following errors:
89 return reinterpret_cast<T*>(GetCurrentThread()); 117 * - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
90 } 118 */
119 ResultVal<Handle> Create(Object* obj);
91 120
92 if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) { 121 /**
93 if (handle != 0) { 122 * Returns a new handle that points to the same object as the passed in handle.
94 LOG_ERROR(Kernel, "Bad object handle %08x", handle); 123 * @return The duplicated Handle or one of the following errors:
95 } 124 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
96 return nullptr; 125 * - Any errors returned by `Create()`.
97 } else { 126 */
98 Object* t = pool[handle - HANDLE_OFFSET]; 127 ResultVal<Handle> Duplicate(Handle handle);
99 if (t->GetHandleType() != T::GetStaticHandleType()) {
100 LOG_ERROR(Kernel, "Wrong object type for %08x", handle);
101 return nullptr;
102 }
103 return static_cast<T*>(t);
104 }
105 }
106 128
107 // ONLY use this when you know the handle is valid. 129 /**
108 template <class T> 130 * Closes a handle, removing it from the table and decreasing the object's ref-count.
109 T *GetFast(Handle handle) { 131 * @return `RESULT_SUCCESS` or one of the following errors:
110 if (handle == CurrentThread) { 132 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
111 return reinterpret_cast<T*>(GetCurrentThread()); 133 */
112 } 134 ResultCode Close(Handle handle);
113 135
114 const Handle realHandle = handle - HANDLE_OFFSET; 136 /// Checks if a handle is valid and points to an existing object.
115 _dbg_assert_(Kernel, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]); 137 bool IsValid(Handle handle) const;
116 return static_cast<T*>(pool[realHandle]);
117 }
118 138
119 template <class T, typename ArgT> 139 /**
120 void Iterate(bool func(T*, ArgT), ArgT arg) { 140 * Looks up a handle.
121 int type = T::GetStaticIDType(); 141 * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid.
122 for (int i = 0; i < MAX_COUNT; i++) 142 */
123 { 143 Object* GetGeneric(Handle handle) const;
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 }
132 }
133 144
134 bool GetIDType(Handle handle, HandleType* type) const { 145 /**
135 if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) || 146 * Looks up a handle while verifying its type.
136 !occupied[handle - HANDLE_OFFSET]) { 147 * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
137 LOG_ERROR(Kernel, "Bad object handle %08X", handle); 148 * type differs from the handle type `T::HANDLE_TYPE`.
138 return false; 149 */
150 template <class T>
151 T* Get(Handle handle) const {
152 Object* object = GetGeneric(handle);
153 if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
154 return static_cast<T*>(object);
139 } 155 }
140 Object* t = pool[handle - HANDLE_OFFSET]; 156 return nullptr;
141 *type = t->GetHandleType();
142 return true;
143 } 157 }
144 158
145 Object* &operator [](Handle handle); 159 /// Closes all handles held in this table.
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;
168
169 static size_t GetSlot(Handle handle) { return handle >> 15; }
170 static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; }
171
172 /// Stores the Object referenced by the handle or null if the slot is empty.
173 std::array<Object*, MAX_COUNT> objects;
151 174
152 enum { 175 /**
153 MAX_COUNT = 0x1000, 176 * The value of `next_generation` when the handle was created, used to check for validity. For
154 HANDLE_OFFSET = 0x100, 177 * empty slots, contains the index of the next free slot in the list.
155 INITIAL_NEXT_ID = 0x10, 178 */
156 }; 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;
157 186
158 std::array<Object*, MAX_COUNT> pool; 187 /// Head of the free slots linked list.
159 std::array<bool, MAX_COUNT> occupied; 188 u16 next_free_slot;
160 int next_id;
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
166/// The ID code of the currently running game 194/// The ID code of the currently running game
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 5a18af114..558068c79 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -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/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index b81d0b26a..6bc8066a6 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -17,8 +17,8 @@ public:
17 std::string GetTypeName() const override { return "Semaphore"; } 17 std::string GetTypeName() const override { return "Semaphore"; }
18 std::string GetName() const override { return name; } 18 std::string GetName() const override { return name; }
19 19
20 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; } 20 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
21 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; } 21 HandleType GetHandleType() const override { return HANDLE_TYPE; }
22 22
23 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have 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 24 s32 available_count; ///< Number of free slots left in the semaphore
@@ -57,7 +57,8 @@ ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
57 ErrorSummary::WrongArgument, ErrorLevel::Permanent); 57 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
58 58
59 Semaphore* semaphore = new Semaphore; 59 Semaphore* semaphore = new Semaphore;
60 *handle = g_object_pool.Create(semaphore); 60 // TOOD(yuriks): Fix error reporting
61 *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE);
61 62
62 // When the semaphore is created, some slots are reserved for other threads, 63 // When the semaphore is created, some slots are reserved for other threads,
63 // and the rest is reserved for the caller thread 64 // and the rest is reserved for the caller thread
@@ -69,7 +70,7 @@ ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
69} 70}
70 71
71ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { 72ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
72 Semaphore* semaphore = g_object_pool.Get<Semaphore>(handle); 73 Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle);
73 if (semaphore == nullptr) 74 if (semaphore == nullptr)
74 return InvalidHandle(ErrorModule::Kernel); 75 return InvalidHandle(ErrorModule::Kernel);
75 76
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index 6760f346e..91f3ffc2c 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -45,8 +45,8 @@ class Session : public Object {
45public: 45public:
46 std::string GetTypeName() const override { return "Session"; } 46 std::string GetTypeName() const override { return "Session"; }
47 47
48 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Session; } 48 static const HandleType HANDLE_TYPE = HandleType::Session;
49 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Session; } 49 HandleType GetHandleType() const override { return HANDLE_TYPE; }
50 50
51 /** 51 /**
52 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls 52 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 2840f13bb..cea1f6fa1 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -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/thread.cpp b/src/core/hle/kernel/thread.cpp
index c6a8dc7b9..872df2d14 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -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; }
@@ -164,7 +164,7 @@ static bool CheckWaitType(const Thread* thread, WaitType type, Handle wait_handl
164 164
165/// Stops the current thread 165/// Stops the current thread
166ResultCode StopThread(Handle handle, const char* reason) { 166ResultCode StopThread(Handle handle, const char* reason) {
167 Thread* thread = g_object_pool.Get<Thread>(handle); 167 Thread* thread = g_handle_table.Get<Thread>(handle);
168 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); 168 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
169 169
170 // Release all the mutexes that this thread holds 170 // Release all the mutexes that this thread holds
@@ -173,7 +173,7 @@ ResultCode StopThread(Handle handle, const char* reason) {
173 ChangeReadyState(thread, false); 173 ChangeReadyState(thread, false);
174 thread->status = THREADSTATUS_DORMANT; 174 thread->status = THREADSTATUS_DORMANT;
175 for (Handle waiting_handle : thread->waiting_threads) { 175 for (Handle waiting_handle : thread->waiting_threads) {
176 Thread* waiting_thread = g_object_pool.Get<Thread>(waiting_handle); 176 Thread* waiting_thread = g_handle_table.Get<Thread>(waiting_handle);
177 177
178 if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, handle)) 178 if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, handle))
179 ResumeThreadFromWait(waiting_handle); 179 ResumeThreadFromWait(waiting_handle);
@@ -210,7 +210,7 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
210 210
211 // 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...
212 for (Handle handle : thread_queue) { 212 for (Handle handle : thread_queue) {
213 Thread* thread = g_object_pool.Get<Thread>(handle); 213 Thread* thread = g_handle_table.Get<Thread>(handle);
214 214
215 if (!CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) 215 if (!CheckWaitType(thread, WAITTYPE_ARB, arbiter, address))
216 continue; 216 continue;
@@ -235,7 +235,7 @@ void ArbitrateAllThreads(u32 arbiter, u32 address) {
235 235
236 // 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...
237 for (Handle handle : thread_queue) { 237 for (Handle handle : thread_queue) {
238 Thread* thread = g_object_pool.Get<Thread>(handle); 238 Thread* thread = g_handle_table.Get<Thread>(handle);
239 239
240 if (CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) 240 if (CheckWaitType(thread, WAITTYPE_ARB, arbiter, address))
241 ResumeThreadFromWait(handle); 241 ResumeThreadFromWait(handle);
@@ -288,7 +288,7 @@ Thread* NextThread() {
288 if (next == 0) { 288 if (next == 0) {
289 return nullptr; 289 return nullptr;
290 } 290 }
291 return Kernel::g_object_pool.Get<Thread>(next); 291 return Kernel::g_handle_table.Get<Thread>(next);
292} 292}
293 293
294void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { 294void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
@@ -305,7 +305,7 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_addres
305 305
306/// Resumes a thread from waiting by marking it as "ready" 306/// Resumes a thread from waiting by marking it as "ready"
307void ResumeThreadFromWait(Handle handle) { 307void ResumeThreadFromWait(Handle handle) {
308 Thread* thread = Kernel::g_object_pool.Get<Thread>(handle); 308 Thread* thread = Kernel::g_handle_table.Get<Thread>(handle);
309 if (thread) { 309 if (thread) {
310 thread->status &= ~THREADSTATUS_WAIT; 310 thread->status &= ~THREADSTATUS_WAIT;
311 thread->wait_handle = 0; 311 thread->wait_handle = 0;
@@ -341,7 +341,8 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio
341 341
342 Thread* thread = new Thread; 342 Thread* thread = new Thread;
343 343
344 handle = Kernel::g_object_pool.Create(thread); 344 // TOOD(yuriks): Fix error reporting
345 handle = Kernel::g_handle_table.Create(thread).ValueOr(INVALID_HANDLE);
345 346
346 thread_queue.push_back(handle); 347 thread_queue.push_back(handle);
347 thread_ready_queue.prepare(priority); 348 thread_ready_queue.prepare(priority);
@@ -398,7 +399,7 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3
398 399
399/// Get the priority of the thread specified by handle 400/// Get the priority of the thread specified by handle
400ResultVal<u32> GetThreadPriority(const Handle handle) { 401ResultVal<u32> GetThreadPriority(const Handle handle) {
401 Thread* thread = g_object_pool.Get<Thread>(handle); 402 Thread* thread = g_handle_table.Get<Thread>(handle);
402 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); 403 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
403 404
404 return MakeResult<u32>(thread->current_priority); 405 return MakeResult<u32>(thread->current_priority);
@@ -410,7 +411,7 @@ ResultCode SetThreadPriority(Handle handle, s32 priority) {
410 if (!handle) { 411 if (!handle) {
411 thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? 412 thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior?
412 } else { 413 } else {
413 thread = g_object_pool.Get<Thread>(handle); 414 thread = g_handle_table.Get<Thread>(handle);
414 if (thread == nullptr) { 415 if (thread == nullptr) {
415 return InvalidHandle(ErrorModule::Kernel); 416 return InvalidHandle(ErrorModule::Kernel);
416 } 417 }
@@ -481,7 +482,7 @@ void Reschedule() {
481 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); 482 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle());
482 483
483 for (Handle handle : thread_queue) { 484 for (Handle handle : thread_queue) {
484 Thread* thread = g_object_pool.Get<Thread>(handle); 485 Thread* thread = g_handle_table.Get<Thread>(handle);
485 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X", 486 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X",
486 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, thread->wait_handle); 487 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, thread->wait_handle);
487 } 488 }
@@ -497,7 +498,7 @@ void Reschedule() {
497} 498}
498 499
499ResultCode GetThreadId(u32* thread_id, Handle handle) { 500ResultCode GetThreadId(u32* thread_id, Handle handle) {
500 Thread* thread = g_object_pool.Get<Thread>(handle); 501 Thread* thread = g_handle_table.Get<Thread>(handle);
501 if (thread == nullptr) 502 if (thread == nullptr)
502 return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS, 503 return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS,
503 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 9396b6b26..0e1397cd9 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -77,9 +77,6 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address);
77/// Arbitrate all threads currently waiting... 77/// Arbitrate all threads currently waiting...
78void ArbitrateAllThreads(u32 arbiter, u32 address); 78void ArbitrateAllThreads(u32 arbiter, u32 address);
79 79
80/// Gets the current thread
81Thread* GetCurrentThread();
82
83/// Gets the current thread handle 80/// Gets the current thread handle
84Handle GetCurrentThreadHandle(); 81Handle GetCurrentThreadHandle();
85 82
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index d180bb4ec..20a3fa2e5 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -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 097b18c4e..f1d26ebe8 100644
--- a/src/core/hle/service/ac_u.h
+++ b/src/core/hle/service/ac_u.h
@@ -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.h b/src/core/hle/service/am_app.h
index 30a0be4c5..50dc2f5a2 100644
--- a/src/core/hle/service/am_app.h
+++ b/src/core/hle/service/am_app.h
@@ -15,10 +15,6 @@ class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 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:app"; 19 return "am:app";
24 } 20 }
diff --git a/src/core/hle/service/am_net.cpp b/src/core/hle/service/am_net.cpp
index 943205e9e..112844e5b 100644
--- a/src/core/hle/service/am_net.cpp
+++ b/src/core/hle/service/am_net.cpp
@@ -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 c0dbfb444..616c33ee8 100644
--- a/src/core/hle/service/am_net.h
+++ b/src/core/hle/service/am_net.h
@@ -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 fecc6e6f9..d8b261ba7 100644
--- a/src/core/hle/service/apt_u.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -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 3807cbecc..aad918cfc 100644
--- a/src/core/hle/service/apt_u.h
+++ b/src/core/hle/service/apt_u.h
@@ -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 24cd413da..1820ea7ad 100644
--- a/src/core/hle/service/boss_u.cpp
+++ b/src/core/hle/service/boss_u.cpp
@@ -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 31e4d0c3a..2668f2dfd 100644
--- a/src/core/hle/service/boss_u.h
+++ b/src/core/hle/service/boss_u.h
@@ -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.h b/src/core/hle/service/cecd_u.h
index 0c9968bfe..e67564135 100644
--- a/src/core/hle/service/cecd_u.h
+++ b/src/core/hle/service/cecd_u.h
@@ -15,10 +15,6 @@ class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 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 "cecd:u"; 19 return "cecd:u";
24 } 20 }
diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp
index 3254cc10e..7c1ee8ac3 100644
--- a/src/core/hle/service/cfg/cfg_i.cpp
+++ b/src/core/hle/service/cfg/cfg_i.cpp
@@ -66,40 +66,40 @@ static void FormatConfig(Service::Interface* self) {
66} 66}
67 67
68const Interface::FunctionInfo FunctionTable[] = { 68const Interface::FunctionInfo FunctionTable[] = {
69 {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, 69 {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
70 {0x04020082, nullptr, "SetConfigInfoBlk4"}, 70 {0x04020082, nullptr, "SetConfigInfoBlk4"},
71 {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, 71 {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
72 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, 72 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
73 {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, 73 {0x04050000, nullptr, "GetLocalFriendCodeSeed"},
74 {0x04060000, nullptr, "SecureInfoGetRegion"}, 74 {0x04060000, nullptr, "SecureInfoGetRegion"},
75 {0x04070000, nullptr, "SecureInfoGetByte101"}, 75 {0x04070000, nullptr, "SecureInfoGetByte101"},
76 {0x04080042, nullptr, "SecureInfoGetSerialNo"}, 76 {0x04080042, nullptr, "SecureInfoGetSerialNo"},
77 {0x04090000, nullptr, "UpdateConfigBlk00040003"}, 77 {0x04090000, nullptr, "UpdateConfigBlk00040003"},
78 {0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, 78 {0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
79 {0x08020082, nullptr, "SetConfigInfoBlk4"}, 79 {0x08020082, nullptr, "SetConfigInfoBlk4"},
80 {0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, 80 {0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
81 {0x080400C2, nullptr, "CreateConfigInfoBlk"}, 81 {0x080400C2, nullptr, "CreateConfigInfoBlk"},
82 {0x08050000, nullptr, "DeleteConfigNANDSavefile"}, 82 {0x08050000, nullptr, "DeleteConfigNANDSavefile"},
83 {0x08060000, FormatConfig, "FormatConfig"}, 83 {0x08060000, FormatConfig, "FormatConfig"},
84 {0x08070000, nullptr, "Unknown"}, 84 {0x08080000, nullptr, "UpdateConfigBlk1"},
85 {0x08080000, nullptr, "UpdateConfigBlk1"}, 85 {0x08090000, nullptr, "UpdateConfigBlk2"},
86 {0x08090000, nullptr, "UpdateConfigBlk2"}, 86 {0x080A0000, nullptr, "UpdateConfigBlk3"},
87 {0x080A0000, nullptr, "UpdateConfigBlk3"}, 87 {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"},
88 {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"}, 88 {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"},
89 {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"}, 89 {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"},
90 {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"}, 90 {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"},
91 {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"}, 91 {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"},
92 {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"}, 92 {0x08100000, nullptr, "GetLocalFriendCodeSeed"},
93 {0x08100000, nullptr, "GetLocalFriendCodeSeed"}, 93 {0x08110084, nullptr, "SetSecureInfo"},
94 {0x08110084, nullptr, "SetSecureInfo"}, 94 {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"},
95 {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"}, 95 {0x08130000, nullptr, "VerifySigSecureInfo"},
96 {0x08130000, nullptr, "VerifySigSecureInfo"}, 96 {0x08140042, nullptr, "SecureInfoGetData"},
97 {0x08140042, nullptr, "SecureInfoGetData"}, 97 {0x08150042, nullptr, "SecureInfoGetSignature"},
98 {0x08150042, nullptr, "SecureInfoGetSignature"}, 98 {0x08160000, nullptr, "SecureInfoGetRegion"},
99 {0x08160000, nullptr, "SecureInfoGetRegion"}, 99 {0x08170000, nullptr, "SecureInfoGetByte101"},
100 {0x08170000, nullptr, "SecureInfoGetByte101"}, 100 {0x08180042, nullptr, "SecureInfoGetSerialNo"},
101 {0x08180042, nullptr, "SecureInfoGetSerialNo"},
102}; 101};
102
103//////////////////////////////////////////////////////////////////////////////////////////////////// 103////////////////////////////////////////////////////////////////////////////////////////////////////
104// Interface class 104// Interface class
105 105
@@ -107,7 +107,4 @@ Interface::Interface() {
107 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 107 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
108} 108}
109 109
110Interface::~Interface() {
111}
112
113} // namespace 110} // namespace
diff --git a/src/core/hle/service/cfg/cfg_i.h b/src/core/hle/service/cfg/cfg_i.h
index 577aad236..a498dd589 100644
--- a/src/core/hle/service/cfg/cfg_i.h
+++ b/src/core/hle/service/cfg/cfg_i.h
@@ -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/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp
index 59934ea46..03c01cf90 100644
--- a/src/core/hle/service/cfg/cfg_u.cpp
+++ b/src/core/hle/service/cfg/cfg_u.cpp
@@ -181,6 +181,7 @@ const Interface::FunctionInfo FunctionTable[] = {
181 {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, 181 {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
182 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, 182 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
183}; 183};
184
184//////////////////////////////////////////////////////////////////////////////////////////////////// 185////////////////////////////////////////////////////////////////////////////////////////////////////
185// Interface class 186// Interface class
186 187
@@ -188,7 +189,4 @@ Interface::Interface() {
188 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 189 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
189} 190}
190 191
191Interface::~Interface() {
192}
193
194} // namespace 192} // namespace
diff --git a/src/core/hle/service/cfg/cfg_u.h b/src/core/hle/service/cfg/cfg_u.h
index 0136bff53..9ad73f355 100644
--- a/src/core/hle/service/cfg/cfg_u.h
+++ b/src/core/hle/service/cfg/cfg_u.h
@@ -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/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp
index 3f62c7e9c..aef8cfbca 100644
--- a/src/core/hle/service/csnd_snd.cpp
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -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 85aab1dd3..a84752473 100644
--- a/src/core/hle/service/csnd_snd.h
+++ b/src/core/hle/service/csnd_snd.h
@@ -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 4c1c5b70b..2cf4d118f 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -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 7bf27fe0f..0b8b64600 100644
--- a/src/core/hle/service/dsp_dsp.h
+++ b/src/core/hle/service/dsp_dsp.h
@@ -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 5c7cce841..8c900eabc 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -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 2c61c3651..892d8af9b 100644
--- a/src/core/hle/service/err_f.h
+++ b/src/core/hle/service/err_f.h
@@ -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 c2ecef5bb..021186e57 100644
--- a/src/core/hle/service/frd_u.cpp
+++ b/src/core/hle/service/frd_u.cpp
@@ -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 e030f8b3b..ab8897d5b 100644
--- a/src/core/hle/service/frd_u.h
+++ b/src/core/hle/service/frd_u.h
@@ -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
index 98db02f15..487bf3aa7 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -133,7 +133,7 @@ public:
133 case FileCommand::Close: 133 case FileCommand::Close:
134 { 134 {
135 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); 135 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
136 Kernel::g_object_pool.Destroy<File>(GetHandle()); 136 backend->Close();
137 break; 137 break;
138 } 138 }
139 139
@@ -189,7 +189,7 @@ public:
189 case DirectoryCommand::Close: 189 case DirectoryCommand::Close:
190 { 190 {
191 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); 191 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
192 Kernel::g_object_pool.Destroy<Directory>(GetHandle()); 192 backend->Close();
193 break; 193 break;
194 } 194 }
195 195
@@ -283,7 +283,8 @@ ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSy
283 } 283 }
284 284
285 auto file = Common::make_unique<File>(std::move(backend), path); 285 auto file = Common::make_unique<File>(std::move(backend), path);
286 Handle handle = Kernel::g_object_pool.Create(file.release()); 286 // TOOD(yuriks): Fix error reporting
287 Handle handle = Kernel::g_handle_table.Create(file.release()).ValueOr(INVALID_HANDLE);
287 return MakeResult<Handle>(handle); 288 return MakeResult<Handle>(handle);
288} 289}
289 290
@@ -388,7 +389,8 @@ ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const F
388 } 389 }
389 390
390 auto directory = Common::make_unique<Directory>(std::move(backend), path); 391 auto directory = Common::make_unique<Directory>(std::move(backend), path);
391 Handle handle = Kernel::g_object_pool.Create(directory.release()); 392 // TOOD(yuriks): Fix error reporting
393 Handle handle = Kernel::g_handle_table.Create(directory.release()).ValueOr(INVALID_HANDLE);
392 return MakeResult<Handle>(handle); 394 return MakeResult<Handle>(handle);
393} 395}
394 396
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 957185f8f..b1a465274 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -597,8 +597,5 @@ FSUserInterface::FSUserInterface() {
597 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 597 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
598} 598}
599 599
600FSUserInterface::~FSUserInterface() {
601}
602
603} // namespace FS 600} // namespace FS
604} // namespace Service 601} // namespace Service
diff --git a/src/core/hle/service/fs/fs_user.h b/src/core/hle/service/fs/fs_user.h
index af4da269b..2d896dd5f 100644
--- a/src/core/hle/service/fs/fs_user.h
+++ b/src/core/hle/service/fs/fs_user.h
@@ -15,15 +15,8 @@ namespace FS {
15/// Interface to "fs:USER" service 15/// Interface to "fs:USER" service
16class FSUserInterface : public Service::Interface { 16class FSUserInterface : public Service::Interface {
17public: 17public:
18
19 FSUserInterface(); 18 FSUserInterface();
20 19
21 ~FSUserInterface();
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 "fs:USER"; 21 return "fs:USER";
29 } 22 }
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 1f841078a..0127d4ee5 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -396,7 +396,4 @@ Interface::Interface() {
396 g_thread_id = 1; 396 g_thread_id = 1;
397} 397}
398 398
399Interface::~Interface() {
400}
401
402} // namespace 399} // namespace
diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h
index 56b5a16c9..932b6170f 100644
--- a/src/core/hle/service/gsp_gpu.h
+++ b/src/core/hle/service/gsp_gpu.h
@@ -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 cec9b1bfb..99b0ea5a0 100644
--- a/src/core/hle/service/hid_user.cpp
+++ b/src/core/hle/service/hid_user.cpp
@@ -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 2164ad896..5b96dda60 100644
--- a/src/core/hle/service/hid_user.h
+++ b/src/core/hle/service/hid_user.h
@@ -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 6145b8b2c..b388afb15 100644
--- a/src/core/hle/service/ir_rst.cpp
+++ b/src/core/hle/service/ir_rst.cpp
@@ -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 2fdab9f02..deef701c5 100644
--- a/src/core/hle/service/ir_rst.h
+++ b/src/core/hle/service/ir_rst.h
@@ -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 db62a9c98..da6f38e41 100644
--- a/src/core/hle/service/ir_u.cpp
+++ b/src/core/hle/service/ir_u.cpp
@@ -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 cf1c73f52..ec47a1524 100644
--- a/src/core/hle/service/ir_u.h
+++ b/src/core/hle/service/ir_u.h
@@ -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
index c08313f9a..9c9e90a40 100644
--- a/src/core/hle/service/ldr_ro.cpp
+++ b/src/core/hle/service/ldr_ro.cpp
@@ -18,6 +18,7 @@ const Interface::FunctionInfo FunctionTable[] = {
18 {0x000402C2, nullptr, "CRO_LoadAndFix"}, 18 {0x000402C2, nullptr, "CRO_LoadAndFix"},
19 {0x000500C2, nullptr, "CRO_ApplyRelocationPatchesAndLink"} 19 {0x000500C2, nullptr, "CRO_ApplyRelocationPatchesAndLink"}
20}; 20};
21
21//////////////////////////////////////////////////////////////////////////////////////////////////// 22////////////////////////////////////////////////////////////////////////////////////////////////////
22// Interface class 23// Interface class
23 24
diff --git a/src/core/hle/service/ldr_ro.h b/src/core/hle/service/ldr_ro.h
index 7716ae74e..331637cde 100644
--- a/src/core/hle/service/ldr_ro.h
+++ b/src/core/hle/service/ldr_ro.h
@@ -15,10 +15,6 @@ class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 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 "ldr:ro"; 19 return "ldr:ro";
24 } 20 }
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index 399548d4d..82bce9180 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -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 26842e5f1..dc795d14c 100644
--- a/src/core/hle/service/mic_u.h
+++ b/src/core/hle/service/mic_u.h
@@ -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 141c311fd..233b14f6d 100644
--- a/src/core/hle/service/ndm_u.cpp
+++ b/src/core/hle/service/ndm_u.cpp
@@ -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 62ed901c2..51c4b3902 100644
--- a/src/core/hle/service/ndm_u.h
+++ b/src/core/hle/service/ndm_u.h
@@ -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.h b/src/core/hle/service/nim_aoc.h
index 33aa25c91..aeb71eed2 100644
--- a/src/core/hle/service/nim_aoc.h
+++ b/src/core/hle/service/nim_aoc.h
@@ -15,10 +15,6 @@ class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 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 "nim:aoc"; 19 return "nim:aoc";
24 } 20 }
diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp
index 2491d14d6..ce456a966 100644
--- a/src/core/hle/service/nwm_uds.cpp
+++ b/src/core/hle/service/nwm_uds.cpp
@@ -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 cd27f78fc..9043f5aa7 100644
--- a/src/core/hle/service/nwm_uds.h
+++ b/src/core/hle/service/nwm_uds.h
@@ -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 729255348..529dccafb 100644
--- a/src/core/hle/service/pm_app.cpp
+++ b/src/core/hle/service/pm_app.cpp
@@ -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 7ed617e5e..c1fb1f9da 100644
--- a/src/core/hle/service/pm_app.h
+++ b/src/core/hle/service/pm_app.h
@@ -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 da48729da..d1498f05c 100644
--- a/src/core/hle/service/ptm_u.cpp
+++ b/src/core/hle/service/ptm_u.cpp
@@ -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 c9e0c519f..a44624fd5 100644
--- a/src/core/hle/service/ptm_u.h
+++ b/src/core/hle/service/ptm_u.h
@@ -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 664f914d6..0f3cc2aa8 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -7,8 +7,10 @@
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"
10#include "core/hle/service/am_app.h" 11#include "core/hle/service/am_app.h"
11#include "core/hle/service/am_net.h" 12#include "core/hle/service/am_net.h"
13#include "core/hle/service/apt_a.h"
12#include "core/hle/service/apt_u.h" 14#include "core/hle/service/apt_u.h"
13#include "core/hle/service/boss_u.h" 15#include "core/hle/service/boss_u.h"
14#include "core/hle/service/cecd_u.h" 16#include "core/hle/service/cecd_u.h"
@@ -21,12 +23,14 @@
21#include "core/hle/service/frd_u.h" 23#include "core/hle/service/frd_u.h"
22#include "core/hle/service/gsp_gpu.h" 24#include "core/hle/service/gsp_gpu.h"
23#include "core/hle/service/hid_user.h" 25#include "core/hle/service/hid_user.h"
26#include "core/hle/service/http_c.h"
24#include "core/hle/service/ir_rst.h" 27#include "core/hle/service/ir_rst.h"
25#include "core/hle/service/ir_u.h" 28#include "core/hle/service/ir_u.h"
26#include "core/hle/service/ldr_ro.h" 29#include "core/hle/service/ldr_ro.h"
27#include "core/hle/service/mic_u.h" 30#include "core/hle/service/mic_u.h"
28#include "core/hle/service/nim_aoc.h"
29#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"
30#include "core/hle/service/nwm_uds.h" 34#include "core/hle/service/nwm_uds.h"
31#include "core/hle/service/pm_app.h" 35#include "core/hle/service/pm_app.h"
32#include "core/hle/service/ptm_u.h" 36#include "core/hle/service/ptm_u.h"
@@ -52,7 +56,8 @@ Manager::~Manager() {
52 56
53/// Add a service to the manager (does not create it though) 57/// Add a service to the manager (does not create it though)
54void Manager::AddService(Interface* service) { 58void Manager::AddService(Interface* service) {
55 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);
56 m_services.push_back(service); 61 m_services.push_back(service);
57} 62}
58 63
@@ -66,7 +71,7 @@ void Manager::DeleteService(const std::string& port_name) {
66 71
67/// Get a Service Interface from its Handle 72/// Get a Service Interface from its Handle
68Interface* Manager::FetchFromHandle(Handle handle) { 73Interface* Manager::FetchFromHandle(Handle handle) {
69 return Kernel::g_object_pool.Get<Interface>(handle); 74 return Kernel::g_handle_table.Get<Interface>(handle);
70} 75}
71 76
72/// Get a Service Interface from its port 77/// Get a Service Interface from its port
@@ -88,8 +93,10 @@ void Init() {
88 93
89 g_manager->AddService(new SRV::Interface); 94 g_manager->AddService(new SRV::Interface);
90 g_manager->AddService(new AC_U::Interface); 95 g_manager->AddService(new AC_U::Interface);
96 g_manager->AddService(new ACT_U::Interface);
91 g_manager->AddService(new AM_APP::Interface); 97 g_manager->AddService(new AM_APP::Interface);
92 g_manager->AddService(new AM_NET::Interface); 98 g_manager->AddService(new AM_NET::Interface);
99 g_manager->AddService(new APT_A::Interface);
93 g_manager->AddService(new APT_U::Interface); 100 g_manager->AddService(new APT_U::Interface);
94 g_manager->AddService(new BOSS_U::Interface); 101 g_manager->AddService(new BOSS_U::Interface);
95 g_manager->AddService(new CECD_U::Interface); 102 g_manager->AddService(new CECD_U::Interface);
@@ -102,12 +109,14 @@ void Init() {
102 g_manager->AddService(new FS::FSUserInterface); 109 g_manager->AddService(new FS::FSUserInterface);
103 g_manager->AddService(new GSP_GPU::Interface); 110 g_manager->AddService(new GSP_GPU::Interface);
104 g_manager->AddService(new HID_User::Interface); 111 g_manager->AddService(new HID_User::Interface);
112 g_manager->AddService(new HTTP_C::Interface);
105 g_manager->AddService(new IR_RST::Interface); 113 g_manager->AddService(new IR_RST::Interface);
106 g_manager->AddService(new IR_U::Interface); 114 g_manager->AddService(new IR_U::Interface);
107 g_manager->AddService(new LDR_RO::Interface); 115 g_manager->AddService(new LDR_RO::Interface);
108 g_manager->AddService(new MIC_U::Interface); 116 g_manager->AddService(new MIC_U::Interface);
109 g_manager->AddService(new NIM_AOC::Interface);
110 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);
111 g_manager->AddService(new NWM_UDS::Interface); 120 g_manager->AddService(new NWM_UDS::Interface);
112 g_manager->AddService(new PM_APP::Interface); 121 g_manager->AddService(new PM_APP::Interface);
113 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 0616822fa..28b4ccd17 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -54,7 +54,8 @@ public:
54 54
55 /// Allocates a new handle for the service 55 /// Allocates a new handle for the service
56 Handle CreateHandle(Kernel::Object *obj) { 56 Handle CreateHandle(Kernel::Object *obj) {
57 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);
58 m_handles.push_back(handle); 59 m_handles.push_back(handle);
59 return handle; 60 return handle;
60 } 61 }
@@ -62,7 +63,7 @@ public:
62 /// Frees a handle from the service 63 /// Frees a handle from the service
63 template <class T> 64 template <class T>
64 void DeleteHandle(const Handle handle) { 65 void DeleteHandle(const Handle handle) {
65 Kernel::g_object_pool.Destroy<T>(handle); 66 Kernel::g_handle_table.Close(handle);
66 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());
67 } 68 }
68 69
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index 03deabe43..ef4f9829d 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -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 5c9623730..2edf3b482 100644
--- a/src/core/hle/service/soc_u.h
+++ b/src/core/hle/service/soc_u.h
@@ -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 05ff1846b..25fab1a4f 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -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 4f3e01aca..653aba5cb 100644
--- a/src/core/hle/service/srv.h
+++ b/src/core/hle/service/srv.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 d5b0c4b06..360516cdf 100644
--- a/src/core/hle/service/ssl_c.cpp
+++ b/src/core/hle/service/ssl_c.cpp
@@ -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 6281503a5..58e87c1cb 100644
--- a/src/core/hle/service/ssl_c.h
+++ b/src/core/hle/service/ssl_c.h
@@ -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 c98168e51..25944fc68 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -92,7 +92,7 @@ static Result ConnectToPort(Handle* out, const char* port_name) {
92 92
93/// Synchronize to an OS service 93/// Synchronize to an OS service
94static Result SendSyncRequest(Handle handle) { 94static Result SendSyncRequest(Handle handle) {
95 Kernel::Session* session = Kernel::g_object_pool.Get<Kernel::Session>(handle); 95 Kernel::Session* session = Kernel::g_handle_table.Get<Kernel::Session>(handle);
96 if (session == nullptr) { 96 if (session == nullptr) {
97 return InvalidHandle(ErrorModule::Kernel).raw; 97 return InvalidHandle(ErrorModule::Kernel).raw;
98 } 98 }
@@ -119,11 +119,9 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
119 // TODO(bunnei): Do something with nano_seconds, currently ignoring this 119 // TODO(bunnei): Do something with nano_seconds, currently ignoring this
120 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
121 121
122 if (!Kernel::g_object_pool.IsValid(handle)) { 122 Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handle);
123 if (object == nullptr)
123 return InvalidHandle(ErrorModule::Kernel).raw; 124 return InvalidHandle(ErrorModule::Kernel).raw;
124 }
125 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
126 _dbg_assert_(Kernel, object != nullptr);
127 125
128 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(),
129 object->GetName().c_str(), nano_seconds); 127 object->GetName().c_str(), nano_seconds);
@@ -150,10 +148,9 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
150 148
151 // Iterate through each handle, synchronize kernel object 149 // Iterate through each handle, synchronize kernel object
152 for (s32 i = 0; i < handle_count; i++) { 150 for (s32 i = 0; i < handle_count; i++) {
153 if (!Kernel::g_object_pool.IsValid(handles[i])) { 151 Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handles[i]);
152 if (object == nullptr)
154 return InvalidHandle(ErrorModule::Kernel).raw; 153 return InvalidHandle(ErrorModule::Kernel).raw;
155 }
156 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]);
157 154
158 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(),
159 object->GetName().c_str()); 156 object->GetName().c_str());
@@ -321,19 +318,12 @@ static Result CreateEvent(Handle* evt, u32 reset_type) {
321 318
322/// Duplicates a kernel handle 319/// Duplicates a kernel handle
323static Result DuplicateHandle(Handle* out, Handle handle) { 320static Result DuplicateHandle(Handle* out, Handle handle) {
324 LOG_WARNING(Kernel_SVC, "(STUBBED) called handle=0x%08X", handle); 321 ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle);
325 322 if (out_h.Succeeded()) {
326 // Translate kernel handles -> real handles 323 *out = *out_h;
327 if (handle == Kernel::CurrentThread) { 324 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
328 handle = Kernel::GetCurrentThreadHandle();
329 } 325 }
330 _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess), 326 return out_h.Code().raw;
331 "(UNIMPLEMENTED) process handle duplication!");
332
333 // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate.
334 *out = handle;
335
336 return 0;
337} 327}
338 328
339/// Signals an event 329/// Signals an event
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index 67a8bc324..dd619cb16 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -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 68f11bfcb..292f496c1 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -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/settings.h b/src/core/settings.h
index 4808872ae..4b8928847 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -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/video_core/clipper.cpp b/src/video_core/clipper.cpp
index 0bcd0b895..1744066ba 100644
--- a/src/video_core/clipper.cpp
+++ b/src/video_core/clipper.cpp
@@ -2,7 +2,7 @@
2// Licensed under GPLv2 or any later version 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/command_processor.cpp b/src/video_core/command_processor.cpp
index 2083357fe..9602779f4 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -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);
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 328386b7e..5921185a6 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -304,7 +304,6 @@ std::unique_ptr<PicaTrace> FinishPicaTracing()
304} 304}
305 305
306const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info, bool disable_alpha) { 306const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info, bool disable_alpha) {
307
308 // Images are split into 8x8 tiles. Each tile is composed of four 4x4 subtiles each 307 // Images are split into 8x8 tiles. Each tile is composed of four 4x4 subtiles each
309 // of which is composed of four 2x2 subtiles each of which is composed of four texels. 308 // of which is composed of four 2x2 subtiles each of which is composed of four texels.
310 // Each structure is embedded into the next-bigger one in a diagonal pattern, e.g. 309 // Each structure is embedded into the next-bigger one in a diagonal pattern, e.g.
@@ -323,41 +322,39 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
323 // 02 03 06 07 18 19 22 23 322 // 02 03 06 07 18 19 22 23
324 // 00 01 04 05 16 17 20 21 323 // 00 01 04 05 16 17 20 21
325 324
326 // TODO(neobrain): Not sure if this swizzling pattern is used for all textures. 325 const unsigned int block_width = 8;
327 // To be flexible in case different but similar patterns are used, we keep this 326 const unsigned int block_height = 8;
328 // somewhat inefficient code around for now. 327
329 int texel_index_within_tile = 0; 328 const unsigned int coarse_x = x & ~7;
330 for (int block_size_index = 0; block_size_index < 3; ++block_size_index) { 329 const unsigned int coarse_y = y & ~7;
331 int sub_tile_width = 1 << block_size_index;
332 int sub_tile_height = 1 << block_size_index;
333
334 int sub_tile_index = (x & sub_tile_width) << block_size_index;
335 sub_tile_index += 2 * ((y & sub_tile_height) << block_size_index);
336 texel_index_within_tile += sub_tile_index;
337 }
338 330
339 const int block_width = 8; 331 // Interleave the lower 3 bits of each coordinate to get the intra-block offsets, which are
340 const int block_height = 8; 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;
341 338
342 int coarse_x = (x / block_width) * block_width; 339 source += coarse_y * info.stride;
343 int coarse_y = (y / block_height) * block_height; 340 const unsigned int offset = coarse_x * block_height + i;
344 341
345 switch (info.format) { 342 switch (info.format) {
346 case Regs::TextureFormat::RGBA8: 343 case Regs::TextureFormat::RGBA8:
347 { 344 {
348 const u8* source_ptr = source + coarse_x * block_height * 4 + coarse_y * info.stride + texel_index_within_tile * 4; 345 const u8* source_ptr = source + offset * 4;
349 return { source_ptr[3], source_ptr[2], source_ptr[1], disable_alpha ? (u8)255 : source_ptr[0] }; 346 return { source_ptr[3], source_ptr[2], source_ptr[1], disable_alpha ? (u8)255 : source_ptr[0] };
350 } 347 }
351 348
352 case Regs::TextureFormat::RGB8: 349 case Regs::TextureFormat::RGB8:
353 { 350 {
354 const u8* source_ptr = source + coarse_x * block_height * 3 + coarse_y * info.stride + texel_index_within_tile * 3; 351 const u8* source_ptr = source + offset * 3;
355 return { source_ptr[2], source_ptr[1], source_ptr[0], 255 }; 352 return { source_ptr[2], source_ptr[1], source_ptr[0], 255 };
356 } 353 }
357 354
358 case Regs::TextureFormat::RGBA5551: 355 case Regs::TextureFormat::RGBA5551:
359 { 356 {
360 const u16 source_ptr = *(const u16*)(source + coarse_x * block_height * 2 + coarse_y * info.stride + texel_index_within_tile * 2); 357 const u16 source_ptr = *(const u16*)(source + offset * 2);
361 u8 r = (source_ptr >> 11) & 0x1F; 358 u8 r = (source_ptr >> 11) & 0x1F;
362 u8 g = ((source_ptr) >> 6) & 0x1F; 359 u8 g = ((source_ptr) >> 6) & 0x1F;
363 u8 b = (source_ptr >> 1) & 0x1F; 360 u8 b = (source_ptr >> 1) & 0x1F;
@@ -367,7 +364,7 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
367 364
368 case Regs::TextureFormat::RGB565: 365 case Regs::TextureFormat::RGB565:
369 { 366 {
370 const u16 source_ptr = *(const u16*)(source + coarse_x * block_height * 2 + coarse_y * info.stride + texel_index_within_tile * 2); 367 const u16 source_ptr = *(const u16*)(source + offset * 2);
371 u8 r = (source_ptr >> 11) & 0x1F; 368 u8 r = (source_ptr >> 11) & 0x1F;
372 u8 g = ((source_ptr) >> 5) & 0x3F; 369 u8 g = ((source_ptr) >> 5) & 0x3F;
373 u8 b = (source_ptr) & 0x1F; 370 u8 b = (source_ptr) & 0x1F;
@@ -376,7 +373,7 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
376 373
377 case Regs::TextureFormat::RGBA4: 374 case Regs::TextureFormat::RGBA4:
378 { 375 {
379 const u8* source_ptr = source + coarse_x * block_height * 2 + coarse_y * info.stride + texel_index_within_tile * 2; 376 const u8* source_ptr = source + offset * 2;
380 u8 r = source_ptr[1] >> 4; 377 u8 r = source_ptr[1] >> 4;
381 u8 g = source_ptr[1] & 0xFF; 378 u8 g = source_ptr[1] & 0xFF;
382 u8 b = source_ptr[0] >> 4; 379 u8 b = source_ptr[0] >> 4;
@@ -390,7 +387,7 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
390 387
391 case Regs::TextureFormat::IA8: 388 case Regs::TextureFormat::IA8:
392 { 389 {
393 const u8* source_ptr = source + coarse_x * block_height * 2 + coarse_y * info.stride + texel_index_within_tile * 2; 390 const u8* source_ptr = source + offset * 2;
394 391
395 // TODO: component order not verified 392 // TODO: component order not verified
396 393
@@ -404,13 +401,13 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
404 401
405 case Regs::TextureFormat::I8: 402 case Regs::TextureFormat::I8:
406 { 403 {
407 const u8* source_ptr = source + coarse_x * block_height + coarse_y * info.stride + texel_index_within_tile; 404 const u8* source_ptr = source + offset;
408 return { *source_ptr, *source_ptr, *source_ptr, 255 }; 405 return { *source_ptr, *source_ptr, *source_ptr, 255 };
409 } 406 }
410 407
411 case Regs::TextureFormat::A8: 408 case Regs::TextureFormat::A8:
412 { 409 {
413 const u8* source_ptr = source + coarse_x * block_height + coarse_y * info.stride + texel_index_within_tile; 410 const u8* source_ptr = source + offset;
414 411
415 if (disable_alpha) { 412 if (disable_alpha) {
416 return { *source_ptr, *source_ptr, *source_ptr, 255 }; 413 return { *source_ptr, *source_ptr, *source_ptr, 255 };
@@ -421,7 +418,7 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
421 418
422 case Regs::TextureFormat::IA4: 419 case Regs::TextureFormat::IA4:
423 { 420 {
424 const u8* source_ptr = source + coarse_x * block_height / 2 + coarse_y * info.stride + texel_index_within_tile / 2; 421 const u8* source_ptr = source + offset / 2;
425 422
426 // TODO: component order not verified 423 // TODO: component order not verified
427 424
@@ -440,7 +437,7 @@ const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const Texture
440 437
441 case Regs::TextureFormat::A4: 438 case Regs::TextureFormat::A4:
442 { 439 {
443 const u8* source_ptr = source + coarse_x * block_height / 2 + coarse_y * info.stride + texel_index_within_tile / 2; 440 const u8* source_ptr = source + offset / 2;
444 441
445 // TODO: component order not verified 442 // TODO: component order not verified
446 443
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 89d97e4e9..38bac748c 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -757,6 +757,26 @@ struct float24 {
757 return float24::FromFloat32(ToFloat32() - flt.ToFloat32()); 757 return float24::FromFloat32(ToFloat32() - flt.ToFloat32());
758 } 758 }
759 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
760 float24 operator - () const { 780 float24 operator - () const {
761 return float24::FromFloat32(-ToFloat32()); 781 return float24::FromFloat32(-ToFloat32());
762 } 782 }
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index df1f88c79..a80148872 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -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{
@@ -177,7 +177,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
177 177
178 Math::Vec4<u8> texture_color[3]{}; 178 Math::Vec4<u8> texture_color[3]{};
179 for (int i = 0; i < 3; ++i) { 179 for (int i = 0; i < 3; ++i) {
180 auto texture = registers.GetTextures()[i]; 180 const auto& texture = textures[i];
181 if (!texture.enabled) 181 if (!texture.enabled)
182 continue; 182 continue;
183 183
@@ -219,7 +219,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
219 // 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
220 // analogously. 220 // analogously.
221 Math::Vec4<u8> combiner_output; 221 Math::Vec4<u8> combiner_output;
222 for (auto tev_stage : registers.GetTevStages()) { 222 for (const auto& tev_stage : tev_stages) {
223 using Source = Regs::TevStageConfig::Source; 223 using Source = Regs::TevStageConfig::Source;
224 using ColorModifier = Regs::TevStageConfig::ColorModifier; 224 using ColorModifier = Regs::TevStageConfig::ColorModifier;
225 using AlphaModifier = Regs::TevStageConfig::AlphaModifier; 225 using AlphaModifier = Regs::TevStageConfig::AlphaModifier;
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp
index 935fe66f0..bed5081a0 100644
--- a/src/video_core/vertex_shader.cpp
+++ b/src/video_core/vertex_shader.cpp
@@ -160,8 +160,8 @@ static void ProcessShaderCode(VertexShaderState& state) {
160 const float24* src1_ = LookupSourceRegister(instr.common.GetSrc1(is_inverted) + address_offset); 160 const float24* src1_ = LookupSourceRegister(instr.common.GetSrc1(is_inverted) + address_offset);
161 const float24* src2_ = LookupSourceRegister(instr.common.GetSrc2(is_inverted)); 161 const float24* src2_ = LookupSourceRegister(instr.common.GetSrc2(is_inverted));
162 162
163 const bool negate_src1 = (swizzle.negate_src1 != false); 163 const bool negate_src1 = ((bool)swizzle.negate_src1 != false);
164 const bool negate_src2 = (swizzle.negate_src2 != false); 164 const bool negate_src2 = ((bool)swizzle.negate_src2 != false);
165 165
166 float24 src1[4] = { 166 float24 src1[4] = {
167 src1_[(int)swizzle.GetSelectorSrc1(0)], 167 src1_[(int)swizzle.GetSelectorSrc1(0)],
@@ -385,8 +385,8 @@ static void ProcessShaderCode(VertexShaderState& state) {
385 // TODO: Do we need to consider swizzlers here? 385 // TODO: Do we need to consider swizzlers here?
386 386
387 auto flow_control = instr.flow_control; 387 auto flow_control = instr.flow_control;
388 bool results[3] = { flow_control.refx == state.conditional_code[0], 388 bool results[3] = { (bool)flow_control.refx == state.conditional_code[0],
389 flow_control.refy == state.conditional_code[1] }; 389 (bool)flow_control.refy == state.conditional_code[1] };
390 390
391 switch (flow_control.op) { 391 switch (flow_control.op) {
392 case flow_control.Or: 392 case flow_control.Or:
@@ -469,6 +469,10 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes)
469 469
470 // Setup output register table 470 // Setup output register table
471 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
472 for (int i = 0; i < 7; ++i) { 476 for (int i = 0; i < 7; ++i) {
473 const auto& output_register_map = registers.vs_output_attributes[i]; 477 const auto& output_register_map = registers.vs_output_attributes[i];
474 478