summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/arm_interface.h7
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp1290
-rw-r--r--src/core/arm/disassembler/arm_disasm.h88
-rw-r--r--src/core/arm/disassembler/load_symbol_map.cpp2
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp11
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.h7
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp6289
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp372
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.h6
-rw-r--r--src/core/arm/dyncom/arm_dyncom_trans.cpp1812
-rw-r--r--src/core/arm/dyncom/arm_dyncom_trans.h30
-rw-r--r--src/core/arm/skyeye_common/arm_regformat.h2
-rw-r--r--src/core/arm/skyeye_common/armstate.cpp233
-rw-r--r--src/core/arm/skyeye_common/armstate.h103
-rw-r--r--src/core/arm/skyeye_common/armsupp.cpp55
-rw-r--r--src/core/arm/skyeye_common/armsupp.h4
-rw-r--r--src/core/arm/skyeye_common/vfp/asm_vfp.h94
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp111
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h185
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp264
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp757
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp278
-rw-r--r--src/core/core.cpp5
-rw-r--r--src/core/core.h4
-rw-r--r--src/core/core_timing.cpp35
-rw-r--r--src/core/core_timing.h9
-rw-r--r--src/core/file_sys/archive_backend.cpp33
-rw-r--r--src/core/file_sys/archive_backend.h37
-rw-r--r--src/core/file_sys/archive_extsavedata.cpp21
-rw-r--r--src/core/file_sys/archive_extsavedata.h14
-rw-r--r--src/core/file_sys/archive_romfs.cpp7
-rw-r--r--src/core/file_sys/archive_romfs.h4
-rw-r--r--src/core/file_sys/archive_savedata.cpp33
-rw-r--r--src/core/file_sys/archive_savedata.h4
-rw-r--r--src/core/file_sys/archive_savedatacheck.cpp15
-rw-r--r--src/core/file_sys/archive_savedatacheck.h4
-rw-r--r--src/core/file_sys/archive_sdmc.cpp6
-rw-r--r--src/core/file_sys/archive_sdmc.h4
-rw-r--r--src/core/file_sys/archive_systemsavedata.cpp9
-rw-r--r--src/core/file_sys/archive_systemsavedata.h7
-rw-r--r--src/core/file_sys/directory_backend.h21
-rw-r--r--src/core/file_sys/disk_archive.cpp49
-rw-r--r--src/core/file_sys/disk_archive.h10
-rw-r--r--src/core/file_sys/file_backend.h9
-rw-r--r--src/core/file_sys/ivfc_archive.cpp34
-rw-r--r--src/core/file_sys/ivfc_archive.h32
-rw-r--r--src/core/gdbstub/gdbstub.cpp101
-rw-r--r--src/core/gdbstub/gdbstub.h14
-rw-r--r--src/core/hle/applets/applet.cpp32
-rw-r--r--src/core/hle/applets/applet.h9
-rw-r--r--src/core/hle/applets/erreula.cpp12
-rw-r--r--src/core/hle/applets/erreula.h11
-rw-r--r--src/core/hle/applets/mii_selector.cpp16
-rw-r--r--src/core/hle/applets/mii_selector.h39
-rw-r--r--src/core/hle/applets/swkbd.cpp20
-rw-r--r--src/core/hle/applets/swkbd.h13
-rw-r--r--src/core/hle/config_mem.cpp2
-rw-r--r--src/core/hle/config_mem.h25
-rw-r--r--src/core/hle/function_wrappers.h103
-rw-r--r--src/core/hle/hle.cpp6
-rw-r--r--src/core/hle/hle.h2
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp26
-rw-r--r--src/core/hle/kernel/address_arbiter.h14
-rw-r--r--src/core/hle/kernel/client_port.cpp6
-rw-r--r--src/core/hle/kernel/client_port.h22
-rw-r--r--src/core/hle/kernel/event.cpp10
-rw-r--r--src/core/hle/kernel/event.h19
-rw-r--r--src/core/hle/kernel/kernel.cpp3
-rw-r--r--src/core/hle/kernel/kernel.h66
-rw-r--r--src/core/hle/kernel/memory.cpp22
-rw-r--r--src/core/hle/kernel/memory.h1
-rw-r--r--src/core/hle/kernel/mutex.cpp6
-rw-r--r--src/core/hle/kernel/mutex.h18
-rw-r--r--src/core/hle/kernel/process.cpp65
-rw-r--r--src/core/hle/kernel/process.h50
-rw-r--r--src/core/hle/kernel/resource_limit.cpp114
-rw-r--r--src/core/hle/kernel/resource_limit.h44
-rw-r--r--src/core/hle/kernel/semaphore.cpp8
-rw-r--r--src/core/hle/kernel/semaphore.h20
-rw-r--r--src/core/hle/kernel/server_port.cpp9
-rw-r--r--src/core/hle/kernel/server_port.h20
-rw-r--r--src/core/hle/kernel/session.cpp7
-rw-r--r--src/core/hle/kernel/session.h61
-rw-r--r--src/core/hle/kernel/shared_memory.cpp75
-rw-r--r--src/core/hle/kernel/shared_memory.h59
-rw-r--r--src/core/hle/kernel/thread.cpp114
-rw-r--r--src/core/hle/kernel/thread.h78
-rw-r--r--src/core/hle/kernel/timer.cpp19
-rw-r--r--src/core/hle/kernel/timer.h22
-rw-r--r--src/core/hle/kernel/vm_manager.cpp36
-rw-r--r--src/core/hle/kernel/vm_manager.h21
-rw-r--r--src/core/hle/result.h100
-rw-r--r--src/core/hle/service/ac_u.cpp38
-rw-r--r--src/core/hle/service/am/am.cpp53
-rw-r--r--src/core/hle/service/am/am_app.cpp16
-rw-r--r--src/core/hle/service/am/am_net.cpp110
-rw-r--r--src/core/hle/service/am/am_sys.cpp44
-rw-r--r--src/core/hle/service/am/am_u.cpp70
-rw-r--r--src/core/hle/service/apt/apt.cpp148
-rw-r--r--src/core/hle/service/apt/apt.h95
-rw-r--r--src/core/hle/service/apt/apt_a.cpp57
-rw-r--r--src/core/hle/service/apt/apt_s.cpp171
-rw-r--r--src/core/hle/service/apt/apt_u.cpp177
-rw-r--r--src/core/hle/service/boss/boss.cpp2
-rw-r--r--src/core/hle/service/boss/boss_p.cpp2
-rw-r--r--src/core/hle/service/boss/boss_u.cpp8
-rw-r--r--src/core/hle/service/cam/cam.cpp75
-rw-r--r--src/core/hle/service/cam/cam.h69
-rw-r--r--src/core/hle/service/cam/cam_c.cpp4
-rw-r--r--src/core/hle/service/cam/cam_q.cpp4
-rw-r--r--src/core/hle/service/cam/cam_s.cpp4
-rw-r--r--src/core/hle/service/cam/cam_u.cpp124
-rw-r--r--src/core/hle/service/cecd/cecd.cpp9
-rw-r--r--src/core/hle/service/cecd/cecd.h10
-rw-r--r--src/core/hle/service/cecd/cecd_s.cpp4
-rw-r--r--src/core/hle/service/cecd/cecd_u.cpp6
-rw-r--r--src/core/hle/service/cfg/cfg.cpp191
-rw-r--r--src/core/hle/service/cfg/cfg.h12
-rw-r--r--src/core/hle/service/cfg/cfg_i.cpp84
-rw-r--r--src/core/hle/service/cfg/cfg_s.cpp38
-rw-r--r--src/core/hle/service/cfg/cfg_u.cpp20
-rw-r--r--src/core/hle/service/csnd_snd.cpp34
-rw-r--r--src/core/hle/service/csnd_snd.h2
-rw-r--r--src/core/hle/service/dlp/dlp.cpp2
-rw-r--r--src/core/hle/service/dlp/dlp_clnt.cpp3
-rw-r--r--src/core/hle/service/dlp/dlp_fkcl.cpp3
-rw-r--r--src/core/hle/service/dlp/dlp_srvr.cpp10
-rw-r--r--src/core/hle/service/dsp_dsp.cpp153
-rw-r--r--src/core/hle/service/err_f.cpp129
-rw-r--r--src/core/hle/service/frd/frd.cpp20
-rw-r--r--src/core/hle/service/frd/frd_a.cpp2
-rw-r--r--src/core/hle/service/frd/frd_u.cpp104
-rw-r--r--src/core/hle/service/fs/archive.cpp389
-rw-r--r--src/core/hle/service/fs/archive.h65
-rw-r--r--src/core/hle/service/fs/fs_user.cpp386
-rw-r--r--src/core/hle/service/gsp_gpu.cpp247
-rw-r--r--src/core/hle/service/gsp_gpu.h40
-rw-r--r--src/core/hle/service/gsp_lcd.cpp12
-rw-r--r--src/core/hle/service/hid/hid.cpp47
-rw-r--r--src/core/hle/service/hid/hid.h69
-rw-r--r--src/core/hle/service/hid/hid_spvr.cpp18
-rw-r--r--src/core/hle/service/hid/hid_user.cpp18
-rw-r--r--src/core/hle/service/http_c.cpp100
-rw-r--r--src/core/hle/service/ir/ir.cpp28
-rw-r--r--src/core/hle/service/ir/ir_rst.cpp8
-rw-r--r--src/core/hle/service/ir/ir_u.cpp27
-rw-r--r--src/core/hle/service/ir/ir_user.cpp50
-rw-r--r--src/core/hle/service/ldr_ro/cro_helper.cpp375
-rw-r--r--src/core/hle/service/ldr_ro/cro_helper.h145
-rw-r--r--src/core/hle/service/ldr_ro/ldr_ro.cpp208
-rw-r--r--src/core/hle/service/ldr_ro/memory_synchronizer.cpp5
-rw-r--r--src/core/hle/service/mic_u.cpp32
-rw-r--r--src/core/hle/service/ndm/ndm.cpp20
-rw-r--r--src/core/hle/service/ndm/ndm.h42
-rw-r--r--src/core/hle/service/ndm/ndm_u.cpp44
-rw-r--r--src/core/hle/service/news/news.cpp2
-rw-r--r--src/core/hle/service/news/news_s.cpp26
-rw-r--r--src/core/hle/service/news/news_u.cpp2
-rw-r--r--src/core/hle/service/nim/nim.cpp2
-rw-r--r--src/core/hle/service/nim/nim_aoc.cpp16
-rw-r--r--src/core/hle/service/nim/nim_s.cpp9
-rw-r--r--src/core/hle/service/nim/nim_u.cpp13
-rw-r--r--src/core/hle/service/ns_s.cpp30
-rw-r--r--src/core/hle/service/nwm_uds.cpp82
-rw-r--r--src/core/hle/service/pm_app.cpp24
-rw-r--r--src/core/hle/service/ptm/ptm.cpp31
-rw-r--r--src/core/hle/service/ptm/ptm.h21
-rw-r--r--src/core/hle/service/ptm/ptm_play.cpp8
-rw-r--r--src/core/hle/service/ptm/ptm_play.h6
-rw-r--r--src/core/hle/service/ptm/ptm_sysm.cpp62
-rw-r--r--src/core/hle/service/ptm/ptm_u.cpp28
-rw-r--r--src/core/hle/service/service.cpp23
-rw-r--r--src/core/hle/service/service.h10
-rw-r--r--src/core/hle/service/soc_u.cpp378
-rw-r--r--src/core/hle/service/srv.cpp50
-rw-r--r--src/core/hle/service/ssl_c.cpp44
-rw-r--r--src/core/hle/service/y2r_u.cpp155
-rw-r--r--src/core/hle/shared_page.cpp7
-rw-r--r--src/core/hle/shared_page.h23
-rw-r--r--src/core/hle/svc.cpp512
-rw-r--r--src/core/hw/gpu.cpp142
-rw-r--r--src/core/hw/gpu.h84
-rw-r--r--src/core/hw/hw.cpp13
-rw-r--r--src/core/hw/hw.h42
-rw-r--r--src/core/hw/lcd.cpp13
-rw-r--r--src/core/hw/lcd.h19
-rw-r--r--src/core/hw/y2r.cpp77
-rw-r--r--src/core/hw/y2r.h3
-rw-r--r--src/core/loader/3dsx.cpp85
-rw-r--r--src/core/loader/3dsx.h9
-rw-r--r--src/core/loader/elf.cpp231
-rw-r--r--src/core/loader/elf.h3
-rw-r--r--src/core/loader/loader.cpp15
-rw-r--r--src/core/loader/loader.h11
-rw-r--r--src/core/loader/ncch.cpp62
-rw-r--r--src/core/loader/ncch.h39
-rw-r--r--src/core/loader/smdh.h2
-rw-r--r--src/core/memory.cpp84
-rw-r--r--src/core/memory.h70
-rw-r--r--src/core/memory_setup.h1
-rw-r--r--src/core/mmio.h1
-rw-r--r--src/core/settings.cpp1
-rw-r--r--src/core/settings.h51
-rw-r--r--src/core/system.cpp6
-rw-r--r--src/core/system.h9
-rw-r--r--src/core/tracer/citrace.h12
-rw-r--r--src/core/tracer/recorder.cpp140
-rw-r--r--src/core/tracer/recorder.h2
208 files changed, 10705 insertions, 10514 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 480c90e66..919da6737 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -9,7 +9,7 @@
9#include "core/arm/skyeye_common/vfp/asm_vfp.h" 9#include "core/arm/skyeye_common/vfp/asm_vfp.h"
10 10
11namespace Core { 11namespace Core {
12 struct ThreadContext; 12struct ThreadContext;
13} 13}
14 14
15/// Generic ARM11 CPU interface 15/// Generic ARM11 CPU interface
@@ -141,10 +141,10 @@ public:
141 return num_instructions; 141 return num_instructions;
142 } 142 }
143 143
144 s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event, decreased by the cpu run loop 144 s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event,
145 /// decreased by the cpu run loop
145 146
146protected: 147protected:
147
148 /** 148 /**
149 * Executes the given number of instructions 149 * Executes the given number of instructions
150 * @param num_instructions Number of instructions to executes 150 * @param num_instructions Number of instructions to executes
@@ -152,6 +152,5 @@ protected:
152 virtual void ExecuteInstructions(int num_instructions) = 0; 152 virtual void ExecuteInstructions(int num_instructions) = 0;
153 153
154private: 154private:
155
156 u64 num_instructions = 0; ///< Number of instructions executed 155 u64 num_instructions = 0; ///< Number of instructions executed
157}; 156};
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp
index 5ad1f1c29..b3b9971e8 100644
--- a/src/core/arm/disassembler/arm_disasm.cpp
+++ b/src/core/arm/disassembler/arm_disasm.cpp
@@ -9,401 +9,225 @@
9#include "core/arm/disassembler/arm_disasm.h" 9#include "core/arm/disassembler/arm_disasm.h"
10#include "core/arm/skyeye_common/armsupp.h" 10#include "core/arm/skyeye_common/armsupp.h"
11 11
12static const char *cond_names[] = { 12static const char* cond_names[] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
13 "eq", 13 "hi", "ls", "ge", "lt", "gt", "le", "", "RESERVED"};
14 "ne", 14
15 "cs", 15static const char* opcode_names[] = {
16 "cc", 16 "invalid", "undefined", "adc", "add", "and", "b", "bl", "bic",
17 "mi", 17 "bkpt", "blx", "bx", "cdp", "clrex", "clz", "cmn", "cmp",
18 "pl", 18 "eor", "ldc", "ldm", "ldr", "ldrb", "ldrbt", "ldrex", "ldrexb",
19 "vs", 19 "ldrexd", "ldrexh", "ldrh", "ldrsb", "ldrsh", "ldrt", "mcr", "mla",
20 "vc", 20 "mov", "mrc", "mrs", "msr", "mul", "mvn", "nop", "orr",
21 "hi", 21 "pkh", "pld", "qadd16", "qadd8", "qasx", "qsax", "qsub16", "qsub8",
22 "ls", 22 "rev", "rev16", "revsh", "rsb", "rsc", "sadd16", "sadd8", "sasx",
23 "ge", 23 "sbc", "sel", "sev", "shadd16", "shadd8", "shasx", "shsax", "shsub16",
24 "lt", 24 "shsub8", "smlad", "smlal", "smlald", "smlsd", "smlsld", "smmla", "smmls",
25 "gt", 25 "smmul", "smuad", "smull", "smusd", "ssat", "ssat16", "ssax", "ssub16",
26 "le", 26 "ssub8", "stc", "stm", "str", "strb", "strbt", "strex", "strexb",
27 "", 27 "strexd", "strexh", "strh", "strt", "sub", "swi", "swp", "swpb",
28 "RESERVED" 28 "sxtab", "sxtab16", "sxtah", "sxtb", "sxtb16", "sxth", "teq", "tst",
29}; 29 "uadd16", "uadd8", "uasx", "uhadd16", "uhadd8", "uhasx", "uhsax", "uhsub16",
30 30 "uhsub8", "umlal", "umull", "uqadd16", "uqadd8", "uqasx", "uqsax", "uqsub16",
31static const char *opcode_names[] = { 31 "uqsub8", "usad8", "usada8", "usat", "usat16", "usax", "usub16", "usub8",
32 "invalid", 32 "uxtab", "uxtab16", "uxtah", "uxtb", "uxtb16", "uxth", "wfe", "wfi",
33 "undefined",
34 "adc",
35 "add",
36 "and",
37 "b",
38 "bl",
39 "bic",
40 "bkpt",
41 "blx",
42 "bx",
43 "cdp",
44 "clrex",
45 "clz",
46 "cmn",
47 "cmp",
48 "eor",
49 "ldc",
50 "ldm",
51 "ldr",
52 "ldrb",
53 "ldrbt",
54 "ldrex",
55 "ldrexb",
56 "ldrexd",
57 "ldrexh",
58 "ldrh",
59 "ldrsb",
60 "ldrsh",
61 "ldrt",
62 "mcr",
63 "mla",
64 "mov",
65 "mrc",
66 "mrs",
67 "msr",
68 "mul",
69 "mvn",
70 "nop",
71 "orr",
72 "pkh",
73 "pld",
74 "qadd16",
75 "qadd8",
76 "qasx",
77 "qsax",
78 "qsub16",
79 "qsub8",
80 "rev",
81 "rev16",
82 "revsh",
83 "rsb",
84 "rsc",
85 "sadd16",
86 "sadd8",
87 "sasx",
88 "sbc",
89 "sel",
90 "sev",
91 "shadd16",
92 "shadd8",
93 "shasx",
94 "shsax",
95 "shsub16",
96 "shsub8",
97 "smlad",
98 "smlal",
99 "smlald",
100 "smlsd",
101 "smlsld",
102 "smmla",
103 "smmls",
104 "smmul",
105 "smuad",
106 "smull",
107 "smusd",
108 "ssat",
109 "ssat16",
110 "ssax",
111 "ssub16",
112 "ssub8",
113 "stc",
114 "stm",
115 "str",
116 "strb",
117 "strbt",
118 "strex",
119 "strexb",
120 "strexd",
121 "strexh",
122 "strh",
123 "strt",
124 "sub",
125 "swi",
126 "swp",
127 "swpb",
128 "sxtab",
129 "sxtab16",
130 "sxtah",
131 "sxtb",
132 "sxtb16",
133 "sxth",
134 "teq",
135 "tst",
136 "uadd16",
137 "uadd8",
138 "uasx",
139 "uhadd16",
140 "uhadd8",
141 "uhasx",
142 "uhsax",
143 "uhsub16",
144 "uhsub8",
145 "umlal",
146 "umull",
147 "uqadd16",
148 "uqadd8",
149 "uqasx",
150 "uqsax",
151 "uqsub16",
152 "uqsub8",
153 "usad8",
154 "usada8",
155 "usat",
156 "usat16",
157 "usax",
158 "usub16",
159 "usub8",
160 "uxtab",
161 "uxtab16",
162 "uxtah",
163 "uxtb",
164 "uxtb16",
165 "uxth",
166 "wfe",
167 "wfi",
168 "yield", 33 "yield",
169 34
170 "undefined", 35 "undefined", "adc", "add", "and", "asr", "b", "bic", "bkpt",
171 "adc", 36 "bl", "blx", "bx", "cmn", "cmp", "eor", "ldmia", "ldr",
172 "add", 37 "ldrb", "ldrh", "ldrsb", "ldrsh", "lsl", "lsr", "mov", "mul",
173 "and", 38 "mvn", "neg", "orr", "pop", "push", "ror", "sbc", "stmia",
174 "asr", 39 "str", "strb", "strh", "sub", "swi", "tst",
175 "b", 40
176 "bic", 41 nullptr};
177 "bkpt",
178 "bl",
179 "blx",
180 "bx",
181 "cmn",
182 "cmp",
183 "eor",
184 "ldmia",
185 "ldr",
186 "ldrb",
187 "ldrh",
188 "ldrsb",
189 "ldrsh",
190 "lsl",
191 "lsr",
192 "mov",
193 "mul",
194 "mvn",
195 "neg",
196 "orr",
197 "pop",
198 "push",
199 "ror",
200 "sbc",
201 "stmia",
202 "str",
203 "strb",
204 "strh",
205 "sub",
206 "swi",
207 "tst",
208
209 nullptr
210};
211 42
212// Indexed by the shift type (bits 6-5) 43// Indexed by the shift type (bits 6-5)
213static const char *shift_names[] = { 44static const char* shift_names[] = {"LSL", "LSR", "ASR", "ROR"};
214 "LSL",
215 "LSR",
216 "ASR",
217 "ROR"
218};
219 45
220static const char* cond_to_str(u32 cond) { 46static const char* cond_to_str(u32 cond) {
221 return cond_names[cond]; 47 return cond_names[cond];
222} 48}
223 49
224std::string ARM_Disasm::Disassemble(u32 addr, u32 insn) 50std::string ARM_Disasm::Disassemble(u32 addr, u32 insn) {
225{
226 Opcode opcode = Decode(insn); 51 Opcode opcode = Decode(insn);
227 switch (opcode) { 52 switch (opcode) {
228 case OP_INVALID: 53 case OP_INVALID:
229 return "Invalid"; 54 return "Invalid";
230 case OP_UNDEFINED: 55 case OP_UNDEFINED:
231 return "Undefined"; 56 return "Undefined";
232 case OP_ADC: 57 case OP_ADC:
233 case OP_ADD: 58 case OP_ADD:
234 case OP_AND: 59 case OP_AND:
235 case OP_BIC: 60 case OP_BIC:
236 case OP_CMN: 61 case OP_CMN:
237 case OP_CMP: 62 case OP_CMP:
238 case OP_EOR: 63 case OP_EOR:
239 case OP_MOV: 64 case OP_MOV:
240 case OP_MVN: 65 case OP_MVN:
241 case OP_ORR: 66 case OP_ORR:
242 case OP_RSB: 67 case OP_RSB:
243 case OP_RSC: 68 case OP_RSC:
244 case OP_SBC: 69 case OP_SBC:
245 case OP_SUB: 70 case OP_SUB:
246 case OP_TEQ: 71 case OP_TEQ:
247 case OP_TST: 72 case OP_TST:
248 return DisassembleALU(opcode, insn); 73 return DisassembleALU(opcode, insn);
249 case OP_B: 74 case OP_B:
250 case OP_BL: 75 case OP_BL:
251 return DisassembleBranch(addr, opcode, insn); 76 return DisassembleBranch(addr, opcode, insn);
252 case OP_BKPT: 77 case OP_BKPT:
253 return DisassembleBKPT(insn); 78 return DisassembleBKPT(insn);
254 case OP_BLX: 79 case OP_BLX:
255 // not supported yet 80 // not supported yet
256 break; 81 break;
257 case OP_BX: 82 case OP_BX:
258 return DisassembleBX(insn); 83 return DisassembleBX(insn);
259 case OP_CDP: 84 case OP_CDP:
260 return "cdp"; 85 return "cdp";
261 case OP_CLREX: 86 case OP_CLREX:
262 return "clrex"; 87 return "clrex";
263 case OP_CLZ: 88 case OP_CLZ:
264 return DisassembleCLZ(insn); 89 return DisassembleCLZ(insn);
265 case OP_LDC: 90 case OP_LDC:
266 return "ldc"; 91 return "ldc";
267 case OP_LDM: 92 case OP_LDM:
268 case OP_STM: 93 case OP_STM:
269 return DisassembleMemblock(opcode, insn); 94 return DisassembleMemblock(opcode, insn);
270 case OP_LDR: 95 case OP_LDR:
271 case OP_LDRB: 96 case OP_LDRB:
272 case OP_LDRBT: 97 case OP_LDRBT:
273 case OP_LDRT: 98 case OP_LDRT:
274 case OP_STR: 99 case OP_STR:
275 case OP_STRB: 100 case OP_STRB:
276 case OP_STRBT: 101 case OP_STRBT:
277 case OP_STRT: 102 case OP_STRT:
278 return DisassembleMem(insn); 103 return DisassembleMem(insn);
279 case OP_LDREX: 104 case OP_LDREX:
280 case OP_LDREXB: 105 case OP_LDREXB:
281 case OP_LDREXD: 106 case OP_LDREXD:
282 case OP_LDREXH: 107 case OP_LDREXH:
283 case OP_STREX: 108 case OP_STREX:
284 case OP_STREXB: 109 case OP_STREXB:
285 case OP_STREXD: 110 case OP_STREXD:
286 case OP_STREXH: 111 case OP_STREXH:
287 return DisassembleREX(opcode, insn); 112 return DisassembleREX(opcode, insn);
288 case OP_LDRH: 113 case OP_LDRH:
289 case OP_LDRSB: 114 case OP_LDRSB:
290 case OP_LDRSH: 115 case OP_LDRSH:
291 case OP_STRH: 116 case OP_STRH:
292 return DisassembleMemHalf(insn); 117 return DisassembleMemHalf(insn);
293 case OP_MCR: 118 case OP_MCR:
294 case OP_MRC: 119 case OP_MRC:
295 return DisassembleMCR(opcode, insn); 120 return DisassembleMCR(opcode, insn);
296 case OP_MLA: 121 case OP_MLA:
297 return DisassembleMLA(opcode, insn); 122 return DisassembleMLA(opcode, insn);
298 case OP_MRS: 123 case OP_MRS:
299 return DisassembleMRS(insn); 124 return DisassembleMRS(insn);
300 case OP_MSR: 125 case OP_MSR:
301 return DisassembleMSR(insn); 126 return DisassembleMSR(insn);
302 case OP_MUL: 127 case OP_MUL:
303 return DisassembleMUL(opcode, insn); 128 return DisassembleMUL(opcode, insn);
304 case OP_NOP: 129 case OP_NOP:
305 case OP_SEV: 130 case OP_SEV:
306 case OP_WFE: 131 case OP_WFE:
307 case OP_WFI: 132 case OP_WFI:
308 case OP_YIELD: 133 case OP_YIELD:
309 return DisassembleNoOperands(opcode, insn); 134 return DisassembleNoOperands(opcode, insn);
310 case OP_PKH: 135 case OP_PKH:
311 return DisassemblePKH(insn); 136 return DisassemblePKH(insn);
312 case OP_PLD: 137 case OP_PLD:
313 return DisassemblePLD(insn); 138 return DisassemblePLD(insn);
314 case OP_QADD16: 139 case OP_QADD16:
315 case OP_QADD8: 140 case OP_QADD8:
316 case OP_QASX: 141 case OP_QASX:
317 case OP_QSAX: 142 case OP_QSAX:
318 case OP_QSUB16: 143 case OP_QSUB16:
319 case OP_QSUB8: 144 case OP_QSUB8:
320 case OP_SADD16: 145 case OP_SADD16:
321 case OP_SADD8: 146 case OP_SADD8:
322 case OP_SASX: 147 case OP_SASX:
323 case OP_SHADD16: 148 case OP_SHADD16:
324 case OP_SHADD8: 149 case OP_SHADD8:
325 case OP_SHASX: 150 case OP_SHASX:
326 case OP_SHSAX: 151 case OP_SHSAX:
327 case OP_SHSUB16: 152 case OP_SHSUB16:
328 case OP_SHSUB8: 153 case OP_SHSUB8:
329 case OP_SSAX: 154 case OP_SSAX:
330 case OP_SSUB16: 155 case OP_SSUB16:
331 case OP_SSUB8: 156 case OP_SSUB8:
332 case OP_UADD16: 157 case OP_UADD16:
333 case OP_UADD8: 158 case OP_UADD8:
334 case OP_UASX: 159 case OP_UASX:
335 case OP_UHADD16: 160 case OP_UHADD16:
336 case OP_UHADD8: 161 case OP_UHADD8:
337 case OP_UHASX: 162 case OP_UHASX:
338 case OP_UHSAX: 163 case OP_UHSAX:
339 case OP_UHSUB16: 164 case OP_UHSUB16:
340 case OP_UHSUB8: 165 case OP_UHSUB8:
341 case OP_UQADD16: 166 case OP_UQADD16:
342 case OP_UQADD8: 167 case OP_UQADD8:
343 case OP_UQASX: 168 case OP_UQASX:
344 case OP_UQSAX: 169 case OP_UQSAX:
345 case OP_UQSUB16: 170 case OP_UQSUB16:
346 case OP_UQSUB8: 171 case OP_UQSUB8:
347 case OP_USAX: 172 case OP_USAX:
348 case OP_USUB16: 173 case OP_USUB16:
349 case OP_USUB8: 174 case OP_USUB8:
350 return DisassembleParallelAddSub(opcode, insn); 175 return DisassembleParallelAddSub(opcode, insn);
351 case OP_REV: 176 case OP_REV:
352 case OP_REV16: 177 case OP_REV16:
353 case OP_REVSH: 178 case OP_REVSH:
354 return DisassembleREV(opcode, insn); 179 return DisassembleREV(opcode, insn);
355 case OP_SEL: 180 case OP_SEL:
356 return DisassembleSEL(insn); 181 return DisassembleSEL(insn);
357 case OP_SMLAD: 182 case OP_SMLAD:
358 case OP_SMLALD: 183 case OP_SMLALD:
359 case OP_SMLSD: 184 case OP_SMLSD:
360 case OP_SMLSLD: 185 case OP_SMLSLD:
361 case OP_SMMLA: 186 case OP_SMMLA:
362 case OP_SMMLS: 187 case OP_SMMLS:
363 case OP_SMMUL: 188 case OP_SMMUL:
364 case OP_SMUAD: 189 case OP_SMUAD:
365 case OP_SMUSD: 190 case OP_SMUSD:
366 case OP_USAD8: 191 case OP_USAD8:
367 case OP_USADA8: 192 case OP_USADA8:
368 return DisassembleMediaMulDiv(opcode, insn); 193 return DisassembleMediaMulDiv(opcode, insn);
369 case OP_SSAT: 194 case OP_SSAT:
370 case OP_SSAT16: 195 case OP_SSAT16:
371 case OP_USAT: 196 case OP_USAT:
372 case OP_USAT16: 197 case OP_USAT16:
373 return DisassembleSAT(opcode, insn); 198 return DisassembleSAT(opcode, insn);
374 case OP_STC: 199 case OP_STC:
375 return "stc"; 200 return "stc";
376 case OP_SWI: 201 case OP_SWI:
377 return DisassembleSWI(insn); 202 return DisassembleSWI(insn);
378 case OP_SWP: 203 case OP_SWP:
379 case OP_SWPB: 204 case OP_SWPB:
380 return DisassembleSWP(opcode, insn); 205 return DisassembleSWP(opcode, insn);
381 case OP_SXTAB: 206 case OP_SXTAB:
382 case OP_SXTAB16: 207 case OP_SXTAB16:
383 case OP_SXTAH: 208 case OP_SXTAH:
384 case OP_SXTB: 209 case OP_SXTB:
385 case OP_SXTB16: 210 case OP_SXTB16:
386 case OP_SXTH: 211 case OP_SXTH:
387 case OP_UXTAB: 212 case OP_UXTAB:
388 case OP_UXTAB16: 213 case OP_UXTAB16:
389 case OP_UXTAH: 214 case OP_UXTAH:
390 case OP_UXTB: 215 case OP_UXTB:
391 case OP_UXTB16: 216 case OP_UXTB16:
392 case OP_UXTH: 217 case OP_UXTH:
393 return DisassembleXT(opcode, insn); 218 return DisassembleXT(opcode, insn);
394 case OP_UMLAL: 219 case OP_UMLAL:
395 case OP_UMULL: 220 case OP_UMULL:
396 case OP_SMLAL: 221 case OP_SMLAL:
397 case OP_SMULL: 222 case OP_SMULL:
398 return DisassembleUMLAL(opcode, insn); 223 return DisassembleUMLAL(opcode, insn);
399 default: 224 default:
400 return "Error"; 225 return "Error";
401 } 226 }
402 return nullptr; 227 return nullptr;
403} 228}
404 229
405std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn) 230std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn) {
406{
407 static const u8 kNoOperand1 = 1; 231 static const u8 kNoOperand1 = 1;
408 static const u8 kNoDest = 2; 232 static const u8 kNoDest = 2;
409 static const u8 kNoSbit = 4; 233 static const u8 kNoSbit = 4;
@@ -421,18 +245,18 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn)
421 245
422 const char* opname = opcode_names[opcode]; 246 const char* opname = opcode_names[opcode];
423 switch (opcode) { 247 switch (opcode) {
424 case OP_CMN: 248 case OP_CMN:
425 case OP_CMP: 249 case OP_CMP:
426 case OP_TEQ: 250 case OP_TEQ:
427 case OP_TST: 251 case OP_TST:
428 flags = kNoDest | kNoSbit; 252 flags = kNoDest | kNoSbit;
429 break; 253 break;
430 case OP_MOV: 254 case OP_MOV:
431 case OP_MVN: 255 case OP_MVN:
432 flags = kNoOperand1; 256 flags = kNoOperand1;
433 break; 257 break;
434 default: 258 default:
435 break; 259 break;
436 } 260 }
437 261
438 // The "mov" instruction ignores the first operand (rn). 262 // The "mov" instruction ignores the first operand (rn).
@@ -448,13 +272,13 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn)
448 rd_str = Common::StringFromFormat("r%d, ", rd); 272 rd_str = Common::StringFromFormat("r%d, ", rd);
449 } 273 }
450 274
451 const char *sbit_str = ""; 275 const char* sbit_str = "";
452 if (bit_s && !(flags & kNoSbit)) 276 if (bit_s && !(flags & kNoSbit))
453 sbit_str = "s"; 277 sbit_str = "s";
454 278
455 if (is_immed) { 279 if (is_immed) {
456 return Common::StringFromFormat("%s%s%s\t%s%s#%u ; 0x%x", 280 return Common::StringFromFormat("%s%s%s\t%s%s#%u ; 0x%x", opname, cond_to_str(cond),
457 opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), immed, immed); 281 sbit_str, rd_str.c_str(), rn_str.c_str(), immed, immed);
458 } 282 }
459 283
460 u8 shift_is_reg = (insn >> 4) & 1; 284 u8 shift_is_reg = (insn >> 4) & 1;
@@ -468,30 +292,28 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn)
468 rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2)); 292 rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2));
469 293
470 if (!shift_is_reg && shift_type == 0 && shift_amount == 0) { 294 if (!shift_is_reg && shift_type == 0 && shift_amount == 0) {
471 return Common::StringFromFormat("%s%s%s\t%s%sr%d", 295 return Common::StringFromFormat("%s%s%s\t%s%sr%d", opname, cond_to_str(cond), sbit_str,
472 opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm); 296 rd_str.c_str(), rn_str.c_str(), rm);
473 } 297 }
474 298
475 const char *shift_name = shift_names[shift_type]; 299 const char* shift_name = shift_names[shift_type];
476 if (shift_is_reg) { 300 if (shift_is_reg) {
477 return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s r%d", 301 return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s r%d", opname, cond_to_str(cond),
478 opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm, 302 sbit_str, rd_str.c_str(), rn_str.c_str(), rm, shift_name,
479 shift_name, rs); 303 rs);
480 } 304 }
481 if (shift_amount == 0) { 305 if (shift_amount == 0) {
482 if (shift_type == 3) { 306 if (shift_type == 3) {
483 return Common::StringFromFormat("%s%s%s\t%s%sr%d, RRX", 307 return Common::StringFromFormat("%s%s%s\t%s%sr%d, RRX", opname, cond_to_str(cond),
484 opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm); 308 sbit_str, rd_str.c_str(), rn_str.c_str(), rm);
485 } 309 }
486 shift_amount = 32; 310 shift_amount = 32;
487 } 311 }
488 return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s #%u", 312 return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s #%u", opname, cond_to_str(cond), sbit_str,
489 opname, cond_to_str(cond), sbit_str, rd_str.c_str(), rn_str.c_str(), rm, 313 rd_str.c_str(), rn_str.c_str(), rm, shift_name, shift_amount);
490 shift_name, shift_amount);
491} 314}
492 315
493std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn) 316std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn) {
494{
495 u8 cond = (insn >> 28) & 0xf; 317 u8 cond = (insn >> 28) & 0xf;
496 u32 offset = insn & 0xffffff; 318 u32 offset = insn & 0xffffff;
497 // Sign-extend the 24-bit offset 319 // Sign-extend the 24-bit offset
@@ -502,26 +324,23 @@ std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn)
502 offset <<= 2; 324 offset <<= 2;
503 offset += 8; 325 offset += 8;
504 addr += offset; 326 addr += offset;
505 const char *opname = opcode_names[opcode]; 327 const char* opname = opcode_names[opcode];
506 return Common::StringFromFormat("%s%s\t0x%x", opname, cond_to_str(cond), addr); 328 return Common::StringFromFormat("%s%s\t0x%x", opname, cond_to_str(cond), addr);
507} 329}
508 330
509std::string ARM_Disasm::DisassembleBX(u32 insn) 331std::string ARM_Disasm::DisassembleBX(u32 insn) {
510{
511 u8 cond = (insn >> 28) & 0xf; 332 u8 cond = (insn >> 28) & 0xf;
512 u8 rn = insn & 0xf; 333 u8 rn = insn & 0xf;
513 return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn); 334 return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn);
514} 335}
515 336
516std::string ARM_Disasm::DisassembleBKPT(u32 insn) 337std::string ARM_Disasm::DisassembleBKPT(u32 insn) {
517{
518 u8 cond = (insn >> 28) & 0xf; 338 u8 cond = (insn >> 28) & 0xf;
519 u32 immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf); 339 u32 immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf);
520 return Common::StringFromFormat("bkpt%s\t#%d", cond_to_str(cond), immed); 340 return Common::StringFromFormat("bkpt%s\t#%d", cond_to_str(cond), immed);
521} 341}
522 342
523std::string ARM_Disasm::DisassembleCLZ(u32 insn) 343std::string ARM_Disasm::DisassembleCLZ(u32 insn) {
524{
525 u8 cond = (insn >> 28) & 0xf; 344 u8 cond = (insn >> 28) & 0xf;
526 u8 rd = (insn >> 12) & 0xf; 345 u8 rd = (insn >> 12) & 0xf;
527 u8 rm = insn & 0xf; 346 u8 rm = insn & 0xf;
@@ -545,9 +364,8 @@ std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, u32 insn) {
545 } 364 }
546 365
547 std::string ext_reg = ""; 366 std::string ext_reg = "";
548 std::unordered_set<Opcode, std::hash<int>> with_ext_reg = { 367 std::unordered_set<Opcode, std::hash<int>> with_ext_reg = {OP_SMLAD, OP_SMLSD, OP_SMMLA,
549 OP_SMLAD, OP_SMLSD, OP_SMMLA, OP_SMMLS, OP_USADA8 368 OP_SMMLS, OP_USADA8};
550 };
551 if (with_ext_reg.find(opcode) != with_ext_reg.end()) 369 if (with_ext_reg.find(opcode) != with_ext_reg.end())
552 ext_reg = Common::StringFromFormat(", r%u", ra); 370 ext_reg = Common::StringFromFormat(", r%u", ra);
553 371
@@ -560,8 +378,7 @@ std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, u32 insn) {
560 ext_reg.c_str()); 378 ext_reg.c_str());
561} 379}
562 380
563std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn) 381std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn) {
564{
565 std::string tmp_list; 382 std::string tmp_list;
566 383
567 u8 cond = (insn >> 28) & 0xf; 384 u8 cond = (insn >> 28) & 0xf;
@@ -572,17 +389,17 @@ std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn)
572 u8 rn = (insn >> 16) & 0xf; 389 u8 rn = (insn >> 16) & 0xf;
573 u16 reg_list = insn & 0xffff; 390 u16 reg_list = insn & 0xffff;
574 391
575 const char *opname = opcode_names[opcode]; 392 const char* opname = opcode_names[opcode];
576 393
577 const char *bang = ""; 394 const char* bang = "";
578 if (write_back) 395 if (write_back)
579 bang = "!"; 396 bang = "!";
580 397
581 const char *carret = ""; 398 const char* carret = "";
582 if (bit_s) 399 if (bit_s)
583 carret = "^"; 400 carret = "^";
584 401
585 const char *comma = ""; 402 const char* comma = "";
586 tmp_list[0] = 0; 403 tmp_list[0] = 0;
587 for (int ii = 0; ii < 16; ++ii) { 404 for (int ii = 0; ii < 16; ++ii) {
588 if (reg_list & (1 << ii)) { 405 if (reg_list & (1 << ii)) {
@@ -591,7 +408,7 @@ std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn)
591 } 408 }
592 } 409 }
593 410
594 const char *addr_mode = ""; 411 const char* addr_mode = "";
595 if (is_pre) { 412 if (is_pre) {
596 if (is_up) { 413 if (is_up) {
597 addr_mode = "ib"; 414 addr_mode = "ib";
@@ -606,12 +423,11 @@ std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn)
606 } 423 }
607 } 424 }
608 425
609 return Common::StringFromFormat("%s%s%s\tr%d%s, {%s}%s", 426 return Common::StringFromFormat("%s%s%s\tr%d%s, {%s}%s", opname, cond_to_str(cond), addr_mode,
610 opname, cond_to_str(cond), addr_mode, rn, bang, tmp_list.c_str(), carret); 427 rn, bang, tmp_list.c_str(), carret);
611} 428}
612 429
613std::string ARM_Disasm::DisassembleMem(u32 insn) 430std::string ARM_Disasm::DisassembleMem(u32 insn) {
614{
615 u8 cond = (insn >> 28) & 0xf; 431 u8 cond = (insn >> 28) & 0xf;
616 u8 is_reg = (insn >> 25) & 0x1; 432 u8 is_reg = (insn >> 25) & 0x1;
617 u8 is_load = (insn >> 20) & 0x1; 433 u8 is_load = (insn >> 20) & 0x1;
@@ -623,38 +439,40 @@ std::string ARM_Disasm::DisassembleMem(u32 insn)
623 u8 rd = (insn >> 12) & 0xf; 439 u8 rd = (insn >> 12) & 0xf;
624 u16 offset = insn & 0xfff; 440 u16 offset = insn & 0xfff;
625 441
626 const char *opname = "ldr"; 442 const char* opname = "ldr";
627 if (!is_load) 443 if (!is_load)
628 opname = "str"; 444 opname = "str";
629 445
630 const char *bang = ""; 446 const char* bang = "";
631 if (write_back) 447 if (write_back)
632 bang = "!"; 448 bang = "!";
633 449
634 const char *minus = ""; 450 const char* minus = "";
635 if (is_up == 0) 451 if (is_up == 0)
636 minus = "-"; 452 minus = "-";
637 453
638 const char *byte = ""; 454 const char* byte = "";
639 if (is_byte) 455 if (is_byte)
640 byte = "b"; 456 byte = "b";
641 457
642 if (is_reg == 0) { 458 if (is_reg == 0) {
643 if (is_pre) { 459 if (is_pre) {
644 if (offset == 0) { 460 if (offset == 0) {
645 return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", 461 return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond),
646 opname, cond_to_str(cond), byte, rd, rn); 462 byte, rd, rn);
647 } else { 463 } else {
648 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", 464 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", opname,
649 opname, cond_to_str(cond), byte, rd, rn, minus, offset, bang); 465 cond_to_str(cond), byte, rd, rn, minus, offset,
466 bang);
650 } 467 }
651 } else { 468 } else {
652 const char *transfer = ""; 469 const char* transfer = "";
653 if (write_back) 470 if (write_back)
654 transfer = "t"; 471 transfer = "t";
655 472
656 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], #%s%u", 473 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], #%s%u", opname,
657 opname, cond_to_str(cond), byte, transfer, rd, rn, minus, offset); 474 cond_to_str(cond), byte, transfer, rd, rn, minus,
475 offset);
658 } 476 }
659 } 477 }
660 478
@@ -662,48 +480,47 @@ std::string ARM_Disasm::DisassembleMem(u32 insn)
662 u8 shift_type = (insn >> 5) & 0x3; 480 u8 shift_type = (insn >> 5) & 0x3;
663 u8 shift_amount = (insn >> 7) & 0x1f; 481 u8 shift_amount = (insn >> 7) & 0x1f;
664 482
665 const char *shift_name = shift_names[shift_type]; 483 const char* shift_name = shift_names[shift_type];
666 484
667 if (is_pre) { 485 if (is_pre) {
668 if (shift_amount == 0) { 486 if (shift_amount == 0) {
669 if (shift_type == 0) { 487 if (shift_type == 0) {
670 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", 488 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", opname,
671 opname, cond_to_str(cond), byte, rd, rn, minus, rm, bang); 489 cond_to_str(cond), byte, rd, rn, minus, rm, bang);
672 } 490 }
673 if (shift_type == 3) { 491 if (shift_type == 3) {
674 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, RRX]%s", 492 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, RRX]%s", opname,
675 opname, cond_to_str(cond), byte, rd, rn, minus, rm, bang); 493 cond_to_str(cond), byte, rd, rn, minus, rm, bang);
676 } 494 }
677 shift_amount = 32; 495 shift_amount = 32;
678 } 496 }
679 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, %s #%u]%s", 497 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, %s #%u]%s", opname,
680 opname, cond_to_str(cond), byte, rd, rn, minus, rm, 498 cond_to_str(cond), byte, rd, rn, minus, rm, shift_name,
681 shift_name, shift_amount, bang); 499 shift_amount, bang);
682 } 500 }
683 501
684 const char *transfer = ""; 502 const char* transfer = "";
685 if (write_back) 503 if (write_back)
686 transfer = "t"; 504 transfer = "t";
687 505
688 if (shift_amount == 0) { 506 if (shift_amount == 0) {
689 if (shift_type == 0) { 507 if (shift_type == 0) {
690 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d", 508 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d", opname,
691 opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm); 509 cond_to_str(cond), byte, transfer, rd, rn, minus, rm);
692 } 510 }
693 if (shift_type == 3) { 511 if (shift_type == 3) {
694 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, RRX", 512 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, RRX", opname,
695 opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm); 513 cond_to_str(cond), byte, transfer, rd, rn, minus, rm);
696 } 514 }
697 shift_amount = 32; 515 shift_amount = 32;
698 } 516 }
699 517
700 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, %s #%u", 518 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, %s #%u", opname,
701 opname, cond_to_str(cond), byte, transfer, rd, rn, minus, rm, 519 cond_to_str(cond), byte, transfer, rd, rn, minus, rm,
702 shift_name, shift_amount); 520 shift_name, shift_amount);
703} 521}
704 522
705std::string ARM_Disasm::DisassembleMemHalf(u32 insn) 523std::string ARM_Disasm::DisassembleMemHalf(u32 insn) {
706{
707 u8 cond = (insn >> 28) & 0xf; 524 u8 cond = (insn >> 28) & 0xf;
708 u8 is_load = (insn >> 20) & 0x1; 525 u8 is_load = (insn >> 20) & 0x1;
709 u8 write_back = (insn >> 21) & 0x1; 526 u8 write_back = (insn >> 21) & 0x1;
@@ -716,11 +533,11 @@ std::string ARM_Disasm::DisassembleMemHalf(u32 insn)
716 u8 rm = insn & 0xf; 533 u8 rm = insn & 0xf;
717 u8 offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf); 534 u8 offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf);
718 535
719 const char *opname = "ldr"; 536 const char* opname = "ldr";
720 if (is_load == 0) 537 if (is_load == 0)
721 opname = "str"; 538 opname = "str";
722 539
723 const char *width = ""; 540 const char* width = "";
724 if (bits_65 == 1) 541 if (bits_65 == 1)
725 width = "h"; 542 width = "h";
726 else if (bits_65 == 2) 543 else if (bits_65 == 2)
@@ -728,38 +545,39 @@ std::string ARM_Disasm::DisassembleMemHalf(u32 insn)
728 else 545 else
729 width = "sh"; 546 width = "sh";
730 547
731 const char *bang = ""; 548 const char* bang = "";
732 if (write_back) 549 if (write_back)
733 bang = "!"; 550 bang = "!";
734 const char *minus = ""; 551 const char* minus = "";
735 if (is_up == 0) 552 if (is_up == 0)
736 minus = "-"; 553 minus = "-";
737 554
738 if (is_immed) { 555 if (is_immed) {
739 if (is_pre) { 556 if (is_pre) {
740 if (offset == 0) { 557 if (offset == 0) {
741 return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond), width, rd, rn); 558 return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond),
559 width, rd, rn);
742 } else { 560 } else {
743 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", 561 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", opname,
744 opname, cond_to_str(cond), width, rd, rn, minus, offset, bang); 562 cond_to_str(cond), width, rd, rn, minus, offset,
563 bang);
745 } 564 }
746 } else { 565 } else {
747 return Common::StringFromFormat("%s%s%s\tr%d, [r%d], #%s%u", 566 return Common::StringFromFormat("%s%s%s\tr%d, [r%d], #%s%u", opname, cond_to_str(cond),
748 opname, cond_to_str(cond), width, rd, rn, minus, offset); 567 width, rd, rn, minus, offset);
749 } 568 }
750 } 569 }
751 570
752 if (is_pre) { 571 if (is_pre) {
753 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", 572 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", opname, cond_to_str(cond),
754 opname, cond_to_str(cond), width, rd, rn, minus, rm, bang); 573 width, rd, rn, minus, rm, bang);
755 } else { 574 } else {
756 return Common::StringFromFormat("%s%s%s\tr%d, [r%d], %sr%d", 575 return Common::StringFromFormat("%s%s%s\tr%d, [r%d], %sr%d", opname, cond_to_str(cond),
757 opname, cond_to_str(cond), width, rd, rn, minus, rm); 576 width, rd, rn, minus, rm);
758 } 577 }
759} 578}
760 579
761std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn) 580std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn) {
762{
763 u8 cond = (insn >> 28) & 0xf; 581 u8 cond = (insn >> 28) & 0xf;
764 u8 crn = (insn >> 16) & 0xf; 582 u8 crn = (insn >> 16) & 0xf;
765 u8 crd = (insn >> 12) & 0xf; 583 u8 crd = (insn >> 12) & 0xf;
@@ -767,13 +585,12 @@ std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn)
767 u8 opcode2 = (insn >> 5) & 0x7; 585 u8 opcode2 = (insn >> 5) & 0x7;
768 u8 crm = insn & 0xf; 586 u8 crm = insn & 0xf;
769 587
770 const char *opname = opcode_names[opcode]; 588 const char* opname = opcode_names[opcode];
771 return Common::StringFromFormat("%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}", 589 return Common::StringFromFormat("%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}", opname, cond_to_str(cond),
772 opname, cond_to_str(cond), cpnum, crd, crn, crm, opcode2); 590 cpnum, crd, crn, crm, opcode2);
773} 591}
774 592
775std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn) 593std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn) {
776{
777 u8 cond = (insn >> 28) & 0xf; 594 u8 cond = (insn >> 28) & 0xf;
778 u8 rd = (insn >> 16) & 0xf; 595 u8 rd = (insn >> 16) & 0xf;
779 u8 rn = (insn >> 12) & 0xf; 596 u8 rn = (insn >> 12) & 0xf;
@@ -781,13 +598,12 @@ std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn)
781 u8 rm = insn & 0xf; 598 u8 rm = insn & 0xf;
782 u8 bit_s = (insn >> 20) & 1; 599 u8 bit_s = (insn >> 20) & 1;
783 600
784 const char *opname = opcode_names[opcode]; 601 const char* opname = opcode_names[opcode];
785 return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", 602 return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", opname, cond_to_str(cond),
786 opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs, rn); 603 bit_s ? "s" : "", rd, rm, rs, rn);
787} 604}
788 605
789std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn) 606std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn) {
790{
791 u8 cond = (insn >> 28) & 0xf; 607 u8 cond = (insn >> 28) & 0xf;
792 u8 rdhi = (insn >> 16) & 0xf; 608 u8 rdhi = (insn >> 16) & 0xf;
793 u8 rdlo = (insn >> 12) & 0xf; 609 u8 rdlo = (insn >> 12) & 0xf;
@@ -795,26 +611,24 @@ std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn)
795 u8 rm = insn & 0xf; 611 u8 rm = insn & 0xf;
796 u8 bit_s = (insn >> 20) & 1; 612 u8 bit_s = (insn >> 20) & 1;
797 613
798 const char *opname = opcode_names[opcode]; 614 const char* opname = opcode_names[opcode];
799 return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", 615 return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", opname, cond_to_str(cond),
800 opname, cond_to_str(cond), bit_s ? "s" : "", rdlo, rdhi, rm, rs); 616 bit_s ? "s" : "", rdlo, rdhi, rm, rs);
801} 617}
802 618
803std::string ARM_Disasm::DisassembleMUL(Opcode opcode, u32 insn) 619std::string ARM_Disasm::DisassembleMUL(Opcode opcode, u32 insn) {
804{
805 u8 cond = (insn >> 28) & 0xf; 620 u8 cond = (insn >> 28) & 0xf;
806 u8 rd = (insn >> 16) & 0xf; 621 u8 rd = (insn >> 16) & 0xf;
807 u8 rs = (insn >> 8) & 0xf; 622 u8 rs = (insn >> 8) & 0xf;
808 u8 rm = insn & 0xf; 623 u8 rm = insn & 0xf;
809 u8 bit_s = (insn >> 20) & 1; 624 u8 bit_s = (insn >> 20) & 1;
810 625
811 const char *opname = opcode_names[opcode]; 626 const char* opname = opcode_names[opcode];
812 return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d", 627 return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d", opname, cond_to_str(cond),
813 opname, cond_to_str(cond), bit_s ? "s" : "", rd, rm, rs); 628 bit_s ? "s" : "", rd, rm, rs);
814} 629}
815 630
816std::string ARM_Disasm::DisassembleMRS(u32 insn) 631std::string ARM_Disasm::DisassembleMRS(u32 insn) {
817{
818 u8 cond = (insn >> 28) & 0xf; 632 u8 cond = (insn >> 28) & 0xf;
819 u8 rd = (insn >> 12) & 0xf; 633 u8 rd = (insn >> 12) & 0xf;
820 u8 ps = (insn >> 22) & 1; 634 u8 ps = (insn >> 22) & 1;
@@ -822,8 +636,7 @@ std::string ARM_Disasm::DisassembleMRS(u32 insn)
822 return Common::StringFromFormat("mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr"); 636 return Common::StringFromFormat("mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr");
823} 637}
824 638
825std::string ARM_Disasm::DisassembleMSR(u32 insn) 639std::string ARM_Disasm::DisassembleMSR(u32 insn) {
826{
827 char flags[8]; 640 char flags[8];
828 int flag_index = 0; 641 int flag_index = 0;
829 u8 cond = (insn >> 28) & 0xf; 642 u8 cond = (insn >> 28) & 0xf;
@@ -846,18 +659,17 @@ std::string ARM_Disasm::DisassembleMSR(u32 insn)
846 u8 rotate = (insn >> 8) & 0xf; 659 u8 rotate = (insn >> 8) & 0xf;
847 u8 rotate2 = rotate << 1; 660 u8 rotate2 = rotate << 1;
848 u32 rotated_val = (immed >> rotate2) | (immed << (32 - rotate2)); 661 u32 rotated_val = (immed >> rotate2) | (immed << (32 - rotate2));
849 return Common::StringFromFormat("msr%s\t%s_%s, #0x%x", 662 return Common::StringFromFormat("msr%s\t%s_%s, #0x%x", cond_to_str(cond),
850 cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rotated_val); 663 pd ? "spsr" : "cpsr", flags, rotated_val);
851 } 664 }
852 665
853 u8 rm = insn & 0xf; 666 u8 rm = insn & 0xf;
854 667
855 return Common::StringFromFormat("msr%s\t%s_%s, r%d", 668 return Common::StringFromFormat("msr%s\t%s_%s, r%d", cond_to_str(cond), pd ? "spsr" : "cpsr",
856 cond_to_str(cond), pd ? "spsr" : "cpsr", flags, rm); 669 flags, rm);
857} 670}
858 671
859std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, u32 insn) 672std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, u32 insn) {
860{
861 u32 cond = BITS(insn, 28, 31); 673 u32 cond = BITS(insn, 28, 31);
862 return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); 674 return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond));
863} 675}
@@ -872,8 +684,7 @@ std::string ARM_Disasm::DisassembleParallelAddSub(Opcode opcode, u32 insn) {
872 rd, rn, rm); 684 rd, rn, rm);
873} 685}
874 686
875std::string ARM_Disasm::DisassemblePKH(u32 insn) 687std::string ARM_Disasm::DisassemblePKH(u32 insn) {
876{
877 u32 cond = BITS(insn, 28, 31); 688 u32 cond = BITS(insn, 28, 31);
878 u32 rn = BITS(insn, 16, 19); 689 u32 rn = BITS(insn, 16, 19);
879 u32 rd = BITS(insn, 12, 15); 690 u32 rd = BITS(insn, 12, 15);
@@ -896,13 +707,12 @@ std::string ARM_Disasm::DisassemblePKH(u32 insn)
896 rd, rn, rm, shift.c_str()); 707 rd, rn, rm, shift.c_str());
897} 708}
898 709
899std::string ARM_Disasm::DisassemblePLD(u32 insn) 710std::string ARM_Disasm::DisassemblePLD(u32 insn) {
900{
901 u8 is_reg = (insn >> 25) & 0x1; 711 u8 is_reg = (insn >> 25) & 0x1;
902 u8 is_up = (insn >> 23) & 0x1; 712 u8 is_up = (insn >> 23) & 0x1;
903 u8 rn = (insn >> 16) & 0xf; 713 u8 rn = (insn >> 16) & 0xf;
904 714
905 const char *minus = ""; 715 const char* minus = "";
906 if (is_up == 0) 716 if (is_up == 0)
907 minus = "-"; 717 minus = "-";
908 718
@@ -924,8 +734,8 @@ std::string ARM_Disasm::DisassembleREV(Opcode opcode, u32 insn) {
924 u32 rd = BITS(insn, 12, 15); 734 u32 rd = BITS(insn, 12, 15);
925 u32 rm = BITS(insn, 0, 3); 735 u32 rm = BITS(insn, 0, 3);
926 736
927 return Common::StringFromFormat("%s%s\tr%u, r%u", opcode_names[opcode], cond_to_str(cond), 737 return Common::StringFromFormat("%s%s\tr%u, r%u", opcode_names[opcode], cond_to_str(cond), rd,
928 rd, rm); 738 rm);
929} 739}
930 740
931std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) { 741std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) {
@@ -935,26 +745,26 @@ std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) {
935 u32 cond = BITS(insn, 28, 31); 745 u32 cond = BITS(insn, 28, 31);
936 746
937 switch (opcode) { 747 switch (opcode) {
938 case OP_STREX: 748 case OP_STREX:
939 case OP_STREXB: 749 case OP_STREXB:
940 case OP_STREXH: 750 case OP_STREXH:
941 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], 751 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode],
942 cond_to_str(cond), rd, rt, rn); 752 cond_to_str(cond), rd, rt, rn);
943 case OP_STREXD: 753 case OP_STREXD:
944 return Common::StringFromFormat("%s%s\tr%d, r%d, r%d, [r%d]", opcode_names[opcode], 754 return Common::StringFromFormat("%s%s\tr%d, r%d, r%d, [r%d]", opcode_names[opcode],
945 cond_to_str(cond), rd, rt, rt + 1, rn); 755 cond_to_str(cond), rd, rt, rt + 1, rn);
946 756
947 // for LDREX instructions, rd corresponds to Rt from reference manual 757 // for LDREX instructions, rd corresponds to Rt from reference manual
948 case OP_LDREX: 758 case OP_LDREX:
949 case OP_LDREXB: 759 case OP_LDREXB:
950 case OP_LDREXH: 760 case OP_LDREXH:
951 return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode], 761 return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode], cond_to_str(cond),
952 cond_to_str(cond), rd, rn); 762 rd, rn);
953 case OP_LDREXD: 763 case OP_LDREXD:
954 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], 764 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode],
955 cond_to_str(cond), rd, rd + 1, rn); 765 cond_to_str(cond), rd, rd + 1, rn);
956 default: 766 default:
957 return opcode_names[OP_UNDEFINED]; 767 return opcode_names[OP_UNDEFINED];
958 } 768 }
959} 769}
960 770
@@ -982,8 +792,8 @@ std::string ARM_Disasm::DisassembleSAT(Opcode opcode, u32 insn) {
982 if (opcode == OP_SSAT || opcode == OP_SSAT16) 792 if (opcode == OP_SSAT || opcode == OP_SSAT16)
983 sat_imm++; 793 sat_imm++;
984 794
985 return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode], cond_to_str(cond), rd, 795 return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode],
986 sat_imm, rn, shift_part.c_str()); 796 cond_to_str(cond), rd, sat_imm, rn, shift_part.c_str());
987} 797}
988 798
989std::string ARM_Disasm::DisassembleSEL(u32 insn) { 799std::string ARM_Disasm::DisassembleSEL(u32 insn) {
@@ -996,27 +806,24 @@ std::string ARM_Disasm::DisassembleSEL(u32 insn) {
996 rd, rn, rm); 806 rd, rn, rm);
997} 807}
998 808
999std::string ARM_Disasm::DisassembleSWI(u32 insn) 809std::string ARM_Disasm::DisassembleSWI(u32 insn) {
1000{
1001 u8 cond = (insn >> 28) & 0xf; 810 u8 cond = (insn >> 28) & 0xf;
1002 u32 sysnum = insn & 0x00ffffff; 811 u32 sysnum = insn & 0x00ffffff;
1003 812
1004 return Common::StringFromFormat("swi%s 0x%x", cond_to_str(cond), sysnum); 813 return Common::StringFromFormat("swi%s 0x%x", cond_to_str(cond), sysnum);
1005} 814}
1006 815
1007std::string ARM_Disasm::DisassembleSWP(Opcode opcode, u32 insn) 816std::string ARM_Disasm::DisassembleSWP(Opcode opcode, u32 insn) {
1008{
1009 u8 cond = (insn >> 28) & 0xf; 817 u8 cond = (insn >> 28) & 0xf;
1010 u8 rn = (insn >> 16) & 0xf; 818 u8 rn = (insn >> 16) & 0xf;
1011 u8 rd = (insn >> 12) & 0xf; 819 u8 rd = (insn >> 12) & 0xf;
1012 u8 rm = insn & 0xf; 820 u8 rm = insn & 0xf;
1013 821
1014 const char *opname = opcode_names[opcode]; 822 const char* opname = opcode_names[opcode];
1015 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn); 823 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn);
1016} 824}
1017 825
1018std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn) 826std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn) {
1019{
1020 u32 cond = BITS(insn, 28, 31); 827 u32 cond = BITS(insn, 28, 31);
1021 u32 rn = BITS(insn, 16, 19); 828 u32 rn = BITS(insn, 16, 19);
1022 u32 rd = BITS(insn, 12, 15); 829 u32 rd = BITS(insn, 12, 15);
@@ -1025,9 +832,7 @@ std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn)
1025 832
1026 std::string rn_part = ""; 833 std::string rn_part = "";
1027 static std::unordered_set<Opcode, std::hash<int>> extend_with_add = { 834 static std::unordered_set<Opcode, std::hash<int>> extend_with_add = {
1028 OP_SXTAB, OP_SXTAB16, OP_SXTAH, 835 OP_SXTAB, OP_SXTAB16, OP_SXTAH, OP_UXTAB, OP_UXTAB16, OP_UXTAH};
1029 OP_UXTAB, OP_UXTAB16, OP_UXTAH
1030 };
1031 if (extend_with_add.find(opcode) != extend_with_add.end()) 836 if (extend_with_add.find(opcode) != extend_with_add.end())
1032 rn_part = ", r" + std::to_string(rn); 837 rn_part = ", r" + std::to_string(rn);
1033 838
@@ -1042,14 +847,14 @@ std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn)
1042Opcode ARM_Disasm::Decode(u32 insn) { 847Opcode ARM_Disasm::Decode(u32 insn) {
1043 u32 bits27_26 = (insn >> 26) & 0x3; 848 u32 bits27_26 = (insn >> 26) & 0x3;
1044 switch (bits27_26) { 849 switch (bits27_26) {
1045 case 0x0: 850 case 0x0:
1046 return Decode00(insn); 851 return Decode00(insn);
1047 case 0x1: 852 case 0x1:
1048 return Decode01(insn); 853 return Decode01(insn);
1049 case 0x2: 854 case 0x2:
1050 return Decode10(insn); 855 return Decode10(insn);
1051 case 0x3: 856 case 0x3:
1052 return Decode11(insn); 857 return Decode11(insn);
1053 } 858 }
1054 return OP_INVALID; 859 return OP_INVALID;
1055} 860}
@@ -1198,28 +1003,28 @@ Opcode ARM_Disasm::DecodeSyncPrimitive(u32 insn) {
1198 u32 op = BITS(insn, 20, 23); 1003 u32 op = BITS(insn, 20, 23);
1199 u32 bit22 = BIT(insn, 22); 1004 u32 bit22 = BIT(insn, 22);
1200 switch (op) { 1005 switch (op) {
1201 case 0x0: 1006 case 0x0:
1202 if (bit22) 1007 if (bit22)
1203 return OP_SWPB; 1008 return OP_SWPB;
1204 return OP_SWP; 1009 return OP_SWP;
1205 case 0x8: 1010 case 0x8:
1206 return OP_STREX; 1011 return OP_STREX;
1207 case 0x9: 1012 case 0x9:
1208 return OP_LDREX; 1013 return OP_LDREX;
1209 case 0xA: 1014 case 0xA:
1210 return OP_STREXD; 1015 return OP_STREXD;
1211 case 0xB: 1016 case 0xB:
1212 return OP_LDREXD; 1017 return OP_LDREXD;
1213 case 0xC: 1018 case 0xC:
1214 return OP_STREXB; 1019 return OP_STREXB;
1215 case 0xD: 1020 case 0xD:
1216 return OP_LDREXB; 1021 return OP_LDREXB;
1217 case 0xE: 1022 case 0xE:
1218 return OP_STREXH; 1023 return OP_STREXH;
1219 case 0xF: 1024 case 0xF:
1220 return OP_LDREXH; 1025 return OP_LDREXH;
1221 default: 1026 default:
1222 return OP_UNDEFINED; 1027 return OP_UNDEFINED;
1223 } 1028 }
1224} 1029}
1225 1030
@@ -1240,27 +1045,14 @@ Opcode ARM_Disasm::DecodeParallelAddSub(u32 insn) {
1240 1045
1241 static std::vector<Opcode> opcodes = { 1046 static std::vector<Opcode> opcodes = {
1242 // op1 = 0 1047 // op1 = 0
1243 OP_SADD16, OP_UADD16, 1048 OP_SADD16, OP_UADD16, OP_SASX, OP_UASX, OP_SSAX, OP_USAX, OP_SSUB16, OP_USUB16, OP_SADD8,
1244 OP_SASX, OP_UASX, 1049 OP_UADD8, OP_SSUB8, OP_USUB8,
1245 OP_SSAX, OP_USAX,
1246 OP_SSUB16, OP_USUB16,
1247 OP_SADD8, OP_UADD8,
1248 OP_SSUB8, OP_USUB8,
1249 // op1 = 1 1050 // op1 = 1
1250 OP_QADD16, OP_UQADD16, 1051 OP_QADD16, OP_UQADD16, OP_QASX, OP_UQASX, OP_QSAX, OP_UQSAX, OP_QSUB16, OP_UQSUB16,
1251 OP_QASX, OP_UQASX, 1052 OP_QADD8, OP_UQADD8, OP_QSUB8, OP_UQSUB8,
1252 OP_QSAX, OP_UQSAX,
1253 OP_QSUB16, OP_UQSUB16,
1254 OP_QADD8, OP_UQADD8,
1255 OP_QSUB8, OP_UQSUB8,
1256 // op1 = 2 1053 // op1 = 2
1257 OP_SHADD16, OP_UHADD16, 1054 OP_SHADD16, OP_UHADD16, OP_SHASX, OP_UHASX, OP_SHSAX, OP_UHSAX, OP_SHSUB16, OP_UHSUB16,
1258 OP_SHASX, OP_UHASX, 1055 OP_SHADD8, OP_UHADD8, OP_SHSUB8, OP_UHSUB8};
1259 OP_SHSAX, OP_UHSAX,
1260 OP_SHSUB16, OP_UHSUB16,
1261 OP_SHADD8, OP_UHADD8,
1262 OP_SHSUB8, OP_UHSUB8
1263 };
1264 1056
1265 u32 opcode_index = op1 * 12 + op2 * 2 + is_unsigned; 1057 u32 opcode_index = op1 * 12 + op2 * 2 + is_unsigned;
1266 return opcodes[opcode_index]; 1058 return opcodes[opcode_index];
@@ -1272,66 +1064,66 @@ Opcode ARM_Disasm::DecodePackingSaturationReversal(u32 insn) {
1272 u32 op2 = BITS(insn, 5, 7); 1064 u32 op2 = BITS(insn, 5, 7);
1273 1065
1274 switch (op1) { 1066 switch (op1) {
1275 case 0x0: 1067 case 0x0:
1276 if (BIT(op2, 0) == 0) 1068 if (BIT(op2, 0) == 0)
1277 return OP_PKH; 1069 return OP_PKH;
1278 if (op2 == 0x3 && a != 0xf) 1070 if (op2 == 0x3 && a != 0xf)
1279 return OP_SXTAB16; 1071 return OP_SXTAB16;
1280 if (op2 == 0x3 && a == 0xf) 1072 if (op2 == 0x3 && a == 0xf)
1281 return OP_SXTB16; 1073 return OP_SXTB16;
1282 if (op2 == 0x5) 1074 if (op2 == 0x5)
1283 return OP_SEL; 1075 return OP_SEL;
1284 break; 1076 break;
1285 case 0x2: 1077 case 0x2:
1286 if (BIT(op2, 0) == 0) 1078 if (BIT(op2, 0) == 0)
1287 return OP_SSAT; 1079 return OP_SSAT;
1288 if (op2 == 0x1) 1080 if (op2 == 0x1)
1289 return OP_SSAT16; 1081 return OP_SSAT16;
1290 if (op2 == 0x3 && a != 0xf) 1082 if (op2 == 0x3 && a != 0xf)
1291 return OP_SXTAB; 1083 return OP_SXTAB;
1292 if (op2 == 0x3 && a == 0xf) 1084 if (op2 == 0x3 && a == 0xf)
1293 return OP_SXTB; 1085 return OP_SXTB;
1294 break; 1086 break;
1295 case 0x3: 1087 case 0x3:
1296 if (op2 == 0x1) 1088 if (op2 == 0x1)
1297 return OP_REV; 1089 return OP_REV;
1298 if (BIT(op2, 0) == 0) 1090 if (BIT(op2, 0) == 0)
1299 return OP_SSAT; 1091 return OP_SSAT;
1300 if (op2 == 0x3 && a != 0xf) 1092 if (op2 == 0x3 && a != 0xf)
1301 return OP_SXTAH; 1093 return OP_SXTAH;
1302 if (op2 == 0x3 && a == 0xf) 1094 if (op2 == 0x3 && a == 0xf)
1303 return OP_SXTH; 1095 return OP_SXTH;
1304 if (op2 == 0x5) 1096 if (op2 == 0x5)
1305 return OP_REV16; 1097 return OP_REV16;
1306 break; 1098 break;
1307 case 0x4: 1099 case 0x4:
1308 if (op2 == 0x3 && a != 0xf) 1100 if (op2 == 0x3 && a != 0xf)
1309 return OP_UXTAB16; 1101 return OP_UXTAB16;
1310 if (op2 == 0x3 && a == 0xf) 1102 if (op2 == 0x3 && a == 0xf)
1311 return OP_UXTB16; 1103 return OP_UXTB16;
1312 break; 1104 break;
1313 case 0x6: 1105 case 0x6:
1314 if (BIT(op2, 0) == 0) 1106 if (BIT(op2, 0) == 0)
1315 return OP_USAT; 1107 return OP_USAT;
1316 if (op2 == 0x1) 1108 if (op2 == 0x1)
1317 return OP_USAT16; 1109 return OP_USAT16;
1318 if (op2 == 0x3 && a != 0xf) 1110 if (op2 == 0x3 && a != 0xf)
1319 return OP_UXTAB; 1111 return OP_UXTAB;
1320 if (op2 == 0x3 && a == 0xf) 1112 if (op2 == 0x3 && a == 0xf)
1321 return OP_UXTB; 1113 return OP_UXTB;
1322 break; 1114 break;
1323 case 0x7: 1115 case 0x7:
1324 if (BIT(op2, 0) == 0) 1116 if (BIT(op2, 0) == 0)
1325 return OP_USAT; 1117 return OP_USAT;
1326 if (op2 == 0x3 && a != 0xf) 1118 if (op2 == 0x3 && a != 0xf)
1327 return OP_UXTAH; 1119 return OP_UXTAH;
1328 if (op2 == 0x3 && a == 0xf) 1120 if (op2 == 0x3 && a == 0xf)
1329 return OP_UXTH; 1121 return OP_UXTH;
1330 if (op2 == 0x5) 1122 if (op2 == 0x5)
1331 return OP_REVSH; 1123 return OP_REVSH;
1332 break; 1124 break;
1333 default: 1125 default:
1334 break; 1126 break;
1335 } 1127 }
1336 1128
1337 return OP_UNDEFINED; 1129 return OP_UNDEFINED;
@@ -1378,18 +1170,18 @@ Opcode ARM_Disasm::DecodeMSRImmAndHints(u32 insn) {
1378 1170
1379 if (op == 0 && op1 == 0) { 1171 if (op == 0 && op1 == 0) {
1380 switch (op2) { 1172 switch (op2) {
1381 case 0x0: 1173 case 0x0:
1382 return OP_NOP; 1174 return OP_NOP;
1383 case 0x1: 1175 case 0x1:
1384 return OP_YIELD; 1176 return OP_YIELD;
1385 case 0x2: 1177 case 0x2:
1386 return OP_WFE; 1178 return OP_WFE;
1387 case 0x3: 1179 case 0x3:
1388 return OP_WFI; 1180 return OP_WFI;
1389 case 0x4: 1181 case 0x4:
1390 return OP_SEV; 1182 return OP_SEV;
1391 default: 1183 default:
1392 return OP_UNDEFINED; 1184 return OP_UNDEFINED;
1393 } 1185 }
1394 } 1186 }
1395 1187
@@ -1402,37 +1194,37 @@ Opcode ARM_Disasm::DecodeMediaMulDiv(u32 insn) {
1402 u32 a = BITS(insn, 12, 15); 1194 u32 a = BITS(insn, 12, 15);
1403 1195
1404 switch (op1) { 1196 switch (op1) {
1405 case 0x0: 1197 case 0x0:
1406 if (op2_h == 0x0) { 1198 if (op2_h == 0x0) {
1407 if (a != 0xf) 1199 if (a != 0xf)
1408 return OP_SMLAD; 1200 return OP_SMLAD;
1409 else 1201 else
1410 return OP_SMUAD; 1202 return OP_SMUAD;
1411 } else if (op2_h == 0x1) { 1203 } else if (op2_h == 0x1) {
1412 if (a != 0xf) 1204 if (a != 0xf)
1413 return OP_SMLSD; 1205 return OP_SMLSD;
1414 else 1206 else
1415 return OP_SMUSD; 1207 return OP_SMUSD;
1416 } 1208 }
1417 break; 1209 break;
1418 case 0x4: 1210 case 0x4:
1419 if (op2_h == 0x0) 1211 if (op2_h == 0x0)
1420 return OP_SMLALD; 1212 return OP_SMLALD;
1421 else if (op2_h == 0x1) 1213 else if (op2_h == 0x1)
1422 return OP_SMLSLD; 1214 return OP_SMLSLD;
1423 break; 1215 break;
1424 case 0x5: 1216 case 0x5:
1425 if (op2_h == 0x0) { 1217 if (op2_h == 0x0) {
1426 if (a != 0xf) 1218 if (a != 0xf)
1427 return OP_SMMLA; 1219 return OP_SMMLA;
1428 else 1220 else
1429 return OP_SMMUL; 1221 return OP_SMMUL;
1430 } else if (op2_h == 0x3) { 1222 } else if (op2_h == 0x3) {
1431 return OP_SMMLS; 1223 return OP_SMMLS;
1432 } 1224 }
1433 break; 1225 break;
1434 default: 1226 default:
1435 break; 1227 break;
1436 } 1228 }
1437 1229
1438 return OP_UNDEFINED; 1230 return OP_UNDEFINED;
@@ -1444,23 +1236,23 @@ Opcode ARM_Disasm::DecodeMedia(u32 insn) {
1444 u32 op2 = BITS(insn, 5, 7); 1236 u32 op2 = BITS(insn, 5, 7);
1445 1237
1446 switch (BITS(op1, 3, 4)) { 1238 switch (BITS(op1, 3, 4)) {
1447 case 0x0: 1239 case 0x0:
1448 // unsigned and signed parallel addition and subtraction 1240 // unsigned and signed parallel addition and subtraction
1449 return DecodeParallelAddSub(insn); 1241 return DecodeParallelAddSub(insn);
1450 case 0x1: 1242 case 0x1:
1451 // Packing, unpacking, saturation, and reversal 1243 // Packing, unpacking, saturation, and reversal
1452 return DecodePackingSaturationReversal(insn); 1244 return DecodePackingSaturationReversal(insn);
1453 case 0x2: 1245 case 0x2:
1454 // Signed multiply, signed and unsigned divide 1246 // Signed multiply, signed and unsigned divide
1455 return DecodeMediaMulDiv(insn); 1247 return DecodeMediaMulDiv(insn);
1456 case 0x3: 1248 case 0x3:
1457 if (op2 == 0 && rd == 0xf) 1249 if (op2 == 0 && rd == 0xf)
1458 return OP_USAD8; 1250 return OP_USAD8;
1459 if (op2 == 0 && rd != 0xf) 1251 if (op2 == 0 && rd != 0xf)
1460 return OP_USADA8; 1252 return OP_USADA8;
1461 break; 1253 break;
1462 default: 1254 default:
1463 break; 1255 break;
1464 } 1256 }
1465 1257
1466 return OP_UNDEFINED; 1258 return OP_UNDEFINED;
@@ -1508,46 +1300,46 @@ Opcode ARM_Disasm::DecodeALU(u32 insn) {
1508 return OP_UNDEFINED; 1300 return OP_UNDEFINED;
1509 } 1301 }
1510 switch (opcode) { 1302 switch (opcode) {
1511 case 0x0: 1303 case 0x0:
1512 return OP_AND; 1304 return OP_AND;
1513 case 0x1: 1305 case 0x1:
1514 return OP_EOR; 1306 return OP_EOR;
1515 case 0x2: 1307 case 0x2:
1516 return OP_SUB; 1308 return OP_SUB;
1517 case 0x3: 1309 case 0x3:
1518 return OP_RSB; 1310 return OP_RSB;
1519 case 0x4: 1311 case 0x4:
1520 return OP_ADD; 1312 return OP_ADD;
1521 case 0x5: 1313 case 0x5:
1522 return OP_ADC; 1314 return OP_ADC;
1523 case 0x6: 1315 case 0x6:
1524 return OP_SBC; 1316 return OP_SBC;
1525 case 0x7: 1317 case 0x7:
1526 return OP_RSC; 1318 return OP_RSC;
1527 case 0x8: 1319 case 0x8:
1528 if (bit_s) 1320 if (bit_s)
1529 return OP_TST; 1321 return OP_TST;
1530 return OP_MRS; 1322 return OP_MRS;
1531 case 0x9: 1323 case 0x9:
1532 if (bit_s) 1324 if (bit_s)
1533 return OP_TEQ; 1325 return OP_TEQ;
1534 return OP_MSR; 1326 return OP_MSR;
1535 case 0xa: 1327 case 0xa:
1536 if (bit_s) 1328 if (bit_s)
1537 return OP_CMP; 1329 return OP_CMP;
1538 return OP_MRS; 1330 return OP_MRS;
1539 case 0xb: 1331 case 0xb:
1540 if (bit_s) 1332 if (bit_s)
1541 return OP_CMN; 1333 return OP_CMN;
1542 return OP_MSR; 1334 return OP_MSR;
1543 case 0xc: 1335 case 0xc:
1544 return OP_ORR; 1336 return OP_ORR;
1545 case 0xd: 1337 case 0xd:
1546 return OP_MOV; 1338 return OP_MOV;
1547 case 0xe: 1339 case 0xe:
1548 return OP_BIC; 1340 return OP_BIC;
1549 case 0xf: 1341 case 0xf:
1550 return OP_MVN; 1342 return OP_MVN;
1551 } 1343 }
1552 // Unreachable 1344 // Unreachable
1553 return OP_INVALID; 1345 return OP_INVALID;
diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h
index 53d9c6a74..031f973d6 100644
--- a/src/core/arm/disassembler/arm_disasm.h
+++ b/src/core/arm/disassembler/arm_disasm.h
@@ -187,53 +187,53 @@ enum Opcode {
187 OP_THUMB_SWI, 187 OP_THUMB_SWI,
188 OP_THUMB_TST, 188 OP_THUMB_TST,
189 189
190 OP_END // must be last 190 OP_END // must be last
191}; 191};
192 192
193class ARM_Disasm { 193class ARM_Disasm {
194 public: 194public:
195 static std::string Disassemble(u32 addr, u32 insn); 195 static std::string Disassemble(u32 addr, u32 insn);
196 static Opcode Decode(u32 insn); 196 static Opcode Decode(u32 insn);
197 197
198 private: 198private:
199 static Opcode Decode00(u32 insn); 199 static Opcode Decode00(u32 insn);
200 static Opcode Decode01(u32 insn); 200 static Opcode Decode01(u32 insn);
201 static Opcode Decode10(u32 insn); 201 static Opcode Decode10(u32 insn);
202 static Opcode Decode11(u32 insn); 202 static Opcode Decode11(u32 insn);
203 static Opcode DecodeSyncPrimitive(u32 insn); 203 static Opcode DecodeSyncPrimitive(u32 insn);
204 static Opcode DecodeParallelAddSub(u32 insn); 204 static Opcode DecodeParallelAddSub(u32 insn);
205 static Opcode DecodePackingSaturationReversal(u32 insn); 205 static Opcode DecodePackingSaturationReversal(u32 insn);
206 static Opcode DecodeMUL(u32 insn); 206 static Opcode DecodeMUL(u32 insn);
207 static Opcode DecodeMSRImmAndHints(u32 insn); 207 static Opcode DecodeMSRImmAndHints(u32 insn);
208 static Opcode DecodeMediaMulDiv(u32 insn); 208 static Opcode DecodeMediaMulDiv(u32 insn);
209 static Opcode DecodeMedia(u32 insn); 209 static Opcode DecodeMedia(u32 insn);
210 static Opcode DecodeLDRH(u32 insn); 210 static Opcode DecodeLDRH(u32 insn);
211 static Opcode DecodeALU(u32 insn); 211 static Opcode DecodeALU(u32 insn);
212 212
213 static std::string DisassembleALU(Opcode opcode, u32 insn); 213 static std::string DisassembleALU(Opcode opcode, u32 insn);
214 static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn); 214 static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn);
215 static std::string DisassembleBX(u32 insn); 215 static std::string DisassembleBX(u32 insn);
216 static std::string DisassembleBKPT(u32 insn); 216 static std::string DisassembleBKPT(u32 insn);
217 static std::string DisassembleCLZ(u32 insn); 217 static std::string DisassembleCLZ(u32 insn);
218 static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn); 218 static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn);
219 static std::string DisassembleMemblock(Opcode opcode, u32 insn); 219 static std::string DisassembleMemblock(Opcode opcode, u32 insn);
220 static std::string DisassembleMem(u32 insn); 220 static std::string DisassembleMem(u32 insn);
221 static std::string DisassembleMemHalf(u32 insn); 221 static std::string DisassembleMemHalf(u32 insn);
222 static std::string DisassembleMCR(Opcode opcode, u32 insn); 222 static std::string DisassembleMCR(Opcode opcode, u32 insn);
223 static std::string DisassembleMLA(Opcode opcode, u32 insn); 223 static std::string DisassembleMLA(Opcode opcode, u32 insn);
224 static std::string DisassembleUMLAL(Opcode opcode, u32 insn); 224 static std::string DisassembleUMLAL(Opcode opcode, u32 insn);
225 static std::string DisassembleMUL(Opcode opcode, u32 insn); 225 static std::string DisassembleMUL(Opcode opcode, u32 insn);
226 static std::string DisassembleMRS(u32 insn); 226 static std::string DisassembleMRS(u32 insn);
227 static std::string DisassembleMSR(u32 insn); 227 static std::string DisassembleMSR(u32 insn);
228 static std::string DisassembleNoOperands(Opcode opcode, u32 insn); 228 static std::string DisassembleNoOperands(Opcode opcode, u32 insn);
229 static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn); 229 static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn);
230 static std::string DisassemblePKH(u32 insn); 230 static std::string DisassemblePKH(u32 insn);
231 static std::string DisassemblePLD(u32 insn); 231 static std::string DisassemblePLD(u32 insn);
232 static std::string DisassembleREV(Opcode opcode, u32 insn); 232 static std::string DisassembleREV(Opcode opcode, u32 insn);
233 static std::string DisassembleREX(Opcode opcode, u32 insn); 233 static std::string DisassembleREX(Opcode opcode, u32 insn);
234 static std::string DisassembleSAT(Opcode opcode, u32 insn); 234 static std::string DisassembleSAT(Opcode opcode, u32 insn);
235 static std::string DisassembleSEL(u32 insn); 235 static std::string DisassembleSEL(u32 insn);
236 static std::string DisassembleSWI(u32 insn); 236 static std::string DisassembleSWI(u32 insn);
237 static std::string DisassembleSWP(Opcode opcode, u32 insn); 237 static std::string DisassembleSWP(Opcode opcode, u32 insn);
238 static std::string DisassembleXT(Opcode opcode, u32 insn); 238 static std::string DisassembleXT(Opcode opcode, u32 insn);
239}; 239};
diff --git a/src/core/arm/disassembler/load_symbol_map.cpp b/src/core/arm/disassembler/load_symbol_map.cpp
index eb20bf6f7..58e8e6fa1 100644
--- a/src/core/arm/disassembler/load_symbol_map.cpp
+++ b/src/core/arm/disassembler/load_symbol_map.cpp
@@ -6,8 +6,8 @@
6#include <string> 6#include <string>
7#include <vector> 7#include <vector>
8 8
9#include "common/symbols.h"
10#include "common/file_util.h" 9#include "common/file_util.h"
10#include "common/symbols.h"
11 11
12#include "core/arm/disassembler/load_symbol_map.h" 12#include "core/arm/disassembler/load_symbol_map.h"
13 13
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp
index 6dbc92b91..64dcaae08 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp
@@ -430,12 +430,15 @@ ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) {
430 continue; 430 continue;
431 431
432 while (n) { 432 while (n) {
433 if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) { 433 if (arm_instruction[i].content[base + 1] == 31 &&
434 arm_instruction[i].content[base] == 0) {
434 // clrex 435 // clrex
435 if (instr != arm_instruction[i].content[base + 2]) { 436 if (instr != arm_instruction[i].content[base + 2]) {
436 break; 437 break;
437 } 438 }
438 } else if (BITS(instr, arm_instruction[i].content[base], arm_instruction[i].content[base + 1]) != arm_instruction[i].content[base + 2]) { 439 } else if (BITS(instr, arm_instruction[i].content[base],
440 arm_instruction[i].content[base + 1]) !=
441 arm_instruction[i].content[base + 2]) {
439 break; 442 break;
440 } 443 }
441 base += 3; 444 base += 3;
@@ -451,7 +454,9 @@ ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) {
451 if (n != 0) { 454 if (n != 0) {
452 base = 0; 455 base = 0;
453 while (n) { 456 while (n) {
454 if (BITS(instr, arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) { 457 if (BITS(instr, arm_exclusion_code[i].content[base],
458 arm_exclusion_code[i].content[base + 1]) !=
459 arm_exclusion_code[i].content[base + 2]) {
455 break; 460 break;
456 } 461 }
457 base += 3; 462 base += 3;
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h
index d7170e0fc..2fb7ac37c 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.h
+++ b/src/core/arm/dyncom/arm_dyncom_dec.h
@@ -6,15 +6,12 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9enum class ARMDecodeStatus { 9enum class ARMDecodeStatus { SUCCESS, FAILURE };
10 SUCCESS,
11 FAILURE
12};
13 10
14ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx); 11ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx);
15 12
16struct InstructionSetEncodingItem { 13struct InstructionSetEncodingItem {
17 const char *name; 14 const char* name;
18 int attribute_value; 15 int attribute_value;
19 int version; 16 int version;
20 u32 content[21]; 17 u32 content[21];
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index c8d45c6db..211d49edb 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -11,29 +11,29 @@
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/microprofile.h" 12#include "common/microprofile.h"
13 13
14#include "core/memory.h"
15#include "core/hle/svc.h"
16#include "core/arm/disassembler/arm_disasm.h" 14#include "core/arm/disassembler/arm_disasm.h"
17#include "core/arm/dyncom/arm_dyncom_dec.h" 15#include "core/arm/dyncom/arm_dyncom_dec.h"
18#include "core/arm/dyncom/arm_dyncom_interpreter.h" 16#include "core/arm/dyncom/arm_dyncom_interpreter.h"
17#include "core/arm/dyncom/arm_dyncom_run.h"
19#include "core/arm/dyncom/arm_dyncom_thumb.h" 18#include "core/arm/dyncom/arm_dyncom_thumb.h"
20#include "core/arm/dyncom/arm_dyncom_trans.h" 19#include "core/arm/dyncom/arm_dyncom_trans.h"
21#include "core/arm/dyncom/arm_dyncom_run.h"
22#include "core/arm/skyeye_common/armstate.h" 20#include "core/arm/skyeye_common/armstate.h"
23#include "core/arm/skyeye_common/armsupp.h" 21#include "core/arm/skyeye_common/armsupp.h"
24#include "core/arm/skyeye_common/vfp/vfp.h" 22#include "core/arm/skyeye_common/vfp/vfp.h"
23#include "core/hle/svc.h"
24#include "core/memory.h"
25 25
26#include "core/gdbstub/gdbstub.h" 26#include "core/gdbstub/gdbstub.h"
27 27
28#define RM BITS(sht_oper, 0, 3) 28#define RM BITS(sht_oper, 0, 3)
29#define RS BITS(sht_oper, 8, 11) 29#define RS BITS(sht_oper, 8, 11)
30 30
31#define glue(x, y) x ## y 31#define glue(x, y) x##y
32#define DPO(s) glue(DataProcessingOperands, s) 32#define DPO(s) glue(DataProcessingOperands, s)
33#define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i)) 33#define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i))
34#define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i)) 34#define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i))
35#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32) 35#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32)
36#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32) 36#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32)
37 37
38static bool CondPassed(const ARMul_State* cpu, unsigned int cond) { 38static bool CondPassed(const ARMul_State* cpu, unsigned int cond) {
39 const bool n_flag = cpu->NFlag != 0; 39 const bool n_flag = cpu->NFlag != 0;
@@ -232,17 +232,19 @@ static unsigned int DPO(RotateRightByRegister)(ARMul_State* cpu, unsigned int sh
232 return shifter_operand; 232 return shifter_operand;
233} 233}
234 234
235#define DEBUG_MSG LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0) 235#define DEBUG_MSG \
236 LOG_DEBUG(Core_ARM11, "inst is %x", inst); \
237 CITRA_IGNORE_EXIT(0)
236 238
237#define LnSWoUB(s) glue(LnSWoUB, s) 239#define LnSWoUB(s) glue(LnSWoUB, s)
238#define MLnS(s) glue(MLnS, s) 240#define MLnS(s) glue(MLnS, s)
239#define LdnStM(s) glue(LdnStM, s) 241#define LdnStM(s) glue(LdnStM, s)
240 242
241#define W_BIT BIT(inst, 21) 243#define W_BIT BIT(inst, 21)
242#define U_BIT BIT(inst, 23) 244#define U_BIT BIT(inst, 23)
243#define I_BIT BIT(inst, 25) 245#define I_BIT BIT(inst, 25)
244#define P_BIT BIT(inst, 24) 246#define P_BIT BIT(inst, 24)
245#define OFFSET_12 BITS(inst, 0, 11) 247#define OFFSET_12 BITS(inst, 0, 11)
246 248
247static void LnSWoUB(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 249static void LnSWoUB(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
248 unsigned int Rn = BITS(inst, 16, 19); 250 unsigned int Rn = BITS(inst, 16, 19);
@@ -271,7 +273,8 @@ static void LnSWoUB(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigne
271 virt_addr = addr; 273 virt_addr = addr;
272} 274}
273 275
274static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 276static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst,
277 unsigned int& virt_addr) {
275 unsigned int Rn = BITS(inst, 16, 19); 278 unsigned int Rn = BITS(inst, 16, 19);
276 unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn); 279 unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn);
277 280
@@ -283,7 +286,8 @@ static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, u
283 virt_addr = addr; 286 virt_addr = addr;
284} 287}
285 288
286static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 289static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst,
290 unsigned int& virt_addr) {
287 unsigned int Rn = BITS(inst, 16, 19); 291 unsigned int Rn = BITS(inst, 16, 19);
288 unsigned int addr; 292 unsigned int addr;
289 293
@@ -301,7 +305,7 @@ static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, un
301static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 305static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
302 unsigned int addr; 306 unsigned int addr;
303 unsigned int Rn = BITS(inst, 16, 19); 307 unsigned int Rn = BITS(inst, 16, 19);
304 unsigned int Rm = BITS(inst, 0, 3); 308 unsigned int Rm = BITS(inst, 0, 3);
305 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 309 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
306 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 310 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
307 311
@@ -316,7 +320,8 @@ static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsign
316 cpu->Reg[Rn] = addr; 320 cpu->Reg[Rn] = addr;
317} 321}
318 322
319static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 323static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst,
324 unsigned int& virt_addr) {
320 unsigned int Rn = BITS(inst, 16, 19); 325 unsigned int Rn = BITS(inst, 16, 19);
321 unsigned int Rm = BITS(inst, 0, 3); 326 unsigned int Rm = BITS(inst, 0, 3);
322 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 327 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
@@ -335,7 +340,8 @@ static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, uns
335 } 340 }
336} 341}
337 342
338static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 343static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int inst,
344 unsigned int& virt_addr) {
339 unsigned int shift = BITS(inst, 5, 6); 345 unsigned int shift = BITS(inst, 5, 6);
340 unsigned int shift_imm = BITS(inst, 7, 11); 346 unsigned int shift_imm = BITS(inst, 7, 11);
341 unsigned int Rn = BITS(inst, 16, 19); 347 unsigned int Rn = BITS(inst, 16, 19);
@@ -386,7 +392,8 @@ static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int ins
386 cpu->Reg[Rn] = addr; 392 cpu->Reg[Rn] = addr;
387} 393}
388 394
389static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 395static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
396 unsigned int& virt_addr) {
390 unsigned int shift = BITS(inst, 5, 6); 397 unsigned int shift = BITS(inst, 5, 6);
391 unsigned int shift_imm = BITS(inst, 7, 11); 398 unsigned int shift_imm = BITS(inst, 7, 11);
392 unsigned int Rn = BITS(inst, 16, 19); 399 unsigned int Rn = BITS(inst, 16, 19);
@@ -435,9 +442,10 @@ static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int in
435 } 442 }
436} 443}
437 444
438static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 445static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
446 unsigned int& virt_addr) {
439 unsigned int Rn = BITS(inst, 16, 19); 447 unsigned int Rn = BITS(inst, 16, 19);
440 unsigned int Rm = BITS(inst, 0, 3); 448 unsigned int Rm = BITS(inst, 0, 3);
441 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 449 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
442 450
443 virt_addr = CHECK_READ_REG15_WA(cpu, Rn); 451 virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
@@ -454,7 +462,7 @@ static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, un
454static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 462static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
455 unsigned int immedL = BITS(inst, 0, 3); 463 unsigned int immedL = BITS(inst, 0, 3);
456 unsigned int immedH = BITS(inst, 8, 11); 464 unsigned int immedH = BITS(inst, 8, 11);
457 unsigned int Rn = BITS(inst, 16, 19); 465 unsigned int Rn = BITS(inst, 16, 19);
458 unsigned int addr; 466 unsigned int addr;
459 467
460 unsigned int offset_8 = (immedH << 4) | immedL; 468 unsigned int offset_8 = (immedH << 4) | immedL;
@@ -470,7 +478,7 @@ static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned
470static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 478static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
471 unsigned int addr; 479 unsigned int addr;
472 unsigned int Rn = BITS(inst, 16, 19); 480 unsigned int Rn = BITS(inst, 16, 19);
473 unsigned int Rm = BITS(inst, 0, 3); 481 unsigned int Rm = BITS(inst, 0, 3);
474 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 482 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
475 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 483 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
476 484
@@ -482,10 +490,11 @@ static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned i
482 virt_addr = addr; 490 virt_addr = addr;
483} 491}
484 492
485static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 493static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst,
486 unsigned int Rn = BITS(inst, 16, 19); 494 unsigned int& virt_addr) {
487 unsigned int immedH = BITS(inst, 8, 11); 495 unsigned int Rn = BITS(inst, 16, 19);
488 unsigned int immedL = BITS(inst, 0, 3); 496 unsigned int immedH = BITS(inst, 8, 11);
497 unsigned int immedL = BITS(inst, 0, 3);
489 unsigned int addr; 498 unsigned int addr;
490 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 499 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
491 unsigned int offset_8 = (immedH << 4) | immedL; 500 unsigned int offset_8 = (immedH << 4) | immedL;
@@ -501,10 +510,11 @@ static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsig
501 cpu->Reg[Rn] = addr; 510 cpu->Reg[Rn] = addr;
502} 511}
503 512
504static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 513static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst,
505 unsigned int Rn = BITS(inst, 16, 19); 514 unsigned int& virt_addr) {
506 unsigned int immedH = BITS(inst, 8, 11); 515 unsigned int Rn = BITS(inst, 16, 19);
507 unsigned int immedL = BITS(inst, 0, 3); 516 unsigned int immedH = BITS(inst, 8, 11);
517 unsigned int immedL = BITS(inst, 0, 3);
508 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 518 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
509 519
510 virt_addr = rn; 520 virt_addr = rn;
@@ -520,9 +530,10 @@ static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, unsi
520 } 530 }
521} 531}
522 532
523static void MLnS(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 533static void MLnS(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
534 unsigned int& virt_addr) {
524 unsigned int Rn = BITS(inst, 16, 19); 535 unsigned int Rn = BITS(inst, 16, 19);
525 unsigned int Rm = BITS(inst, 0, 3); 536 unsigned int Rm = BITS(inst, 0, 3);
526 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 537 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
527 538
528 virt_addr = CHECK_READ_REG15_WA(cpu, Rn); 539 virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
@@ -541,7 +552,8 @@ static void LdnStM(DecrementBefore)(ARMul_State* cpu, unsigned int inst, unsigne
541 int count = 0; 552 int count = 0;
542 553
543 while (i) { 554 while (i) {
544 if (i & 1) count++; 555 if (i & 1)
556 count++;
545 i = i >> 1; 557 i = i >> 1;
546 } 558 }
547 559
@@ -557,7 +569,8 @@ static void LdnStM(IncrementBefore)(ARMul_State* cpu, unsigned int inst, unsigne
557 int count = 0; 569 int count = 0;
558 570
559 while (i) { 571 while (i) {
560 if (i & 1) count++; 572 if (i & 1)
573 count++;
561 i = i >> 1; 574 i = i >> 1;
562 } 575 }
563 576
@@ -572,8 +585,9 @@ static void LdnStM(IncrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned
572 unsigned int i = BITS(inst, 0, 15); 585 unsigned int i = BITS(inst, 0, 15);
573 int count = 0; 586 int count = 0;
574 587
575 while(i) { 588 while (i) {
576 if (i & 1) count++; 589 if (i & 1)
590 count++;
577 i = i >> 1; 591 i = i >> 1;
578 } 592 }
579 593
@@ -587,8 +601,9 @@ static void LdnStM(DecrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned
587 unsigned int Rn = BITS(inst, 16, 19); 601 unsigned int Rn = BITS(inst, 16, 19);
588 unsigned int i = BITS(inst, 0, 15); 602 unsigned int i = BITS(inst, 0, 15);
589 int count = 0; 603 int count = 0;
590 while(i) { 604 while (i) {
591 if(i & 1) count++; 605 if (i & 1)
606 count++;
592 i = i >> 1; 607 i = i >> 1;
593 } 608 }
594 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 609 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
@@ -601,7 +616,8 @@ static void LdnStM(DecrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned
601 } 616 }
602} 617}
603 618
604static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 619static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst,
620 unsigned int& virt_addr) {
605 unsigned int shift = BITS(inst, 5, 6); 621 unsigned int shift = BITS(inst, 5, 6);
606 unsigned int shift_imm = BITS(inst, 7, 11); 622 unsigned int shift_imm = BITS(inst, 7, 11);
607 unsigned int Rn = BITS(inst, 16, 19); 623 unsigned int Rn = BITS(inst, 16, 19);
@@ -693,17 +709,23 @@ get_addr_fp_t GetAddressingOp(unsigned int inst) {
693 return LnSWoUB(RegisterPostIndexed); 709 return LnSWoUB(RegisterPostIndexed);
694 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) { 710 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
695 return LnSWoUB(ScaledRegisterPostIndexed); 711 return LnSWoUB(ScaledRegisterPostIndexed);
696 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 712 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 &&
713 BIT(inst, 4) == 1) {
697 return MLnS(ImmediateOffset); 714 return MLnS(ImmediateOffset);
698 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 715 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 &&
716 BIT(inst, 4) == 1) {
699 return MLnS(RegisterOffset); 717 return MLnS(RegisterOffset);
700 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 718 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 &&
719 BIT(inst, 4) == 1) {
701 return MLnS(ImmediatePreIndexed); 720 return MLnS(ImmediatePreIndexed);
702 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 721 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 &&
722 BIT(inst, 4) == 1) {
703 return MLnS(RegisterPreIndexed); 723 return MLnS(RegisterPreIndexed);
704 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 724 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 &&
725 BIT(inst, 4) == 1) {
705 return MLnS(ImmediatePostIndexed); 726 return MLnS(ImmediatePostIndexed);
706 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 727 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 &&
728 BIT(inst, 4) == 1) {
707 return MLnS(RegisterPostIndexed); 729 return MLnS(RegisterPostIndexed);
708 } else if (BITS(inst, 23, 27) == 0x11) { 730 } else if (BITS(inst, 23, 27) == 0x11) {
709 return LdnStM(IncrementAfter); 731 return LdnStM(IncrementAfter);
@@ -732,14 +754,12 @@ get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst) {
732 return nullptr; 754 return nullptr;
733} 755}
734 756
735enum { 757enum { FETCH_SUCCESS, FETCH_FAILURE };
736 FETCH_SUCCESS,
737 FETCH_FAILURE
738};
739 758
740static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { 759static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size,
760 ARM_INST_PTR* ptr_inst_base) {
741 // Check if in Thumb mode 761 // Check if in Thumb mode
742 ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size); 762 ThumbDecodeStatus ret = TranslateThumbInstruction(addr, inst, arm_inst, inst_size);
743 if (ret == ThumbDecodeStatus::BRANCH) { 763 if (ret == ThumbDecodeStatus::BRANCH) {
744 int inst_index; 764 int inst_index;
745 int table_length = arm_instruction_trans_len; 765 int table_length = arm_instruction_trans_len;
@@ -748,7 +768,7 @@ static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_ins
748 switch ((tinstr & 0xF800) >> 11) { 768 switch ((tinstr & 0xF800) >> 11) {
749 case 26: 769 case 26:
750 case 27: 770 case 27:
751 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ 771 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)) {
752 inst_index = table_length - 4; 772 inst_index = table_length - 4;
753 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); 773 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
754 } else { 774 } else {
@@ -785,21 +805,21 @@ static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_ins
785 return ret; 805 return ret;
786} 806}
787 807
788enum { 808enum { KEEP_GOING, FETCH_EXCEPTION };
789 KEEP_GOING,
790 FETCH_EXCEPTION
791};
792 809
793MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); 810MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64));
794 811
795static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, ARM_INST_PTR& inst_base) { 812static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr,
813 ARM_INST_PTR& inst_base) {
796 unsigned int inst_size = 4; 814 unsigned int inst_size = 4;
797 unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC); 815 unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
798 816
799 // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction 817 // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM
818 // instruction
800 if (cpu->TFlag) { 819 if (cpu->TFlag) {
801 u32 arm_inst; 820 u32 arm_inst;
802 ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); 821 ThumbDecodeStatus state =
822 DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
803 823
804 // We have translated the Thumb branch instruction in the Thumb decoder 824 // We have translated the Thumb branch instruction in the Thumb decoder
805 if (state == ThumbDecodeStatus::BRANCH) { 825 if (state == ThumbDecodeStatus::BRANCH) {
@@ -811,8 +831,10 @@ static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, cons
811 int idx; 831 int idx;
812 if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { 832 if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
813 std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); 833 std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst);
814 LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst); 834 LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr,
815 LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]); 835 disasm.c_str(), inst);
836 LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag,
837 cpu->Reg[15]);
816 CITRA_IGNORE_EXIT(-1); 838 CITRA_IGNORE_EXIT(-1);
817 } 839 }
818 inst_base = arm_instruction_trans[idx](inst, idx); 840 inst_base = arm_instruction_trans[idx](inst, idx);
@@ -875,12 +897,25 @@ static int InterpreterTranslateSingle(ARMul_State* cpu, int& bb_start, u32 addr)
875 897
876static int clz(unsigned int x) { 898static int clz(unsigned int x) {
877 int n; 899 int n;
878 if (x == 0) return (32); 900 if (x == 0)
901 return (32);
879 n = 1; 902 n = 1;
880 if ((x >> 16) == 0) { n = n + 16; x = x << 16;} 903 if ((x >> 16) == 0) {
881 if ((x >> 24) == 0) { n = n + 8; x = x << 8;} 904 n = n + 16;
882 if ((x >> 28) == 0) { n = n + 4; x = x << 4;} 905 x = x << 16;
883 if ((x >> 30) == 0) { n = n + 2; x = x << 2;} 906 }
907 if ((x >> 24) == 0) {
908 n = n + 8;
909 x = x << 8;
910 }
911 if ((x >> 28) == 0) {
912 n = n + 4;
913 x = x << 4;
914 }
915 if ((x >> 30) == 0) {
916 n = n + 2;
917 x = x << 2;
918 }
884 n = n - (x >> 31); 919 n = n - (x >> 31);
885 return n; 920 return n;
886} 921}
@@ -892,310 +927,698 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
892 927
893 GDBStub::BreakpointAddress breakpoint_data; 928 GDBStub::BreakpointAddress breakpoint_data;
894 929
895 #undef RM 930#undef RM
896 #undef RS 931#undef RS
897 932
898 #define CRn inst_cream->crn 933#define CRn inst_cream->crn
899 #define OPCODE_1 inst_cream->opcode_1 934#define OPCODE_1 inst_cream->opcode_1
900 #define OPCODE_2 inst_cream->opcode_2 935#define OPCODE_2 inst_cream->opcode_2
901 #define CRm inst_cream->crm 936#define CRm inst_cream->crm
902 #define RD cpu->Reg[inst_cream->Rd] 937#define RD cpu->Reg[inst_cream->Rd]
903 #define RD2 cpu->Reg[inst_cream->Rd + 1] 938#define RD2 cpu->Reg[inst_cream->Rd + 1]
904 #define RN cpu->Reg[inst_cream->Rn] 939#define RN cpu->Reg[inst_cream->Rn]
905 #define RM cpu->Reg[inst_cream->Rm] 940#define RM cpu->Reg[inst_cream->Rm]
906 #define RS cpu->Reg[inst_cream->Rs] 941#define RS cpu->Reg[inst_cream->Rs]
907 #define RDHI cpu->Reg[inst_cream->RdHi] 942#define RDHI cpu->Reg[inst_cream->RdHi]
908 #define RDLO cpu->Reg[inst_cream->RdLo] 943#define RDLO cpu->Reg[inst_cream->RdLo]
909 #define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4) 944#define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4)
910 #define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24) 945#define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24)
911 #define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand) 946#define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand)
912 947
913 #define FETCH_INST if (inst_base->br != TransExtData::NON_BRANCH) goto DISPATCH; \ 948#define FETCH_INST \
914 inst_base = (arm_inst *)&trans_cache_buf[ptr] 949 if (inst_base->br != TransExtData::NON_BRANCH) \
915 950 goto DISPATCH; \
916 #define INC_PC(l) ptr += sizeof(arm_inst) + l 951 inst_base = (arm_inst*)&trans_cache_buf[ptr]
917 #define INC_PC_STUB ptr += sizeof(arm_inst) 952
918 953#define INC_PC(l) ptr += sizeof(arm_inst) + l
919#define GDB_BP_CHECK \ 954#define INC_PC_STUB ptr += sizeof(arm_inst)
920 cpu->Cpsr &= ~(1 << 5); \ 955
921 cpu->Cpsr |= cpu->TFlag << 5; \ 956#define GDB_BP_CHECK \
922 if (GDBStub::g_server_enabled) { \ 957 cpu->Cpsr &= ~(1 << 5); \
923 if (GDBStub::IsMemoryBreak() || (breakpoint_data.type != GDBStub::BreakpointType::None && PC == breakpoint_data.address)) { \ 958 cpu->Cpsr |= cpu->TFlag << 5; \
924 GDBStub::Break(); \ 959 if (GDBStub::g_server_enabled) { \
925 goto END; \ 960 if (GDBStub::IsMemoryBreak() || (breakpoint_data.type != GDBStub::BreakpointType::None && \
926 } \ 961 PC == breakpoint_data.address)) { \
962 GDBStub::Break(); \
963 goto END; \
964 } \
927 } 965 }
928 966
929// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a 967// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a
930// clunky switch statement. 968// clunky switch statement.
931#if defined __GNUC__ || defined __clang__ 969#if defined __GNUC__ || defined __clang__
932#define GOTO_NEXT_INST \ 970#define GOTO_NEXT_INST \
933 GDB_BP_CHECK; \ 971 GDB_BP_CHECK; \
934 if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ 972 if (num_instrs >= cpu->NumInstrsToExecute) \
935 num_instrs++; \ 973 goto END; \
936 goto *InstLabel[inst_base->idx] 974 num_instrs++; \
975 goto* InstLabel[inst_base->idx]
937#else 976#else
938#define GOTO_NEXT_INST \ 977#define GOTO_NEXT_INST \
939 GDB_BP_CHECK; \ 978 GDB_BP_CHECK; \
940 if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ 979 if (num_instrs >= cpu->NumInstrsToExecute) \
941 num_instrs++; \ 980 goto END; \
942 switch(inst_base->idx) { \ 981 num_instrs++; \
943 case 0: goto VMLA_INST; \ 982 switch (inst_base->idx) { \
944 case 1: goto VMLS_INST; \ 983 case 0: \
945 case 2: goto VNMLA_INST; \ 984 goto VMLA_INST; \
946 case 3: goto VNMLS_INST; \ 985 case 1: \
947 case 4: goto VNMUL_INST; \ 986 goto VMLS_INST; \
948 case 5: goto VMUL_INST; \ 987 case 2: \
949 case 6: goto VADD_INST; \ 988 goto VNMLA_INST; \
950 case 7: goto VSUB_INST; \ 989 case 3: \
951 case 8: goto VDIV_INST; \ 990 goto VNMLS_INST; \
952 case 9: goto VMOVI_INST; \ 991 case 4: \
953 case 10: goto VMOVR_INST; \ 992 goto VNMUL_INST; \
954 case 11: goto VABS_INST; \ 993 case 5: \
955 case 12: goto VNEG_INST; \ 994 goto VMUL_INST; \
956 case 13: goto VSQRT_INST; \ 995 case 6: \
957 case 14: goto VCMP_INST; \ 996 goto VADD_INST; \
958 case 15: goto VCMP2_INST; \ 997 case 7: \
959 case 16: goto VCVTBDS_INST; \ 998 goto VSUB_INST; \
960 case 17: goto VCVTBFF_INST; \ 999 case 8: \
961 case 18: goto VCVTBFI_INST; \ 1000 goto VDIV_INST; \
962 case 19: goto VMOVBRS_INST; \ 1001 case 9: \
963 case 20: goto VMSR_INST; \ 1002 goto VMOVI_INST; \
964 case 21: goto VMOVBRC_INST; \ 1003 case 10: \
965 case 22: goto VMRS_INST; \ 1004 goto VMOVR_INST; \
966 case 23: goto VMOVBCR_INST; \ 1005 case 11: \
967 case 24: goto VMOVBRRSS_INST; \ 1006 goto VABS_INST; \
968 case 25: goto VMOVBRRD_INST; \ 1007 case 12: \
969 case 26: goto VSTR_INST; \ 1008 goto VNEG_INST; \
970 case 27: goto VPUSH_INST; \ 1009 case 13: \
971 case 28: goto VSTM_INST; \ 1010 goto VSQRT_INST; \
972 case 29: goto VPOP_INST; \ 1011 case 14: \
973 case 30: goto VLDR_INST; \ 1012 goto VCMP_INST; \
974 case 31: goto VLDM_INST ; \ 1013 case 15: \
975 case 32: goto SRS_INST; \ 1014 goto VCMP2_INST; \
976 case 33: goto RFE_INST; \ 1015 case 16: \
977 case 34: goto BKPT_INST; \ 1016 goto VCVTBDS_INST; \
978 case 35: goto BLX_INST; \ 1017 case 17: \
979 case 36: goto CPS_INST; \ 1018 goto VCVTBFF_INST; \
980 case 37: goto PLD_INST; \ 1019 case 18: \
981 case 38: goto SETEND_INST; \ 1020 goto VCVTBFI_INST; \
982 case 39: goto CLREX_INST; \ 1021 case 19: \
983 case 40: goto REV16_INST; \ 1022 goto VMOVBRS_INST; \
984 case 41: goto USAD8_INST; \ 1023 case 20: \
985 case 42: goto SXTB_INST; \ 1024 goto VMSR_INST; \
986 case 43: goto UXTB_INST; \ 1025 case 21: \
987 case 44: goto SXTH_INST; \ 1026 goto VMOVBRC_INST; \
988 case 45: goto SXTB16_INST; \ 1027 case 22: \
989 case 46: goto UXTH_INST; \ 1028 goto VMRS_INST; \
990 case 47: goto UXTB16_INST; \ 1029 case 23: \
991 case 48: goto CPY_INST; \ 1030 goto VMOVBCR_INST; \
992 case 49: goto UXTAB_INST; \ 1031 case 24: \
993 case 50: goto SSUB8_INST; \ 1032 goto VMOVBRRSS_INST; \
994 case 51: goto SHSUB8_INST; \ 1033 case 25: \
995 case 52: goto SSUBADDX_INST; \ 1034 goto VMOVBRRD_INST; \
996 case 53: goto STREX_INST; \ 1035 case 26: \
997 case 54: goto STREXB_INST; \ 1036 goto VSTR_INST; \
998 case 55: goto SWP_INST; \ 1037 case 27: \
999 case 56: goto SWPB_INST; \ 1038 goto VPUSH_INST; \
1000 case 57: goto SSUB16_INST; \ 1039 case 28: \
1001 case 58: goto SSAT16_INST; \ 1040 goto VSTM_INST; \
1002 case 59: goto SHSUBADDX_INST; \ 1041 case 29: \
1003 case 60: goto QSUBADDX_INST; \ 1042 goto VPOP_INST; \
1004 case 61: goto SHADDSUBX_INST; \ 1043 case 30: \
1005 case 62: goto SHADD8_INST; \ 1044 goto VLDR_INST; \
1006 case 63: goto SHADD16_INST; \ 1045 case 31: \
1007 case 64: goto SEL_INST; \ 1046 goto VLDM_INST; \
1008 case 65: goto SADDSUBX_INST; \ 1047 case 32: \
1009 case 66: goto SADD8_INST; \ 1048 goto SRS_INST; \
1010 case 67: goto SADD16_INST; \ 1049 case 33: \
1011 case 68: goto SHSUB16_INST; \ 1050 goto RFE_INST; \
1012 case 69: goto UMAAL_INST; \ 1051 case 34: \
1013 case 70: goto UXTAB16_INST; \ 1052 goto BKPT_INST; \
1014 case 71: goto USUBADDX_INST; \ 1053 case 35: \
1015 case 72: goto USUB8_INST; \ 1054 goto BLX_INST; \
1016 case 73: goto USUB16_INST; \ 1055 case 36: \
1017 case 74: goto USAT16_INST; \ 1056 goto CPS_INST; \
1018 case 75: goto USADA8_INST; \ 1057 case 37: \
1019 case 76: goto UQSUBADDX_INST; \ 1058 goto PLD_INST; \
1020 case 77: goto UQSUB8_INST; \ 1059 case 38: \
1021 case 78: goto UQSUB16_INST; \ 1060 goto SETEND_INST; \
1022 case 79: goto UQADDSUBX_INST; \ 1061 case 39: \
1023 case 80: goto UQADD8_INST; \ 1062 goto CLREX_INST; \
1024 case 81: goto UQADD16_INST; \ 1063 case 40: \
1025 case 82: goto SXTAB_INST; \ 1064 goto REV16_INST; \
1026 case 83: goto UHSUBADDX_INST; \ 1065 case 41: \
1027 case 84: goto UHSUB8_INST; \ 1066 goto USAD8_INST; \
1028 case 85: goto UHSUB16_INST; \ 1067 case 42: \
1029 case 86: goto UHADDSUBX_INST; \ 1068 goto SXTB_INST; \
1030 case 87: goto UHADD8_INST; \ 1069 case 43: \
1031 case 88: goto UHADD16_INST; \ 1070 goto UXTB_INST; \
1032 case 89: goto UADDSUBX_INST; \ 1071 case 44: \
1033 case 90: goto UADD8_INST; \ 1072 goto SXTH_INST; \
1034 case 91: goto UADD16_INST; \ 1073 case 45: \
1035 case 92: goto SXTAH_INST; \ 1074 goto SXTB16_INST; \
1036 case 93: goto SXTAB16_INST; \ 1075 case 46: \
1037 case 94: goto QADD8_INST; \ 1076 goto UXTH_INST; \
1038 case 95: goto BXJ_INST; \ 1077 case 47: \
1039 case 96: goto CLZ_INST; \ 1078 goto UXTB16_INST; \
1040 case 97: goto UXTAH_INST; \ 1079 case 48: \
1041 case 98: goto BX_INST; \ 1080 goto CPY_INST; \
1042 case 99: goto REV_INST; \ 1081 case 49: \
1043 case 100: goto BLX_INST; \ 1082 goto UXTAB_INST; \
1044 case 101: goto REVSH_INST; \ 1083 case 50: \
1045 case 102: goto QADD_INST; \ 1084 goto SSUB8_INST; \
1046 case 103: goto QADD16_INST; \ 1085 case 51: \
1047 case 104: goto QADDSUBX_INST; \ 1086 goto SHSUB8_INST; \
1048 case 105: goto LDREX_INST; \ 1087 case 52: \
1049 case 106: goto QDADD_INST; \ 1088 goto SSUBADDX_INST; \
1050 case 107: goto QDSUB_INST; \ 1089 case 53: \
1051 case 108: goto QSUB_INST; \ 1090 goto STREX_INST; \
1052 case 109: goto LDREXB_INST; \ 1091 case 54: \
1053 case 110: goto QSUB8_INST; \ 1092 goto STREXB_INST; \
1054 case 111: goto QSUB16_INST; \ 1093 case 55: \
1055 case 112: goto SMUAD_INST; \ 1094 goto SWP_INST; \
1056 case 113: goto SMMUL_INST; \ 1095 case 56: \
1057 case 114: goto SMUSD_INST; \ 1096 goto SWPB_INST; \
1058 case 115: goto SMLSD_INST; \ 1097 case 57: \
1059 case 116: goto SMLSLD_INST; \ 1098 goto SSUB16_INST; \
1060 case 117: goto SMMLA_INST; \ 1099 case 58: \
1061 case 118: goto SMMLS_INST; \ 1100 goto SSAT16_INST; \
1062 case 119: goto SMLALD_INST; \ 1101 case 59: \
1063 case 120: goto SMLAD_INST; \ 1102 goto SHSUBADDX_INST; \
1064 case 121: goto SMLAW_INST; \ 1103 case 60: \
1065 case 122: goto SMULW_INST; \ 1104 goto QSUBADDX_INST; \
1066 case 123: goto PKHTB_INST; \ 1105 case 61: \
1067 case 124: goto PKHBT_INST; \ 1106 goto SHADDSUBX_INST; \
1068 case 125: goto SMUL_INST; \ 1107 case 62: \
1069 case 126: goto SMLALXY_INST; \ 1108 goto SHADD8_INST; \
1070 case 127: goto SMLA_INST; \ 1109 case 63: \
1071 case 128: goto MCRR_INST; \ 1110 goto SHADD16_INST; \
1072 case 129: goto MRRC_INST; \ 1111 case 64: \
1073 case 130: goto CMP_INST; \ 1112 goto SEL_INST; \
1074 case 131: goto TST_INST; \ 1113 case 65: \
1075 case 132: goto TEQ_INST; \ 1114 goto SADDSUBX_INST; \
1076 case 133: goto CMN_INST; \ 1115 case 66: \
1077 case 134: goto SMULL_INST; \ 1116 goto SADD8_INST; \
1078 case 135: goto UMULL_INST; \ 1117 case 67: \
1079 case 136: goto UMLAL_INST; \ 1118 goto SADD16_INST; \
1080 case 137: goto SMLAL_INST; \ 1119 case 68: \
1081 case 138: goto MUL_INST; \ 1120 goto SHSUB16_INST; \
1082 case 139: goto MLA_INST; \ 1121 case 69: \
1083 case 140: goto SSAT_INST; \ 1122 goto UMAAL_INST; \
1084 case 141: goto USAT_INST; \ 1123 case 70: \
1085 case 142: goto MRS_INST; \ 1124 goto UXTAB16_INST; \
1086 case 143: goto MSR_INST; \ 1125 case 71: \
1087 case 144: goto AND_INST; \ 1126 goto USUBADDX_INST; \
1088 case 145: goto BIC_INST; \ 1127 case 72: \
1089 case 146: goto LDM_INST; \ 1128 goto USUB8_INST; \
1090 case 147: goto EOR_INST; \ 1129 case 73: \
1091 case 148: goto ADD_INST; \ 1130 goto USUB16_INST; \
1092 case 149: goto RSB_INST; \ 1131 case 74: \
1093 case 150: goto RSC_INST; \ 1132 goto USAT16_INST; \
1094 case 151: goto SBC_INST; \ 1133 case 75: \
1095 case 152: goto ADC_INST; \ 1134 goto USADA8_INST; \
1096 case 153: goto SUB_INST; \ 1135 case 76: \
1097 case 154: goto ORR_INST; \ 1136 goto UQSUBADDX_INST; \
1098 case 155: goto MVN_INST; \ 1137 case 77: \
1099 case 156: goto MOV_INST; \ 1138 goto UQSUB8_INST; \
1100 case 157: goto STM_INST; \ 1139 case 78: \
1101 case 158: goto LDM_INST; \ 1140 goto UQSUB16_INST; \
1102 case 159: goto LDRSH_INST; \ 1141 case 79: \
1103 case 160: goto STM_INST; \ 1142 goto UQADDSUBX_INST; \
1104 case 161: goto LDM_INST; \ 1143 case 80: \
1105 case 162: goto LDRSB_INST; \ 1144 goto UQADD8_INST; \
1106 case 163: goto STRD_INST; \ 1145 case 81: \
1107 case 164: goto LDRH_INST; \ 1146 goto UQADD16_INST; \
1108 case 165: goto STRH_INST; \ 1147 case 82: \
1109 case 166: goto LDRD_INST; \ 1148 goto SXTAB_INST; \
1110 case 167: goto STRT_INST; \ 1149 case 83: \
1111 case 168: goto STRBT_INST; \ 1150 goto UHSUBADDX_INST; \
1112 case 169: goto LDRBT_INST; \ 1151 case 84: \
1113 case 170: goto LDRT_INST; \ 1152 goto UHSUB8_INST; \
1114 case 171: goto MRC_INST; \ 1153 case 85: \
1115 case 172: goto MCR_INST; \ 1154 goto UHSUB16_INST; \
1116 case 173: goto MSR_INST; \ 1155 case 86: \
1117 case 174: goto MSR_INST; \ 1156 goto UHADDSUBX_INST; \
1118 case 175: goto MSR_INST; \ 1157 case 87: \
1119 case 176: goto MSR_INST; \ 1158 goto UHADD8_INST; \
1120 case 177: goto MSR_INST; \ 1159 case 88: \
1121 case 178: goto LDRB_INST; \ 1160 goto UHADD16_INST; \
1122 case 179: goto STRB_INST; \ 1161 case 89: \
1123 case 180: goto LDR_INST; \ 1162 goto UADDSUBX_INST; \
1124 case 181: goto LDRCOND_INST ; \ 1163 case 90: \
1125 case 182: goto STR_INST; \ 1164 goto UADD8_INST; \
1126 case 183: goto CDP_INST; \ 1165 case 91: \
1127 case 184: goto STC_INST; \ 1166 goto UADD16_INST; \
1128 case 185: goto LDC_INST; \ 1167 case 92: \
1129 case 186: goto LDREXD_INST; \ 1168 goto SXTAH_INST; \
1130 case 187: goto STREXD_INST; \ 1169 case 93: \
1131 case 188: goto LDREXH_INST; \ 1170 goto SXTAB16_INST; \
1132 case 189: goto STREXH_INST; \ 1171 case 94: \
1133 case 190: goto NOP_INST; \ 1172 goto QADD8_INST; \
1134 case 191: goto YIELD_INST; \ 1173 case 95: \
1135 case 192: goto WFE_INST; \ 1174 goto BXJ_INST; \
1136 case 193: goto WFI_INST; \ 1175 case 96: \
1137 case 194: goto SEV_INST; \ 1176 goto CLZ_INST; \
1138 case 195: goto SWI_INST; \ 1177 case 97: \
1139 case 196: goto BBL_INST; \ 1178 goto UXTAH_INST; \
1140 case 197: goto B_2_THUMB ; \ 1179 case 98: \
1141 case 198: goto B_COND_THUMB ; \ 1180 goto BX_INST; \
1142 case 199: goto BL_1_THUMB ; \ 1181 case 99: \
1143 case 200: goto BL_2_THUMB ; \ 1182 goto REV_INST; \
1144 case 201: goto BLX_1_THUMB ; \ 1183 case 100: \
1145 case 202: goto DISPATCH; \ 1184 goto BLX_INST; \
1146 case 203: goto INIT_INST_LENGTH; \ 1185 case 101: \
1147 case 204: goto END; \ 1186 goto REVSH_INST; \
1187 case 102: \
1188 goto QADD_INST; \
1189 case 103: \
1190 goto QADD16_INST; \
1191 case 104: \
1192 goto QADDSUBX_INST; \
1193 case 105: \
1194 goto LDREX_INST; \
1195 case 106: \
1196 goto QDADD_INST; \
1197 case 107: \
1198 goto QDSUB_INST; \
1199 case 108: \
1200 goto QSUB_INST; \
1201 case 109: \
1202 goto LDREXB_INST; \
1203 case 110: \
1204 goto QSUB8_INST; \
1205 case 111: \
1206 goto QSUB16_INST; \
1207 case 112: \
1208 goto SMUAD_INST; \
1209 case 113: \
1210 goto SMMUL_INST; \
1211 case 114: \
1212 goto SMUSD_INST; \
1213 case 115: \
1214 goto SMLSD_INST; \
1215 case 116: \
1216 goto SMLSLD_INST; \
1217 case 117: \
1218 goto SMMLA_INST; \
1219 case 118: \
1220 goto SMMLS_INST; \
1221 case 119: \
1222 goto SMLALD_INST; \
1223 case 120: \
1224 goto SMLAD_INST; \
1225 case 121: \
1226 goto SMLAW_INST; \
1227 case 122: \
1228 goto SMULW_INST; \
1229 case 123: \
1230 goto PKHTB_INST; \
1231 case 124: \
1232 goto PKHBT_INST; \
1233 case 125: \
1234 goto SMUL_INST; \
1235 case 126: \
1236 goto SMLALXY_INST; \
1237 case 127: \
1238 goto SMLA_INST; \
1239 case 128: \
1240 goto MCRR_INST; \
1241 case 129: \
1242 goto MRRC_INST; \
1243 case 130: \
1244 goto CMP_INST; \
1245 case 131: \
1246 goto TST_INST; \
1247 case 132: \
1248 goto TEQ_INST; \
1249 case 133: \
1250 goto CMN_INST; \
1251 case 134: \
1252 goto SMULL_INST; \
1253 case 135: \
1254 goto UMULL_INST; \
1255 case 136: \
1256 goto UMLAL_INST; \
1257 case 137: \
1258 goto SMLAL_INST; \
1259 case 138: \
1260 goto MUL_INST; \
1261 case 139: \
1262 goto MLA_INST; \
1263 case 140: \
1264 goto SSAT_INST; \
1265 case 141: \
1266 goto USAT_INST; \
1267 case 142: \
1268 goto MRS_INST; \
1269 case 143: \
1270 goto MSR_INST; \
1271 case 144: \
1272 goto AND_INST; \
1273 case 145: \
1274 goto BIC_INST; \
1275 case 146: \
1276 goto LDM_INST; \
1277 case 147: \
1278 goto EOR_INST; \
1279 case 148: \
1280 goto ADD_INST; \
1281 case 149: \
1282 goto RSB_INST; \
1283 case 150: \
1284 goto RSC_INST; \
1285 case 151: \
1286 goto SBC_INST; \
1287 case 152: \
1288 goto ADC_INST; \
1289 case 153: \
1290 goto SUB_INST; \
1291 case 154: \
1292 goto ORR_INST; \
1293 case 155: \
1294 goto MVN_INST; \
1295 case 156: \
1296 goto MOV_INST; \
1297 case 157: \
1298 goto STM_INST; \
1299 case 158: \
1300 goto LDM_INST; \
1301 case 159: \
1302 goto LDRSH_INST; \
1303 case 160: \
1304 goto STM_INST; \
1305 case 161: \
1306 goto LDM_INST; \
1307 case 162: \
1308 goto LDRSB_INST; \
1309 case 163: \
1310 goto STRD_INST; \
1311 case 164: \
1312 goto LDRH_INST; \
1313 case 165: \
1314 goto STRH_INST; \
1315 case 166: \
1316 goto LDRD_INST; \
1317 case 167: \
1318 goto STRT_INST; \
1319 case 168: \
1320 goto STRBT_INST; \
1321 case 169: \
1322 goto LDRBT_INST; \
1323 case 170: \
1324 goto LDRT_INST; \
1325 case 171: \
1326 goto MRC_INST; \
1327 case 172: \
1328 goto MCR_INST; \
1329 case 173: \
1330 goto MSR_INST; \
1331 case 174: \
1332 goto MSR_INST; \
1333 case 175: \
1334 goto MSR_INST; \
1335 case 176: \
1336 goto MSR_INST; \
1337 case 177: \
1338 goto MSR_INST; \
1339 case 178: \
1340 goto LDRB_INST; \
1341 case 179: \
1342 goto STRB_INST; \
1343 case 180: \
1344 goto LDR_INST; \
1345 case 181: \
1346 goto LDRCOND_INST; \
1347 case 182: \
1348 goto STR_INST; \
1349 case 183: \
1350 goto CDP_INST; \
1351 case 184: \
1352 goto STC_INST; \
1353 case 185: \
1354 goto LDC_INST; \
1355 case 186: \
1356 goto LDREXD_INST; \
1357 case 187: \
1358 goto STREXD_INST; \
1359 case 188: \
1360 goto LDREXH_INST; \
1361 case 189: \
1362 goto STREXH_INST; \
1363 case 190: \
1364 goto NOP_INST; \
1365 case 191: \
1366 goto YIELD_INST; \
1367 case 192: \
1368 goto WFE_INST; \
1369 case 193: \
1370 goto WFI_INST; \
1371 case 194: \
1372 goto SEV_INST; \
1373 case 195: \
1374 goto SWI_INST; \
1375 case 196: \
1376 goto BBL_INST; \
1377 case 197: \
1378 goto B_2_THUMB; \
1379 case 198: \
1380 goto B_COND_THUMB; \
1381 case 199: \
1382 goto BL_1_THUMB; \
1383 case 200: \
1384 goto BL_2_THUMB; \
1385 case 201: \
1386 goto BLX_1_THUMB; \
1387 case 202: \
1388 goto DISPATCH; \
1389 case 203: \
1390 goto INIT_INST_LENGTH; \
1391 case 204: \
1392 goto END; \
1148 } 1393 }
1149#endif 1394#endif
1150 1395
1151 #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0) 1396#define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0)
1152 #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1) 1397#define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1)
1153 #define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out) 1398#define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out)
1154 1399
1155 #define SAVE_NZCVT cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | \ 1400#define SAVE_NZCVT \
1156 (cpu->NFlag << 31) | \ 1401 cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | (cpu->NFlag << 31) | (cpu->ZFlag << 30) | \
1157 (cpu->ZFlag << 30) | \ 1402 (cpu->CFlag << 29) | (cpu->VFlag << 28) | (cpu->TFlag << 5)
1158 (cpu->CFlag << 29) | \ 1403#define LOAD_NZCVT \
1159 (cpu->VFlag << 28) | \ 1404 cpu->NFlag = (cpu->Cpsr >> 31); \
1160 (cpu->TFlag << 5) 1405 cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \
1161 #define LOAD_NZCVT cpu->NFlag = (cpu->Cpsr >> 31); \ 1406 cpu->CFlag = (cpu->Cpsr >> 29) & 1; \
1162 cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \ 1407 cpu->VFlag = (cpu->Cpsr >> 28) & 1; \
1163 cpu->CFlag = (cpu->Cpsr >> 29) & 1; \ 1408 cpu->TFlag = (cpu->Cpsr >> 5) & 1;
1164 cpu->VFlag = (cpu->Cpsr >> 28) & 1; \ 1409
1165 cpu->TFlag = (cpu->Cpsr >> 5) & 1; 1410#define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE)
1166 1411#define PC (cpu->Reg[15])
1167 #define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE) 1412
1168 #define PC (cpu->Reg[15]) 1413// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback
1169 1414// to a clunky switch statement.
1170 // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback
1171 // to a clunky switch statement.
1172#if defined __GNUC__ || defined __clang__ 1415#if defined __GNUC__ || defined __clang__
1173 void *InstLabel[] = { 1416 void* InstLabel[] = {&&VMLA_INST,
1174 &&VMLA_INST, &&VMLS_INST, &&VNMLA_INST, &&VNMLS_INST, &&VNMUL_INST, &&VMUL_INST, &&VADD_INST, &&VSUB_INST, 1417 &&VMLS_INST,
1175 &&VDIV_INST, &&VMOVI_INST, &&VMOVR_INST, &&VABS_INST, &&VNEG_INST, &&VSQRT_INST, &&VCMP_INST, &&VCMP2_INST, &&VCVTBDS_INST, 1418 &&VNMLA_INST,
1176 &&VCVTBFF_INST, &&VCVTBFI_INST, &&VMOVBRS_INST, &&VMSR_INST, &&VMOVBRC_INST, &&VMRS_INST, &&VMOVBCR_INST, &&VMOVBRRSS_INST, 1419 &&VNMLS_INST,
1177 &&VMOVBRRD_INST, &&VSTR_INST, &&VPUSH_INST, &&VSTM_INST, &&VPOP_INST, &&VLDR_INST, &&VLDM_INST, 1420 &&VNMUL_INST,
1178 1421 &&VMUL_INST,
1179 &&SRS_INST,&&RFE_INST,&&BKPT_INST,&&BLX_INST,&&CPS_INST,&&PLD_INST,&&SETEND_INST,&&CLREX_INST,&&REV16_INST,&&USAD8_INST,&&SXTB_INST, 1422 &&VADD_INST,
1180 &&UXTB_INST,&&SXTH_INST,&&SXTB16_INST,&&UXTH_INST,&&UXTB16_INST,&&CPY_INST,&&UXTAB_INST,&&SSUB8_INST,&&SHSUB8_INST,&&SSUBADDX_INST, 1423 &&VSUB_INST,
1181 &&STREX_INST,&&STREXB_INST,&&SWP_INST,&&SWPB_INST,&&SSUB16_INST,&&SSAT16_INST,&&SHSUBADDX_INST,&&QSUBADDX_INST,&&SHADDSUBX_INST, 1424 &&VDIV_INST,
1182 &&SHADD8_INST,&&SHADD16_INST,&&SEL_INST,&&SADDSUBX_INST,&&SADD8_INST,&&SADD16_INST,&&SHSUB16_INST,&&UMAAL_INST,&&UXTAB16_INST, 1425 &&VMOVI_INST,
1183 &&USUBADDX_INST,&&USUB8_INST,&&USUB16_INST,&&USAT16_INST,&&USADA8_INST,&&UQSUBADDX_INST,&&UQSUB8_INST,&&UQSUB16_INST, 1426 &&VMOVR_INST,
1184 &&UQADDSUBX_INST,&&UQADD8_INST,&&UQADD16_INST,&&SXTAB_INST,&&UHSUBADDX_INST,&&UHSUB8_INST,&&UHSUB16_INST,&&UHADDSUBX_INST,&&UHADD8_INST, 1427 &&VABS_INST,
1185 &&UHADD16_INST,&&UADDSUBX_INST,&&UADD8_INST,&&UADD16_INST,&&SXTAH_INST,&&SXTAB16_INST,&&QADD8_INST,&&BXJ_INST,&&CLZ_INST,&&UXTAH_INST, 1428 &&VNEG_INST,
1186 &&BX_INST,&&REV_INST,&&BLX_INST,&&REVSH_INST,&&QADD_INST,&&QADD16_INST,&&QADDSUBX_INST,&&LDREX_INST,&&QDADD_INST,&&QDSUB_INST, 1429 &&VSQRT_INST,
1187 &&QSUB_INST,&&LDREXB_INST,&&QSUB8_INST,&&QSUB16_INST,&&SMUAD_INST,&&SMMUL_INST,&&SMUSD_INST,&&SMLSD_INST,&&SMLSLD_INST,&&SMMLA_INST, 1430 &&VCMP_INST,
1188 &&SMMLS_INST,&&SMLALD_INST,&&SMLAD_INST,&&SMLAW_INST,&&SMULW_INST,&&PKHTB_INST,&&PKHBT_INST,&&SMUL_INST,&&SMLALXY_INST,&&SMLA_INST, 1431 &&VCMP2_INST,
1189 &&MCRR_INST,&&MRRC_INST,&&CMP_INST,&&TST_INST,&&TEQ_INST,&&CMN_INST,&&SMULL_INST,&&UMULL_INST,&&UMLAL_INST,&&SMLAL_INST,&&MUL_INST, 1432 &&VCVTBDS_INST,
1190 &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST, 1433 &&VCVTBFF_INST,
1191 &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST, 1434 &&VCVTBFI_INST,
1192 &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST, 1435 &&VMOVBRS_INST,
1193 &&MSR_INST, &&MSR_INST, &&MSR_INST, &&MSR_INST, &&MSR_INST, 1436 &&VMSR_INST,
1194 &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST, &&LDREXD_INST, 1437 &&VMOVBRC_INST,
1195 &&STREXD_INST,&&LDREXH_INST,&&STREXH_INST, &&NOP_INST, &&YIELD_INST, &&WFE_INST, &&WFI_INST, &&SEV_INST, &&SWI_INST,&&BBL_INST, 1438 &&VMRS_INST,
1196 &&B_2_THUMB, &&B_COND_THUMB,&&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH, 1439 &&VMOVBCR_INST,
1197 &&INIT_INST_LENGTH,&&END 1440 &&VMOVBRRSS_INST,
1198 }; 1441 &&VMOVBRRD_INST,
1442 &&VSTR_INST,
1443 &&VPUSH_INST,
1444 &&VSTM_INST,
1445 &&VPOP_INST,
1446 &&VLDR_INST,
1447 &&VLDM_INST,
1448
1449 &&SRS_INST,
1450 &&RFE_INST,
1451 &&BKPT_INST,
1452 &&BLX_INST,
1453 &&CPS_INST,
1454 &&PLD_INST,
1455 &&SETEND_INST,
1456 &&CLREX_INST,
1457 &&REV16_INST,
1458 &&USAD8_INST,
1459 &&SXTB_INST,
1460 &&UXTB_INST,
1461 &&SXTH_INST,
1462 &&SXTB16_INST,
1463 &&UXTH_INST,
1464 &&UXTB16_INST,
1465 &&CPY_INST,
1466 &&UXTAB_INST,
1467 &&SSUB8_INST,
1468 &&SHSUB8_INST,
1469 &&SSUBADDX_INST,
1470 &&STREX_INST,
1471 &&STREXB_INST,
1472 &&SWP_INST,
1473 &&SWPB_INST,
1474 &&SSUB16_INST,
1475 &&SSAT16_INST,
1476 &&SHSUBADDX_INST,
1477 &&QSUBADDX_INST,
1478 &&SHADDSUBX_INST,
1479 &&SHADD8_INST,
1480 &&SHADD16_INST,
1481 &&SEL_INST,
1482 &&SADDSUBX_INST,
1483 &&SADD8_INST,
1484 &&SADD16_INST,
1485 &&SHSUB16_INST,
1486 &&UMAAL_INST,
1487 &&UXTAB16_INST,
1488 &&USUBADDX_INST,
1489 &&USUB8_INST,
1490 &&USUB16_INST,
1491 &&USAT16_INST,
1492 &&USADA8_INST,
1493 &&UQSUBADDX_INST,
1494 &&UQSUB8_INST,
1495 &&UQSUB16_INST,
1496 &&UQADDSUBX_INST,
1497 &&UQADD8_INST,
1498 &&UQADD16_INST,
1499 &&SXTAB_INST,
1500 &&UHSUBADDX_INST,
1501 &&UHSUB8_INST,
1502 &&UHSUB16_INST,
1503 &&UHADDSUBX_INST,
1504 &&UHADD8_INST,
1505 &&UHADD16_INST,
1506 &&UADDSUBX_INST,
1507 &&UADD8_INST,
1508 &&UADD16_INST,
1509 &&SXTAH_INST,
1510 &&SXTAB16_INST,
1511 &&QADD8_INST,
1512 &&BXJ_INST,
1513 &&CLZ_INST,
1514 &&UXTAH_INST,
1515 &&BX_INST,
1516 &&REV_INST,
1517 &&BLX_INST,
1518 &&REVSH_INST,
1519 &&QADD_INST,
1520 &&QADD16_INST,
1521 &&QADDSUBX_INST,
1522 &&LDREX_INST,
1523 &&QDADD_INST,
1524 &&QDSUB_INST,
1525 &&QSUB_INST,
1526 &&LDREXB_INST,
1527 &&QSUB8_INST,
1528 &&QSUB16_INST,
1529 &&SMUAD_INST,
1530 &&SMMUL_INST,
1531 &&SMUSD_INST,
1532 &&SMLSD_INST,
1533 &&SMLSLD_INST,
1534 &&SMMLA_INST,
1535 &&SMMLS_INST,
1536 &&SMLALD_INST,
1537 &&SMLAD_INST,
1538 &&SMLAW_INST,
1539 &&SMULW_INST,
1540 &&PKHTB_INST,
1541 &&PKHBT_INST,
1542 &&SMUL_INST,
1543 &&SMLALXY_INST,
1544 &&SMLA_INST,
1545 &&MCRR_INST,
1546 &&MRRC_INST,
1547 &&CMP_INST,
1548 &&TST_INST,
1549 &&TEQ_INST,
1550 &&CMN_INST,
1551 &&SMULL_INST,
1552 &&UMULL_INST,
1553 &&UMLAL_INST,
1554 &&SMLAL_INST,
1555 &&MUL_INST,
1556 &&MLA_INST,
1557 &&SSAT_INST,
1558 &&USAT_INST,
1559 &&MRS_INST,
1560 &&MSR_INST,
1561 &&AND_INST,
1562 &&BIC_INST,
1563 &&LDM_INST,
1564 &&EOR_INST,
1565 &&ADD_INST,
1566 &&RSB_INST,
1567 &&RSC_INST,
1568 &&SBC_INST,
1569 &&ADC_INST,
1570 &&SUB_INST,
1571 &&ORR_INST,
1572 &&MVN_INST,
1573 &&MOV_INST,
1574 &&STM_INST,
1575 &&LDM_INST,
1576 &&LDRSH_INST,
1577 &&STM_INST,
1578 &&LDM_INST,
1579 &&LDRSB_INST,
1580 &&STRD_INST,
1581 &&LDRH_INST,
1582 &&STRH_INST,
1583 &&LDRD_INST,
1584 &&STRT_INST,
1585 &&STRBT_INST,
1586 &&LDRBT_INST,
1587 &&LDRT_INST,
1588 &&MRC_INST,
1589 &&MCR_INST,
1590 &&MSR_INST,
1591 &&MSR_INST,
1592 &&MSR_INST,
1593 &&MSR_INST,
1594 &&MSR_INST,
1595 &&LDRB_INST,
1596 &&STRB_INST,
1597 &&LDR_INST,
1598 &&LDRCOND_INST,
1599 &&STR_INST,
1600 &&CDP_INST,
1601 &&STC_INST,
1602 &&LDC_INST,
1603 &&LDREXD_INST,
1604 &&STREXD_INST,
1605 &&LDREXH_INST,
1606 &&STREXH_INST,
1607 &&NOP_INST,
1608 &&YIELD_INST,
1609 &&WFE_INST,
1610 &&WFI_INST,
1611 &&SEV_INST,
1612 &&SWI_INST,
1613 &&BBL_INST,
1614 &&B_2_THUMB,
1615 &&B_COND_THUMB,
1616 &&BL_1_THUMB,
1617 &&BL_2_THUMB,
1618 &&BLX_1_THUMB,
1619 &&DISPATCH,
1620 &&INIT_INST_LENGTH,
1621 &&END};
1199#endif 1622#endif
1200 arm_inst* inst_base; 1623 arm_inst* inst_base;
1201 unsigned int addr; 1624 unsigned int addr;
@@ -1204,516 +1627,517 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
1204 int ptr; 1627 int ptr;
1205 1628
1206 LOAD_NZCVT; 1629 LOAD_NZCVT;
1207 DISPATCH: 1630DISPATCH : {
1208 { 1631 if (!cpu->NirqSig) {
1209 if (!cpu->NirqSig) { 1632 if (!(cpu->Cpsr & 0x80)) {
1210 if (!(cpu->Cpsr & 0x80)) { 1633 goto END;
1211 goto END;
1212 }
1213 } 1634 }
1635 }
1214 1636
1215 if (cpu->TFlag) 1637 if (cpu->TFlag)
1216 cpu->Reg[15] &= 0xfffffffe; 1638 cpu->Reg[15] &= 0xfffffffe;
1217 else 1639 else
1218 cpu->Reg[15] &= 0xfffffffc; 1640 cpu->Reg[15] &= 0xfffffffc;
1219 1641
1220 // Find the cached instruction cream, otherwise translate it... 1642 // Find the cached instruction cream, otherwise translate it...
1221 auto itr = cpu->instruction_cache.find(cpu->Reg[15]); 1643 auto itr = cpu->instruction_cache.find(cpu->Reg[15]);
1222 if (itr != cpu->instruction_cache.end()) { 1644 if (itr != cpu->instruction_cache.end()) {
1223 ptr = itr->second; 1645 ptr = itr->second;
1224 } else if (cpu->NumInstrsToExecute != 1) { 1646 } else if (cpu->NumInstrsToExecute != 1) {
1225 if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) 1647 if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
1226 goto END; 1648 goto END;
1227 } else { 1649 } else {
1228 if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) 1650 if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
1229 goto END; 1651 goto END;
1230 } 1652 }
1231 1653
1232 // Find breakpoint if one exists within the block 1654 // Find breakpoint if one exists within the block
1233 if (GDBStub::g_server_enabled && GDBStub::IsConnected()) { 1655 if (GDBStub::g_server_enabled && GDBStub::IsConnected()) {
1234 breakpoint_data = GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute); 1656 breakpoint_data =
1235 } 1657 GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute);
1658 }
1236 1659
1237 inst_base = (arm_inst *)&trans_cache_buf[ptr]; 1660 inst_base = (arm_inst*)&trans_cache_buf[ptr];
1238 GOTO_NEXT_INST; 1661 GOTO_NEXT_INST;
1662}
1663ADC_INST : {
1664 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1665 adc_inst* const inst_cream = (adc_inst*)inst_base->component;
1666
1667 u32 rn_val = RN;
1668 if (inst_cream->Rn == 15)
1669 rn_val += 2 * cpu->GetInstructionSize();
1670
1671 bool carry;
1672 bool overflow;
1673 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
1674
1675 if (inst_cream->S && (inst_cream->Rd == 15)) {
1676 if (CurrentModeHasSPSR) {
1677 cpu->Cpsr = cpu->Spsr_copy;
1678 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1679 LOAD_NZCVT;
1680 }
1681 } else if (inst_cream->S) {
1682 UPDATE_NFLAG(RD);
1683 UPDATE_ZFLAG(RD);
1684 cpu->CFlag = carry;
1685 cpu->VFlag = overflow;
1686 }
1687 if (inst_cream->Rd == 15) {
1688 INC_PC(sizeof(adc_inst));
1689 goto DISPATCH;
1690 }
1239 } 1691 }
1240 ADC_INST: 1692 cpu->Reg[15] += cpu->GetInstructionSize();
1241 { 1693 INC_PC(sizeof(adc_inst));
1242 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1694 FETCH_INST;
1243 adc_inst* const inst_cream = (adc_inst*)inst_base->component; 1695 GOTO_NEXT_INST;
1696}
1697ADD_INST : {
1698 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1699 add_inst* const inst_cream = (add_inst*)inst_base->component;
1244 1700
1245 u32 rn_val = RN; 1701 u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
1246 if (inst_cream->Rn == 15)
1247 rn_val += 2 * cpu->GetInstructionSize();
1248 1702
1249 bool carry; 1703 bool carry;
1250 bool overflow; 1704 bool overflow;
1251 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); 1705 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
1252 1706
1253 if (inst_cream->S && (inst_cream->Rd == 15)) { 1707 if (inst_cream->S && (inst_cream->Rd == 15)) {
1254 if (CurrentModeHasSPSR) { 1708 if (CurrentModeHasSPSR) {
1255 cpu->Cpsr = cpu->Spsr_copy; 1709 cpu->Cpsr = cpu->Spsr_copy;
1256 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 1710 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
1257 LOAD_NZCVT; 1711 LOAD_NZCVT;
1258 }
1259 } else if (inst_cream->S) {
1260 UPDATE_NFLAG(RD);
1261 UPDATE_ZFLAG(RD);
1262 cpu->CFlag = carry;
1263 cpu->VFlag = overflow;
1264 }
1265 if (inst_cream->Rd == 15) {
1266 INC_PC(sizeof(adc_inst));
1267 goto DISPATCH;
1268 } 1712 }
1713 } else if (inst_cream->S) {
1714 UPDATE_NFLAG(RD);
1715 UPDATE_ZFLAG(RD);
1716 cpu->CFlag = carry;
1717 cpu->VFlag = overflow;
1269 } 1718 }
1270 cpu->Reg[15] += cpu->GetInstructionSize(); 1719 if (inst_cream->Rd == 15) {
1271 INC_PC(sizeof(adc_inst)); 1720 INC_PC(sizeof(add_inst));
1272 FETCH_INST; 1721 goto DISPATCH;
1273 GOTO_NEXT_INST;
1274 }
1275 ADD_INST:
1276 {
1277 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1278 add_inst* const inst_cream = (add_inst*)inst_base->component;
1279
1280 u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
1281
1282 bool carry;
1283 bool overflow;
1284 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
1285
1286 if (inst_cream->S && (inst_cream->Rd == 15)) {
1287 if (CurrentModeHasSPSR) {
1288 cpu->Cpsr = cpu->Spsr_copy;
1289 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
1290 LOAD_NZCVT;
1291 }
1292 } else if (inst_cream->S) {
1293 UPDATE_NFLAG(RD);
1294 UPDATE_ZFLAG(RD);
1295 cpu->CFlag = carry;
1296 cpu->VFlag = overflow;
1297 }
1298 if (inst_cream->Rd == 15) {
1299 INC_PC(sizeof(add_inst));
1300 goto DISPATCH;
1301 }
1302 } 1722 }
1303 cpu->Reg[15] += cpu->GetInstructionSize();
1304 INC_PC(sizeof(add_inst));
1305 FETCH_INST;
1306 GOTO_NEXT_INST;
1307 } 1723 }
1308 AND_INST: 1724 cpu->Reg[15] += cpu->GetInstructionSize();
1309 { 1725 INC_PC(sizeof(add_inst));
1310 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1726 FETCH_INST;
1311 and_inst* const inst_cream = (and_inst*)inst_base->component; 1727 GOTO_NEXT_INST;
1728}
1729AND_INST : {
1730 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1731 and_inst* const inst_cream = (and_inst*)inst_base->component;
1312 1732
1313 u32 lop = RN; 1733 u32 lop = RN;
1314 u32 rop = SHIFTER_OPERAND; 1734 u32 rop = SHIFTER_OPERAND;
1315 1735
1316 if (inst_cream->Rn == 15) 1736 if (inst_cream->Rn == 15)
1317 lop += 2 * cpu->GetInstructionSize(); 1737 lop += 2 * cpu->GetInstructionSize();
1318 1738
1319 RD = lop & rop; 1739 RD = lop & rop;
1320 1740
1321 if (inst_cream->S && (inst_cream->Rd == 15)) { 1741 if (inst_cream->S && (inst_cream->Rd == 15)) {
1322 if (CurrentModeHasSPSR) { 1742 if (CurrentModeHasSPSR) {
1323 cpu->Cpsr = cpu->Spsr_copy; 1743 cpu->Cpsr = cpu->Spsr_copy;
1324 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); 1744 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
1325 LOAD_NZCVT; 1745 LOAD_NZCVT;
1326 }
1327 } else if (inst_cream->S) {
1328 UPDATE_NFLAG(RD);
1329 UPDATE_ZFLAG(RD);
1330 UPDATE_CFLAG_WITH_SC;
1331 }
1332 if (inst_cream->Rd == 15) {
1333 INC_PC(sizeof(and_inst));
1334 goto DISPATCH;
1335 } 1746 }
1747 } else if (inst_cream->S) {
1748 UPDATE_NFLAG(RD);
1749 UPDATE_ZFLAG(RD);
1750 UPDATE_CFLAG_WITH_SC;
1336 } 1751 }
1337 cpu->Reg[15] += cpu->GetInstructionSize(); 1752 if (inst_cream->Rd == 15) {
1338 INC_PC(sizeof(and_inst)); 1753 INC_PC(sizeof(and_inst));
1339 FETCH_INST;
1340 GOTO_NEXT_INST;
1341 }
1342 BBL_INST:
1343 {
1344 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1345 bbl_inst *inst_cream = (bbl_inst *)inst_base->component;
1346 if (inst_cream->L) {
1347 LINK_RTN_ADDR;
1348 }
1349 SET_PC;
1350 INC_PC(sizeof(bbl_inst));
1351 goto DISPATCH; 1754 goto DISPATCH;
1352 } 1755 }
1353 cpu->Reg[15] += cpu->GetInstructionSize(); 1756 }
1757 cpu->Reg[15] += cpu->GetInstructionSize();
1758 INC_PC(sizeof(and_inst));
1759 FETCH_INST;
1760 GOTO_NEXT_INST;
1761}
1762BBL_INST : {
1763 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1764 bbl_inst* inst_cream = (bbl_inst*)inst_base->component;
1765 if (inst_cream->L) {
1766 LINK_RTN_ADDR;
1767 }
1768 SET_PC;
1354 INC_PC(sizeof(bbl_inst)); 1769 INC_PC(sizeof(bbl_inst));
1355 goto DISPATCH; 1770 goto DISPATCH;
1356 } 1771 }
1357 BIC_INST: 1772 cpu->Reg[15] += cpu->GetInstructionSize();
1358 { 1773 INC_PC(sizeof(bbl_inst));
1359 bic_inst *inst_cream = (bic_inst *)inst_base->component; 1774 goto DISPATCH;
1360 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 1775}
1361 u32 lop = RN; 1776BIC_INST : {
1362 if (inst_cream->Rn == 15) { 1777 bic_inst* inst_cream = (bic_inst*)inst_base->component;
1363 lop += 2 * cpu->GetInstructionSize(); 1778 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1364 } 1779 u32 lop = RN;
1365 u32 rop = SHIFTER_OPERAND; 1780 if (inst_cream->Rn == 15) {
1366 RD = lop & (~rop); 1781 lop += 2 * cpu->GetInstructionSize();
1367 if ((inst_cream->S) && (inst_cream->Rd == 15)) {
1368 if (CurrentModeHasSPSR) {
1369 cpu->Cpsr = cpu->Spsr_copy;
1370 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1371 LOAD_NZCVT;
1372 }
1373 } else if (inst_cream->S) {
1374 UPDATE_NFLAG(RD);
1375 UPDATE_ZFLAG(RD);
1376 UPDATE_CFLAG_WITH_SC;
1377 }
1378 if (inst_cream->Rd == 15) {
1379 INC_PC(sizeof(bic_inst));
1380 goto DISPATCH;
1381 }
1382 }
1383 cpu->Reg[15] += cpu->GetInstructionSize();
1384 INC_PC(sizeof(bic_inst));
1385 FETCH_INST;
1386 GOTO_NEXT_INST;
1387 }
1388 BKPT_INST:
1389 {
1390 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1391 bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
1392 LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm);
1393 } 1782 }
1394 cpu->Reg[15] += cpu->GetInstructionSize(); 1783 u32 rop = SHIFTER_OPERAND;
1395 INC_PC(sizeof(bkpt_inst)); 1784 RD = lop & (~rop);
1396 FETCH_INST; 1785 if ((inst_cream->S) && (inst_cream->Rd == 15)) {
1397 GOTO_NEXT_INST; 1786 if (CurrentModeHasSPSR) {
1398 } 1787 cpu->Cpsr = cpu->Spsr_copy;
1399 BLX_INST: 1788 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1400 { 1789 LOAD_NZCVT;
1401 blx_inst *inst_cream = (blx_inst *)inst_base->component;
1402 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1403 unsigned int inst = inst_cream->inst;
1404 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
1405 const u32 jump_address = cpu->Reg[inst_cream->val.Rm];
1406 cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
1407 if(cpu->TFlag)
1408 cpu->Reg[14] |= 0x1;
1409 cpu->Reg[15] = jump_address & 0xfffffffe;
1410 cpu->TFlag = jump_address & 0x1;
1411 } else {
1412 cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
1413 cpu->TFlag = 0x1;
1414 int signed_int = inst_cream->val.signed_immed_24;
1415 signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int;
1416 signed_int = signed_int << 2;
1417 cpu->Reg[15] = cpu->Reg[15] + 8 + signed_int + (BIT(inst, 24) << 1);
1418 } 1790 }
1419 INC_PC(sizeof(blx_inst)); 1791 } else if (inst_cream->S) {
1792 UPDATE_NFLAG(RD);
1793 UPDATE_ZFLAG(RD);
1794 UPDATE_CFLAG_WITH_SC;
1795 }
1796 if (inst_cream->Rd == 15) {
1797 INC_PC(sizeof(bic_inst));
1420 goto DISPATCH; 1798 goto DISPATCH;
1421 } 1799 }
1422 cpu->Reg[15] += cpu->GetInstructionSize(); 1800 }
1801 cpu->Reg[15] += cpu->GetInstructionSize();
1802 INC_PC(sizeof(bic_inst));
1803 FETCH_INST;
1804 GOTO_NEXT_INST;
1805}
1806BKPT_INST : {
1807 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1808 bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
1809 LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm);
1810 }
1811 cpu->Reg[15] += cpu->GetInstructionSize();
1812 INC_PC(sizeof(bkpt_inst));
1813 FETCH_INST;
1814 GOTO_NEXT_INST;
1815}
1816BLX_INST : {
1817 blx_inst* inst_cream = (blx_inst*)inst_base->component;
1818 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1819 unsigned int inst = inst_cream->inst;
1820 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
1821 const u32 jump_address = cpu->Reg[inst_cream->val.Rm];
1822 cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
1823 if (cpu->TFlag)
1824 cpu->Reg[14] |= 0x1;
1825 cpu->Reg[15] = jump_address & 0xfffffffe;
1826 cpu->TFlag = jump_address & 0x1;
1827 } else {
1828 cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
1829 cpu->TFlag = 0x1;
1830 int signed_int = inst_cream->val.signed_immed_24;
1831 signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int;
1832 signed_int = signed_int << 2;
1833 cpu->Reg[15] = cpu->Reg[15] + 8 + signed_int + (BIT(inst, 24) << 1);
1834 }
1423 INC_PC(sizeof(blx_inst)); 1835 INC_PC(sizeof(blx_inst));
1424 goto DISPATCH; 1836 goto DISPATCH;
1425 } 1837 }
1838 cpu->Reg[15] += cpu->GetInstructionSize();
1839 INC_PC(sizeof(blx_inst));
1840 goto DISPATCH;
1841}
1426 1842
1427 BX_INST: 1843BX_INST:
1428 BXJ_INST: 1844BXJ_INST : {
1429 { 1845 // Note that only the 'fail' case of BXJ is emulated. This is because
1430 // Note that only the 'fail' case of BXJ is emulated. This is because 1846 // the facilities for Jazelle emulation are not implemented.
1431 // the facilities for Jazelle emulation are not implemented. 1847 //
1432 // 1848 // According to the ARM documentation on BXJ, if setting the J bit in the APSR
1433 // According to the ARM documentation on BXJ, if setting the J bit in the APSR 1849 // fails, then BXJ functions identically like a regular BX instruction.
1434 // fails, then BXJ functions identically like a regular BX instruction. 1850 //
1435 // 1851 // This is sufficient for citra, as the CPU for the 3DS does not implement Jazelle.
1436 // This is sufficient for citra, as the CPU for the 3DS does not implement Jazelle.
1437 1852
1438 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1853 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1439 bx_inst* const inst_cream = (bx_inst*)inst_base->component; 1854 bx_inst* const inst_cream = (bx_inst*)inst_base->component;
1440 1855
1441 u32 address = RM; 1856 u32 address = RM;
1442 1857
1443 if (inst_cream->Rm == 15) 1858 if (inst_cream->Rm == 15)
1444 address += 2 * cpu->GetInstructionSize(); 1859 address += 2 * cpu->GetInstructionSize();
1445 1860
1446 cpu->TFlag = address & 1; 1861 cpu->TFlag = address & 1;
1447 cpu->Reg[15] = address & 0xfffffffe; 1862 cpu->Reg[15] = address & 0xfffffffe;
1448 INC_PC(sizeof(bx_inst));
1449 goto DISPATCH;
1450 }
1451
1452 cpu->Reg[15] += cpu->GetInstructionSize();
1453 INC_PC(sizeof(bx_inst)); 1863 INC_PC(sizeof(bx_inst));
1454 goto DISPATCH; 1864 goto DISPATCH;
1455 } 1865 }
1456 1866
1457 CDP_INST: 1867 cpu->Reg[15] += cpu->GetInstructionSize();
1458 { 1868 INC_PC(sizeof(bx_inst));
1459 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1869 goto DISPATCH;
1460 // Undefined instruction here 1870}
1461 cpu->NumInstrsToExecute = 0; 1871
1462 return num_instrs; 1872CDP_INST : {
1873 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1874 // Undefined instruction here
1875 cpu->NumInstrsToExecute = 0;
1876 return num_instrs;
1877 }
1878 cpu->Reg[15] += cpu->GetInstructionSize();
1879 INC_PC(sizeof(cdp_inst));
1880 FETCH_INST;
1881 GOTO_NEXT_INST;
1882}
1883
1884CLREX_INST : {
1885 cpu->UnsetExclusiveMemoryAddress();
1886 cpu->Reg[15] += cpu->GetInstructionSize();
1887 INC_PC(sizeof(clrex_inst));
1888 FETCH_INST;
1889 GOTO_NEXT_INST;
1890}
1891CLZ_INST : {
1892 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1893 clz_inst* inst_cream = (clz_inst*)inst_base->component;
1894 RD = clz(RM);
1895 }
1896 cpu->Reg[15] += cpu->GetInstructionSize();
1897 INC_PC(sizeof(clz_inst));
1898 FETCH_INST;
1899 GOTO_NEXT_INST;
1900}
1901CMN_INST : {
1902 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1903 cmn_inst* const inst_cream = (cmn_inst*)inst_base->component;
1904
1905 u32 rn_val = RN;
1906 if (inst_cream->Rn == 15)
1907 rn_val += 2 * cpu->GetInstructionSize();
1908
1909 bool carry;
1910 bool overflow;
1911 u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
1912
1913 UPDATE_NFLAG(result);
1914 UPDATE_ZFLAG(result);
1915 cpu->CFlag = carry;
1916 cpu->VFlag = overflow;
1917 }
1918 cpu->Reg[15] += cpu->GetInstructionSize();
1919 INC_PC(sizeof(cmn_inst));
1920 FETCH_INST;
1921 GOTO_NEXT_INST;
1922}
1923CMP_INST : {
1924 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1925 cmp_inst* const inst_cream = (cmp_inst*)inst_base->component;
1926
1927 u32 rn_val = RN;
1928 if (inst_cream->Rn == 15)
1929 rn_val += 2 * cpu->GetInstructionSize();
1930
1931 bool carry;
1932 bool overflow;
1933 u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
1934
1935 UPDATE_NFLAG(result);
1936 UPDATE_ZFLAG(result);
1937 cpu->CFlag = carry;
1938 cpu->VFlag = overflow;
1939 }
1940 cpu->Reg[15] += cpu->GetInstructionSize();
1941 INC_PC(sizeof(cmp_inst));
1942 FETCH_INST;
1943 GOTO_NEXT_INST;
1944}
1945CPS_INST : {
1946 cps_inst* inst_cream = (cps_inst*)inst_base->component;
1947 u32 aif_val = 0;
1948 u32 aif_mask = 0;
1949 if (cpu->InAPrivilegedMode()) {
1950 if (inst_cream->imod1) {
1951 if (inst_cream->A) {
1952 aif_val |= (inst_cream->imod0 << 8);
1953 aif_mask |= 1 << 8;
1954 }
1955 if (inst_cream->I) {
1956 aif_val |= (inst_cream->imod0 << 7);
1957 aif_mask |= 1 << 7;
1958 }
1959 if (inst_cream->F) {
1960 aif_val |= (inst_cream->imod0 << 6);
1961 aif_mask |= 1 << 6;
1962 }
1963 aif_mask = ~aif_mask;
1964 cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val;
1463 } 1965 }
1464 cpu->Reg[15] += cpu->GetInstructionSize(); 1966 if (inst_cream->mmod) {
1465 INC_PC(sizeof(cdp_inst)); 1967 cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode;
1466 FETCH_INST; 1968 cpu->ChangePrivilegeMode(inst_cream->mode);
1467 GOTO_NEXT_INST;
1468 }
1469
1470 CLREX_INST:
1471 {
1472 cpu->UnsetExclusiveMemoryAddress();
1473 cpu->Reg[15] += cpu->GetInstructionSize();
1474 INC_PC(sizeof(clrex_inst));
1475 FETCH_INST;
1476 GOTO_NEXT_INST;
1477 }
1478 CLZ_INST:
1479 {
1480 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1481 clz_inst* inst_cream = (clz_inst*)inst_base->component;
1482 RD = clz(RM);
1483 } 1969 }
1484 cpu->Reg[15] += cpu->GetInstructionSize(); 1970 }
1485 INC_PC(sizeof(clz_inst)); 1971 cpu->Reg[15] += cpu->GetInstructionSize();
1486 FETCH_INST; 1972 INC_PC(sizeof(cps_inst));
1487 GOTO_NEXT_INST; 1973 FETCH_INST;
1488 } 1974 GOTO_NEXT_INST;
1489 CMN_INST: 1975}
1490 { 1976CPY_INST : {
1491 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1977 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1492 cmn_inst* const inst_cream = (cmn_inst*)inst_base->component; 1978 mov_inst* inst_cream = (mov_inst*)inst_base->component;
1493 1979
1494 u32 rn_val = RN; 1980 RD = SHIFTER_OPERAND;
1495 if (inst_cream->Rn == 15) 1981 if (inst_cream->Rd == 15) {
1496 rn_val += 2 * cpu->GetInstructionSize(); 1982 INC_PC(sizeof(mov_inst));
1497 1983 goto DISPATCH;
1498 bool carry;
1499 bool overflow;
1500 u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
1501
1502 UPDATE_NFLAG(result);
1503 UPDATE_ZFLAG(result);
1504 cpu->CFlag = carry;
1505 cpu->VFlag = overflow;
1506 } 1984 }
1507 cpu->Reg[15] += cpu->GetInstructionSize(); 1985 }
1508 INC_PC(sizeof(cmn_inst)); 1986 cpu->Reg[15] += cpu->GetInstructionSize();
1509 FETCH_INST; 1987 INC_PC(sizeof(mov_inst));
1510 GOTO_NEXT_INST; 1988 FETCH_INST;
1511 } 1989 GOTO_NEXT_INST;
1512 CMP_INST: 1990}
1513 { 1991EOR_INST : {
1514 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1992 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1515 cmp_inst* const inst_cream = (cmp_inst*)inst_base->component; 1993 eor_inst* inst_cream = (eor_inst*)inst_base->component;
1516 1994
1517 u32 rn_val = RN; 1995 u32 lop = RN;
1518 if (inst_cream->Rn == 15) 1996 if (inst_cream->Rn == 15) {
1519 rn_val += 2 * cpu->GetInstructionSize(); 1997 lop += 2 * cpu->GetInstructionSize();
1520
1521 bool carry;
1522 bool overflow;
1523 u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
1524
1525 UPDATE_NFLAG(result);
1526 UPDATE_ZFLAG(result);
1527 cpu->CFlag = carry;
1528 cpu->VFlag = overflow;
1529 } 1998 }
1530 cpu->Reg[15] += cpu->GetInstructionSize(); 1999 u32 rop = SHIFTER_OPERAND;
1531 INC_PC(sizeof(cmp_inst)); 2000 RD = lop ^ rop;
1532 FETCH_INST; 2001 if (inst_cream->S && (inst_cream->Rd == 15)) {
1533 GOTO_NEXT_INST; 2002 if (CurrentModeHasSPSR) {
1534 } 2003 cpu->Cpsr = cpu->Spsr_copy;
1535 CPS_INST: 2004 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1536 { 2005 LOAD_NZCVT;
1537 cps_inst *inst_cream = (cps_inst *)inst_base->component;
1538 u32 aif_val = 0;
1539 u32 aif_mask = 0;
1540 if (cpu->InAPrivilegedMode()) {
1541 if (inst_cream->imod1) {
1542 if (inst_cream->A) {
1543 aif_val |= (inst_cream->imod0 << 8);
1544 aif_mask |= 1 << 8;
1545 }
1546 if (inst_cream->I) {
1547 aif_val |= (inst_cream->imod0 << 7);
1548 aif_mask |= 1 << 7;
1549 }
1550 if (inst_cream->F) {
1551 aif_val |= (inst_cream->imod0 << 6);
1552 aif_mask |= 1 << 6;
1553 }
1554 aif_mask = ~aif_mask;
1555 cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val;
1556 }
1557 if (inst_cream->mmod) {
1558 cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode;
1559 cpu->ChangePrivilegeMode(inst_cream->mode);
1560 } 2006 }
2007 } else if (inst_cream->S) {
2008 UPDATE_NFLAG(RD);
2009 UPDATE_ZFLAG(RD);
2010 UPDATE_CFLAG_WITH_SC;
2011 }
2012 if (inst_cream->Rd == 15) {
2013 INC_PC(sizeof(eor_inst));
2014 goto DISPATCH;
1561 } 2015 }
1562 cpu->Reg[15] += cpu->GetInstructionSize();
1563 INC_PC(sizeof(cps_inst));
1564 FETCH_INST;
1565 GOTO_NEXT_INST;
1566 } 2016 }
1567 CPY_INST: 2017 cpu->Reg[15] += cpu->GetInstructionSize();
1568 { 2018 INC_PC(sizeof(eor_inst));
1569 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2019 FETCH_INST;
1570 mov_inst* inst_cream = (mov_inst*)inst_base->component; 2020 GOTO_NEXT_INST;
2021}
2022LDC_INST : {
2023 // Instruction not implemented
2024 // LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
2025 cpu->Reg[15] += cpu->GetInstructionSize();
2026 INC_PC(sizeof(ldc_inst));
2027 FETCH_INST;
2028 GOTO_NEXT_INST;
2029}
2030LDM_INST : {
2031 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2032 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2033 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1571 2034
1572 RD = SHIFTER_OPERAND; 2035 unsigned int inst = inst_cream->inst;
1573 if (inst_cream->Rd == 15) { 2036 if (BIT(inst, 22) && !BIT(inst, 15)) {
1574 INC_PC(sizeof(mov_inst)); 2037 for (int i = 0; i < 13; i++) {
1575 goto DISPATCH; 2038 if (BIT(inst, i)) {
1576 } 2039 cpu->Reg[i] = cpu->ReadMemory32(addr);
1577 } 2040 addr += 4;
1578 cpu->Reg[15] += cpu->GetInstructionSize();
1579 INC_PC(sizeof(mov_inst));
1580 FETCH_INST;
1581 GOTO_NEXT_INST;
1582 }
1583 EOR_INST:
1584 {
1585 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1586 eor_inst* inst_cream = (eor_inst*)inst_base->component;
1587
1588 u32 lop = RN;
1589 if (inst_cream->Rn == 15) {
1590 lop += 2 * cpu->GetInstructionSize();
1591 }
1592 u32 rop = SHIFTER_OPERAND;
1593 RD = lop ^ rop;
1594 if (inst_cream->S && (inst_cream->Rd == 15)) {
1595 if (CurrentModeHasSPSR) {
1596 cpu->Cpsr = cpu->Spsr_copy;
1597 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1598 LOAD_NZCVT;
1599 } 2041 }
1600 } else if (inst_cream->S) {
1601 UPDATE_NFLAG(RD);
1602 UPDATE_ZFLAG(RD);
1603 UPDATE_CFLAG_WITH_SC;
1604 } 2042 }
1605 if (inst_cream->Rd == 15) { 2043 if (BIT(inst, 13)) {
1606 INC_PC(sizeof(eor_inst)); 2044 if (cpu->Mode == USER32MODE)
1607 goto DISPATCH; 2045 cpu->Reg[13] = cpu->ReadMemory32(addr);
2046 else
2047 cpu->Reg_usr[0] = cpu->ReadMemory32(addr);
2048
2049 addr += 4;
1608 } 2050 }
1609 } 2051 if (BIT(inst, 14)) {
1610 cpu->Reg[15] += cpu->GetInstructionSize(); 2052 if (cpu->Mode == USER32MODE)
1611 INC_PC(sizeof(eor_inst)); 2053 cpu->Reg[14] = cpu->ReadMemory32(addr);
1612 FETCH_INST; 2054 else
1613 GOTO_NEXT_INST; 2055 cpu->Reg_usr[1] = cpu->ReadMemory32(addr);
1614 } 2056
1615 LDC_INST: 2057 addr += 4;
1616 { 2058 }
1617 // Instruction not implemented 2059 } else if (!BIT(inst, 22)) {
1618 //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); 2060 for (int i = 0; i < 16; i++) {
1619 cpu->Reg[15] += cpu->GetInstructionSize(); 2061 if (BIT(inst, i)) {
1620 INC_PC(sizeof(ldc_inst)); 2062 unsigned int ret = cpu->ReadMemory32(addr);
1621 FETCH_INST; 2063
1622 GOTO_NEXT_INST; 2064 // For armv5t, should enter thumb when bits[0] is non-zero.
1623 } 2065 if (i == 15) {
1624 LDM_INST: 2066 cpu->TFlag = ret & 0x1;
1625 { 2067 ret &= 0xFFFFFFFE;
1626 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1627 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1628 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1629
1630 unsigned int inst = inst_cream->inst;
1631 if (BIT(inst, 22) && !BIT(inst, 15)) {
1632 for (int i = 0; i < 13; i++) {
1633 if(BIT(inst, i)) {
1634 cpu->Reg[i] = cpu->ReadMemory32(addr);
1635 addr += 4;
1636 } 2068 }
1637 }
1638 if (BIT(inst, 13)) {
1639 if (cpu->Mode == USER32MODE)
1640 cpu->Reg[13] = cpu->ReadMemory32(addr);
1641 else
1642 cpu->Reg_usr[0] = cpu->ReadMemory32(addr);
1643 2069
2070 cpu->Reg[i] = ret;
1644 addr += 4; 2071 addr += 4;
1645 } 2072 }
1646 if (BIT(inst, 14)) { 2073 }
1647 if (cpu->Mode == USER32MODE) 2074 } else if (BIT(inst, 22) && BIT(inst, 15)) {
1648 cpu->Reg[14] = cpu->ReadMemory32(addr); 2075 for (int i = 0; i < 15; i++) {
1649 else 2076 if (BIT(inst, i)) {
1650 cpu->Reg_usr[1] = cpu->ReadMemory32(addr); 2077 cpu->Reg[i] = cpu->ReadMemory32(addr);
1651
1652 addr += 4; 2078 addr += 4;
1653 } 2079 }
1654 } else if (!BIT(inst, 22)) {
1655 for(int i = 0; i < 16; i++ ){
1656 if(BIT(inst, i)){
1657 unsigned int ret = cpu->ReadMemory32(addr);
1658
1659 // For armv5t, should enter thumb when bits[0] is non-zero.
1660 if(i == 15){
1661 cpu->TFlag = ret & 0x1;
1662 ret &= 0xFFFFFFFE;
1663 }
1664
1665 cpu->Reg[i] = ret;
1666 addr += 4;
1667 }
1668 }
1669 } else if (BIT(inst, 22) && BIT(inst, 15)) {
1670 for(int i = 0; i < 15; i++ ){
1671 if(BIT(inst, i)){
1672 cpu->Reg[i] = cpu->ReadMemory32(addr);
1673 addr += 4;
1674 }
1675 }
1676
1677 if (CurrentModeHasSPSR) {
1678 cpu->Cpsr = cpu->Spsr_copy;
1679 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
1680 LOAD_NZCVT;
1681 }
1682
1683 cpu->Reg[15] = cpu->ReadMemory32(addr);
1684 } 2080 }
1685 2081
1686 if (BIT(inst, 15)) { 2082 if (CurrentModeHasSPSR) {
1687 INC_PC(sizeof(ldst_inst)); 2083 cpu->Cpsr = cpu->Spsr_copy;
1688 goto DISPATCH; 2084 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
2085 LOAD_NZCVT;
1689 } 2086 }
2087
2088 cpu->Reg[15] = cpu->ReadMemory32(addr);
2089 }
2090
2091 if (BIT(inst, 15)) {
2092 INC_PC(sizeof(ldst_inst));
2093 goto DISPATCH;
1690 } 2094 }
1691 cpu->Reg[15] += cpu->GetInstructionSize();
1692 INC_PC(sizeof(ldst_inst));
1693 FETCH_INST;
1694 GOTO_NEXT_INST;
1695 } 2095 }
1696 SXTH_INST: 2096 cpu->Reg[15] += cpu->GetInstructionSize();
1697 { 2097 INC_PC(sizeof(ldst_inst));
1698 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2098 FETCH_INST;
1699 sxth_inst* inst_cream = (sxth_inst*)inst_base->component; 2099 GOTO_NEXT_INST;
2100}
2101SXTH_INST : {
2102 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2103 sxth_inst* inst_cream = (sxth_inst*)inst_base->component;
1700 2104
1701 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate); 2105 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
1702 if (BIT(operand2, 15)) { 2106 if (BIT(operand2, 15)) {
1703 operand2 |= 0xffff0000; 2107 operand2 |= 0xffff0000;
1704 } else { 2108 } else {
1705 operand2 &= 0xffff; 2109 operand2 &= 0xffff;
1706 }
1707 RD = operand2;
1708 } 2110 }
1709 cpu->Reg[15] += cpu->GetInstructionSize(); 2111 RD = operand2;
1710 INC_PC(sizeof(sxth_inst)); 2112 }
1711 FETCH_INST; 2113 cpu->Reg[15] += cpu->GetInstructionSize();
1712 GOTO_NEXT_INST; 2114 INC_PC(sizeof(sxth_inst));
1713 } 2115 FETCH_INST;
1714 LDR_INST: 2116 GOTO_NEXT_INST;
1715 { 2117}
1716 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2118LDR_INST : {
2119 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2120 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2121
2122 unsigned int value = cpu->ReadMemory32(addr);
2123 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
2124
2125 if (BITS(inst_cream->inst, 12, 15) == 15) {
2126 // For armv5t, should enter thumb when bits[0] is non-zero.
2127 cpu->TFlag = value & 0x1;
2128 cpu->Reg[15] &= 0xFFFFFFFE;
2129 INC_PC(sizeof(ldst_inst));
2130 goto DISPATCH;
2131 }
2132
2133 cpu->Reg[15] += cpu->GetInstructionSize();
2134 INC_PC(sizeof(ldst_inst));
2135 FETCH_INST;
2136 GOTO_NEXT_INST;
2137}
2138LDRCOND_INST : {
2139 if (CondPassed(cpu, inst_base->cond)) {
2140 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1717 inst_cream->get_addr(cpu, inst_cream->inst, addr); 2141 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1718 2142
1719 unsigned int value = cpu->ReadMemory32(addr); 2143 unsigned int value = cpu->ReadMemory32(addr);
@@ -1726,2546 +2150,2433 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
1726 INC_PC(sizeof(ldst_inst)); 2150 INC_PC(sizeof(ldst_inst));
1727 goto DISPATCH; 2151 goto DISPATCH;
1728 } 2152 }
2153 }
2154 cpu->Reg[15] += cpu->GetInstructionSize();
2155 INC_PC(sizeof(ldst_inst));
2156 FETCH_INST;
2157 GOTO_NEXT_INST;
2158}
2159UXTH_INST : {
2160 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2161 uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
2162 RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
2163 }
2164 cpu->Reg[15] += cpu->GetInstructionSize();
2165 INC_PC(sizeof(uxth_inst));
2166 FETCH_INST;
2167 GOTO_NEXT_INST;
2168}
2169UXTAH_INST : {
2170 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2171 uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component;
2172 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
1729 2173
1730 cpu->Reg[15] += cpu->GetInstructionSize(); 2174 RD = RN + operand2;
1731 INC_PC(sizeof(ldst_inst)); 2175 }
1732 FETCH_INST; 2176 cpu->Reg[15] += cpu->GetInstructionSize();
1733 GOTO_NEXT_INST; 2177 INC_PC(sizeof(uxtah_inst));
1734 } 2178 FETCH_INST;
1735 LDRCOND_INST: 2179 GOTO_NEXT_INST;
1736 { 2180}
1737 if (CondPassed(cpu, inst_base->cond)) { 2181LDRB_INST : {
1738 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2182 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1739 inst_cream->get_addr(cpu, inst_cream->inst, addr); 2183 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1740 2184 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1741 unsigned int value = cpu->ReadMemory32(addr); 2185
1742 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 2186 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr);
1743
1744 if (BITS(inst_cream->inst, 12, 15) == 15) {
1745 // For armv5t, should enter thumb when bits[0] is non-zero.
1746 cpu->TFlag = value & 0x1;
1747 cpu->Reg[15] &= 0xFFFFFFFE;
1748 INC_PC(sizeof(ldst_inst));
1749 goto DISPATCH;
1750 }
1751 }
1752 cpu->Reg[15] += cpu->GetInstructionSize();
1753 INC_PC(sizeof(ldst_inst));
1754 FETCH_INST;
1755 GOTO_NEXT_INST;
1756 }
1757 UXTH_INST:
1758 {
1759 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1760 uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
1761 RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
1762 }
1763 cpu->Reg[15] += cpu->GetInstructionSize();
1764 INC_PC(sizeof(uxth_inst));
1765 FETCH_INST;
1766 GOTO_NEXT_INST;
1767 }
1768 UXTAH_INST:
1769 {
1770 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1771 uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component;
1772 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
1773
1774 RD = RN + operand2;
1775 }
1776 cpu->Reg[15] += cpu->GetInstructionSize();
1777 INC_PC(sizeof(uxtah_inst));
1778 FETCH_INST;
1779 GOTO_NEXT_INST;
1780 }
1781 LDRB_INST:
1782 {
1783 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1784 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1785 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1786
1787 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr);
1788 }
1789 cpu->Reg[15] += cpu->GetInstructionSize();
1790 INC_PC(sizeof(ldst_inst));
1791 FETCH_INST;
1792 GOTO_NEXT_INST;
1793 } 2187 }
1794 LDRBT_INST: 2188 cpu->Reg[15] += cpu->GetInstructionSize();
1795 { 2189 INC_PC(sizeof(ldst_inst));
1796 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2190 FETCH_INST;
1797 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 2191 GOTO_NEXT_INST;
1798 inst_cream->get_addr(cpu, inst_cream->inst, addr); 2192}
2193LDRBT_INST : {
2194 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2195 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2196 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1799 2197
1800 const u32 dest_index = BITS(inst_cream->inst, 12, 15); 2198 const u32 dest_index = BITS(inst_cream->inst, 12, 15);
1801 const u32 previous_mode = cpu->Mode; 2199 const u32 previous_mode = cpu->Mode;
1802 2200
1803 cpu->ChangePrivilegeMode(USER32MODE); 2201 cpu->ChangePrivilegeMode(USER32MODE);
1804 const u8 value = cpu->ReadMemory8(addr); 2202 const u8 value = cpu->ReadMemory8(addr);
1805 cpu->ChangePrivilegeMode(previous_mode); 2203 cpu->ChangePrivilegeMode(previous_mode);
1806 2204
1807 cpu->Reg[dest_index] = value; 2205 cpu->Reg[dest_index] = value;
1808 }
1809 cpu->Reg[15] += cpu->GetInstructionSize();
1810 INC_PC(sizeof(ldst_inst));
1811 FETCH_INST;
1812 GOTO_NEXT_INST;
1813 }
1814 LDRD_INST:
1815 {
1816 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1817 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1818 // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0)
1819 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1820
1821 // The 3DS doesn't have LPAE (Large Physical Access Extension), so it
1822 // wouldn't do this as a single read.
1823 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr);
1824 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = cpu->ReadMemory32(addr + 4);
1825
1826 // No dispatch since this operation should not modify R15
1827 }
1828 cpu->Reg[15] += 4;
1829 INC_PC(sizeof(ldst_inst));
1830 FETCH_INST;
1831 GOTO_NEXT_INST;
1832 } 2206 }
2207 cpu->Reg[15] += cpu->GetInstructionSize();
2208 INC_PC(sizeof(ldst_inst));
2209 FETCH_INST;
2210 GOTO_NEXT_INST;
2211}
2212LDRD_INST : {
2213 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2214 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2215 // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 ||
2216 // addr[2] == 0)
2217 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1833 2218
1834 LDREX_INST: 2219 // The 3DS doesn't have LPAE (Large Physical Access Extension), so it
1835 { 2220 // wouldn't do this as a single read.
1836 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2221 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr);
1837 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 2222 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = cpu->ReadMemory32(addr + 4);
1838 unsigned int read_addr = RN;
1839
1840 cpu->SetExclusiveMemoryAddress(read_addr);
1841 2223
1842 RD = cpu->ReadMemory32(read_addr); 2224 // No dispatch since this operation should not modify R15
1843 }
1844 cpu->Reg[15] += cpu->GetInstructionSize();
1845 INC_PC(sizeof(generic_arm_inst));
1846 FETCH_INST;
1847 GOTO_NEXT_INST;
1848 } 2225 }
1849 LDREXB_INST: 2226 cpu->Reg[15] += 4;
1850 { 2227 INC_PC(sizeof(ldst_inst));
1851 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2228 FETCH_INST;
1852 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 2229 GOTO_NEXT_INST;
1853 unsigned int read_addr = RN; 2230}
1854 2231
1855 cpu->SetExclusiveMemoryAddress(read_addr); 2232LDREX_INST : {
2233 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2234 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2235 unsigned int read_addr = RN;
1856 2236
1857 RD = cpu->ReadMemory8(read_addr); 2237 cpu->SetExclusiveMemoryAddress(read_addr);
1858 } 2238
1859 cpu->Reg[15] += cpu->GetInstructionSize(); 2239 RD = cpu->ReadMemory32(read_addr);
1860 INC_PC(sizeof(generic_arm_inst));
1861 FETCH_INST;
1862 GOTO_NEXT_INST;
1863 } 2240 }
1864 LDREXH_INST: 2241 cpu->Reg[15] += cpu->GetInstructionSize();
1865 { 2242 INC_PC(sizeof(generic_arm_inst));
1866 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2243 FETCH_INST;
1867 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 2244 GOTO_NEXT_INST;
1868 unsigned int read_addr = RN; 2245}
2246LDREXB_INST : {
2247 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2248 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2249 unsigned int read_addr = RN;
1869 2250
1870 cpu->SetExclusiveMemoryAddress(read_addr); 2251 cpu->SetExclusiveMemoryAddress(read_addr);
1871 2252
1872 RD = cpu->ReadMemory16(read_addr); 2253 RD = cpu->ReadMemory8(read_addr);
1873 }
1874 cpu->Reg[15] += cpu->GetInstructionSize();
1875 INC_PC(sizeof(generic_arm_inst));
1876 FETCH_INST;
1877 GOTO_NEXT_INST;
1878 } 2254 }
1879 LDREXD_INST: 2255 cpu->Reg[15] += cpu->GetInstructionSize();
1880 { 2256 INC_PC(sizeof(generic_arm_inst));
1881 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2257 FETCH_INST;
1882 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 2258 GOTO_NEXT_INST;
1883 unsigned int read_addr = RN; 2259}
2260LDREXH_INST : {
2261 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2262 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2263 unsigned int read_addr = RN;
1884 2264
1885 cpu->SetExclusiveMemoryAddress(read_addr); 2265 cpu->SetExclusiveMemoryAddress(read_addr);
1886 2266
1887 RD = cpu->ReadMemory32(read_addr); 2267 RD = cpu->ReadMemory16(read_addr);
1888 RD2 = cpu->ReadMemory32(read_addr + 4);
1889 }
1890 cpu->Reg[15] += cpu->GetInstructionSize();
1891 INC_PC(sizeof(generic_arm_inst));
1892 FETCH_INST;
1893 GOTO_NEXT_INST;
1894 }
1895 LDRH_INST:
1896 {
1897 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1898 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1899 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1900
1901 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr);
1902 }
1903 cpu->Reg[15] += cpu->GetInstructionSize();
1904 INC_PC(sizeof(ldst_inst));
1905 FETCH_INST;
1906 GOTO_NEXT_INST;
1907 }
1908 LDRSB_INST:
1909 {
1910 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1911 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1912 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1913 unsigned int value = cpu->ReadMemory8(addr);
1914 if (BIT(value, 7)) {
1915 value |= 0xffffff00;
1916 }
1917 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
1918 }
1919 cpu->Reg[15] += cpu->GetInstructionSize();
1920 INC_PC(sizeof(ldst_inst));
1921 FETCH_INST;
1922 GOTO_NEXT_INST;
1923 }
1924 LDRSH_INST:
1925 {
1926 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1927 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1928 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1929
1930 unsigned int value = cpu->ReadMemory16(addr);
1931 if (BIT(value, 15)) {
1932 value |= 0xffff0000;
1933 }
1934 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
1935 }
1936 cpu->Reg[15] += cpu->GetInstructionSize();
1937 INC_PC(sizeof(ldst_inst));
1938 FETCH_INST;
1939 GOTO_NEXT_INST;
1940 } 2268 }
1941 LDRT_INST: 2269 cpu->Reg[15] += cpu->GetInstructionSize();
1942 { 2270 INC_PC(sizeof(generic_arm_inst));
1943 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2271 FETCH_INST;
1944 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 2272 GOTO_NEXT_INST;
1945 inst_cream->get_addr(cpu, inst_cream->inst, addr); 2273}
2274LDREXD_INST : {
2275 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2276 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2277 unsigned int read_addr = RN;
1946 2278
1947 const u32 dest_index = BITS(inst_cream->inst, 12, 15); 2279 cpu->SetExclusiveMemoryAddress(read_addr);
1948 const u32 previous_mode = cpu->Mode;
1949 2280
1950 cpu->ChangePrivilegeMode(USER32MODE); 2281 RD = cpu->ReadMemory32(read_addr);
1951 const u32 value = cpu->ReadMemory32(addr); 2282 RD2 = cpu->ReadMemory32(read_addr + 4);
1952 cpu->ChangePrivilegeMode(previous_mode); 2283 }
2284 cpu->Reg[15] += cpu->GetInstructionSize();
2285 INC_PC(sizeof(generic_arm_inst));
2286 FETCH_INST;
2287 GOTO_NEXT_INST;
2288}
2289LDRH_INST : {
2290 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2291 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2292 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1953 2293
1954 cpu->Reg[dest_index] = value; 2294 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr);
2295 }
2296 cpu->Reg[15] += cpu->GetInstructionSize();
2297 INC_PC(sizeof(ldst_inst));
2298 FETCH_INST;
2299 GOTO_NEXT_INST;
2300}
2301LDRSB_INST : {
2302 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2303 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2304 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2305 unsigned int value = cpu->ReadMemory8(addr);
2306 if (BIT(value, 7)) {
2307 value |= 0xffffff00;
1955 } 2308 }
1956 cpu->Reg[15] += cpu->GetInstructionSize(); 2309 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
1957 INC_PC(sizeof(ldst_inst));
1958 FETCH_INST;
1959 GOTO_NEXT_INST;
1960 } 2310 }
1961 MCR_INST: 2311 cpu->Reg[15] += cpu->GetInstructionSize();
1962 { 2312 INC_PC(sizeof(ldst_inst));
1963 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2313 FETCH_INST;
1964 mcr_inst* inst_cream = (mcr_inst*)inst_base->component; 2314 GOTO_NEXT_INST;
2315}
2316LDRSH_INST : {
2317 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2318 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2319 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1965 2320
1966 unsigned int inst = inst_cream->inst; 2321 unsigned int value = cpu->ReadMemory16(addr);
1967 if (inst_cream->Rd == 15) { 2322 if (BIT(value, 15)) {
1968 DEBUG_MSG; 2323 value |= 0xffff0000;
1969 } else {
1970 if (inst_cream->cp_num == 15)
1971 cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2);
1972 }
1973 } 2324 }
1974 cpu->Reg[15] += cpu->GetInstructionSize(); 2325 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
1975 INC_PC(sizeof(mcr_inst));
1976 FETCH_INST;
1977 GOTO_NEXT_INST;
1978 } 2326 }
2327 cpu->Reg[15] += cpu->GetInstructionSize();
2328 INC_PC(sizeof(ldst_inst));
2329 FETCH_INST;
2330 GOTO_NEXT_INST;
2331}
2332LDRT_INST : {
2333 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2334 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2335 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2336
2337 const u32 dest_index = BITS(inst_cream->inst, 12, 15);
2338 const u32 previous_mode = cpu->Mode;
1979 2339
1980 MCRR_INST: 2340 cpu->ChangePrivilegeMode(USER32MODE);
1981 { 2341 const u32 value = cpu->ReadMemory32(addr);
1982 // Stubbed, as the MPCore doesn't have any registers that are accessible 2342 cpu->ChangePrivilegeMode(previous_mode);
1983 // through this instruction.
1984 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1985 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
1986 2343
1987 LOG_ERROR(Core_ARM11, "MCRR executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", 2344 cpu->Reg[dest_index] = value;
1988 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); 2345 }
2346 cpu->Reg[15] += cpu->GetInstructionSize();
2347 INC_PC(sizeof(ldst_inst));
2348 FETCH_INST;
2349 GOTO_NEXT_INST;
2350}
2351MCR_INST : {
2352 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2353 mcr_inst* inst_cream = (mcr_inst*)inst_base->component;
2354
2355 unsigned int inst = inst_cream->inst;
2356 if (inst_cream->Rd == 15) {
2357 DEBUG_MSG;
2358 } else {
2359 if (inst_cream->cp_num == 15)
2360 cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2);
1989 } 2361 }
2362 }
2363 cpu->Reg[15] += cpu->GetInstructionSize();
2364 INC_PC(sizeof(mcr_inst));
2365 FETCH_INST;
2366 GOTO_NEXT_INST;
2367}
2368
2369MCRR_INST : {
2370 // Stubbed, as the MPCore doesn't have any registers that are accessible
2371 // through this instruction.
2372 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2373 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
1990 2374
1991 cpu->Reg[15] += cpu->GetInstructionSize(); 2375 LOG_ERROR(Core_ARM11, "MCRR executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u",
1992 INC_PC(sizeof(mcrr_inst)); 2376 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt,
1993 FETCH_INST; 2377 inst_cream->rt2);
1994 GOTO_NEXT_INST;
1995 } 2378 }
1996 2379
1997 MLA_INST: 2380 cpu->Reg[15] += cpu->GetInstructionSize();
1998 { 2381 INC_PC(sizeof(mcrr_inst));
1999 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2382 FETCH_INST;
2000 mla_inst* inst_cream = (mla_inst*)inst_base->component; 2383 GOTO_NEXT_INST;
2384}
2001 2385
2002 u64 rm = RM; 2386MLA_INST : {
2003 u64 rs = RS; 2387 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2004 u64 rn = RN; 2388 mla_inst* inst_cream = (mla_inst*)inst_base->component;
2005 2389
2006 RD = static_cast<u32>((rm * rs + rn) & 0xffffffff); 2390 u64 rm = RM;
2007 if (inst_cream->S) { 2391 u64 rs = RS;
2008 UPDATE_NFLAG(RD); 2392 u64 rn = RN;
2009 UPDATE_ZFLAG(RD); 2393
2010 } 2394 RD = static_cast<u32>((rm * rs + rn) & 0xffffffff);
2395 if (inst_cream->S) {
2396 UPDATE_NFLAG(RD);
2397 UPDATE_ZFLAG(RD);
2011 } 2398 }
2012 cpu->Reg[15] += cpu->GetInstructionSize(); 2399 }
2013 INC_PC(sizeof(mla_inst)); 2400 cpu->Reg[15] += cpu->GetInstructionSize();
2014 FETCH_INST; 2401 INC_PC(sizeof(mla_inst));
2015 GOTO_NEXT_INST; 2402 FETCH_INST;
2016 } 2403 GOTO_NEXT_INST;
2017 MOV_INST: 2404}
2018 { 2405MOV_INST : {
2019 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2406 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2020 mov_inst* inst_cream = (mov_inst*)inst_base->component; 2407 mov_inst* inst_cream = (mov_inst*)inst_base->component;
2021 2408
2022 RD = SHIFTER_OPERAND; 2409 RD = SHIFTER_OPERAND;
2023 if (inst_cream->S && (inst_cream->Rd == 15)) { 2410 if (inst_cream->S && (inst_cream->Rd == 15)) {
2024 if (CurrentModeHasSPSR) { 2411 if (CurrentModeHasSPSR) {
2025 cpu->Cpsr = cpu->Spsr_copy; 2412 cpu->Cpsr = cpu->Spsr_copy;
2026 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 2413 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2027 LOAD_NZCVT; 2414 LOAD_NZCVT;
2028 }
2029 } else if (inst_cream->S) {
2030 UPDATE_NFLAG(RD);
2031 UPDATE_ZFLAG(RD);
2032 UPDATE_CFLAG_WITH_SC;
2033 }
2034 if (inst_cream->Rd == 15) {
2035 INC_PC(sizeof(mov_inst));
2036 goto DISPATCH;
2037 } 2415 }
2416 } else if (inst_cream->S) {
2417 UPDATE_NFLAG(RD);
2418 UPDATE_ZFLAG(RD);
2419 UPDATE_CFLAG_WITH_SC;
2038 } 2420 }
2039 cpu->Reg[15] += cpu->GetInstructionSize(); 2421 if (inst_cream->Rd == 15) {
2040 INC_PC(sizeof(mov_inst)); 2422 INC_PC(sizeof(mov_inst));
2041 FETCH_INST; 2423 goto DISPATCH;
2042 GOTO_NEXT_INST;
2043 }
2044 MRC_INST:
2045 {
2046 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2047 mrc_inst* inst_cream = (mrc_inst*)inst_base->component;
2048
2049 if (inst_cream->cp_num == 15) {
2050 const uint32_t value = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2);
2051
2052 if (inst_cream->Rd == 15) {
2053 cpu->Cpsr = (cpu->Cpsr & ~0xF0000000) | (value & 0xF0000000);
2054 LOAD_NZCVT;
2055 } else {
2056 RD = value;
2057 }
2058 }
2059 } 2424 }
2060 cpu->Reg[15] += cpu->GetInstructionSize();
2061 INC_PC(sizeof(mrc_inst));
2062 FETCH_INST;
2063 GOTO_NEXT_INST;
2064 } 2425 }
2426 cpu->Reg[15] += cpu->GetInstructionSize();
2427 INC_PC(sizeof(mov_inst));
2428 FETCH_INST;
2429 GOTO_NEXT_INST;
2430}
2431MRC_INST : {
2432 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2433 mrc_inst* inst_cream = (mrc_inst*)inst_base->component;
2065 2434
2066 MRRC_INST: 2435 if (inst_cream->cp_num == 15) {
2067 { 2436 const uint32_t value = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2);
2068 // Stubbed, as the MPCore doesn't have any registers that are accessible
2069 // through this instruction.
2070 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2071 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
2072 2437
2073 LOG_ERROR(Core_ARM11, "MRRC executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", 2438 if (inst_cream->Rd == 15) {
2074 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); 2439 cpu->Cpsr = (cpu->Cpsr & ~0xF0000000) | (value & 0xF0000000);
2440 LOAD_NZCVT;
2441 } else {
2442 RD = value;
2443 }
2075 } 2444 }
2445 }
2446 cpu->Reg[15] += cpu->GetInstructionSize();
2447 INC_PC(sizeof(mrc_inst));
2448 FETCH_INST;
2449 GOTO_NEXT_INST;
2450}
2451
2452MRRC_INST : {
2453 // Stubbed, as the MPCore doesn't have any registers that are accessible
2454 // through this instruction.
2455 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2456 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
2076 2457
2077 cpu->Reg[15] += cpu->GetInstructionSize(); 2458 LOG_ERROR(Core_ARM11, "MRRC executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u",
2078 INC_PC(sizeof(mcrr_inst)); 2459 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt,
2079 FETCH_INST; 2460 inst_cream->rt2);
2080 GOTO_NEXT_INST;
2081 } 2461 }
2082 2462
2083 MRS_INST: 2463 cpu->Reg[15] += cpu->GetInstructionSize();
2084 { 2464 INC_PC(sizeof(mcrr_inst));
2085 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2465 FETCH_INST;
2086 mrs_inst* inst_cream = (mrs_inst*)inst_base->component; 2466 GOTO_NEXT_INST;
2467}
2468
2469MRS_INST : {
2470 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2471 mrs_inst* inst_cream = (mrs_inst*)inst_base->component;
2087 2472
2088 if (inst_cream->R) { 2473 if (inst_cream->R) {
2089 RD = cpu->Spsr_copy; 2474 RD = cpu->Spsr_copy;
2090 } else { 2475 } else {
2091 SAVE_NZCVT; 2476 SAVE_NZCVT;
2092 RD = cpu->Cpsr; 2477 RD = cpu->Cpsr;
2093 }
2094 } 2478 }
2095 cpu->Reg[15] += cpu->GetInstructionSize(); 2479 }
2096 INC_PC(sizeof(mrs_inst)); 2480 cpu->Reg[15] += cpu->GetInstructionSize();
2097 FETCH_INST; 2481 INC_PC(sizeof(mrs_inst));
2098 GOTO_NEXT_INST; 2482 FETCH_INST;
2099 } 2483 GOTO_NEXT_INST;
2100 MSR_INST: 2484}
2101 { 2485MSR_INST : {
2102 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2486 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2103 msr_inst* inst_cream = (msr_inst*)inst_base->component; 2487 msr_inst* inst_cream = (msr_inst*)inst_base->component;
2104 const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; 2488 const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
2105 unsigned int inst = inst_cream->inst; 2489 unsigned int inst = inst_cream->inst;
2106 unsigned int operand; 2490 unsigned int operand;
2107 2491
2108 if (BIT(inst, 25)) { 2492 if (BIT(inst, 25)) {
2109 int rot_imm = BITS(inst, 8, 11) * 2; 2493 int rot_imm = BITS(inst, 8, 11) * 2;
2110 operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); 2494 operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
2495 } else {
2496 operand = cpu->Reg[BITS(inst, 0, 3)];
2497 }
2498 u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) |
2499 (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
2500 u32 mask = 0;
2501 if (!inst_cream->R) {
2502 if (cpu->InAPrivilegedMode()) {
2503 if ((operand & StateMask) != 0) {
2504 /// UNPREDICTABLE
2505 DEBUG_MSG;
2506 } else
2507 mask = byte_mask & (UserMask | PrivMask);
2111 } else { 2508 } else {
2112 operand = cpu->Reg[BITS(inst, 0, 3)]; 2509 mask = byte_mask & UserMask;
2113 } 2510 }
2114 u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) 2511 SAVE_NZCVT;
2115 | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
2116 u32 mask = 0;
2117 if (!inst_cream->R) {
2118 if (cpu->InAPrivilegedMode()) {
2119 if ((operand & StateMask) != 0) {
2120 /// UNPREDICTABLE
2121 DEBUG_MSG;
2122 } else
2123 mask = byte_mask & (UserMask | PrivMask);
2124 } else {
2125 mask = byte_mask & UserMask;
2126 }
2127 SAVE_NZCVT;
2128 2512
2129 cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); 2513 cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
2130 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); 2514 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
2131 LOAD_NZCVT; 2515 LOAD_NZCVT;
2132 } else { 2516 } else {
2133 if (CurrentModeHasSPSR) { 2517 if (CurrentModeHasSPSR) {
2134 mask = byte_mask & (UserMask | PrivMask | StateMask); 2518 mask = byte_mask & (UserMask | PrivMask | StateMask);
2135 cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); 2519 cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask);
2136 }
2137 } 2520 }
2138 } 2521 }
2139 cpu->Reg[15] += cpu->GetInstructionSize(); 2522 }
2140 INC_PC(sizeof(msr_inst)); 2523 cpu->Reg[15] += cpu->GetInstructionSize();
2141 FETCH_INST; 2524 INC_PC(sizeof(msr_inst));
2142 GOTO_NEXT_INST; 2525 FETCH_INST;
2143 } 2526 GOTO_NEXT_INST;
2144 MUL_INST: 2527}
2145 { 2528MUL_INST : {
2146 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2529 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2147 mul_inst* inst_cream = (mul_inst*)inst_base->component; 2530 mul_inst* inst_cream = (mul_inst*)inst_base->component;
2148 2531
2149 u64 rm = RM; 2532 u64 rm = RM;
2150 u64 rs = RS; 2533 u64 rs = RS;
2151 RD = static_cast<u32>((rm * rs) & 0xffffffff); 2534 RD = static_cast<u32>((rm * rs) & 0xffffffff);
2152 if (inst_cream->S) { 2535 if (inst_cream->S) {
2153 UPDATE_NFLAG(RD); 2536 UPDATE_NFLAG(RD);
2154 UPDATE_ZFLAG(RD); 2537 UPDATE_ZFLAG(RD);
2155 }
2156 } 2538 }
2157 cpu->Reg[15] += cpu->GetInstructionSize(); 2539 }
2158 INC_PC(sizeof(mul_inst)); 2540 cpu->Reg[15] += cpu->GetInstructionSize();
2159 FETCH_INST; 2541 INC_PC(sizeof(mul_inst));
2160 GOTO_NEXT_INST; 2542 FETCH_INST;
2161 } 2543 GOTO_NEXT_INST;
2162 MVN_INST: 2544}
2163 { 2545MVN_INST : {
2164 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2546 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2165 mvn_inst* const inst_cream = (mvn_inst*)inst_base->component; 2547 mvn_inst* const inst_cream = (mvn_inst*)inst_base->component;
2166 2548
2167 RD = ~SHIFTER_OPERAND; 2549 RD = ~SHIFTER_OPERAND;
2168 2550
2169 if (inst_cream->S && (inst_cream->Rd == 15)) { 2551 if (inst_cream->S && (inst_cream->Rd == 15)) {
2170 if (CurrentModeHasSPSR) { 2552 if (CurrentModeHasSPSR) {
2171 cpu->Cpsr = cpu->Spsr_copy; 2553 cpu->Cpsr = cpu->Spsr_copy;
2172 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 2554 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2173 LOAD_NZCVT; 2555 LOAD_NZCVT;
2174 }
2175 } else if (inst_cream->S) {
2176 UPDATE_NFLAG(RD);
2177 UPDATE_ZFLAG(RD);
2178 UPDATE_CFLAG_WITH_SC;
2179 }
2180 if (inst_cream->Rd == 15) {
2181 INC_PC(sizeof(mvn_inst));
2182 goto DISPATCH;
2183 } 2556 }
2557 } else if (inst_cream->S) {
2558 UPDATE_NFLAG(RD);
2559 UPDATE_ZFLAG(RD);
2560 UPDATE_CFLAG_WITH_SC;
2561 }
2562 if (inst_cream->Rd == 15) {
2563 INC_PC(sizeof(mvn_inst));
2564 goto DISPATCH;
2184 } 2565 }
2185 cpu->Reg[15] += cpu->GetInstructionSize();
2186 INC_PC(sizeof(mvn_inst));
2187 FETCH_INST;
2188 GOTO_NEXT_INST;
2189 } 2566 }
2190 ORR_INST: 2567 cpu->Reg[15] += cpu->GetInstructionSize();
2191 { 2568 INC_PC(sizeof(mvn_inst));
2192 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2569 FETCH_INST;
2193 orr_inst* const inst_cream = (orr_inst*)inst_base->component; 2570 GOTO_NEXT_INST;
2571}
2572ORR_INST : {
2573 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2574 orr_inst* const inst_cream = (orr_inst*)inst_base->component;
2194 2575
2195 u32 lop = RN; 2576 u32 lop = RN;
2196 u32 rop = SHIFTER_OPERAND; 2577 u32 rop = SHIFTER_OPERAND;
2197 2578
2198 if (inst_cream->Rn == 15) 2579 if (inst_cream->Rn == 15)
2199 lop += 2 * cpu->GetInstructionSize(); 2580 lop += 2 * cpu->GetInstructionSize();
2200 2581
2201 RD = lop | rop; 2582 RD = lop | rop;
2202 2583
2203 if (inst_cream->S && (inst_cream->Rd == 15)) { 2584 if (inst_cream->S && (inst_cream->Rd == 15)) {
2204 if (CurrentModeHasSPSR) { 2585 if (CurrentModeHasSPSR) {
2205 cpu->Cpsr = cpu->Spsr_copy; 2586 cpu->Cpsr = cpu->Spsr_copy;
2206 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 2587 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2207 LOAD_NZCVT; 2588 LOAD_NZCVT;
2208 }
2209 } else if (inst_cream->S) {
2210 UPDATE_NFLAG(RD);
2211 UPDATE_ZFLAG(RD);
2212 UPDATE_CFLAG_WITH_SC;
2213 }
2214 if (inst_cream->Rd == 15) {
2215 INC_PC(sizeof(orr_inst));
2216 goto DISPATCH;
2217 } 2589 }
2590 } else if (inst_cream->S) {
2591 UPDATE_NFLAG(RD);
2592 UPDATE_ZFLAG(RD);
2593 UPDATE_CFLAG_WITH_SC;
2594 }
2595 if (inst_cream->Rd == 15) {
2596 INC_PC(sizeof(orr_inst));
2597 goto DISPATCH;
2218 } 2598 }
2219 cpu->Reg[15] += cpu->GetInstructionSize();
2220 INC_PC(sizeof(orr_inst));
2221 FETCH_INST;
2222 GOTO_NEXT_INST;
2223 } 2599 }
2600 cpu->Reg[15] += cpu->GetInstructionSize();
2601 INC_PC(sizeof(orr_inst));
2602 FETCH_INST;
2603 GOTO_NEXT_INST;
2604}
2605
2606NOP_INST : {
2607 cpu->Reg[15] += cpu->GetInstructionSize();
2608 INC_PC_STUB;
2609 FETCH_INST;
2610 GOTO_NEXT_INST;
2611}
2224 2612
2225 NOP_INST: 2613PKHBT_INST : {
2226 { 2614 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2227 cpu->Reg[15] += cpu->GetInstructionSize(); 2615 pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
2228 INC_PC_STUB; 2616 RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000);
2229 FETCH_INST;
2230 GOTO_NEXT_INST;
2231 } 2617 }
2618 cpu->Reg[15] += cpu->GetInstructionSize();
2619 INC_PC(sizeof(pkh_inst));
2620 FETCH_INST;
2621 GOTO_NEXT_INST;
2622}
2232 2623
2233 PKHBT_INST: 2624PKHTB_INST : {
2234 { 2625 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2235 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2626 pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
2236 pkh_inst *inst_cream = (pkh_inst *)inst_base->component; 2627 int shift_imm = inst_cream->imm ? inst_cream->imm : 31;
2237 RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000); 2628 RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000);
2238 } 2629 }
2239 cpu->Reg[15] += cpu->GetInstructionSize(); 2630 cpu->Reg[15] += cpu->GetInstructionSize();
2240 INC_PC(sizeof(pkh_inst)); 2631 INC_PC(sizeof(pkh_inst));
2241 FETCH_INST; 2632 FETCH_INST;
2242 GOTO_NEXT_INST; 2633 GOTO_NEXT_INST;
2243 } 2634}
2244
2245 PKHTB_INST:
2246 {
2247 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2248 pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
2249 int shift_imm = inst_cream->imm ? inst_cream->imm : 31;
2250 RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000);
2251 }
2252 cpu->Reg[15] += cpu->GetInstructionSize();
2253 INC_PC(sizeof(pkh_inst));
2254 FETCH_INST;
2255 GOTO_NEXT_INST;
2256 }
2257
2258 PLD_INST:
2259 {
2260 // Not implemented. PLD is a hint instruction, so it's optional.
2261
2262 cpu->Reg[15] += cpu->GetInstructionSize();
2263 INC_PC(sizeof(pld_inst));
2264 FETCH_INST;
2265 GOTO_NEXT_INST;
2266 }
2267
2268 QADD_INST:
2269 QDADD_INST:
2270 QDSUB_INST:
2271 QSUB_INST:
2272 {
2273 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2274 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2275 const u8 op1 = inst_cream->op1;
2276 const u32 rm_val = RM;
2277 const u32 rn_val = RN;
2278 2635
2279 u32 result = 0; 2636PLD_INST : {
2637 // Not implemented. PLD is a hint instruction, so it's optional.
2280 2638
2281 // QADD 2639 cpu->Reg[15] += cpu->GetInstructionSize();
2282 if (op1 == 0x00) { 2640 INC_PC(sizeof(pld_inst));
2283 result = rm_val + rn_val; 2641 FETCH_INST;
2642 GOTO_NEXT_INST;
2643}
2284 2644
2285 if (AddOverflow(rm_val, rn_val, result)) { 2645QADD_INST:
2286 result = POS(result) ? 0x80000000 : 0x7FFFFFFF; 2646QDADD_INST:
2287 cpu->Cpsr |= (1 << 27); 2647QDSUB_INST:
2288 } 2648QSUB_INST : {
2289 } 2649 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2290 // QSUB 2650 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2291 else if (op1 == 0x01) { 2651 const u8 op1 = inst_cream->op1;
2292 result = rm_val - rn_val; 2652 const u32 rm_val = RM;
2653 const u32 rn_val = RN;
2293 2654
2294 if (SubOverflow(rm_val, rn_val, result)) { 2655 u32 result = 0;
2295 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2296 cpu->Cpsr |= (1 << 27);
2297 }
2298 }
2299 // QDADD
2300 else if (op1 == 0x02) {
2301 u32 mul = (rn_val * 2);
2302 2656
2303 if (AddOverflow(rn_val, rn_val, rn_val * 2)) { 2657 // QADD
2304 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; 2658 if (op1 == 0x00) {
2305 cpu->Cpsr |= (1 << 27); 2659 result = rm_val + rn_val;
2306 }
2307 2660
2308 result = mul + rm_val; 2661 if (AddOverflow(rm_val, rn_val, result)) {
2662 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2663 cpu->Cpsr |= (1 << 27);
2664 }
2665 }
2666 // QSUB
2667 else if (op1 == 0x01) {
2668 result = rm_val - rn_val;
2309 2669
2310 if (AddOverflow(rm_val, mul, result)) { 2670 if (SubOverflow(rm_val, rn_val, result)) {
2311 result = POS(result) ? 0x80000000 : 0x7FFFFFFF; 2671 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2312 cpu->Cpsr |= (1 << 27); 2672 cpu->Cpsr |= (1 << 27);
2313 }
2314 } 2673 }
2315 // QDSUB 2674 }
2316 else if (op1 == 0x03) { 2675 // QDADD
2317 u32 mul = (rn_val * 2); 2676 else if (op1 == 0x02) {
2677 u32 mul = (rn_val * 2);
2318 2678
2319 if (AddOverflow(rn_val, rn_val, mul)) { 2679 if (AddOverflow(rn_val, rn_val, rn_val * 2)) {
2320 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; 2680 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
2321 cpu->Cpsr |= (1 << 27); 2681 cpu->Cpsr |= (1 << 27);
2322 } 2682 }
2323 2683
2324 result = rm_val - mul; 2684 result = mul + rm_val;
2325 2685
2326 if (SubOverflow(rm_val, mul, result)) { 2686 if (AddOverflow(rm_val, mul, result)) {
2327 result = POS(result) ? 0x80000000 : 0x7FFFFFFF; 2687 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2328 cpu->Cpsr |= (1 << 27); 2688 cpu->Cpsr |= (1 << 27);
2329 }
2330 } 2689 }
2331
2332 RD = result;
2333 } 2690 }
2691 // QDSUB
2692 else if (op1 == 0x03) {
2693 u32 mul = (rn_val * 2);
2334 2694
2335 cpu->Reg[15] += cpu->GetInstructionSize(); 2695 if (AddOverflow(rn_val, rn_val, mul)) {
2336 INC_PC(sizeof(generic_arm_inst)); 2696 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
2337 FETCH_INST; 2697 cpu->Cpsr |= (1 << 27);
2338 GOTO_NEXT_INST;
2339 }
2340
2341 QADD8_INST:
2342 QADD16_INST:
2343 QADDSUBX_INST:
2344 QSUB8_INST:
2345 QSUB16_INST:
2346 QSUBADDX_INST:
2347 {
2348 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2349 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2350 const u16 rm_lo = (RM & 0xFFFF);
2351 const u16 rm_hi = ((RM >> 16) & 0xFFFF);
2352 const u16 rn_lo = (RN & 0xFFFF);
2353 const u16 rn_hi = ((RN >> 16) & 0xFFFF);
2354 const u8 op2 = inst_cream->op2;
2355
2356 u16 lo_result = 0;
2357 u16 hi_result = 0;
2358
2359 // QADD16
2360 if (op2 == 0x00) {
2361 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
2362 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
2363 }
2364 // QASX
2365 else if (op2 == 0x01) {
2366 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
2367 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
2368 }
2369 // QSAX
2370 else if (op2 == 0x02) {
2371 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
2372 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
2373 }
2374 // QSUB16
2375 else if (op2 == 0x03) {
2376 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
2377 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
2378 }
2379 // QADD8
2380 else if (op2 == 0x04) {
2381 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
2382 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
2383 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
2384 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
2385 } 2698 }
2386 // QSUB8 2699
2387 else if (op2 == 0x07) { 2700 result = rm_val - mul;
2388 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) | 2701
2389 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8; 2702 if (SubOverflow(rm_val, mul, result)) {
2390 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) | 2703 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2391 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8; 2704 cpu->Cpsr |= (1 << 27);
2392 } 2705 }
2706 }
2393 2707
2394 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); 2708 RD = result;
2709 }
2710
2711 cpu->Reg[15] += cpu->GetInstructionSize();
2712 INC_PC(sizeof(generic_arm_inst));
2713 FETCH_INST;
2714 GOTO_NEXT_INST;
2715}
2716
2717QADD8_INST:
2718QADD16_INST:
2719QADDSUBX_INST:
2720QSUB8_INST:
2721QSUB16_INST:
2722QSUBADDX_INST : {
2723 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2724 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2725 const u16 rm_lo = (RM & 0xFFFF);
2726 const u16 rm_hi = ((RM >> 16) & 0xFFFF);
2727 const u16 rn_lo = (RN & 0xFFFF);
2728 const u16 rn_hi = ((RN >> 16) & 0xFFFF);
2729 const u8 op2 = inst_cream->op2;
2730
2731 u16 lo_result = 0;
2732 u16 hi_result = 0;
2733
2734 // QADD16
2735 if (op2 == 0x00) {
2736 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
2737 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
2738 }
2739 // QASX
2740 else if (op2 == 0x01) {
2741 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
2742 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
2743 }
2744 // QSAX
2745 else if (op2 == 0x02) {
2746 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
2747 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
2748 }
2749 // QSUB16
2750 else if (op2 == 0x03) {
2751 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
2752 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
2753 }
2754 // QADD8
2755 else if (op2 == 0x04) {
2756 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
2757 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
2758 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
2759 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
2760 }
2761 // QSUB8
2762 else if (op2 == 0x07) {
2763 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
2764 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
2765 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
2766 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
2395 } 2767 }
2396 2768
2397 cpu->Reg[15] += cpu->GetInstructionSize(); 2769 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
2398 INC_PC(sizeof(generic_arm_inst));
2399 FETCH_INST;
2400 GOTO_NEXT_INST;
2401 } 2770 }
2402 2771
2403 REV_INST: 2772 cpu->Reg[15] += cpu->GetInstructionSize();
2404 REV16_INST: 2773 INC_PC(sizeof(generic_arm_inst));
2405 REVSH_INST: 2774 FETCH_INST;
2406 { 2775 GOTO_NEXT_INST;
2776}
2407 2777
2408 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2778REV_INST:
2409 rev_inst* const inst_cream = (rev_inst*)inst_base->component; 2779REV16_INST:
2780REVSH_INST : {
2410 2781
2411 const u8 op1 = inst_cream->op1; 2782 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2412 const u8 op2 = inst_cream->op2; 2783 rev_inst* const inst_cream = (rev_inst*)inst_base->component;
2413 2784
2414 // REV 2785 const u8 op1 = inst_cream->op1;
2415 if (op1 == 0x03 && op2 == 0x01) { 2786 const u8 op2 = inst_cream->op2;
2416 RD = ((RM & 0xFF) << 24) | (((RM >> 8) & 0xFF) << 16) | (((RM >> 16) & 0xFF) << 8) | ((RM >> 24) & 0xFF);
2417 }
2418 // REV16
2419 else if (op1 == 0x03 && op2 == 0x05) {
2420 RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8) | ((RM & 0xFF0000) << 8) | ((RM & 0xFF000000) >> 8);
2421 }
2422 // REVSH
2423 else if (op1 == 0x07 && op2 == 0x05) {
2424 RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8);
2425 if (RD & 0x8000)
2426 RD |= 0xffff0000;
2427 }
2428 }
2429 2787
2430 cpu->Reg[15] += cpu->GetInstructionSize(); 2788 // REV
2431 INC_PC(sizeof(rev_inst)); 2789 if (op1 == 0x03 && op2 == 0x01) {
2432 FETCH_INST; 2790 RD = ((RM & 0xFF) << 24) | (((RM >> 8) & 0xFF) << 16) | (((RM >> 16) & 0xFF) << 8) |
2433 GOTO_NEXT_INST; 2791 ((RM >> 24) & 0xFF);
2792 }
2793 // REV16
2794 else if (op1 == 0x03 && op2 == 0x05) {
2795 RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8) | ((RM & 0xFF0000) << 8) |
2796 ((RM & 0xFF000000) >> 8);
2797 }
2798 // REVSH
2799 else if (op1 == 0x07 && op2 == 0x05) {
2800 RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8);
2801 if (RD & 0x8000)
2802 RD |= 0xffff0000;
2803 }
2434 } 2804 }
2435 2805
2436 RFE_INST: 2806 cpu->Reg[15] += cpu->GetInstructionSize();
2437 { 2807 INC_PC(sizeof(rev_inst));
2438 // RFE is unconditional 2808 FETCH_INST;
2439 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; 2809 GOTO_NEXT_INST;
2810}
2440 2811
2441 u32 address = 0; 2812RFE_INST : {
2442 inst_cream->get_addr(cpu, inst_cream->inst, address); 2813 // RFE is unconditional
2814 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
2443 2815
2444 cpu->Cpsr = cpu->ReadMemory32(address); 2816 u32 address = 0;
2445 cpu->Reg[15] = cpu->ReadMemory32(address + 4); 2817 inst_cream->get_addr(cpu, inst_cream->inst, address);
2446 2818
2447 INC_PC(sizeof(ldst_inst)); 2819 cpu->Cpsr = cpu->ReadMemory32(address);
2448 goto DISPATCH; 2820 cpu->Reg[15] = cpu->ReadMemory32(address + 4);
2449 }
2450 2821
2451 RSB_INST: 2822 INC_PC(sizeof(ldst_inst));
2452 { 2823 goto DISPATCH;
2453 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2824}
2454 rsb_inst* const inst_cream = (rsb_inst*)inst_base->component;
2455 2825
2456 u32 rn_val = RN; 2826RSB_INST : {
2457 if (inst_cream->Rn == 15) 2827 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2458 rn_val += 2 * cpu->GetInstructionSize(); 2828 rsb_inst* const inst_cream = (rsb_inst*)inst_base->component;
2459 2829
2460 bool carry; 2830 u32 rn_val = RN;
2461 bool overflow; 2831 if (inst_cream->Rn == 15)
2462 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow); 2832 rn_val += 2 * cpu->GetInstructionSize();
2463 2833
2464 if (inst_cream->S && (inst_cream->Rd == 15)) { 2834 bool carry;
2465 if (CurrentModeHasSPSR) { 2835 bool overflow;
2466 cpu->Cpsr = cpu->Spsr_copy; 2836 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow);
2467 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 2837
2468 LOAD_NZCVT; 2838 if (inst_cream->S && (inst_cream->Rd == 15)) {
2469 } 2839 if (CurrentModeHasSPSR) {
2470 } else if (inst_cream->S) { 2840 cpu->Cpsr = cpu->Spsr_copy;
2471 UPDATE_NFLAG(RD); 2841 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2472 UPDATE_ZFLAG(RD); 2842 LOAD_NZCVT;
2473 cpu->CFlag = carry;
2474 cpu->VFlag = overflow;
2475 } 2843 }
2476 if (inst_cream->Rd == 15) { 2844 } else if (inst_cream->S) {
2477 INC_PC(sizeof(rsb_inst)); 2845 UPDATE_NFLAG(RD);
2478 goto DISPATCH; 2846 UPDATE_ZFLAG(RD);
2847 cpu->CFlag = carry;
2848 cpu->VFlag = overflow;
2849 }
2850 if (inst_cream->Rd == 15) {
2851 INC_PC(sizeof(rsb_inst));
2852 goto DISPATCH;
2853 }
2854 }
2855 cpu->Reg[15] += cpu->GetInstructionSize();
2856 INC_PC(sizeof(rsb_inst));
2857 FETCH_INST;
2858 GOTO_NEXT_INST;
2859}
2860RSC_INST : {
2861 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2862 rsc_inst* const inst_cream = (rsc_inst*)inst_base->component;
2863
2864 u32 rn_val = RN;
2865 if (inst_cream->Rn == 15)
2866 rn_val += 2 * cpu->GetInstructionSize();
2867
2868 bool carry;
2869 bool overflow;
2870 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
2871
2872 if (inst_cream->S && (inst_cream->Rd == 15)) {
2873 if (CurrentModeHasSPSR) {
2874 cpu->Cpsr = cpu->Spsr_copy;
2875 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2876 LOAD_NZCVT;
2479 } 2877 }
2878 } else if (inst_cream->S) {
2879 UPDATE_NFLAG(RD);
2880 UPDATE_ZFLAG(RD);
2881 cpu->CFlag = carry;
2882 cpu->VFlag = overflow;
2480 } 2883 }
2481 cpu->Reg[15] += cpu->GetInstructionSize(); 2884 if (inst_cream->Rd == 15) {
2482 INC_PC(sizeof(rsb_inst)); 2885 INC_PC(sizeof(rsc_inst));
2483 FETCH_INST; 2886 goto DISPATCH;
2484 GOTO_NEXT_INST; 2887 }
2485 } 2888 }
2486 RSC_INST: 2889 cpu->Reg[15] += cpu->GetInstructionSize();
2487 { 2890 INC_PC(sizeof(rsc_inst));
2488 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2891 FETCH_INST;
2489 rsc_inst* const inst_cream = (rsc_inst*)inst_base->component; 2892 GOTO_NEXT_INST;
2490 2893}
2491 u32 rn_val = RN; 2894
2492 if (inst_cream->Rn == 15) 2895SADD8_INST:
2493 rn_val += 2 * cpu->GetInstructionSize(); 2896SSUB8_INST:
2494 2897SADD16_INST:
2495 bool carry; 2898SADDSUBX_INST:
2496 bool overflow; 2899SSUBADDX_INST:
2497 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); 2900SSUB16_INST : {
2498 2901 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2499 if (inst_cream->S && (inst_cream->Rd == 15)) { 2902 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2500 if (CurrentModeHasSPSR) { 2903 const u8 op2 = inst_cream->op2;
2501 cpu->Cpsr = cpu->Spsr_copy; 2904
2502 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 2905 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
2503 LOAD_NZCVT; 2906 const s16 rn_lo = (RN & 0xFFFF);
2504 } 2907 const s16 rn_hi = ((RN >> 16) & 0xFFFF);
2505 } else if (inst_cream->S) { 2908 const s16 rm_lo = (RM & 0xFFFF);
2506 UPDATE_NFLAG(RD); 2909 const s16 rm_hi = ((RM >> 16) & 0xFFFF);
2507 UPDATE_ZFLAG(RD); 2910
2508 cpu->CFlag = carry; 2911 s32 lo_result = 0;
2509 cpu->VFlag = overflow; 2912 s32 hi_result = 0;
2913
2914 // SADD16
2915 if (inst_cream->op2 == 0x00) {
2916 lo_result = (rn_lo + rm_lo);
2917 hi_result = (rn_hi + rm_hi);
2510 } 2918 }
2511 if (inst_cream->Rd == 15) { 2919 // SASX
2512 INC_PC(sizeof(rsc_inst)); 2920 else if (op2 == 0x01) {
2513 goto DISPATCH; 2921 lo_result = (rn_lo - rm_hi);
2922 hi_result = (rn_hi + rm_lo);
2923 }
2924 // SSAX
2925 else if (op2 == 0x02) {
2926 lo_result = (rn_lo + rm_hi);
2927 hi_result = (rn_hi - rm_lo);
2928 }
2929 // SSUB16
2930 else if (op2 == 0x03) {
2931 lo_result = (rn_lo - rm_lo);
2932 hi_result = (rn_hi - rm_hi);
2514 } 2933 }
2515 }
2516 cpu->Reg[15] += cpu->GetInstructionSize();
2517 INC_PC(sizeof(rsc_inst));
2518 FETCH_INST;
2519 GOTO_NEXT_INST;
2520 }
2521
2522 SADD8_INST:
2523 SSUB8_INST:
2524 SADD16_INST:
2525 SADDSUBX_INST:
2526 SSUBADDX_INST:
2527 SSUB16_INST:
2528 {
2529 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2530 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2531 const u8 op2 = inst_cream->op2;
2532
2533 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
2534 const s16 rn_lo = (RN & 0xFFFF);
2535 const s16 rn_hi = ((RN >> 16) & 0xFFFF);
2536 const s16 rm_lo = (RM & 0xFFFF);
2537 const s16 rm_hi = ((RM >> 16) & 0xFFFF);
2538
2539 s32 lo_result = 0;
2540 s32 hi_result = 0;
2541
2542 // SADD16
2543 if (inst_cream->op2 == 0x00) {
2544 lo_result = (rn_lo + rm_lo);
2545 hi_result = (rn_hi + rm_hi);
2546 }
2547 // SASX
2548 else if (op2 == 0x01) {
2549 lo_result = (rn_lo - rm_hi);
2550 hi_result = (rn_hi + rm_lo);
2551 }
2552 // SSAX
2553 else if (op2 == 0x02) {
2554 lo_result = (rn_lo + rm_hi);
2555 hi_result = (rn_hi - rm_lo);
2556 }
2557 // SSUB16
2558 else if (op2 == 0x03) {
2559 lo_result = (rn_lo - rm_lo);
2560 hi_result = (rn_hi - rm_hi);
2561 }
2562 2934
2563 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); 2935 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
2564 2936
2565 if (lo_result >= 0) { 2937 if (lo_result >= 0) {
2566 cpu->Cpsr |= (1 << 16); 2938 cpu->Cpsr |= (1 << 16);
2567 cpu->Cpsr |= (1 << 17); 2939 cpu->Cpsr |= (1 << 17);
2568 } else { 2940 } else {
2569 cpu->Cpsr &= ~(1 << 16); 2941 cpu->Cpsr &= ~(1 << 16);
2570 cpu->Cpsr &= ~(1 << 17); 2942 cpu->Cpsr &= ~(1 << 17);
2571 } 2943 }
2572 2944
2573 if (hi_result >= 0) { 2945 if (hi_result >= 0) {
2574 cpu->Cpsr |= (1 << 18); 2946 cpu->Cpsr |= (1 << 18);
2575 cpu->Cpsr |= (1 << 19); 2947 cpu->Cpsr |= (1 << 19);
2576 } else { 2948 } else {
2577 cpu->Cpsr &= ~(1 << 18); 2949 cpu->Cpsr &= ~(1 << 18);
2578 cpu->Cpsr &= ~(1 << 19); 2950 cpu->Cpsr &= ~(1 << 19);
2579 } 2951 }
2952 } else if (op2 == 0x04 || op2 == 0x07) {
2953 s32 lo_val1, lo_val2;
2954 s32 hi_val1, hi_val2;
2955
2956 // SADD8
2957 if (op2 == 0x04) {
2958 lo_val1 = (s32)(s8)(RN & 0xFF) + (s32)(s8)(RM & 0xFF);
2959 lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) + (s32)(s8)((RM >> 8) & 0xFF);
2960 hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) + (s32)(s8)((RM >> 16) & 0xFF);
2961 hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) + (s32)(s8)((RM >> 24) & 0xFF);
2962 }
2963 // SSUB8
2964 else {
2965 lo_val1 = (s32)(s8)(RN & 0xFF) - (s32)(s8)(RM & 0xFF);
2966 lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) - (s32)(s8)((RM >> 8) & 0xFF);
2967 hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) - (s32)(s8)((RM >> 16) & 0xFF);
2968 hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) - (s32)(s8)((RM >> 24) & 0xFF);
2580 } 2969 }
2581 else if (op2 == 0x04 || op2 == 0x07) {
2582 s32 lo_val1, lo_val2;
2583 s32 hi_val1, hi_val2;
2584
2585 // SADD8
2586 if (op2 == 0x04) {
2587 lo_val1 = (s32)(s8)(RN & 0xFF) + (s32)(s8)(RM & 0xFF);
2588 lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) + (s32)(s8)((RM >> 8) & 0xFF);
2589 hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) + (s32)(s8)((RM >> 16) & 0xFF);
2590 hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) + (s32)(s8)((RM >> 24) & 0xFF);
2591 }
2592 // SSUB8
2593 else {
2594 lo_val1 = (s32)(s8)(RN & 0xFF) - (s32)(s8)(RM & 0xFF);
2595 lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) - (s32)(s8)((RM >> 8) & 0xFF);
2596 hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) - (s32)(s8)((RM >> 16) & 0xFF);
2597 hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) - (s32)(s8)((RM >> 24) & 0xFF);
2598 }
2599 2970
2600 RD = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24)); 2971 RD = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) |
2972 ((hi_val2 & 0xFF) << 24));
2601 2973
2602 if (lo_val1 >= 0) 2974 if (lo_val1 >= 0)
2603 cpu->Cpsr |= (1 << 16); 2975 cpu->Cpsr |= (1 << 16);
2604 else 2976 else
2605 cpu->Cpsr &= ~(1 << 16); 2977 cpu->Cpsr &= ~(1 << 16);
2606 2978
2607 if (lo_val2 >= 0) 2979 if (lo_val2 >= 0)
2608 cpu->Cpsr |= (1 << 17); 2980 cpu->Cpsr |= (1 << 17);
2609 else 2981 else
2610 cpu->Cpsr &= ~(1 << 17); 2982 cpu->Cpsr &= ~(1 << 17);
2611 2983
2612 if (hi_val1 >= 0) 2984 if (hi_val1 >= 0)
2613 cpu->Cpsr |= (1 << 18); 2985 cpu->Cpsr |= (1 << 18);
2614 else 2986 else
2615 cpu->Cpsr &= ~(1 << 18); 2987 cpu->Cpsr &= ~(1 << 18);
2616 2988
2617 if (hi_val2 >= 0) 2989 if (hi_val2 >= 0)
2618 cpu->Cpsr |= (1 << 19); 2990 cpu->Cpsr |= (1 << 19);
2619 else 2991 else
2620 cpu->Cpsr &= ~(1 << 19); 2992 cpu->Cpsr &= ~(1 << 19);
2621 }
2622 } 2993 }
2623
2624 cpu->Reg[15] += cpu->GetInstructionSize();
2625 INC_PC(sizeof(generic_arm_inst));
2626 FETCH_INST;
2627 GOTO_NEXT_INST;
2628 } 2994 }
2629 2995
2630 SBC_INST: 2996 cpu->Reg[15] += cpu->GetInstructionSize();
2631 { 2997 INC_PC(sizeof(generic_arm_inst));
2632 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2998 FETCH_INST;
2633 sbc_inst* const inst_cream = (sbc_inst*)inst_base->component; 2999 GOTO_NEXT_INST;
3000}
2634 3001
2635 u32 rn_val = RN; 3002SBC_INST : {
2636 if (inst_cream->Rn == 15) 3003 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2637 rn_val += 2 * cpu->GetInstructionSize(); 3004 sbc_inst* const inst_cream = (sbc_inst*)inst_base->component;
2638 3005
2639 bool carry; 3006 u32 rn_val = RN;
2640 bool overflow; 3007 if (inst_cream->Rn == 15)
2641 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); 3008 rn_val += 2 * cpu->GetInstructionSize();
2642 3009
2643 if (inst_cream->S && (inst_cream->Rd == 15)) { 3010 bool carry;
2644 if (CurrentModeHasSPSR) { 3011 bool overflow;
2645 cpu->Cpsr = cpu->Spsr_copy; 3012 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
2646 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 3013
2647 LOAD_NZCVT; 3014 if (inst_cream->S && (inst_cream->Rd == 15)) {
2648 } 3015 if (CurrentModeHasSPSR) {
2649 } else if (inst_cream->S) { 3016 cpu->Cpsr = cpu->Spsr_copy;
2650 UPDATE_NFLAG(RD); 3017 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2651 UPDATE_ZFLAG(RD); 3018 LOAD_NZCVT;
2652 cpu->CFlag = carry;
2653 cpu->VFlag = overflow;
2654 }
2655 if (inst_cream->Rd == 15) {
2656 INC_PC(sizeof(sbc_inst));
2657 goto DISPATCH;
2658 } 3019 }
3020 } else if (inst_cream->S) {
3021 UPDATE_NFLAG(RD);
3022 UPDATE_ZFLAG(RD);
3023 cpu->CFlag = carry;
3024 cpu->VFlag = overflow;
3025 }
3026 if (inst_cream->Rd == 15) {
3027 INC_PC(sizeof(sbc_inst));
3028 goto DISPATCH;
2659 } 3029 }
2660 cpu->Reg[15] += cpu->GetInstructionSize();
2661 INC_PC(sizeof(sbc_inst));
2662 FETCH_INST;
2663 GOTO_NEXT_INST;
2664 } 3030 }
3031 cpu->Reg[15] += cpu->GetInstructionSize();
3032 INC_PC(sizeof(sbc_inst));
3033 FETCH_INST;
3034 GOTO_NEXT_INST;
3035}
2665 3036
2666 SEL_INST: 3037SEL_INST : {
2667 { 3038 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2668 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3039 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2669 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2670
2671 const u32 to = RM;
2672 const u32 from = RN;
2673 const u32 cpsr = cpu->Cpsr;
2674 3040
2675 u32 result; 3041 const u32 to = RM;
2676 if (cpsr & (1 << 16)) 3042 const u32 from = RN;
2677 result = from & 0xff; 3043 const u32 cpsr = cpu->Cpsr;
2678 else
2679 result = to & 0xff;
2680 3044
2681 if (cpsr & (1 << 17)) 3045 u32 result;
2682 result |= from & 0x0000ff00; 3046 if (cpsr & (1 << 16))
2683 else 3047 result = from & 0xff;
2684 result |= to & 0x0000ff00; 3048 else
3049 result = to & 0xff;
2685 3050
2686 if (cpsr & (1 << 18)) 3051 if (cpsr & (1 << 17))
2687 result |= from & 0x00ff0000; 3052 result |= from & 0x0000ff00;
2688 else 3053 else
2689 result |= to & 0x00ff0000; 3054 result |= to & 0x0000ff00;
2690 3055
2691 if (cpsr & (1 << 19)) 3056 if (cpsr & (1 << 18))
2692 result |= from & 0xff000000; 3057 result |= from & 0x00ff0000;
2693 else 3058 else
2694 result |= to & 0xff000000; 3059 result |= to & 0x00ff0000;
2695 3060
2696 RD = result; 3061 if (cpsr & (1 << 19))
2697 } 3062 result |= from & 0xff000000;
3063 else
3064 result |= to & 0xff000000;
2698 3065
2699 cpu->Reg[15] += cpu->GetInstructionSize(); 3066 RD = result;
2700 INC_PC(sizeof(generic_arm_inst));
2701 FETCH_INST;
2702 GOTO_NEXT_INST;
2703 } 3067 }
2704 3068
2705 SETEND_INST: 3069 cpu->Reg[15] += cpu->GetInstructionSize();
2706 { 3070 INC_PC(sizeof(generic_arm_inst));
2707 // SETEND is unconditional 3071 FETCH_INST;
2708 setend_inst* const inst_cream = (setend_inst*)inst_base->component; 3072 GOTO_NEXT_INST;
2709 const bool big_endian = (inst_cream->set_bigend == 1); 3073}
2710 3074
2711 if (big_endian) 3075SETEND_INST : {
2712 cpu->Cpsr |= (1 << 9); 3076 // SETEND is unconditional
2713 else 3077 setend_inst* const inst_cream = (setend_inst*)inst_base->component;
2714 cpu->Cpsr &= ~(1 << 9); 3078 const bool big_endian = (inst_cream->set_bigend == 1);
2715 3079
2716 LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE"); 3080 if (big_endian)
3081 cpu->Cpsr |= (1 << 9);
3082 else
3083 cpu->Cpsr &= ~(1 << 9);
2717 3084
2718 cpu->Reg[15] += cpu->GetInstructionSize(); 3085 LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE");
2719 INC_PC(sizeof(setend_inst));
2720 FETCH_INST;
2721 GOTO_NEXT_INST;
2722 }
2723 3086
2724 SEV_INST: 3087 cpu->Reg[15] += cpu->GetInstructionSize();
2725 { 3088 INC_PC(sizeof(setend_inst));
2726 // Stubbed, as SEV is a hint instruction. 3089 FETCH_INST;
2727 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3090 GOTO_NEXT_INST;
2728 LOG_TRACE(Core_ARM11, "SEV executed."); 3091}
2729 }
2730 3092
2731 cpu->Reg[15] += cpu->GetInstructionSize(); 3093SEV_INST : {
2732 INC_PC_STUB; 3094 // Stubbed, as SEV is a hint instruction.
2733 FETCH_INST; 3095 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2734 GOTO_NEXT_INST; 3096 LOG_TRACE(Core_ARM11, "SEV executed.");
2735 } 3097 }
2736 3098
2737 SHADD8_INST: 3099 cpu->Reg[15] += cpu->GetInstructionSize();
2738 SHADD16_INST: 3100 INC_PC_STUB;
2739 SHADDSUBX_INST: 3101 FETCH_INST;
2740 SHSUB8_INST: 3102 GOTO_NEXT_INST;
2741 SHSUB16_INST: 3103}
2742 SHSUBADDX_INST:
2743 {
2744 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2745 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2746 3104
2747 const u8 op2 = inst_cream->op2; 3105SHADD8_INST:
2748 const u32 rm_val = RM; 3106SHADD16_INST:
2749 const u32 rn_val = RN; 3107SHADDSUBX_INST:
3108SHSUB8_INST:
3109SHSUB16_INST:
3110SHSUBADDX_INST : {
3111 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3112 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2750 3113
2751 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) { 3114 const u8 op2 = inst_cream->op2;
2752 s32 lo_result = 0; 3115 const u32 rm_val = RM;
2753 s32 hi_result = 0; 3116 const u32 rn_val = RN;
2754 3117
2755 // SHADD16 3118 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
2756 if (op2 == 0x00) { 3119 s32 lo_result = 0;
2757 lo_result = ((s16)(rn_val & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1; 3120 s32 hi_result = 0;
2758 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
2759 }
2760 // SHASX
2761 else if (op2 == 0x01) {
2762 lo_result = ((s16)(rn_val & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
2763 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1;
2764 }
2765 // SHSAX
2766 else if (op2 == 0x02) {
2767 lo_result = ((s16)(rn_val & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
2768 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
2769 }
2770 // SHSUB16
2771 else if (op2 == 0x03) {
2772 lo_result = ((s16)(rn_val & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
2773 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
2774 }
2775 3121
2776 RD = ((lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16)); 3122 // SHADD16
3123 if (op2 == 0x00) {
3124 lo_result = ((s16)(rn_val & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1;
3125 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3126 }
3127 // SHASX
3128 else if (op2 == 0x01) {
3129 lo_result = ((s16)(rn_val & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3130 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1;
3131 }
3132 // SHSAX
3133 else if (op2 == 0x02) {
3134 lo_result = ((s16)(rn_val & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3135 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
3136 }
3137 // SHSUB16
3138 else if (op2 == 0x03) {
3139 lo_result = ((s16)(rn_val & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
3140 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
2777 } 3141 }
2778 else if (op2 == 0x04 || op2 == 0x07) {
2779 s16 lo_val1, lo_val2;
2780 s16 hi_val1, hi_val2;
2781 3142
2782 // SHADD8 3143 RD = ((lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16));
2783 if (op2 == 0x04) { 3144 } else if (op2 == 0x04 || op2 == 0x07) {
2784 lo_val1 = ((s8)(rn_val & 0xFF) + (s8)(rm_val & 0xFF)) >> 1; 3145 s16 lo_val1, lo_val2;
2785 lo_val2 = ((s8)((rn_val >> 8) & 0xFF) + (s8)((rm_val >> 8) & 0xFF)) >> 1; 3146 s16 hi_val1, hi_val2;
2786 3147
2787 hi_val1 = ((s8)((rn_val >> 16) & 0xFF) + (s8)((rm_val >> 16) & 0xFF)) >> 1; 3148 // SHADD8
2788 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) + (s8)((rm_val >> 24) & 0xFF)) >> 1; 3149 if (op2 == 0x04) {
2789 } 3150 lo_val1 = ((s8)(rn_val & 0xFF) + (s8)(rm_val & 0xFF)) >> 1;
2790 // SHSUB8 3151 lo_val2 = ((s8)((rn_val >> 8) & 0xFF) + (s8)((rm_val >> 8) & 0xFF)) >> 1;
2791 else {
2792 lo_val1 = ((s8)(rn_val & 0xFF) - (s8)(rm_val & 0xFF)) >> 1;
2793 lo_val2 = ((s8)((rn_val >> 8) & 0xFF) - (s8)((rm_val >> 8) & 0xFF)) >> 1;
2794 3152
2795 hi_val1 = ((s8)((rn_val >> 16) & 0xFF) - (s8)((rm_val >> 16) & 0xFF)) >> 1; 3153 hi_val1 = ((s8)((rn_val >> 16) & 0xFF) + (s8)((rm_val >> 16) & 0xFF)) >> 1;
2796 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) - (s8)((rm_val >> 24) & 0xFF)) >> 1; 3154 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) + (s8)((rm_val >> 24) & 0xFF)) >> 1;
2797 }
2798
2799 RD = (lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24);
2800 } 3155 }
2801 } 3156 // SHSUB8
2802 3157 else {
2803 cpu->Reg[15] += cpu->GetInstructionSize(); 3158 lo_val1 = ((s8)(rn_val & 0xFF) - (s8)(rm_val & 0xFF)) >> 1;
2804 INC_PC(sizeof(generic_arm_inst)); 3159 lo_val2 = ((s8)((rn_val >> 8) & 0xFF) - (s8)((rm_val >> 8) & 0xFF)) >> 1;
2805 FETCH_INST;
2806 GOTO_NEXT_INST;
2807 }
2808
2809 SMLA_INST:
2810 {
2811 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2812 smla_inst* inst_cream = (smla_inst*)inst_base->component;
2813 s32 operand1, operand2;
2814 if (inst_cream->x == 0)
2815 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
2816 else
2817 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
2818 3160
2819 if (inst_cream->y == 0) 3161 hi_val1 = ((s8)((rn_val >> 16) & 0xFF) - (s8)((rm_val >> 16) & 0xFF)) >> 1;
2820 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15); 3162 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) - (s8)((rm_val >> 24) & 0xFF)) >> 1;
2821 else 3163 }
2822 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
2823 3164
2824 u32 product = operand1 * operand2; 3165 RD = (lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) |
2825 u32 result = product + RN; 3166 ((hi_val2 & 0xFF) << 24);
2826 if (AddOverflow(product, RN, result))
2827 cpu->Cpsr |= (1 << 27);
2828 RD = result;
2829 } 3167 }
2830 cpu->Reg[15] += cpu->GetInstructionSize();
2831 INC_PC(sizeof(smla_inst));
2832 FETCH_INST;
2833 GOTO_NEXT_INST;
2834 } 3168 }
2835 3169
2836 SMLAD_INST: 3170 cpu->Reg[15] += cpu->GetInstructionSize();
2837 SMLSD_INST: 3171 INC_PC(sizeof(generic_arm_inst));
2838 SMUAD_INST: 3172 FETCH_INST;
2839 SMUSD_INST: 3173 GOTO_NEXT_INST;
2840 { 3174}
2841 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2842 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
2843 const u8 op2 = inst_cream->op2;
2844 3175
2845 u32 rm_val = cpu->Reg[inst_cream->Rm]; 3176SMLA_INST : {
2846 const u32 rn_val = cpu->Reg[inst_cream->Rn]; 3177 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3178 smla_inst* inst_cream = (smla_inst*)inst_base->component;
3179 s32 operand1, operand2;
3180 if (inst_cream->x == 0)
3181 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
3182 else
3183 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
2847 3184
2848 if (inst_cream->m) 3185 if (inst_cream->y == 0)
2849 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); 3186 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
3187 else
3188 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
3189
3190 u32 product = operand1 * operand2;
3191 u32 result = product + RN;
3192 if (AddOverflow(product, RN, result))
3193 cpu->Cpsr |= (1 << 27);
3194 RD = result;
3195 }
3196 cpu->Reg[15] += cpu->GetInstructionSize();
3197 INC_PC(sizeof(smla_inst));
3198 FETCH_INST;
3199 GOTO_NEXT_INST;
3200}
2850 3201
2851 const s16 rm_lo = (rm_val & 0xFFFF); 3202SMLAD_INST:
2852 const s16 rm_hi = ((rm_val >> 16) & 0xFFFF); 3203SMLSD_INST:
2853 const s16 rn_lo = (rn_val & 0xFFFF); 3204SMUAD_INST:
2854 const s16 rn_hi = ((rn_val >> 16) & 0xFFFF); 3205SMUSD_INST : {
3206 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3207 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3208 const u8 op2 = inst_cream->op2;
2855 3209
2856 const u32 product1 = (rn_lo * rm_lo); 3210 u32 rm_val = cpu->Reg[inst_cream->Rm];
2857 const u32 product2 = (rn_hi * rm_hi); 3211 const u32 rn_val = cpu->Reg[inst_cream->Rn];
2858 3212
2859 // SMUAD and SMLAD 3213 if (inst_cream->m)
2860 if (BIT(op2, 1) == 0) { 3214 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
2861 u32 rd_val = (product1 + product2);
2862 3215
2863 if (inst_cream->Ra != 15) { 3216 const s16 rm_lo = (rm_val & 0xFFFF);
2864 rd_val += cpu->Reg[inst_cream->Ra]; 3217 const s16 rm_hi = ((rm_val >> 16) & 0xFFFF);
3218 const s16 rn_lo = (rn_val & 0xFFFF);
3219 const s16 rn_hi = ((rn_val >> 16) & 0xFFFF);
2865 3220
2866 if (ARMul_AddOverflowQ(product1 + product2, cpu->Reg[inst_cream->Ra])) 3221 const u32 product1 = (rn_lo * rm_lo);
2867 cpu->Cpsr |= (1 << 27); 3222 const u32 product2 = (rn_hi * rm_hi);
2868 } 3223
3224 // SMUAD and SMLAD
3225 if (BIT(op2, 1) == 0) {
3226 u32 rd_val = (product1 + product2);
2869 3227
2870 RD = rd_val; 3228 if (inst_cream->Ra != 15) {
3229 rd_val += cpu->Reg[inst_cream->Ra];
2871 3230
2872 if (ARMul_AddOverflowQ(product1, product2)) 3231 if (ARMul_AddOverflowQ(product1 + product2, cpu->Reg[inst_cream->Ra]))
2873 cpu->Cpsr |= (1 << 27); 3232 cpu->Cpsr |= (1 << 27);
2874 } 3233 }
2875 // SMUSD and SMLSD
2876 else {
2877 u32 rd_val = (product1 - product2);
2878 3234
2879 if (inst_cream->Ra != 15) { 3235 RD = rd_val;
2880 rd_val += cpu->Reg[inst_cream->Ra];
2881 3236
2882 if (ARMul_AddOverflowQ(product1 - product2, cpu->Reg[inst_cream->Ra])) 3237 if (ARMul_AddOverflowQ(product1, product2))
2883 cpu->Cpsr |= (1 << 27); 3238 cpu->Cpsr |= (1 << 27);
2884 } 3239 }
3240 // SMUSD and SMLSD
3241 else {
3242 u32 rd_val = (product1 - product2);
3243
3244 if (inst_cream->Ra != 15) {
3245 rd_val += cpu->Reg[inst_cream->Ra];
2885 3246
2886 RD = rd_val; 3247 if (ARMul_AddOverflowQ(product1 - product2, cpu->Reg[inst_cream->Ra]))
3248 cpu->Cpsr |= (1 << 27);
2887 } 3249 }
2888 }
2889 3250
2890 cpu->Reg[15] += cpu->GetInstructionSize(); 3251 RD = rd_val;
2891 INC_PC(sizeof(smlad_inst)); 3252 }
2892 FETCH_INST;
2893 GOTO_NEXT_INST;
2894 } 3253 }
2895 3254
2896 SMLAL_INST: 3255 cpu->Reg[15] += cpu->GetInstructionSize();
2897 { 3256 INC_PC(sizeof(smlad_inst));
2898 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3257 FETCH_INST;
2899 umlal_inst* inst_cream = (umlal_inst*)inst_base->component; 3258 GOTO_NEXT_INST;
2900 long long int rm = RM; 3259}
2901 long long int rs = RS; 3260
2902 if (BIT(rm, 31)) { 3261SMLAL_INST : {
2903 rm |= 0xffffffff00000000LL; 3262 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2904 } 3263 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
2905 if (BIT(rs, 31)) { 3264 long long int rm = RM;
2906 rs |= 0xffffffff00000000LL; 3265 long long int rs = RS;
2907 } 3266 if (BIT(rm, 31)) {
2908 long long int rst = rm * rs; 3267 rm |= 0xffffffff00000000LL;
2909 long long int rdhi32 = RDHI;
2910 long long int hilo = (rdhi32 << 32) + RDLO;
2911 rst += hilo;
2912 RDLO = BITS(rst, 0, 31);
2913 RDHI = BITS(rst, 32, 63);
2914 if (inst_cream->S) {
2915 cpu->NFlag = BIT(RDHI, 31);
2916 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
2917 }
2918 } 3268 }
2919 cpu->Reg[15] += cpu->GetInstructionSize(); 3269 if (BIT(rs, 31)) {
2920 INC_PC(sizeof(umlal_inst)); 3270 rs |= 0xffffffff00000000LL;
2921 FETCH_INST; 3271 }
2922 GOTO_NEXT_INST; 3272 long long int rst = rm * rs;
2923 } 3273 long long int rdhi32 = RDHI;
2924 3274 long long int hilo = (rdhi32 << 32) + RDLO;
2925 SMLALXY_INST: 3275 rst += hilo;
2926 { 3276 RDLO = BITS(rst, 0, 31);
2927 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3277 RDHI = BITS(rst, 32, 63);
2928 smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component; 3278 if (inst_cream->S) {
2929 3279 cpu->NFlag = BIT(RDHI, 31);
2930 u64 operand1 = RN; 3280 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
2931 u64 operand2 = RM;
2932
2933 if (inst_cream->x != 0)
2934 operand1 >>= 16;
2935 if (inst_cream->y != 0)
2936 operand2 >>= 16;
2937 operand1 &= 0xFFFF;
2938 if (operand1 & 0x8000)
2939 operand1 -= 65536;
2940 operand2 &= 0xFFFF;
2941 if (operand2 & 0x8000)
2942 operand2 -= 65536;
2943
2944 u64 dest = ((u64)RDHI << 32 | RDLO) + (operand1 * operand2);
2945 RDLO = (dest & 0xFFFFFFFF);
2946 RDHI = ((dest >> 32) & 0xFFFFFFFF);
2947 } 3281 }
2948
2949 cpu->Reg[15] += cpu->GetInstructionSize();
2950 INC_PC(sizeof(smlalxy_inst));
2951 FETCH_INST;
2952 GOTO_NEXT_INST;
2953 } 3282 }
3283 cpu->Reg[15] += cpu->GetInstructionSize();
3284 INC_PC(sizeof(umlal_inst));
3285 FETCH_INST;
3286 GOTO_NEXT_INST;
3287}
2954 3288
2955 SMLAW_INST: 3289SMLALXY_INST : {
2956 { 3290 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2957 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3291 smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component;
2958 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; 3292
3293 u64 operand1 = RN;
3294 u64 operand2 = RM;
3295
3296 if (inst_cream->x != 0)
3297 operand1 >>= 16;
3298 if (inst_cream->y != 0)
3299 operand2 >>= 16;
3300 operand1 &= 0xFFFF;
3301 if (operand1 & 0x8000)
3302 operand1 -= 65536;
3303 operand2 &= 0xFFFF;
3304 if (operand2 & 0x8000)
3305 operand2 -= 65536;
3306
3307 u64 dest = ((u64)RDHI << 32 | RDLO) + (operand1 * operand2);
3308 RDLO = (dest & 0xFFFFFFFF);
3309 RDHI = ((dest >> 32) & 0xFFFFFFFF);
3310 }
3311
3312 cpu->Reg[15] += cpu->GetInstructionSize();
3313 INC_PC(sizeof(smlalxy_inst));
3314 FETCH_INST;
3315 GOTO_NEXT_INST;
3316}
2959 3317
2960 const u32 rm_val = RM; 3318SMLAW_INST : {
2961 const u32 rn_val = RN; 3319 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2962 const u32 ra_val = cpu->Reg[inst_cream->Ra]; 3320 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
2963 const bool high = (inst_cream->m == 1);
2964 3321
2965 const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF); 3322 const u32 rm_val = RM;
2966 const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16); 3323 const u32 rn_val = RN;
3324 const u32 ra_val = cpu->Reg[inst_cream->Ra];
3325 const bool high = (inst_cream->m == 1);
2967 3326
2968 RD = BITS(result, 16, 47); 3327 const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF);
3328 const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16);
2969 3329
2970 if ((result >> 16) != (s32)RD) 3330 RD = BITS(result, 16, 47);
2971 cpu->Cpsr |= (1 << 27);
2972 }
2973 3331
2974 cpu->Reg[15] += cpu->GetInstructionSize(); 3332 if ((result >> 16) != (s32)RD)
2975 INC_PC(sizeof(smlad_inst)); 3333 cpu->Cpsr |= (1 << 27);
2976 FETCH_INST;
2977 GOTO_NEXT_INST;
2978 } 3334 }
2979 3335
2980 SMLALD_INST: 3336 cpu->Reg[15] += cpu->GetInstructionSize();
2981 SMLSLD_INST: 3337 INC_PC(sizeof(smlad_inst));
2982 { 3338 FETCH_INST;
2983 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3339 GOTO_NEXT_INST;
2984 smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; 3340}
2985 3341
2986 const bool do_swap = (inst_cream->swap == 1); 3342SMLALD_INST:
2987 const u32 rdlo_val = RDLO; 3343SMLSLD_INST : {
2988 const u32 rdhi_val = RDHI; 3344 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2989 const u32 rn_val = RN; 3345 smlald_inst* const inst_cream = (smlald_inst*)inst_base->component;
2990 u32 rm_val = RM;
2991 3346
2992 if (do_swap) 3347 const bool do_swap = (inst_cream->swap == 1);
2993 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); 3348 const u32 rdlo_val = RDLO;
3349 const u32 rdhi_val = RDHI;
3350 const u32 rn_val = RN;
3351 u32 rm_val = RM;
2994 3352
2995 const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF); 3353 if (do_swap)
2996 const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF); 3354 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
2997 s64 result;
2998 3355
2999 // SMLALD 3356 const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF);
3000 if (BIT(inst_cream->op2, 1) == 0) { 3357 const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF);
3001 result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); 3358 s64 result;
3002 }
3003 // SMLSLD
3004 else {
3005 result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
3006 }
3007 3359
3008 RDLO = (result & 0xFFFFFFFF); 3360 // SMLALD
3009 RDHI = ((result >> 32) & 0xFFFFFFFF); 3361 if (BIT(inst_cream->op2, 1) == 0) {
3362 result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
3363 }
3364 // SMLSLD
3365 else {
3366 result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
3010 } 3367 }
3011 3368
3012 cpu->Reg[15] += cpu->GetInstructionSize(); 3369 RDLO = (result & 0xFFFFFFFF);
3013 INC_PC(sizeof(smlald_inst)); 3370 RDHI = ((result >> 32) & 0xFFFFFFFF);
3014 FETCH_INST;
3015 GOTO_NEXT_INST;
3016 } 3371 }
3017 3372
3018 SMMLA_INST: 3373 cpu->Reg[15] += cpu->GetInstructionSize();
3019 SMMLS_INST: 3374 INC_PC(sizeof(smlald_inst));
3020 SMMUL_INST: 3375 FETCH_INST;
3021 { 3376 GOTO_NEXT_INST;
3022 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3377}
3023 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3024
3025 const u32 rm_val = RM;
3026 const u32 rn_val = RN;
3027 const bool do_round = (inst_cream->m == 1);
3028 3378
3029 // Assume SMMUL by default. 3379SMMLA_INST:
3030 s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val; 3380SMMLS_INST:
3381SMMUL_INST : {
3382 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3383 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3031 3384
3032 if (inst_cream->Ra != 15) { 3385 const u32 rm_val = RM;
3033 const u32 ra_val = cpu->Reg[inst_cream->Ra]; 3386 const u32 rn_val = RN;
3387 const bool do_round = (inst_cream->m == 1);
3034 3388
3035 // SMMLA, otherwise SMMLS 3389 // Assume SMMUL by default.
3036 if (BIT(inst_cream->op2, 1) == 0) 3390 s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val;
3037 result += ((s64)ra_val << 32);
3038 else
3039 result = ((s64)ra_val << 32) - result;
3040 }
3041 3391
3042 if (do_round) 3392 if (inst_cream->Ra != 15) {
3043 result += 0x80000000; 3393 const u32 ra_val = cpu->Reg[inst_cream->Ra];
3044 3394
3045 RD = ((result >> 32) & 0xFFFFFFFF); 3395 // SMMLA, otherwise SMMLS
3396 if (BIT(inst_cream->op2, 1) == 0)
3397 result += ((s64)ra_val << 32);
3398 else
3399 result = ((s64)ra_val << 32) - result;
3046 } 3400 }
3047 3401
3048 cpu->Reg[15] += cpu->GetInstructionSize(); 3402 if (do_round)
3049 INC_PC(sizeof(smlad_inst)); 3403 result += 0x80000000;
3050 FETCH_INST; 3404
3051 GOTO_NEXT_INST; 3405 RD = ((result >> 32) & 0xFFFFFFFF);
3052 } 3406 }
3053 3407
3054 SMUL_INST: 3408 cpu->Reg[15] += cpu->GetInstructionSize();
3055 { 3409 INC_PC(sizeof(smlad_inst));
3056 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3410 FETCH_INST;
3057 smul_inst* inst_cream = (smul_inst*)inst_base->component; 3411 GOTO_NEXT_INST;
3058 u32 operand1, operand2; 3412}
3059 if (inst_cream->x == 0)
3060 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
3061 else
3062 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
3063 3413
3064 if (inst_cream->y == 0) 3414SMUL_INST : {
3065 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15); 3415 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3066 else 3416 smul_inst* inst_cream = (smul_inst*)inst_base->component;
3067 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); 3417 u32 operand1, operand2;
3068 RD = operand1 * operand2; 3418 if (inst_cream->x == 0)
3419 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
3420 else
3421 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
3422
3423 if (inst_cream->y == 0)
3424 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
3425 else
3426 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
3427 RD = operand1 * operand2;
3428 }
3429 cpu->Reg[15] += cpu->GetInstructionSize();
3430 INC_PC(sizeof(smul_inst));
3431 FETCH_INST;
3432 GOTO_NEXT_INST;
3433}
3434SMULL_INST : {
3435 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3436 umull_inst* inst_cream = (umull_inst*)inst_base->component;
3437 s64 rm = RM;
3438 s64 rs = RS;
3439 if (BIT(rm, 31)) {
3440 rm |= 0xffffffff00000000LL;
3069 } 3441 }
3070 cpu->Reg[15] += cpu->GetInstructionSize(); 3442 if (BIT(rs, 31)) {
3071 INC_PC(sizeof(smul_inst)); 3443 rs |= 0xffffffff00000000LL;
3072 FETCH_INST; 3444 }
3073 GOTO_NEXT_INST; 3445 s64 rst = rm * rs;
3074 } 3446 RDHI = BITS(rst, 32, 63);
3075 SMULL_INST: 3447 RDLO = BITS(rst, 0, 31);
3076 {
3077 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3078 umull_inst* inst_cream = (umull_inst*)inst_base->component;
3079 s64 rm = RM;
3080 s64 rs = RS;
3081 if (BIT(rm, 31)) {
3082 rm |= 0xffffffff00000000LL;
3083 }
3084 if (BIT(rs, 31)) {
3085 rs |= 0xffffffff00000000LL;
3086 }
3087 s64 rst = rm * rs;
3088 RDHI = BITS(rst, 32, 63);
3089 RDLO = BITS(rst, 0, 31);
3090 3448
3091 if (inst_cream->S) { 3449 if (inst_cream->S) {
3092 cpu->NFlag = BIT(RDHI, 31); 3450 cpu->NFlag = BIT(RDHI, 31);
3093 cpu->ZFlag = (RDHI == 0 && RDLO == 0); 3451 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
3094 }
3095 } 3452 }
3096 cpu->Reg[15] += cpu->GetInstructionSize();
3097 INC_PC(sizeof(umull_inst));
3098 FETCH_INST;
3099 GOTO_NEXT_INST;
3100 } 3453 }
3454 cpu->Reg[15] += cpu->GetInstructionSize();
3455 INC_PC(sizeof(umull_inst));
3456 FETCH_INST;
3457 GOTO_NEXT_INST;
3458}
3101 3459
3102 SMULW_INST: 3460SMULW_INST : {
3103 { 3461 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3104 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3462 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3105 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3106 3463
3107 s16 rm = (inst_cream->m == 1) ? ((RM >> 16) & 0xFFFF) : (RM & 0xFFFF); 3464 s16 rm = (inst_cream->m == 1) ? ((RM >> 16) & 0xFFFF) : (RM & 0xFFFF);
3108 3465
3109 s64 result = (s64)rm * (s64)(s32)RN; 3466 s64 result = (s64)rm * (s64)(s32)RN;
3110 RD = BITS(result, 16, 47); 3467 RD = BITS(result, 16, 47);
3111 }
3112 cpu->Reg[15] += cpu->GetInstructionSize();
3113 INC_PC(sizeof(smlad_inst));
3114 FETCH_INST;
3115 GOTO_NEXT_INST;
3116 } 3468 }
3469 cpu->Reg[15] += cpu->GetInstructionSize();
3470 INC_PC(sizeof(smlad_inst));
3471 FETCH_INST;
3472 GOTO_NEXT_INST;
3473}
3117 3474
3118 SRS_INST: 3475SRS_INST : {
3119 { 3476 // SRS is unconditional
3120 // SRS is unconditional 3477 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
3121 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
3122 3478
3123 u32 address = 0; 3479 u32 address = 0;
3124 inst_cream->get_addr(cpu, inst_cream->inst, address); 3480 inst_cream->get_addr(cpu, inst_cream->inst, address);
3125 3481
3126 cpu->WriteMemory32(address + 0, cpu->Reg[14]); 3482 cpu->WriteMemory32(address + 0, cpu->Reg[14]);
3127 cpu->WriteMemory32(address + 4, cpu->Spsr_copy); 3483 cpu->WriteMemory32(address + 4, cpu->Spsr_copy);
3128 3484
3129 cpu->Reg[15] += cpu->GetInstructionSize(); 3485 cpu->Reg[15] += cpu->GetInstructionSize();
3130 INC_PC(sizeof(ldst_inst)); 3486 INC_PC(sizeof(ldst_inst));
3131 FETCH_INST; 3487 FETCH_INST;
3132 GOTO_NEXT_INST; 3488 GOTO_NEXT_INST;
3133 } 3489}
3134
3135 SSAT_INST:
3136 {
3137 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3138 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
3139 3490
3140 u8 shift_type = inst_cream->shift_type; 3491SSAT_INST : {
3141 u8 shift_amount = inst_cream->imm5; 3492 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3142 u32 rn_val = RN; 3493 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
3143 3494
3144 // 32-bit ASR is encoded as an amount of 0. 3495 u8 shift_type = inst_cream->shift_type;
3145 if (shift_type == 1 && shift_amount == 0) 3496 u8 shift_amount = inst_cream->imm5;
3146 shift_amount = 31; 3497 u32 rn_val = RN;
3147 3498
3148 if (shift_type == 0) 3499 // 32-bit ASR is encoded as an amount of 0.
3149 rn_val <<= shift_amount; 3500 if (shift_type == 1 && shift_amount == 0)
3150 else if (shift_type == 1) 3501 shift_amount = 31;
3151 rn_val = ((s32)rn_val >> shift_amount);
3152 3502
3153 bool saturated = false; 3503 if (shift_type == 0)
3154 rn_val = ARMul_SignedSatQ(rn_val, inst_cream->sat_imm, &saturated); 3504 rn_val <<= shift_amount;
3505 else if (shift_type == 1)
3506 rn_val = ((s32)rn_val >> shift_amount);
3155 3507
3156 if (saturated) 3508 bool saturated = false;
3157 cpu->Cpsr |= (1 << 27); 3509 rn_val = ARMul_SignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
3158 3510
3159 RD = rn_val; 3511 if (saturated)
3160 } 3512 cpu->Cpsr |= (1 << 27);
3161 3513
3162 cpu->Reg[15] += cpu->GetInstructionSize(); 3514 RD = rn_val;
3163 INC_PC(sizeof(ssat_inst));
3164 FETCH_INST;
3165 GOTO_NEXT_INST;
3166 } 3515 }
3167 3516
3168 SSAT16_INST: 3517 cpu->Reg[15] += cpu->GetInstructionSize();
3169 { 3518 INC_PC(sizeof(ssat_inst));
3170 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3519 FETCH_INST;
3171 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; 3520 GOTO_NEXT_INST;
3172 const u8 saturate_to = inst_cream->sat_imm; 3521}
3173 3522
3174 bool sat1 = false; 3523SSAT16_INST : {
3175 bool sat2 = false; 3524 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3525 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
3526 const u8 saturate_to = inst_cream->sat_imm;
3176 3527
3177 RD = (ARMul_SignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) | 3528 bool sat1 = false;
3178 ARMul_SignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16; 3529 bool sat2 = false;
3179 3530
3180 if (sat1 || sat2) 3531 RD = (ARMul_SignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) |
3181 cpu->Cpsr |= (1 << 27); 3532 ARMul_SignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16;
3182 }
3183 3533
3184 cpu->Reg[15] += cpu->GetInstructionSize(); 3534 if (sat1 || sat2)
3185 INC_PC(sizeof(ssat_inst)); 3535 cpu->Cpsr |= (1 << 27);
3186 FETCH_INST; 3536 }
3187 GOTO_NEXT_INST;
3188 }
3189
3190 STC_INST:
3191 {
3192 // Instruction not implemented
3193 //LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
3194 cpu->Reg[15] += cpu->GetInstructionSize();
3195 INC_PC(sizeof(stc_inst));
3196 FETCH_INST;
3197 GOTO_NEXT_INST;
3198 }
3199 STM_INST:
3200 {
3201 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3202 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3203 unsigned int inst = inst_cream->inst;
3204
3205 unsigned int Rn = BITS(inst, 16, 19);
3206 unsigned int old_RN = cpu->Reg[Rn];
3207
3208 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3209 if (BIT(inst_cream->inst, 22) == 1) {
3210 for (int i = 0; i < 13; i++) {
3211 if (BIT(inst_cream->inst, i)) {
3212 cpu->WriteMemory32(addr, cpu->Reg[i]);
3213 addr += 4;
3214 }
3215 }
3216 if (BIT(inst_cream->inst, 13)) {
3217 if (cpu->Mode == USER32MODE)
3218 cpu->WriteMemory32(addr, cpu->Reg[13]);
3219 else
3220 cpu->WriteMemory32(addr, cpu->Reg_usr[0]);
3221 3537
3538 cpu->Reg[15] += cpu->GetInstructionSize();
3539 INC_PC(sizeof(ssat_inst));
3540 FETCH_INST;
3541 GOTO_NEXT_INST;
3542}
3543
3544STC_INST : {
3545 // Instruction not implemented
3546 // LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
3547 cpu->Reg[15] += cpu->GetInstructionSize();
3548 INC_PC(sizeof(stc_inst));
3549 FETCH_INST;
3550 GOTO_NEXT_INST;
3551}
3552STM_INST : {
3553 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3554 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3555 unsigned int inst = inst_cream->inst;
3556
3557 unsigned int Rn = BITS(inst, 16, 19);
3558 unsigned int old_RN = cpu->Reg[Rn];
3559
3560 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3561 if (BIT(inst_cream->inst, 22) == 1) {
3562 for (int i = 0; i < 13; i++) {
3563 if (BIT(inst_cream->inst, i)) {
3564 cpu->WriteMemory32(addr, cpu->Reg[i]);
3222 addr += 4; 3565 addr += 4;
3223 } 3566 }
3224 if (BIT(inst_cream->inst, 14)) { 3567 }
3225 if (cpu->Mode == USER32MODE) 3568 if (BIT(inst_cream->inst, 13)) {
3226 cpu->WriteMemory32(addr, cpu->Reg[14]); 3569 if (cpu->Mode == USER32MODE)
3570 cpu->WriteMemory32(addr, cpu->Reg[13]);
3571 else
3572 cpu->WriteMemory32(addr, cpu->Reg_usr[0]);
3573
3574 addr += 4;
3575 }
3576 if (BIT(inst_cream->inst, 14)) {
3577 if (cpu->Mode == USER32MODE)
3578 cpu->WriteMemory32(addr, cpu->Reg[14]);
3579 else
3580 cpu->WriteMemory32(addr, cpu->Reg_usr[1]);
3581
3582 addr += 4;
3583 }
3584 if (BIT(inst_cream->inst, 15)) {
3585 cpu->WriteMemory32(addr, cpu->Reg[15] + 8);
3586 }
3587 } else {
3588 for (int i = 0; i < 15; i++) {
3589 if (BIT(inst_cream->inst, i)) {
3590 if (i == Rn)
3591 cpu->WriteMemory32(addr, old_RN);
3227 else 3592 else
3228 cpu->WriteMemory32(addr, cpu->Reg_usr[1]); 3593 cpu->WriteMemory32(addr, cpu->Reg[i]);
3229 3594
3230 addr += 4; 3595 addr += 4;
3231 } 3596 }
3232 if (BIT(inst_cream->inst, 15)) { 3597 }
3233 cpu->WriteMemory32(addr, cpu->Reg[15] + 8);
3234 }
3235 } else {
3236 for (int i = 0; i < 15; i++) {
3237 if (BIT(inst_cream->inst, i)) {
3238 if (i == Rn)
3239 cpu->WriteMemory32(addr, old_RN);
3240 else
3241 cpu->WriteMemory32(addr, cpu->Reg[i]);
3242
3243 addr += 4;
3244 }
3245 }
3246 3598
3247 // Check PC reg 3599 // Check PC reg
3248 if (BIT(inst_cream->inst, 15)) { 3600 if (BIT(inst_cream->inst, 15)) {
3249 cpu->WriteMemory32(addr, cpu->Reg[15] + 8); 3601 cpu->WriteMemory32(addr, cpu->Reg[15] + 8);
3250 }
3251 } 3602 }
3252 } 3603 }
3253 cpu->Reg[15] += cpu->GetInstructionSize();
3254 INC_PC(sizeof(ldst_inst));
3255 FETCH_INST;
3256 GOTO_NEXT_INST;
3257 } 3604 }
3258 SXTB_INST: 3605 cpu->Reg[15] += cpu->GetInstructionSize();
3259 { 3606 INC_PC(sizeof(ldst_inst));
3260 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3607 FETCH_INST;
3261 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component; 3608 GOTO_NEXT_INST;
3609}
3610SXTB_INST : {
3611 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3612 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component;
3262 3613
3263 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate); 3614 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
3264 if (BIT(operand2, 7)) { 3615 if (BIT(operand2, 7)) {
3265 operand2 |= 0xffffff00; 3616 operand2 |= 0xffffff00;
3266 } else { 3617 } else {
3267 operand2 &= 0xff; 3618 operand2 &= 0xff;
3268 }
3269 RD = operand2;
3270 } 3619 }
3271 cpu->Reg[15] += cpu->GetInstructionSize(); 3620 RD = operand2;
3272 INC_PC(sizeof(sxtb_inst));
3273 FETCH_INST;
3274 GOTO_NEXT_INST;
3275 } 3621 }
3276 STR_INST: 3622 cpu->Reg[15] += cpu->GetInstructionSize();
3277 { 3623 INC_PC(sizeof(sxtb_inst));
3278 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3624 FETCH_INST;
3279 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 3625 GOTO_NEXT_INST;
3280 inst_cream->get_addr(cpu, inst_cream->inst, addr); 3626}
3627STR_INST : {
3628 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3629 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3630 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3281 3631
3282 unsigned int reg = BITS(inst_cream->inst, 12, 15); 3632 unsigned int reg = BITS(inst_cream->inst, 12, 15);
3283 unsigned int value = cpu->Reg[reg]; 3633 unsigned int value = cpu->Reg[reg];
3284 3634
3285 if (reg == 15) 3635 if (reg == 15)
3286 value += 2 * cpu->GetInstructionSize(); 3636 value += 2 * cpu->GetInstructionSize();
3287 3637
3288 cpu->WriteMemory32(addr, value); 3638 cpu->WriteMemory32(addr, value);
3289 }
3290 cpu->Reg[15] += cpu->GetInstructionSize();
3291 INC_PC(sizeof(ldst_inst));
3292 FETCH_INST;
3293 GOTO_NEXT_INST;
3294 }
3295 UXTB_INST:
3296 {
3297 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3298 uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component;
3299 RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3300 }
3301 cpu->Reg[15] += cpu->GetInstructionSize();
3302 INC_PC(sizeof(uxtb_inst));
3303 FETCH_INST;
3304 GOTO_NEXT_INST;
3305 }
3306 UXTAB_INST:
3307 {
3308 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3309 uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component;
3310
3311 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3312 RD = RN + operand2;
3313 }
3314 cpu->Reg[15] += cpu->GetInstructionSize();
3315 INC_PC(sizeof(uxtab_inst));
3316 FETCH_INST;
3317 GOTO_NEXT_INST;
3318 }
3319 STRB_INST:
3320 {
3321 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3322 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3323 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3324 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
3325 cpu->WriteMemory8(addr, value);
3326 }
3327 cpu->Reg[15] += cpu->GetInstructionSize();
3328 INC_PC(sizeof(ldst_inst));
3329 FETCH_INST;
3330 GOTO_NEXT_INST;
3331 } 3639 }
3332 STRBT_INST: 3640 cpu->Reg[15] += cpu->GetInstructionSize();
3333 { 3641 INC_PC(sizeof(ldst_inst));
3334 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3642 FETCH_INST;
3335 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 3643 GOTO_NEXT_INST;
3336 inst_cream->get_addr(cpu, inst_cream->inst, addr); 3644}
3645UXTB_INST : {
3646 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3647 uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component;
3648 RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3649 }
3650 cpu->Reg[15] += cpu->GetInstructionSize();
3651 INC_PC(sizeof(uxtb_inst));
3652 FETCH_INST;
3653 GOTO_NEXT_INST;
3654}
3655UXTAB_INST : {
3656 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3657 uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component;
3337 3658
3338 const u32 previous_mode = cpu->Mode; 3659 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3339 const u32 value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; 3660 RD = RN + operand2;
3661 }
3662 cpu->Reg[15] += cpu->GetInstructionSize();
3663 INC_PC(sizeof(uxtab_inst));
3664 FETCH_INST;
3665 GOTO_NEXT_INST;
3666}
3667STRB_INST : {
3668 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3669 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3670 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3671 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
3672 cpu->WriteMemory8(addr, value);
3673 }
3674 cpu->Reg[15] += cpu->GetInstructionSize();
3675 INC_PC(sizeof(ldst_inst));
3676 FETCH_INST;
3677 GOTO_NEXT_INST;
3678}
3679STRBT_INST : {
3680 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3681 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3682 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3340 3683
3341 cpu->ChangePrivilegeMode(USER32MODE); 3684 const u32 previous_mode = cpu->Mode;
3342 cpu->WriteMemory8(addr, value); 3685 const u32 value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
3343 cpu->ChangePrivilegeMode(previous_mode);
3344 }
3345 cpu->Reg[15] += cpu->GetInstructionSize();
3346 INC_PC(sizeof(ldst_inst));
3347 FETCH_INST;
3348 GOTO_NEXT_INST;
3349 }
3350 STRD_INST:
3351 {
3352 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3353 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3354 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3355
3356 // The 3DS doesn't have the Large Physical Access Extension (LPAE)
3357 // so STRD wouldn't store these as a single write.
3358 cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]);
3359 cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]);
3360 }
3361 cpu->Reg[15] += cpu->GetInstructionSize();
3362 INC_PC(sizeof(ldst_inst));
3363 FETCH_INST;
3364 GOTO_NEXT_INST;
3365 }
3366 STREX_INST:
3367 {
3368 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3369 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3370 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3371
3372 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3373 cpu->UnsetExclusiveMemoryAddress();
3374 cpu->WriteMemory32(write_addr, RM);
3375 RD = 0;
3376 } else {
3377 // Failed to write due to mutex access
3378 RD = 1;
3379 }
3380 }
3381 cpu->Reg[15] += cpu->GetInstructionSize();
3382 INC_PC(sizeof(generic_arm_inst));
3383 FETCH_INST;
3384 GOTO_NEXT_INST;
3385 }
3386 STREXB_INST:
3387 {
3388 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3389 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3390 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3391
3392 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3393 cpu->UnsetExclusiveMemoryAddress();
3394 cpu->WriteMemory8(write_addr, cpu->Reg[inst_cream->Rm]);
3395 RD = 0;
3396 } else {
3397 // Failed to write due to mutex access
3398 RD = 1;
3399 }
3400 }
3401 cpu->Reg[15] += cpu->GetInstructionSize();
3402 INC_PC(sizeof(generic_arm_inst));
3403 FETCH_INST;
3404 GOTO_NEXT_INST;
3405 }
3406 STREXD_INST:
3407 {
3408 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3409 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3410 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3411
3412 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3413 cpu->UnsetExclusiveMemoryAddress();
3414
3415 const u32 rt = cpu->Reg[inst_cream->Rm + 0];
3416 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
3417 u64 value;
3418
3419 if (cpu->InBigEndianMode())
3420 value = (((u64)rt << 32) | rt2);
3421 else
3422 value = (((u64)rt2 << 32) | rt);
3423 3686
3424 cpu->WriteMemory64(write_addr, value); 3687 cpu->ChangePrivilegeMode(USER32MODE);
3425 RD = 0; 3688 cpu->WriteMemory8(addr, value);
3426 } 3689 cpu->ChangePrivilegeMode(previous_mode);
3427 else { 3690 }
3428 // Failed to write due to mutex access 3691 cpu->Reg[15] += cpu->GetInstructionSize();
3429 RD = 1; 3692 INC_PC(sizeof(ldst_inst));
3430 } 3693 FETCH_INST;
3431 } 3694 GOTO_NEXT_INST;
3432 cpu->Reg[15] += cpu->GetInstructionSize(); 3695}
3433 INC_PC(sizeof(generic_arm_inst)); 3696STRD_INST : {
3434 FETCH_INST; 3697 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3435 GOTO_NEXT_INST; 3698 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3436 } 3699 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3437 STREXH_INST: 3700
3438 { 3701 // The 3DS doesn't have the Large Physical Access Extension (LPAE)
3439 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3702 // so STRD wouldn't store these as a single write.
3440 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 3703 cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]);
3441 unsigned int write_addr = cpu->Reg[inst_cream->Rn]; 3704 cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]);
3442 3705 }
3443 if (cpu->IsExclusiveMemoryAccess(write_addr)) { 3706 cpu->Reg[15] += cpu->GetInstructionSize();
3444 cpu->UnsetExclusiveMemoryAddress(); 3707 INC_PC(sizeof(ldst_inst));
3445 cpu->WriteMemory16(write_addr, RM); 3708 FETCH_INST;
3446 RD = 0; 3709 GOTO_NEXT_INST;
3447 } else { 3710}
3448 // Failed to write due to mutex access 3711STREX_INST : {
3449 RD = 1; 3712 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3450 } 3713 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3714 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3715
3716 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3717 cpu->UnsetExclusiveMemoryAddress();
3718 cpu->WriteMemory32(write_addr, RM);
3719 RD = 0;
3720 } else {
3721 // Failed to write due to mutex access
3722 RD = 1;
3451 } 3723 }
3452 cpu->Reg[15] += cpu->GetInstructionSize(); 3724 }
3453 INC_PC(sizeof(generic_arm_inst)); 3725 cpu->Reg[15] += cpu->GetInstructionSize();
3454 FETCH_INST; 3726 INC_PC(sizeof(generic_arm_inst));
3455 GOTO_NEXT_INST; 3727 FETCH_INST;
3456 } 3728 GOTO_NEXT_INST;
3457 STRH_INST: 3729}
3458 { 3730STREXB_INST : {
3459 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3731 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3460 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 3732 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3461 inst_cream->get_addr(cpu, inst_cream->inst, addr); 3733 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3462 3734
3463 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; 3735 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3464 cpu->WriteMemory16(addr, value); 3736 cpu->UnsetExclusiveMemoryAddress();
3737 cpu->WriteMemory8(write_addr, cpu->Reg[inst_cream->Rm]);
3738 RD = 0;
3739 } else {
3740 // Failed to write due to mutex access
3741 RD = 1;
3465 } 3742 }
3466 cpu->Reg[15] += cpu->GetInstructionSize();
3467 INC_PC(sizeof(ldst_inst));
3468 FETCH_INST;
3469 GOTO_NEXT_INST;
3470 } 3743 }
3471 STRT_INST: 3744 cpu->Reg[15] += cpu->GetInstructionSize();
3472 { 3745 INC_PC(sizeof(generic_arm_inst));
3473 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3746 FETCH_INST;
3474 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 3747 GOTO_NEXT_INST;
3475 inst_cream->get_addr(cpu, inst_cream->inst, addr); 3748}
3749STREXD_INST : {
3750 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3751 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3752 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3476 3753
3477 const u32 previous_mode = cpu->Mode; 3754 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3478 const u32 rt_index = BITS(inst_cream->inst, 12, 15); 3755 cpu->UnsetExclusiveMemoryAddress();
3479 3756
3480 u32 value = cpu->Reg[rt_index]; 3757 const u32 rt = cpu->Reg[inst_cream->Rm + 0];
3481 if (rt_index == 15) 3758 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
3482 value += 2 * cpu->GetInstructionSize(); 3759 u64 value;
3483 3760
3484 cpu->ChangePrivilegeMode(USER32MODE); 3761 if (cpu->InBigEndianMode())
3485 cpu->WriteMemory32(addr, value); 3762 value = (((u64)rt << 32) | rt2);
3486 cpu->ChangePrivilegeMode(previous_mode); 3763 else
3764 value = (((u64)rt2 << 32) | rt);
3765
3766 cpu->WriteMemory64(write_addr, value);
3767 RD = 0;
3768 } else {
3769 // Failed to write due to mutex access
3770 RD = 1;
3487 } 3771 }
3488 cpu->Reg[15] += cpu->GetInstructionSize();
3489 INC_PC(sizeof(ldst_inst));
3490 FETCH_INST;
3491 GOTO_NEXT_INST;
3492 } 3772 }
3493 SUB_INST: 3773 cpu->Reg[15] += cpu->GetInstructionSize();
3494 { 3774 INC_PC(sizeof(generic_arm_inst));
3495 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3775 FETCH_INST;
3496 sub_inst* const inst_cream = (sub_inst*)inst_base->component; 3776 GOTO_NEXT_INST;
3777}
3778STREXH_INST : {
3779 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3780 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3781 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3782
3783 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3784 cpu->UnsetExclusiveMemoryAddress();
3785 cpu->WriteMemory16(write_addr, RM);
3786 RD = 0;
3787 } else {
3788 // Failed to write due to mutex access
3789 RD = 1;
3790 }
3791 }
3792 cpu->Reg[15] += cpu->GetInstructionSize();
3793 INC_PC(sizeof(generic_arm_inst));
3794 FETCH_INST;
3795 GOTO_NEXT_INST;
3796}
3797STRH_INST : {
3798 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3799 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3800 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3497 3801
3498 u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn); 3802 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
3803 cpu->WriteMemory16(addr, value);
3804 }
3805 cpu->Reg[15] += cpu->GetInstructionSize();
3806 INC_PC(sizeof(ldst_inst));
3807 FETCH_INST;
3808 GOTO_NEXT_INST;
3809}
3810STRT_INST : {
3811 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3812 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3813 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3499 3814
3500 bool carry; 3815 const u32 previous_mode = cpu->Mode;
3501 bool overflow; 3816 const u32 rt_index = BITS(inst_cream->inst, 12, 15);
3502 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
3503 3817
3504 if (inst_cream->S && (inst_cream->Rd == 15)) { 3818 u32 value = cpu->Reg[rt_index];
3505 if (CurrentModeHasSPSR) { 3819 if (rt_index == 15)
3506 cpu->Cpsr = cpu->Spsr_copy; 3820 value += 2 * cpu->GetInstructionSize();
3507 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
3508 LOAD_NZCVT;
3509 }
3510 } else if (inst_cream->S) {
3511 UPDATE_NFLAG(RD);
3512 UPDATE_ZFLAG(RD);
3513 cpu->CFlag = carry;
3514 cpu->VFlag = overflow;
3515 }
3516 if (inst_cream->Rd == 15) {
3517 INC_PC(sizeof(sub_inst));
3518 goto DISPATCH;
3519 }
3520 }
3521 cpu->Reg[15] += cpu->GetInstructionSize();
3522 INC_PC(sizeof(sub_inst));
3523 FETCH_INST;
3524 GOTO_NEXT_INST;
3525 }
3526 SWI_INST:
3527 {
3528 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3529 swi_inst* const inst_cream = (swi_inst*)inst_base->component;
3530 SVC::CallSVC(inst_cream->num & 0xFFFF);
3531 }
3532 3821
3533 cpu->Reg[15] += cpu->GetInstructionSize(); 3822 cpu->ChangePrivilegeMode(USER32MODE);
3534 INC_PC(sizeof(swi_inst)); 3823 cpu->WriteMemory32(addr, value);
3535 FETCH_INST; 3824 cpu->ChangePrivilegeMode(previous_mode);
3536 GOTO_NEXT_INST;
3537 } 3825 }
3538 SWP_INST: 3826 cpu->Reg[15] += cpu->GetInstructionSize();
3539 { 3827 INC_PC(sizeof(ldst_inst));
3540 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3828 FETCH_INST;
3541 swp_inst* inst_cream = (swp_inst*)inst_base->component; 3829 GOTO_NEXT_INST;
3830}
3831SUB_INST : {
3832 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3833 sub_inst* const inst_cream = (sub_inst*)inst_base->component;
3542 3834
3543 addr = RN; 3835 u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
3544 unsigned int value = cpu->ReadMemory32(addr);
3545 cpu->WriteMemory32(addr, RM);
3546 3836
3547 RD = value; 3837 bool carry;
3838 bool overflow;
3839 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
3840
3841 if (inst_cream->S && (inst_cream->Rd == 15)) {
3842 if (CurrentModeHasSPSR) {
3843 cpu->Cpsr = cpu->Spsr_copy;
3844 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
3845 LOAD_NZCVT;
3846 }
3847 } else if (inst_cream->S) {
3848 UPDATE_NFLAG(RD);
3849 UPDATE_ZFLAG(RD);
3850 cpu->CFlag = carry;
3851 cpu->VFlag = overflow;
3548 } 3852 }
3549 cpu->Reg[15] += cpu->GetInstructionSize(); 3853 if (inst_cream->Rd == 15) {
3550 INC_PC(sizeof(swp_inst)); 3854 INC_PC(sizeof(sub_inst));
3551 FETCH_INST; 3855 goto DISPATCH;
3552 GOTO_NEXT_INST;
3553 }
3554 SWPB_INST:
3555 {
3556 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3557 swp_inst* inst_cream = (swp_inst*)inst_base->component;
3558 addr = RN;
3559 unsigned int value = cpu->ReadMemory8(addr);
3560 cpu->WriteMemory8(addr, (RM & 0xFF));
3561 RD = value;
3562 } 3856 }
3563 cpu->Reg[15] += cpu->GetInstructionSize();
3564 INC_PC(sizeof(swp_inst));
3565 FETCH_INST;
3566 GOTO_NEXT_INST;
3567 } 3857 }
3568 SXTAB_INST: 3858 cpu->Reg[15] += cpu->GetInstructionSize();
3569 { 3859 INC_PC(sizeof(sub_inst));
3570 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3860 FETCH_INST;
3571 sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component; 3861 GOTO_NEXT_INST;
3862}
3863SWI_INST : {
3864 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3865 swi_inst* const inst_cream = (swi_inst*)inst_base->component;
3866 SVC::CallSVC(inst_cream->num & 0xFFFF);
3867 }
3572 3868
3573 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; 3869 cpu->Reg[15] += cpu->GetInstructionSize();
3870 INC_PC(sizeof(swi_inst));
3871 FETCH_INST;
3872 GOTO_NEXT_INST;
3873}
3874SWP_INST : {
3875 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3876 swp_inst* inst_cream = (swp_inst*)inst_base->component;
3574 3877
3575 // Sign extend for byte 3878 addr = RN;
3576 operand2 = (0x80 & operand2)? (0xFFFFFF00 | operand2):operand2; 3879 unsigned int value = cpu->ReadMemory32(addr);
3577 RD = RN + operand2; 3880 cpu->WriteMemory32(addr, RM);
3578 }
3579 cpu->Reg[15] += cpu->GetInstructionSize();
3580 INC_PC(sizeof(uxtab_inst));
3581 FETCH_INST;
3582 GOTO_NEXT_INST;
3583 }
3584
3585 SXTAB16_INST:
3586 SXTB16_INST:
3587 {
3588 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3589 sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component;
3590
3591 const u8 rotation = inst_cream->rotate * 8;
3592 u32 rm_val = RM;
3593 u32 rn_val = RN;
3594
3595 if (rotation)
3596 rm_val = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
3597
3598 // SXTB16
3599 if (inst_cream->Rn == 15) {
3600 u32 lo = (u32)(s8)rm_val;
3601 u32 hi = (u32)(s8)(rm_val >> 16);
3602 RD = (lo | (hi << 16));
3603 }
3604 // SXTAB16
3605 else {
3606 u32 lo = (rn_val & 0xFFFF) + (u32)(s8)(rm_val & 0xFF);
3607 u32 hi = ((rn_val >> 16) & 0xFFFF) + (u32)(s8)((rm_val >> 16) & 0xFF);
3608 RD = (lo | (hi << 16));
3609 }
3610 }
3611 3881
3612 cpu->Reg[15] += cpu->GetInstructionSize(); 3882 RD = value;
3613 INC_PC(sizeof(sxtab_inst));
3614 FETCH_INST;
3615 GOTO_NEXT_INST;
3616 } 3883 }
3884 cpu->Reg[15] += cpu->GetInstructionSize();
3885 INC_PC(sizeof(swp_inst));
3886 FETCH_INST;
3887 GOTO_NEXT_INST;
3888}
3889SWPB_INST : {
3890 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3891 swp_inst* inst_cream = (swp_inst*)inst_base->component;
3892 addr = RN;
3893 unsigned int value = cpu->ReadMemory8(addr);
3894 cpu->WriteMemory8(addr, (RM & 0xFF));
3895 RD = value;
3896 }
3897 cpu->Reg[15] += cpu->GetInstructionSize();
3898 INC_PC(sizeof(swp_inst));
3899 FETCH_INST;
3900 GOTO_NEXT_INST;
3901}
3902SXTAB_INST : {
3903 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3904 sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component;
3617 3905
3618 SXTAH_INST: 3906 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3619 {
3620 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3621 sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component;
3622 3907
3623 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; 3908 // Sign extend for byte
3624 // Sign extend for half 3909 operand2 = (0x80 & operand2) ? (0xFFFFFF00 | operand2) : operand2;
3625 operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2; 3910 RD = RN + operand2;
3626 RD = RN + operand2;
3627 }
3628 cpu->Reg[15] += cpu->GetInstructionSize();
3629 INC_PC(sizeof(sxtah_inst));
3630 FETCH_INST;
3631 GOTO_NEXT_INST;
3632 } 3911 }
3912 cpu->Reg[15] += cpu->GetInstructionSize();
3913 INC_PC(sizeof(uxtab_inst));
3914 FETCH_INST;
3915 GOTO_NEXT_INST;
3916}
3633 3917
3634 TEQ_INST: 3918SXTAB16_INST:
3635 { 3919SXTB16_INST : {
3636 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3920 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3637 teq_inst* const inst_cream = (teq_inst*)inst_base->component; 3921 sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component;
3638
3639 u32 lop = RN;
3640 u32 rop = SHIFTER_OPERAND;
3641 3922
3642 if (inst_cream->Rn == 15) 3923 const u8 rotation = inst_cream->rotate * 8;
3643 lop += cpu->GetInstructionSize() * 2; 3924 u32 rm_val = RM;
3925 u32 rn_val = RN;
3644 3926
3645 u32 result = lop ^ rop; 3927 if (rotation)
3928 rm_val = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
3646 3929
3647 UPDATE_NFLAG(result); 3930 // SXTB16
3648 UPDATE_ZFLAG(result); 3931 if (inst_cream->Rn == 15) {
3649 UPDATE_CFLAG_WITH_SC; 3932 u32 lo = (u32)(s8)rm_val;
3933 u32 hi = (u32)(s8)(rm_val >> 16);
3934 RD = (lo | (hi << 16));
3935 }
3936 // SXTAB16
3937 else {
3938 u32 lo = (rn_val & 0xFFFF) + (u32)(s8)(rm_val & 0xFF);
3939 u32 hi = ((rn_val >> 16) & 0xFFFF) + (u32)(s8)((rm_val >> 16) & 0xFF);
3940 RD = (lo | (hi << 16));
3650 } 3941 }
3651 cpu->Reg[15] += cpu->GetInstructionSize();
3652 INC_PC(sizeof(teq_inst));
3653 FETCH_INST;
3654 GOTO_NEXT_INST;
3655 } 3942 }
3656 TST_INST:
3657 {
3658 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3659 tst_inst* const inst_cream = (tst_inst*)inst_base->component;
3660 3943
3661 u32 lop = RN; 3944 cpu->Reg[15] += cpu->GetInstructionSize();
3662 u32 rop = SHIFTER_OPERAND; 3945 INC_PC(sizeof(sxtab_inst));
3663 3946 FETCH_INST;
3664 if (inst_cream->Rn == 15) 3947 GOTO_NEXT_INST;
3665 lop += cpu->GetInstructionSize() * 2; 3948}
3666 3949
3667 u32 result = lop & rop; 3950SXTAH_INST : {
3951 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3952 sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component;
3668 3953
3669 UPDATE_NFLAG(result); 3954 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
3670 UPDATE_ZFLAG(result); 3955 // Sign extend for half
3671 UPDATE_CFLAG_WITH_SC; 3956 operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2;
3672 } 3957 RD = RN + operand2;
3673 cpu->Reg[15] += cpu->GetInstructionSize(); 3958 }
3674 INC_PC(sizeof(tst_inst)); 3959 cpu->Reg[15] += cpu->GetInstructionSize();
3675 FETCH_INST; 3960 INC_PC(sizeof(sxtah_inst));
3676 GOTO_NEXT_INST; 3961 FETCH_INST;
3677 } 3962 GOTO_NEXT_INST;
3678 3963}
3679 UADD8_INST:
3680 UADD16_INST:
3681 UADDSUBX_INST:
3682 USUB8_INST:
3683 USUB16_INST:
3684 USUBADDX_INST:
3685 {
3686 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3687 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
3688
3689 const u8 op2 = inst_cream->op2;
3690 const u32 rm_val = RM;
3691 const u32 rn_val = RN;
3692 3964
3693 s32 lo_result = 0; 3965TEQ_INST : {
3694 s32 hi_result = 0; 3966 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3967 teq_inst* const inst_cream = (teq_inst*)inst_base->component;
3695 3968
3696 // UADD16 3969 u32 lop = RN;
3697 if (op2 == 0x00) { 3970 u32 rop = SHIFTER_OPERAND;
3698 lo_result = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
3699 hi_result = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
3700
3701 if (lo_result & 0xFFFF0000) {
3702 cpu->Cpsr |= (1 << 16);
3703 cpu->Cpsr |= (1 << 17);
3704 } else {
3705 cpu->Cpsr &= ~(1 << 16);
3706 cpu->Cpsr &= ~(1 << 17);
3707 }
3708 3971
3709 if (hi_result & 0xFFFF0000) { 3972 if (inst_cream->Rn == 15)
3710 cpu->Cpsr |= (1 << 18); 3973 lop += cpu->GetInstructionSize() * 2;
3711 cpu->Cpsr |= (1 << 19);
3712 } else {
3713 cpu->Cpsr &= ~(1 << 18);
3714 cpu->Cpsr &= ~(1 << 19);
3715 }
3716 }
3717 // UASX
3718 else if (op2 == 0x01) {
3719 lo_result = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
3720 hi_result = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
3721
3722 if (lo_result >= 0) {
3723 cpu->Cpsr |= (1 << 16);
3724 cpu->Cpsr |= (1 << 17);
3725 } else {
3726 cpu->Cpsr &= ~(1 << 16);
3727 cpu->Cpsr &= ~(1 << 17);
3728 }
3729 3974
3730 if (hi_result >= 0x10000) { 3975 u32 result = lop ^ rop;
3731 cpu->Cpsr |= (1 << 18);
3732 cpu->Cpsr |= (1 << 19);
3733 } else {
3734 cpu->Cpsr &= ~(1 << 18);
3735 cpu->Cpsr &= ~(1 << 19);
3736 }
3737 }
3738 // USAX
3739 else if (op2 == 0x02) {
3740 lo_result = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
3741 hi_result = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
3742
3743 if (lo_result >= 0x10000) {
3744 cpu->Cpsr |= (1 << 16);
3745 cpu->Cpsr |= (1 << 17);
3746 } else {
3747 cpu->Cpsr &= ~(1 << 16);
3748 cpu->Cpsr &= ~(1 << 17);
3749 }
3750 3976
3751 if (hi_result >= 0) { 3977 UPDATE_NFLAG(result);
3752 cpu->Cpsr |= (1 << 18); 3978 UPDATE_ZFLAG(result);
3753 cpu->Cpsr |= (1 << 19); 3979 UPDATE_CFLAG_WITH_SC;
3754 } else { 3980 }
3755 cpu->Cpsr &= ~(1 << 18); 3981 cpu->Reg[15] += cpu->GetInstructionSize();
3756 cpu->Cpsr &= ~(1 << 19); 3982 INC_PC(sizeof(teq_inst));
3757 } 3983 FETCH_INST;
3758 } 3984 GOTO_NEXT_INST;
3759 // USUB16 3985}
3760 else if (op2 == 0x03) { 3986TST_INST : {
3761 lo_result = (rn_val & 0xFFFF) - (rm_val & 0xFFFF); 3987 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3762 hi_result = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); 3988 tst_inst* const inst_cream = (tst_inst*)inst_base->component;
3763
3764 if ((lo_result & 0xFFFF0000) == 0) {
3765 cpu->Cpsr |= (1 << 16);
3766 cpu->Cpsr |= (1 << 17);
3767 } else {
3768 cpu->Cpsr &= ~(1 << 16);
3769 cpu->Cpsr &= ~(1 << 17);
3770 }
3771 3989
3772 if ((hi_result & 0xFFFF0000) == 0) { 3990 u32 lop = RN;
3773 cpu->Cpsr |= (1 << 18); 3991 u32 rop = SHIFTER_OPERAND;
3774 cpu->Cpsr |= (1 << 19);
3775 } else {
3776 cpu->Cpsr &= ~(1 << 18);
3777 cpu->Cpsr &= ~(1 << 19);
3778 }
3779 }
3780 // UADD8
3781 else if (op2 == 0x04) {
3782 s16 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
3783 s16 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
3784 s16 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
3785 s16 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
3786
3787 if (sum1 >= 0x100)
3788 cpu->Cpsr |= (1 << 16);
3789 else
3790 cpu->Cpsr &= ~(1 << 16);
3791 3992
3792 if (sum2 >= 0x100) 3993 if (inst_cream->Rn == 15)
3793 cpu->Cpsr |= (1 << 17); 3994 lop += cpu->GetInstructionSize() * 2;
3794 else
3795 cpu->Cpsr &= ~(1 << 17);
3796 3995
3797 if (sum3 >= 0x100) 3996 u32 result = lop & rop;
3798 cpu->Cpsr |= (1 << 18);
3799 else
3800 cpu->Cpsr &= ~(1 << 18);
3801 3997
3802 if (sum4 >= 0x100) 3998 UPDATE_NFLAG(result);
3803 cpu->Cpsr |= (1 << 19); 3999 UPDATE_ZFLAG(result);
3804 else 4000 UPDATE_CFLAG_WITH_SC;
3805 cpu->Cpsr &= ~(1 << 19); 4001 }
4002 cpu->Reg[15] += cpu->GetInstructionSize();
4003 INC_PC(sizeof(tst_inst));
4004 FETCH_INST;
4005 GOTO_NEXT_INST;
4006}
3806 4007
3807 lo_result = ((sum1 & 0xFF) | (sum2 & 0xFF) << 8); 4008UADD8_INST:
3808 hi_result = ((sum3 & 0xFF) | (sum4 & 0xFF) << 8); 4009UADD16_INST:
4010UADDSUBX_INST:
4011USUB8_INST:
4012USUB16_INST:
4013USUBADDX_INST : {
4014 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4015 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4016
4017 const u8 op2 = inst_cream->op2;
4018 const u32 rm_val = RM;
4019 const u32 rn_val = RN;
4020
4021 s32 lo_result = 0;
4022 s32 hi_result = 0;
4023
4024 // UADD16
4025 if (op2 == 0x00) {
4026 lo_result = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
4027 hi_result = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4028
4029 if (lo_result & 0xFFFF0000) {
4030 cpu->Cpsr |= (1 << 16);
4031 cpu->Cpsr |= (1 << 17);
4032 } else {
4033 cpu->Cpsr &= ~(1 << 16);
4034 cpu->Cpsr &= ~(1 << 17);
3809 } 4035 }
3810 // USUB8
3811 else if (op2 == 0x07) {
3812 s16 diff1 = (rn_val & 0xFF) - (rm_val & 0xFF);
3813 s16 diff2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
3814 s16 diff3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
3815 s16 diff4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
3816
3817 if (diff1 >= 0)
3818 cpu->Cpsr |= (1 << 16);
3819 else
3820 cpu->Cpsr &= ~(1 << 16);
3821 4036
3822 if (diff2 >= 0) 4037 if (hi_result & 0xFFFF0000) {
3823 cpu->Cpsr |= (1 << 17); 4038 cpu->Cpsr |= (1 << 18);
3824 else 4039 cpu->Cpsr |= (1 << 19);
3825 cpu->Cpsr &= ~(1 << 17); 4040 } else {
3826 4041 cpu->Cpsr &= ~(1 << 18);
3827 if (diff3 >= 0) 4042 cpu->Cpsr &= ~(1 << 19);
3828 cpu->Cpsr |= (1 << 18);
3829 else
3830 cpu->Cpsr &= ~(1 << 18);
3831
3832 if (diff4 >= 0)
3833 cpu->Cpsr |= (1 << 19);
3834 else
3835 cpu->Cpsr &= ~(1 << 19);
3836
3837 lo_result = (diff1 & 0xFF) | ((diff2 & 0xFF) << 8);
3838 hi_result = (diff3 & 0xFF) | ((diff4 & 0xFF) << 8);
3839 } 4043 }
3840
3841 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
3842 } 4044 }
4045 // UASX
4046 else if (op2 == 0x01) {
4047 lo_result = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4048 hi_result = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
4049
4050 if (lo_result >= 0) {
4051 cpu->Cpsr |= (1 << 16);
4052 cpu->Cpsr |= (1 << 17);
4053 } else {
4054 cpu->Cpsr &= ~(1 << 16);
4055 cpu->Cpsr &= ~(1 << 17);
4056 }
3843 4057
3844 cpu->Reg[15] += cpu->GetInstructionSize(); 4058 if (hi_result >= 0x10000) {
3845 INC_PC(sizeof(generic_arm_inst)); 4059 cpu->Cpsr |= (1 << 18);
3846 FETCH_INST; 4060 cpu->Cpsr |= (1 << 19);
3847 GOTO_NEXT_INST; 4061 } else {
3848 } 4062 cpu->Cpsr &= ~(1 << 18);
3849 4063 cpu->Cpsr &= ~(1 << 19);
3850 UHADD8_INST: 4064 }
3851 UHADD16_INST: 4065 }
3852 UHADDSUBX_INST: 4066 // USAX
3853 UHSUBADDX_INST: 4067 else if (op2 == 0x02) {
3854 UHSUB8_INST: 4068 lo_result = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
3855 UHSUB16_INST: 4069 hi_result = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
3856 { 4070
3857 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4071 if (lo_result >= 0x10000) {
3858 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 4072 cpu->Cpsr |= (1 << 16);
3859 const u32 rm_val = RM; 4073 cpu->Cpsr |= (1 << 17);
3860 const u32 rn_val = RN; 4074 } else {
3861 const u8 op2 = inst_cream->op2; 4075 cpu->Cpsr &= ~(1 << 16);
3862 4076 cpu->Cpsr &= ~(1 << 17);
3863 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03)
3864 {
3865 u32 lo_val = 0;
3866 u32 hi_val = 0;
3867
3868 // UHADD16
3869 if (op2 == 0x00) {
3870 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
3871 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
3872 }
3873 // UHASX
3874 else if (op2 == 0x01) {
3875 lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
3876 hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
3877 }
3878 // UHSAX
3879 else if (op2 == 0x02) {
3880 lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
3881 hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
3882 }
3883 // UHSUB16
3884 else if (op2 == 0x03) {
3885 lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
3886 hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
3887 }
3888
3889 lo_val >>= 1;
3890 hi_val >>= 1;
3891
3892 RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
3893 } 4077 }
3894 else if (op2 == 0x04 || op2 == 0x07) {
3895 u32 sum1;
3896 u32 sum2;
3897 u32 sum3;
3898 u32 sum4;
3899
3900 // UHADD8
3901 if (op2 == 0x04) {
3902 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
3903 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
3904 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
3905 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
3906 }
3907 // UHSUB8
3908 else {
3909 sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
3910 sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
3911 sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
3912 sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
3913 }
3914 4078
3915 sum1 >>= 1; 4079 if (hi_result >= 0) {
3916 sum2 >>= 1; 4080 cpu->Cpsr |= (1 << 18);
3917 sum3 >>= 1; 4081 cpu->Cpsr |= (1 << 19);
3918 sum4 >>= 1; 4082 } else {
4083 cpu->Cpsr &= ~(1 << 18);
4084 cpu->Cpsr &= ~(1 << 19);
4085 }
4086 }
4087 // USUB16
4088 else if (op2 == 0x03) {
4089 lo_result = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
4090 hi_result = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4091
4092 if ((lo_result & 0xFFFF0000) == 0) {
4093 cpu->Cpsr |= (1 << 16);
4094 cpu->Cpsr |= (1 << 17);
4095 } else {
4096 cpu->Cpsr &= ~(1 << 16);
4097 cpu->Cpsr &= ~(1 << 17);
4098 }
3919 4099
3920 RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24); 4100 if ((hi_result & 0xFFFF0000) == 0) {
4101 cpu->Cpsr |= (1 << 18);
4102 cpu->Cpsr |= (1 << 19);
4103 } else {
4104 cpu->Cpsr &= ~(1 << 18);
4105 cpu->Cpsr &= ~(1 << 19);
3921 } 4106 }
3922 } 4107 }
4108 // UADD8
4109 else if (op2 == 0x04) {
4110 s16 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
4111 s16 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
4112 s16 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
4113 s16 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
4114
4115 if (sum1 >= 0x100)
4116 cpu->Cpsr |= (1 << 16);
4117 else
4118 cpu->Cpsr &= ~(1 << 16);
3923 4119
3924 cpu->Reg[15] += cpu->GetInstructionSize(); 4120 if (sum2 >= 0x100)
3925 INC_PC(sizeof(generic_arm_inst)); 4121 cpu->Cpsr |= (1 << 17);
3926 FETCH_INST; 4122 else
3927 GOTO_NEXT_INST; 4123 cpu->Cpsr &= ~(1 << 17);
3928 }
3929 4124
3930 UMAAL_INST: 4125 if (sum3 >= 0x100)
3931 { 4126 cpu->Cpsr |= (1 << 18);
3932 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4127 else
3933 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; 4128 cpu->Cpsr &= ~(1 << 18);
3934 const u64 rm = RM;
3935 const u64 rn = RN;
3936 const u64 rd_lo = RDLO;
3937 const u64 rd_hi = RDHI;
3938 const u64 result = (rm * rn) + rd_lo + rd_hi;
3939 4129
3940 RDLO = (result & 0xFFFFFFFF); 4130 if (sum4 >= 0x100)
3941 RDHI = ((result >> 32) & 0xFFFFFFFF); 4131 cpu->Cpsr |= (1 << 19);
3942 } 4132 else
3943 cpu->Reg[15] += cpu->GetInstructionSize(); 4133 cpu->Cpsr &= ~(1 << 19);
3944 INC_PC(sizeof(umaal_inst)); 4134
3945 FETCH_INST; 4135 lo_result = ((sum1 & 0xFF) | (sum2 & 0xFF) << 8);
3946 GOTO_NEXT_INST; 4136 hi_result = ((sum3 & 0xFF) | (sum4 & 0xFF) << 8);
3947 }
3948 UMLAL_INST:
3949 {
3950 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3951 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
3952 unsigned long long int rm = RM;
3953 unsigned long long int rs = RS;
3954 unsigned long long int rst = rm * rs;
3955 unsigned long long int add = ((unsigned long long) RDHI)<<32;
3956 add += RDLO;
3957 rst += add;
3958 RDLO = BITS(rst, 0, 31);
3959 RDHI = BITS(rst, 32, 63);
3960
3961 if (inst_cream->S) {
3962 cpu->NFlag = BIT(RDHI, 31);
3963 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
3964 }
3965 }
3966 cpu->Reg[15] += cpu->GetInstructionSize();
3967 INC_PC(sizeof(umlal_inst));
3968 FETCH_INST;
3969 GOTO_NEXT_INST;
3970 }
3971 UMULL_INST:
3972 {
3973 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3974 umull_inst* inst_cream = (umull_inst*)inst_base->component;
3975 unsigned long long int rm = RM;
3976 unsigned long long int rs = RS;
3977 unsigned long long int rst = rm * rs;
3978 RDHI = BITS(rst, 32, 63);
3979 RDLO = BITS(rst, 0, 31);
3980
3981 if (inst_cream->S) {
3982 cpu->NFlag = BIT(RDHI, 31);
3983 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
3984 }
3985 } 4137 }
3986 cpu->Reg[15] += cpu->GetInstructionSize(); 4138 // USUB8
3987 INC_PC(sizeof(umull_inst)); 4139 else if (op2 == 0x07) {
3988 FETCH_INST; 4140 s16 diff1 = (rn_val & 0xFF) - (rm_val & 0xFF);
3989 GOTO_NEXT_INST; 4141 s16 diff2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
3990 } 4142 s16 diff3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
3991 B_2_THUMB: 4143 s16 diff4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
3992 { 4144
3993 b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component; 4145 if (diff1 >= 0)
3994 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; 4146 cpu->Cpsr |= (1 << 16);
3995 INC_PC(sizeof(b_2_thumb)); 4147 else
3996 goto DISPATCH; 4148 cpu->Cpsr &= ~(1 << 16);
3997 }
3998 B_COND_THUMB:
3999 {
4000 b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component;
4001 4149
4002 if(CondPassed(cpu, inst_cream->cond)) 4150 if (diff2 >= 0)
4003 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; 4151 cpu->Cpsr |= (1 << 17);
4004 else 4152 else
4005 cpu->Reg[15] += 2; 4153 cpu->Cpsr &= ~(1 << 17);
4006 4154
4007 INC_PC(sizeof(b_cond_thumb)); 4155 if (diff3 >= 0)
4008 goto DISPATCH; 4156 cpu->Cpsr |= (1 << 18);
4009 } 4157 else
4010 BL_1_THUMB: 4158 cpu->Cpsr &= ~(1 << 18);
4011 {
4012 bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component;
4013 cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm;
4014 cpu->Reg[15] += cpu->GetInstructionSize();
4015 INC_PC(sizeof(bl_1_thumb));
4016 FETCH_INST;
4017 GOTO_NEXT_INST;
4018 }
4019 BL_2_THUMB:
4020 {
4021 bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component;
4022 int tmp = ((cpu->Reg[15] + 2) | 1);
4023 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm);
4024 cpu->Reg[14] = tmp;
4025 INC_PC(sizeof(bl_2_thumb));
4026 goto DISPATCH;
4027 }
4028 BLX_1_THUMB:
4029 {
4030 // BLX 1 for armv5t and above
4031 u32 tmp = cpu->Reg[15];
4032 blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component;
4033 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC;
4034 cpu->Reg[14] = ((tmp + 2) | 1);
4035 cpu->TFlag = 0;
4036 INC_PC(sizeof(blx_1_thumb));
4037 goto DISPATCH;
4038 }
4039 4159
4040 UQADD8_INST: 4160 if (diff4 >= 0)
4041 UQADD16_INST: 4161 cpu->Cpsr |= (1 << 19);
4042 UQADDSUBX_INST: 4162 else
4043 UQSUB8_INST: 4163 cpu->Cpsr &= ~(1 << 19);
4044 UQSUB16_INST:
4045 UQSUBADDX_INST:
4046 {
4047 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4048 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4049 4164
4050 const u8 op2 = inst_cream->op2; 4165 lo_result = (diff1 & 0xFF) | ((diff2 & 0xFF) << 8);
4051 const u32 rm_val = RM; 4166 hi_result = (diff3 & 0xFF) | ((diff4 & 0xFF) << 8);
4052 const u32 rn_val = RN; 4167 }
4053 4168
4054 u16 lo_val = 0; 4169 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
4055 u16 hi_val = 0; 4170 }
4056 4171
4057 // UQADD16 4172 cpu->Reg[15] += cpu->GetInstructionSize();
4173 INC_PC(sizeof(generic_arm_inst));
4174 FETCH_INST;
4175 GOTO_NEXT_INST;
4176}
4177
4178UHADD8_INST:
4179UHADD16_INST:
4180UHADDSUBX_INST:
4181UHSUBADDX_INST:
4182UHSUB8_INST:
4183UHSUB16_INST : {
4184 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4185 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4186 const u32 rm_val = RM;
4187 const u32 rn_val = RN;
4188 const u8 op2 = inst_cream->op2;
4189
4190 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
4191 u32 lo_val = 0;
4192 u32 hi_val = 0;
4193
4194 // UHADD16
4058 if (op2 == 0x00) { 4195 if (op2 == 0x00) {
4059 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF); 4196 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
4060 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); 4197 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4061 } 4198 }
4062 // UQASX 4199 // UHASX
4063 else if (op2 == 0x01) { 4200 else if (op2 == 0x01) {
4064 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); 4201 lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4065 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); 4202 hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
4066 } 4203 }
4067 // UQSAX 4204 // UHSAX
4068 else if (op2 == 0x02) { 4205 else if (op2 == 0x02) {
4069 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); 4206 lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4070 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); 4207 hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
4071 } 4208 }
4072 // UQSUB16 4209 // UHSUB16
4073 else if (op2 == 0x03) { 4210 else if (op2 == 0x03) {
4074 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF); 4211 lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
4075 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); 4212 hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4076 } 4213 }
4077 // UQADD8 4214
4078 else if (op2 == 0x04) { 4215 lo_val >>= 1;
4079 lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) | 4216 hi_val >>= 1;
4080 ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8; 4217
4081 hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) | 4218 RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
4082 ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8; 4219 } else if (op2 == 0x04 || op2 == 0x07) {
4220 u32 sum1;
4221 u32 sum2;
4222 u32 sum3;
4223 u32 sum4;
4224
4225 // UHADD8
4226 if (op2 == 0x04) {
4227 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
4228 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
4229 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
4230 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
4083 } 4231 }
4084 // UQSUB8 4232 // UHSUB8
4085 else { 4233 else {
4086 lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) | 4234 sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
4087 ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8; 4235 sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
4088 hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) | 4236 sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
4089 ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8; 4237 sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
4090 } 4238 }
4091 4239
4092 RD = ((lo_val & 0xFFFF) | hi_val << 16); 4240 sum1 >>= 1;
4241 sum2 >>= 1;
4242 sum3 >>= 1;
4243 sum4 >>= 1;
4244
4245 RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) |
4246 ((sum4 & 0xFF) << 24);
4093 } 4247 }
4248 }
4249
4250 cpu->Reg[15] += cpu->GetInstructionSize();
4251 INC_PC(sizeof(generic_arm_inst));
4252 FETCH_INST;
4253 GOTO_NEXT_INST;
4254}
4094 4255
4095 cpu->Reg[15] += cpu->GetInstructionSize(); 4256UMAAL_INST : {
4096 INC_PC(sizeof(generic_arm_inst)); 4257 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4097 FETCH_INST; 4258 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
4098 GOTO_NEXT_INST; 4259 const u64 rm = RM;
4260 const u64 rn = RN;
4261 const u64 rd_lo = RDLO;
4262 const u64 rd_hi = RDHI;
4263 const u64 result = (rm * rn) + rd_lo + rd_hi;
4264
4265 RDLO = (result & 0xFFFFFFFF);
4266 RDHI = ((result >> 32) & 0xFFFFFFFF);
4267 }
4268 cpu->Reg[15] += cpu->GetInstructionSize();
4269 INC_PC(sizeof(umaal_inst));
4270 FETCH_INST;
4271 GOTO_NEXT_INST;
4272}
4273UMLAL_INST : {
4274 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4275 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
4276 unsigned long long int rm = RM;
4277 unsigned long long int rs = RS;
4278 unsigned long long int rst = rm * rs;
4279 unsigned long long int add = ((unsigned long long)RDHI) << 32;
4280 add += RDLO;
4281 rst += add;
4282 RDLO = BITS(rst, 0, 31);
4283 RDHI = BITS(rst, 32, 63);
4284
4285 if (inst_cream->S) {
4286 cpu->NFlag = BIT(RDHI, 31);
4287 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
4288 }
4289 }
4290 cpu->Reg[15] += cpu->GetInstructionSize();
4291 INC_PC(sizeof(umlal_inst));
4292 FETCH_INST;
4293 GOTO_NEXT_INST;
4294}
4295UMULL_INST : {
4296 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4297 umull_inst* inst_cream = (umull_inst*)inst_base->component;
4298 unsigned long long int rm = RM;
4299 unsigned long long int rs = RS;
4300 unsigned long long int rst = rm * rs;
4301 RDHI = BITS(rst, 32, 63);
4302 RDLO = BITS(rst, 0, 31);
4303
4304 if (inst_cream->S) {
4305 cpu->NFlag = BIT(RDHI, 31);
4306 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
4307 }
4099 } 4308 }
4309 cpu->Reg[15] += cpu->GetInstructionSize();
4310 INC_PC(sizeof(umull_inst));
4311 FETCH_INST;
4312 GOTO_NEXT_INST;
4313}
4314B_2_THUMB : {
4315 b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component;
4316 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
4317 INC_PC(sizeof(b_2_thumb));
4318 goto DISPATCH;
4319}
4320B_COND_THUMB : {
4321 b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component;
4100 4322
4101 USAD8_INST: 4323 if (CondPassed(cpu, inst_cream->cond))
4102 USADA8_INST: 4324 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
4103 { 4325 else
4104 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4326 cpu->Reg[15] += 2;
4105 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4106 4327
4107 const u8 ra_idx = inst_cream->Ra; 4328 INC_PC(sizeof(b_cond_thumb));
4108 const u32 rm_val = RM; 4329 goto DISPATCH;
4109 const u32 rn_val = RN; 4330}
4331BL_1_THUMB : {
4332 bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component;
4333 cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm;
4334 cpu->Reg[15] += cpu->GetInstructionSize();
4335 INC_PC(sizeof(bl_1_thumb));
4336 FETCH_INST;
4337 GOTO_NEXT_INST;
4338}
4339BL_2_THUMB : {
4340 bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component;
4341 int tmp = ((cpu->Reg[15] + 2) | 1);
4342 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm);
4343 cpu->Reg[14] = tmp;
4344 INC_PC(sizeof(bl_2_thumb));
4345 goto DISPATCH;
4346}
4347BLX_1_THUMB : {
4348 // BLX 1 for armv5t and above
4349 u32 tmp = cpu->Reg[15];
4350 blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component;
4351 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC;
4352 cpu->Reg[14] = ((tmp + 2) | 1);
4353 cpu->TFlag = 0;
4354 INC_PC(sizeof(blx_1_thumb));
4355 goto DISPATCH;
4356}
4110 4357
4111 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF); 4358UQADD8_INST:
4112 const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF); 4359UQADD16_INST:
4113 const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF); 4360UQADDSUBX_INST:
4114 const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF); 4361UQSUB8_INST:
4362UQSUB16_INST:
4363UQSUBADDX_INST : {
4364 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4365 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4366
4367 const u8 op2 = inst_cream->op2;
4368 const u32 rm_val = RM;
4369 const u32 rn_val = RN;
4370
4371 u16 lo_val = 0;
4372 u16 hi_val = 0;
4373
4374 // UQADD16
4375 if (op2 == 0x00) {
4376 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
4377 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4378 }
4379 // UQASX
4380 else if (op2 == 0x01) {
4381 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4382 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
4383 }
4384 // UQSAX
4385 else if (op2 == 0x02) {
4386 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4387 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
4388 }
4389 // UQSUB16
4390 else if (op2 == 0x03) {
4391 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF);
4392 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4393 }
4394 // UQADD8
4395 else if (op2 == 0x04) {
4396 lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) |
4397 ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8;
4398 hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) |
4399 ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8;
4400 }
4401 // UQSUB8
4402 else {
4403 lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) |
4404 ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8;
4405 hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) |
4406 ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8;
4407 }
4408
4409 RD = ((lo_val & 0xFFFF) | hi_val << 16);
4410 }
4115 4411
4116 u32 finalDif = (diff1 + diff2 + diff3 + diff4); 4412 cpu->Reg[15] += cpu->GetInstructionSize();
4413 INC_PC(sizeof(generic_arm_inst));
4414 FETCH_INST;
4415 GOTO_NEXT_INST;
4416}
4117 4417
4118 // Op is USADA8 if true. 4418USAD8_INST:
4119 if (ra_idx != 15) 4419USADA8_INST : {
4120 finalDif += cpu->Reg[ra_idx]; 4420 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4421 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4121 4422
4122 RD = finalDif; 4423 const u8 ra_idx = inst_cream->Ra;
4123 } 4424 const u32 rm_val = RM;
4425 const u32 rn_val = RN;
4426
4427 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
4428 const u8 diff2 =
4429 ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
4430 const u8 diff3 =
4431 ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
4432 const u8 diff4 =
4433 ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
4124 4434
4125 cpu->Reg[15] += cpu->GetInstructionSize(); 4435 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
4126 INC_PC(sizeof(generic_arm_inst)); 4436
4127 FETCH_INST; 4437 // Op is USADA8 if true.
4128 GOTO_NEXT_INST; 4438 if (ra_idx != 15)
4439 finalDif += cpu->Reg[ra_idx];
4440
4441 RD = finalDif;
4129 } 4442 }
4130 4443
4131 USAT_INST: 4444 cpu->Reg[15] += cpu->GetInstructionSize();
4132 { 4445 INC_PC(sizeof(generic_arm_inst));
4133 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4446 FETCH_INST;
4134 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; 4447 GOTO_NEXT_INST;
4448}
4135 4449
4136 u8 shift_type = inst_cream->shift_type; 4450USAT_INST : {
4137 u8 shift_amount = inst_cream->imm5; 4451 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4138 u32 rn_val = RN; 4452 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
4139 4453
4140 // 32-bit ASR is encoded as an amount of 0. 4454 u8 shift_type = inst_cream->shift_type;
4141 if (shift_type == 1 && shift_amount == 0) 4455 u8 shift_amount = inst_cream->imm5;
4142 shift_amount = 31; 4456 u32 rn_val = RN;
4143 4457
4144 if (shift_type == 0) 4458 // 32-bit ASR is encoded as an amount of 0.
4145 rn_val <<= shift_amount; 4459 if (shift_type == 1 && shift_amount == 0)
4146 else if (shift_type == 1) 4460 shift_amount = 31;
4147 rn_val = ((s32)rn_val >> shift_amount);
4148 4461
4149 bool saturated = false; 4462 if (shift_type == 0)
4150 rn_val = ARMul_UnsignedSatQ(rn_val, inst_cream->sat_imm, &saturated); 4463 rn_val <<= shift_amount;
4464 else if (shift_type == 1)
4465 rn_val = ((s32)rn_val >> shift_amount);
4151 4466
4152 if (saturated) 4467 bool saturated = false;
4153 cpu->Cpsr |= (1 << 27); 4468 rn_val = ARMul_UnsignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
4154 4469
4155 RD = rn_val; 4470 if (saturated)
4156 } 4471 cpu->Cpsr |= (1 << 27);
4157 4472
4158 cpu->Reg[15] += cpu->GetInstructionSize(); 4473 RD = rn_val;
4159 INC_PC(sizeof(ssat_inst));
4160 FETCH_INST;
4161 GOTO_NEXT_INST;
4162 } 4474 }
4163 4475
4164 USAT16_INST: 4476 cpu->Reg[15] += cpu->GetInstructionSize();
4165 { 4477 INC_PC(sizeof(ssat_inst));
4166 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4478 FETCH_INST;
4167 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; 4479 GOTO_NEXT_INST;
4168 const u8 saturate_to = inst_cream->sat_imm; 4480}
4169 4481
4170 bool sat1 = false; 4482USAT16_INST : {
4171 bool sat2 = false; 4483 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4484 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
4485 const u8 saturate_to = inst_cream->sat_imm;
4172 4486
4173 RD = (ARMul_UnsignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) | 4487 bool sat1 = false;
4174 ARMul_UnsignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16; 4488 bool sat2 = false;
4175 4489
4176 if (sat1 || sat2) 4490 RD = (ARMul_UnsignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) |
4177 cpu->Cpsr |= (1 << 27); 4491 ARMul_UnsignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16;
4178 }
4179 4492
4180 cpu->Reg[15] += cpu->GetInstructionSize(); 4493 if (sat1 || sat2)
4181 INC_PC(sizeof(ssat_inst)); 4494 cpu->Cpsr |= (1 << 27);
4182 FETCH_INST;
4183 GOTO_NEXT_INST;
4184 } 4495 }
4185 4496
4186 UXTAB16_INST: 4497 cpu->Reg[15] += cpu->GetInstructionSize();
4187 UXTB16_INST: 4498 INC_PC(sizeof(ssat_inst));
4188 { 4499 FETCH_INST;
4189 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4500 GOTO_NEXT_INST;
4190 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component; 4501}
4191 4502
4192 const u8 rn_idx = inst_cream->Rn; 4503UXTAB16_INST:
4193 const u32 rm_val = RM; 4504UXTB16_INST : {
4194 const u32 rotation = inst_cream->rotate * 8; 4505 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4195 const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); 4506 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
4196 4507
4197 // UXTB16, otherwise UXTAB16 4508 const u8 rn_idx = inst_cream->Rn;
4198 if (rn_idx == 15) { 4509 const u32 rm_val = RM;
4199 RD = rotated_rm & 0x00FF00FF; 4510 const u32 rotation = inst_cream->rotate * 8;
4200 } else { 4511 const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
4201 const u32 rn_val = RN;
4202 const u8 lo_rotated = (rotated_rm & 0xFF);
4203 const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
4204 const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
4205 const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
4206 4512
4207 RD = ((hi_result << 16) | (lo_result & 0xFFFF)); 4513 // UXTB16, otherwise UXTAB16
4208 } 4514 if (rn_idx == 15) {
4209 } 4515 RD = rotated_rm & 0x00FF00FF;
4516 } else {
4517 const u32 rn_val = RN;
4518 const u8 lo_rotated = (rotated_rm & 0xFF);
4519 const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
4520 const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
4521 const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
4210 4522
4211 cpu->Reg[15] += cpu->GetInstructionSize(); 4523 RD = ((hi_result << 16) | (lo_result & 0xFFFF));
4212 INC_PC(sizeof(uxtab_inst)); 4524 }
4213 FETCH_INST;
4214 GOTO_NEXT_INST;
4215 } 4525 }
4216 4526
4217 WFE_INST: 4527 cpu->Reg[15] += cpu->GetInstructionSize();
4218 { 4528 INC_PC(sizeof(uxtab_inst));
4219 // Stubbed, as WFE is a hint instruction. 4529 FETCH_INST;
4220 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4530 GOTO_NEXT_INST;
4221 LOG_TRACE(Core_ARM11, "WFE executed."); 4531}
4222 }
4223 4532
4224 cpu->Reg[15] += cpu->GetInstructionSize(); 4533WFE_INST : {
4225 INC_PC_STUB; 4534 // Stubbed, as WFE is a hint instruction.
4226 FETCH_INST; 4535 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4227 GOTO_NEXT_INST; 4536 LOG_TRACE(Core_ARM11, "WFE executed.");
4228 } 4537 }
4229 4538
4230 WFI_INST: 4539 cpu->Reg[15] += cpu->GetInstructionSize();
4231 { 4540 INC_PC_STUB;
4232 // Stubbed, as WFI is a hint instruction. 4541 FETCH_INST;
4233 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4542 GOTO_NEXT_INST;
4234 LOG_TRACE(Core_ARM11, "WFI executed."); 4543}
4235 }
4236 4544
4237 cpu->Reg[15] += cpu->GetInstructionSize(); 4545WFI_INST : {
4238 INC_PC_STUB; 4546 // Stubbed, as WFI is a hint instruction.
4239 FETCH_INST; 4547 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4240 GOTO_NEXT_INST; 4548 LOG_TRACE(Core_ARM11, "WFI executed.");
4241 } 4549 }
4242 4550
4243 YIELD_INST: 4551 cpu->Reg[15] += cpu->GetInstructionSize();
4244 { 4552 INC_PC_STUB;
4245 // Stubbed, as YIELD is a hint instruction. 4553 FETCH_INST;
4246 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4554 GOTO_NEXT_INST;
4247 LOG_TRACE(Core_ARM11, "YIELD executed."); 4555}
4248 }
4249 4556
4250 cpu->Reg[15] += cpu->GetInstructionSize(); 4557YIELD_INST : {
4251 INC_PC_STUB; 4558 // Stubbed, as YIELD is a hint instruction.
4252 FETCH_INST; 4559 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4253 GOTO_NEXT_INST; 4560 LOG_TRACE(Core_ARM11, "YIELD executed.");
4254 } 4561 }
4255 4562
4256 #define VFP_INTERPRETER_IMPL 4563 cpu->Reg[15] += cpu->GetInstructionSize();
4257 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 4564 INC_PC_STUB;
4258 #undef VFP_INTERPRETER_IMPL 4565 FETCH_INST;
4566 GOTO_NEXT_INST;
4567}
4259 4568
4260 END: 4569#define VFP_INTERPRETER_IMPL
4261 { 4570#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
4262 SAVE_NZCVT; 4571#undef VFP_INTERPRETER_IMPL
4263 cpu->NumInstrsToExecute = 0; 4572
4264 return num_instrs; 4573END : {
4265 } 4574 SAVE_NZCVT;
4266 INIT_INST_LENGTH: 4575 cpu->NumInstrsToExecute = 0;
4267 { 4576 return num_instrs;
4268 cpu->NumInstrsToExecute = 0; 4577}
4269 return num_instrs; 4578INIT_INST_LENGTH : {
4270 } 4579 cpu->NumInstrsToExecute = 0;
4580 return num_instrs;
4581}
4271} 4582}
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
index 3576370d1..2a3dd0f53 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
@@ -21,50 +21,48 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
21 *ainstr = 0xDEADC0DE; // Debugging to catch non updates 21 *ainstr = 0xDEADC0DE; // Debugging to catch non updates
22 22
23 switch ((tinstr & 0xF800) >> 11) { 23 switch ((tinstr & 0xF800) >> 11) {
24 case 0: // LSL 24 case 0: // LSL
25 case 1: // LSR 25 case 1: // LSR
26 case 2: // ASR 26 case 2: // ASR
27 *ainstr = 0xE1B00000 // base opcode 27 *ainstr = 0xE1B00000 // base opcode
28 | ((tinstr & 0x1800) >> (11 - 5)) // shift type 28 | ((tinstr & 0x1800) >> (11 - 5)) // shift type
29 |((tinstr & 0x07C0) << (7 - 6)) // imm5 29 | ((tinstr & 0x07C0) << (7 - 6)) // imm5
30 |((tinstr & 0x0038) >> 3) // Rs 30 | ((tinstr & 0x0038) >> 3) // Rs
31 |((tinstr & 0x0007) << 12); // Rd 31 | ((tinstr & 0x0007) << 12); // Rd
32 break; 32 break;
33 33
34 case 3: // ADD/SUB 34 case 3: // ADD/SUB
35 { 35 {
36 static const u32 subset[4] = { 36 static const u32 subset[4] = {
37 0xE0900000, // ADDS Rd,Rs,Rn 37 0xE0900000, // ADDS Rd,Rs,Rn
38 0xE0500000, // SUBS Rd,Rs,Rn 38 0xE0500000, // SUBS Rd,Rs,Rn
39 0xE2900000, // ADDS Rd,Rs,#imm3 39 0xE2900000, // ADDS Rd,Rs,#imm3
40 0xE2500000 // SUBS Rd,Rs,#imm3 40 0xE2500000 // SUBS Rd,Rs,#imm3
41 }; 41 };
42 // It is quicker indexing into a table, than performing switch or conditionals: 42 // It is quicker indexing into a table, than performing switch or conditionals:
43 *ainstr = subset[(tinstr & 0x0600) >> 9] // base opcode 43 *ainstr = subset[(tinstr & 0x0600) >> 9] // base opcode
44 |((tinstr & 0x01C0) >> 6) // Rn or imm3 44 | ((tinstr & 0x01C0) >> 6) // Rn or imm3
45 |((tinstr & 0x0038) << (16 - 3)) // Rs 45 | ((tinstr & 0x0038) << (16 - 3)) // Rs
46 |((tinstr & 0x0007) << (12 - 0)); // Rd 46 | ((tinstr & 0x0007) << (12 - 0)); // Rd
47 } 47 } break;
48 break;
49 48
50 case 4: // MOV 49 case 4: // MOV
51 case 5: // CMP 50 case 5: // CMP
52 case 6: // ADD 51 case 6: // ADD
53 case 7: // SUB 52 case 7: // SUB
54 { 53 {
55 static const u32 subset[4] = { 54 static const u32 subset[4] = {
56 0xE3B00000, // MOVS Rd,#imm8 55 0xE3B00000, // MOVS Rd,#imm8
57 0xE3500000, // CMP Rd,#imm8 56 0xE3500000, // CMP Rd,#imm8
58 0xE2900000, // ADDS Rd,Rd,#imm8 57 0xE2900000, // ADDS Rd,Rd,#imm8
59 0xE2500000, // SUBS Rd,Rd,#imm8 58 0xE2500000, // SUBS Rd,Rd,#imm8
60 }; 59 };
61 60
62 *ainstr = subset[(tinstr & 0x1800) >> 11] // base opcode 61 *ainstr = subset[(tinstr & 0x1800) >> 11] // base opcode
63 |((tinstr & 0x00FF) >> 0) // imm8 62 | ((tinstr & 0x00FF) >> 0) // imm8
64 |((tinstr & 0x0700) << (16 - 8)) // Rn 63 | ((tinstr & 0x0700) << (16 - 8)) // Rn
65 |((tinstr & 0x0700) << (12 - 8)); // Rd 64 | ((tinstr & 0x0700) << (12 - 8)); // Rd
66 } 65 } break;
67 break;
68 66
69 case 8: // Arithmetic and high register transfers 67 case 8: // Arithmetic and high register transfers
70 68
@@ -73,56 +71,51 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
73 // large subset 71 // large subset
74 72
75 if ((tinstr & (1 << 10)) == 0) { 73 if ((tinstr & (1 << 10)) == 0) {
76 enum otype { 74 enum otype { t_norm, t_shift, t_neg, t_mul };
77 t_norm,
78 t_shift,
79 t_neg,
80 t_mul
81 };
82 75
83 static const struct { 76 static const struct {
84 u32 opcode; 77 u32 opcode;
85 otype type; 78 otype type;
86 } subset[16] = { 79 } subset[16] = {
87 { 0xE0100000, t_norm }, // ANDS Rd,Rd,Rs 80 {0xE0100000, t_norm}, // ANDS Rd,Rd,Rs
88 { 0xE0300000, t_norm }, // EORS Rd,Rd,Rs 81 {0xE0300000, t_norm}, // EORS Rd,Rd,Rs
89 { 0xE1B00010, t_shift }, // MOVS Rd,Rd,LSL Rs 82 {0xE1B00010, t_shift}, // MOVS Rd,Rd,LSL Rs
90 { 0xE1B00030, t_shift }, // MOVS Rd,Rd,LSR Rs 83 {0xE1B00030, t_shift}, // MOVS Rd,Rd,LSR Rs
91 { 0xE1B00050, t_shift }, // MOVS Rd,Rd,ASR Rs 84 {0xE1B00050, t_shift}, // MOVS Rd,Rd,ASR Rs
92 { 0xE0B00000, t_norm }, // ADCS Rd,Rd,Rs 85 {0xE0B00000, t_norm}, // ADCS Rd,Rd,Rs
93 { 0xE0D00000, t_norm }, // SBCS Rd,Rd,Rs 86 {0xE0D00000, t_norm}, // SBCS Rd,Rd,Rs
94 { 0xE1B00070, t_shift }, // MOVS Rd,Rd,ROR Rs 87 {0xE1B00070, t_shift}, // MOVS Rd,Rd,ROR Rs
95 { 0xE1100000, t_norm }, // TST Rd,Rs 88 {0xE1100000, t_norm}, // TST Rd,Rs
96 { 0xE2700000, t_neg }, // RSBS Rd,Rs,#0 89 {0xE2700000, t_neg}, // RSBS Rd,Rs,#0
97 { 0xE1500000, t_norm }, // CMP Rd,Rs 90 {0xE1500000, t_norm}, // CMP Rd,Rs
98 { 0xE1700000, t_norm }, // CMN Rd,Rs 91 {0xE1700000, t_norm}, // CMN Rd,Rs
99 { 0xE1900000, t_norm }, // ORRS Rd,Rd,Rs 92 {0xE1900000, t_norm}, // ORRS Rd,Rd,Rs
100 { 0xE0100090, t_mul }, // MULS Rd,Rd,Rs 93 {0xE0100090, t_mul}, // MULS Rd,Rd,Rs
101 { 0xE1D00000, t_norm }, // BICS Rd,Rd,Rs 94 {0xE1D00000, t_norm}, // BICS Rd,Rd,Rs
102 { 0xE1F00000, t_norm } // MVNS Rd,Rs 95 {0xE1F00000, t_norm} // MVNS Rd,Rs
103 }; 96 };
104 97
105 *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; // base 98 *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; // base
106 99
107 switch (subset[(tinstr & 0x03C0) >> 6].type) { 100 switch (subset[(tinstr & 0x03C0) >> 6].type) {
108 case t_norm: 101 case t_norm:
109 *ainstr |= ((tinstr & 0x0007) << 16) // Rn 102 *ainstr |= ((tinstr & 0x0007) << 16) // Rn
110 |((tinstr & 0x0007) << 12) // Rd 103 | ((tinstr & 0x0007) << 12) // Rd
111 |((tinstr & 0x0038) >> 3); // Rs 104 | ((tinstr & 0x0038) >> 3); // Rs
112 break; 105 break;
113 case t_shift: 106 case t_shift:
114 *ainstr |= ((tinstr & 0x0007) << 12) // Rd 107 *ainstr |= ((tinstr & 0x0007) << 12) // Rd
115 |((tinstr & 0x0007) >> 0) // Rm 108 | ((tinstr & 0x0007) >> 0) // Rm
116 |((tinstr & 0x0038) << (8 - 3)); // Rs 109 | ((tinstr & 0x0038) << (8 - 3)); // Rs
117 break; 110 break;
118 case t_neg: 111 case t_neg:
119 *ainstr |= ((tinstr & 0x0007) << 12) // Rd 112 *ainstr |= ((tinstr & 0x0007) << 12) // Rd
120 |((tinstr & 0x0038) << (16 - 3)); // Rn 113 | ((tinstr & 0x0038) << (16 - 3)); // Rn
121 break; 114 break;
122 case t_mul: 115 case t_mul:
123 *ainstr |= ((tinstr & 0x0007) << 16) // Rd 116 *ainstr |= ((tinstr & 0x0007) << 16) // Rd
124 |((tinstr & 0x0007) << 8) // Rs 117 | ((tinstr & 0x0007) << 8) // Rs
125 |((tinstr & 0x0038) >> 3); // Rm 118 | ((tinstr & 0x0038) >> 3); // Rm
126 break; 119 break;
127 } 120 }
128 } else { 121 } else {
@@ -133,109 +126,106 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
133 Rd += 8; 126 Rd += 8;
134 127
135 switch ((tinstr & 0x03C0) >> 6) { 128 switch ((tinstr & 0x03C0) >> 6) {
136 case 0x0: // ADD Rd,Rd,Rs 129 case 0x0: // ADD Rd,Rd,Rs
137 case 0x1: // ADD Rd,Rd,Hs 130 case 0x1: // ADD Rd,Rd,Hs
138 case 0x2: // ADD Hd,Hd,Rs 131 case 0x2: // ADD Hd,Hd,Rs
139 case 0x3: // ADD Hd,Hd,Hs 132 case 0x3: // ADD Hd,Hd,Hs
140 *ainstr = 0xE0800000 // base 133 *ainstr = 0xE0800000 // base
141 | (Rd << 16) // Rn 134 | (Rd << 16) // Rn
142 |(Rd << 12) // Rd 135 | (Rd << 12) // Rd
143 |(Rs << 0); // Rm 136 | (Rs << 0); // Rm
144 break; 137 break;
145 case 0x4: // CMP Rd,Rs 138 case 0x4: // CMP Rd,Rs
146 case 0x5: // CMP Rd,Hs 139 case 0x5: // CMP Rd,Hs
147 case 0x6: // CMP Hd,Rs 140 case 0x6: // CMP Hd,Rs
148 case 0x7: // CMP Hd,Hs 141 case 0x7: // CMP Hd,Hs
149 *ainstr = 0xE1500000 // base 142 *ainstr = 0xE1500000 // base
150 | (Rd << 16) // Rn 143 | (Rd << 16) // Rn
151 |(Rs << 0); // Rm 144 | (Rs << 0); // Rm
152 break; 145 break;
153 case 0x8: // MOV Rd,Rs 146 case 0x8: // MOV Rd,Rs
154 case 0x9: // MOV Rd,Hs 147 case 0x9: // MOV Rd,Hs
155 case 0xA: // MOV Hd,Rs 148 case 0xA: // MOV Hd,Rs
156 case 0xB: // MOV Hd,Hs 149 case 0xB: // MOV Hd,Hs
157 *ainstr = 0xE1A00000 // base 150 *ainstr = 0xE1A00000 // base
158 |(Rd << 12) // Rd 151 | (Rd << 12) // Rd
159 |(Rs << 0); // Rm 152 | (Rs << 0); // Rm
160 break; 153 break;
161 case 0xC: // BX Rs 154 case 0xC: // BX Rs
162 case 0xD: // BX Hs 155 case 0xD: // BX Hs
163 *ainstr = 0xE12FFF10 // base 156 *ainstr = 0xE12FFF10 // base
164 | ((tinstr & 0x0078) >> 3); // Rd 157 | ((tinstr & 0x0078) >> 3); // Rd
165 break; 158 break;
166 case 0xE: // BLX 159 case 0xE: // BLX
167 case 0xF: // BLX 160 case 0xF: // BLX
168 *ainstr = 0xE1200030 // base 161 *ainstr = 0xE1200030 // base
169 | (Rs << 0); // Rm 162 | (Rs << 0); // Rm
170 break; 163 break;
171 } 164 }
172 } 165 }
173 break; 166 break;
174 167
175 case 9: // LDR Rd,[PC,#imm8] 168 case 9: // LDR Rd,[PC,#imm8]
176 *ainstr = 0xE59F0000 // base 169 *ainstr = 0xE59F0000 // base
177 | ((tinstr & 0x0700) << (12 - 8)) // Rd 170 | ((tinstr & 0x0700) << (12 - 8)) // Rd
178 |((tinstr & 0x00FF) << (2 - 0)); // off8 171 | ((tinstr & 0x00FF) << (2 - 0)); // off8
179 break; 172 break;
180 173
181 case 10: 174 case 10:
182 case 11: 175 case 11: {
183 { 176 static const u32 subset[8] = {
184 static const u32 subset[8] = { 177 0xE7800000, // STR Rd,[Rb,Ro]
185 0xE7800000, // STR Rd,[Rb,Ro] 178 0xE18000B0, // STRH Rd,[Rb,Ro]
186 0xE18000B0, // STRH Rd,[Rb,Ro] 179 0xE7C00000, // STRB Rd,[Rb,Ro]
187 0xE7C00000, // STRB Rd,[Rb,Ro] 180 0xE19000D0, // LDRSB Rd,[Rb,Ro]
188 0xE19000D0, // LDRSB Rd,[Rb,Ro] 181 0xE7900000, // LDR Rd,[Rb,Ro]
189 0xE7900000, // LDR Rd,[Rb,Ro] 182 0xE19000B0, // LDRH Rd,[Rb,Ro]
190 0xE19000B0, // LDRH Rd,[Rb,Ro] 183 0xE7D00000, // LDRB Rd,[Rb,Ro]
191 0xE7D00000, // LDRB Rd,[Rb,Ro] 184 0xE19000F0 // LDRSH Rd,[Rb,Ro]
192 0xE19000F0 // LDRSH Rd,[Rb,Ro] 185 };
193 }; 186
194 187 *ainstr = subset[(tinstr & 0xE00) >> 9] // base
195 *ainstr = subset[(tinstr & 0xE00) >> 9] // base 188 | ((tinstr & 0x0007) << (12 - 0)) // Rd
196 |((tinstr & 0x0007) << (12 - 0)) // Rd 189 | ((tinstr & 0x0038) << (16 - 3)) // Rb
197 |((tinstr & 0x0038) << (16 - 3)) // Rb 190 | ((tinstr & 0x01C0) >> 6); // Ro
198 |((tinstr & 0x01C0) >> 6); // Ro 191 } break;
199 }
200 break;
201 192
202 case 12: // STR Rd,[Rb,#imm5] 193 case 12: // STR Rd,[Rb,#imm5]
203 case 13: // LDR Rd,[Rb,#imm5] 194 case 13: // LDR Rd,[Rb,#imm5]
204 case 14: // STRB Rd,[Rb,#imm5] 195 case 14: // STRB Rd,[Rb,#imm5]
205 case 15: // LDRB Rd,[Rb,#imm5] 196 case 15: // LDRB Rd,[Rb,#imm5]
206 { 197 {
207 static const u32 subset[4] = { 198 static const u32 subset[4] = {
208 0xE5800000, // STR Rd,[Rb,#imm5] 199 0xE5800000, // STR Rd,[Rb,#imm5]
209 0xE5900000, // LDR Rd,[Rb,#imm5] 200 0xE5900000, // LDR Rd,[Rb,#imm5]
210 0xE5C00000, // STRB Rd,[Rb,#imm5] 201 0xE5C00000, // STRB Rd,[Rb,#imm5]
211 0xE5D00000 // LDRB Rd,[Rb,#imm5] 202 0xE5D00000 // LDRB Rd,[Rb,#imm5]
212 }; 203 };
213 // The offset range defends on whether we are transferring a byte or word value: 204 // The offset range defends on whether we are transferring a byte or word value:
214 *ainstr = subset[(tinstr & 0x1800) >> 11] // base 205 *ainstr = subset[(tinstr & 0x1800) >> 11] // base
215 |((tinstr & 0x0007) << (12 - 0)) // Rd 206 | ((tinstr & 0x0007) << (12 - 0)) // Rd
216 |((tinstr & 0x0038) << (16 - 3)) // Rb 207 | ((tinstr & 0x0038) << (16 - 3)) // Rb
217 |((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); // off5 208 | ((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); // off5
218 } 209 } break;
210
211 case 16: // STRH Rd,[Rb,#imm5]
212 case 17: // LDRH Rd,[Rb,#imm5]
213 *ainstr = ((tinstr & (1 << 11)) // base
214 ? 0xE1D000B0 // LDRH
215 : 0xE1C000B0) // STRH
216 | ((tinstr & 0x0007) << (12 - 0)) // Rd
217 | ((tinstr & 0x0038) << (16 - 3)) // Rb
218 | ((tinstr & 0x01C0) >> (6 - 1)) // off5, low nibble
219 | ((tinstr & 0x0600) >> (9 - 8)); // off5, high nibble
219 break; 220 break;
220 221
221 case 16: // STRH Rd,[Rb,#imm5] 222 case 18: // STR Rd,[SP,#imm8]
222 case 17: // LDRH Rd,[Rb,#imm5] 223 case 19: // LDR Rd,[SP,#imm8]
223 *ainstr = ((tinstr & (1 << 11)) // base 224 *ainstr = ((tinstr & (1 << 11)) // base
224 ? 0xE1D000B0 // LDRH 225 ? 0xE59D0000 // LDR
225 : 0xE1C000B0) // STRH 226 : 0xE58D0000) // STR
226 |((tinstr & 0x0007) << (12 - 0)) // Rd 227 | ((tinstr & 0x0700) << (12 - 8)) // Rd
227 |((tinstr & 0x0038) << (16 - 3)) // Rb 228 | ((tinstr & 0x00FF) << 2); // off8
228 |((tinstr & 0x01C0) >> (6 - 1)) // off5, low nibble
229 |((tinstr & 0x0600) >> (9 - 8)); // off5, high nibble
230 break;
231
232 case 18: // STR Rd,[SP,#imm8]
233 case 19: // LDR Rd,[SP,#imm8]
234 *ainstr = ((tinstr & (1 << 11)) // base
235 ? 0xE59D0000 // LDR
236 : 0xE58D0000) // STR
237 |((tinstr & 0x0700) << (12 - 8)) // Rd
238 |((tinstr & 0x00FF) << 2); // off8
239 break; 229 break;
240 230
241 case 20: // ADD Rd,PC,#imm8 231 case 20: // ADD Rd,PC,#imm8
@@ -246,14 +236,15 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
246 // NOTE: The PC value used here should by word aligned. We encode shift-left-by-2 in the 236 // NOTE: The PC value used here should by word aligned. We encode shift-left-by-2 in the
247 // rotate immediate field, so no shift of off8 is needed. 237 // rotate immediate field, so no shift of off8 is needed.
248 238
249 *ainstr = 0xE28F0F00 // base 239 *ainstr = 0xE28F0F00 // base
250 | ((tinstr & 0x0700) << (12 - 8)) // Rd 240 | ((tinstr & 0x0700) << (12 - 8)) // Rd
251 |(tinstr & 0x00FF); // off8 241 | (tinstr & 0x00FF); // off8
252 } else { 242 } else {
253 // We encode shift-left-by-2 in the rotate immediate field, so no shift of off8 is needed. 243 // We encode shift-left-by-2 in the rotate immediate field, so no shift of off8 is
254 *ainstr = 0xE28D0F00 // base 244 // needed.
255 | ((tinstr & 0x0700) << (12 - 8)) // Rd 245 *ainstr = 0xE28D0F00 // base
256 |(tinstr & 0x00FF); // off8 246 | ((tinstr & 0x0700) << (12 - 8)) // Rd
247 | (tinstr & 0x00FF); // off8
257 } 248 }
258 break; 249 break;
259 250
@@ -261,15 +252,15 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
261 case 23: 252 case 23:
262 if ((tinstr & 0x0F00) == 0x0000) { 253 if ((tinstr & 0x0F00) == 0x0000) {
263 // NOTE: The instruction contains a shift left of 2 equivalent (implemented as ROR #30): 254 // NOTE: The instruction contains a shift left of 2 equivalent (implemented as ROR #30):
264 *ainstr = ((tinstr & (1 << 7)) // base 255 *ainstr = ((tinstr & (1 << 7)) // base
265 ? 0xE24DDF00 // SUB 256 ? 0xE24DDF00 // SUB
266 : 0xE28DDF00) // ADD 257 : 0xE28DDF00) // ADD
267 |(tinstr & 0x007F); // off7 258 | (tinstr & 0x007F); // off7
268 } else if ((tinstr & 0x0F00) == 0x0e00) { 259 } else if ((tinstr & 0x0F00) == 0x0e00) {
269 // BKPT 260 // BKPT
270 *ainstr = 0xEF000000 // base 261 *ainstr = 0xEF000000 // base
271 | BITS(tinstr, 0, 3) // imm4 field; 262 | BITS(tinstr, 0, 3) // imm4 field;
272 | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12 263 | (BITS(tinstr, 4, 7) << 8); // beginning 4 bits of imm12
273 } else if ((tinstr & 0x0F00) == 0x0200) { 264 } else if ((tinstr & 0x0F00) == 0x0200) {
274 static const u32 subset[4] = { 265 static const u32 subset[4] = {
275 0xE6BF0070, // SXTH 266 0xE6BF0070, // SXTH
@@ -278,21 +269,21 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
278 0xE6EF0070, // UXTB 269 0xE6EF0070, // UXTB
279 }; 270 };
280 271
281 *ainstr = subset[BITS(tinstr, 6, 7)] // base 272 *ainstr = subset[BITS(tinstr, 6, 7)] // base
282 | (BITS(tinstr, 0, 2) << 12) // Rd 273 | (BITS(tinstr, 0, 2) << 12) // Rd
283 | BITS(tinstr, 3, 5); // Rm 274 | BITS(tinstr, 3, 5); // Rm
284 } else if ((tinstr & 0x0F00) == 0x600) { 275 } else if ((tinstr & 0x0F00) == 0x600) {
285 if (BIT(tinstr, 5) == 0) { 276 if (BIT(tinstr, 5) == 0) {
286 // SETEND 277 // SETEND
287 *ainstr = 0xF1010000 // base 278 *ainstr = 0xF1010000 // base
288 | (BIT(tinstr, 3) << 9); // endian specifier 279 | (BIT(tinstr, 3) << 9); // endian specifier
289 } else { 280 } else {
290 // CPS 281 // CPS
291 *ainstr = 0xF1080000 // base 282 *ainstr = 0xF1080000 // base
292 | (BIT(tinstr, 0) << 6) // fiq bit 283 | (BIT(tinstr, 0) << 6) // fiq bit
293 | (BIT(tinstr, 1) << 7) // irq bit 284 | (BIT(tinstr, 1) << 7) // irq bit
294 | (BIT(tinstr, 2) << 8) // abort bit 285 | (BIT(tinstr, 2) << 8) // abort bit
295 | (BIT(tinstr, 4) << 18); // enable bit 286 | (BIT(tinstr, 4) << 18); // enable bit
296 } 287 }
297 } else if ((tinstr & 0x0F00) == 0x0a00) { 288 } else if ((tinstr & 0x0F00) == 0x0a00) {
298 static const u32 subset[4] = { 289 static const u32 subset[4] = {
@@ -307,9 +298,9 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
307 if (subset_index == 2) { 298 if (subset_index == 2) {
308 valid = ThumbDecodeStatus::UNDEFINED; 299 valid = ThumbDecodeStatus::UNDEFINED;
309 } else { 300 } else {
310 *ainstr = subset[subset_index] // base 301 *ainstr = subset[subset_index] // base
311 | (BITS(tinstr, 0, 2) << 12) // Rd 302 | (BITS(tinstr, 0, 2) << 12) // Rd
312 | BITS(tinstr, 3, 5); // Rm 303 | BITS(tinstr, 3, 5); // Rm
313 } 304 }
314 } else { 305 } else {
315 static const u32 subset[4] = { 306 static const u32 subset[4] = {
@@ -319,14 +310,13 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
319 0xE8BD8000 // LDMIA sp!,{rlist,pc} 310 0xE8BD8000 // LDMIA sp!,{rlist,pc}
320 }; 311 };
321 *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] // base 312 *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] // base
322 |(tinstr & 0x00FF); // mask8 313 | (tinstr & 0x00FF); // mask8
323 } 314 }
324 break; 315 break;
325 316
326 case 24: // STMIA 317 case 24: // STMIA
327 case 25: // LDMIA 318 case 25: // LDMIA
328 if (tinstr & (1 << 11)) 319 if (tinstr & (1 << 11)) {
329 {
330 unsigned int base = 0xE8900000; 320 unsigned int base = 0xE8900000;
331 unsigned int rn = BITS(tinstr, 8, 10); 321 unsigned int rn = BITS(tinstr, 8, 10);
332 322
@@ -334,15 +324,13 @@ ThumbDecodeStatus TranslateThumbInstruction(u32 addr, u32 instr, u32* ainstr, u3
334 if ((tinstr & (1 << rn)) == 0) 324 if ((tinstr & (1 << rn)) == 0)
335 base |= (1 << 21); 325 base |= (1 << 21);
336 326
337 *ainstr = base // base (LDMIA) 327 *ainstr = base // base (LDMIA)
338 | (rn << 16) // Rn 328 | (rn << 16) // Rn
339 | (tinstr & 0x00FF); // Register list 329 | (tinstr & 0x00FF); // Register list
340 } 330 } else {
341 else 331 *ainstr = 0xE8A00000 // base (STMIA)
342 { 332 | (BITS(tinstr, 8, 10) << 16) // Rn
343 *ainstr = 0xE8A00000 // base (STMIA) 333 | (tinstr & 0x00FF); // Register list
344 | (BITS(tinstr, 8, 10) << 16) // Rn
345 | (tinstr & 0x00FF); // Register list
346 } 334 }
347 break; 335 break;
348 336
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.h b/src/core/arm/dyncom/arm_dyncom_thumb.h
index c1be3c735..231e48aa4 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.h
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.h
@@ -29,9 +29,9 @@
29#include "common/common_types.h" 29#include "common/common_types.h"
30 30
31enum class ThumbDecodeStatus { 31enum class ThumbDecodeStatus {
32 UNDEFINED, // Undefined Thumb instruction 32 UNDEFINED, // Undefined Thumb instruction
33 DECODED, // Instruction decoded to ARM equivalent 33 DECODED, // Instruction decoded to ARM equivalent
34 BRANCH, // Thumb branch (already processed) 34 BRANCH, // Thumb branch (already processed)
35 UNINITIALIZED, 35 UNINITIALIZED,
36}; 36};
37 37
diff --git a/src/core/arm/dyncom/arm_dyncom_trans.cpp b/src/core/arm/dyncom/arm_dyncom_trans.cpp
index 00b42c246..e056d890c 100644
--- a/src/core/arm/dyncom/arm_dyncom_trans.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_trans.cpp
@@ -19,24 +19,23 @@ static void* AllocBuffer(size_t size) {
19 return static_cast<void*>(&trans_cache_buf[start]); 19 return static_cast<void*>(&trans_cache_buf[start]);
20} 20}
21 21
22#define glue(x, y) x ## y 22#define glue(x, y) x##y
23#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s) 23#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s)
24 24
25shtop_fp_t GetShifterOp(unsigned int inst); 25shtop_fp_t GetShifterOp(unsigned int inst);
26get_addr_fp_t GetAddressingOp(unsigned int inst); 26get_addr_fp_t GetAddressingOp(unsigned int inst);
27get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst); 27get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst);
28 28
29static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) 29static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) {
30{ 30 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst));
31 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst)); 31 adc_inst* inst_cream = (adc_inst*)inst_base->component;
32 adc_inst *inst_cream = (adc_inst *)inst_base->component;
33 32
34 inst_base->cond = BITS(inst, 28, 31); 33 inst_base->cond = BITS(inst, 28, 31);
35 inst_base->idx = index; 34 inst_base->idx = index;
36 inst_base->br = TransExtData::NON_BRANCH; 35 inst_base->br = TransExtData::NON_BRANCH;
37 36
38 inst_cream->I = BIT(inst, 25); 37 inst_cream->I = BIT(inst, 25);
39 inst_cream->S = BIT(inst, 20); 38 inst_cream->S = BIT(inst, 20);
40 inst_cream->Rn = BITS(inst, 16, 19); 39 inst_cream->Rn = BITS(inst, 16, 19);
41 inst_cream->Rd = BITS(inst, 12, 15); 40 inst_cream->Rd = BITS(inst, 12, 15);
42 inst_cream->shifter_operand = BITS(inst, 0, 11); 41 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -47,17 +46,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index)
47 46
48 return inst_base; 47 return inst_base;
49} 48}
50static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) 49static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) {
51{ 50 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst));
52 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst)); 51 add_inst* inst_cream = (add_inst*)inst_base->component;
53 add_inst *inst_cream = (add_inst *)inst_base->component;
54 52
55 inst_base->cond = BITS(inst, 28, 31); 53 inst_base->cond = BITS(inst, 28, 31);
56 inst_base->idx = index; 54 inst_base->idx = index;
57 inst_base->br = TransExtData::NON_BRANCH; 55 inst_base->br = TransExtData::NON_BRANCH;
58 56
59 inst_cream->I = BIT(inst, 25); 57 inst_cream->I = BIT(inst, 25);
60 inst_cream->S = BIT(inst, 20); 58 inst_cream->S = BIT(inst, 20);
61 inst_cream->Rn = BITS(inst, 16, 19); 59 inst_cream->Rn = BITS(inst, 16, 19);
62 inst_cream->Rd = BITS(inst, 12, 15); 60 inst_cream->Rd = BITS(inst, 12, 15);
63 inst_cream->shifter_operand = BITS(inst, 0, 11); 61 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -68,17 +66,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index)
68 66
69 return inst_base; 67 return inst_base;
70} 68}
71static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) 69static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) {
72{ 70 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst));
73 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst)); 71 and_inst* inst_cream = (and_inst*)inst_base->component;
74 and_inst *inst_cream = (and_inst *)inst_base->component;
75 72
76 inst_base->cond = BITS(inst, 28, 31); 73 inst_base->cond = BITS(inst, 28, 31);
77 inst_base->idx = index; 74 inst_base->idx = index;
78 inst_base->br = TransExtData::NON_BRANCH; 75 inst_base->br = TransExtData::NON_BRANCH;
79 76
80 inst_cream->I = BIT(inst, 25); 77 inst_cream->I = BIT(inst, 25);
81 inst_cream->S = BIT(inst, 20); 78 inst_cream->S = BIT(inst, 20);
82 inst_cream->Rn = BITS(inst, 16, 19); 79 inst_cream->Rn = BITS(inst, 16, 19);
83 inst_cream->Rd = BITS(inst, 12, 15); 80 inst_cream->Rd = BITS(inst, 12, 15);
84 inst_cream->shifter_operand = BITS(inst, 0, 11); 81 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -89,37 +86,35 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index)
89 86
90 return inst_base; 87 return inst_base;
91} 88}
92static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index) 89static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index) {
93{ 90#define POSBRANCH ((inst & 0x7fffff) << 2)
94 #define POSBRANCH ((inst & 0x7fffff) << 2) 91#define NEGBRANCH ((0xff000000 | (inst & 0xffffff)) << 2)
95 #define NEGBRANCH ((0xff000000 |(inst & 0xffffff)) << 2)
96 92
97 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst)); 93 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst));
98 bbl_inst *inst_cream = (bbl_inst *)inst_base->component; 94 bbl_inst* inst_cream = (bbl_inst*)inst_base->component;
99 95
100 inst_base->cond = BITS(inst, 28, 31); 96 inst_base->cond = BITS(inst, 28, 31);
101 inst_base->idx = index; 97 inst_base->idx = index;
102 inst_base->br = TransExtData::DIRECT_BRANCH; 98 inst_base->br = TransExtData::DIRECT_BRANCH;
103 99
104 if (BIT(inst, 24)) 100 if (BIT(inst, 24))
105 inst_base->br = TransExtData::CALL; 101 inst_base->br = TransExtData::CALL;
106 102
107 inst_cream->L = BIT(inst, 24); 103 inst_cream->L = BIT(inst, 24);
108 inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH; 104 inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH;
109 105
110 return inst_base; 106 return inst_base;
111} 107}
112static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) 108static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) {
113{ 109 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst));
114 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst)); 110 bic_inst* inst_cream = (bic_inst*)inst_base->component;
115 bic_inst *inst_cream = (bic_inst *)inst_base->component;
116 111
117 inst_base->cond = BITS(inst, 28, 31); 112 inst_base->cond = BITS(inst, 28, 31);
118 inst_base->idx = index; 113 inst_base->idx = index;
119 inst_base->br = TransExtData::NON_BRANCH; 114 inst_base->br = TransExtData::NON_BRANCH;
120 115
121 inst_cream->I = BIT(inst, 25); 116 inst_cream->I = BIT(inst, 25);
122 inst_cream->S = BIT(inst, 20); 117 inst_cream->S = BIT(inst, 20);
123 inst_cream->Rn = BITS(inst, 16, 19); 118 inst_cream->Rn = BITS(inst, 16, 19);
124 inst_cream->Rd = BITS(inst, 12, 15); 119 inst_cream->Rd = BITS(inst, 12, 15);
125 inst_cream->shifter_operand = BITS(inst, 0, 11); 120 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -130,28 +125,26 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index)
130 return inst_base; 125 return inst_base;
131} 126}
132 127
133static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) 128static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) {
134{
135 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bkpt_inst)); 129 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bkpt_inst));
136 bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component; 130 bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
137 131
138 inst_base->cond = BITS(inst, 28, 31); 132 inst_base->cond = BITS(inst, 28, 31);
139 inst_base->idx = index; 133 inst_base->idx = index;
140 inst_base->br = TransExtData::NON_BRANCH; 134 inst_base->br = TransExtData::NON_BRANCH;
141 135
142 inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3); 136 inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3);
143 137
144 return inst_base; 138 return inst_base;
145} 139}
146 140
147static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) 141static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) {
148{ 142 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst));
149 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst)); 143 blx_inst* inst_cream = (blx_inst*)inst_base->component;
150 blx_inst *inst_cream = (blx_inst *)inst_base->component;
151 144
152 inst_base->cond = BITS(inst, 28, 31); 145 inst_base->cond = BITS(inst, 28, 31);
153 inst_base->idx = index; 146 inst_base->idx = index;
154 inst_base->br = TransExtData::INDIRECT_BRANCH; 147 inst_base->br = TransExtData::INDIRECT_BRANCH;
155 148
156 inst_cream->inst = inst; 149 inst_cream->inst = inst;
157 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { 150 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
@@ -162,36 +155,34 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index)
162 155
163 return inst_base; 156 return inst_base;
164} 157}
165static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) 158static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) {
166{ 159 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst));
167 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst)); 160 bx_inst* inst_cream = (bx_inst*)inst_base->component;
168 bx_inst *inst_cream = (bx_inst *)inst_base->component;
169 161
170 inst_base->cond = BITS(inst, 28, 31); 162 inst_base->cond = BITS(inst, 28, 31);
171 inst_base->idx = index; 163 inst_base->idx = index;
172 inst_base->br = TransExtData::INDIRECT_BRANCH; 164 inst_base->br = TransExtData::INDIRECT_BRANCH;
173 165
174 inst_cream->Rm = BITS(inst, 0, 3); 166 inst_cream->Rm = BITS(inst, 0, 3);
175 167
176 return inst_base; 168 return inst_base;
177} 169}
178static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) 170static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) {
179{
180 return INTERPRETER_TRANSLATE(bx)(inst, index); 171 return INTERPRETER_TRANSLATE(bx)(inst, index);
181} 172}
182 173
183static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) { 174static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) {
184 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst)); 175 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst));
185 cdp_inst *inst_cream = (cdp_inst *)inst_base->component; 176 cdp_inst* inst_cream = (cdp_inst*)inst_base->component;
186 177
187 inst_base->cond = BITS(inst, 28, 31); 178 inst_base->cond = BITS(inst, 28, 31);
188 inst_base->idx = index; 179 inst_base->idx = index;
189 inst_base->br = TransExtData::NON_BRANCH; 180 inst_base->br = TransExtData::NON_BRANCH;
190 181
191 inst_cream->CRm = BITS(inst, 0, 3); 182 inst_cream->CRm = BITS(inst, 0, 3);
192 inst_cream->CRd = BITS(inst, 12, 15); 183 inst_cream->CRd = BITS(inst, 12, 15);
193 inst_cream->CRn = BITS(inst, 16, 19); 184 inst_cream->CRn = BITS(inst, 16, 19);
194 inst_cream->cp_num = BITS(inst, 8, 11); 185 inst_cream->cp_num = BITS(inst, 8, 11);
195 inst_cream->opcode_2 = BITS(inst, 5, 7); 186 inst_cream->opcode_2 = BITS(inst, 5, 7);
196 inst_cream->opcode_1 = BITS(inst, 20, 23); 187 inst_cream->opcode_1 = BITS(inst, 20, 23);
197 inst_cream->inst = inst; 188 inst_cream->inst = inst;
@@ -199,91 +190,85 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) {
199 LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index); 190 LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index);
200 return inst_base; 191 return inst_base;
201} 192}
202static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index) 193static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index) {
203{ 194 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst));
204 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst));
205 inst_base->cond = BITS(inst, 28, 31); 195 inst_base->cond = BITS(inst, 28, 31);
206 inst_base->idx = index; 196 inst_base->idx = index;
207 inst_base->br = TransExtData::NON_BRANCH; 197 inst_base->br = TransExtData::NON_BRANCH;
208 198
209 return inst_base; 199 return inst_base;
210} 200}
211static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index) 201static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index) {
212{ 202 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst));
213 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst)); 203 clz_inst* inst_cream = (clz_inst*)inst_base->component;
214 clz_inst *inst_cream = (clz_inst *)inst_base->component;
215 204
216 inst_base->cond = BITS(inst, 28, 31); 205 inst_base->cond = BITS(inst, 28, 31);
217 inst_base->idx = index; 206 inst_base->idx = index;
218 inst_base->br = TransExtData::NON_BRANCH; 207 inst_base->br = TransExtData::NON_BRANCH;
219 208
220 inst_cream->Rm = BITS(inst, 0, 3); 209 inst_cream->Rm = BITS(inst, 0, 3);
221 inst_cream->Rd = BITS(inst, 12, 15); 210 inst_cream->Rd = BITS(inst, 12, 15);
222 211
223 return inst_base; 212 return inst_base;
224} 213}
225static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) 214static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) {
226{ 215 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst));
227 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst)); 216 cmn_inst* inst_cream = (cmn_inst*)inst_base->component;
228 cmn_inst *inst_cream = (cmn_inst *)inst_base->component;
229 217
230 inst_base->cond = BITS(inst, 28, 31); 218 inst_base->cond = BITS(inst, 28, 31);
231 inst_base->idx = index; 219 inst_base->idx = index;
232 inst_base->br = TransExtData::NON_BRANCH; 220 inst_base->br = TransExtData::NON_BRANCH;
233 221
234 inst_cream->I = BIT(inst, 25); 222 inst_cream->I = BIT(inst, 25);
235 inst_cream->Rn = BITS(inst, 16, 19); 223 inst_cream->Rn = BITS(inst, 16, 19);
236 inst_cream->shifter_operand = BITS(inst, 0, 11); 224 inst_cream->shifter_operand = BITS(inst, 0, 11);
237 inst_cream->shtop_func = GetShifterOp(inst); 225 inst_cream->shtop_func = GetShifterOp(inst);
238 226
239 return inst_base; 227 return inst_base;
240} 228}
241static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) 229static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) {
242{ 230 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst));
243 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst)); 231 cmp_inst* inst_cream = (cmp_inst*)inst_base->component;
244 cmp_inst *inst_cream = (cmp_inst *)inst_base->component;
245 232
246 inst_base->cond = BITS(inst, 28, 31); 233 inst_base->cond = BITS(inst, 28, 31);
247 inst_base->idx = index; 234 inst_base->idx = index;
248 inst_base->br = TransExtData::NON_BRANCH; 235 inst_base->br = TransExtData::NON_BRANCH;
249 236
250 inst_cream->I = BIT(inst, 25); 237 inst_cream->I = BIT(inst, 25);
251 inst_cream->Rn = BITS(inst, 16, 19); 238 inst_cream->Rn = BITS(inst, 16, 19);
252 inst_cream->shifter_operand = BITS(inst, 0, 11); 239 inst_cream->shifter_operand = BITS(inst, 0, 11);
253 inst_cream->shtop_func = GetShifterOp(inst); 240 inst_cream->shtop_func = GetShifterOp(inst);
254 241
255 return inst_base; 242 return inst_base;
256} 243}
257static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index) 244static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index) {
258{ 245 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst));
259 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst)); 246 cps_inst* inst_cream = (cps_inst*)inst_base->component;
260 cps_inst *inst_cream = (cps_inst *)inst_base->component;
261 247
262 inst_base->cond = BITS(inst, 28, 31); 248 inst_base->cond = BITS(inst, 28, 31);
263 inst_base->idx = index; 249 inst_base->idx = index;
264 inst_base->br = TransExtData::NON_BRANCH; 250 inst_base->br = TransExtData::NON_BRANCH;
265 251
266 inst_cream->imod0 = BIT(inst, 18); 252 inst_cream->imod0 = BIT(inst, 18);
267 inst_cream->imod1 = BIT(inst, 19); 253 inst_cream->imod1 = BIT(inst, 19);
268 inst_cream->mmod = BIT(inst, 17); 254 inst_cream->mmod = BIT(inst, 17);
269 inst_cream->A = BIT(inst, 8); 255 inst_cream->A = BIT(inst, 8);
270 inst_cream->I = BIT(inst, 7); 256 inst_cream->I = BIT(inst, 7);
271 inst_cream->F = BIT(inst, 6); 257 inst_cream->F = BIT(inst, 6);
272 inst_cream->mode = BITS(inst, 0, 4); 258 inst_cream->mode = BITS(inst, 0, 4);
273 259
274 return inst_base; 260 return inst_base;
275} 261}
276static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) 262static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) {
277{ 263 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
278 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); 264 mov_inst* inst_cream = (mov_inst*)inst_base->component;
279 mov_inst *inst_cream = (mov_inst *)inst_base->component;
280 265
281 inst_base->cond = BITS(inst, 28, 31); 266 inst_base->cond = BITS(inst, 28, 31);
282 inst_base->idx = index; 267 inst_base->idx = index;
283 inst_base->br = TransExtData::NON_BRANCH; 268 inst_base->br = TransExtData::NON_BRANCH;
284 269
285 inst_cream->I = BIT(inst, 25); 270 inst_cream->I = BIT(inst, 25);
286 inst_cream->S = BIT(inst, 20); 271 inst_cream->S = BIT(inst, 20);
287 inst_cream->Rd = BITS(inst, 12, 15); 272 inst_cream->Rd = BITS(inst, 12, 15);
288 inst_cream->shifter_operand = BITS(inst, 0, 11); 273 inst_cream->shifter_operand = BITS(inst, 0, 11);
289 inst_cream->shtop_func = GetShifterOp(inst); 274 inst_cream->shtop_func = GetShifterOp(inst);
@@ -293,17 +278,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index)
293 } 278 }
294 return inst_base; 279 return inst_base;
295} 280}
296static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) 281static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) {
297{ 282 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst));
298 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst)); 283 eor_inst* inst_cream = (eor_inst*)inst_base->component;
299 eor_inst *inst_cream = (eor_inst *)inst_base->component;
300 284
301 inst_base->cond = BITS(inst, 28, 31); 285 inst_base->cond = BITS(inst, 28, 31);
302 inst_base->idx = index; 286 inst_base->idx = index;
303 inst_base->br = TransExtData::NON_BRANCH; 287 inst_base->br = TransExtData::NON_BRANCH;
304 288
305 inst_cream->I = BIT(inst, 25); 289 inst_cream->I = BIT(inst, 25);
306 inst_cream->S = BIT(inst, 20); 290 inst_cream->S = BIT(inst, 20);
307 inst_cream->Rn = BITS(inst, 16, 19); 291 inst_cream->Rn = BITS(inst, 16, 19);
308 inst_cream->Rd = BITS(inst, 12, 15); 292 inst_cream->Rd = BITS(inst, 12, 15);
309 inst_cream->shifter_operand = BITS(inst, 0, 11); 293 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -314,23 +298,21 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index)
314 298
315 return inst_base; 299 return inst_base;
316} 300}
317static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index) 301static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index) {
318{ 302 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst));
319 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst));
320 inst_base->cond = BITS(inst, 28, 31); 303 inst_base->cond = BITS(inst, 28, 31);
321 inst_base->idx = index; 304 inst_base->idx = index;
322 inst_base->br = TransExtData::NON_BRANCH; 305 inst_base->br = TransExtData::NON_BRANCH;
323 306
324 return inst_base; 307 return inst_base;
325} 308}
326static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) 309static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) {
327{ 310 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
328 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 311 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
329 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
330 312
331 inst_base->cond = BITS(inst, 28, 31); 313 inst_base->cond = BITS(inst, 28, 31);
332 inst_base->idx = index; 314 inst_base->idx = index;
333 inst_base->br = TransExtData::NON_BRANCH; 315 inst_base->br = TransExtData::NON_BRANCH;
334 316
335 inst_cream->inst = inst; 317 inst_cream->inst = inst;
336 inst_cream->get_addr = GetAddressingOp(inst); 318 inst_cream->get_addr = GetAddressingOp(inst);
@@ -340,29 +322,27 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index)
340 } 322 }
341 return inst_base; 323 return inst_base;
342} 324}
343static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index) 325static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index) {
344{ 326 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
345 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); 327 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component;
346 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
347 328
348 inst_base->cond = BITS(inst, 28, 31); 329 inst_base->cond = BITS(inst, 28, 31);
349 inst_base->idx = index; 330 inst_base->idx = index;
350 inst_base->br = TransExtData::NON_BRANCH; 331 inst_base->br = TransExtData::NON_BRANCH;
351 332
352 inst_cream->Rd = BITS(inst, 12, 15); 333 inst_cream->Rd = BITS(inst, 12, 15);
353 inst_cream->Rm = BITS(inst, 0, 3); 334 inst_cream->Rm = BITS(inst, 0, 3);
354 inst_cream->rotate = BITS(inst, 10, 11); 335 inst_cream->rotate = BITS(inst, 10, 11);
355 336
356 return inst_base; 337 return inst_base;
357} 338}
358static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) 339static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) {
359{ 340 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
360 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 341 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
361 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
362 342
363 inst_base->cond = BITS(inst, 28, 31); 343 inst_base->cond = BITS(inst, 28, 31);
364 inst_base->idx = index; 344 inst_base->idx = index;
365 inst_base->br = TransExtData::NON_BRANCH; 345 inst_base->br = TransExtData::NON_BRANCH;
366 346
367 inst_cream->inst = inst; 347 inst_cream->inst = inst;
368 inst_cream->get_addr = GetAddressingOp(inst); 348 inst_cream->get_addr = GetAddressingOp(inst);
@@ -373,14 +353,13 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index)
373 return inst_base; 353 return inst_base;
374} 354}
375 355
376static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) 356static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) {
377{ 357 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
378 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 358 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
379 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
380 359
381 inst_base->cond = BITS(inst, 28, 31); 360 inst_base->cond = BITS(inst, 28, 31);
382 inst_base->idx = index; 361 inst_base->idx = index;
383 inst_base->br = TransExtData::NON_BRANCH; 362 inst_base->br = TransExtData::NON_BRANCH;
384 363
385 inst_cream->inst = inst; 364 inst_cream->inst = inst;
386 inst_cream->get_addr = GetAddressingOp(inst); 365 inst_cream->get_addr = GetAddressingOp(inst);
@@ -391,155 +370,143 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index)
391 return inst_base; 370 return inst_base;
392} 371}
393 372
394static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index) 373static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index) {
395{ 374 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
396 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); 375 uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
397 uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
398 376
399 inst_base->cond = BITS(inst, 28, 31); 377 inst_base->cond = BITS(inst, 28, 31);
400 inst_base->idx = index; 378 inst_base->idx = index;
401 inst_base->br = TransExtData::NON_BRANCH; 379 inst_base->br = TransExtData::NON_BRANCH;
402 380
403 inst_cream->Rd = BITS(inst, 12, 15); 381 inst_cream->Rd = BITS(inst, 12, 15);
404 inst_cream->rotate = BITS(inst, 10, 11); 382 inst_cream->rotate = BITS(inst, 10, 11);
405 inst_cream->Rm = BITS(inst, 0, 3); 383 inst_cream->Rm = BITS(inst, 0, 3);
406 384
407 return inst_base; 385 return inst_base;
408} 386}
409static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index) 387static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index) {
410{ 388 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst));
411 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst)); 389 uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component;
412 uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component;
413 390
414 inst_base->cond = BITS(inst, 28, 31); 391 inst_base->cond = BITS(inst, 28, 31);
415 inst_base->idx = index; 392 inst_base->idx = index;
416 inst_base->br = TransExtData::NON_BRANCH; 393 inst_base->br = TransExtData::NON_BRANCH;
417 394
418 inst_cream->Rn = BITS(inst, 16, 19); 395 inst_cream->Rn = BITS(inst, 16, 19);
419 inst_cream->Rd = BITS(inst, 12, 15); 396 inst_cream->Rd = BITS(inst, 12, 15);
420 inst_cream->rotate = BITS(inst, 10, 11); 397 inst_cream->rotate = BITS(inst, 10, 11);
421 inst_cream->Rm = BITS(inst, 0, 3); 398 inst_cream->Rm = BITS(inst, 0, 3);
422 399
423 return inst_base; 400 return inst_base;
424} 401}
425static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) 402static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) {
426{ 403 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
427 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 404 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
428 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
429 405
430 inst_base->cond = BITS(inst, 28, 31); 406 inst_base->cond = BITS(inst, 28, 31);
431 inst_base->idx = index; 407 inst_base->idx = index;
432 inst_base->br = TransExtData::NON_BRANCH; 408 inst_base->br = TransExtData::NON_BRANCH;
433 409
434 inst_cream->inst = inst; 410 inst_cream->inst = inst;
435 inst_cream->get_addr = GetAddressingOp(inst); 411 inst_cream->get_addr = GetAddressingOp(inst);
436 412
437 return inst_base; 413 return inst_base;
438} 414}
439static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) 415static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) {
440{
441 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 416 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
442 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 417 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
443 418
444 inst_base->cond = BITS(inst, 28, 31); 419 inst_base->cond = BITS(inst, 28, 31);
445 inst_base->idx = index; 420 inst_base->idx = index;
446 inst_base->br = TransExtData::NON_BRANCH; 421 inst_base->br = TransExtData::NON_BRANCH;
447 422
448 inst_cream->inst = inst; 423 inst_cream->inst = inst;
449 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); 424 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
450 425
451 return inst_base; 426 return inst_base;
452} 427}
453static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) 428static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) {
454{ 429 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
455 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 430 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
456 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
457 431
458 inst_base->cond = BITS(inst, 28, 31); 432 inst_base->cond = BITS(inst, 28, 31);
459 inst_base->idx = index; 433 inst_base->idx = index;
460 inst_base->br = TransExtData::NON_BRANCH; 434 inst_base->br = TransExtData::NON_BRANCH;
461 435
462 inst_cream->inst = inst; 436 inst_cream->inst = inst;
463 inst_cream->get_addr = GetAddressingOp(inst); 437 inst_cream->get_addr = GetAddressingOp(inst);
464 438
465 return inst_base; 439 return inst_base;
466} 440}
467static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) 441static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) {
468{ 442 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
469 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 443 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
470 generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component;
471 444
472 inst_base->cond = BITS(inst, 28, 31); 445 inst_base->cond = BITS(inst, 28, 31);
473 inst_base->idx = index; 446 inst_base->idx = index;
474 inst_base->br = (BITS(inst, 12, 15) == 15) ? TransExtData::INDIRECT_BRANCH : TransExtData::NON_BRANCH; // Branch if dest is R15 447 inst_base->br = (BITS(inst, 12, 15) == 15) ? TransExtData::INDIRECT_BRANCH
448 : TransExtData::NON_BRANCH; // Branch if dest is R15
475 449
476 inst_cream->Rn = BITS(inst, 16, 19); 450 inst_cream->Rn = BITS(inst, 16, 19);
477 inst_cream->Rd = BITS(inst, 12, 15); 451 inst_cream->Rd = BITS(inst, 12, 15);
478 452
479 return inst_base; 453 return inst_base;
480} 454}
481static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) 455static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) {
482{
483 return INTERPRETER_TRANSLATE(ldrex)(inst, index); 456 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
484} 457}
485static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index) 458static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index) {
486{
487 return INTERPRETER_TRANSLATE(ldrex)(inst, index); 459 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
488} 460}
489static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index) 461static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index) {
490{
491 return INTERPRETER_TRANSLATE(ldrex)(inst, index); 462 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
492} 463}
493static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) 464static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) {
494{ 465 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
495 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 466 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
496 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
497 467
498 inst_base->cond = BITS(inst, 28, 31); 468 inst_base->cond = BITS(inst, 28, 31);
499 inst_base->idx = index; 469 inst_base->idx = index;
500 inst_base->br = TransExtData::NON_BRANCH; 470 inst_base->br = TransExtData::NON_BRANCH;
501 471
502 inst_cream->inst = inst; 472 inst_cream->inst = inst;
503 inst_cream->get_addr = GetAddressingOp(inst); 473 inst_cream->get_addr = GetAddressingOp(inst);
504 474
505 return inst_base; 475 return inst_base;
506} 476}
507static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) 477static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) {
508{ 478 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
509 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 479 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
510 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
511 480
512 inst_base->cond = BITS(inst, 28, 31); 481 inst_base->cond = BITS(inst, 28, 31);
513 inst_base->idx = index; 482 inst_base->idx = index;
514 inst_base->br = TransExtData::NON_BRANCH; 483 inst_base->br = TransExtData::NON_BRANCH;
515 484
516 inst_cream->inst = inst; 485 inst_cream->inst = inst;
517 inst_cream->get_addr = GetAddressingOp(inst); 486 inst_cream->get_addr = GetAddressingOp(inst);
518 487
519 return inst_base; 488 return inst_base;
520} 489}
521static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) 490static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) {
522{ 491 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
523 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 492 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
524 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
525 493
526 inst_base->cond = BITS(inst, 28, 31); 494 inst_base->cond = BITS(inst, 28, 31);
527 inst_base->idx = index; 495 inst_base->idx = index;
528 inst_base->br = TransExtData::NON_BRANCH; 496 inst_base->br = TransExtData::NON_BRANCH;
529 497
530 inst_cream->inst = inst; 498 inst_cream->inst = inst;
531 inst_cream->get_addr = GetAddressingOp(inst); 499 inst_cream->get_addr = GetAddressingOp(inst);
532 500
533 return inst_base; 501 return inst_base;
534} 502}
535static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) 503static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) {
536{
537 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 504 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
538 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 505 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
539 506
540 inst_base->cond = BITS(inst, 28, 31); 507 inst_base->cond = BITS(inst, 28, 31);
541 inst_base->idx = index; 508 inst_base->idx = index;
542 inst_base->br = TransExtData::NON_BRANCH; 509 inst_base->br = TransExtData::NON_BRANCH;
543 510
544 inst_cream->inst = inst; 511 inst_cream->inst = inst;
545 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); 512 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
@@ -549,70 +516,66 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index)
549 } 516 }
550 return inst_base; 517 return inst_base;
551} 518}
552static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) 519static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) {
553{ 520 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst));
554 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst)); 521 mcr_inst* inst_cream = (mcr_inst*)inst_base->component;
555 mcr_inst *inst_cream = (mcr_inst *)inst_base->component;
556 inst_base->cond = BITS(inst, 28, 31); 522 inst_base->cond = BITS(inst, 28, 31);
557 inst_base->idx = index; 523 inst_base->idx = index;
558 inst_base->br = TransExtData::NON_BRANCH; 524 inst_base->br = TransExtData::NON_BRANCH;
559 525
560 inst_cream->crn = BITS(inst, 16, 19); 526 inst_cream->crn = BITS(inst, 16, 19);
561 inst_cream->crm = BITS(inst, 0, 3); 527 inst_cream->crm = BITS(inst, 0, 3);
562 inst_cream->opcode_1 = BITS(inst, 21, 23); 528 inst_cream->opcode_1 = BITS(inst, 21, 23);
563 inst_cream->opcode_2 = BITS(inst, 5, 7); 529 inst_cream->opcode_2 = BITS(inst, 5, 7);
564 inst_cream->Rd = BITS(inst, 12, 15); 530 inst_cream->Rd = BITS(inst, 12, 15);
565 inst_cream->cp_num = BITS(inst, 8, 11); 531 inst_cream->cp_num = BITS(inst, 8, 11);
566 inst_cream->inst = inst; 532 inst_cream->inst = inst;
567 return inst_base; 533 return inst_base;
568} 534}
569 535
570static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) 536static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) {
571{
572 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst)); 537 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst));
573 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component; 538 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
574 539
575 inst_base->cond = BITS(inst, 28, 31); 540 inst_base->cond = BITS(inst, 28, 31);
576 inst_base->idx = index; 541 inst_base->idx = index;
577 inst_base->br = TransExtData::NON_BRANCH; 542 inst_base->br = TransExtData::NON_BRANCH;
578 543
579 inst_cream->crm = BITS(inst, 0, 3); 544 inst_cream->crm = BITS(inst, 0, 3);
580 inst_cream->opcode_1 = BITS(inst, 4, 7); 545 inst_cream->opcode_1 = BITS(inst, 4, 7);
581 inst_cream->cp_num = BITS(inst, 8, 11); 546 inst_cream->cp_num = BITS(inst, 8, 11);
582 inst_cream->rt = BITS(inst, 12, 15); 547 inst_cream->rt = BITS(inst, 12, 15);
583 inst_cream->rt2 = BITS(inst, 16, 19); 548 inst_cream->rt2 = BITS(inst, 16, 19);
584 549
585 return inst_base; 550 return inst_base;
586} 551}
587 552
588static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) 553static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) {
589{ 554 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst));
590 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst)); 555 mla_inst* inst_cream = (mla_inst*)inst_base->component;
591 mla_inst *inst_cream = (mla_inst *)inst_base->component;
592 556
593 inst_base->cond = BITS(inst, 28, 31); 557 inst_base->cond = BITS(inst, 28, 31);
594 inst_base->idx = index; 558 inst_base->idx = index;
595 inst_base->br = TransExtData::NON_BRANCH; 559 inst_base->br = TransExtData::NON_BRANCH;
596 560
597 inst_cream->S = BIT(inst, 20); 561 inst_cream->S = BIT(inst, 20);
598 inst_cream->Rn = BITS(inst, 12, 15); 562 inst_cream->Rn = BITS(inst, 12, 15);
599 inst_cream->Rd = BITS(inst, 16, 19); 563 inst_cream->Rd = BITS(inst, 16, 19);
600 inst_cream->Rs = BITS(inst, 8, 11); 564 inst_cream->Rs = BITS(inst, 8, 11);
601 inst_cream->Rm = BITS(inst, 0, 3); 565 inst_cream->Rm = BITS(inst, 0, 3);
602 566
603 return inst_base; 567 return inst_base;
604} 568}
605static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) 569static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) {
606{ 570 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
607 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); 571 mov_inst* inst_cream = (mov_inst*)inst_base->component;
608 mov_inst *inst_cream = (mov_inst *)inst_base->component;
609 572
610 inst_base->cond = BITS(inst, 28, 31); 573 inst_base->cond = BITS(inst, 28, 31);
611 inst_base->idx = index; 574 inst_base->idx = index;
612 inst_base->br = TransExtData::NON_BRANCH; 575 inst_base->br = TransExtData::NON_BRANCH;
613 576
614 inst_cream->I = BIT(inst, 25); 577 inst_cream->I = BIT(inst, 25);
615 inst_cream->S = BIT(inst, 20); 578 inst_cream->S = BIT(inst, 20);
616 inst_cream->Rd = BITS(inst, 12, 15); 579 inst_cream->Rd = BITS(inst, 12, 15);
617 inst_cream->shifter_operand = BITS(inst, 0, 11); 580 inst_cream->shifter_operand = BITS(inst, 0, 11);
618 inst_cream->shtop_func = GetShifterOp(inst); 581 inst_cream->shtop_func = GetShifterOp(inst);
@@ -622,85 +585,79 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index)
622 } 585 }
623 return inst_base; 586 return inst_base;
624} 587}
625static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) 588static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) {
626{ 589 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst));
627 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst)); 590 mrc_inst* inst_cream = (mrc_inst*)inst_base->component;
628 mrc_inst *inst_cream = (mrc_inst *)inst_base->component;
629 inst_base->cond = BITS(inst, 28, 31); 591 inst_base->cond = BITS(inst, 28, 31);
630 inst_base->idx = index; 592 inst_base->idx = index;
631 inst_base->br = TransExtData::NON_BRANCH; 593 inst_base->br = TransExtData::NON_BRANCH;
632 594
633 inst_cream->crn = BITS(inst, 16, 19); 595 inst_cream->crn = BITS(inst, 16, 19);
634 inst_cream->crm = BITS(inst, 0, 3); 596 inst_cream->crm = BITS(inst, 0, 3);
635 inst_cream->opcode_1 = BITS(inst, 21, 23); 597 inst_cream->opcode_1 = BITS(inst, 21, 23);
636 inst_cream->opcode_2 = BITS(inst, 5, 7); 598 inst_cream->opcode_2 = BITS(inst, 5, 7);
637 inst_cream->Rd = BITS(inst, 12, 15); 599 inst_cream->Rd = BITS(inst, 12, 15);
638 inst_cream->cp_num = BITS(inst, 8, 11); 600 inst_cream->cp_num = BITS(inst, 8, 11);
639 inst_cream->inst = inst; 601 inst_cream->inst = inst;
640 return inst_base; 602 return inst_base;
641} 603}
642 604
643static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) 605static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) {
644{
645 return INTERPRETER_TRANSLATE(mcrr)(inst, index); 606 return INTERPRETER_TRANSLATE(mcrr)(inst, index);
646} 607}
647 608
648static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) 609static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) {
649{ 610 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst));
650 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst)); 611 mrs_inst* inst_cream = (mrs_inst*)inst_base->component;
651 mrs_inst *inst_cream = (mrs_inst *)inst_base->component;
652 612
653 inst_base->cond = BITS(inst, 28, 31); 613 inst_base->cond = BITS(inst, 28, 31);
654 inst_base->idx = index; 614 inst_base->idx = index;
655 inst_base->br = TransExtData::NON_BRANCH; 615 inst_base->br = TransExtData::NON_BRANCH;
656 616
657 inst_cream->Rd = BITS(inst, 12, 15); 617 inst_cream->Rd = BITS(inst, 12, 15);
658 inst_cream->R = BIT(inst, 22); 618 inst_cream->R = BIT(inst, 22);
659 619
660 return inst_base; 620 return inst_base;
661} 621}
662static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index) 622static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index) {
663{ 623 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst));
664 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst)); 624 msr_inst* inst_cream = (msr_inst*)inst_base->component;
665 msr_inst *inst_cream = (msr_inst *)inst_base->component;
666 625
667 inst_base->cond = BITS(inst, 28, 31); 626 inst_base->cond = BITS(inst, 28, 31);
668 inst_base->idx = index; 627 inst_base->idx = index;
669 inst_base->br = TransExtData::NON_BRANCH; 628 inst_base->br = TransExtData::NON_BRANCH;
670 629
671 inst_cream->field_mask = BITS(inst, 16, 19); 630 inst_cream->field_mask = BITS(inst, 16, 19);
672 inst_cream->R = BIT(inst, 22); 631 inst_cream->R = BIT(inst, 22);
673 inst_cream->inst = inst; 632 inst_cream->inst = inst;
674 633
675 return inst_base; 634 return inst_base;
676} 635}
677static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index) 636static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index) {
678{ 637 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst));
679 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst)); 638 mul_inst* inst_cream = (mul_inst*)inst_base->component;
680 mul_inst *inst_cream = (mul_inst *)inst_base->component;
681 639
682 inst_base->cond = BITS(inst, 28, 31); 640 inst_base->cond = BITS(inst, 28, 31);
683 inst_base->idx = index; 641 inst_base->idx = index;
684 inst_base->br = TransExtData::NON_BRANCH; 642 inst_base->br = TransExtData::NON_BRANCH;
685 643
686 inst_cream->S = BIT(inst, 20); 644 inst_cream->S = BIT(inst, 20);
687 inst_cream->Rm = BITS(inst, 0, 3); 645 inst_cream->Rm = BITS(inst, 0, 3);
688 inst_cream->Rs = BITS(inst, 8, 11); 646 inst_cream->Rs = BITS(inst, 8, 11);
689 inst_cream->Rd = BITS(inst, 16, 19); 647 inst_cream->Rd = BITS(inst, 16, 19);
690 648
691 return inst_base; 649 return inst_base;
692} 650}
693static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) 651static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) {
694{ 652 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst));
695 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst)); 653 mvn_inst* inst_cream = (mvn_inst*)inst_base->component;
696 mvn_inst *inst_cream = (mvn_inst *)inst_base->component;
697 654
698 inst_base->cond = BITS(inst, 28, 31); 655 inst_base->cond = BITS(inst, 28, 31);
699 inst_base->idx = index; 656 inst_base->idx = index;
700 inst_base->br = TransExtData::NON_BRANCH; 657 inst_base->br = TransExtData::NON_BRANCH;
701 658
702 inst_cream->I = BIT(inst, 25); 659 inst_cream->I = BIT(inst, 25);
703 inst_cream->S = BIT(inst, 20); 660 inst_cream->S = BIT(inst, 20);
704 inst_cream->Rd = BITS(inst, 12, 15); 661 inst_cream->Rd = BITS(inst, 12, 15);
705 inst_cream->shifter_operand = BITS(inst, 0, 11); 662 inst_cream->shifter_operand = BITS(inst, 0, 11);
706 inst_cream->shtop_func = GetShifterOp(inst); 663 inst_cream->shtop_func = GetShifterOp(inst);
@@ -709,19 +666,17 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index)
709 inst_base->br = TransExtData::INDIRECT_BRANCH; 666 inst_base->br = TransExtData::INDIRECT_BRANCH;
710 } 667 }
711 return inst_base; 668 return inst_base;
712
713} 669}
714static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) 670static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) {
715{ 671 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst));
716 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst)); 672 orr_inst* inst_cream = (orr_inst*)inst_base->component;
717 orr_inst *inst_cream = (orr_inst *)inst_base->component;
718 673
719 inst_base->cond = BITS(inst, 28, 31); 674 inst_base->cond = BITS(inst, 28, 31);
720 inst_base->idx = index; 675 inst_base->idx = index;
721 inst_base->br = TransExtData::NON_BRANCH; 676 inst_base->br = TransExtData::NON_BRANCH;
722 677
723 inst_cream->I = BIT(inst, 25); 678 inst_cream->I = BIT(inst, 25);
724 inst_cream->S = BIT(inst, 20); 679 inst_cream->S = BIT(inst, 20);
725 inst_cream->Rd = BITS(inst, 12, 15); 680 inst_cream->Rd = BITS(inst, 12, 15);
726 inst_cream->Rn = BITS(inst, 16, 19); 681 inst_cream->Rn = BITS(inst, 16, 19);
727 inst_cream->shifter_operand = BITS(inst, 0, 11); 682 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -734,150 +689,132 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index)
734} 689}
735 690
736// NOP introduced in ARMv6K. 691// NOP introduced in ARMv6K.
737static ARM_INST_PTR INTERPRETER_TRANSLATE(nop)(unsigned int inst, int index) 692static ARM_INST_PTR INTERPRETER_TRANSLATE(nop)(unsigned int inst, int index) {
738{
739 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); 693 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
740 694
741 inst_base->cond = BITS(inst, 28, 31); 695 inst_base->cond = BITS(inst, 28, 31);
742 inst_base->idx = index; 696 inst_base->idx = index;
743 inst_base->br = TransExtData::NON_BRANCH; 697 inst_base->br = TransExtData::NON_BRANCH;
744 698
745 return inst_base; 699 return inst_base;
746} 700}
747 701
748static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) 702static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) {
749{ 703 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst));
750 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst)); 704 pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
751 pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
752 705
753 inst_base->cond = BITS(inst, 28, 31); 706 inst_base->cond = BITS(inst, 28, 31);
754 inst_base->idx = index; 707 inst_base->idx = index;
755 inst_base->br = TransExtData::NON_BRANCH; 708 inst_base->br = TransExtData::NON_BRANCH;
756 709
757 inst_cream->Rd = BITS(inst, 12, 15); 710 inst_cream->Rd = BITS(inst, 12, 15);
758 inst_cream->Rn = BITS(inst, 16, 19); 711 inst_cream->Rn = BITS(inst, 16, 19);
759 inst_cream->Rm = BITS(inst, 0, 3); 712 inst_cream->Rm = BITS(inst, 0, 3);
760 inst_cream->imm = BITS(inst, 7, 11); 713 inst_cream->imm = BITS(inst, 7, 11);
761 714
762 return inst_base; 715 return inst_base;
763} 716}
764 717
765static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) 718static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) {
766{
767 return INTERPRETER_TRANSLATE(pkhbt)(inst, index); 719 return INTERPRETER_TRANSLATE(pkhbt)(inst, index);
768} 720}
769 721
770static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) 722static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) {
771{ 723 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst));
772 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst));
773 724
774 inst_base->cond = BITS(inst, 28, 31); 725 inst_base->cond = BITS(inst, 28, 31);
775 inst_base->idx = index; 726 inst_base->idx = index;
776 inst_base->br = TransExtData::NON_BRANCH; 727 inst_base->br = TransExtData::NON_BRANCH;
777 728
778 return inst_base; 729 return inst_base;
779} 730}
780 731
781static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) 732static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) {
782{
783 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 733 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
784 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 734 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
785 735
786 inst_base->cond = BITS(inst, 28, 31); 736 inst_base->cond = BITS(inst, 28, 31);
787 inst_base->idx = index; 737 inst_base->idx = index;
788 inst_base->br = TransExtData::NON_BRANCH; 738 inst_base->br = TransExtData::NON_BRANCH;
789 739
790 inst_cream->op1 = BITS(inst, 21, 22); 740 inst_cream->op1 = BITS(inst, 21, 22);
791 inst_cream->Rm = BITS(inst, 0, 3); 741 inst_cream->Rm = BITS(inst, 0, 3);
792 inst_cream->Rn = BITS(inst, 16, 19); 742 inst_cream->Rn = BITS(inst, 16, 19);
793 inst_cream->Rd = BITS(inst, 12, 15); 743 inst_cream->Rd = BITS(inst, 12, 15);
794 744
795 return inst_base; 745 return inst_base;
796} 746}
797static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) 747static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) {
798{
799 return INTERPRETER_TRANSLATE(qadd)(inst, index); 748 return INTERPRETER_TRANSLATE(qadd)(inst, index);
800} 749}
801static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) 750static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) {
802{
803 return INTERPRETER_TRANSLATE(qadd)(inst, index); 751 return INTERPRETER_TRANSLATE(qadd)(inst, index);
804} 752}
805static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) 753static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) {
806{
807 return INTERPRETER_TRANSLATE(qadd)(inst, index); 754 return INTERPRETER_TRANSLATE(qadd)(inst, index);
808} 755}
809 756
810static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) 757static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) {
811{
812 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 758 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
813 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 759 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
814 760
815 inst_base->cond = BITS(inst, 28, 31); 761 inst_base->cond = BITS(inst, 28, 31);
816 inst_base->idx = index; 762 inst_base->idx = index;
817 inst_base->br = TransExtData::NON_BRANCH; 763 inst_base->br = TransExtData::NON_BRANCH;
818 764
819 inst_cream->Rm = BITS(inst, 0, 3); 765 inst_cream->Rm = BITS(inst, 0, 3);
820 inst_cream->Rn = BITS(inst, 16, 19); 766 inst_cream->Rn = BITS(inst, 16, 19);
821 inst_cream->Rd = BITS(inst, 12, 15); 767 inst_cream->Rd = BITS(inst, 12, 15);
822 inst_cream->op1 = BITS(inst, 20, 21); 768 inst_cream->op1 = BITS(inst, 20, 21);
823 inst_cream->op2 = BITS(inst, 5, 7); 769 inst_cream->op2 = BITS(inst, 5, 7);
824 770
825 return inst_base; 771 return inst_base;
826} 772}
827static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) 773static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) {
828{
829 return INTERPRETER_TRANSLATE(qadd8)(inst, index); 774 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
830} 775}
831static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) 776static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) {
832{
833 return INTERPRETER_TRANSLATE(qadd8)(inst, index); 777 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
834} 778}
835static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) 779static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) {
836{
837 return INTERPRETER_TRANSLATE(qadd8)(inst, index); 780 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
838} 781}
839static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) 782static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) {
840{
841 return INTERPRETER_TRANSLATE(qadd8)(inst, index); 783 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
842} 784}
843static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) 785static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) {
844{
845 return INTERPRETER_TRANSLATE(qadd8)(inst, index); 786 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
846} 787}
847 788
848static ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) 789static ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) {
849{
850 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); 790 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst));
851 rev_inst* const inst_cream = (rev_inst*)inst_base->component; 791 rev_inst* const inst_cream = (rev_inst*)inst_base->component;
852 792
853 inst_base->cond = BITS(inst, 28, 31); 793 inst_base->cond = BITS(inst, 28, 31);
854 inst_base->idx = index; 794 inst_base->idx = index;
855 inst_base->br = TransExtData::NON_BRANCH; 795 inst_base->br = TransExtData::NON_BRANCH;
856 796
857 inst_cream->Rm = BITS(inst, 0, 3); 797 inst_cream->Rm = BITS(inst, 0, 3);
858 inst_cream->Rd = BITS(inst, 12, 15); 798 inst_cream->Rd = BITS(inst, 12, 15);
859 inst_cream->op1 = BITS(inst, 20, 22); 799 inst_cream->op1 = BITS(inst, 20, 22);
860 inst_cream->op2 = BITS(inst, 5, 7); 800 inst_cream->op2 = BITS(inst, 5, 7);
861 801
862 return inst_base; 802 return inst_base;
863} 803}
864static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index) 804static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index) {
865{
866 return INTERPRETER_TRANSLATE(rev)(inst, index); 805 return INTERPRETER_TRANSLATE(rev)(inst, index);
867} 806}
868static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) 807static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) {
869{ 808 return INTERPRETER_TRANSLATE(rev)(inst, index);
870 return INTERPRETER_TRANSLATE(rev)(inst, index);
871} 809}
872 810
873static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) 811static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) {
874{
875 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 812 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
876 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; 813 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
877 814
878 inst_base->cond = AL; 815 inst_base->cond = AL;
879 inst_base->idx = index; 816 inst_base->idx = index;
880 inst_base->br = TransExtData::INDIRECT_BRANCH; 817 inst_base->br = TransExtData::INDIRECT_BRANCH;
881 818
882 inst_cream->inst = inst; 819 inst_cream->inst = inst;
883 inst_cream->get_addr = GetAddressingOp(inst); 820 inst_cream->get_addr = GetAddressingOp(inst);
@@ -885,17 +822,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index)
885 return inst_base; 822 return inst_base;
886} 823}
887 824
888static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) 825static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) {
889{ 826 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst));
890 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst)); 827 rsb_inst* inst_cream = (rsb_inst*)inst_base->component;
891 rsb_inst *inst_cream = (rsb_inst *)inst_base->component;
892 828
893 inst_base->cond = BITS(inst, 28, 31); 829 inst_base->cond = BITS(inst, 28, 31);
894 inst_base->idx = index; 830 inst_base->idx = index;
895 inst_base->br = TransExtData::NON_BRANCH; 831 inst_base->br = TransExtData::NON_BRANCH;
896 832
897 inst_cream->I = BIT(inst, 25); 833 inst_cream->I = BIT(inst, 25);
898 inst_cream->S = BIT(inst, 20); 834 inst_cream->S = BIT(inst, 20);
899 inst_cream->Rn = BITS(inst, 16, 19); 835 inst_cream->Rn = BITS(inst, 16, 19);
900 inst_cream->Rd = BITS(inst, 12, 15); 836 inst_cream->Rd = BITS(inst, 12, 15);
901 inst_cream->shifter_operand = BITS(inst, 0, 11); 837 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -906,17 +842,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index)
906 842
907 return inst_base; 843 return inst_base;
908} 844}
909static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) 845static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) {
910{ 846 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst));
911 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst)); 847 rsc_inst* inst_cream = (rsc_inst*)inst_base->component;
912 rsc_inst *inst_cream = (rsc_inst *)inst_base->component;
913 848
914 inst_base->cond = BITS(inst, 28, 31); 849 inst_base->cond = BITS(inst, 28, 31);
915 inst_base->idx = index; 850 inst_base->idx = index;
916 inst_base->br = TransExtData::NON_BRANCH; 851 inst_base->br = TransExtData::NON_BRANCH;
917 852
918 inst_cream->I = BIT(inst, 25); 853 inst_cream->I = BIT(inst, 25);
919 inst_cream->S = BIT(inst, 20); 854 inst_cream->S = BIT(inst, 20);
920 inst_cream->Rn = BITS(inst, 16, 19); 855 inst_cream->Rn = BITS(inst, 16, 19);
921 inst_cream->Rd = BITS(inst, 12, 15); 856 inst_cream->Rd = BITS(inst, 12, 15);
922 inst_cream->shifter_operand = BITS(inst, 0, 11); 857 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -927,55 +862,48 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index)
927 862
928 return inst_base; 863 return inst_base;
929} 864}
930static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index) 865static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index) {
931{
932 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 866 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
933 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 867 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
934 868
935 inst_base->cond = BITS(inst, 28, 31); 869 inst_base->cond = BITS(inst, 28, 31);
936 inst_base->idx = index; 870 inst_base->idx = index;
937 inst_base->br = TransExtData::NON_BRANCH; 871 inst_base->br = TransExtData::NON_BRANCH;
938 872
939 inst_cream->Rm = BITS(inst, 0, 3); 873 inst_cream->Rm = BITS(inst, 0, 3);
940 inst_cream->Rn = BITS(inst, 16, 19); 874 inst_cream->Rn = BITS(inst, 16, 19);
941 inst_cream->Rd = BITS(inst, 12, 15); 875 inst_cream->Rd = BITS(inst, 12, 15);
942 inst_cream->op1 = BITS(inst, 20, 21); 876 inst_cream->op1 = BITS(inst, 20, 21);
943 inst_cream->op2 = BITS(inst, 5, 7); 877 inst_cream->op2 = BITS(inst, 5, 7);
944 878
945 return inst_base; 879 return inst_base;
946} 880}
947static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index) 881static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index) {
948{
949 return INTERPRETER_TRANSLATE(sadd8)(inst, index); 882 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
950} 883}
951static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index) 884static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index) {
952{
953 return INTERPRETER_TRANSLATE(sadd8)(inst, index); 885 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
954} 886}
955static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) 887static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) {
956{
957 return INTERPRETER_TRANSLATE(sadd8)(inst, index); 888 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
958} 889}
959static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) 890static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) {
960{
961 return INTERPRETER_TRANSLATE(sadd8)(inst, index); 891 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
962} 892}
963static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index) 893static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index) {
964{
965 return INTERPRETER_TRANSLATE(sadd8)(inst, index); 894 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
966} 895}
967 896
968static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) 897static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) {
969{ 898 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst));
970 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst)); 899 sbc_inst* inst_cream = (sbc_inst*)inst_base->component;
971 sbc_inst *inst_cream = (sbc_inst *)inst_base->component;
972 900
973 inst_base->cond = BITS(inst, 28, 31); 901 inst_base->cond = BITS(inst, 28, 31);
974 inst_base->idx = index; 902 inst_base->idx = index;
975 inst_base->br = TransExtData::NON_BRANCH; 903 inst_base->br = TransExtData::NON_BRANCH;
976 904
977 inst_cream->I = BIT(inst, 25); 905 inst_cream->I = BIT(inst, 25);
978 inst_cream->S = BIT(inst, 20); 906 inst_cream->S = BIT(inst, 20);
979 inst_cream->Rn = BITS(inst, 16, 19); 907 inst_cream->Rn = BITS(inst, 16, 19);
980 inst_cream->Rd = BITS(inst, 12, 15); 908 inst_cream->Rd = BITS(inst, 12, 15);
981 inst_cream->shifter_operand = BITS(inst, 0, 11); 909 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -986,98 +914,88 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index)
986 914
987 return inst_base; 915 return inst_base;
988} 916}
989static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) 917static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) {
990{
991 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 918 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
992 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 919 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
993 920
994 inst_base->cond = BITS(inst, 28, 31); 921 inst_base->cond = BITS(inst, 28, 31);
995 inst_base->idx = index; 922 inst_base->idx = index;
996 inst_base->br = TransExtData::NON_BRANCH; 923 inst_base->br = TransExtData::NON_BRANCH;
997 924
998 inst_cream->Rm = BITS(inst, 0, 3); 925 inst_cream->Rm = BITS(inst, 0, 3);
999 inst_cream->Rn = BITS(inst, 16, 19); 926 inst_cream->Rn = BITS(inst, 16, 19);
1000 inst_cream->Rd = BITS(inst, 12, 15); 927 inst_cream->Rd = BITS(inst, 12, 15);
1001 inst_cream->op1 = BITS(inst, 20, 22); 928 inst_cream->op1 = BITS(inst, 20, 22);
1002 inst_cream->op2 = BITS(inst, 5, 7); 929 inst_cream->op2 = BITS(inst, 5, 7);
1003 930
1004 return inst_base; 931 return inst_base;
1005} 932}
1006 933
1007static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) 934static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) {
1008{
1009 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst)); 935 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst));
1010 setend_inst* const inst_cream = (setend_inst*)inst_base->component; 936 setend_inst* const inst_cream = (setend_inst*)inst_base->component;
1011 937
1012 inst_base->cond = AL; 938 inst_base->cond = AL;
1013 inst_base->idx = index; 939 inst_base->idx = index;
1014 inst_base->br = TransExtData::NON_BRANCH; 940 inst_base->br = TransExtData::NON_BRANCH;
1015 941
1016 inst_cream->set_bigend = BIT(inst, 9); 942 inst_cream->set_bigend = BIT(inst, 9);
1017 943
1018 return inst_base; 944 return inst_base;
1019} 945}
1020 946
1021static ARM_INST_PTR INTERPRETER_TRANSLATE(sev)(unsigned int inst, int index) 947static ARM_INST_PTR INTERPRETER_TRANSLATE(sev)(unsigned int inst, int index) {
1022{
1023 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); 948 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
1024 949
1025 inst_base->cond = BITS(inst, 28, 31); 950 inst_base->cond = BITS(inst, 28, 31);
1026 inst_base->idx = index; 951 inst_base->idx = index;
1027 inst_base->br = TransExtData::NON_BRANCH; 952 inst_base->br = TransExtData::NON_BRANCH;
1028 953
1029 return inst_base; 954 return inst_base;
1030} 955}
1031 956
1032static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) 957static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) {
1033{
1034 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 958 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1035 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 959 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1036 960
1037 inst_base->cond = BITS(inst, 28, 31); 961 inst_base->cond = BITS(inst, 28, 31);
1038 inst_base->idx = index; 962 inst_base->idx = index;
1039 inst_base->br = TransExtData::NON_BRANCH; 963 inst_base->br = TransExtData::NON_BRANCH;
1040 964
1041 inst_cream->op1 = BITS(inst, 20, 21); 965 inst_cream->op1 = BITS(inst, 20, 21);
1042 inst_cream->op2 = BITS(inst, 5, 7); 966 inst_cream->op2 = BITS(inst, 5, 7);
1043 inst_cream->Rm = BITS(inst, 0, 3); 967 inst_cream->Rm = BITS(inst, 0, 3);
1044 inst_cream->Rn = BITS(inst, 16, 19); 968 inst_cream->Rn = BITS(inst, 16, 19);
1045 inst_cream->Rd = BITS(inst, 12, 15); 969 inst_cream->Rd = BITS(inst, 12, 15);
1046 970
1047 return inst_base; 971 return inst_base;
1048} 972}
1049static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) 973static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) {
1050{
1051 return INTERPRETER_TRANSLATE(shadd8)(inst, index); 974 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
1052} 975}
1053static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) 976static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) {
1054{
1055 return INTERPRETER_TRANSLATE(shadd8)(inst, index); 977 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
1056} 978}
1057static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) 979static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) {
1058{
1059 return INTERPRETER_TRANSLATE(shadd8)(inst, index); 980 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
1060} 981}
1061static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) 982static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) {
1062{
1063 return INTERPRETER_TRANSLATE(shadd8)(inst, index); 983 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
1064} 984}
1065static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) 985static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) {
1066{
1067 return INTERPRETER_TRANSLATE(shadd8)(inst, index); 986 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
1068} 987}
1069 988
1070static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) 989static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) {
1071{ 990 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst));
1072 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst)); 991 smla_inst* inst_cream = (smla_inst*)inst_base->component;
1073 smla_inst *inst_cream = (smla_inst *)inst_base->component;
1074 992
1075 inst_base->cond = BITS(inst, 28, 31); 993 inst_base->cond = BITS(inst, 28, 31);
1076 inst_base->idx = index; 994 inst_base->idx = index;
1077 inst_base->br = TransExtData::NON_BRANCH; 995 inst_base->br = TransExtData::NON_BRANCH;
1078 996
1079 inst_cream->x = BIT(inst, 5); 997 inst_cream->x = BIT(inst, 5);
1080 inst_cream->y = BIT(inst, 6); 998 inst_cream->y = BIT(inst, 6);
1081 inst_cream->Rm = BITS(inst, 0, 3); 999 inst_cream->Rm = BITS(inst, 0, 3);
1082 inst_cream->Rs = BITS(inst, 8, 11); 1000 inst_cream->Rs = BITS(inst, 8, 11);
1083 inst_cream->Rd = BITS(inst, 16, 19); 1001 inst_cream->Rd = BITS(inst, 16, 19);
@@ -1086,192 +1004,176 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index)
1086 return inst_base; 1004 return inst_base;
1087} 1005}
1088 1006
1089static ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index) 1007static ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index) {
1090{
1091 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); 1008 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
1092 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; 1009 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
1093 1010
1094 inst_base->cond = BITS(inst, 28, 31); 1011 inst_base->cond = BITS(inst, 28, 31);
1095 inst_base->idx = index; 1012 inst_base->idx = index;
1096 inst_base->br = TransExtData::NON_BRANCH; 1013 inst_base->br = TransExtData::NON_BRANCH;
1097 1014
1098 inst_cream->m = BIT(inst, 5); 1015 inst_cream->m = BIT(inst, 5);
1099 inst_cream->Rn = BITS(inst, 0, 3); 1016 inst_cream->Rn = BITS(inst, 0, 3);
1100 inst_cream->Rm = BITS(inst, 8, 11); 1017 inst_cream->Rm = BITS(inst, 8, 11);
1101 inst_cream->Rd = BITS(inst, 16, 19); 1018 inst_cream->Rd = BITS(inst, 16, 19);
1102 inst_cream->Ra = BITS(inst, 12, 15); 1019 inst_cream->Ra = BITS(inst, 12, 15);
1103 inst_cream->op1 = BITS(inst, 20, 22); 1020 inst_cream->op1 = BITS(inst, 20, 22);
1104 inst_cream->op2 = BITS(inst, 5, 7); 1021 inst_cream->op2 = BITS(inst, 5, 7);
1105 1022
1106 return inst_base; 1023 return inst_base;
1107} 1024}
1108static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) 1025static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) {
1109{
1110 return INTERPRETER_TRANSLATE(smlad)(inst, index); 1026 return INTERPRETER_TRANSLATE(smlad)(inst, index);
1111} 1027}
1112static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) 1028static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) {
1113{
1114 return INTERPRETER_TRANSLATE(smlad)(inst, index); 1029 return INTERPRETER_TRANSLATE(smlad)(inst, index);
1115} 1030}
1116static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index) 1031static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index) {
1117{
1118 return INTERPRETER_TRANSLATE(smlad)(inst, index); 1032 return INTERPRETER_TRANSLATE(smlad)(inst, index);
1119} 1033}
1120 1034
1121static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) 1035static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) {
1122{ 1036 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
1123 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); 1037 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
1124 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
1125 1038
1126 inst_base->cond = BITS(inst, 28, 31); 1039 inst_base->cond = BITS(inst, 28, 31);
1127 inst_base->idx = index; 1040 inst_base->idx = index;
1128 inst_base->br = TransExtData::NON_BRANCH; 1041 inst_base->br = TransExtData::NON_BRANCH;
1129 1042
1130 inst_cream->S = BIT(inst, 20); 1043 inst_cream->S = BIT(inst, 20);
1131 inst_cream->Rm = BITS(inst, 0, 3); 1044 inst_cream->Rm = BITS(inst, 0, 3);
1132 inst_cream->Rs = BITS(inst, 8, 11); 1045 inst_cream->Rs = BITS(inst, 8, 11);
1133 inst_cream->RdHi = BITS(inst, 16, 19); 1046 inst_cream->RdHi = BITS(inst, 16, 19);
1134 inst_cream->RdLo = BITS(inst, 12, 15); 1047 inst_cream->RdLo = BITS(inst, 12, 15);
1135 1048
1136 return inst_base; 1049 return inst_base;
1137} 1050}
1138 1051
1139static ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) 1052static ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) {
1140{
1141 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlalxy_inst)); 1053 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlalxy_inst));
1142 smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component; 1054 smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component;
1143 1055
1144 inst_base->cond = BITS(inst, 28, 31); 1056 inst_base->cond = BITS(inst, 28, 31);
1145 inst_base->idx = index; 1057 inst_base->idx = index;
1146 inst_base->br = TransExtData::NON_BRANCH; 1058 inst_base->br = TransExtData::NON_BRANCH;
1147 1059
1148 inst_cream->x = BIT(inst, 5); 1060 inst_cream->x = BIT(inst, 5);
1149 inst_cream->y = BIT(inst, 6); 1061 inst_cream->y = BIT(inst, 6);
1150 inst_cream->RdLo = BITS(inst, 12, 15); 1062 inst_cream->RdLo = BITS(inst, 12, 15);
1151 inst_cream->RdHi = BITS(inst, 16, 19); 1063 inst_cream->RdHi = BITS(inst, 16, 19);
1152 inst_cream->Rn = BITS(inst, 0, 4); 1064 inst_cream->Rn = BITS(inst, 0, 4);
1153 inst_cream->Rm = BITS(inst, 8, 11); 1065 inst_cream->Rm = BITS(inst, 8, 11);
1154 1066
1155 return inst_base; 1067 return inst_base;
1156} 1068}
1157 1069
1158static ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) 1070static ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) {
1159{
1160 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); 1071 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
1161 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; 1072 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
1162 1073
1163 inst_base->cond = BITS(inst, 28, 31); 1074 inst_base->cond = BITS(inst, 28, 31);
1164 inst_base->idx = index; 1075 inst_base->idx = index;
1165 inst_base->br = TransExtData::NON_BRANCH; 1076 inst_base->br = TransExtData::NON_BRANCH;
1166 1077
1167 inst_cream->Ra = BITS(inst, 12, 15); 1078 inst_cream->Ra = BITS(inst, 12, 15);
1168 inst_cream->Rm = BITS(inst, 8, 11); 1079 inst_cream->Rm = BITS(inst, 8, 11);
1169 inst_cream->Rn = BITS(inst, 0, 3); 1080 inst_cream->Rn = BITS(inst, 0, 3);
1170 inst_cream->Rd = BITS(inst, 16, 19); 1081 inst_cream->Rd = BITS(inst, 16, 19);
1171 inst_cream->m = BIT(inst, 6); 1082 inst_cream->m = BIT(inst, 6);
1172 1083
1173 return inst_base; 1084 return inst_base;
1174} 1085}
1175 1086
1176static ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) 1087static ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) {
1177{
1178 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlald_inst)); 1088 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlald_inst));
1179 smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; 1089 smlald_inst* const inst_cream = (smlald_inst*)inst_base->component;
1180 1090
1181 inst_base->cond = BITS(inst, 28, 31); 1091 inst_base->cond = BITS(inst, 28, 31);
1182 inst_base->idx = index; 1092 inst_base->idx = index;
1183 inst_base->br = TransExtData::NON_BRANCH; 1093 inst_base->br = TransExtData::NON_BRANCH;
1184 1094
1185 inst_cream->Rm = BITS(inst, 8, 11); 1095 inst_cream->Rm = BITS(inst, 8, 11);
1186 inst_cream->Rn = BITS(inst, 0, 3); 1096 inst_cream->Rn = BITS(inst, 0, 3);
1187 inst_cream->RdLo = BITS(inst, 12, 15); 1097 inst_cream->RdLo = BITS(inst, 12, 15);
1188 inst_cream->RdHi = BITS(inst, 16, 19); 1098 inst_cream->RdHi = BITS(inst, 16, 19);
1189 inst_cream->swap = BIT(inst, 5); 1099 inst_cream->swap = BIT(inst, 5);
1190 inst_cream->op1 = BITS(inst, 20, 22); 1100 inst_cream->op1 = BITS(inst, 20, 22);
1191 inst_cream->op2 = BITS(inst, 5, 7); 1101 inst_cream->op2 = BITS(inst, 5, 7);
1192 1102
1193 return inst_base; 1103 return inst_base;
1194} 1104}
1195static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) 1105static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) {
1196{
1197 return INTERPRETER_TRANSLATE(smlald)(inst, index); 1106 return INTERPRETER_TRANSLATE(smlald)(inst, index);
1198} 1107}
1199 1108
1200static ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) 1109static ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) {
1201{
1202 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); 1110 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
1203 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; 1111 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
1204 1112
1205 inst_base->cond = BITS(inst, 28, 31); 1113 inst_base->cond = BITS(inst, 28, 31);
1206 inst_base->idx = index; 1114 inst_base->idx = index;
1207 inst_base->br = TransExtData::NON_BRANCH; 1115 inst_base->br = TransExtData::NON_BRANCH;
1208 1116
1209 inst_cream->m = BIT(inst, 5); 1117 inst_cream->m = BIT(inst, 5);
1210 inst_cream->Ra = BITS(inst, 12, 15); 1118 inst_cream->Ra = BITS(inst, 12, 15);
1211 inst_cream->Rm = BITS(inst, 8, 11); 1119 inst_cream->Rm = BITS(inst, 8, 11);
1212 inst_cream->Rn = BITS(inst, 0, 3); 1120 inst_cream->Rn = BITS(inst, 0, 3);
1213 inst_cream->Rd = BITS(inst, 16, 19); 1121 inst_cream->Rd = BITS(inst, 16, 19);
1214 inst_cream->op1 = BITS(inst, 20, 22); 1122 inst_cream->op1 = BITS(inst, 20, 22);
1215 inst_cream->op2 = BITS(inst, 5, 7); 1123 inst_cream->op2 = BITS(inst, 5, 7);
1216 1124
1217 return inst_base; 1125 return inst_base;
1218} 1126}
1219static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index) 1127static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index) {
1220{
1221 return INTERPRETER_TRANSLATE(smmla)(inst, index); 1128 return INTERPRETER_TRANSLATE(smmla)(inst, index);
1222} 1129}
1223static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index) 1130static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index) {
1224{
1225 return INTERPRETER_TRANSLATE(smmla)(inst, index); 1131 return INTERPRETER_TRANSLATE(smmla)(inst, index);
1226} 1132}
1227 1133
1228static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index) 1134static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index) {
1229{ 1135 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst));
1230 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst)); 1136 smul_inst* inst_cream = (smul_inst*)inst_base->component;
1231 smul_inst *inst_cream = (smul_inst *)inst_base->component;
1232 1137
1233 inst_base->cond = BITS(inst, 28, 31); 1138 inst_base->cond = BITS(inst, 28, 31);
1234 inst_base->idx = index; 1139 inst_base->idx = index;
1235 inst_base->br = TransExtData::NON_BRANCH; 1140 inst_base->br = TransExtData::NON_BRANCH;
1236 1141
1237 inst_cream->Rd = BITS(inst, 16, 19); 1142 inst_cream->Rd = BITS(inst, 16, 19);
1238 inst_cream->Rs = BITS(inst, 8, 11); 1143 inst_cream->Rs = BITS(inst, 8, 11);
1239 inst_cream->Rm = BITS(inst, 0, 3); 1144 inst_cream->Rm = BITS(inst, 0, 3);
1240 1145
1241 inst_cream->x = BIT(inst, 5); 1146 inst_cream->x = BIT(inst, 5);
1242 inst_cream->y = BIT(inst, 6); 1147 inst_cream->y = BIT(inst, 6);
1243 1148
1244 return inst_base; 1149 return inst_base;
1245
1246} 1150}
1247static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index) 1151static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index) {
1248{ 1152 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
1249 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); 1153 umull_inst* inst_cream = (umull_inst*)inst_base->component;
1250 umull_inst *inst_cream = (umull_inst *)inst_base->component;
1251 1154
1252 inst_base->cond = BITS(inst, 28, 31); 1155 inst_base->cond = BITS(inst, 28, 31);
1253 inst_base->idx = index; 1156 inst_base->idx = index;
1254 inst_base->br = TransExtData::NON_BRANCH; 1157 inst_base->br = TransExtData::NON_BRANCH;
1255 1158
1256 inst_cream->S = BIT(inst, 20); 1159 inst_cream->S = BIT(inst, 20);
1257 inst_cream->Rm = BITS(inst, 0, 3); 1160 inst_cream->Rm = BITS(inst, 0, 3);
1258 inst_cream->Rs = BITS(inst, 8, 11); 1161 inst_cream->Rs = BITS(inst, 8, 11);
1259 inst_cream->RdHi = BITS(inst, 16, 19); 1162 inst_cream->RdHi = BITS(inst, 16, 19);
1260 inst_cream->RdLo = BITS(inst, 12, 15); 1163 inst_cream->RdLo = BITS(inst, 12, 15);
1261 1164
1262 return inst_base; 1165 return inst_base;
1263} 1166}
1264 1167
1265static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) 1168static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) {
1266{ 1169 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
1267 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); 1170 smlad_inst* inst_cream = (smlad_inst*)inst_base->component;
1268 smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
1269 1171
1270 inst_base->cond = BITS(inst, 28, 31); 1172 inst_base->cond = BITS(inst, 28, 31);
1271 inst_base->idx = index; 1173 inst_base->idx = index;
1272 inst_base->br = TransExtData::NON_BRANCH; 1174 inst_base->br = TransExtData::NON_BRANCH;
1273 1175
1274 inst_cream->m = BIT(inst, 6); 1176 inst_cream->m = BIT(inst, 6);
1275 inst_cream->Rm = BITS(inst, 8, 11); 1177 inst_cream->Rm = BITS(inst, 8, 11);
1276 inst_cream->Rn = BITS(inst, 0, 3); 1178 inst_cream->Rn = BITS(inst, 0, 3);
1277 inst_cream->Rd = BITS(inst, 16, 19); 1179 inst_cream->Rd = BITS(inst, 16, 19);
@@ -1279,29 +1181,27 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index)
1279 return inst_base; 1181 return inst_base;
1280} 1182}
1281 1183
1282static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) 1184static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) {
1283{
1284 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1185 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1285 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; 1186 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
1286 1187
1287 inst_base->cond = AL; 1188 inst_base->cond = AL;
1288 inst_base->idx = index; 1189 inst_base->idx = index;
1289 inst_base->br = TransExtData::NON_BRANCH; 1190 inst_base->br = TransExtData::NON_BRANCH;
1290 1191
1291 inst_cream->inst = inst; 1192 inst_cream->inst = inst;
1292 inst_cream->get_addr = GetAddressingOp(inst); 1193 inst_cream->get_addr = GetAddressingOp(inst);
1293 1194
1294 return inst_base; 1195 return inst_base;
1295} 1196}
1296 1197
1297static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) 1198static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) {
1298{
1299 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); 1199 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst));
1300 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; 1200 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
1301 1201
1302 inst_base->cond = BITS(inst, 28, 31); 1202 inst_base->cond = BITS(inst, 28, 31);
1303 inst_base->idx = index; 1203 inst_base->idx = index;
1304 inst_base->br = TransExtData::NON_BRANCH; 1204 inst_base->br = TransExtData::NON_BRANCH;
1305 1205
1306 inst_cream->Rn = BITS(inst, 0, 3); 1206 inst_cream->Rn = BITS(inst, 0, 3);
1307 inst_cream->Rd = BITS(inst, 12, 15); 1207 inst_cream->Rd = BITS(inst, 12, 15);
@@ -1311,211 +1211,195 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index)
1311 1211
1312 return inst_base; 1212 return inst_base;
1313} 1213}
1314static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) 1214static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) {
1315{
1316 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst)); 1215 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst));
1317 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; 1216 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
1318 1217
1319 inst_base->cond = BITS(inst, 28, 31); 1218 inst_base->cond = BITS(inst, 28, 31);
1320 inst_base->idx = index; 1219 inst_base->idx = index;
1321 inst_base->br = TransExtData::NON_BRANCH; 1220 inst_base->br = TransExtData::NON_BRANCH;
1322 1221
1323 inst_cream->Rn = BITS(inst, 0, 3); 1222 inst_cream->Rn = BITS(inst, 0, 3);
1324 inst_cream->Rd = BITS(inst, 12, 15); 1223 inst_cream->Rd = BITS(inst, 12, 15);
1325 inst_cream->sat_imm = BITS(inst, 16, 19); 1224 inst_cream->sat_imm = BITS(inst, 16, 19);
1326 1225
1327 return inst_base; 1226 return inst_base;
1328} 1227}
1329 1228
1330static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index) 1229static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index) {
1331{ 1230 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst));
1332 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst));
1333 inst_base->cond = BITS(inst, 28, 31); 1231 inst_base->cond = BITS(inst, 28, 31);
1334 inst_base->idx = index; 1232 inst_base->idx = index;
1335 inst_base->br = TransExtData::NON_BRANCH; 1233 inst_base->br = TransExtData::NON_BRANCH;
1336 1234
1337 return inst_base; 1235 return inst_base;
1338} 1236}
1339static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) 1237static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) {
1340{ 1238 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1341 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1239 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1342 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1343 1240
1344 inst_base->cond = BITS(inst, 28, 31); 1241 inst_base->cond = BITS(inst, 28, 31);
1345 inst_base->idx = index; 1242 inst_base->idx = index;
1346 inst_base->br = TransExtData::NON_BRANCH; 1243 inst_base->br = TransExtData::NON_BRANCH;
1347 1244
1348 inst_cream->inst = inst; 1245 inst_cream->inst = inst;
1349 inst_cream->get_addr = GetAddressingOp(inst); 1246 inst_cream->get_addr = GetAddressingOp(inst);
1350 return inst_base; 1247 return inst_base;
1351} 1248}
1352static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) 1249static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) {
1353{ 1250 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
1354 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); 1251 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component;
1355 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
1356 1252
1357 inst_base->cond = BITS(inst, 28, 31); 1253 inst_base->cond = BITS(inst, 28, 31);
1358 inst_base->idx = index; 1254 inst_base->idx = index;
1359 inst_base->br = TransExtData::NON_BRANCH; 1255 inst_base->br = TransExtData::NON_BRANCH;
1360 1256
1361 inst_cream->Rd = BITS(inst, 12, 15); 1257 inst_cream->Rd = BITS(inst, 12, 15);
1362 inst_cream->Rm = BITS(inst, 0, 3); 1258 inst_cream->Rm = BITS(inst, 0, 3);
1363 inst_cream->rotate = BITS(inst, 10, 11); 1259 inst_cream->rotate = BITS(inst, 10, 11);
1364 1260
1365 return inst_base; 1261 return inst_base;
1366} 1262}
1367static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) 1263static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) {
1368{ 1264 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1369 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1265 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1370 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1371 1266
1372 inst_base->cond = BITS(inst, 28, 31); 1267 inst_base->cond = BITS(inst, 28, 31);
1373 inst_base->idx = index; 1268 inst_base->idx = index;
1374 inst_base->br = TransExtData::NON_BRANCH; 1269 inst_base->br = TransExtData::NON_BRANCH;
1375 1270
1376 inst_cream->inst = inst; 1271 inst_cream->inst = inst;
1377 inst_cream->get_addr = GetAddressingOp(inst); 1272 inst_cream->get_addr = GetAddressingOp(inst);
1378 1273
1379 return inst_base; 1274 return inst_base;
1380} 1275}
1381static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) 1276static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) {
1382{ 1277 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
1383 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); 1278 uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
1384 uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
1385 1279
1386 inst_base->cond = BITS(inst, 28, 31); 1280 inst_base->cond = BITS(inst, 28, 31);
1387 inst_base->idx = index; 1281 inst_base->idx = index;
1388 inst_base->br = TransExtData::NON_BRANCH; 1282 inst_base->br = TransExtData::NON_BRANCH;
1389 1283
1390 inst_cream->Rd = BITS(inst, 12, 15); 1284 inst_cream->Rd = BITS(inst, 12, 15);
1391 inst_cream->rotate = BITS(inst, 10, 11); 1285 inst_cream->rotate = BITS(inst, 10, 11);
1392 inst_cream->Rm = BITS(inst, 0, 3); 1286 inst_cream->Rm = BITS(inst, 0, 3);
1393 1287
1394 return inst_base; 1288 return inst_base;
1395} 1289}
1396static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index) 1290static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index) {
1397{ 1291 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
1398 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); 1292 uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component;
1399 uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component;
1400 1293
1401 inst_base->cond = BITS(inst, 28, 31); 1294 inst_base->cond = BITS(inst, 28, 31);
1402 inst_base->idx = index; 1295 inst_base->idx = index;
1403 inst_base->br = TransExtData::NON_BRANCH; 1296 inst_base->br = TransExtData::NON_BRANCH;
1404 1297
1405 inst_cream->Rd = BITS(inst, 12, 15); 1298 inst_cream->Rd = BITS(inst, 12, 15);
1406 inst_cream->rotate = BITS(inst, 10, 11); 1299 inst_cream->rotate = BITS(inst, 10, 11);
1407 inst_cream->Rm = BITS(inst, 0, 3); 1300 inst_cream->Rm = BITS(inst, 0, 3);
1408 inst_cream->Rn = BITS(inst, 16, 19); 1301 inst_cream->Rn = BITS(inst, 16, 19);
1409 1302
1410 return inst_base; 1303 return inst_base;
1411} 1304}
1412static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) 1305static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) {
1413{ 1306 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1414 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1307 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1415 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1416 1308
1417 inst_base->cond = BITS(inst, 28, 31); 1309 inst_base->cond = BITS(inst, 28, 31);
1418 inst_base->idx = index; 1310 inst_base->idx = index;
1419 inst_base->br = TransExtData::NON_BRANCH; 1311 inst_base->br = TransExtData::NON_BRANCH;
1420 1312
1421 inst_cream->inst = inst; 1313 inst_cream->inst = inst;
1422 inst_cream->get_addr = GetAddressingOp(inst); 1314 inst_cream->get_addr = GetAddressingOp(inst);
1423 1315
1424 return inst_base; 1316 return inst_base;
1425} 1317}
1426static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) 1318static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) {
1427{
1428 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1319 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1429 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 1320 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1430 1321
1431 inst_base->cond = BITS(inst, 28, 31); 1322 inst_base->cond = BITS(inst, 28, 31);
1432 inst_base->idx = index; 1323 inst_base->idx = index;
1433 inst_base->br = TransExtData::NON_BRANCH; 1324 inst_base->br = TransExtData::NON_BRANCH;
1434 1325
1435 inst_cream->inst = inst; 1326 inst_cream->inst = inst;
1436 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); 1327 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
1437 1328
1438 return inst_base; 1329 return inst_base;
1439} 1330}
1440static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){ 1331static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index) {
1441 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1332 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1442 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1333 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1443 1334
1444 inst_base->cond = BITS(inst, 28, 31); 1335 inst_base->cond = BITS(inst, 28, 31);
1445 inst_base->idx = index; 1336 inst_base->idx = index;
1446 inst_base->br = TransExtData::NON_BRANCH; 1337 inst_base->br = TransExtData::NON_BRANCH;
1447 1338
1448 inst_cream->inst = inst; 1339 inst_cream->inst = inst;
1449 inst_cream->get_addr = GetAddressingOp(inst); 1340 inst_cream->get_addr = GetAddressingOp(inst);
1450 1341
1451 return inst_base; 1342 return inst_base;
1452} 1343}
1453static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) 1344static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) {
1454{ 1345 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1455 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 1346 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
1456 generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component;
1457 1347
1458 inst_base->cond = BITS(inst, 28, 31); 1348 inst_base->cond = BITS(inst, 28, 31);
1459 inst_base->idx = index; 1349 inst_base->idx = index;
1460 inst_base->br = TransExtData::NON_BRANCH; 1350 inst_base->br = TransExtData::NON_BRANCH;
1461 1351
1462 inst_cream->Rn = BITS(inst, 16, 19); 1352 inst_cream->Rn = BITS(inst, 16, 19);
1463 inst_cream->Rd = BITS(inst, 12, 15); 1353 inst_cream->Rd = BITS(inst, 12, 15);
1464 inst_cream->Rm = BITS(inst, 0, 3); 1354 inst_cream->Rm = BITS(inst, 0, 3);
1465 1355
1466 return inst_base; 1356 return inst_base;
1467} 1357}
1468static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) 1358static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) {
1469{
1470 return INTERPRETER_TRANSLATE(strex)(inst, index); 1359 return INTERPRETER_TRANSLATE(strex)(inst, index);
1471} 1360}
1472static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index) 1361static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index) {
1473{
1474 return INTERPRETER_TRANSLATE(strex)(inst, index); 1362 return INTERPRETER_TRANSLATE(strex)(inst, index);
1475} 1363}
1476static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index) 1364static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index) {
1477{
1478 return INTERPRETER_TRANSLATE(strex)(inst, index); 1365 return INTERPRETER_TRANSLATE(strex)(inst, index);
1479} 1366}
1480static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) 1367static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) {
1481{ 1368 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1482 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1369 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1483 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1484 1370
1485 inst_base->cond = BITS(inst, 28, 31); 1371 inst_base->cond = BITS(inst, 28, 31);
1486 inst_base->idx = index; 1372 inst_base->idx = index;
1487 inst_base->br = TransExtData::NON_BRANCH; 1373 inst_base->br = TransExtData::NON_BRANCH;
1488 1374
1489 inst_cream->inst = inst; 1375 inst_cream->inst = inst;
1490 inst_cream->get_addr = GetAddressingOp(inst); 1376 inst_cream->get_addr = GetAddressingOp(inst);
1491 1377
1492 return inst_base; 1378 return inst_base;
1493} 1379}
1494static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) 1380static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) {
1495{
1496 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1381 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1497 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 1382 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1498 1383
1499 inst_base->cond = BITS(inst, 28, 31); 1384 inst_base->cond = BITS(inst, 28, 31);
1500 inst_base->idx = index; 1385 inst_base->idx = index;
1501 inst_base->br = TransExtData::NON_BRANCH; 1386 inst_base->br = TransExtData::NON_BRANCH;
1502 1387
1503 inst_cream->inst = inst; 1388 inst_cream->inst = inst;
1504 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); 1389 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
1505 1390
1506 return inst_base; 1391 return inst_base;
1507} 1392}
1508static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) 1393static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) {
1509{ 1394 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst));
1510 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst)); 1395 sub_inst* inst_cream = (sub_inst*)inst_base->component;
1511 sub_inst *inst_cream = (sub_inst *)inst_base->component;
1512 1396
1513 inst_base->cond = BITS(inst, 28, 31); 1397 inst_base->cond = BITS(inst, 28, 31);
1514 inst_base->idx = index; 1398 inst_base->idx = index;
1515 inst_base->br = TransExtData::NON_BRANCH; 1399 inst_base->br = TransExtData::NON_BRANCH;
1516 1400
1517 inst_cream->I = BIT(inst, 25); 1401 inst_cream->I = BIT(inst, 25);
1518 inst_cream->S = BIT(inst, 20); 1402 inst_cream->S = BIT(inst, 20);
1519 inst_cream->Rn = BITS(inst, 16, 19); 1403 inst_cream->Rn = BITS(inst, 16, 19);
1520 inst_cream->Rd = BITS(inst, 12, 15); 1404 inst_cream->Rd = BITS(inst, 12, 15);
1521 inst_cream->shifter_operand = BITS(inst, 0, 11); 1405 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -1526,71 +1410,68 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index)
1526 1410
1527 return inst_base; 1411 return inst_base;
1528} 1412}
1529static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index) 1413static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index) {
1530{ 1414 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst));
1531 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst)); 1415 swi_inst* inst_cream = (swi_inst*)inst_base->component;
1532 swi_inst *inst_cream = (swi_inst *)inst_base->component;
1533 1416
1534 inst_base->cond = BITS(inst, 28, 31); 1417 inst_base->cond = BITS(inst, 28, 31);
1535 inst_base->idx = index; 1418 inst_base->idx = index;
1536 inst_base->br = TransExtData::NON_BRANCH; 1419 inst_base->br = TransExtData::NON_BRANCH;
1537 1420
1538 inst_cream->num = BITS(inst, 0, 23); 1421 inst_cream->num = BITS(inst, 0, 23);
1539 return inst_base; 1422 return inst_base;
1540} 1423}
1541static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) 1424static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) {
1542{ 1425 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
1543 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); 1426 swp_inst* inst_cream = (swp_inst*)inst_base->component;
1544 swp_inst *inst_cream = (swp_inst *)inst_base->component;
1545 1427
1546 inst_base->cond = BITS(inst, 28, 31); 1428 inst_base->cond = BITS(inst, 28, 31);
1547 inst_base->idx = index; 1429 inst_base->idx = index;
1548 inst_base->br = TransExtData::NON_BRANCH; 1430 inst_base->br = TransExtData::NON_BRANCH;
1549 1431
1550 inst_cream->Rn = BITS(inst, 16, 19); 1432 inst_cream->Rn = BITS(inst, 16, 19);
1551 inst_cream->Rd = BITS(inst, 12, 15); 1433 inst_cream->Rd = BITS(inst, 12, 15);
1552 inst_cream->Rm = BITS(inst, 0, 3); 1434 inst_cream->Rm = BITS(inst, 0, 3);
1553 1435
1554 return inst_base; 1436 return inst_base;
1555} 1437}
1556static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){ 1438static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index) {
1557 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); 1439 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
1558 swp_inst *inst_cream = (swp_inst *)inst_base->component; 1440 swp_inst* inst_cream = (swp_inst*)inst_base->component;
1559 1441
1560 inst_base->cond = BITS(inst, 28, 31); 1442 inst_base->cond = BITS(inst, 28, 31);
1561 inst_base->idx = index; 1443 inst_base->idx = index;
1562 inst_base->br = TransExtData::NON_BRANCH; 1444 inst_base->br = TransExtData::NON_BRANCH;
1563 1445
1564 inst_cream->Rn = BITS(inst, 16, 19); 1446 inst_cream->Rn = BITS(inst, 16, 19);
1565 inst_cream->Rd = BITS(inst, 12, 15); 1447 inst_cream->Rd = BITS(inst, 12, 15);
1566 inst_cream->Rm = BITS(inst, 0, 3); 1448 inst_cream->Rm = BITS(inst, 0, 3);
1567 1449
1568 return inst_base; 1450 return inst_base;
1569} 1451}
1570static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){ 1452static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index) {
1571 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); 1453 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst));
1572 sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component; 1454 sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component;
1573 1455
1574 inst_base->cond = BITS(inst, 28, 31); 1456 inst_base->cond = BITS(inst, 28, 31);
1575 inst_base->idx = index; 1457 inst_base->idx = index;
1576 inst_base->br = TransExtData::NON_BRANCH; 1458 inst_base->br = TransExtData::NON_BRANCH;
1577 1459
1578 inst_cream->Rd = BITS(inst, 12, 15); 1460 inst_cream->Rd = BITS(inst, 12, 15);
1579 inst_cream->rotate = BITS(inst, 10, 11); 1461 inst_cream->rotate = BITS(inst, 10, 11);
1580 inst_cream->Rm = BITS(inst, 0, 3); 1462 inst_cream->Rm = BITS(inst, 0, 3);
1581 inst_cream->Rn = BITS(inst, 16, 19); 1463 inst_cream->Rn = BITS(inst, 16, 19);
1582 1464
1583 return inst_base; 1465 return inst_base;
1584} 1466}
1585 1467
1586static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) 1468static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) {
1587{
1588 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); 1469 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst));
1589 sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component; 1470 sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component;
1590 1471
1591 inst_base->cond = BITS(inst, 28, 31); 1472 inst_base->cond = BITS(inst, 28, 31);
1592 inst_base->idx = index; 1473 inst_base->idx = index;
1593 inst_base->br = TransExtData::NON_BRANCH; 1474 inst_base->br = TransExtData::NON_BRANCH;
1594 1475
1595 inst_cream->Rm = BITS(inst, 0, 3); 1476 inst_cream->Rm = BITS(inst, 0, 3);
1596 inst_cream->Rn = BITS(inst, 16, 19); 1477 inst_cream->Rn = BITS(inst, 16, 19);
@@ -1599,54 +1480,51 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index)
1599 1480
1600 return inst_base; 1481 return inst_base;
1601} 1482}
1602static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) 1483static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) {
1603{
1604 return INTERPRETER_TRANSLATE(sxtab16)(inst, index); 1484 return INTERPRETER_TRANSLATE(sxtab16)(inst, index);
1605} 1485}
1606 1486
1607static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index) { 1487static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index) {
1608 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst)); 1488 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst));
1609 sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component; 1489 sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component;
1610 1490
1611 inst_base->cond = BITS(inst, 28, 31); 1491 inst_base->cond = BITS(inst, 28, 31);
1612 inst_base->idx = index; 1492 inst_base->idx = index;
1613 inst_base->br = TransExtData::NON_BRANCH; 1493 inst_base->br = TransExtData::NON_BRANCH;
1614 1494
1615 inst_cream->Rd = BITS(inst, 12, 15); 1495 inst_cream->Rd = BITS(inst, 12, 15);
1616 inst_cream->rotate = BITS(inst, 10, 11); 1496 inst_cream->rotate = BITS(inst, 10, 11);
1617 inst_cream->Rm = BITS(inst, 0, 3); 1497 inst_cream->Rm = BITS(inst, 0, 3);
1618 inst_cream->Rn = BITS(inst, 16, 19); 1498 inst_cream->Rn = BITS(inst, 16, 19);
1619 1499
1620 return inst_base; 1500 return inst_base;
1621} 1501}
1622 1502
1623static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) 1503static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) {
1624{ 1504 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst));
1625 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst)); 1505 teq_inst* inst_cream = (teq_inst*)inst_base->component;
1626 teq_inst *inst_cream = (teq_inst *)inst_base->component;
1627 1506
1628 inst_base->cond = BITS(inst, 28, 31); 1507 inst_base->cond = BITS(inst, 28, 31);
1629 inst_base->idx = index; 1508 inst_base->idx = index;
1630 inst_base->br = TransExtData::NON_BRANCH; 1509 inst_base->br = TransExtData::NON_BRANCH;
1631 1510
1632 inst_cream->I = BIT(inst, 25); 1511 inst_cream->I = BIT(inst, 25);
1633 inst_cream->Rn = BITS(inst, 16, 19); 1512 inst_cream->Rn = BITS(inst, 16, 19);
1634 inst_cream->shifter_operand = BITS(inst, 0, 11); 1513 inst_cream->shifter_operand = BITS(inst, 0, 11);
1635 inst_cream->shtop_func = GetShifterOp(inst); 1514 inst_cream->shtop_func = GetShifterOp(inst);
1636 1515
1637 return inst_base; 1516 return inst_base;
1638} 1517}
1639static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) 1518static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) {
1640{ 1519 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst));
1641 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst)); 1520 tst_inst* inst_cream = (tst_inst*)inst_base->component;
1642 tst_inst *inst_cream = (tst_inst *)inst_base->component;
1643 1521
1644 inst_base->cond = BITS(inst, 28, 31); 1522 inst_base->cond = BITS(inst, 28, 31);
1645 inst_base->idx = index; 1523 inst_base->idx = index;
1646 inst_base->br = TransExtData::NON_BRANCH; 1524 inst_base->br = TransExtData::NON_BRANCH;
1647 1525
1648 inst_cream->I = BIT(inst, 25); 1526 inst_cream->I = BIT(inst, 25);
1649 inst_cream->S = BIT(inst, 20); 1527 inst_cream->S = BIT(inst, 20);
1650 inst_cream->Rn = BITS(inst, 16, 19); 1528 inst_cream->Rn = BITS(inst, 16, 19);
1651 inst_cream->Rd = BITS(inst, 12, 15); 1529 inst_cream->Rd = BITS(inst, 12, 15);
1652 inst_cream->shifter_operand = BITS(inst, 0, 11); 1530 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -1655,309 +1533,274 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index)
1655 return inst_base; 1533 return inst_base;
1656} 1534}
1657 1535
1658static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) 1536static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) {
1659{
1660 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 1537 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1661 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 1538 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1662 1539
1663 inst_base->cond = BITS(inst, 28, 31); 1540 inst_base->cond = BITS(inst, 28, 31);
1664 inst_base->idx = index; 1541 inst_base->idx = index;
1665 inst_base->br = TransExtData::NON_BRANCH; 1542 inst_base->br = TransExtData::NON_BRANCH;
1666 1543
1667 inst_cream->op1 = BITS(inst, 20, 21); 1544 inst_cream->op1 = BITS(inst, 20, 21);
1668 inst_cream->op2 = BITS(inst, 5, 7); 1545 inst_cream->op2 = BITS(inst, 5, 7);
1669 inst_cream->Rm = BITS(inst, 0, 3); 1546 inst_cream->Rm = BITS(inst, 0, 3);
1670 inst_cream->Rn = BITS(inst, 16, 19); 1547 inst_cream->Rn = BITS(inst, 16, 19);
1671 inst_cream->Rd = BITS(inst, 12, 15); 1548 inst_cream->Rd = BITS(inst, 12, 15);
1672 1549
1673 return inst_base; 1550 return inst_base;
1674} 1551}
1675static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) 1552static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) {
1676{
1677 return INTERPRETER_TRANSLATE(uadd8)(inst, index); 1553 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1678} 1554}
1679static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) 1555static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) {
1680{
1681 return INTERPRETER_TRANSLATE(uadd8)(inst, index); 1556 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1682} 1557}
1683static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) 1558static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) {
1684{
1685 return INTERPRETER_TRANSLATE(uadd8)(inst, index); 1559 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1686} 1560}
1687static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) 1561static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) {
1688{
1689 return INTERPRETER_TRANSLATE(uadd8)(inst, index); 1562 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1690} 1563}
1691static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) 1564static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) {
1692{
1693 return INTERPRETER_TRANSLATE(uadd8)(inst, index); 1565 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1694} 1566}
1695 1567
1696static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) 1568static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) {
1697{
1698 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 1569 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1699 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 1570 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1700 1571
1701 inst_base->cond = BITS(inst, 28, 31); 1572 inst_base->cond = BITS(inst, 28, 31);
1702 inst_base->idx = index; 1573 inst_base->idx = index;
1703 inst_base->br = TransExtData::NON_BRANCH; 1574 inst_base->br = TransExtData::NON_BRANCH;
1704 1575
1705 inst_cream->op1 = BITS(inst, 20, 21); 1576 inst_cream->op1 = BITS(inst, 20, 21);
1706 inst_cream->op2 = BITS(inst, 5, 7); 1577 inst_cream->op2 = BITS(inst, 5, 7);
1707 inst_cream->Rm = BITS(inst, 0, 3); 1578 inst_cream->Rm = BITS(inst, 0, 3);
1708 inst_cream->Rn = BITS(inst, 16, 19); 1579 inst_cream->Rn = BITS(inst, 16, 19);
1709 inst_cream->Rd = BITS(inst, 12, 15); 1580 inst_cream->Rd = BITS(inst, 12, 15);
1710 1581
1711 return inst_base; 1582 return inst_base;
1712} 1583}
1713static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) 1584static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) {
1714{
1715 return INTERPRETER_TRANSLATE(uhadd8)(inst, index); 1585 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1716} 1586}
1717static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) 1587static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) {
1718{
1719 return INTERPRETER_TRANSLATE(uhadd8)(inst, index); 1588 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1720} 1589}
1721static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) 1590static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) {
1722{
1723 return INTERPRETER_TRANSLATE(uhadd8)(inst, index); 1591 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1724} 1592}
1725static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) 1593static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) {
1726{
1727 return INTERPRETER_TRANSLATE(uhadd8)(inst, index); 1594 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1728} 1595}
1729static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) 1596static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) {
1730{
1731 return INTERPRETER_TRANSLATE(uhadd8)(inst, index); 1597 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1732} 1598}
1733static ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) 1599static ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) {
1734{
1735 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst)); 1600 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst));
1736 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; 1601 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
1737 1602
1738 inst_base->cond = BITS(inst, 28, 31); 1603 inst_base->cond = BITS(inst, 28, 31);
1739 inst_base->idx = index; 1604 inst_base->idx = index;
1740 inst_base->br = TransExtData::NON_BRANCH; 1605 inst_base->br = TransExtData::NON_BRANCH;
1741 1606
1742 inst_cream->Rm = BITS(inst, 8, 11); 1607 inst_cream->Rm = BITS(inst, 8, 11);
1743 inst_cream->Rn = BITS(inst, 0, 3); 1608 inst_cream->Rn = BITS(inst, 0, 3);
1744 inst_cream->RdLo = BITS(inst, 12, 15); 1609 inst_cream->RdLo = BITS(inst, 12, 15);
1745 inst_cream->RdHi = BITS(inst, 16, 19); 1610 inst_cream->RdHi = BITS(inst, 16, 19);
1746 1611
1747 return inst_base; 1612 return inst_base;
1748} 1613}
1749static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) 1614static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) {
1750{ 1615 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
1751 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); 1616 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
1752 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
1753 1617
1754 inst_base->cond = BITS(inst, 28, 31); 1618 inst_base->cond = BITS(inst, 28, 31);
1755 inst_base->idx = index; 1619 inst_base->idx = index;
1756 inst_base->br = TransExtData::NON_BRANCH; 1620 inst_base->br = TransExtData::NON_BRANCH;
1757 1621
1758 inst_cream->S = BIT(inst, 20); 1622 inst_cream->S = BIT(inst, 20);
1759 inst_cream->Rm = BITS(inst, 0, 3); 1623 inst_cream->Rm = BITS(inst, 0, 3);
1760 inst_cream->Rs = BITS(inst, 8, 11); 1624 inst_cream->Rs = BITS(inst, 8, 11);
1761 inst_cream->RdHi = BITS(inst, 16, 19); 1625 inst_cream->RdHi = BITS(inst, 16, 19);
1762 inst_cream->RdLo = BITS(inst, 12, 15); 1626 inst_cream->RdLo = BITS(inst, 12, 15);
1763 1627
1764 return inst_base; 1628 return inst_base;
1765} 1629}
1766static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index) 1630static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index) {
1767{ 1631 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
1768 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); 1632 umull_inst* inst_cream = (umull_inst*)inst_base->component;
1769 umull_inst *inst_cream = (umull_inst *)inst_base->component;
1770 1633
1771 inst_base->cond = BITS(inst, 28, 31); 1634 inst_base->cond = BITS(inst, 28, 31);
1772 inst_base->idx = index; 1635 inst_base->idx = index;
1773 inst_base->br = TransExtData::NON_BRANCH; 1636 inst_base->br = TransExtData::NON_BRANCH;
1774 1637
1775 inst_cream->S = BIT(inst, 20); 1638 inst_cream->S = BIT(inst, 20);
1776 inst_cream->Rm = BITS(inst, 0, 3); 1639 inst_cream->Rm = BITS(inst, 0, 3);
1777 inst_cream->Rs = BITS(inst, 8, 11); 1640 inst_cream->Rs = BITS(inst, 8, 11);
1778 inst_cream->RdHi = BITS(inst, 16, 19); 1641 inst_cream->RdHi = BITS(inst, 16, 19);
1779 inst_cream->RdLo = BITS(inst, 12, 15); 1642 inst_cream->RdLo = BITS(inst, 12, 15);
1780 1643
1781 return inst_base; 1644 return inst_base;
1782} 1645}
1783 1646
1784static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index) 1647static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index) {
1785{ 1648 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb));
1786 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb)); 1649 b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component;
1787 b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component;
1788 1650
1789 inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0); 1651 inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0);
1790 1652
1791 inst_base->idx = index; 1653 inst_base->idx = index;
1792 inst_base->br = TransExtData::DIRECT_BRANCH; 1654 inst_base->br = TransExtData::DIRECT_BRANCH;
1793 1655
1794 return inst_base; 1656 return inst_base;
1795} 1657}
1796 1658
1797static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index) 1659static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index) {
1798{ 1660 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb));
1799 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb)); 1661 b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component;
1800 b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component;
1801 1662
1802 inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0)); 1663 inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0));
1803 inst_cream->cond = ((tinst >> 8) & 0xf); 1664 inst_cream->cond = ((tinst >> 8) & 0xf);
1804 inst_base->idx = index; 1665 inst_base->idx = index;
1805 inst_base->br = TransExtData::DIRECT_BRANCH; 1666 inst_base->br = TransExtData::DIRECT_BRANCH;
1806 1667
1807 return inst_base; 1668 return inst_base;
1808} 1669}
1809 1670
1810static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index) 1671static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index) {
1811{ 1672 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb));
1812 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb)); 1673 bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component;
1813 bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component;
1814 1674
1815 inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0)); 1675 inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0));
1816 1676
1817 inst_base->idx = index; 1677 inst_base->idx = index;
1818 inst_base->br = TransExtData::NON_BRANCH; 1678 inst_base->br = TransExtData::NON_BRANCH;
1819 return inst_base; 1679 return inst_base;
1820} 1680}
1821static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index) 1681static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index) {
1822{ 1682 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb));
1823 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb)); 1683 bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component;
1824 bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component;
1825 1684
1826 inst_cream->imm = (tinst & 0x07FF) << 1; 1685 inst_cream->imm = (tinst & 0x07FF) << 1;
1827 1686
1828 inst_base->idx = index; 1687 inst_base->idx = index;
1829 inst_base->br = TransExtData::DIRECT_BRANCH; 1688 inst_base->br = TransExtData::DIRECT_BRANCH;
1830 return inst_base; 1689 return inst_base;
1831} 1690}
1832static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) 1691static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) {
1833{ 1692 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb));
1834 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb)); 1693 blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component;
1835 blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component;
1836 1694
1837 inst_cream->imm = (tinst & 0x07FF) << 1; 1695 inst_cream->imm = (tinst & 0x07FF) << 1;
1838 inst_cream->instr = tinst; 1696 inst_cream->instr = tinst;
1839 1697
1840 inst_base->idx = index; 1698 inst_base->idx = index;
1841 inst_base->br = TransExtData::DIRECT_BRANCH; 1699 inst_base->br = TransExtData::DIRECT_BRANCH;
1842 return inst_base; 1700 return inst_base;
1843} 1701}
1844 1702
1845static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) 1703static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) {
1846{
1847 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 1704 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1848 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 1705 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1849 1706
1850 inst_base->cond = BITS(inst, 28, 31); 1707 inst_base->cond = BITS(inst, 28, 31);
1851 inst_base->idx = index; 1708 inst_base->idx = index;
1852 inst_base->br = TransExtData::NON_BRANCH; 1709 inst_base->br = TransExtData::NON_BRANCH;
1853 1710
1854 inst_cream->Rm = BITS(inst, 0, 3); 1711 inst_cream->Rm = BITS(inst, 0, 3);
1855 inst_cream->Rn = BITS(inst, 16, 19); 1712 inst_cream->Rn = BITS(inst, 16, 19);
1856 inst_cream->Rd = BITS(inst, 12, 15); 1713 inst_cream->Rd = BITS(inst, 12, 15);
1857 inst_cream->op1 = BITS(inst, 20, 21); 1714 inst_cream->op1 = BITS(inst, 20, 21);
1858 inst_cream->op2 = BITS(inst, 5, 7); 1715 inst_cream->op2 = BITS(inst, 5, 7);
1859 1716
1860 return inst_base; 1717 return inst_base;
1861} 1718}
1862static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) 1719static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) {
1863{
1864 return INTERPRETER_TRANSLATE(uqadd8)(inst, index); 1720 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1865} 1721}
1866static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) 1722static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) {
1867{
1868 return INTERPRETER_TRANSLATE(uqadd8)(inst, index); 1723 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1869} 1724}
1870static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) 1725static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) {
1871{
1872 return INTERPRETER_TRANSLATE(uqadd8)(inst, index); 1726 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1873} 1727}
1874static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) 1728static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) {
1875{
1876 return INTERPRETER_TRANSLATE(uqadd8)(inst, index); 1729 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1877} 1730}
1878static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) 1731static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) {
1879{
1880 return INTERPRETER_TRANSLATE(uqadd8)(inst, index); 1732 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1881} 1733}
1882static ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) 1734static ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) {
1883{
1884 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst)); 1735 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
1885 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 1736 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1886 1737
1887 inst_base->cond = BITS(inst, 28, 31); 1738 inst_base->cond = BITS(inst, 28, 31);
1888 inst_base->idx = index; 1739 inst_base->idx = index;
1889 inst_base->br = TransExtData::NON_BRANCH; 1740 inst_base->br = TransExtData::NON_BRANCH;
1890 1741
1891 inst_cream->op1 = BITS(inst, 20, 24); 1742 inst_cream->op1 = BITS(inst, 20, 24);
1892 inst_cream->op2 = BITS(inst, 5, 7); 1743 inst_cream->op2 = BITS(inst, 5, 7);
1893 inst_cream->Rd = BITS(inst, 16, 19); 1744 inst_cream->Rd = BITS(inst, 16, 19);
1894 inst_cream->Rm = BITS(inst, 8, 11); 1745 inst_cream->Rm = BITS(inst, 8, 11);
1895 inst_cream->Rn = BITS(inst, 0, 3); 1746 inst_cream->Rn = BITS(inst, 0, 3);
1896 inst_cream->Ra = BITS(inst, 12, 15); 1747 inst_cream->Ra = BITS(inst, 12, 15);
1897 1748
1898 return inst_base; 1749 return inst_base;
1899} 1750}
1900static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) 1751static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) {
1901{
1902 return INTERPRETER_TRANSLATE(usada8)(inst, index); 1752 return INTERPRETER_TRANSLATE(usada8)(inst, index);
1903} 1753}
1904static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) 1754static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) {
1905{
1906 return INTERPRETER_TRANSLATE(ssat)(inst, index); 1755 return INTERPRETER_TRANSLATE(ssat)(inst, index);
1907} 1756}
1908static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) 1757static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) {
1909{
1910 return INTERPRETER_TRANSLATE(ssat16)(inst, index); 1758 return INTERPRETER_TRANSLATE(ssat16)(inst, index);
1911} 1759}
1912 1760
1913static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) 1761static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) {
1914{
1915 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); 1762 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
1916 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component; 1763 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
1917 1764
1918 inst_base->cond = BITS(inst, 28, 31); 1765 inst_base->cond = BITS(inst, 28, 31);
1919 inst_base->idx = index; 1766 inst_base->idx = index;
1920 inst_base->br = TransExtData::NON_BRANCH; 1767 inst_base->br = TransExtData::NON_BRANCH;
1921 1768
1922 inst_cream->Rm = BITS(inst, 0, 3); 1769 inst_cream->Rm = BITS(inst, 0, 3);
1923 inst_cream->Rn = BITS(inst, 16, 19); 1770 inst_cream->Rn = BITS(inst, 16, 19);
1924 inst_cream->Rd = BITS(inst, 12, 15); 1771 inst_cream->Rd = BITS(inst, 12, 15);
1925 inst_cream->rotate = BITS(inst, 10, 11); 1772 inst_cream->rotate = BITS(inst, 10, 11);
1926 1773
1927 return inst_base; 1774 return inst_base;
1928} 1775}
1929static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) 1776static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) {
1930{
1931 return INTERPRETER_TRANSLATE(uxtab16)(inst, index); 1777 return INTERPRETER_TRANSLATE(uxtab16)(inst, index);
1932} 1778}
1933 1779
1934static ARM_INST_PTR INTERPRETER_TRANSLATE(wfe)(unsigned int inst, int index) 1780static ARM_INST_PTR INTERPRETER_TRANSLATE(wfe)(unsigned int inst, int index) {
1935{
1936 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); 1781 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
1937 1782
1938 inst_base->cond = BITS(inst, 28, 31); 1783 inst_base->cond = BITS(inst, 28, 31);
1939 inst_base->idx = index; 1784 inst_base->idx = index;
1940 inst_base->br = TransExtData::NON_BRANCH; 1785 inst_base->br = TransExtData::NON_BRANCH;
1941 1786
1942 return inst_base; 1787 return inst_base;
1943} 1788}
1944static ARM_INST_PTR INTERPRETER_TRANSLATE(wfi)(unsigned int inst, int index) 1789static ARM_INST_PTR INTERPRETER_TRANSLATE(wfi)(unsigned int inst, int index) {
1945{
1946 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); 1790 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
1947 1791
1948 inst_base->cond = BITS(inst, 28, 31); 1792 inst_base->cond = BITS(inst, 28, 31);
1949 inst_base->idx = index; 1793 inst_base->idx = index;
1950 inst_base->br = TransExtData::NON_BRANCH; 1794 inst_base->br = TransExtData::NON_BRANCH;
1951 1795
1952 return inst_base; 1796 return inst_base;
1953} 1797}
1954static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) 1798static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) {
1955{
1956 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); 1799 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
1957 1800
1958 inst_base->cond = BITS(inst, 28, 31); 1801 inst_base->cond = BITS(inst, 28, 31);
1959 inst_base->idx = index; 1802 inst_base->idx = index;
1960 inst_base->br = TransExtData::NON_BRANCH; 1803 inst_base->br = TransExtData::NON_BRANCH;
1961 1804
1962 return inst_base; 1805 return inst_base;
1963} 1806}
@@ -1968,211 +1811,78 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index)
1968#undef VFP_INTERPRETER_TRANS 1811#undef VFP_INTERPRETER_TRANS
1969 1812
1970const transop_fp_t arm_instruction_trans[] = { 1813const transop_fp_t arm_instruction_trans[] = {
1971 INTERPRETER_TRANSLATE(vmla), 1814 INTERPRETER_TRANSLATE(vmla), INTERPRETER_TRANSLATE(vmls), INTERPRETER_TRANSLATE(vnmla),
1972 INTERPRETER_TRANSLATE(vmls), 1815 INTERPRETER_TRANSLATE(vnmls), INTERPRETER_TRANSLATE(vnmul), INTERPRETER_TRANSLATE(vmul),
1973 INTERPRETER_TRANSLATE(vnmla), 1816 INTERPRETER_TRANSLATE(vadd), INTERPRETER_TRANSLATE(vsub), INTERPRETER_TRANSLATE(vdiv),
1974 INTERPRETER_TRANSLATE(vnmls), 1817 INTERPRETER_TRANSLATE(vmovi), INTERPRETER_TRANSLATE(vmovr), INTERPRETER_TRANSLATE(vabs),
1975 INTERPRETER_TRANSLATE(vnmul), 1818 INTERPRETER_TRANSLATE(vneg), INTERPRETER_TRANSLATE(vsqrt), INTERPRETER_TRANSLATE(vcmp),
1976 INTERPRETER_TRANSLATE(vmul), 1819 INTERPRETER_TRANSLATE(vcmp2), INTERPRETER_TRANSLATE(vcvtbds), INTERPRETER_TRANSLATE(vcvtbff),
1977 INTERPRETER_TRANSLATE(vadd), 1820 INTERPRETER_TRANSLATE(vcvtbfi), INTERPRETER_TRANSLATE(vmovbrs), INTERPRETER_TRANSLATE(vmsr),
1978 INTERPRETER_TRANSLATE(vsub), 1821 INTERPRETER_TRANSLATE(vmovbrc), INTERPRETER_TRANSLATE(vmrs), INTERPRETER_TRANSLATE(vmovbcr),
1979 INTERPRETER_TRANSLATE(vdiv), 1822 INTERPRETER_TRANSLATE(vmovbrrss), INTERPRETER_TRANSLATE(vmovbrrd), INTERPRETER_TRANSLATE(vstr),
1980 INTERPRETER_TRANSLATE(vmovi), 1823 INTERPRETER_TRANSLATE(vpush), INTERPRETER_TRANSLATE(vstm), INTERPRETER_TRANSLATE(vpop),
1981 INTERPRETER_TRANSLATE(vmovr), 1824 INTERPRETER_TRANSLATE(vldr), INTERPRETER_TRANSLATE(vldm),
1982 INTERPRETER_TRANSLATE(vabs), 1825
1983 INTERPRETER_TRANSLATE(vneg), 1826 INTERPRETER_TRANSLATE(srs), INTERPRETER_TRANSLATE(rfe), INTERPRETER_TRANSLATE(bkpt),
1984 INTERPRETER_TRANSLATE(vsqrt), 1827 INTERPRETER_TRANSLATE(blx), INTERPRETER_TRANSLATE(cps), INTERPRETER_TRANSLATE(pld),
1985 INTERPRETER_TRANSLATE(vcmp), 1828 INTERPRETER_TRANSLATE(setend), INTERPRETER_TRANSLATE(clrex), INTERPRETER_TRANSLATE(rev16),
1986 INTERPRETER_TRANSLATE(vcmp2), 1829 INTERPRETER_TRANSLATE(usad8), INTERPRETER_TRANSLATE(sxtb), INTERPRETER_TRANSLATE(uxtb),
1987 INTERPRETER_TRANSLATE(vcvtbds), 1830 INTERPRETER_TRANSLATE(sxth), INTERPRETER_TRANSLATE(sxtb16), INTERPRETER_TRANSLATE(uxth),
1988 INTERPRETER_TRANSLATE(vcvtbff), 1831 INTERPRETER_TRANSLATE(uxtb16), INTERPRETER_TRANSLATE(cpy), INTERPRETER_TRANSLATE(uxtab),
1989 INTERPRETER_TRANSLATE(vcvtbfi), 1832 INTERPRETER_TRANSLATE(ssub8), INTERPRETER_TRANSLATE(shsub8), INTERPRETER_TRANSLATE(ssubaddx),
1990 INTERPRETER_TRANSLATE(vmovbrs), 1833 INTERPRETER_TRANSLATE(strex), INTERPRETER_TRANSLATE(strexb), INTERPRETER_TRANSLATE(swp),
1991 INTERPRETER_TRANSLATE(vmsr), 1834 INTERPRETER_TRANSLATE(swpb), INTERPRETER_TRANSLATE(ssub16), INTERPRETER_TRANSLATE(ssat16),
1992 INTERPRETER_TRANSLATE(vmovbrc), 1835 INTERPRETER_TRANSLATE(shsubaddx), INTERPRETER_TRANSLATE(qsubaddx),
1993 INTERPRETER_TRANSLATE(vmrs), 1836 INTERPRETER_TRANSLATE(shaddsubx), INTERPRETER_TRANSLATE(shadd8), INTERPRETER_TRANSLATE(shadd16),
1994 INTERPRETER_TRANSLATE(vmovbcr), 1837 INTERPRETER_TRANSLATE(sel), INTERPRETER_TRANSLATE(saddsubx), INTERPRETER_TRANSLATE(sadd8),
1995 INTERPRETER_TRANSLATE(vmovbrrss), 1838 INTERPRETER_TRANSLATE(sadd16), INTERPRETER_TRANSLATE(shsub16), INTERPRETER_TRANSLATE(umaal),
1996 INTERPRETER_TRANSLATE(vmovbrrd), 1839 INTERPRETER_TRANSLATE(uxtab16), INTERPRETER_TRANSLATE(usubaddx), INTERPRETER_TRANSLATE(usub8),
1997 INTERPRETER_TRANSLATE(vstr), 1840 INTERPRETER_TRANSLATE(usub16), INTERPRETER_TRANSLATE(usat16), INTERPRETER_TRANSLATE(usada8),
1998 INTERPRETER_TRANSLATE(vpush), 1841 INTERPRETER_TRANSLATE(uqsubaddx), INTERPRETER_TRANSLATE(uqsub8), INTERPRETER_TRANSLATE(uqsub16),
1999 INTERPRETER_TRANSLATE(vstm), 1842 INTERPRETER_TRANSLATE(uqaddsubx), INTERPRETER_TRANSLATE(uqadd8), INTERPRETER_TRANSLATE(uqadd16),
2000 INTERPRETER_TRANSLATE(vpop), 1843 INTERPRETER_TRANSLATE(sxtab), INTERPRETER_TRANSLATE(uhsubaddx), INTERPRETER_TRANSLATE(uhsub8),
2001 INTERPRETER_TRANSLATE(vldr), 1844 INTERPRETER_TRANSLATE(uhsub16), INTERPRETER_TRANSLATE(uhaddsubx), INTERPRETER_TRANSLATE(uhadd8),
2002 INTERPRETER_TRANSLATE(vldm), 1845 INTERPRETER_TRANSLATE(uhadd16), INTERPRETER_TRANSLATE(uaddsubx), INTERPRETER_TRANSLATE(uadd8),
2003 1846 INTERPRETER_TRANSLATE(uadd16), INTERPRETER_TRANSLATE(sxtah), INTERPRETER_TRANSLATE(sxtab16),
2004 INTERPRETER_TRANSLATE(srs), 1847 INTERPRETER_TRANSLATE(qadd8), INTERPRETER_TRANSLATE(bxj), INTERPRETER_TRANSLATE(clz),
2005 INTERPRETER_TRANSLATE(rfe), 1848 INTERPRETER_TRANSLATE(uxtah), INTERPRETER_TRANSLATE(bx), INTERPRETER_TRANSLATE(rev),
2006 INTERPRETER_TRANSLATE(bkpt), 1849 INTERPRETER_TRANSLATE(blx), INTERPRETER_TRANSLATE(revsh), INTERPRETER_TRANSLATE(qadd),
2007 INTERPRETER_TRANSLATE(blx), 1850 INTERPRETER_TRANSLATE(qadd16), INTERPRETER_TRANSLATE(qaddsubx), INTERPRETER_TRANSLATE(ldrex),
2008 INTERPRETER_TRANSLATE(cps), 1851 INTERPRETER_TRANSLATE(qdadd), INTERPRETER_TRANSLATE(qdsub), INTERPRETER_TRANSLATE(qsub),
2009 INTERPRETER_TRANSLATE(pld), 1852 INTERPRETER_TRANSLATE(ldrexb), INTERPRETER_TRANSLATE(qsub8), INTERPRETER_TRANSLATE(qsub16),
2010 INTERPRETER_TRANSLATE(setend), 1853 INTERPRETER_TRANSLATE(smuad), INTERPRETER_TRANSLATE(smmul), INTERPRETER_TRANSLATE(smusd),
2011 INTERPRETER_TRANSLATE(clrex), 1854 INTERPRETER_TRANSLATE(smlsd), INTERPRETER_TRANSLATE(smlsld), INTERPRETER_TRANSLATE(smmla),
2012 INTERPRETER_TRANSLATE(rev16), 1855 INTERPRETER_TRANSLATE(smmls), INTERPRETER_TRANSLATE(smlald), INTERPRETER_TRANSLATE(smlad),
2013 INTERPRETER_TRANSLATE(usad8), 1856 INTERPRETER_TRANSLATE(smlaw), INTERPRETER_TRANSLATE(smulw), INTERPRETER_TRANSLATE(pkhtb),
2014 INTERPRETER_TRANSLATE(sxtb), 1857 INTERPRETER_TRANSLATE(pkhbt), INTERPRETER_TRANSLATE(smul), INTERPRETER_TRANSLATE(smlalxy),
2015 INTERPRETER_TRANSLATE(uxtb), 1858 INTERPRETER_TRANSLATE(smla), INTERPRETER_TRANSLATE(mcrr), INTERPRETER_TRANSLATE(mrrc),
2016 INTERPRETER_TRANSLATE(sxth), 1859 INTERPRETER_TRANSLATE(cmp), INTERPRETER_TRANSLATE(tst), INTERPRETER_TRANSLATE(teq),
2017 INTERPRETER_TRANSLATE(sxtb16), 1860 INTERPRETER_TRANSLATE(cmn), INTERPRETER_TRANSLATE(smull), INTERPRETER_TRANSLATE(umull),
2018 INTERPRETER_TRANSLATE(uxth), 1861 INTERPRETER_TRANSLATE(umlal), INTERPRETER_TRANSLATE(smlal), INTERPRETER_TRANSLATE(mul),
2019 INTERPRETER_TRANSLATE(uxtb16), 1862 INTERPRETER_TRANSLATE(mla), INTERPRETER_TRANSLATE(ssat), INTERPRETER_TRANSLATE(usat),
2020 INTERPRETER_TRANSLATE(cpy), 1863 INTERPRETER_TRANSLATE(mrs), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(and),
2021 INTERPRETER_TRANSLATE(uxtab), 1864 INTERPRETER_TRANSLATE(bic), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(eor),
2022 INTERPRETER_TRANSLATE(ssub8), 1865 INTERPRETER_TRANSLATE(add), INTERPRETER_TRANSLATE(rsb), INTERPRETER_TRANSLATE(rsc),
2023 INTERPRETER_TRANSLATE(shsub8), 1866 INTERPRETER_TRANSLATE(sbc), INTERPRETER_TRANSLATE(adc), INTERPRETER_TRANSLATE(sub),
2024 INTERPRETER_TRANSLATE(ssubaddx), 1867 INTERPRETER_TRANSLATE(orr), INTERPRETER_TRANSLATE(mvn), INTERPRETER_TRANSLATE(mov),
2025 INTERPRETER_TRANSLATE(strex), 1868 INTERPRETER_TRANSLATE(stm), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(ldrsh),
2026 INTERPRETER_TRANSLATE(strexb), 1869 INTERPRETER_TRANSLATE(stm), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(ldrsb),
2027 INTERPRETER_TRANSLATE(swp), 1870 INTERPRETER_TRANSLATE(strd), INTERPRETER_TRANSLATE(ldrh), INTERPRETER_TRANSLATE(strh),
2028 INTERPRETER_TRANSLATE(swpb), 1871 INTERPRETER_TRANSLATE(ldrd), INTERPRETER_TRANSLATE(strt), INTERPRETER_TRANSLATE(strbt),
2029 INTERPRETER_TRANSLATE(ssub16), 1872 INTERPRETER_TRANSLATE(ldrbt), INTERPRETER_TRANSLATE(ldrt), INTERPRETER_TRANSLATE(mrc),
2030 INTERPRETER_TRANSLATE(ssat16), 1873 INTERPRETER_TRANSLATE(mcr), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr),
2031 INTERPRETER_TRANSLATE(shsubaddx), 1874 INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr),
2032 INTERPRETER_TRANSLATE(qsubaddx), 1875 INTERPRETER_TRANSLATE(ldrb), INTERPRETER_TRANSLATE(strb), INTERPRETER_TRANSLATE(ldr),
2033 INTERPRETER_TRANSLATE(shaddsubx), 1876 INTERPRETER_TRANSLATE(ldrcond), INTERPRETER_TRANSLATE(str), INTERPRETER_TRANSLATE(cdp),
2034 INTERPRETER_TRANSLATE(shadd8), 1877 INTERPRETER_TRANSLATE(stc), INTERPRETER_TRANSLATE(ldc), INTERPRETER_TRANSLATE(ldrexd),
2035 INTERPRETER_TRANSLATE(shadd16), 1878 INTERPRETER_TRANSLATE(strexd), INTERPRETER_TRANSLATE(ldrexh), INTERPRETER_TRANSLATE(strexh),
2036 INTERPRETER_TRANSLATE(sel), 1879 INTERPRETER_TRANSLATE(nop), INTERPRETER_TRANSLATE(yield), INTERPRETER_TRANSLATE(wfe),
2037 INTERPRETER_TRANSLATE(saddsubx), 1880 INTERPRETER_TRANSLATE(wfi), INTERPRETER_TRANSLATE(sev), INTERPRETER_TRANSLATE(swi),
2038 INTERPRETER_TRANSLATE(sadd8),
2039 INTERPRETER_TRANSLATE(sadd16),
2040 INTERPRETER_TRANSLATE(shsub16),
2041 INTERPRETER_TRANSLATE(umaal),
2042 INTERPRETER_TRANSLATE(uxtab16),
2043 INTERPRETER_TRANSLATE(usubaddx),
2044 INTERPRETER_TRANSLATE(usub8),
2045 INTERPRETER_TRANSLATE(usub16),
2046 INTERPRETER_TRANSLATE(usat16),
2047 INTERPRETER_TRANSLATE(usada8),
2048 INTERPRETER_TRANSLATE(uqsubaddx),
2049 INTERPRETER_TRANSLATE(uqsub8),
2050 INTERPRETER_TRANSLATE(uqsub16),
2051 INTERPRETER_TRANSLATE(uqaddsubx),
2052 INTERPRETER_TRANSLATE(uqadd8),
2053 INTERPRETER_TRANSLATE(uqadd16),
2054 INTERPRETER_TRANSLATE(sxtab),
2055 INTERPRETER_TRANSLATE(uhsubaddx),
2056 INTERPRETER_TRANSLATE(uhsub8),
2057 INTERPRETER_TRANSLATE(uhsub16),
2058 INTERPRETER_TRANSLATE(uhaddsubx),
2059 INTERPRETER_TRANSLATE(uhadd8),
2060 INTERPRETER_TRANSLATE(uhadd16),
2061 INTERPRETER_TRANSLATE(uaddsubx),
2062 INTERPRETER_TRANSLATE(uadd8),
2063 INTERPRETER_TRANSLATE(uadd16),
2064 INTERPRETER_TRANSLATE(sxtah),
2065 INTERPRETER_TRANSLATE(sxtab16),
2066 INTERPRETER_TRANSLATE(qadd8),
2067 INTERPRETER_TRANSLATE(bxj),
2068 INTERPRETER_TRANSLATE(clz),
2069 INTERPRETER_TRANSLATE(uxtah),
2070 INTERPRETER_TRANSLATE(bx),
2071 INTERPRETER_TRANSLATE(rev),
2072 INTERPRETER_TRANSLATE(blx),
2073 INTERPRETER_TRANSLATE(revsh),
2074 INTERPRETER_TRANSLATE(qadd),
2075 INTERPRETER_TRANSLATE(qadd16),
2076 INTERPRETER_TRANSLATE(qaddsubx),
2077 INTERPRETER_TRANSLATE(ldrex),
2078 INTERPRETER_TRANSLATE(qdadd),
2079 INTERPRETER_TRANSLATE(qdsub),
2080 INTERPRETER_TRANSLATE(qsub),
2081 INTERPRETER_TRANSLATE(ldrexb),
2082 INTERPRETER_TRANSLATE(qsub8),
2083 INTERPRETER_TRANSLATE(qsub16),
2084 INTERPRETER_TRANSLATE(smuad),
2085 INTERPRETER_TRANSLATE(smmul),
2086 INTERPRETER_TRANSLATE(smusd),
2087 INTERPRETER_TRANSLATE(smlsd),
2088 INTERPRETER_TRANSLATE(smlsld),
2089 INTERPRETER_TRANSLATE(smmla),
2090 INTERPRETER_TRANSLATE(smmls),
2091 INTERPRETER_TRANSLATE(smlald),
2092 INTERPRETER_TRANSLATE(smlad),
2093 INTERPRETER_TRANSLATE(smlaw),
2094 INTERPRETER_TRANSLATE(smulw),
2095 INTERPRETER_TRANSLATE(pkhtb),
2096 INTERPRETER_TRANSLATE(pkhbt),
2097 INTERPRETER_TRANSLATE(smul),
2098 INTERPRETER_TRANSLATE(smlalxy),
2099 INTERPRETER_TRANSLATE(smla),
2100 INTERPRETER_TRANSLATE(mcrr),
2101 INTERPRETER_TRANSLATE(mrrc),
2102 INTERPRETER_TRANSLATE(cmp),
2103 INTERPRETER_TRANSLATE(tst),
2104 INTERPRETER_TRANSLATE(teq),
2105 INTERPRETER_TRANSLATE(cmn),
2106 INTERPRETER_TRANSLATE(smull),
2107 INTERPRETER_TRANSLATE(umull),
2108 INTERPRETER_TRANSLATE(umlal),
2109 INTERPRETER_TRANSLATE(smlal),
2110 INTERPRETER_TRANSLATE(mul),
2111 INTERPRETER_TRANSLATE(mla),
2112 INTERPRETER_TRANSLATE(ssat),
2113 INTERPRETER_TRANSLATE(usat),
2114 INTERPRETER_TRANSLATE(mrs),
2115 INTERPRETER_TRANSLATE(msr),
2116 INTERPRETER_TRANSLATE(and),
2117 INTERPRETER_TRANSLATE(bic),
2118 INTERPRETER_TRANSLATE(ldm),
2119 INTERPRETER_TRANSLATE(eor),
2120 INTERPRETER_TRANSLATE(add),
2121 INTERPRETER_TRANSLATE(rsb),
2122 INTERPRETER_TRANSLATE(rsc),
2123 INTERPRETER_TRANSLATE(sbc),
2124 INTERPRETER_TRANSLATE(adc),
2125 INTERPRETER_TRANSLATE(sub),
2126 INTERPRETER_TRANSLATE(orr),
2127 INTERPRETER_TRANSLATE(mvn),
2128 INTERPRETER_TRANSLATE(mov),
2129 INTERPRETER_TRANSLATE(stm),
2130 INTERPRETER_TRANSLATE(ldm),
2131 INTERPRETER_TRANSLATE(ldrsh),
2132 INTERPRETER_TRANSLATE(stm),
2133 INTERPRETER_TRANSLATE(ldm),
2134 INTERPRETER_TRANSLATE(ldrsb),
2135 INTERPRETER_TRANSLATE(strd),
2136 INTERPRETER_TRANSLATE(ldrh),
2137 INTERPRETER_TRANSLATE(strh),
2138 INTERPRETER_TRANSLATE(ldrd),
2139 INTERPRETER_TRANSLATE(strt),
2140 INTERPRETER_TRANSLATE(strbt),
2141 INTERPRETER_TRANSLATE(ldrbt),
2142 INTERPRETER_TRANSLATE(ldrt),
2143 INTERPRETER_TRANSLATE(mrc),
2144 INTERPRETER_TRANSLATE(mcr),
2145 INTERPRETER_TRANSLATE(msr),
2146 INTERPRETER_TRANSLATE(msr),
2147 INTERPRETER_TRANSLATE(msr),
2148 INTERPRETER_TRANSLATE(msr),
2149 INTERPRETER_TRANSLATE(msr),
2150 INTERPRETER_TRANSLATE(ldrb),
2151 INTERPRETER_TRANSLATE(strb),
2152 INTERPRETER_TRANSLATE(ldr),
2153 INTERPRETER_TRANSLATE(ldrcond),
2154 INTERPRETER_TRANSLATE(str),
2155 INTERPRETER_TRANSLATE(cdp),
2156 INTERPRETER_TRANSLATE(stc),
2157 INTERPRETER_TRANSLATE(ldc),
2158 INTERPRETER_TRANSLATE(ldrexd),
2159 INTERPRETER_TRANSLATE(strexd),
2160 INTERPRETER_TRANSLATE(ldrexh),
2161 INTERPRETER_TRANSLATE(strexh),
2162 INTERPRETER_TRANSLATE(nop),
2163 INTERPRETER_TRANSLATE(yield),
2164 INTERPRETER_TRANSLATE(wfe),
2165 INTERPRETER_TRANSLATE(wfi),
2166 INTERPRETER_TRANSLATE(sev),
2167 INTERPRETER_TRANSLATE(swi),
2168 INTERPRETER_TRANSLATE(bbl), 1881 INTERPRETER_TRANSLATE(bbl),
2169 1882
2170 // All the thumb instructions should be placed the end of table 1883 // All the thumb instructions should be placed the end of table
2171 INTERPRETER_TRANSLATE(b_2_thumb), 1884 INTERPRETER_TRANSLATE(b_2_thumb), INTERPRETER_TRANSLATE(b_cond_thumb),
2172 INTERPRETER_TRANSLATE(b_cond_thumb), 1885 INTERPRETER_TRANSLATE(bl_1_thumb), INTERPRETER_TRANSLATE(bl_2_thumb),
2173 INTERPRETER_TRANSLATE(bl_1_thumb), 1886 INTERPRETER_TRANSLATE(blx_1_thumb)};
2174 INTERPRETER_TRANSLATE(bl_2_thumb),
2175 INTERPRETER_TRANSLATE(blx_1_thumb)
2176};
2177 1887
2178const size_t arm_instruction_trans_len = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); 1888const size_t arm_instruction_trans_len = sizeof(arm_instruction_trans) / sizeof(transop_fp_t);
diff --git a/src/core/arm/dyncom/arm_dyncom_trans.h b/src/core/arm/dyncom/arm_dyncom_trans.h
index 7af71f4e3..6fdb3d248 100644
--- a/src/core/arm/dyncom/arm_dyncom_trans.h
+++ b/src/core/arm/dyncom/arm_dyncom_trans.h
@@ -2,15 +2,15 @@ struct ARMul_State;
2typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); 2typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
3 3
4enum class TransExtData { 4enum class TransExtData {
5 COND = (1 << 0), 5 COND = (1 << 0),
6 NON_BRANCH = (1 << 1), 6 NON_BRANCH = (1 << 1),
7 DIRECT_BRANCH = (1 << 2), 7 DIRECT_BRANCH = (1 << 2),
8 INDIRECT_BRANCH = (1 << 3), 8 INDIRECT_BRANCH = (1 << 3),
9 CALL = (1 << 4), 9 CALL = (1 << 4),
10 RET = (1 << 5), 10 RET = (1 << 5),
11 END_OF_PAGE = (1 << 6), 11 END_OF_PAGE = (1 << 6),
12 THUMB = (1 << 7), 12 THUMB = (1 << 7),
13 SINGLE_STEP = (1 << 8) 13 SINGLE_STEP = (1 << 8)
14}; 14};
15 15
16struct arm_inst { 16struct arm_inst {
@@ -106,8 +106,7 @@ struct cps_inst {
106 unsigned int mode; 106 unsigned int mode;
107}; 107};
108 108
109struct clrex_inst { 109struct clrex_inst {};
110};
111 110
112struct cpy_inst { 111struct cpy_inst {
113 unsigned int Rm; 112 unsigned int Rm;
@@ -163,11 +162,9 @@ struct bkpt_inst {
163 u32 imm; 162 u32 imm;
164}; 163};
165 164
166struct stc_inst { 165struct stc_inst {};
167};
168 166
169struct ldc_inst { 167struct ldc_inst {};
170};
171 168
172struct swi_inst { 169struct swi_inst {
173 unsigned int num; 170 unsigned int num;
@@ -369,8 +366,7 @@ struct msr_inst {
369 unsigned int inst; 366 unsigned int inst;
370}; 367};
371 368
372struct pld_inst { 369struct pld_inst {};
373};
374 370
375struct sxtb_inst { 371struct sxtb_inst {
376 unsigned int Rd; 372 unsigned int Rd;
@@ -475,7 +471,7 @@ struct pkh_inst {
475#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 471#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
476#undef VFP_INTERPRETER_STRUCT 472#undef VFP_INTERPRETER_STRUCT
477 473
478typedef void (*get_addr_fp_t)(ARMul_State *cpu, unsigned int inst, unsigned int &virt_addr); 474typedef void (*get_addr_fp_t)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr);
479 475
480struct ldst_inst { 476struct ldst_inst {
481 unsigned int inst; 477 unsigned int inst;
diff --git a/src/core/arm/skyeye_common/arm_regformat.h b/src/core/arm/skyeye_common/arm_regformat.h
index 38fa97ab9..706195a05 100644
--- a/src/core/arm/skyeye_common/arm_regformat.h
+++ b/src/core/arm/skyeye_common/arm_regformat.h
@@ -16,7 +16,7 @@ enum {
16 R12, 16 R12,
17 R13, 17 R13,
18 LR, 18 LR,
19 R15, //PC, 19 R15, // PC,
20 CPSR_REG, 20 CPSR_REG,
21 SPSR_REG, 21 SPSR_REG,
22 22
diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp
index 5550c112e..59329c656 100644
--- a/src/core/arm/skyeye_common/armstate.cpp
+++ b/src/core/arm/skyeye_common/armstate.cpp
@@ -2,22 +2,20 @@
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 "core/arm/skyeye_common/armstate.h"
5#include <algorithm> 6#include <algorithm>
6#include "common/swap.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/memory.h" 8#include "common/swap.h"
9#include "core/arm/skyeye_common/armstate.h"
10#include "core/arm/skyeye_common/vfp/vfp.h" 9#include "core/arm/skyeye_common/vfp/vfp.h"
11#include "core/gdbstub/gdbstub.h" 10#include "core/gdbstub/gdbstub.h"
11#include "core/memory.h"
12 12
13ARMul_State::ARMul_State(PrivilegeMode initial_mode) 13ARMul_State::ARMul_State(PrivilegeMode initial_mode) {
14{
15 Reset(); 14 Reset();
16 ChangePrivilegeMode(initial_mode); 15 ChangePrivilegeMode(initial_mode);
17} 16}
18 17
19void ARMul_State::ChangePrivilegeMode(u32 new_mode) 18void ARMul_State::ChangePrivilegeMode(u32 new_mode) {
20{
21 if (Mode == new_mode) 19 if (Mode == new_mode)
22 return; 20 return;
23 21
@@ -103,8 +101,7 @@ void ARMul_State::ChangePrivilegeMode(u32 new_mode)
103} 101}
104 102
105// Performs a reset 103// Performs a reset
106void ARMul_State::Reset() 104void ARMul_State::Reset() {
107{
108 VFPInit(this); 105 VFPInit(this);
109 106
110 // Set stack pointer to the top of the stack 107 // Set stack pointer to the top of the stack
@@ -128,8 +125,7 @@ void ARMul_State::Reset()
128} 125}
129 126
130// Resets certain MPCore CP15 values to their ARM-defined reset values. 127// Resets certain MPCore CP15 values to their ARM-defined reset values.
131void ARMul_State::ResetMPCoreCP15Registers() 128void ARMul_State::ResetMPCoreCP15Registers() {
132{
133 // c0 129 // c0
134 CP15[CP15_MAIN_ID] = 0x410FB024; 130 CP15[CP15_MAIN_ID] = 0x410FB024;
135 CP15[CP15_TLB_TYPE] = 0x00000800; 131 CP15[CP15_TLB_TYPE] = 0x00000800;
@@ -185,23 +181,20 @@ void ARMul_State::ResetMPCoreCP15Registers()
185 CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; 181 CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000;
186} 182}
187 183
188static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) 184static void CheckMemoryBreakpoint(u32 address, GDBStub::BreakpointType type) {
189{
190 if (GDBStub::g_server_enabled && GDBStub::CheckBreakpoint(address, type)) { 185 if (GDBStub::g_server_enabled && GDBStub::CheckBreakpoint(address, type)) {
191 LOG_DEBUG(Debug, "Found memory breakpoint @ %08x", address); 186 LOG_DEBUG(Debug, "Found memory breakpoint @ %08x", address);
192 GDBStub::Break(true); 187 GDBStub::Break(true);
193 } 188 }
194} 189}
195 190
196u8 ARMul_State::ReadMemory8(u32 address) const 191u8 ARMul_State::ReadMemory8(u32 address) const {
197{
198 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); 192 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
199 193
200 return Memory::Read8(address); 194 return Memory::Read8(address);
201} 195}
202 196
203u16 ARMul_State::ReadMemory16(u32 address) const 197u16 ARMul_State::ReadMemory16(u32 address) const {
204{
205 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); 198 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
206 199
207 u16 data = Memory::Read16(address); 200 u16 data = Memory::Read16(address);
@@ -212,8 +205,7 @@ u16 ARMul_State::ReadMemory16(u32 address) const
212 return data; 205 return data;
213} 206}
214 207
215u32 ARMul_State::ReadMemory32(u32 address) const 208u32 ARMul_State::ReadMemory32(u32 address) const {
216{
217 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); 209 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
218 210
219 u32 data = Memory::Read32(address); 211 u32 data = Memory::Read32(address);
@@ -224,8 +216,7 @@ u32 ARMul_State::ReadMemory32(u32 address) const
224 return data; 216 return data;
225} 217}
226 218
227u64 ARMul_State::ReadMemory64(u32 address) const 219u64 ARMul_State::ReadMemory64(u32 address) const {
228{
229 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read); 220 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Read);
230 221
231 u64 data = Memory::Read64(address); 222 u64 data = Memory::Read64(address);
@@ -236,15 +227,13 @@ u64 ARMul_State::ReadMemory64(u32 address) const
236 return data; 227 return data;
237} 228}
238 229
239void ARMul_State::WriteMemory8(u32 address, u8 data) 230void ARMul_State::WriteMemory8(u32 address, u8 data) {
240{
241 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); 231 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
242 232
243 Memory::Write8(address, data); 233 Memory::Write8(address, data);
244} 234}
245 235
246void ARMul_State::WriteMemory16(u32 address, u16 data) 236void ARMul_State::WriteMemory16(u32 address, u16 data) {
247{
248 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); 237 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
249 238
250 if (InBigEndianMode()) 239 if (InBigEndianMode())
@@ -253,8 +242,7 @@ void ARMul_State::WriteMemory16(u32 address, u16 data)
253 Memory::Write16(address, data); 242 Memory::Write16(address, data);
254} 243}
255 244
256void ARMul_State::WriteMemory32(u32 address, u32 data) 245void ARMul_State::WriteMemory32(u32 address, u32 data) {
257{
258 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); 246 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
259 247
260 if (InBigEndianMode()) 248 if (InBigEndianMode())
@@ -263,8 +251,7 @@ void ARMul_State::WriteMemory32(u32 address, u32 data)
263 Memory::Write32(address, data); 251 Memory::Write32(address, data);
264} 252}
265 253
266void ARMul_State::WriteMemory64(u32 address, u64 data) 254void ARMul_State::WriteMemory64(u32 address, u64 data) {
267{
268 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write); 255 CheckMemoryBreakpoint(address, GDBStub::BreakpointType::Write);
269 256
270 if (InBigEndianMode()) 257 if (InBigEndianMode())
@@ -273,15 +260,12 @@ void ARMul_State::WriteMemory64(u32 address, u64 data)
273 Memory::Write64(address, data); 260 Memory::Write64(address, data);
274} 261}
275 262
276
277// Reads from the CP15 registers. Used with implementation of the MRC instruction. 263// Reads from the CP15 registers. Used with implementation of the MRC instruction.
278// Note that since the 3DS does not have the hypervisor extensions, these registers 264// Note that since the 3DS does not have the hypervisor extensions, these registers
279// are not implemented. 265// are not implemented.
280u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const 266u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const {
281{
282 // Unprivileged registers 267 // Unprivileged registers
283 if (crn == 13 && opcode_1 == 0 && crm == 0) 268 if (crn == 13 && opcode_1 == 0 && crm == 0) {
284 {
285 if (opcode_2 == 2) 269 if (opcode_2 == 2)
286 return CP15[CP15_THREAD_UPRW]; 270 return CP15[CP15_THREAD_UPRW];
287 271
@@ -289,12 +273,9 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
289 return CP15[CP15_THREAD_URO]; 273 return CP15[CP15_THREAD_URO];
290 } 274 }
291 275
292 if (InAPrivilegedMode()) 276 if (InAPrivilegedMode()) {
293 { 277 if (crn == 0 && opcode_1 == 0) {
294 if (crn == 0 && opcode_1 == 0) 278 if (crm == 0) {
295 {
296 if (crm == 0)
297 {
298 if (opcode_2 == 0) 279 if (opcode_2 == 0)
299 return CP15[CP15_MAIN_ID]; 280 return CP15[CP15_MAIN_ID];
300 281
@@ -306,9 +287,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
306 287
307 if (opcode_2 == 5) 288 if (opcode_2 == 5)
308 return CP15[CP15_CPU_ID]; 289 return CP15[CP15_CPU_ID];
309 } 290 } else if (crm == 1) {
310 else if (crm == 1)
311 {
312 if (opcode_2 == 0) 291 if (opcode_2 == 0)
313 return CP15[CP15_PROCESSOR_FEATURE_0]; 292 return CP15[CP15_PROCESSOR_FEATURE_0];
314 293
@@ -329,9 +308,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
329 308
330 if (opcode_2 == 7) 309 if (opcode_2 == 7)
331 return CP15[CP15_MEMORY_MODEL_FEATURE_3]; 310 return CP15[CP15_MEMORY_MODEL_FEATURE_3];
332 } 311 } else if (crm == 2) {
333 else if (crm == 2)
334 {
335 if (opcode_2 == 0) 312 if (opcode_2 == 0)
336 return CP15[CP15_ISA_FEATURE_0]; 313 return CP15[CP15_ISA_FEATURE_0];
337 314
@@ -349,8 +326,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
349 } 326 }
350 } 327 }
351 328
352 if (crn == 1 && opcode_1 == 0 && crm == 0) 329 if (crn == 1 && opcode_1 == 0 && crm == 0) {
353 {
354 if (opcode_2 == 0) 330 if (opcode_2 == 0)
355 return CP15[CP15_CONTROL]; 331 return CP15[CP15_CONTROL];
356 332
@@ -361,8 +337,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
361 return CP15[CP15_COPROCESSOR_ACCESS_CONTROL]; 337 return CP15[CP15_COPROCESSOR_ACCESS_CONTROL];
362 } 338 }
363 339
364 if (crn == 2 && opcode_1 == 0 && crm == 0) 340 if (crn == 2 && opcode_1 == 0 && crm == 0) {
365 {
366 if (opcode_2 == 0) 341 if (opcode_2 == 0)
367 return CP15[CP15_TRANSLATION_BASE_TABLE_0]; 342 return CP15[CP15_TRANSLATION_BASE_TABLE_0];
368 343
@@ -376,8 +351,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
376 if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) 351 if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
377 return CP15[CP15_DOMAIN_ACCESS_CONTROL]; 352 return CP15[CP15_DOMAIN_ACCESS_CONTROL];
378 353
379 if (crn == 5 && opcode_1 == 0 && crm == 0) 354 if (crn == 5 && opcode_1 == 0 && crm == 0) {
380 {
381 if (opcode_2 == 0) 355 if (opcode_2 == 0)
382 return CP15[CP15_FAULT_STATUS]; 356 return CP15[CP15_FAULT_STATUS];
383 357
@@ -385,8 +359,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
385 return CP15[CP15_INSTR_FAULT_STATUS]; 359 return CP15[CP15_INSTR_FAULT_STATUS];
386 } 360 }
387 361
388 if (crn == 6 && opcode_1 == 0 && crm == 0) 362 if (crn == 6 && opcode_1 == 0 && crm == 0) {
389 {
390 if (opcode_2 == 0) 363 if (opcode_2 == 0)
391 return CP15[CP15_FAULT_ADDRESS]; 364 return CP15[CP15_FAULT_ADDRESS];
392 365
@@ -400,13 +373,11 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
400 if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) 373 if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
401 return CP15[CP15_DATA_CACHE_LOCKDOWN]; 374 return CP15[CP15_DATA_CACHE_LOCKDOWN];
402 375
403 if (crn == 10 && opcode_1 == 0) 376 if (crn == 10 && opcode_1 == 0) {
404 {
405 if (crm == 0 && opcode_2 == 0) 377 if (crm == 0 && opcode_2 == 0)
406 return CP15[CP15_TLB_LOCKDOWN]; 378 return CP15[CP15_TLB_LOCKDOWN];
407 379
408 if (crm == 2) 380 if (crm == 2) {
409 {
410 if (opcode_2 == 0) 381 if (opcode_2 == 0)
411 return CP15[CP15_PRIMARY_REGION_REMAP]; 382 return CP15[CP15_PRIMARY_REGION_REMAP];
412 383
@@ -415,8 +386,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
415 } 386 }
416 } 387 }
417 388
418 if (crn == 13 && crm == 0) 389 if (crn == 13 && crm == 0) {
419 {
420 if (opcode_2 == 0) 390 if (opcode_2 == 0)
421 return CP15[CP15_PID]; 391 return CP15[CP15_PID];
422 392
@@ -427,10 +397,8 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
427 return CP15[CP15_THREAD_PRW]; 397 return CP15[CP15_THREAD_PRW];
428 } 398 }
429 399
430 if (crn == 15) 400 if (crn == 15) {
431 { 401 if (opcode_1 == 0 && crm == 12) {
432 if (opcode_1 == 0 && crm == 12)
433 {
434 if (opcode_2 == 0) 402 if (opcode_2 == 0)
435 return CP15[CP15_PERFORMANCE_MONITOR_CONTROL]; 403 return CP15[CP15_PERFORMANCE_MONITOR_CONTROL];
436 404
@@ -444,8 +412,7 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
444 return CP15[CP15_COUNT_1]; 412 return CP15[CP15_COUNT_1];
445 } 413 }
446 414
447 if (opcode_1 == 5 && opcode_2 == 2) 415 if (opcode_1 == 5 && opcode_2 == 2) {
448 {
449 if (crm == 5) 416 if (crm == 5)
450 return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS]; 417 return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS];
451 418
@@ -461,66 +428,49 @@ u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
461 } 428 }
462 } 429 }
463 430
464 LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2); 431 LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.",
432 crn, crm, opcode_1, opcode_2);
465 return 0; 433 return 0;
466} 434}
467 435
468// Write to the CP15 registers. Used with implementation of the MCR instruction. 436// Write to the CP15 registers. Used with implementation of the MCR instruction.
469// Note that since the 3DS does not have the hypervisor extensions, these registers 437// Note that since the 3DS does not have the hypervisor extensions, these registers
470// are not implemented. 438// are not implemented.
471void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) 439void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) {
472{ 440 if (InAPrivilegedMode()) {
473 if (InAPrivilegedMode()) 441 if (crn == 1 && opcode_1 == 0 && crm == 0) {
474 {
475 if (crn == 1 && opcode_1 == 0 && crm == 0)
476 {
477 if (opcode_2 == 0) 442 if (opcode_2 == 0)
478 CP15[CP15_CONTROL] = value; 443 CP15[CP15_CONTROL] = value;
479 else if (opcode_2 == 1) 444 else if (opcode_2 == 1)
480 CP15[CP15_AUXILIARY_CONTROL] = value; 445 CP15[CP15_AUXILIARY_CONTROL] = value;
481 else if (opcode_2 == 2) 446 else if (opcode_2 == 2)
482 CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value; 447 CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value;
483 } 448 } else if (crn == 2 && opcode_1 == 0 && crm == 0) {
484 else if (crn == 2 && opcode_1 == 0 && crm == 0)
485 {
486 if (opcode_2 == 0) 449 if (opcode_2 == 0)
487 CP15[CP15_TRANSLATION_BASE_TABLE_0] = value; 450 CP15[CP15_TRANSLATION_BASE_TABLE_0] = value;
488 else if (opcode_2 == 1) 451 else if (opcode_2 == 1)
489 CP15[CP15_TRANSLATION_BASE_TABLE_1] = value; 452 CP15[CP15_TRANSLATION_BASE_TABLE_1] = value;
490 else if (opcode_2 == 2) 453 else if (opcode_2 == 2)
491 CP15[CP15_TRANSLATION_BASE_CONTROL] = value; 454 CP15[CP15_TRANSLATION_BASE_CONTROL] = value;
492 } 455 } else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) {
493 else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
494 {
495 CP15[CP15_DOMAIN_ACCESS_CONTROL] = value; 456 CP15[CP15_DOMAIN_ACCESS_CONTROL] = value;
496 } 457 } else if (crn == 5 && opcode_1 == 0 && crm == 0) {
497 else if (crn == 5 && opcode_1 == 0 && crm == 0)
498 {
499 if (opcode_2 == 0) 458 if (opcode_2 == 0)
500 CP15[CP15_FAULT_STATUS] = value; 459 CP15[CP15_FAULT_STATUS] = value;
501 else if (opcode_2 == 1) 460 else if (opcode_2 == 1)
502 CP15[CP15_INSTR_FAULT_STATUS] = value; 461 CP15[CP15_INSTR_FAULT_STATUS] = value;
503 } 462 } else if (crn == 6 && opcode_1 == 0 && crm == 0) {
504 else if (crn == 6 && opcode_1 == 0 && crm == 0)
505 {
506 if (opcode_2 == 0) 463 if (opcode_2 == 0)
507 CP15[CP15_FAULT_ADDRESS] = value; 464 CP15[CP15_FAULT_ADDRESS] = value;
508 else if (opcode_2 == 1) 465 else if (opcode_2 == 1)
509 CP15[CP15_WFAR] = value; 466 CP15[CP15_WFAR] = value;
510 } 467 } else if (crn == 7 && opcode_1 == 0) {
511 else if (crn == 7 && opcode_1 == 0) 468 if (crm == 0 && opcode_2 == 4) {
512 {
513 if (crm == 0 && opcode_2 == 4)
514 {
515 CP15[CP15_WAIT_FOR_INTERRUPT] = value; 469 CP15[CP15_WAIT_FOR_INTERRUPT] = value;
516 } 470 } else if (crm == 4 && opcode_2 == 0) {
517 else if (crm == 4 && opcode_2 == 0)
518 {
519 // NOTE: Not entirely accurate. This should do permission checks. 471 // NOTE: Not entirely accurate. This should do permission checks.
520 CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value); 472 CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value);
521 } 473 } else if (crm == 5) {
522 else if (crm == 5)
523 {
524 if (opcode_2 == 0) 474 if (opcode_2 == 0)
525 CP15[CP15_INVALIDATE_INSTR_CACHE] = value; 475 CP15[CP15_INVALIDATE_INSTR_CACHE] = value;
526 else if (opcode_2 == 1) 476 else if (opcode_2 == 1)
@@ -531,31 +481,23 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
531 CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value; 481 CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value;
532 else if (opcode_2 == 7) 482 else if (opcode_2 == 7)
533 CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value; 483 CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value;
534 } 484 } else if (crm == 6) {
535 else if (crm == 6)
536 {
537 if (opcode_2 == 0) 485 if (opcode_2 == 0)
538 CP15[CP15_INVALIDATE_DATA_CACHE] = value; 486 CP15[CP15_INVALIDATE_DATA_CACHE] = value;
539 else if (opcode_2 == 1) 487 else if (opcode_2 == 1)
540 CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; 488 CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
541 else if (opcode_2 == 2) 489 else if (opcode_2 == 2)
542 CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; 490 CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
543 } 491 } else if (crm == 7 && opcode_2 == 0) {
544 else if (crm == 7 && opcode_2 == 0)
545 {
546 CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value; 492 CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value;
547 } 493 } else if (crm == 10) {
548 else if (crm == 10)
549 {
550 if (opcode_2 == 0) 494 if (opcode_2 == 0)
551 CP15[CP15_CLEAN_DATA_CACHE] = value; 495 CP15[CP15_CLEAN_DATA_CACHE] = value;
552 else if (opcode_2 == 1) 496 else if (opcode_2 == 1)
553 CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value; 497 CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value;
554 else if (opcode_2 == 2) 498 else if (opcode_2 == 2)
555 CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value; 499 CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value;
556 } 500 } else if (crm == 14) {
557 else if (crm == 14)
558 {
559 if (opcode_2 == 0) 501 if (opcode_2 == 0)
560 CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value; 502 CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value;
561 else if (opcode_2 == 1) 503 else if (opcode_2 == 1)
@@ -563,11 +505,8 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
563 else if (opcode_2 == 2) 505 else if (opcode_2 == 2)
564 CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; 506 CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
565 } 507 }
566 } 508 } else if (crn == 8 && opcode_1 == 0) {
567 else if (crn == 8 && opcode_1 == 0) 509 if (crm == 5) {
568 {
569 if (crm == 5)
570 {
571 if (opcode_2 == 0) 510 if (opcode_2 == 0)
572 CP15[CP15_INVALIDATE_ITLB] = value; 511 CP15[CP15_INVALIDATE_ITLB] = value;
573 else if (opcode_2 == 1) 512 else if (opcode_2 == 1)
@@ -576,9 +515,7 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
576 CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value; 515 CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value;
577 else if (opcode_2 == 3) 516 else if (opcode_2 == 3)
578 CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value; 517 CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value;
579 } 518 } else if (crm == 6) {
580 else if (crm == 6)
581 {
582 if (opcode_2 == 0) 519 if (opcode_2 == 0)
583 CP15[CP15_INVALIDATE_DTLB] = value; 520 CP15[CP15_INVALIDATE_DTLB] = value;
584 else if (opcode_2 == 1) 521 else if (opcode_2 == 1)
@@ -587,9 +524,7 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
587 CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value; 524 CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value;
588 else if (opcode_2 == 3) 525 else if (opcode_2 == 3)
589 CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value; 526 CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value;
590 } 527 } else if (crm == 7) {
591 else if (crm == 7)
592 {
593 if (opcode_2 == 0) 528 if (opcode_2 == 0)
594 CP15[CP15_INVALIDATE_UTLB] = value; 529 CP15[CP15_INVALIDATE_UTLB] = value;
595 else if (opcode_2 == 1) 530 else if (opcode_2 == 1)
@@ -599,27 +534,18 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
599 else if (opcode_2 == 3) 534 else if (opcode_2 == 3)
600 CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value; 535 CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value;
601 } 536 }
602 } 537 } else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) {
603 else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
604 {
605 CP15[CP15_DATA_CACHE_LOCKDOWN] = value; 538 CP15[CP15_DATA_CACHE_LOCKDOWN] = value;
606 } 539 } else if (crn == 10 && opcode_1 == 0) {
607 else if (crn == 10 && opcode_1 == 0) 540 if (crm == 0 && opcode_2 == 0) {
608 {
609 if (crm == 0 && opcode_2 == 0)
610 {
611 CP15[CP15_TLB_LOCKDOWN] = value; 541 CP15[CP15_TLB_LOCKDOWN] = value;
612 } 542 } else if (crm == 2) {
613 else if (crm == 2)
614 {
615 if (opcode_2 == 0) 543 if (opcode_2 == 0)
616 CP15[CP15_PRIMARY_REGION_REMAP] = value; 544 CP15[CP15_PRIMARY_REGION_REMAP] = value;
617 else if (opcode_2 == 1) 545 else if (opcode_2 == 1)
618 CP15[CP15_NORMAL_REGION_REMAP] = value; 546 CP15[CP15_NORMAL_REGION_REMAP] = value;
619 } 547 }
620 } 548 } else if (crn == 13 && opcode_1 == 0 && crm == 0) {
621 else if (crn == 13 && opcode_1 == 0 && crm == 0)
622 {
623 if (opcode_2 == 0) 549 if (opcode_2 == 0)
624 CP15[CP15_PID] = value; 550 CP15[CP15_PID] = value;
625 else if (opcode_2 == 1) 551 else if (opcode_2 == 1)
@@ -628,11 +554,8 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
628 CP15[CP15_THREAD_URO] = value; 554 CP15[CP15_THREAD_URO] = value;
629 else if (opcode_2 == 4) 555 else if (opcode_2 == 4)
630 CP15[CP15_THREAD_PRW] = value; 556 CP15[CP15_THREAD_PRW] = value;
631 } 557 } else if (crn == 15) {
632 else if (crn == 15) 558 if (opcode_1 == 0 && crm == 12) {
633 {
634 if (opcode_1 == 0 && crm == 12)
635 {
636 if (opcode_2 == 0) 559 if (opcode_2 == 0)
637 CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value; 560 CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value;
638 else if (opcode_2 == 1) 561 else if (opcode_2 == 1)
@@ -641,50 +564,34 @@ void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u
641 CP15[CP15_COUNT_0] = value; 564 CP15[CP15_COUNT_0] = value;
642 else if (opcode_2 == 3) 565 else if (opcode_2 == 3)
643 CP15[CP15_COUNT_1] = value; 566 CP15[CP15_COUNT_1] = value;
644 } 567 } else if (opcode_1 == 5) {
645 else if (opcode_1 == 5) 568 if (crm == 4) {
646 {
647 if (crm == 4)
648 {
649 if (opcode_2 == 2) 569 if (opcode_2 == 2)
650 CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value; 570 CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value;
651 else if (opcode_2 == 4) 571 else if (opcode_2 == 4)
652 CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value; 572 CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value;
653 } 573 } else if (crm == 5 && opcode_2 == 2) {
654 else if (crm == 5 && opcode_2 == 2)
655 {
656 CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value; 574 CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value;
657 } 575 } else if (crm == 6 && opcode_2 == 2) {
658 else if (crm == 6 && opcode_2 == 2)
659 {
660 CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value; 576 CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value;
661 } 577 } else if (crm == 7 && opcode_2 == 2) {
662 else if (crm == 7 && opcode_2 == 2)
663 {
664 CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value; 578 CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value;
665 } 579 }
666 } 580 } else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) {
667 else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
668 {
669 CP15[CP15_TLB_DEBUG_CONTROL] = value; 581 CP15[CP15_TLB_DEBUG_CONTROL] = value;
670 } 582 }
671 } 583 }
672 } 584 }
673 585
674 // Unprivileged registers 586 // Unprivileged registers
675 if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) 587 if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) {
676 {
677 CP15[CP15_FLUSH_PREFETCH_BUFFER] = value; 588 CP15[CP15_FLUSH_PREFETCH_BUFFER] = value;
678 } 589 } else if (crn == 7 && opcode_1 == 0 && crm == 10) {
679 else if (crn == 7 && opcode_1 == 0 && crm == 10)
680 {
681 if (opcode_2 == 4) 590 if (opcode_2 == 4)
682 CP15[CP15_DATA_SYNC_BARRIER] = value; 591 CP15[CP15_DATA_SYNC_BARRIER] = value;
683 else if (opcode_2 == 5) 592 else if (opcode_2 == 5)
684 CP15[CP15_DATA_MEMORY_BARRIER] = value; 593 CP15[CP15_DATA_MEMORY_BARRIER] = value;
685 } 594 } else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) {
686 else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2)
687 {
688 CP15[CP15_THREAD_UPRW] = value; 595 CP15[CP15_THREAD_UPRW] = value;
689 } 596 }
690} 597}
diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h
index d42ff2669..66567c285 100644
--- a/src/core/arm/skyeye_common/armstate.h
+++ b/src/core/arm/skyeye_common/armstate.h
@@ -24,75 +24,70 @@
24#include "core/arm/skyeye_common/arm_regformat.h" 24#include "core/arm/skyeye_common/arm_regformat.h"
25 25
26// Signal levels 26// Signal levels
27enum { 27enum { LOW = 0, HIGH = 1, LOWHIGH = 1, HIGHLOW = 2 };
28 LOW = 0,
29 HIGH = 1,
30 LOWHIGH = 1,
31 HIGHLOW = 2
32};
33 28
34// Cache types 29// Cache types
35enum { 30enum {
36 NONCACHE = 0, 31 NONCACHE = 0,
37 DATACACHE = 1, 32 DATACACHE = 1,
38 INSTCACHE = 2, 33 INSTCACHE = 2,
39}; 34};
40 35
41// ARM privilege modes 36// ARM privilege modes
42enum PrivilegeMode { 37enum PrivilegeMode {
43 USER32MODE = 16, 38 USER32MODE = 16,
44 FIQ32MODE = 17, 39 FIQ32MODE = 17,
45 IRQ32MODE = 18, 40 IRQ32MODE = 18,
46 SVC32MODE = 19, 41 SVC32MODE = 19,
47 ABORT32MODE = 23, 42 ABORT32MODE = 23,
48 UNDEF32MODE = 27, 43 UNDEF32MODE = 27,
49 SYSTEM32MODE = 31 44 SYSTEM32MODE = 31
50}; 45};
51 46
52// ARM privilege mode register banks 47// ARM privilege mode register banks
53enum { 48enum {
54 USERBANK = 0, 49 USERBANK = 0,
55 FIQBANK = 1, 50 FIQBANK = 1,
56 IRQBANK = 2, 51 IRQBANK = 2,
57 SVCBANK = 3, 52 SVCBANK = 3,
58 ABORTBANK = 4, 53 ABORTBANK = 4,
59 UNDEFBANK = 5, 54 UNDEFBANK = 5,
60 DUMMYBANK = 6, 55 DUMMYBANK = 6,
61 SYSTEMBANK = 7 56 SYSTEMBANK = 7
62}; 57};
63 58
64// Hardware vector addresses 59// Hardware vector addresses
65enum { 60enum {
66 ARMResetV = 0, 61 ARMResetV = 0,
67 ARMUndefinedInstrV = 4, 62 ARMUndefinedInstrV = 4,
68 ARMSWIV = 8, 63 ARMSWIV = 8,
69 ARMPrefetchAbortV = 12, 64 ARMPrefetchAbortV = 12,
70 ARMDataAbortV = 16, 65 ARMDataAbortV = 16,
71 ARMAddrExceptnV = 20, 66 ARMAddrExceptnV = 20,
72 ARMIRQV = 24, 67 ARMIRQV = 24,
73 ARMFIQV = 28, 68 ARMFIQV = 28,
74 ARMErrorV = 32, // This is an offset, not an address! 69 ARMErrorV = 32, // This is an offset, not an address!
75 70
76 ARMul_ResetV = ARMResetV, 71 ARMul_ResetV = ARMResetV,
77 ARMul_UndefinedInstrV = ARMUndefinedInstrV, 72 ARMul_UndefinedInstrV = ARMUndefinedInstrV,
78 ARMul_SWIV = ARMSWIV, 73 ARMul_SWIV = ARMSWIV,
79 ARMul_PrefetchAbortV = ARMPrefetchAbortV, 74 ARMul_PrefetchAbortV = ARMPrefetchAbortV,
80 ARMul_DataAbortV = ARMDataAbortV, 75 ARMul_DataAbortV = ARMDataAbortV,
81 ARMul_AddrExceptnV = ARMAddrExceptnV, 76 ARMul_AddrExceptnV = ARMAddrExceptnV,
82 ARMul_IRQV = ARMIRQV, 77 ARMul_IRQV = ARMIRQV,
83 ARMul_FIQV = ARMFIQV 78 ARMul_FIQV = ARMFIQV
84}; 79};
85 80
86// Coprocessor status values 81// Coprocessor status values
87enum { 82enum {
88 ARMul_FIRST = 0, 83 ARMul_FIRST = 0,
89 ARMul_TRANSFER = 1, 84 ARMul_TRANSFER = 1,
90 ARMul_BUSY = 2, 85 ARMul_BUSY = 2,
91 ARMul_DATA = 3, 86 ARMul_DATA = 3,
92 ARMul_INTERRUPT = 4, 87 ARMul_INTERRUPT = 4,
93 ARMul_DONE = 0, 88 ARMul_DONE = 0,
94 ARMul_CANT = 1, 89 ARMul_CANT = 1,
95 ARMul_INC = 3 90 ARMul_INC = 3
96}; 91};
97 92
98// Instruction condition codes 93// Instruction condition codes
@@ -136,15 +131,13 @@ enum : u32 {
136 131
137// Values for Emulate. 132// Values for Emulate.
138enum { 133enum {
139 STOP = 0, // Stop 134 STOP = 0, // Stop
140 CHANGEMODE = 1, // Change mode 135 CHANGEMODE = 1, // Change mode
141 ONCE = 2, // Execute just one iteration 136 ONCE = 2, // Execute just one iteration
142 RUN = 3 // Continuous execution 137 RUN = 3 // Continuous execution
143}; 138};
144 139
145 140struct ARMul_State final {
146struct ARMul_State final
147{
148public: 141public:
149 explicit ARMul_State(PrivilegeMode initial_mode); 142 explicit ARMul_State(PrivilegeMode initial_mode);
150 143
@@ -193,7 +186,7 @@ public:
193 return TFlag ? 2 : 4; 186 return TFlag ? 2 : 4;
194 } 187 }
195 188
196 std::array<u32, 16> Reg{}; // The current register file 189 std::array<u32, 16> Reg{}; // The current register file
197 std::array<u32, 2> Reg_usr{}; 190 std::array<u32, 2> Reg_usr{};
198 std::array<u32, 2> Reg_svc{}; // R13_SVC R14_SVC 191 std::array<u32, 2> Reg_svc{}; // R13_SVC R14_SVC
199 std::array<u32, 2> Reg_abort{}; // R13_ABORT R14_ABORT 192 std::array<u32, 2> Reg_abort{}; // R13_ABORT R14_ABORT
@@ -216,8 +209,8 @@ public:
216 u32 Spsr_copy; 209 u32 Spsr_copy;
217 u32 phys_pc; 210 u32 phys_pc;
218 211
219 u32 Mode; // The current mode 212 u32 Mode; // The current mode
220 u32 Bank; // The current register bank 213 u32 Bank; // The current register bank
221 214
222 u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed 215 u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
223 unsigned int shifter_carry_out; 216 unsigned int shifter_carry_out;
@@ -243,8 +236,10 @@ public:
243private: 236private:
244 void ResetMPCoreCP15Registers(); 237 void ResetMPCoreCP15Registers();
245 238
246 // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag. 239 // Defines a reservation granule of 2 words, which protects the first 2 words starting at the
247 // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to 240 // tag.
241 // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough
242 // to
248 // support LDR/STREXD. 243 // support LDR/STREXD.
249 static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; 244 static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
250 245
diff --git a/src/core/arm/skyeye_common/armsupp.cpp b/src/core/arm/skyeye_common/armsupp.cpp
index 883713e86..e70be29a7 100644
--- a/src/core/arm/skyeye_common/armsupp.cpp
+++ b/src/core/arm/skyeye_common/armsupp.cpp
@@ -22,8 +22,7 @@
22#include "core/arm/skyeye_common/armsupp.h" 22#include "core/arm/skyeye_common/armsupp.h"
23 23
24// Unsigned sum of absolute difference 24// Unsigned sum of absolute difference
25u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) 25u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) {
26{
27 if (left > right) 26 if (left > right)
28 return left - right; 27 return left - right;
29 28
@@ -31,8 +30,8 @@ u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
31} 30}
32 31
33// Add with carry, indicates if a carry-out or signed overflow occurred. 32// Add with carry, indicates if a carry-out or signed overflow occurred.
34u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred) 33u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred,
35{ 34 bool* overflow_occurred) {
36 u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; 35 u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in;
37 s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; 36 s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in;
38 u64 result = (unsigned_sum & 0xFFFFFFFF); 37 u64 result = (unsigned_sum & 0xFFFFFFFF);
@@ -47,22 +46,17 @@ u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bo
47} 46}
48 47
49// Compute whether an addition of A and B, giving RESULT, overflowed. 48// Compute whether an addition of A and B, giving RESULT, overflowed.
50bool AddOverflow(u32 a, u32 b, u32 result) 49bool AddOverflow(u32 a, u32 b, u32 result) {
51{ 50 return ((NEG(a) && NEG(b) && POS(result)) || (POS(a) && POS(b) && NEG(result)));
52 return ((NEG(a) && NEG(b) && POS(result)) ||
53 (POS(a) && POS(b) && NEG(result)));
54} 51}
55 52
56// Compute whether a subtraction of A and B, giving RESULT, overflowed. 53// Compute whether a subtraction of A and B, giving RESULT, overflowed.
57bool SubOverflow(u32 a, u32 b, u32 result) 54bool SubOverflow(u32 a, u32 b, u32 result) {
58{ 55 return ((NEG(a) && POS(b) && POS(result)) || (POS(a) && NEG(b) && NEG(result)));
59 return ((NEG(a) && POS(b) && POS(result)) ||
60 (POS(a) && NEG(b) && NEG(result)));
61} 56}
62 57
63// Returns true if the Q flag should be set as a result of overflow. 58// Returns true if the Q flag should be set as a result of overflow.
64bool ARMul_AddOverflowQ(u32 a, u32 b) 59bool ARMul_AddOverflowQ(u32 a, u32 b) {
65{
66 u32 result = a + b; 60 u32 result = a + b;
67 if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0) 61 if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0)
68 return true; 62 return true;
@@ -71,8 +65,7 @@ bool ARMul_AddOverflowQ(u32 a, u32 b)
71} 65}
72 66
73// 8-bit signed saturated addition 67// 8-bit signed saturated addition
74u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) 68u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) {
75{
76 u8 result = left + right; 69 u8 result = left + right;
77 70
78 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) { 71 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) {
@@ -86,8 +79,7 @@ u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
86} 79}
87 80
88// 8-bit signed saturated subtraction 81// 8-bit signed saturated subtraction
89u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) 82u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) {
90{
91 u8 result = left - right; 83 u8 result = left - right;
92 84
93 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) { 85 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) {
@@ -101,8 +93,7 @@ u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
101} 93}
102 94
103// 16-bit signed saturated addition 95// 16-bit signed saturated addition
104u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) 96u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) {
105{
106 u16 result = left + right; 97 u16 result = left + right;
107 98
108 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) { 99 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) {
@@ -116,8 +107,7 @@ u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
116} 107}
117 108
118// 16-bit signed saturated subtraction 109// 16-bit signed saturated subtraction
119u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) 110u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) {
120{
121 u16 result = left - right; 111 u16 result = left - right;
122 112
123 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) { 113 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) {
@@ -131,8 +121,7 @@ u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
131} 121}
132 122
133// 8-bit unsigned saturated addition 123// 8-bit unsigned saturated addition
134u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) 124u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) {
135{
136 u8 result = left + right; 125 u8 result = left + right;
137 126
138 if (result < left) 127 if (result < left)
@@ -142,8 +131,7 @@ u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
142} 131}
143 132
144// 16-bit unsigned saturated addition 133// 16-bit unsigned saturated addition
145u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) 134u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) {
146{
147 u16 result = left + right; 135 u16 result = left + right;
148 136
149 if (result < left) 137 if (result < left)
@@ -153,8 +141,7 @@ u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
153} 141}
154 142
155// 8-bit unsigned saturated subtraction 143// 8-bit unsigned saturated subtraction
156u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) 144u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) {
157{
158 if (left <= right) 145 if (left <= right)
159 return 0; 146 return 0;
160 147
@@ -162,8 +149,7 @@ u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
162} 149}
163 150
164// 16-bit unsigned saturated subtraction 151// 16-bit unsigned saturated subtraction
165u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) 152u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) {
166{
167 if (left <= right) 153 if (left <= right)
168 return 0; 154 return 0;
169 155
@@ -171,16 +157,14 @@ u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
171} 157}
172 158
173// Signed saturation. 159// Signed saturation.
174u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) 160u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) {
175{
176 const u32 max = (1 << shift) - 1; 161 const u32 max = (1 << shift) - 1;
177 const s32 top = (value >> shift); 162 const s32 top = (value >> shift);
178 163
179 if (top > 0) { 164 if (top > 0) {
180 *saturation_occurred = true; 165 *saturation_occurred = true;
181 return max; 166 return max;
182 } 167 } else if (top < -1) {
183 else if (top < -1) {
184 *saturation_occurred = true; 168 *saturation_occurred = true;
185 return ~max; 169 return ~max;
186 } 170 }
@@ -190,8 +174,7 @@ u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
190} 174}
191 175
192// Unsigned saturation 176// Unsigned saturation
193u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) 177u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) {
194{
195 const u32 max = (1 << shift) - 1; 178 const u32 max = (1 << shift) - 1;
196 179
197 if (value < 0) { 180 if (value < 0) {
diff --git a/src/core/arm/skyeye_common/armsupp.h b/src/core/arm/skyeye_common/armsupp.h
index 391309fa8..bf9299c07 100644
--- a/src/core/arm/skyeye_common/armsupp.h
+++ b/src/core/arm/skyeye_common/armsupp.h
@@ -9,8 +9,8 @@
9#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) 9#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
10#define BIT(s, n) ((s >> (n)) & 1) 10#define BIT(s, n) ((s >> (n)) & 1)
11 11
12#define POS(i) ( (~(i)) >> 31 ) 12#define POS(i) ((~(i)) >> 31)
13#define NEG(i) ( (i) >> 31 ) 13#define NEG(i) ((i) >> 31)
14 14
15bool AddOverflow(u32, u32, u32); 15bool AddOverflow(u32, u32, u32);
16bool SubOverflow(u32, u32, u32); 16bool SubOverflow(u32, u32, u32);
diff --git a/src/core/arm/skyeye_common/vfp/asm_vfp.h b/src/core/arm/skyeye_common/vfp/asm_vfp.h
index 1187924f4..15b2394eb 100644
--- a/src/core/arm/skyeye_common/vfp/asm_vfp.h
+++ b/src/core/arm/skyeye_common/vfp/asm_vfp.h
@@ -10,74 +10,74 @@
10// ARM11 MPCore FPSID Information 10// ARM11 MPCore FPSID Information
11// Note that these are used as values and not as flags. 11// Note that these are used as values and not as flags.
12enum : u32 { 12enum : u32 {
13 VFP_FPSID_IMPLMEN = 0x41, // Implementation code. Should be the same as cp15 0 c0 0 13 VFP_FPSID_IMPLMEN = 0x41, // Implementation code. Should be the same as cp15 0 c0 0
14 VFP_FPSID_SW = 0, // Software emulation bit value 14 VFP_FPSID_SW = 0, // Software emulation bit value
15 VFP_FPSID_SUBARCH = 0x1, // Subarchitecture version number 15 VFP_FPSID_SUBARCH = 0x1, // Subarchitecture version number
16 VFP_FPSID_PARTNUM = 0x20, // Part number 16 VFP_FPSID_PARTNUM = 0x20, // Part number
17 VFP_FPSID_VARIANT = 0xB, // Variant number 17 VFP_FPSID_VARIANT = 0xB, // Variant number
18 VFP_FPSID_REVISION = 0x4 // Revision number 18 VFP_FPSID_REVISION = 0x4 // Revision number
19}; 19};
20 20
21// FPEXC bits 21// FPEXC bits
22enum : u32 { 22enum : u32 {
23 FPEXC_EX = (1U << 31U), 23 FPEXC_EX = (1U << 31U),
24 FPEXC_EN = (1 << 30), 24 FPEXC_EN = (1 << 30),
25 FPEXC_DEX = (1 << 29), 25 FPEXC_DEX = (1 << 29),
26 FPEXC_FP2V = (1 << 28), 26 FPEXC_FP2V = (1 << 28),
27 FPEXC_VV = (1 << 27), 27 FPEXC_VV = (1 << 27),
28 FPEXC_TFV = (1 << 26), 28 FPEXC_TFV = (1 << 26),
29 FPEXC_LENGTH_BIT = (8), 29 FPEXC_LENGTH_BIT = (8),
30 FPEXC_LENGTH_MASK = (7 << FPEXC_LENGTH_BIT), 30 FPEXC_LENGTH_MASK = (7 << FPEXC_LENGTH_BIT),
31 FPEXC_IDF = (1 << 7), 31 FPEXC_IDF = (1 << 7),
32 FPEXC_IXF = (1 << 4), 32 FPEXC_IXF = (1 << 4),
33 FPEXC_UFF = (1 << 3), 33 FPEXC_UFF = (1 << 3),
34 FPEXC_OFF = (1 << 2), 34 FPEXC_OFF = (1 << 2),
35 FPEXC_DZF = (1 << 1), 35 FPEXC_DZF = (1 << 1),
36 FPEXC_IOF = (1 << 0), 36 FPEXC_IOF = (1 << 0),
37 FPEXC_TRAP_MASK = (FPEXC_IDF|FPEXC_IXF|FPEXC_UFF|FPEXC_OFF|FPEXC_DZF|FPEXC_IOF) 37 FPEXC_TRAP_MASK = (FPEXC_IDF | FPEXC_IXF | FPEXC_UFF | FPEXC_OFF | FPEXC_DZF | FPEXC_IOF)
38}; 38};
39 39
40// FPSCR Flags 40// FPSCR Flags
41enum : u32 { 41enum : u32 {
42 FPSCR_NFLAG = (1U << 31U), // Negative condition flag 42 FPSCR_NFLAG = (1U << 31U), // Negative condition flag
43 FPSCR_ZFLAG = (1 << 30), // Zero condition flag 43 FPSCR_ZFLAG = (1 << 30), // Zero condition flag
44 FPSCR_CFLAG = (1 << 29), // Carry condition flag 44 FPSCR_CFLAG = (1 << 29), // Carry condition flag
45 FPSCR_VFLAG = (1 << 28), // Overflow condition flag 45 FPSCR_VFLAG = (1 << 28), // Overflow condition flag
46 46
47 FPSCR_QC = (1 << 27), // Cumulative saturation bit 47 FPSCR_QC = (1 << 27), // Cumulative saturation bit
48 FPSCR_AHP = (1 << 26), // Alternative half-precision control bit 48 FPSCR_AHP = (1 << 26), // Alternative half-precision control bit
49 FPSCR_DEFAULT_NAN = (1 << 25), // Default NaN mode control bit 49 FPSCR_DEFAULT_NAN = (1 << 25), // Default NaN mode control bit
50 FPSCR_FLUSH_TO_ZERO = (1 << 24), // Flush-to-zero mode control bit 50 FPSCR_FLUSH_TO_ZERO = (1 << 24), // Flush-to-zero mode control bit
51 FPSCR_RMODE_MASK = (3 << 22), // Rounding Mode bit mask 51 FPSCR_RMODE_MASK = (3 << 22), // Rounding Mode bit mask
52 FPSCR_STRIDE_MASK = (3 << 20), // Vector stride bit mask 52 FPSCR_STRIDE_MASK = (3 << 20), // Vector stride bit mask
53 FPSCR_LENGTH_MASK = (7 << 16), // Vector length bit mask 53 FPSCR_LENGTH_MASK = (7 << 16), // Vector length bit mask
54 54
55 FPSCR_IDE = (1 << 15), // Input Denormal exception trap enable. 55 FPSCR_IDE = (1 << 15), // Input Denormal exception trap enable.
56 FPSCR_IXE = (1 << 12), // Inexact exception trap enable 56 FPSCR_IXE = (1 << 12), // Inexact exception trap enable
57 FPSCR_UFE = (1 << 11), // Undeflow exception trap enable 57 FPSCR_UFE = (1 << 11), // Undeflow exception trap enable
58 FPSCR_OFE = (1 << 10), // Overflow exception trap enable 58 FPSCR_OFE = (1 << 10), // Overflow exception trap enable
59 FPSCR_DZE = (1 << 9), // Division by Zero exception trap enable 59 FPSCR_DZE = (1 << 9), // Division by Zero exception trap enable
60 FPSCR_IOE = (1 << 8), // Invalid Operation exception trap enable 60 FPSCR_IOE = (1 << 8), // Invalid Operation exception trap enable
61 61
62 FPSCR_IDC = (1 << 7), // Input Denormal cumulative exception bit 62 FPSCR_IDC = (1 << 7), // Input Denormal cumulative exception bit
63 FPSCR_IXC = (1 << 4), // Inexact cumulative exception bit 63 FPSCR_IXC = (1 << 4), // Inexact cumulative exception bit
64 FPSCR_UFC = (1 << 3), // Undeflow cumulative exception bit 64 FPSCR_UFC = (1 << 3), // Undeflow cumulative exception bit
65 FPSCR_OFC = (1 << 2), // Overflow cumulative exception bit 65 FPSCR_OFC = (1 << 2), // Overflow cumulative exception bit
66 FPSCR_DZC = (1 << 1), // Division by Zero cumulative exception bit 66 FPSCR_DZC = (1 << 1), // Division by Zero cumulative exception bit
67 FPSCR_IOC = (1 << 0), // Invalid Operation cumulative exception bit 67 FPSCR_IOC = (1 << 0), // Invalid Operation cumulative exception bit
68}; 68};
69 69
70// FPSCR bit offsets 70// FPSCR bit offsets
71enum : u32 { 71enum : u32 {
72 FPSCR_RMODE_BIT = 22, 72 FPSCR_RMODE_BIT = 22,
73 FPSCR_STRIDE_BIT = 20, 73 FPSCR_STRIDE_BIT = 20,
74 FPSCR_LENGTH_BIT = 16, 74 FPSCR_LENGTH_BIT = 16,
75}; 75};
76 76
77// FPSCR rounding modes 77// FPSCR rounding modes
78enum : u32 { 78enum : u32 {
79 FPSCR_ROUND_NEAREST = (0 << 22), 79 FPSCR_ROUND_NEAREST = (0 << 22),
80 FPSCR_ROUND_PLUSINF = (1 << 22), 80 FPSCR_ROUND_PLUSINF = (1 << 22),
81 FPSCR_ROUND_MINUSINF = (2 << 22), 81 FPSCR_ROUND_MINUSINF = (2 << 22),
82 FPSCR_ROUND_TOZERO = (3 << 22) 82 FPSCR_ROUND_TOZERO = (3 << 22)
83}; 83};
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index a27a7e194..859937645 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -28,15 +28,14 @@
28#include "core/arm/skyeye_common/vfp/asm_vfp.h" 28#include "core/arm/skyeye_common/vfp/asm_vfp.h"
29#include "core/arm/skyeye_common/vfp/vfp.h" 29#include "core/arm/skyeye_common/vfp/vfp.h"
30 30
31void VFPInit(ARMul_State* state) 31void VFPInit(ARMul_State* state) {
32{ 32 state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN << 24 | VFP_FPSID_SW << 23 | VFP_FPSID_SUBARCH << 16 |
33 state->VFP[VFP_FPSID] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 | 33 VFP_FPSID_PARTNUM << 8 | VFP_FPSID_VARIANT << 4 | VFP_FPSID_REVISION;
34 VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION;
35 state->VFP[VFP_FPEXC] = 0; 34 state->VFP[VFP_FPEXC] = 0;
36 state->VFP[VFP_FPSCR] = 0; 35 state->VFP[VFP_FPSCR] = 0;
37 36
38 // ARM11 MPCore instruction register reset values. 37 // ARM11 MPCore instruction register reset values.
39 state->VFP[VFP_FPINST] = 0xEE000A00; 38 state->VFP[VFP_FPINST] = 0xEE000A00;
40 state->VFP[VFP_FPINST2] = 0; 39 state->VFP[VFP_FPINST2] = 0;
41 40
42 // ARM11 MPCore feature register values. 41 // ARM11 MPCore feature register values.
@@ -44,104 +43,80 @@ void VFPInit(ARMul_State* state)
44 state->VFP[VFP_MVFR1] = 0; 43 state->VFP[VFP_MVFR1] = 0;
45} 44}
46 45
47void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value) 46void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value) {
48{ 47 if (to_arm) {
49 if (to_arm)
50 {
51 *value = state->ExtReg[n]; 48 *value = state->ExtReg[n];
52 } 49 } else {
53 else
54 {
55 state->ExtReg[n] = *value; 50 state->ExtReg[n] = *value;
56 } 51 }
57} 52}
58 53
59void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) 54void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) {
60{ 55 if (to_arm) {
61 if (to_arm) 56 *value2 = state->ExtReg[n * 2 + 1];
62 { 57 *value1 = state->ExtReg[n * 2];
63 *value2 = state->ExtReg[n*2+1]; 58 } else {
64 *value1 = state->ExtReg[n*2]; 59 state->ExtReg[n * 2 + 1] = *value2;
65 } 60 state->ExtReg[n * 2] = *value1;
66 else
67 {
68 state->ExtReg[n*2+1] = *value2;
69 state->ExtReg[n*2] = *value1;
70 } 61 }
71} 62}
72void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) 63void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) {
73{ 64 if (to_arm) {
74 if (to_arm) 65 *value1 = state->ExtReg[n + 0];
75 { 66 *value2 = state->ExtReg[n + 1];
76 *value1 = state->ExtReg[n+0]; 67 } else {
77 *value2 = state->ExtReg[n+1]; 68 state->ExtReg[n + 0] = *value1;
78 } 69 state->ExtReg[n + 1] = *value2;
79 else
80 {
81 state->ExtReg[n+0] = *value1;
82 state->ExtReg[n+1] = *value2;
83 } 70 }
84} 71}
85 72
86void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) 73void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) {
87{ 74 if (single) {
88 if (single)
89 {
90 state->ExtReg[d] = imm; 75 state->ExtReg[d] = imm;
91 } 76 } else {
92 else
93 {
94 /* Check endian please */ 77 /* Check endian please */
95 state->ExtReg[d*2+1] = imm; 78 state->ExtReg[d * 2 + 1] = imm;
96 state->ExtReg[d*2] = 0; 79 state->ExtReg[d * 2] = 0;
97 } 80 }
98} 81}
99void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) 82void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) {
100{ 83 if (single) {
101 if (single)
102 {
103 state->ExtReg[d] = state->ExtReg[m]; 84 state->ExtReg[d] = state->ExtReg[m];
104 } 85 } else {
105 else
106 {
107 /* Check endian please */ 86 /* Check endian please */
108 state->ExtReg[d*2+1] = state->ExtReg[m*2+1]; 87 state->ExtReg[d * 2 + 1] = state->ExtReg[m * 2 + 1];
109 state->ExtReg[d*2] = state->ExtReg[m*2]; 88 state->ExtReg[d * 2] = state->ExtReg[m * 2];
110 } 89 }
111} 90}
112 91
113/* Miscellaneous functions */ 92/* Miscellaneous functions */
114s32 vfp_get_float(ARMul_State* state, unsigned int reg) 93s32 vfp_get_float(ARMul_State* state, unsigned int reg) {
115{
116 LOG_TRACE(Core_ARM11, "VFP get float: s%d=[%08x]", reg, state->ExtReg[reg]); 94 LOG_TRACE(Core_ARM11, "VFP get float: s%d=[%08x]", reg, state->ExtReg[reg]);
117 return state->ExtReg[reg]; 95 return state->ExtReg[reg];
118} 96}
119 97
120void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg) 98void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg) {
121{
122 LOG_TRACE(Core_ARM11, "VFP put float: s%d <= [%08x]", reg, val); 99 LOG_TRACE(Core_ARM11, "VFP put float: s%d <= [%08x]", reg, val);
123 state->ExtReg[reg] = val; 100 state->ExtReg[reg] = val;
124} 101}
125 102
126u64 vfp_get_double(ARMul_State* state, unsigned int reg) 103u64 vfp_get_double(ARMul_State* state, unsigned int reg) {
127{ 104 u64 result = ((u64)state->ExtReg[reg * 2 + 1]) << 32 | state->ExtReg[reg * 2];
128 u64 result = ((u64) state->ExtReg[reg*2+1])<<32 | state->ExtReg[reg*2];
129 LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]", reg * 2 + 1, reg * 2, result); 105 LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]", reg * 2 + 1, reg * 2, result);
130 return result; 106 return result;
131} 107}
132 108
133void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg) 109void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg) {
134{ 110 LOG_TRACE(Core_ARM11, "VFP put double: s[%d-%d] <= [%08x-%08x]", reg * 2 + 1, reg * 2,
135 LOG_TRACE(Core_ARM11, "VFP put double: s[%d-%d] <= [%08x-%08x]", reg * 2 + 1, reg * 2, (u32)(val >> 32), (u32)(val & 0xffffffff)); 111 (u32)(val >> 32), (u32)(val & 0xffffffff));
136 state->ExtReg[reg*2] = (u32) (val & 0xffffffff); 112 state->ExtReg[reg * 2] = (u32)(val & 0xffffffff);
137 state->ExtReg[reg*2+1] = (u32) (val>>32); 113 state->ExtReg[reg * 2 + 1] = (u32)(val >> 32);
138} 114}
139 115
140/* 116/*
141 * Process bitmask of exception conditions. (from vfpmodule.c) 117 * Process bitmask of exception conditions. (from vfpmodule.c)
142 */ 118 */
143void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) 119void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) {
144{
145 LOG_TRACE(Core_ARM11, "VFP: raising exceptions %08x", exceptions); 120 LOG_TRACE(Core_ARM11, "VFP: raising exceptions %08x", exceptions);
146 121
147 if (exceptions == VFP_EXCEPTION_ERROR) { 122 if (exceptions == VFP_EXCEPTION_ERROR) {
@@ -154,8 +129,8 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc
154 * Comparison instructions always return at least one of 129 * Comparison instructions always return at least one of
155 * these flags set. 130 * these flags set.
156 */ 131 */
157 if (exceptions & (FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG)) 132 if (exceptions & (FPSCR_NFLAG | FPSCR_ZFLAG | FPSCR_CFLAG | FPSCR_VFLAG))
158 fpscr &= ~(FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG); 133 fpscr &= ~(FPSCR_NFLAG | FPSCR_ZFLAG | FPSCR_CFLAG | FPSCR_VFLAG);
159 134
160 fpscr |= exceptions; 135 fpscr |= exceptions;
161 136
diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h
index 68714800c..5e14345ce 100644
--- a/src/core/arm/skyeye_common/vfp/vfp_helper.h
+++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h
@@ -37,56 +37,56 @@
37#include "core/arm/skyeye_common/armstate.h" 37#include "core/arm/skyeye_common/armstate.h"
38#include "core/arm/skyeye_common/vfp/asm_vfp.h" 38#include "core/arm/skyeye_common/vfp/asm_vfp.h"
39 39
40#define do_div(n, base) {n/=base;} 40#define do_div(n, base) \
41 { n /= base; }
41 42
42enum : u32 { 43enum : u32 {
43 FOP_MASK = 0x00b00040, 44 FOP_MASK = 0x00b00040,
44 FOP_FMAC = 0x00000000, 45 FOP_FMAC = 0x00000000,
45 FOP_FNMAC = 0x00000040, 46 FOP_FNMAC = 0x00000040,
46 FOP_FMSC = 0x00100000, 47 FOP_FMSC = 0x00100000,
47 FOP_FNMSC = 0x00100040, 48 FOP_FNMSC = 0x00100040,
48 FOP_FMUL = 0x00200000, 49 FOP_FMUL = 0x00200000,
49 FOP_FNMUL = 0x00200040, 50 FOP_FNMUL = 0x00200040,
50 FOP_FADD = 0x00300000, 51 FOP_FADD = 0x00300000,
51 FOP_FSUB = 0x00300040, 52 FOP_FSUB = 0x00300040,
52 FOP_FDIV = 0x00800000, 53 FOP_FDIV = 0x00800000,
53 FOP_EXT = 0x00b00040 54 FOP_EXT = 0x00b00040
54}; 55};
55 56
56#define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4) 57#define FOP_TO_IDX(inst) ((inst & 0x00b00000) >> 20 | (inst & (1 << 6)) >> 4)
57 58
58enum : u32 { 59enum : u32 {
59 FEXT_MASK = 0x000f0080, 60 FEXT_MASK = 0x000f0080,
60 FEXT_FCPY = 0x00000000, 61 FEXT_FCPY = 0x00000000,
61 FEXT_FABS = 0x00000080, 62 FEXT_FABS = 0x00000080,
62 FEXT_FNEG = 0x00010000, 63 FEXT_FNEG = 0x00010000,
63 FEXT_FSQRT = 0x00010080, 64 FEXT_FSQRT = 0x00010080,
64 FEXT_FCMP = 0x00040000, 65 FEXT_FCMP = 0x00040000,
65 FEXT_FCMPE = 0x00040080, 66 FEXT_FCMPE = 0x00040080,
66 FEXT_FCMPZ = 0x00050000, 67 FEXT_FCMPZ = 0x00050000,
67 FEXT_FCMPEZ = 0x00050080, 68 FEXT_FCMPEZ = 0x00050080,
68 FEXT_FCVT = 0x00070080, 69 FEXT_FCVT = 0x00070080,
69 FEXT_FUITO = 0x00080000, 70 FEXT_FUITO = 0x00080000,
70 FEXT_FSITO = 0x00080080, 71 FEXT_FSITO = 0x00080080,
71 FEXT_FTOUI = 0x000c0000, 72 FEXT_FTOUI = 0x000c0000,
72 FEXT_FTOUIZ = 0x000c0080, 73 FEXT_FTOUIZ = 0x000c0080,
73 FEXT_FTOSI = 0x000d0000, 74 FEXT_FTOSI = 0x000d0000,
74 FEXT_FTOSIZ = 0x000d0080 75 FEXT_FTOSIZ = 0x000d0080
75}; 76};
76 77
77#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) 78#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
78 79
79#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22) 80#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22)
80#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18) 81#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18)
81#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5) 82#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5)
82#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1) 83#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1)
83#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) 84#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
84#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3) 85#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3)
85 86
86#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00) 87#define vfp_single(inst) (((inst)&0x0000f00) == 0xa00)
87 88
88inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) 89inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift) {
89{
90 if (shift) { 90 if (shift) {
91 if (shift < 32) 91 if (shift < 32)
92 val = val >> shift | ((val << (32 - shift)) != 0); 92 val = val >> shift | ((val << (32 - shift)) != 0);
@@ -96,8 +96,7 @@ inline u32 vfp_shiftright32jamming(u32 val, unsigned int shift)
96 return val; 96 return val;
97} 97}
98 98
99inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) 99inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift) {
100{
101 if (shift) { 100 if (shift) {
102 if (shift < 64) 101 if (shift < 64)
103 val = val >> shift | ((val << (64 - shift)) != 0); 102 val = val >> shift | ((val << (64 - shift)) != 0);
@@ -107,8 +106,7 @@ inline u64 vfp_shiftright64jamming(u64 val, unsigned int shift)
107 return val; 106 return val;
108} 107}
109 108
110inline u32 vfp_hi64to32jamming(u64 val) 109inline u32 vfp_hi64to32jamming(u64 val) {
111{
112 u32 v; 110 u32 v;
113 u32 highval = val >> 32; 111 u32 highval = val >> 32;
114 u32 lowval = val & 0xffffffff; 112 u32 lowval = val & 0xffffffff;
@@ -121,24 +119,21 @@ inline u32 vfp_hi64to32jamming(u64 val)
121 return v; 119 return v;
122} 120}
123 121
124inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) 122inline void add128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) {
125{
126 *resl = nl + ml; 123 *resl = nl + ml;
127 *resh = nh + mh; 124 *resh = nh + mh;
128 if (*resl < nl) 125 if (*resl < nl)
129 *resh += 1; 126 *resh += 1;
130} 127}
131 128
132inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) 129inline void sub128(u64* resh, u64* resl, u64 nh, u64 nl, u64 mh, u64 ml) {
133{
134 *resl = nl - ml; 130 *resl = nl - ml;
135 *resh = nh - mh; 131 *resh = nh - mh;
136 if (*resl > nl) 132 if (*resl > nl)
137 *resh -= 1; 133 *resh -= 1;
138} 134}
139 135
140inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m) 136inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m) {
141{
142 u32 nh, nl, mh, ml; 137 u32 nh, nl, mh, ml;
143 u64 rh, rma, rmb, rl; 138 u64 rh, rma, rmb, rl;
144 139
@@ -164,21 +159,18 @@ inline void mul64to128(u64* resh, u64* resl, u64 n, u64 m)
164 *resh = rh; 159 *resh = rh;
165} 160}
166 161
167inline void shift64left(u64* resh, u64* resl, u64 n) 162inline void shift64left(u64* resh, u64* resl, u64 n) {
168{
169 *resh = n >> 63; 163 *resh = n >> 63;
170 *resl = n << 1; 164 *resl = n << 1;
171} 165}
172 166
173inline u64 vfp_hi64multiply64(u64 n, u64 m) 167inline u64 vfp_hi64multiply64(u64 n, u64 m) {
174{
175 u64 rh, rl; 168 u64 rh, rl;
176 mul64to128(&rh, &rl, n, m); 169 mul64to128(&rh, &rl, n, m);
177 return rh | (rl != 0); 170 return rh | (rl != 0);
178} 171}
179 172
180inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) 173inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m) {
181{
182 u64 mh, ml, remh, reml, termh, terml, z; 174 u64 mh, ml, remh, reml, termh, terml, z;
183 175
184 if (nh >= m) 176 if (nh >= m)
@@ -213,9 +205,9 @@ inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
213 205
214// Single-precision 206// Single-precision
215struct vfp_single { 207struct vfp_single {
216 s16 exponent; 208 s16 exponent;
217 u16 sign; 209 u16 sign;
218 u32 significand; 210 u32 significand;
219}; 211};
220 212
221// VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa 213// VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa
@@ -224,33 +216,33 @@ struct vfp_single {
224// which are not propagated to the float upon packing. 216// which are not propagated to the float upon packing.
225#define VFP_SINGLE_MANTISSA_BITS (23) 217#define VFP_SINGLE_MANTISSA_BITS (23)
226#define VFP_SINGLE_EXPONENT_BITS (8) 218#define VFP_SINGLE_EXPONENT_BITS (8)
227#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2) 219#define VFP_SINGLE_LOW_BITS (32 - VFP_SINGLE_MANTISSA_BITS - 2)
228#define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1) 220#define VFP_SINGLE_LOW_BITS_MASK ((1 << VFP_SINGLE_LOW_BITS) - 1)
229 221
230// The bit in an unpacked float which indicates that it is a quiet NaN 222// The bit in an unpacked float which indicates that it is a quiet NaN
231#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS)) 223#define VFP_SINGLE_SIGNIFICAND_QNAN (1 << (VFP_SINGLE_MANTISSA_BITS - 1 + VFP_SINGLE_LOW_BITS))
232 224
233// Operations on packed single-precision numbers 225// Operations on packed single-precision numbers
234#define vfp_single_packed_sign(v) ((v) & 0x80000000) 226#define vfp_single_packed_sign(v) ((v)&0x80000000)
235#define vfp_single_packed_negate(v) ((v) ^ 0x80000000) 227#define vfp_single_packed_negate(v) ((v) ^ 0x80000000)
236#define vfp_single_packed_abs(v) ((v) & ~0x80000000) 228#define vfp_single_packed_abs(v) ((v) & ~0x80000000)
237#define vfp_single_packed_exponent(v) (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1)) 229#define vfp_single_packed_exponent(v) \
230 (((v) >> VFP_SINGLE_MANTISSA_BITS) & ((1 << VFP_SINGLE_EXPONENT_BITS) - 1))
238#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1)) 231#define vfp_single_packed_mantissa(v) ((v) & ((1 << VFP_SINGLE_MANTISSA_BITS) - 1))
239 232
240enum : u32 { 233enum : u32 {
241 VFP_NUMBER = (1 << 0), 234 VFP_NUMBER = (1 << 0),
242 VFP_ZERO = (1 << 1), 235 VFP_ZERO = (1 << 1),
243 VFP_DENORMAL = (1 << 2), 236 VFP_DENORMAL = (1 << 2),
244 VFP_INFINITY = (1 << 3), 237 VFP_INFINITY = (1 << 3),
245 VFP_NAN = (1 << 4), 238 VFP_NAN = (1 << 4),
246 VFP_NAN_SIGNAL = (1 << 5), 239 VFP_NAN_SIGNAL = (1 << 5),
247 240
248 VFP_QNAN = (VFP_NAN), 241 VFP_QNAN = (VFP_NAN),
249 VFP_SNAN = (VFP_NAN|VFP_NAN_SIGNAL) 242 VFP_SNAN = (VFP_NAN | VFP_NAN_SIGNAL)
250}; 243};
251 244
252inline int vfp_single_type(const vfp_single* s) 245inline int vfp_single_type(const vfp_single* s) {
253{
254 int type = VFP_NUMBER; 246 int type = VFP_NUMBER;
255 if (s->exponent == 255) { 247 if (s->exponent == 255) {
256 if (s->significand == 0) 248 if (s->significand == 0)
@@ -271,11 +263,9 @@ inline int vfp_single_type(const vfp_single* s)
271// Unpack a single-precision float. Note that this returns the magnitude 263// Unpack a single-precision float. Note that this returns the magnitude
272// of the single-precision float mantissa with the 1. if necessary, 264// of the single-precision float mantissa with the 1. if necessary,
273// aligned to bit 30. 265// aligned to bit 30.
274inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr) 266inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr) {
275{
276 u32 exceptions = 0; 267 u32 exceptions = 0;
277 s->sign = vfp_single_packed_sign(val) >> 16, 268 s->sign = vfp_single_packed_sign(val) >> 16, s->exponent = vfp_single_packed_exponent(val);
278 s->exponent = vfp_single_packed_exponent(val);
279 269
280 u32 significand = ((u32)val << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2; 270 u32 significand = ((u32)val << (32 - VFP_SINGLE_MANTISSA_BITS)) >> 2;
281 if (s->exponent && s->exponent != 255) 271 if (s->exponent && s->exponent != 255)
@@ -295,22 +285,20 @@ inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr)
295 285
296// Re-pack a single-precision float. This assumes that the float is 286// Re-pack a single-precision float. This assumes that the float is
297// already normalised such that the MSB is bit 30, _not_ bit 31. 287// already normalised such that the MSB is bit 30, _not_ bit 31.
298inline s32 vfp_single_pack(const vfp_single* s) 288inline s32 vfp_single_pack(const vfp_single* s) {
299{ 289 u32 val = (s->sign << 16) + (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
300 u32 val = (s->sign << 16) +
301 (s->exponent << VFP_SINGLE_MANTISSA_BITS) +
302 (s->significand >> VFP_SINGLE_LOW_BITS); 290 (s->significand >> VFP_SINGLE_LOW_BITS);
303 return (s32)val; 291 return (s32)val;
304} 292}
305 293
306 294u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr,
307u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, const char* func); 295 const char* func);
308 296
309// Double-precision 297// Double-precision
310struct vfp_double { 298struct vfp_double {
311 s16 exponent; 299 s16 exponent;
312 u16 sign; 300 u16 sign;
313 u64 significand; 301 u64 significand;
314}; 302};
315 303
316// VFP_REG_ZERO is a special register number for vfp_get_double 304// VFP_REG_ZERO is a special register number for vfp_get_double
@@ -324,21 +312,21 @@ struct vfp_double {
324 312
325#define VFP_DOUBLE_MANTISSA_BITS (52) 313#define VFP_DOUBLE_MANTISSA_BITS (52)
326#define VFP_DOUBLE_EXPONENT_BITS (11) 314#define VFP_DOUBLE_EXPONENT_BITS (11)
327#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2) 315#define VFP_DOUBLE_LOW_BITS (64 - VFP_DOUBLE_MANTISSA_BITS - 2)
328#define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1) 316#define VFP_DOUBLE_LOW_BITS_MASK ((1 << VFP_DOUBLE_LOW_BITS) - 1)
329 317
330// The bit in an unpacked double which indicates that it is a quiet NaN 318// The bit in an unpacked double which indicates that it is a quiet NaN
331#define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS)) 319#define VFP_DOUBLE_SIGNIFICAND_QNAN (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1 + VFP_DOUBLE_LOW_BITS))
332 320
333// Operations on packed single-precision numbers 321// Operations on packed single-precision numbers
334#define vfp_double_packed_sign(v) ((v) & (1ULL << 63)) 322#define vfp_double_packed_sign(v) ((v) & (1ULL << 63))
335#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63)) 323#define vfp_double_packed_negate(v) ((v) ^ (1ULL << 63))
336#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63)) 324#define vfp_double_packed_abs(v) ((v) & ~(1ULL << 63))
337#define vfp_double_packed_exponent(v) (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1)) 325#define vfp_double_packed_exponent(v) \
326 (((v) >> VFP_DOUBLE_MANTISSA_BITS) & ((1 << VFP_DOUBLE_EXPONENT_BITS) - 1))
338#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1)) 327#define vfp_double_packed_mantissa(v) ((v) & ((1ULL << VFP_DOUBLE_MANTISSA_BITS) - 1))
339 328
340inline int vfp_double_type(const vfp_double* s) 329inline int vfp_double_type(const vfp_double* s) {
341{
342 int type = VFP_NUMBER; 330 int type = VFP_NUMBER;
343 if (s->exponent == 2047) { 331 if (s->exponent == 2047) {
344 if (s->significand == 0) 332 if (s->significand == 0)
@@ -359,8 +347,7 @@ inline int vfp_double_type(const vfp_double* s)
359// Unpack a double-precision float. Note that this returns the magnitude 347// Unpack a double-precision float. Note that this returns the magnitude
360// of the double-precision float mantissa with the 1. if necessary, 348// of the double-precision float mantissa with the 1. if necessary,
361// aligned to bit 62. 349// aligned to bit 62.
362inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr) 350inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr) {
363{
364 u32 exceptions = 0; 351 u32 exceptions = 0;
365 s->sign = vfp_double_packed_sign(val) >> 48; 352 s->sign = vfp_double_packed_sign(val) >> 48;
366 s->exponent = vfp_double_packed_exponent(val); 353 s->exponent = vfp_double_packed_exponent(val);
@@ -383,10 +370,8 @@ inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr)
383 370
384// Re-pack a double-precision float. This assumes that the float is 371// Re-pack a double-precision float. This assumes that the float is
385// already normalised such that the MSB is bit 30, _not_ bit 31. 372// already normalised such that the MSB is bit 30, _not_ bit 31.
386inline s64 vfp_double_pack(const vfp_double* s) 373inline s64 vfp_double_pack(const vfp_double* s) {
387{ 374 u64 val = ((u64)s->sign << 48) + ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
388 u64 val = ((u64)s->sign << 48) +
389 ((u64)s->exponent << VFP_DOUBLE_MANTISSA_BITS) +
390 (s->significand >> VFP_DOUBLE_LOW_BITS); 375 (s->significand >> VFP_DOUBLE_LOW_BITS);
391 return (s64)val; 376 return (s64)val;
392} 377}
@@ -407,20 +392,14 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand);
407// OP_SD - The instruction exceptionally writes to a single precision result. 392// OP_SD - The instruction exceptionally writes to a single precision result.
408// OP_DD - The instruction exceptionally writes to a double precision result. 393// OP_DD - The instruction exceptionally writes to a double precision result.
409// OP_SM - The instruction exceptionally reads from a single precision operand. 394// OP_SM - The instruction exceptionally reads from a single precision operand.
410enum : u32 { 395enum : u32 { OP_SCALAR = (1 << 0), OP_SD = (1 << 1), OP_DD = (1 << 1), OP_SM = (1 << 2) };
411 OP_SCALAR = (1 << 0),
412 OP_SD = (1 << 1),
413 OP_DD = (1 << 1),
414 OP_SM = (1 << 2)
415};
416 396
417struct op { 397struct op {
418 u32 (* const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr); 398 u32 (*const fn)(ARMul_State* state, int dd, int dn, int dm, u32 fpscr);
419 u32 flags; 399 u32 flags;
420}; 400};
421 401
422inline u32 fls(u32 x) 402inline u32 fls(u32 x) {
423{
424 int r = 32; 403 int r = 32;
425 404
426 if (!x) 405 if (!x)
@@ -446,9 +425,9 @@ inline u32 fls(u32 x)
446 r -= 1; 425 r -= 1;
447 } 426 }
448 return r; 427 return r;
449
450} 428}
451 429
452u32 vfp_double_multiply(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr); 430u32 vfp_double_multiply(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr);
453u32 vfp_double_add(vfp_double* vdd, vfp_double* vdn, vfp_double *vdm, u32 fpscr); 431u32 vfp_double_add(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr);
454u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double* vd, u32 fpscr, const char* func); 432u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double* vd, u32 fpscr,
433 const char* func);
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
index 1d5641810..4d89743e7 100644
--- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
@@ -51,26 +51,22 @@
51 * =========================================================================== 51 * ===========================================================================
52 */ 52 */
53 53
54#include "core/arm/skyeye_common/vfp/vfp.h"
54#include <algorithm> 55#include <algorithm>
55#include "common/logging/log.h" 56#include "common/logging/log.h"
56#include "core/arm/skyeye_common/vfp/vfp.h"
57#include "core/arm/skyeye_common/vfp/vfp_helper.h"
58#include "core/arm/skyeye_common/vfp/asm_vfp.h" 57#include "core/arm/skyeye_common/vfp/asm_vfp.h"
58#include "core/arm/skyeye_common/vfp/vfp_helper.h"
59 59
60static struct vfp_double vfp_double_default_qnan = { 60static struct vfp_double vfp_double_default_qnan = {
61 2047, 61 2047, 0, VFP_DOUBLE_SIGNIFICAND_QNAN,
62 0,
63 VFP_DOUBLE_SIGNIFICAND_QNAN,
64}; 62};
65 63
66static void vfp_double_dump(const char *str, struct vfp_double *d) 64static void vfp_double_dump(const char* str, struct vfp_double* d) {
67{ 65 LOG_TRACE(Core_ARM11, "VFP: %s: sign=%d exponent=%d significand=%016llx", str, d->sign != 0,
68 LOG_TRACE(Core_ARM11, "VFP: %s: sign=%d exponent=%d significand=%016llx", 66 d->exponent, d->significand);
69 str, d->sign != 0, d->exponent, d->significand);
70} 67}
71 68
72static void vfp_double_normalise_denormal(struct vfp_double *vd) 69static void vfp_double_normalise_denormal(struct vfp_double* vd) {
73{
74 int bits = 31 - fls((u32)(vd->significand >> 32)); 70 int bits = 31 - fls((u32)(vd->significand >> 32));
75 if (bits == 31) 71 if (bits == 31)
76 bits = 63 - fls((u32)vd->significand); 72 bits = 63 - fls((u32)vd->significand);
@@ -85,8 +81,8 @@ static void vfp_double_normalise_denormal(struct vfp_double *vd)
85 vfp_double_dump("normalise_denormal: out", vd); 81 vfp_double_dump("normalise_denormal: out", vd);
86} 82}
87 83
88u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, const char *func) 84u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double* vd, u32 fpscr,
89{ 85 const char* func) {
90 u64 significand, incr; 86 u64 significand, incr;
91 int exponent, shift, underflow; 87 int exponent, shift, underflow;
92 u32 rmode; 88 u32 rmode;
@@ -193,7 +189,7 @@ u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd,
193 vd->exponent = 2045; 189 vd->exponent = 2045;
194 vd->significand = 0x7fffffffffffffffULL; 190 vd->significand = 0x7fffffffffffffffULL;
195 } else { 191 } else {
196 vd->exponent = 2047; /* infinity */ 192 vd->exponent = 2047; /* infinity */
197 vd->significand = 0; 193 vd->significand = 0;
198 } 194 }
199 } else { 195 } else {
@@ -211,8 +207,7 @@ pack:
211 vfp_double_dump("pack: final", vd); 207 vfp_double_dump("pack: final", vd);
212 { 208 {
213 s64 d = vfp_double_pack(vd); 209 s64 d = vfp_double_pack(vd);
214 LOG_TRACE(Core_ARM11, "VFP: %s: d(d%d)=%016llx exceptions=%08x", func, 210 LOG_TRACE(Core_ARM11, "VFP: %s: d(d%d)=%016llx exceptions=%08x", func, dd, d, exceptions);
215 dd, d, exceptions);
216 vfp_put_double(state, d, dd); 211 vfp_put_double(state, d, dd);
217 } 212 }
218 return exceptions; 213 return exceptions;
@@ -222,11 +217,9 @@ pack:
222 * Propagate the NaN, setting exceptions if it is signalling. 217 * Propagate the NaN, setting exceptions if it is signalling.
223 * 'n' is always a NaN. 'm' may be a number, NaN or infinity. 218 * 'n' is always a NaN. 'm' may be a number, NaN or infinity.
224 */ 219 */
225static u32 220static u32 vfp_propagate_nan(struct vfp_double* vdd, struct vfp_double* vdn, struct vfp_double* vdm,
226vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn, 221 u32 fpscr) {
227 struct vfp_double *vdm, u32 fpscr) 222 struct vfp_double* nan;
228{
229 struct vfp_double *nan;
230 int tn, tm = 0; 223 int tn, tm = 0;
231 224
232 tn = vfp_double_type(vdn); 225 tn = vfp_double_type(vdn);
@@ -266,29 +259,25 @@ vfp_propagate_nan(struct vfp_double *vdd, struct vfp_double *vdn,
266/* 259/*
267 * Extended operations 260 * Extended operations
268 */ 261 */
269static u32 vfp_double_fabs(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 262static u32 vfp_double_fabs(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
270{
271 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 263 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
272 vfp_put_double(state, vfp_double_packed_abs(vfp_get_double(state, dm)), dd); 264 vfp_put_double(state, vfp_double_packed_abs(vfp_get_double(state, dm)), dd);
273 return 0; 265 return 0;
274} 266}
275 267
276static u32 vfp_double_fcpy(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 268static u32 vfp_double_fcpy(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
277{
278 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 269 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
279 vfp_put_double(state, vfp_get_double(state, dm), dd); 270 vfp_put_double(state, vfp_get_double(state, dm), dd);
280 return 0; 271 return 0;
281} 272}
282 273
283static u32 vfp_double_fneg(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 274static u32 vfp_double_fneg(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
284{
285 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 275 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
286 vfp_put_double(state, vfp_double_packed_negate(vfp_get_double(state, dm)), dd); 276 vfp_put_double(state, vfp_double_packed_negate(vfp_get_double(state, dm)), dd);
287 return 0; 277 return 0;
288} 278}
289 279
290static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 280static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
291{
292 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 281 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
293 vfp_double vdm, vdd, *vdp; 282 vfp_double vdm, vdd, *vdp;
294 int ret, tm; 283 int ret, tm;
@@ -297,17 +286,17 @@ static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32
297 exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); 286 exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr);
298 287
299 tm = vfp_double_type(&vdm); 288 tm = vfp_double_type(&vdm);
300 if (tm & (VFP_NAN|VFP_INFINITY)) { 289 if (tm & (VFP_NAN | VFP_INFINITY)) {
301 vdp = &vdd; 290 vdp = &vdd;
302 291
303 if (tm & VFP_NAN) 292 if (tm & VFP_NAN)
304 ret = vfp_propagate_nan(vdp, &vdm, nullptr, fpscr); 293 ret = vfp_propagate_nan(vdp, &vdm, nullptr, fpscr);
305 else if (vdm.sign == 0) { 294 else if (vdm.sign == 0) {
306sqrt_copy: 295 sqrt_copy:
307 vdp = &vdm; 296 vdp = &vdm;
308 ret = 0; 297 ret = 0;
309 } else { 298 } else {
310sqrt_invalid: 299 sqrt_invalid:
311 vdp = &vfp_double_default_qnan; 300 vdp = &vfp_double_default_qnan;
312 ret = FPSCR_IOC; 301 ret = FPSCR_IOC;
313 } 302 }
@@ -381,8 +370,7 @@ sqrt_invalid:
381 * Greater than := C 370 * Greater than := C
382 * Unordered := CV 371 * Unordered := CV
383 */ 372 */
384static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u32 fpscr) 373static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u32 fpscr) {
385{
386 s64 d, m; 374 s64 d, m;
387 u32 ret = 0; 375 u32 ret = 0;
388 376
@@ -390,7 +378,8 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
390 m = vfp_get_double(state, dm); 378 m = vfp_get_double(state, dm);
391 if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) { 379 if (vfp_double_packed_exponent(m) == 2047 && vfp_double_packed_mantissa(m)) {
392 ret |= FPSCR_CFLAG | FPSCR_VFLAG; 380 ret |= FPSCR_CFLAG | FPSCR_VFLAG;
393 if (signal_on_qnan || !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) 381 if (signal_on_qnan ||
382 !(vfp_double_packed_mantissa(m) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
394 /* 383 /*
395 * Signalling NaN, or signalling on quiet NaN 384 * Signalling NaN, or signalling on quiet NaN
396 */ 385 */
@@ -400,7 +389,8 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
400 d = vfp_get_double(state, dd); 389 d = vfp_get_double(state, dd);
401 if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) { 390 if (vfp_double_packed_exponent(d) == 2047 && vfp_double_packed_mantissa(d)) {
402 ret |= FPSCR_CFLAG | FPSCR_VFLAG; 391 ret |= FPSCR_CFLAG | FPSCR_VFLAG;
403 if (signal_on_qnan || !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1)))) 392 if (signal_on_qnan ||
393 !(vfp_double_packed_mantissa(d) & (1ULL << (VFP_DOUBLE_MANTISSA_BITS - 1))))
404 /* 394 /*
405 * Signalling NaN, or signalling on quiet NaN 395 * Signalling NaN, or signalling on quiet NaN
406 */ 396 */
@@ -408,13 +398,13 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
408 } 398 }
409 399
410 if (ret == 0) { 400 if (ret == 0) {
411 //printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m); 401 // printf("In %s, d=%lld, m =%lld\n ", __FUNCTION__, d, m);
412 if (d == m || vfp_double_packed_abs(d | m) == 0) { 402 if (d == m || vfp_double_packed_abs(d | m) == 0) {
413 /* 403 /*
414 * equal 404 * equal
415 */ 405 */
416 ret |= FPSCR_ZFLAG | FPSCR_CFLAG; 406 ret |= FPSCR_ZFLAG | FPSCR_CFLAG;
417 //printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret); 407 // printf("In %s,1 ret=0x%x\n", __FUNCTION__, ret);
418 } else if (vfp_double_packed_sign(d ^ m)) { 408 } else if (vfp_double_packed_sign(d ^ m)) {
419 /* 409 /*
420 * different signs 410 * different signs
@@ -446,32 +436,27 @@ static u32 vfp_compare(ARMul_State* state, int dd, int signal_on_qnan, int dm, u
446 return ret; 436 return ret;
447} 437}
448 438
449static u32 vfp_double_fcmp(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 439static u32 vfp_double_fcmp(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
450{
451 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 440 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
452 return vfp_compare(state, dd, 0, dm, fpscr); 441 return vfp_compare(state, dd, 0, dm, fpscr);
453} 442}
454 443
455static u32 vfp_double_fcmpe(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 444static u32 vfp_double_fcmpe(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
456{
457 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 445 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
458 return vfp_compare(state, dd, 1, dm, fpscr); 446 return vfp_compare(state, dd, 1, dm, fpscr);
459} 447}
460 448
461static u32 vfp_double_fcmpz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 449static u32 vfp_double_fcmpz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
462{
463 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 450 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
464 return vfp_compare(state, dd, 0, VFP_REG_ZERO, fpscr); 451 return vfp_compare(state, dd, 0, VFP_REG_ZERO, fpscr);
465} 452}
466 453
467static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 454static u32 vfp_double_fcmpez(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
468{
469 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 455 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
470 return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr); 456 return vfp_compare(state, dd, 1, VFP_REG_ZERO, fpscr);
471} 457}
472 458
473static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) 459static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) {
474{
475 struct vfp_double vdm; 460 struct vfp_double vdm;
476 struct vfp_single vsd; 461 struct vfp_single vsd;
477 int tm; 462 int tm;
@@ -497,7 +482,7 @@ static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32
497 /* 482 /*
498 * If we have an infinity or a NaN, the exponent must be 255 483 * If we have an infinity or a NaN, the exponent must be 255
499 */ 484 */
500 if (tm & (VFP_INFINITY|VFP_NAN)) { 485 if (tm & (VFP_INFINITY | VFP_NAN)) {
501 vsd.exponent = 255; 486 vsd.exponent = 255;
502 if (tm == VFP_QNAN) 487 if (tm == VFP_QNAN)
503 vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN; 488 vsd.significand |= VFP_SINGLE_SIGNIFICAND_QNAN;
@@ -515,8 +500,7 @@ pack_nan:
515 return exceptions; 500 return exceptions;
516} 501}
517 502
518static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 503static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
519{
520 struct vfp_double vdm; 504 struct vfp_double vdm;
521 u32 exceptions = 0; 505 u32 exceptions = 0;
522 u32 m = vfp_get_float(state, dm); 506 u32 m = vfp_get_float(state, dm);
@@ -530,8 +514,7 @@ static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32
530 return exceptions; 514 return exceptions;
531} 515}
532 516
533static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 517static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
534{
535 struct vfp_double vdm; 518 struct vfp_double vdm;
536 u32 exceptions = 0; 519 u32 exceptions = 0;
537 u32 m = vfp_get_float(state, dm); 520 u32 m = vfp_get_float(state, dm);
@@ -545,8 +528,7 @@ static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32
545 return exceptions; 528 return exceptions;
546} 529}
547 530
548static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) 531static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) {
549{
550 struct vfp_double vdm; 532 struct vfp_double vdm;
551 u32 d, exceptions = 0; 533 u32 d, exceptions = 0;
552 int rmode = fpscr & FPSCR_RMODE_MASK; 534 int rmode = fpscr & FPSCR_RMODE_MASK;
@@ -628,14 +610,13 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32
628 return exceptions; 610 return exceptions;
629} 611}
630 612
631static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) 613static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) {
632{
633 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 614 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
634 return vfp_double_ftoui(state, sd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); 615 return vfp_double_ftoui(state, sd, unused, dm,
616 (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO);
635} 617}
636 618
637static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) 619static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) {
638{
639 struct vfp_double vdm; 620 struct vfp_double vdm;
640 u32 d, exceptions = 0; 621 u32 d, exceptions = 0;
641 int rmode = fpscr & FPSCR_RMODE_MASK; 622 int rmode = fpscr & FPSCR_RMODE_MASK;
@@ -661,7 +642,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32
661 d = ~d; 642 d = ~d;
662 exceptions |= FPSCR_IOC; 643 exceptions |= FPSCR_IOC;
663 } else if (vdm.exponent >= 1023) { 644 } else if (vdm.exponent >= 1023) {
664 int shift = 1023 + 63 - vdm.exponent; /* 58 */ 645 int shift = 1023 + 63 - vdm.exponent; /* 58 */
665 u64 rem, incr = 0; 646 u64 rem, incr = 0;
666 647
667 d = (u32)((vdm.significand << 1) >> shift); 648 d = (u32)((vdm.significand << 1) >> shift);
@@ -712,48 +693,46 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32
712 return exceptions; 693 return exceptions;
713} 694}
714 695
715static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) 696static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) {
716{
717 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 697 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
718 return vfp_double_ftosi(state, dd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); 698 return vfp_double_ftosi(state, dd, unused, dm,
699 (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO);
719} 700}
720 701
721static struct op fops_ext[] = { 702static struct op fops_ext[] = {
722 { vfp_double_fcpy, 0 }, //0x00000000 - FEXT_FCPY 703 {vfp_double_fcpy, 0}, // 0x00000000 - FEXT_FCPY
723 { vfp_double_fabs, 0 }, //0x00000001 - FEXT_FABS 704 {vfp_double_fabs, 0}, // 0x00000001 - FEXT_FABS
724 { vfp_double_fneg, 0 }, //0x00000002 - FEXT_FNEG 705 {vfp_double_fneg, 0}, // 0x00000002 - FEXT_FNEG
725 { vfp_double_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT 706 {vfp_double_fsqrt, 0}, // 0x00000003 - FEXT_FSQRT
726 { nullptr, 0 }, 707 {nullptr, 0},
727 { nullptr, 0 }, 708 {nullptr, 0},
728 { nullptr, 0 }, 709 {nullptr, 0},
729 { nullptr, 0 }, 710 {nullptr, 0},
730 { vfp_double_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP 711 {vfp_double_fcmp, OP_SCALAR}, // 0x00000008 - FEXT_FCMP
731 { vfp_double_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE 712 {vfp_double_fcmpe, OP_SCALAR}, // 0x00000009 - FEXT_FCMPE
732 { vfp_double_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ 713 {vfp_double_fcmpz, OP_SCALAR}, // 0x0000000A - FEXT_FCMPZ
733 { vfp_double_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ 714 {vfp_double_fcmpez, OP_SCALAR}, // 0x0000000B - FEXT_FCMPEZ
734 { nullptr, 0 }, 715 {nullptr, 0},
735 { nullptr, 0 }, 716 {nullptr, 0},
736 { nullptr, 0 }, 717 {nullptr, 0},
737 { vfp_double_fcvts, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT 718 {vfp_double_fcvts, OP_SCALAR | OP_DD}, // 0x0000000F - FEXT_FCVT
738 { vfp_double_fuito, OP_SCALAR|OP_SM }, //0x00000010 - FEXT_FUITO 719 {vfp_double_fuito, OP_SCALAR | OP_SM}, // 0x00000010 - FEXT_FUITO
739 { vfp_double_fsito, OP_SCALAR|OP_SM }, //0x00000011 - FEXT_FSITO 720 {vfp_double_fsito, OP_SCALAR | OP_SM}, // 0x00000011 - FEXT_FSITO
740 { nullptr, 0 }, 721 {nullptr, 0},
741 { nullptr, 0 }, 722 {nullptr, 0},
742 { nullptr, 0 }, 723 {nullptr, 0},
743 { nullptr, 0 }, 724 {nullptr, 0},
744 { nullptr, 0 }, 725 {nullptr, 0},
745 { nullptr, 0 }, 726 {nullptr, 0},
746 { vfp_double_ftoui, OP_SCALAR|OP_SD }, //0x00000018 - FEXT_FTOUI 727 {vfp_double_ftoui, OP_SCALAR | OP_SD}, // 0x00000018 - FEXT_FTOUI
747 { vfp_double_ftouiz, OP_SCALAR|OP_SD }, //0x00000019 - FEXT_FTOUIZ 728 {vfp_double_ftouiz, OP_SCALAR | OP_SD}, // 0x00000019 - FEXT_FTOUIZ
748 { vfp_double_ftosi, OP_SCALAR|OP_SD }, //0x0000001A - FEXT_FTOSI 729 {vfp_double_ftosi, OP_SCALAR | OP_SD}, // 0x0000001A - FEXT_FTOSI
749 { vfp_double_ftosiz, OP_SCALAR|OP_SD }, //0x0000001B - FEXT_FTOSIZ 730 {vfp_double_ftosiz, OP_SCALAR | OP_SD}, // 0x0000001B - FEXT_FTOSIZ
750}; 731};
751 732
752static u32 733static u32 vfp_double_fadd_nonnumber(struct vfp_double* vdd, struct vfp_double* vdn,
753vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn, 734 struct vfp_double* vdm, u32 fpscr) {
754 struct vfp_double *vdm, u32 fpscr) 735 struct vfp_double* vdp;
755{
756 struct vfp_double *vdp;
757 u32 exceptions = 0; 736 u32 exceptions = 0;
758 int tn, tm; 737 int tn, tm;
759 738
@@ -791,13 +770,12 @@ vfp_double_fadd_nonnumber(struct vfp_double *vdd, struct vfp_double *vdn,
791 return exceptions; 770 return exceptions;
792} 771}
793 772
794u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_double *vdm, u32 fpscr) 773u32 vfp_double_add(struct vfp_double* vdd, struct vfp_double* vdn, struct vfp_double* vdm,
795{ 774 u32 fpscr) {
796 u32 exp_diff; 775 u32 exp_diff;
797 u64 m_sig; 776 u64 m_sig;
798 777
799 if (vdn->significand & (1ULL << 63) || 778 if (vdn->significand & (1ULL << 63) || vdm->significand & (1ULL << 63)) {
800 vdm->significand & (1ULL << 63)) {
801 LOG_INFO(Core_ARM11, "VFP: bad FP values in %s", __func__); 779 LOG_INFO(Core_ARM11, "VFP: bad FP values in %s", __func__);
802 vfp_double_dump("VDN", vdn); 780 vfp_double_dump("VDN", vdn);
803 vfp_double_dump("VDM", vdm); 781 vfp_double_dump("VDM", vdm);
@@ -841,8 +819,7 @@ u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_dou
841 vdd->sign = vfp_sign_negate(vdd->sign); 819 vdd->sign = vfp_sign_negate(vdd->sign);
842 m_sig = (~m_sig + 1); 820 m_sig = (~m_sig + 1);
843 } else if (m_sig == 0) { 821 } else if (m_sig == 0) {
844 vdd->sign = (fpscr & FPSCR_RMODE_MASK) == 822 vdd->sign = (fpscr & FPSCR_RMODE_MASK) == FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
845 FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
846 } 823 }
847 } else { 824 } else {
848 m_sig += vdn->significand; 825 m_sig += vdn->significand;
@@ -852,10 +829,8 @@ u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_dou
852 return 0; 829 return 0;
853} 830}
854 831
855u32 832u32 vfp_double_multiply(struct vfp_double* vdd, struct vfp_double* vdn, struct vfp_double* vdm,
856vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn, 833 u32 fpscr) {
857 struct vfp_double *vdm, u32 fpscr)
858{
859 vfp_double_dump("VDN", vdn); 834 vfp_double_dump("VDN", vdn);
860 vfp_double_dump("VDM", vdm); 835 vfp_double_dump("VDM", vdm);
861 836
@@ -908,12 +883,11 @@ vfp_double_multiply(struct vfp_double *vdd, struct vfp_double *vdn,
908 return 0; 883 return 0;
909} 884}
910 885
911#define NEG_MULTIPLY (1 << 0) 886#define NEG_MULTIPLY (1 << 0)
912#define NEG_SUBTRACT (1 << 1) 887#define NEG_SUBTRACT (1 << 1)
913 888
914static u32 889static u32 vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr,
915vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr, u32 negate, const char *func) 890 u32 negate, const char* func) {
916{
917 struct vfp_double vdd, vdp, vdn, vdm; 891 struct vfp_double vdd, vdp, vdn, vdm;
918 u32 exceptions = 0; 892 u32 exceptions = 0;
919 893
@@ -949,8 +923,7 @@ vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 f
949/* 923/*
950 * sd = sd + (sn * sm) 924 * sd = sd + (sn * sm)
951 */ 925 */
952static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 926static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
953{
954 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 927 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
955 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, 0, "fmac"); 928 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, 0, "fmac");
956} 929}
@@ -958,8 +931,7 @@ static u32 vfp_double_fmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
958/* 931/*
959 * sd = sd - (sn * sm) 932 * sd = sd - (sn * sm)
960 */ 933 */
961static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 934static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
962{
963 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 935 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
964 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac"); 936 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_MULTIPLY, "fnmac");
965} 937}
@@ -967,8 +939,7 @@ static u32 vfp_double_fnmac(ARMul_State* state, int dd, int dn, int dm, u32 fpsc
967/* 939/*
968 * sd = -sd + (sn * sm) 940 * sd = -sd + (sn * sm)
969 */ 941 */
970static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 942static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
971{
972 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 943 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
973 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc"); 944 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT, "fmsc");
974} 945}
@@ -976,17 +947,16 @@ static u32 vfp_double_fmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
976/* 947/*
977 * sd = -sd - (sn * sm) 948 * sd = -sd - (sn * sm)
978 */ 949 */
979static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 950static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
980{
981 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 951 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
982 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc"); 952 return vfp_double_multiply_accumulate(state, dd, dn, dm, fpscr, NEG_SUBTRACT | NEG_MULTIPLY,
953 "fnmsc");
983} 954}
984 955
985/* 956/*
986 * sd = sn * sm 957 * sd = sn * sm
987 */ 958 */
988static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 959static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
989{
990 struct vfp_double vdd, vdn, vdm; 960 struct vfp_double vdd, vdn, vdm;
991 u32 exceptions = 0; 961 u32 exceptions = 0;
992 962
@@ -1008,8 +978,7 @@ static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
1008/* 978/*
1009 * sd = -(sn * sm) 979 * sd = -(sn * sm)
1010 */ 980 */
1011static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 981static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
1012{
1013 struct vfp_double vdd, vdn, vdm; 982 struct vfp_double vdd, vdn, vdm;
1014 u32 exceptions = 0; 983 u32 exceptions = 0;
1015 984
@@ -1032,8 +1001,7 @@ static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpsc
1032/* 1001/*
1033 * sd = sn + sm 1002 * sd = sn + sm
1034 */ 1003 */
1035static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1004static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
1036{
1037 struct vfp_double vdd, vdn, vdm; 1005 struct vfp_double vdd, vdn, vdm;
1038 u32 exceptions = 0; 1006 u32 exceptions = 0;
1039 1007
@@ -1055,8 +1023,7 @@ static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
1055/* 1023/*
1056 * sd = sn - sm 1024 * sd = sn - sm
1057 */ 1025 */
1058static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1026static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
1059{
1060 struct vfp_double vdd, vdn, vdm; 1027 struct vfp_double vdd, vdn, vdm;
1061 u32 exceptions = 0; 1028 u32 exceptions = 0;
1062 1029
@@ -1083,8 +1050,7 @@ static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
1083/* 1050/*
1084 * sd = sn / sm 1051 * sd = sn / sm
1085 */ 1052 */
1086static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) 1053static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) {
1087{
1088 struct vfp_double vdd, vdn, vdm; 1054 struct vfp_double vdd, vdn, vdm;
1089 u32 exceptions = 0; 1055 u32 exceptions = 0;
1090 int tm, tn; 1056 int tm, tn;
@@ -1114,7 +1080,7 @@ static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr
1114 * If n and m are infinity, the result is invalid 1080 * If n and m are infinity, the result is invalid
1115 * If n and m are zero, the result is invalid 1081 * If n and m are zero, the result is invalid
1116 */ 1082 */
1117 if (tm & tn & (VFP_INFINITY|VFP_ZERO)) 1083 if (tm & tn & (VFP_INFINITY | VFP_ZERO))
1118 goto invalid; 1084 goto invalid;
1119 1085
1120 /* 1086 /*
@@ -1193,29 +1159,22 @@ invalid:
1193} 1159}
1194 1160
1195static struct op fops[] = { 1161static struct op fops[] = {
1196 { vfp_double_fmac, 0 }, 1162 {vfp_double_fmac, 0}, {vfp_double_fmsc, 0}, {vfp_double_fmul, 0},
1197 { vfp_double_fmsc, 0 }, 1163 {vfp_double_fadd, 0}, {vfp_double_fnmac, 0}, {vfp_double_fnmsc, 0},
1198 { vfp_double_fmul, 0 }, 1164 {vfp_double_fnmul, 0}, {vfp_double_fsub, 0}, {vfp_double_fdiv, 0},
1199 { vfp_double_fadd, 0 },
1200 { vfp_double_fnmac, 0 },
1201 { vfp_double_fnmsc, 0 },
1202 { vfp_double_fnmul, 0 },
1203 { vfp_double_fsub, 0 },
1204 { vfp_double_fdiv, 0 },
1205}; 1165};
1206 1166
1207#define FREG_BANK(x) ((x) & 0x0c) 1167#define FREG_BANK(x) ((x)&0x0c)
1208#define FREG_IDX(x) ((x) & 3) 1168#define FREG_IDX(x) ((x)&3)
1209 1169
1210u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr) 1170u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr) {
1211{
1212 u32 op = inst & FOP_MASK; 1171 u32 op = inst & FOP_MASK;
1213 u32 exceptions = 0; 1172 u32 exceptions = 0;
1214 unsigned int dest; 1173 unsigned int dest;
1215 unsigned int dn = vfp_get_dn(inst); 1174 unsigned int dn = vfp_get_dn(inst);
1216 unsigned int dm; 1175 unsigned int dm;
1217 unsigned int vecitr, veclen, vecstride; 1176 unsigned int vecitr, veclen, vecstride;
1218 struct op *fop; 1177 struct op* fop;
1219 1178
1220 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); 1179 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__);
1221 vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK)); 1180 vecstride = (1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK));
@@ -1249,7 +1208,7 @@ u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1249 veclen = fpscr & FPSCR_LENGTH_MASK; 1208 veclen = fpscr & FPSCR_LENGTH_MASK;
1250 1209
1251 LOG_TRACE(Core_ARM11, "VFP: vecstride=%u veclen=%u", vecstride, 1210 LOG_TRACE(Core_ARM11, "VFP: vecstride=%u veclen=%u", vecstride,
1252 (veclen >> FPSCR_LENGTH_BIT) + 1); 1211 (veclen >> FPSCR_LENGTH_BIT) + 1);
1253 1212
1254 if (!fop->fn) { 1213 if (!fop->fn) {
1255 printf("VFP: could not find double op %d\n", FEXT_TO_IDX(inst)); 1214 printf("VFP: could not find double op %d\n", FEXT_TO_IDX(inst));
@@ -1262,17 +1221,14 @@ u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1262 1221
1263 type = (fop->flags & OP_SD) ? 's' : 'd'; 1222 type = (fop->flags & OP_SD) ? 's' : 'd';
1264 if (op == FOP_EXT) 1223 if (op == FOP_EXT)
1265 LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = op[%u] (d%u)", 1224 LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = op[%u] (d%u)", vecitr >> FPSCR_LENGTH_BIT,
1266 vecitr >> FPSCR_LENGTH_BIT, 1225 type, dest, dn, dm);
1267 type, dest, dn, dm);
1268 else 1226 else
1269 LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)", 1227 LOG_TRACE(Core_ARM11, "VFP: itr%d (%c%u) = (d%u) op[%u] (d%u)",
1270 vecitr >> FPSCR_LENGTH_BIT, 1228 vecitr >> FPSCR_LENGTH_BIT, type, dest, dn, FOP_TO_IDX(op), dm);
1271 type, dest, dn, FOP_TO_IDX(op), dm);
1272 1229
1273 except = fop->fn(state, dest, dn, dm, fpscr); 1230 except = fop->fn(state, dest, dn, dm, fpscr);
1274 LOG_TRACE(Core_ARM11, "VFP: itr%d: exceptions=%08x", 1231 LOG_TRACE(Core_ARM11, "VFP: itr%d: exceptions=%08x", vecitr >> FPSCR_LENGTH_BIT, except);
1275 vecitr >> FPSCR_LENGTH_BIT, except);
1276 1232
1277 exceptions |= except; 1233 exceptions |= except;
1278 1234
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index 1a98d0114..a66dc1016 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -19,14 +19,13 @@ struct vmla_inst {
19}; 19};
20#endif 20#endif
21#ifdef VFP_INTERPRETER_TRANS 21#ifdef VFP_INTERPRETER_TRANS
22static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index) 22static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index) {
23{ 23 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmla_inst));
24 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmla_inst)); 24 vmla_inst* inst_cream = (vmla_inst*)inst_base->component;
25 vmla_inst *inst_cream = (vmla_inst *)inst_base->component;
26 25
27 inst_base->cond = BITS(inst, 28, 31); 26 inst_base->cond = BITS(inst, 28, 31);
28 inst_base->idx = index; 27 inst_base->idx = index;
29 inst_base->br = TransExtData::NON_BRANCH; 28 inst_base->br = TransExtData::NON_BRANCH;
30 29
31 inst_cream->dp_operation = BIT(inst, 8); 30 inst_cream->dp_operation = BIT(inst, 8);
32 inst_cream->instr = inst; 31 inst_cream->instr = inst;
@@ -35,12 +34,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index)
35} 34}
36#endif 35#endif
37#ifdef VFP_INTERPRETER_IMPL 36#ifdef VFP_INTERPRETER_IMPL
38VMLA_INST: 37VMLA_INST : {
39{
40 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 38 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
41 CHECK_VFP_ENABLED; 39 CHECK_VFP_ENABLED;
42 40
43 vmla_inst *inst_cream = (vmla_inst *)inst_base->component; 41 vmla_inst* inst_cream = (vmla_inst*)inst_base->component;
44 42
45 int ret; 43 int ret;
46 44
@@ -68,14 +66,13 @@ struct vmls_inst {
68}; 66};
69#endif 67#endif
70#ifdef VFP_INTERPRETER_TRANS 68#ifdef VFP_INTERPRETER_TRANS
71static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index) 69static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index) {
72{ 70 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmls_inst));
73 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmls_inst)); 71 vmls_inst* inst_cream = (vmls_inst*)inst_base->component;
74 vmls_inst *inst_cream = (vmls_inst *)inst_base->component;
75 72
76 inst_base->cond = BITS(inst, 28, 31); 73 inst_base->cond = BITS(inst, 28, 31);
77 inst_base->idx = index; 74 inst_base->idx = index;
78 inst_base->br = TransExtData::NON_BRANCH; 75 inst_base->br = TransExtData::NON_BRANCH;
79 76
80 inst_cream->dp_operation = BIT(inst, 8); 77 inst_cream->dp_operation = BIT(inst, 8);
81 inst_cream->instr = inst; 78 inst_cream->instr = inst;
@@ -84,12 +81,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index)
84} 81}
85#endif 82#endif
86#ifdef VFP_INTERPRETER_IMPL 83#ifdef VFP_INTERPRETER_IMPL
87VMLS_INST: 84VMLS_INST : {
88{
89 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 85 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
90 CHECK_VFP_ENABLED; 86 CHECK_VFP_ENABLED;
91 87
92 vmls_inst *inst_cream = (vmls_inst *)inst_base->component; 88 vmls_inst* inst_cream = (vmls_inst*)inst_base->component;
93 89
94 int ret; 90 int ret;
95 91
@@ -117,14 +113,13 @@ struct vnmla_inst {
117}; 113};
118#endif 114#endif
119#ifdef VFP_INTERPRETER_TRANS 115#ifdef VFP_INTERPRETER_TRANS
120static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index) 116static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index) {
121{ 117 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vnmla_inst));
122 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmla_inst)); 118 vnmla_inst* inst_cream = (vnmla_inst*)inst_base->component;
123 vnmla_inst *inst_cream = (vnmla_inst *)inst_base->component;
124 119
125 inst_base->cond = BITS(inst, 28, 31); 120 inst_base->cond = BITS(inst, 28, 31);
126 inst_base->idx = index; 121 inst_base->idx = index;
127 inst_base->br = TransExtData::NON_BRANCH; 122 inst_base->br = TransExtData::NON_BRANCH;
128 123
129 inst_cream->dp_operation = BIT(inst, 8); 124 inst_cream->dp_operation = BIT(inst, 8);
130 inst_cream->instr = inst; 125 inst_cream->instr = inst;
@@ -133,12 +128,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index)
133} 128}
134#endif 129#endif
135#ifdef VFP_INTERPRETER_IMPL 130#ifdef VFP_INTERPRETER_IMPL
136VNMLA_INST: 131VNMLA_INST : {
137{
138 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 132 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
139 CHECK_VFP_ENABLED; 133 CHECK_VFP_ENABLED;
140 134
141 vnmla_inst *inst_cream = (vnmla_inst *)inst_base->component; 135 vnmla_inst* inst_cream = (vnmla_inst*)inst_base->component;
142 136
143 int ret; 137 int ret;
144 138
@@ -167,14 +161,13 @@ struct vnmls_inst {
167}; 161};
168#endif 162#endif
169#ifdef VFP_INTERPRETER_TRANS 163#ifdef VFP_INTERPRETER_TRANS
170static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index) 164static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index) {
171{ 165 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vnmls_inst));
172 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmls_inst)); 166 vnmls_inst* inst_cream = (vnmls_inst*)inst_base->component;
173 vnmls_inst *inst_cream = (vnmls_inst *)inst_base->component;
174 167
175 inst_base->cond = BITS(inst, 28, 31); 168 inst_base->cond = BITS(inst, 28, 31);
176 inst_base->idx = index; 169 inst_base->idx = index;
177 inst_base->br = TransExtData::NON_BRANCH; 170 inst_base->br = TransExtData::NON_BRANCH;
178 171
179 inst_cream->dp_operation = BIT(inst, 8); 172 inst_cream->dp_operation = BIT(inst, 8);
180 inst_cream->instr = inst; 173 inst_cream->instr = inst;
@@ -183,12 +176,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index)
183} 176}
184#endif 177#endif
185#ifdef VFP_INTERPRETER_IMPL 178#ifdef VFP_INTERPRETER_IMPL
186VNMLS_INST: 179VNMLS_INST : {
187{
188 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 180 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
189 CHECK_VFP_ENABLED; 181 CHECK_VFP_ENABLED;
190 182
191 vnmls_inst *inst_cream = (vnmls_inst *)inst_base->component; 183 vnmls_inst* inst_cream = (vnmls_inst*)inst_base->component;
192 184
193 int ret; 185 int ret;
194 186
@@ -216,14 +208,13 @@ struct vnmul_inst {
216}; 208};
217#endif 209#endif
218#ifdef VFP_INTERPRETER_TRANS 210#ifdef VFP_INTERPRETER_TRANS
219static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index) 211static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index) {
220{ 212 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vnmul_inst));
221 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmul_inst)); 213 vnmul_inst* inst_cream = (vnmul_inst*)inst_base->component;
222 vnmul_inst *inst_cream = (vnmul_inst *)inst_base->component;
223 214
224 inst_base->cond = BITS(inst, 28, 31); 215 inst_base->cond = BITS(inst, 28, 31);
225 inst_base->idx = index; 216 inst_base->idx = index;
226 inst_base->br = TransExtData::NON_BRANCH; 217 inst_base->br = TransExtData::NON_BRANCH;
227 218
228 inst_cream->dp_operation = BIT(inst, 8); 219 inst_cream->dp_operation = BIT(inst, 8);
229 inst_cream->instr = inst; 220 inst_cream->instr = inst;
@@ -232,12 +223,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index)
232} 223}
233#endif 224#endif
234#ifdef VFP_INTERPRETER_IMPL 225#ifdef VFP_INTERPRETER_IMPL
235VNMUL_INST: 226VNMUL_INST : {
236{
237 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 227 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
238 CHECK_VFP_ENABLED; 228 CHECK_VFP_ENABLED;
239 229
240 vnmul_inst *inst_cream = (vnmul_inst *)inst_base->component; 230 vnmul_inst* inst_cream = (vnmul_inst*)inst_base->component;
241 231
242 int ret; 232 int ret;
243 233
@@ -265,14 +255,13 @@ struct vmul_inst {
265}; 255};
266#endif 256#endif
267#ifdef VFP_INTERPRETER_TRANS 257#ifdef VFP_INTERPRETER_TRANS
268static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index) 258static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index) {
269{ 259 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmul_inst));
270 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmul_inst)); 260 vmul_inst* inst_cream = (vmul_inst*)inst_base->component;
271 vmul_inst *inst_cream = (vmul_inst *)inst_base->component;
272 261
273 inst_base->cond = BITS(inst, 28, 31); 262 inst_base->cond = BITS(inst, 28, 31);
274 inst_base->idx = index; 263 inst_base->idx = index;
275 inst_base->br = TransExtData::NON_BRANCH; 264 inst_base->br = TransExtData::NON_BRANCH;
276 265
277 inst_cream->dp_operation = BIT(inst, 8); 266 inst_cream->dp_operation = BIT(inst, 8);
278 inst_cream->instr = inst; 267 inst_cream->instr = inst;
@@ -281,12 +270,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index)
281} 270}
282#endif 271#endif
283#ifdef VFP_INTERPRETER_IMPL 272#ifdef VFP_INTERPRETER_IMPL
284VMUL_INST: 273VMUL_INST : {
285{
286 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 274 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
287 CHECK_VFP_ENABLED; 275 CHECK_VFP_ENABLED;
288 276
289 vmul_inst *inst_cream = (vmul_inst *)inst_base->component; 277 vmul_inst* inst_cream = (vmul_inst*)inst_base->component;
290 278
291 int ret; 279 int ret;
292 280
@@ -314,14 +302,13 @@ struct vadd_inst {
314}; 302};
315#endif 303#endif
316#ifdef VFP_INTERPRETER_TRANS 304#ifdef VFP_INTERPRETER_TRANS
317static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index) 305static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index) {
318{ 306 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vadd_inst));
319 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vadd_inst)); 307 vadd_inst* inst_cream = (vadd_inst*)inst_base->component;
320 vadd_inst *inst_cream = (vadd_inst *)inst_base->component;
321 308
322 inst_base->cond = BITS(inst, 28, 31); 309 inst_base->cond = BITS(inst, 28, 31);
323 inst_base->idx = index; 310 inst_base->idx = index;
324 inst_base->br = TransExtData::NON_BRANCH; 311 inst_base->br = TransExtData::NON_BRANCH;
325 312
326 inst_cream->dp_operation = BIT(inst, 8); 313 inst_cream->dp_operation = BIT(inst, 8);
327 inst_cream->instr = inst; 314 inst_cream->instr = inst;
@@ -330,12 +317,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index)
330} 317}
331#endif 318#endif
332#ifdef VFP_INTERPRETER_IMPL 319#ifdef VFP_INTERPRETER_IMPL
333VADD_INST: 320VADD_INST : {
334{
335 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 321 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
336 CHECK_VFP_ENABLED; 322 CHECK_VFP_ENABLED;
337 323
338 vadd_inst *inst_cream = (vadd_inst *)inst_base->component; 324 vadd_inst* inst_cream = (vadd_inst*)inst_base->component;
339 325
340 int ret; 326 int ret;
341 327
@@ -363,14 +349,13 @@ struct vsub_inst {
363}; 349};
364#endif 350#endif
365#ifdef VFP_INTERPRETER_TRANS 351#ifdef VFP_INTERPRETER_TRANS
366static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index) 352static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index) {
367{ 353 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vsub_inst));
368 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vsub_inst)); 354 vsub_inst* inst_cream = (vsub_inst*)inst_base->component;
369 vsub_inst *inst_cream = (vsub_inst *)inst_base->component;
370 355
371 inst_base->cond = BITS(inst, 28, 31); 356 inst_base->cond = BITS(inst, 28, 31);
372 inst_base->idx = index; 357 inst_base->idx = index;
373 inst_base->br = TransExtData::NON_BRANCH; 358 inst_base->br = TransExtData::NON_BRANCH;
374 359
375 inst_cream->dp_operation = BIT(inst, 8); 360 inst_cream->dp_operation = BIT(inst, 8);
376 inst_cream->instr = inst; 361 inst_cream->instr = inst;
@@ -379,12 +364,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index)
379} 364}
380#endif 365#endif
381#ifdef VFP_INTERPRETER_IMPL 366#ifdef VFP_INTERPRETER_IMPL
382VSUB_INST: 367VSUB_INST : {
383{
384 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 368 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
385 CHECK_VFP_ENABLED; 369 CHECK_VFP_ENABLED;
386 370
387 vsub_inst *inst_cream = (vsub_inst *)inst_base->component; 371 vsub_inst* inst_cream = (vsub_inst*)inst_base->component;
388 372
389 int ret; 373 int ret;
390 374
@@ -412,14 +396,13 @@ struct vdiv_inst {
412}; 396};
413#endif 397#endif
414#ifdef VFP_INTERPRETER_TRANS 398#ifdef VFP_INTERPRETER_TRANS
415static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index) 399static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index) {
416{ 400 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vdiv_inst));
417 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vdiv_inst)); 401 vdiv_inst* inst_cream = (vdiv_inst*)inst_base->component;
418 vdiv_inst *inst_cream = (vdiv_inst *)inst_base->component;
419 402
420 inst_base->cond = BITS(inst, 28, 31); 403 inst_base->cond = BITS(inst, 28, 31);
421 inst_base->idx = index; 404 inst_base->idx = index;
422 inst_base->br = TransExtData::NON_BRANCH; 405 inst_base->br = TransExtData::NON_BRANCH;
423 406
424 inst_cream->dp_operation = BIT(inst, 8); 407 inst_cream->dp_operation = BIT(inst, 8);
425 inst_cream->instr = inst; 408 inst_cream->instr = inst;
@@ -428,12 +411,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index)
428} 411}
429#endif 412#endif
430#ifdef VFP_INTERPRETER_IMPL 413#ifdef VFP_INTERPRETER_IMPL
431VDIV_INST: 414VDIV_INST : {
432{
433 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 415 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
434 CHECK_VFP_ENABLED; 416 CHECK_VFP_ENABLED;
435 417
436 vdiv_inst *inst_cream = (vdiv_inst *)inst_base->component; 418 vdiv_inst* inst_cream = (vdiv_inst*)inst_base->component;
437 419
438 int ret; 420 int ret;
439 421
@@ -463,32 +445,33 @@ struct vmovi_inst {
463}; 445};
464#endif 446#endif
465#ifdef VFP_INTERPRETER_TRANS 447#ifdef VFP_INTERPRETER_TRANS
466static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index) 448static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index) {
467{ 449 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovi_inst));
468 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovi_inst)); 450 vmovi_inst* inst_cream = (vmovi_inst*)inst_base->component;
469 vmovi_inst *inst_cream = (vmovi_inst *)inst_base->component;
470 451
471 inst_base->cond = BITS(inst, 28, 31); 452 inst_base->cond = BITS(inst, 28, 31);
472 inst_base->idx = index; 453 inst_base->idx = index;
473 inst_base->br = TransExtData::NON_BRANCH; 454 inst_base->br = TransExtData::NON_BRANCH;
474 455
475 inst_cream->single = BIT(inst, 8) == 0; 456 inst_cream->single = BIT(inst, 8) == 0;
476 inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4); 457 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
458 : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
477 unsigned int imm8 = BITS(inst, 16, 19) << 4 | BITS(inst, 0, 3); 459 unsigned int imm8 = BITS(inst, 16, 19) << 4 | BITS(inst, 0, 3);
478 if (inst_cream->single) 460 if (inst_cream->single)
479 inst_cream->imm = BIT(imm8, 7)<<31 | (BIT(imm8, 6)==0)<<30 | (BIT(imm8, 6) ? 0x1f : 0)<<25 | BITS(imm8, 0, 5)<<19; 461 inst_cream->imm = BIT(imm8, 7) << 31 | (BIT(imm8, 6) == 0) << 30 |
462 (BIT(imm8, 6) ? 0x1f : 0) << 25 | BITS(imm8, 0, 5) << 19;
480 else 463 else
481 inst_cream->imm = BIT(imm8, 7)<<31 | (BIT(imm8, 6)==0)<<30 | (BIT(imm8, 6) ? 0xff : 0)<<22 | BITS(imm8, 0, 5)<<16; 464 inst_cream->imm = BIT(imm8, 7) << 31 | (BIT(imm8, 6) == 0) << 30 |
465 (BIT(imm8, 6) ? 0xff : 0) << 22 | BITS(imm8, 0, 5) << 16;
482 return inst_base; 466 return inst_base;
483} 467}
484#endif 468#endif
485#ifdef VFP_INTERPRETER_IMPL 469#ifdef VFP_INTERPRETER_IMPL
486VMOVI_INST: 470VMOVI_INST : {
487{
488 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 471 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
489 CHECK_VFP_ENABLED; 472 CHECK_VFP_ENABLED;
490 473
491 vmovi_inst *inst_cream = (vmovi_inst *)inst_base->component; 474 vmovi_inst* inst_cream = (vmovi_inst*)inst_base->component;
492 475
493 VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm); 476 VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm);
494 } 477 }
@@ -511,28 +494,28 @@ struct vmovr_inst {
511}; 494};
512#endif 495#endif
513#ifdef VFP_INTERPRETER_TRANS 496#ifdef VFP_INTERPRETER_TRANS
514static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index) 497static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index) {
515{ 498 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovr_inst));
516 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovr_inst)); 499 vmovr_inst* inst_cream = (vmovr_inst*)inst_base->component;
517 vmovr_inst *inst_cream = (vmovr_inst *)inst_base->component;
518 500
519 inst_base->cond = BITS(inst, 28, 31); 501 inst_base->cond = BITS(inst, 28, 31);
520 inst_base->idx = index; 502 inst_base->idx = index;
521 inst_base->br = TransExtData::NON_BRANCH; 503 inst_base->br = TransExtData::NON_BRANCH;
522 504
523 inst_cream->single = BIT(inst, 8) == 0; 505 inst_cream->single = BIT(inst, 8) == 0;
524 inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4); 506 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
525 inst_cream->m = (inst_cream->single ? BITS(inst, 0, 3)<<1 | BIT(inst, 5) : BITS(inst, 0, 3) | BIT(inst, 5)<<4); 507 : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
508 inst_cream->m = (inst_cream->single ? BITS(inst, 0, 3) << 1 | BIT(inst, 5)
509 : BITS(inst, 0, 3) | BIT(inst, 5) << 4);
526 return inst_base; 510 return inst_base;
527} 511}
528#endif 512#endif
529#ifdef VFP_INTERPRETER_IMPL 513#ifdef VFP_INTERPRETER_IMPL
530VMOVR_INST: 514VMOVR_INST : {
531{
532 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 515 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
533 CHECK_VFP_ENABLED; 516 CHECK_VFP_ENABLED;
534 517
535 vmovr_inst *inst_cream = (vmovr_inst *)inst_base->component; 518 vmovr_inst* inst_cream = (vmovr_inst*)inst_base->component;
536 519
537 VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m); 520 VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m);
538 } 521 }
@@ -553,14 +536,13 @@ typedef struct _vabs_inst {
553} vabs_inst; 536} vabs_inst;
554#endif 537#endif
555#ifdef VFP_INTERPRETER_TRANS 538#ifdef VFP_INTERPRETER_TRANS
556static ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index) 539static ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index) {
557{ 540 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vabs_inst));
558 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vabs_inst)); 541 vabs_inst* inst_cream = (vabs_inst*)inst_base->component;
559 vabs_inst *inst_cream = (vabs_inst *)inst_base->component;
560 542
561 inst_base->cond = BITS(inst, 28, 31); 543 inst_base->cond = BITS(inst, 28, 31);
562 inst_base->idx = index; 544 inst_base->idx = index;
563 inst_base->br = TransExtData::NON_BRANCH; 545 inst_base->br = TransExtData::NON_BRANCH;
564 546
565 inst_cream->dp_operation = BIT(inst, 8); 547 inst_cream->dp_operation = BIT(inst, 8);
566 inst_cream->instr = inst; 548 inst_cream->instr = inst;
@@ -569,12 +551,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index)
569} 551}
570#endif 552#endif
571#ifdef VFP_INTERPRETER_IMPL 553#ifdef VFP_INTERPRETER_IMPL
572VABS_INST: 554VABS_INST : {
573{
574 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 555 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
575 CHECK_VFP_ENABLED; 556 CHECK_VFP_ENABLED;
576 557
577 vabs_inst *inst_cream = (vabs_inst *)inst_base->component; 558 vabs_inst* inst_cream = (vabs_inst*)inst_base->component;
578 559
579 int ret; 560 int ret;
580 561
@@ -603,14 +584,13 @@ struct vneg_inst {
603}; 584};
604#endif 585#endif
605#ifdef VFP_INTERPRETER_TRANS 586#ifdef VFP_INTERPRETER_TRANS
606static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index) 587static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index) {
607{ 588 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vneg_inst));
608 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vneg_inst)); 589 vneg_inst* inst_cream = (vneg_inst*)inst_base->component;
609 vneg_inst *inst_cream = (vneg_inst *)inst_base->component;
610 590
611 inst_base->cond = BITS(inst, 28, 31); 591 inst_base->cond = BITS(inst, 28, 31);
612 inst_base->idx = index; 592 inst_base->idx = index;
613 inst_base->br = TransExtData::NON_BRANCH; 593 inst_base->br = TransExtData::NON_BRANCH;
614 594
615 inst_cream->dp_operation = BIT(inst, 8); 595 inst_cream->dp_operation = BIT(inst, 8);
616 inst_cream->instr = inst; 596 inst_cream->instr = inst;
@@ -619,12 +599,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index)
619} 599}
620#endif 600#endif
621#ifdef VFP_INTERPRETER_IMPL 601#ifdef VFP_INTERPRETER_IMPL
622VNEG_INST: 602VNEG_INST : {
623{
624 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 603 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
625 CHECK_VFP_ENABLED; 604 CHECK_VFP_ENABLED;
626 605
627 vneg_inst *inst_cream = (vneg_inst *)inst_base->component; 606 vneg_inst* inst_cream = (vneg_inst*)inst_base->component;
628 607
629 int ret; 608 int ret;
630 609
@@ -652,14 +631,13 @@ struct vsqrt_inst {
652}; 631};
653#endif 632#endif
654#ifdef VFP_INTERPRETER_TRANS 633#ifdef VFP_INTERPRETER_TRANS
655static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index) 634static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index) {
656{ 635 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vsqrt_inst));
657 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vsqrt_inst)); 636 vsqrt_inst* inst_cream = (vsqrt_inst*)inst_base->component;
658 vsqrt_inst *inst_cream = (vsqrt_inst *)inst_base->component;
659 637
660 inst_base->cond = BITS(inst, 28, 31); 638 inst_base->cond = BITS(inst, 28, 31);
661 inst_base->idx = index; 639 inst_base->idx = index;
662 inst_base->br = TransExtData::NON_BRANCH; 640 inst_base->br = TransExtData::NON_BRANCH;
663 641
664 inst_cream->dp_operation = BIT(inst, 8); 642 inst_cream->dp_operation = BIT(inst, 8);
665 inst_cream->instr = inst; 643 inst_cream->instr = inst;
@@ -668,12 +646,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index)
668} 646}
669#endif 647#endif
670#ifdef VFP_INTERPRETER_IMPL 648#ifdef VFP_INTERPRETER_IMPL
671VSQRT_INST: 649VSQRT_INST : {
672{
673 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 650 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
674 CHECK_VFP_ENABLED; 651 CHECK_VFP_ENABLED;
675 652
676 vsqrt_inst *inst_cream = (vsqrt_inst *)inst_base->component; 653 vsqrt_inst* inst_cream = (vsqrt_inst*)inst_base->component;
677 654
678 int ret; 655 int ret;
679 656
@@ -701,14 +678,13 @@ struct vcmp_inst {
701}; 678};
702#endif 679#endif
703#ifdef VFP_INTERPRETER_TRANS 680#ifdef VFP_INTERPRETER_TRANS
704static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index) 681static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index) {
705{ 682 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp_inst));
706 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp_inst)); 683 vcmp_inst* inst_cream = (vcmp_inst*)inst_base->component;
707 vcmp_inst *inst_cream = (vcmp_inst *)inst_base->component;
708 684
709 inst_base->cond = BITS(inst, 28, 31); 685 inst_base->cond = BITS(inst, 28, 31);
710 inst_base->idx = index; 686 inst_base->idx = index;
711 inst_base->br = TransExtData::NON_BRANCH; 687 inst_base->br = TransExtData::NON_BRANCH;
712 688
713 inst_cream->dp_operation = BIT(inst, 8); 689 inst_cream->dp_operation = BIT(inst, 8);
714 inst_cream->instr = inst; 690 inst_cream->instr = inst;
@@ -717,12 +693,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index)
717} 693}
718#endif 694#endif
719#ifdef VFP_INTERPRETER_IMPL 695#ifdef VFP_INTERPRETER_IMPL
720VCMP_INST: 696VCMP_INST : {
721{
722 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 697 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
723 CHECK_VFP_ENABLED; 698 CHECK_VFP_ENABLED;
724 699
725 vcmp_inst *inst_cream = (vcmp_inst *)inst_base->component; 700 vcmp_inst* inst_cream = (vcmp_inst*)inst_base->component;
726 701
727 int ret; 702 int ret;
728 703
@@ -750,14 +725,13 @@ struct vcmp2_inst {
750}; 725};
751#endif 726#endif
752#ifdef VFP_INTERPRETER_TRANS 727#ifdef VFP_INTERPRETER_TRANS
753static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index) 728static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index) {
754{ 729 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp2_inst));
755 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp2_inst)); 730 vcmp2_inst* inst_cream = (vcmp2_inst*)inst_base->component;
756 vcmp2_inst *inst_cream = (vcmp2_inst *)inst_base->component;
757 731
758 inst_base->cond = BITS(inst, 28, 31); 732 inst_base->cond = BITS(inst, 28, 31);
759 inst_base->idx = index; 733 inst_base->idx = index;
760 inst_base->br = TransExtData::NON_BRANCH; 734 inst_base->br = TransExtData::NON_BRANCH;
761 735
762 inst_cream->dp_operation = BIT(inst, 8); 736 inst_cream->dp_operation = BIT(inst, 8);
763 inst_cream->instr = inst; 737 inst_cream->instr = inst;
@@ -766,12 +740,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index)
766} 740}
767#endif 741#endif
768#ifdef VFP_INTERPRETER_IMPL 742#ifdef VFP_INTERPRETER_IMPL
769VCMP2_INST: 743VCMP2_INST : {
770{
771 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 744 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
772 CHECK_VFP_ENABLED; 745 CHECK_VFP_ENABLED;
773 746
774 vcmp2_inst *inst_cream = (vcmp2_inst *)inst_base->component; 747 vcmp2_inst* inst_cream = (vcmp2_inst*)inst_base->component;
775 748
776 int ret; 749 int ret;
777 750
@@ -799,14 +772,13 @@ struct vcvtbds_inst {
799}; 772};
800#endif 773#endif
801#ifdef VFP_INTERPRETER_TRANS 774#ifdef VFP_INTERPRETER_TRANS
802static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index) 775static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index) {
803{ 776 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbds_inst));
804 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbds_inst)); 777 vcvtbds_inst* inst_cream = (vcvtbds_inst*)inst_base->component;
805 vcvtbds_inst *inst_cream = (vcvtbds_inst *)inst_base->component;
806 778
807 inst_base->cond = BITS(inst, 28, 31); 779 inst_base->cond = BITS(inst, 28, 31);
808 inst_base->idx = index; 780 inst_base->idx = index;
809 inst_base->br = TransExtData::NON_BRANCH; 781 inst_base->br = TransExtData::NON_BRANCH;
810 782
811 inst_cream->dp_operation = BIT(inst, 8); 783 inst_cream->dp_operation = BIT(inst, 8);
812 inst_cream->instr = inst; 784 inst_cream->instr = inst;
@@ -815,12 +787,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index)
815} 787}
816#endif 788#endif
817#ifdef VFP_INTERPRETER_IMPL 789#ifdef VFP_INTERPRETER_IMPL
818VCVTBDS_INST: 790VCVTBDS_INST : {
819{
820 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 791 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
821 CHECK_VFP_ENABLED; 792 CHECK_VFP_ENABLED;
822 793
823 vcvtbds_inst *inst_cream = (vcvtbds_inst *)inst_base->component; 794 vcvtbds_inst* inst_cream = (vcvtbds_inst*)inst_base->component;
824 795
825 int ret; 796 int ret;
826 797
@@ -848,16 +819,15 @@ struct vcvtbff_inst {
848}; 819};
849#endif 820#endif
850#ifdef VFP_INTERPRETER_TRANS 821#ifdef VFP_INTERPRETER_TRANS
851static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index) 822static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index) {
852{
853 VFP_DEBUG_UNTESTED(VCVTBFF); 823 VFP_DEBUG_UNTESTED(VCVTBFF);
854 824
855 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbff_inst)); 825 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbff_inst));
856 vcvtbff_inst *inst_cream = (vcvtbff_inst *)inst_base->component; 826 vcvtbff_inst* inst_cream = (vcvtbff_inst*)inst_base->component;
857 827
858 inst_base->cond = BITS(inst, 28, 31); 828 inst_base->cond = BITS(inst, 28, 31);
859 inst_base->idx = index; 829 inst_base->idx = index;
860 inst_base->br = TransExtData::NON_BRANCH; 830 inst_base->br = TransExtData::NON_BRANCH;
861 831
862 inst_cream->dp_operation = BIT(inst, 8); 832 inst_cream->dp_operation = BIT(inst, 8);
863 inst_cream->instr = inst; 833 inst_cream->instr = inst;
@@ -866,12 +836,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index)
866} 836}
867#endif 837#endif
868#ifdef VFP_INTERPRETER_IMPL 838#ifdef VFP_INTERPRETER_IMPL
869VCVTBFF_INST: 839VCVTBFF_INST : {
870{
871 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 840 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
872 CHECK_VFP_ENABLED; 841 CHECK_VFP_ENABLED;
873 842
874 vcvtbff_inst *inst_cream = (vcvtbff_inst *)inst_base->component; 843 vcvtbff_inst* inst_cream = (vcvtbff_inst*)inst_base->component;
875 844
876 int ret; 845 int ret;
877 846
@@ -899,14 +868,13 @@ struct vcvtbfi_inst {
899}; 868};
900#endif 869#endif
901#ifdef VFP_INTERPRETER_TRANS 870#ifdef VFP_INTERPRETER_TRANS
902static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index) 871static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index) {
903{ 872 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbfi_inst));
904 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbfi_inst)); 873 vcvtbfi_inst* inst_cream = (vcvtbfi_inst*)inst_base->component;
905 vcvtbfi_inst *inst_cream = (vcvtbfi_inst *)inst_base->component;
906 874
907 inst_base->cond = BITS(inst, 28, 31); 875 inst_base->cond = BITS(inst, 28, 31);
908 inst_base->idx = index; 876 inst_base->idx = index;
909 inst_base->br = TransExtData::NON_BRANCH; 877 inst_base->br = TransExtData::NON_BRANCH;
910 878
911 inst_cream->dp_operation = BIT(inst, 8); 879 inst_cream->dp_operation = BIT(inst, 8);
912 inst_cream->instr = inst; 880 inst_cream->instr = inst;
@@ -915,12 +883,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index)
915} 883}
916#endif 884#endif
917#ifdef VFP_INTERPRETER_IMPL 885#ifdef VFP_INTERPRETER_IMPL
918VCVTBFI_INST: 886VCVTBFI_INST : {
919{
920 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 887 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
921 CHECK_VFP_ENABLED; 888 CHECK_VFP_ENABLED;
922 889
923 vcvtbfi_inst *inst_cream = (vcvtbfi_inst *)inst_base->component; 890 vcvtbfi_inst* inst_cream = (vcvtbfi_inst*)inst_base->component;
924 891
925 int ret; 892 int ret;
926 893
@@ -955,29 +922,27 @@ struct vmovbrs_inst {
955}; 922};
956#endif 923#endif
957#ifdef VFP_INTERPRETER_TRANS 924#ifdef VFP_INTERPRETER_TRANS
958static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index) 925static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index) {
959{ 926 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrs_inst));
960 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrs_inst)); 927 vmovbrs_inst* inst_cream = (vmovbrs_inst*)inst_base->component;
961 vmovbrs_inst *inst_cream = (vmovbrs_inst *)inst_base->component;
962 928
963 inst_base->cond = BITS(inst, 28, 31); 929 inst_base->cond = BITS(inst, 28, 31);
964 inst_base->idx = index; 930 inst_base->idx = index;
965 inst_base->br = TransExtData::NON_BRANCH; 931 inst_base->br = TransExtData::NON_BRANCH;
966 932
967 inst_cream->to_arm = BIT(inst, 20) == 1; 933 inst_cream->to_arm = BIT(inst, 20) == 1;
968 inst_cream->t = BITS(inst, 12, 15); 934 inst_cream->t = BITS(inst, 12, 15);
969 inst_cream->n = BIT(inst, 7) | BITS(inst, 16, 19)<<1; 935 inst_cream->n = BIT(inst, 7) | BITS(inst, 16, 19) << 1;
970 936
971 return inst_base; 937 return inst_base;
972} 938}
973#endif 939#endif
974#ifdef VFP_INTERPRETER_IMPL 940#ifdef VFP_INTERPRETER_IMPL
975VMOVBRS_INST: 941VMOVBRS_INST : {
976{
977 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 942 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
978 CHECK_VFP_ENABLED; 943 CHECK_VFP_ENABLED;
979 944
980 vmovbrs_inst *inst_cream = (vmovbrs_inst *)inst_base->component; 945 vmovbrs_inst* inst_cream = (vmovbrs_inst*)inst_base->component;
981 946
982 VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t])); 947 VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t]));
983 } 948 }
@@ -999,24 +964,22 @@ struct vmsr_inst {
999}; 964};
1000#endif 965#endif
1001#ifdef VFP_INTERPRETER_TRANS 966#ifdef VFP_INTERPRETER_TRANS
1002static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index) 967static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index) {
1003{ 968 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmsr_inst));
1004 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmsr_inst)); 969 vmsr_inst* inst_cream = (vmsr_inst*)inst_base->component;
1005 vmsr_inst *inst_cream = (vmsr_inst *)inst_base->component;
1006 970
1007 inst_base->cond = BITS(inst, 28, 31); 971 inst_base->cond = BITS(inst, 28, 31);
1008 inst_base->idx = index; 972 inst_base->idx = index;
1009 inst_base->br = TransExtData::NON_BRANCH; 973 inst_base->br = TransExtData::NON_BRANCH;
1010 974
1011 inst_cream->reg = BITS(inst, 16, 19); 975 inst_cream->reg = BITS(inst, 16, 19);
1012 inst_cream->Rt = BITS(inst, 12, 15); 976 inst_cream->Rt = BITS(inst, 12, 15);
1013 977
1014 return inst_base; 978 return inst_base;
1015} 979}
1016#endif 980#endif
1017#ifdef VFP_INTERPRETER_IMPL 981#ifdef VFP_INTERPRETER_IMPL
1018VMSR_INST: 982VMSR_INST : {
1019{
1020 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 983 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1021 /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled , 984 /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled ,
1022 and in privileged mode */ 985 and in privileged mode */
@@ -1026,14 +989,11 @@ VMSR_INST:
1026 vmsr_inst* const inst_cream = (vmsr_inst*)inst_base->component; 989 vmsr_inst* const inst_cream = (vmsr_inst*)inst_base->component;
1027 990
1028 unsigned int reg = inst_cream->reg; 991 unsigned int reg = inst_cream->reg;
1029 unsigned int rt = inst_cream->Rt; 992 unsigned int rt = inst_cream->Rt;
1030 993
1031 if (reg == 1) 994 if (reg == 1) {
1032 {
1033 cpu->VFP[VFP_FPSCR] = cpu->Reg[rt]; 995 cpu->VFP[VFP_FPSCR] = cpu->Reg[rt];
1034 } 996 } else if (cpu->InAPrivilegedMode()) {
1035 else if (cpu->InAPrivilegedMode())
1036 {
1037 if (reg == 8) 997 if (reg == 8)
1038 cpu->VFP[VFP_FPEXC] = cpu->Reg[rt]; 998 cpu->VFP[VFP_FPEXC] = cpu->Reg[rt];
1039 else if (reg == 9) 999 else if (reg == 9)
@@ -1062,17 +1022,16 @@ struct vmovbrc_inst {
1062}; 1022};
1063#endif 1023#endif
1064#ifdef VFP_INTERPRETER_TRANS 1024#ifdef VFP_INTERPRETER_TRANS
1065static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index) 1025static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index) {
1066{ 1026 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrc_inst));
1067 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrc_inst)); 1027 vmovbrc_inst* inst_cream = (vmovbrc_inst*)inst_base->component;
1068 vmovbrc_inst *inst_cream = (vmovbrc_inst *)inst_base->component;
1069 1028
1070 inst_base->cond = BITS(inst, 28, 31); 1029 inst_base->cond = BITS(inst, 28, 31);
1071 inst_base->idx = index; 1030 inst_base->idx = index;
1072 inst_base->br = TransExtData::NON_BRANCH; 1031 inst_base->br = TransExtData::NON_BRANCH;
1073 1032
1074 inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4; 1033 inst_cream->d = BITS(inst, 16, 19) | BIT(inst, 7) << 4;
1075 inst_cream->t = BITS(inst, 12, 15); 1034 inst_cream->t = BITS(inst, 12, 15);
1076 /* VFP variant of instruction */ 1035 /* VFP variant of instruction */
1077 inst_cream->esize = 32; 1036 inst_cream->esize = 32;
1078 inst_cream->index = BIT(inst, 21); 1037 inst_cream->index = BIT(inst, 21);
@@ -1081,8 +1040,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index)
1081} 1040}
1082#endif 1041#endif
1083#ifdef VFP_INTERPRETER_IMPL 1042#ifdef VFP_INTERPRETER_IMPL
1084VMOVBRC_INST: 1043VMOVBRC_INST : {
1085{
1086 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1044 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1087 CHECK_VFP_ENABLED; 1045 CHECK_VFP_ENABLED;
1088 1046
@@ -1108,24 +1066,22 @@ struct vmrs_inst {
1108}; 1066};
1109#endif 1067#endif
1110#ifdef VFP_INTERPRETER_TRANS 1068#ifdef VFP_INTERPRETER_TRANS
1111static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index) 1069static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index) {
1112{ 1070 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmrs_inst));
1113 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmrs_inst)); 1071 vmrs_inst* inst_cream = (vmrs_inst*)inst_base->component;
1114 vmrs_inst *inst_cream = (vmrs_inst *)inst_base->component;
1115 1072
1116 inst_base->cond = BITS(inst, 28, 31); 1073 inst_base->cond = BITS(inst, 28, 31);
1117 inst_base->idx = index; 1074 inst_base->idx = index;
1118 inst_base->br = TransExtData::NON_BRANCH; 1075 inst_base->br = TransExtData::NON_BRANCH;
1119 1076
1120 inst_cream->reg = BITS(inst, 16, 19); 1077 inst_cream->reg = BITS(inst, 16, 19);
1121 inst_cream->Rt = BITS(inst, 12, 15); 1078 inst_cream->Rt = BITS(inst, 12, 15);
1122 1079
1123 return inst_base; 1080 return inst_base;
1124} 1081}
1125#endif 1082#endif
1126#ifdef VFP_INTERPRETER_IMPL 1083#ifdef VFP_INTERPRETER_IMPL
1127VMRS_INST: 1084VMRS_INST : {
1128{
1129 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1085 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1130 /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled, 1086 /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled,
1131 and in privileged mode */ 1087 and in privileged mode */
@@ -1135,36 +1091,25 @@ VMRS_INST:
1135 vmrs_inst* const inst_cream = (vmrs_inst*)inst_base->component; 1091 vmrs_inst* const inst_cream = (vmrs_inst*)inst_base->component;
1136 1092
1137 unsigned int reg = inst_cream->reg; 1093 unsigned int reg = inst_cream->reg;
1138 unsigned int rt = inst_cream->Rt; 1094 unsigned int rt = inst_cream->Rt;
1139 1095
1140 if (reg == 1) // FPSCR 1096 if (reg == 1) // FPSCR
1141 { 1097 {
1142 if (rt != 15) 1098 if (rt != 15) {
1143 {
1144 cpu->Reg[rt] = cpu->VFP[VFP_FPSCR]; 1099 cpu->Reg[rt] = cpu->VFP[VFP_FPSCR];
1145 } 1100 } else {
1146 else
1147 {
1148 cpu->NFlag = (cpu->VFP[VFP_FPSCR] >> 31) & 1; 1101 cpu->NFlag = (cpu->VFP[VFP_FPSCR] >> 31) & 1;
1149 cpu->ZFlag = (cpu->VFP[VFP_FPSCR] >> 30) & 1; 1102 cpu->ZFlag = (cpu->VFP[VFP_FPSCR] >> 30) & 1;
1150 cpu->CFlag = (cpu->VFP[VFP_FPSCR] >> 29) & 1; 1103 cpu->CFlag = (cpu->VFP[VFP_FPSCR] >> 29) & 1;
1151 cpu->VFlag = (cpu->VFP[VFP_FPSCR] >> 28) & 1; 1104 cpu->VFlag = (cpu->VFP[VFP_FPSCR] >> 28) & 1;
1152 } 1105 }
1153 } 1106 } else if (reg == 0) {
1154 else if (reg == 0)
1155 {
1156 cpu->Reg[rt] = cpu->VFP[VFP_FPSID]; 1107 cpu->Reg[rt] = cpu->VFP[VFP_FPSID];
1157 } 1108 } else if (reg == 6) {
1158 else if (reg == 6)
1159 {
1160 cpu->Reg[rt] = cpu->VFP[VFP_MVFR1]; 1109 cpu->Reg[rt] = cpu->VFP[VFP_MVFR1];
1161 } 1110 } else if (reg == 7) {
1162 else if (reg == 7)
1163 {
1164 cpu->Reg[rt] = cpu->VFP[VFP_MVFR0]; 1111 cpu->Reg[rt] = cpu->VFP[VFP_MVFR0];
1165 } 1112 } else if (cpu->InAPrivilegedMode()) {
1166 else if (cpu->InAPrivilegedMode())
1167 {
1168 if (reg == 8) 1113 if (reg == 8)
1169 cpu->Reg[rt] = cpu->VFP[VFP_FPEXC]; 1114 cpu->Reg[rt] = cpu->VFP[VFP_FPEXC];
1170 else if (reg == 9) 1115 else if (reg == 9)
@@ -1193,17 +1138,16 @@ struct vmovbcr_inst {
1193}; 1138};
1194#endif 1139#endif
1195#ifdef VFP_INTERPRETER_TRANS 1140#ifdef VFP_INTERPRETER_TRANS
1196static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index) 1141static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index) {
1197{ 1142 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbcr_inst));
1198 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbcr_inst)); 1143 vmovbcr_inst* inst_cream = (vmovbcr_inst*)inst_base->component;
1199 vmovbcr_inst *inst_cream = (vmovbcr_inst *)inst_base->component;
1200 1144
1201 inst_base->cond = BITS(inst, 28, 31); 1145 inst_base->cond = BITS(inst, 28, 31);
1202 inst_base->idx = index; 1146 inst_base->idx = index;
1203 inst_base->br = TransExtData::NON_BRANCH; 1147 inst_base->br = TransExtData::NON_BRANCH;
1204 1148
1205 inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4; 1149 inst_cream->d = BITS(inst, 16, 19) | BIT(inst, 7) << 4;
1206 inst_cream->t = BITS(inst, 12, 15); 1150 inst_cream->t = BITS(inst, 12, 15);
1207 /* VFP variant of instruction */ 1151 /* VFP variant of instruction */
1208 inst_cream->esize = 32; 1152 inst_cream->esize = 32;
1209 inst_cream->index = BIT(inst, 21); 1153 inst_cream->index = BIT(inst, 21);
@@ -1212,12 +1156,11 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index)
1212} 1156}
1213#endif 1157#endif
1214#ifdef VFP_INTERPRETER_IMPL 1158#ifdef VFP_INTERPRETER_IMPL
1215VMOVBCR_INST: 1159VMOVBCR_INST : {
1216{
1217 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1160 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1218 CHECK_VFP_ENABLED; 1161 CHECK_VFP_ENABLED;
1219 1162
1220 vmovbcr_inst* const inst_cream = (vmovbcr_inst*) inst_base->component; 1163 vmovbcr_inst* const inst_cream = (vmovbcr_inst*)inst_base->component;
1221 1164
1222 cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index]; 1165 cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index];
1223 } 1166 }
@@ -1246,33 +1189,31 @@ struct vmovbrrss_inst {
1246}; 1189};
1247#endif 1190#endif
1248#ifdef VFP_INTERPRETER_TRANS 1191#ifdef VFP_INTERPRETER_TRANS
1249static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int index) 1192static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int index) {
1250{ 1193 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrss_inst));
1251 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrss_inst)); 1194 vmovbrrss_inst* inst_cream = (vmovbrrss_inst*)inst_base->component;
1252 vmovbrrss_inst *inst_cream = (vmovbrrss_inst *)inst_base->component;
1253 1195
1254 inst_base->cond = BITS(inst, 28, 31); 1196 inst_base->cond = BITS(inst, 28, 31);
1255 inst_base->idx = index; 1197 inst_base->idx = index;
1256 inst_base->br = TransExtData::NON_BRANCH; 1198 inst_base->br = TransExtData::NON_BRANCH;
1257 1199
1258 inst_cream->to_arm = BIT(inst, 20) == 1; 1200 inst_cream->to_arm = BIT(inst, 20) == 1;
1259 inst_cream->t = BITS(inst, 12, 15); 1201 inst_cream->t = BITS(inst, 12, 15);
1260 inst_cream->t2 = BITS(inst, 16, 19); 1202 inst_cream->t2 = BITS(inst, 16, 19);
1261 inst_cream->m = BITS(inst, 0, 3)<<1|BIT(inst, 5); 1203 inst_cream->m = BITS(inst, 0, 3) << 1 | BIT(inst, 5);
1262 1204
1263 return inst_base; 1205 return inst_base;
1264} 1206}
1265#endif 1207#endif
1266#ifdef VFP_INTERPRETER_IMPL 1208#ifdef VFP_INTERPRETER_IMPL
1267VMOVBRRSS_INST: 1209VMOVBRRSS_INST : {
1268{
1269 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 1210 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1270 CHECK_VFP_ENABLED; 1211 CHECK_VFP_ENABLED;
1271 1212
1272 vmovbrrss_inst* const inst_cream = (vmovbrrss_inst*)inst_base->component; 1213 vmovbrrss_inst* const inst_cream = (vmovbrrss_inst*)inst_base->component;
1273 1214
1274 VMOVBRRSS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, 1215 VMOVBRRSS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m,
1275 &cpu->Reg[inst_cream->t], &cpu->Reg[inst_cream->t2]); 1216 &cpu->Reg[inst_cream->t], &cpu->Reg[inst_cream->t2]);
1276 } 1217 }
1277 cpu->Reg[15] += cpu->GetInstructionSize(); 1218 cpu->Reg[15] += cpu->GetInstructionSize();
1278 INC_PC(sizeof(vmovbrrss_inst)); 1219 INC_PC(sizeof(vmovbrrss_inst));
@@ -1294,33 +1235,31 @@ struct vmovbrrd_inst {
1294}; 1235};
1295#endif 1236#endif
1296#ifdef VFP_INTERPRETER_TRANS 1237#ifdef VFP_INTERPRETER_TRANS
1297static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index) 1238static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index) {
1298{ 1239 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrd_inst));
1299 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrd_inst)); 1240 vmovbrrd_inst* inst_cream = (vmovbrrd_inst*)inst_base->component;
1300 vmovbrrd_inst *inst_cream = (vmovbrrd_inst *)inst_base->component;
1301 1241
1302 inst_base->cond = BITS(inst, 28, 31); 1242 inst_base->cond = BITS(inst, 28, 31);
1303 inst_base->idx = index; 1243 inst_base->idx = index;
1304 inst_base->br = TransExtData::NON_BRANCH; 1244 inst_base->br = TransExtData::NON_BRANCH;
1305 1245
1306 inst_cream->to_arm = BIT(inst, 20) == 1; 1246 inst_cream->to_arm = BIT(inst, 20) == 1;
1307 inst_cream->t = BITS(inst, 12, 15); 1247 inst_cream->t = BITS(inst, 12, 15);
1308 inst_cream->t2 = BITS(inst, 16, 19); 1248 inst_cream->t2 = BITS(inst, 16, 19);
1309 inst_cream->m = BIT(inst, 5)<<4 | BITS(inst, 0, 3); 1249 inst_cream->m = BIT(inst, 5) << 4 | BITS(inst, 0, 3);
1310 1250
1311 return inst_base; 1251 return inst_base;
1312} 1252}
1313#endif 1253#endif
1314#ifdef VFP_INTERPRETER_IMPL 1254#ifdef VFP_INTERPRETER_IMPL
1315VMOVBRRD_INST: 1255VMOVBRRD_INST : {
1316{
1317 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 1256 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1318 CHECK_VFP_ENABLED; 1257 CHECK_VFP_ENABLED;
1319 1258
1320 vmovbrrd_inst *inst_cream = (vmovbrrd_inst *)inst_base->component; 1259 vmovbrrd_inst* inst_cream = (vmovbrrd_inst*)inst_base->component;
1321 1260
1322 VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, 1261 VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m,
1323 &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2])); 1262 &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2]));
1324 } 1263 }
1325 cpu->Reg[15] += cpu->GetInstructionSize(); 1264 cpu->Reg[15] += cpu->GetInstructionSize();
1326 INC_PC(sizeof(vmovbrrd_inst)); 1265 INC_PC(sizeof(vmovbrrd_inst));
@@ -1347,43 +1286,40 @@ struct vstr_inst {
1347}; 1286};
1348#endif 1287#endif
1349#ifdef VFP_INTERPRETER_TRANS 1288#ifdef VFP_INTERPRETER_TRANS
1350static ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index) 1289static ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index) {
1351{ 1290 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vstr_inst));
1352 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vstr_inst)); 1291 vstr_inst* inst_cream = (vstr_inst*)inst_base->component;
1353 vstr_inst *inst_cream = (vstr_inst *)inst_base->component;
1354 1292
1355 inst_base->cond = BITS(inst, 28, 31); 1293 inst_base->cond = BITS(inst, 28, 31);
1356 inst_base->idx = index; 1294 inst_base->idx = index;
1357 inst_base->br = TransExtData::NON_BRANCH; 1295 inst_base->br = TransExtData::NON_BRANCH;
1358 1296
1359 inst_cream->single = BIT(inst, 8) == 0; 1297 inst_cream->single = BIT(inst, 8) == 0;
1360 inst_cream->add = BIT(inst, 23); 1298 inst_cream->add = BIT(inst, 23);
1361 inst_cream->imm32 = BITS(inst, 0,7) << 2; 1299 inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1362 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); 1300 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
1363 inst_cream->n = BITS(inst, 16, 19); 1301 : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
1302 inst_cream->n = BITS(inst, 16, 19);
1364 1303
1365 return inst_base; 1304 return inst_base;
1366} 1305}
1367#endif 1306#endif
1368#ifdef VFP_INTERPRETER_IMPL 1307#ifdef VFP_INTERPRETER_IMPL
1369VSTR_INST: 1308VSTR_INST : {
1370{
1371 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 1309 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1372 CHECK_VFP_ENABLED; 1310 CHECK_VFP_ENABLED;
1373 1311
1374 vstr_inst *inst_cream = (vstr_inst *)inst_base->component; 1312 vstr_inst* inst_cream = (vstr_inst*)inst_base->component;
1375 1313
1376 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]); 1314 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8
1315 : cpu->Reg[inst_cream->n]);
1377 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32); 1316 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32);
1378 1317
1379 if (inst_cream->single) 1318 if (inst_cream->single) {
1380 {
1381 cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d]); 1319 cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d]);
1382 } 1320 } else {
1383 else 1321 const u32 word1 = cpu->ExtReg[inst_cream->d * 2 + 0];
1384 { 1322 const u32 word2 = cpu->ExtReg[inst_cream->d * 2 + 1];
1385 const u32 word1 = cpu->ExtReg[inst_cream->d*2+0];
1386 const u32 word2 = cpu->ExtReg[inst_cream->d*2+1];
1387 1323
1388 if (cpu->InBigEndianMode()) { 1324 if (cpu->InBigEndianMode()) {
1389 cpu->WriteMemory32(addr + 0, word2); 1325 cpu->WriteMemory32(addr + 0, word2);
@@ -1413,44 +1349,39 @@ struct vpush_inst {
1413}; 1349};
1414#endif 1350#endif
1415#ifdef VFP_INTERPRETER_TRANS 1351#ifdef VFP_INTERPRETER_TRANS
1416static ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index) 1352static ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index) {
1417{ 1353 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vpush_inst));
1418 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vpush_inst)); 1354 vpush_inst* inst_cream = (vpush_inst*)inst_base->component;
1419 vpush_inst *inst_cream = (vpush_inst *)inst_base->component;
1420 1355
1421 inst_base->cond = BITS(inst, 28, 31); 1356 inst_base->cond = BITS(inst, 28, 31);
1422 inst_base->idx = index; 1357 inst_base->idx = index;
1423 inst_base->br = TransExtData::NON_BRANCH; 1358 inst_base->br = TransExtData::NON_BRANCH;
1424 1359
1425 inst_cream->single = BIT(inst, 8) == 0; 1360 inst_cream->single = BIT(inst, 8) == 0;
1426 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); 1361 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
1427 inst_cream->imm32 = BITS(inst, 0, 7)<<2; 1362 : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
1428 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); 1363 inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1364 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
1429 1365
1430 return inst_base; 1366 return inst_base;
1431} 1367}
1432#endif 1368#endif
1433#ifdef VFP_INTERPRETER_IMPL 1369#ifdef VFP_INTERPRETER_IMPL
1434VPUSH_INST: 1370VPUSH_INST : {
1435{
1436 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 1371 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1437 CHECK_VFP_ENABLED; 1372 CHECK_VFP_ENABLED;
1438 1373
1439 vpush_inst *inst_cream = (vpush_inst *)inst_base->component; 1374 vpush_inst* inst_cream = (vpush_inst*)inst_base->component;
1440 1375
1441 addr = cpu->Reg[R13] - inst_cream->imm32; 1376 addr = cpu->Reg[R13] - inst_cream->imm32;
1442 1377
1443 for (unsigned int i = 0; i < inst_cream->regs; i++) 1378 for (unsigned int i = 0; i < inst_cream->regs; i++) {
1444 { 1379 if (inst_cream->single) {
1445 if (inst_cream->single) 1380 cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d + i]);
1446 {
1447 cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d+i]);
1448 addr += 4; 1381 addr += 4;
1449 } 1382 } else {
1450 else 1383 const u32 word1 = cpu->ExtReg[(inst_cream->d + i) * 2 + 0];
1451 { 1384 const u32 word2 = cpu->ExtReg[(inst_cream->d + i) * 2 + 1];
1452 const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
1453 const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
1454 1385
1455 if (cpu->InBigEndianMode()) { 1386 if (cpu->InBigEndianMode()) {
1456 cpu->WriteMemory32(addr + 0, word2); 1387 cpu->WriteMemory32(addr + 0, word2);
@@ -1488,28 +1419,28 @@ struct vstm_inst {
1488}; 1419};
1489#endif 1420#endif
1490#ifdef VFP_INTERPRETER_TRANS 1421#ifdef VFP_INTERPRETER_TRANS
1491static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index) 1422static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index) {
1492{ 1423 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vstm_inst));
1493 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vstm_inst)); 1424 vstm_inst* inst_cream = (vstm_inst*)inst_base->component;
1494 vstm_inst *inst_cream = (vstm_inst *)inst_base->component;
1495 1425
1496 inst_base->cond = BITS(inst, 28, 31); 1426 inst_base->cond = BITS(inst, 28, 31);
1497 inst_base->idx = index; 1427 inst_base->idx = index;
1498 inst_base->br = TransExtData::NON_BRANCH; 1428 inst_base->br = TransExtData::NON_BRANCH;
1499 1429
1500 inst_cream->single = BIT(inst, 8) == 0; 1430 inst_cream->single = BIT(inst, 8) == 0;
1501 inst_cream->add = BIT(inst, 23); 1431 inst_cream->add = BIT(inst, 23);
1502 inst_cream->wback = BIT(inst, 21); 1432 inst_cream->wback = BIT(inst, 21);
1503 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); 1433 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
1504 inst_cream->n = BITS(inst, 16, 19); 1434 : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
1505 inst_cream->imm32 = BITS(inst, 0, 7)<<2; 1435 inst_cream->n = BITS(inst, 16, 19);
1506 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); 1436 inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1437 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
1507 1438
1508 return inst_base; 1439 return inst_base;
1509} 1440}
1510#endif 1441#endif
1511#ifdef VFP_INTERPRETER_IMPL 1442#ifdef VFP_INTERPRETER_IMPL
1512VSTM_INST: /* encoding 1 */ 1443VSTM_INST : /* encoding 1 */
1513{ 1444{
1514 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1445 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1515 CHECK_VFP_ENABLED; 1446 CHECK_VFP_ENABLED;
@@ -1525,17 +1456,13 @@ VSTM_INST: /* encoding 1 */
1525 if (inst_cream->add == 0) 1456 if (inst_cream->add == 0)
1526 address -= inst_cream->imm32; 1457 address -= inst_cream->imm32;
1527 1458
1528 for (unsigned int i = 0; i < inst_cream->regs; i++) 1459 for (unsigned int i = 0; i < inst_cream->regs; i++) {
1529 { 1460 if (inst_cream->single) {
1530 if (inst_cream->single) 1461 cpu->WriteMemory32(address, cpu->ExtReg[inst_cream->d + i]);
1531 {
1532 cpu->WriteMemory32(address, cpu->ExtReg[inst_cream->d+i]);
1533 address += 4; 1462 address += 4;
1534 } 1463 } else {
1535 else 1464 const u32 word1 = cpu->ExtReg[(inst_cream->d + i) * 2 + 0];
1536 { 1465 const u32 word2 = cpu->ExtReg[(inst_cream->d + i) * 2 + 1];
1537 const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0];
1538 const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1];
1539 1466
1540 if (cpu->InBigEndianMode()) { 1467 if (cpu->InBigEndianMode()) {
1541 cpu->WriteMemory32(address + 0, word2); 1468 cpu->WriteMemory32(address + 0, word2);
@@ -1549,8 +1476,9 @@ VSTM_INST: /* encoding 1 */
1549 } 1476 }
1550 } 1477 }
1551 if (inst_cream->wback) { 1478 if (inst_cream->wback) {
1552 cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 : 1479 cpu->Reg[inst_cream->n] =
1553 cpu->Reg[inst_cream->n] - inst_cream->imm32); 1480 (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32
1481 : cpu->Reg[inst_cream->n] - inst_cream->imm32);
1554 } 1482 }
1555 } 1483 }
1556 cpu->Reg[15] += 4; 1484 cpu->Reg[15] += 4;
@@ -1573,51 +1501,46 @@ struct vpop_inst {
1573}; 1501};
1574#endif 1502#endif
1575#ifdef VFP_INTERPRETER_TRANS 1503#ifdef VFP_INTERPRETER_TRANS
1576static ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index) 1504static ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index) {
1577{ 1505 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vpop_inst));
1578 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vpop_inst)); 1506 vpop_inst* inst_cream = (vpop_inst*)inst_base->component;
1579 vpop_inst *inst_cream = (vpop_inst *)inst_base->component;
1580 1507
1581 inst_base->cond = BITS(inst, 28, 31); 1508 inst_base->cond = BITS(inst, 28, 31);
1582 inst_base->idx = index; 1509 inst_base->idx = index;
1583 inst_base->br = TransExtData::NON_BRANCH; 1510 inst_base->br = TransExtData::NON_BRANCH;
1584 1511
1585 inst_cream->single = BIT(inst, 8) == 0; 1512 inst_cream->single = BIT(inst, 8) == 0;
1586 inst_cream->d = (inst_cream->single ? (BITS(inst, 12, 15)<<1)|BIT(inst, 22) : BITS(inst, 12, 15)|(BIT(inst, 22)<<4)); 1513 inst_cream->d = (inst_cream->single ? (BITS(inst, 12, 15) << 1) | BIT(inst, 22)
1587 inst_cream->imm32 = BITS(inst, 0, 7)<<2; 1514 : BITS(inst, 12, 15) | (BIT(inst, 22) << 4));
1588 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); 1515 inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1516 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
1589 1517
1590 return inst_base; 1518 return inst_base;
1591} 1519}
1592#endif 1520#endif
1593#ifdef VFP_INTERPRETER_IMPL 1521#ifdef VFP_INTERPRETER_IMPL
1594VPOP_INST: 1522VPOP_INST : {
1595{
1596 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 1523 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1597 CHECK_VFP_ENABLED; 1524 CHECK_VFP_ENABLED;
1598 1525
1599 vpop_inst *inst_cream = (vpop_inst *)inst_base->component; 1526 vpop_inst* inst_cream = (vpop_inst*)inst_base->component;
1600 1527
1601 addr = cpu->Reg[R13]; 1528 addr = cpu->Reg[R13];
1602 1529
1603 for (unsigned int i = 0; i < inst_cream->regs; i++) 1530 for (unsigned int i = 0; i < inst_cream->regs; i++) {
1604 { 1531 if (inst_cream->single) {
1605 if (inst_cream->single) 1532 cpu->ExtReg[inst_cream->d + i] = cpu->ReadMemory32(addr);
1606 {
1607 cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(addr);
1608 addr += 4; 1533 addr += 4;
1609 } 1534 } else {
1610 else
1611 {
1612 const u32 word1 = cpu->ReadMemory32(addr + 0); 1535 const u32 word1 = cpu->ReadMemory32(addr + 0);
1613 const u32 word2 = cpu->ReadMemory32(addr + 4); 1536 const u32 word2 = cpu->ReadMemory32(addr + 4);
1614 1537
1615 if (cpu->InBigEndianMode()) { 1538 if (cpu->InBigEndianMode()) {
1616 cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; 1539 cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word2;
1617 cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; 1540 cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word1;
1618 } else { 1541 } else {
1619 cpu->ExtReg[(inst_cream->d+i)*2+0] = word1; 1542 cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word1;
1620 cpu->ExtReg[(inst_cream->d+i)*2+1] = word2; 1543 cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word2;
1621 } 1544 }
1622 1545
1623 addr += 8; 1546 addr += 8;
@@ -1632,7 +1555,6 @@ VPOP_INST:
1632} 1555}
1633#endif 1556#endif
1634 1557
1635
1636/* ----------------------------------------------------------------------- */ 1558/* ----------------------------------------------------------------------- */
1637/* VLDR */ 1559/* VLDR */
1638/* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */ 1560/* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */
@@ -1646,50 +1568,47 @@ struct vldr_inst {
1646}; 1568};
1647#endif 1569#endif
1648#ifdef VFP_INTERPRETER_TRANS 1570#ifdef VFP_INTERPRETER_TRANS
1649static ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index) 1571static ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index) {
1650{ 1572 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vldr_inst));
1651 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vldr_inst)); 1573 vldr_inst* inst_cream = (vldr_inst*)inst_base->component;
1652 vldr_inst *inst_cream = (vldr_inst *)inst_base->component;
1653 1574
1654 inst_base->cond = BITS(inst, 28, 31); 1575 inst_base->cond = BITS(inst, 28, 31);
1655 inst_base->idx = index; 1576 inst_base->idx = index;
1656 inst_base->br = TransExtData::NON_BRANCH; 1577 inst_base->br = TransExtData::NON_BRANCH;
1657 1578
1658 inst_cream->single = BIT(inst, 8) == 0; 1579 inst_cream->single = BIT(inst, 8) == 0;
1659 inst_cream->add = BIT(inst, 23); 1580 inst_cream->add = BIT(inst, 23);
1660 inst_cream->imm32 = BITS(inst, 0,7) << 2; 1581 inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1661 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); 1582 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
1662 inst_cream->n = BITS(inst, 16, 19); 1583 : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
1584 inst_cream->n = BITS(inst, 16, 19);
1663 1585
1664 return inst_base; 1586 return inst_base;
1665} 1587}
1666#endif 1588#endif
1667#ifdef VFP_INTERPRETER_IMPL 1589#ifdef VFP_INTERPRETER_IMPL
1668VLDR_INST: 1590VLDR_INST : {
1669{
1670 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 1591 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1671 CHECK_VFP_ENABLED; 1592 CHECK_VFP_ENABLED;
1672 1593
1673 vldr_inst *inst_cream = (vldr_inst *)inst_base->component; 1594 vldr_inst* inst_cream = (vldr_inst*)inst_base->component;
1674 1595
1675 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]); 1596 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8
1597 : cpu->Reg[inst_cream->n]);
1676 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32); 1598 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32);
1677 1599
1678 if (inst_cream->single) 1600 if (inst_cream->single) {
1679 {
1680 cpu->ExtReg[inst_cream->d] = cpu->ReadMemory32(addr); 1601 cpu->ExtReg[inst_cream->d] = cpu->ReadMemory32(addr);
1681 } 1602 } else {
1682 else
1683 {
1684 const u32 word1 = cpu->ReadMemory32(addr + 0); 1603 const u32 word1 = cpu->ReadMemory32(addr + 0);
1685 const u32 word2 = cpu->ReadMemory32(addr + 4); 1604 const u32 word2 = cpu->ReadMemory32(addr + 4);
1686 1605
1687 if (cpu->InBigEndianMode()) { 1606 if (cpu->InBigEndianMode()) {
1688 cpu->ExtReg[inst_cream->d*2+0] = word2; 1607 cpu->ExtReg[inst_cream->d * 2 + 0] = word2;
1689 cpu->ExtReg[inst_cream->d*2+1] = word1; 1608 cpu->ExtReg[inst_cream->d * 2 + 1] = word1;
1690 } else { 1609 } else {
1691 cpu->ExtReg[inst_cream->d*2+0] = word1; 1610 cpu->ExtReg[inst_cream->d * 2 + 0] = word1;
1692 cpu->ExtReg[inst_cream->d*2+1] = word2; 1611 cpu->ExtReg[inst_cream->d * 2 + 1] = word2;
1693 } 1612 }
1694 } 1613 }
1695 } 1614 }
@@ -1715,29 +1634,28 @@ struct vldm_inst {
1715}; 1634};
1716#endif 1635#endif
1717#ifdef VFP_INTERPRETER_TRANS 1636#ifdef VFP_INTERPRETER_TRANS
1718static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index) 1637static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index) {
1719{ 1638 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(vldm_inst));
1720 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vldm_inst)); 1639 vldm_inst* inst_cream = (vldm_inst*)inst_base->component;
1721 vldm_inst *inst_cream = (vldm_inst *)inst_base->component;
1722 1640
1723 inst_base->cond = BITS(inst, 28, 31); 1641 inst_base->cond = BITS(inst, 28, 31);
1724 inst_base->idx = index; 1642 inst_base->idx = index;
1725 inst_base->br = TransExtData::NON_BRANCH; 1643 inst_base->br = TransExtData::NON_BRANCH;
1726 1644
1727 inst_cream->single = BIT(inst, 8) == 0; 1645 inst_cream->single = BIT(inst, 8) == 0;
1728 inst_cream->add = BIT(inst, 23); 1646 inst_cream->add = BIT(inst, 23);
1729 inst_cream->wback = BIT(inst, 21); 1647 inst_cream->wback = BIT(inst, 21);
1730 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4); 1648 inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15) << 1 | BIT(inst, 22)
1731 inst_cream->n = BITS(inst, 16, 19); 1649 : BITS(inst, 12, 15) | BIT(inst, 22) << 4);
1732 inst_cream->imm32 = BITS(inst, 0, 7)<<2; 1650 inst_cream->n = BITS(inst, 16, 19);
1733 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7)); 1651 inst_cream->imm32 = BITS(inst, 0, 7) << 2;
1652 inst_cream->regs = (inst_cream->single ? BITS(inst, 0, 7) : BITS(inst, 1, 7));
1734 1653
1735 return inst_base; 1654 return inst_base;
1736} 1655}
1737#endif 1656#endif
1738#ifdef VFP_INTERPRETER_IMPL 1657#ifdef VFP_INTERPRETER_IMPL
1739VLDM_INST: 1658VLDM_INST : {
1740{
1741 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1659 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1742 CHECK_VFP_ENABLED; 1660 CHECK_VFP_ENABLED;
1743 1661
@@ -1752,32 +1670,29 @@ VLDM_INST:
1752 if (inst_cream->add == 0) 1670 if (inst_cream->add == 0)
1753 address -= inst_cream->imm32; 1671 address -= inst_cream->imm32;
1754 1672
1755 for (unsigned int i = 0; i < inst_cream->regs; i++) 1673 for (unsigned int i = 0; i < inst_cream->regs; i++) {
1756 { 1674 if (inst_cream->single) {
1757 if (inst_cream->single) 1675 cpu->ExtReg[inst_cream->d + i] = cpu->ReadMemory32(address);
1758 {
1759 cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(address);
1760 address += 4; 1676 address += 4;
1761 } 1677 } else {
1762 else
1763 {
1764 const u32 word1 = cpu->ReadMemory32(address + 0); 1678 const u32 word1 = cpu->ReadMemory32(address + 0);
1765 const u32 word2 = cpu->ReadMemory32(address + 4); 1679 const u32 word2 = cpu->ReadMemory32(address + 4);
1766 1680
1767 if (cpu->InBigEndianMode()) { 1681 if (cpu->InBigEndianMode()) {
1768 cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; 1682 cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word2;
1769 cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; 1683 cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word1;
1770 } else { 1684 } else {
1771 cpu->ExtReg[(inst_cream->d+i)*2+0] = word1; 1685 cpu->ExtReg[(inst_cream->d + i) * 2 + 0] = word1;
1772 cpu->ExtReg[(inst_cream->d+i)*2+1] = word2; 1686 cpu->ExtReg[(inst_cream->d + i) * 2 + 1] = word2;
1773 } 1687 }
1774 1688
1775 address += 8; 1689 address += 8;
1776 } 1690 }
1777 } 1691 }
1778 if (inst_cream->wback) { 1692 if (inst_cream->wback) {
1779 cpu->Reg[inst_cream->n] = (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32 : 1693 cpu->Reg[inst_cream->n] =
1780 cpu->Reg[inst_cream->n] - inst_cream->imm32); 1694 (inst_cream->add ? cpu->Reg[inst_cream->n] + inst_cream->imm32
1695 : cpu->Reg[inst_cream->n] - inst_cream->imm32);
1781 } 1696 }
1782 } 1697 }
1783 cpu->Reg[15] += cpu->GetInstructionSize(); 1698 cpu->Reg[15] += cpu->GetInstructionSize();
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index 60264f9b3..3c21efe62 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -58,24 +58,20 @@
58#include "common/common_types.h" 58#include "common/common_types.h"
59#include "common/logging/log.h" 59#include "common/logging/log.h"
60 60
61#include "core/arm/skyeye_common/vfp/vfp_helper.h"
62#include "core/arm/skyeye_common/vfp/asm_vfp.h" 61#include "core/arm/skyeye_common/vfp/asm_vfp.h"
63#include "core/arm/skyeye_common/vfp/vfp.h" 62#include "core/arm/skyeye_common/vfp/vfp.h"
63#include "core/arm/skyeye_common/vfp/vfp_helper.h"
64 64
65static struct vfp_single vfp_single_default_qnan = { 65static struct vfp_single vfp_single_default_qnan = {
66 255, 66 255, 0, VFP_SINGLE_SIGNIFICAND_QNAN,
67 0,
68 VFP_SINGLE_SIGNIFICAND_QNAN,
69}; 67};
70 68
71static void vfp_single_dump(const char *str, struct vfp_single *s) 69static void vfp_single_dump(const char* str, struct vfp_single* s) {
72{ 70 LOG_TRACE(Core_ARM11, "%s: sign=%d exponent=%d significand=%08x", str, s->sign != 0,
73 LOG_TRACE(Core_ARM11, "%s: sign=%d exponent=%d significand=%08x", 71 s->exponent, s->significand);
74 str, s->sign != 0, s->exponent, s->significand);
75} 72}
76 73
77static void vfp_single_normalise_denormal(struct vfp_single *vs) 74static void vfp_single_normalise_denormal(struct vfp_single* vs) {
78{
79 int bits = 31 - fls(vs->significand); 75 int bits = 31 - fls(vs->significand);
80 76
81 vfp_single_dump("normalise_denormal: in", vs); 77 vfp_single_dump("normalise_denormal: in", vs);
@@ -88,9 +84,8 @@ static void vfp_single_normalise_denormal(struct vfp_single *vs)
88 vfp_single_dump("normalise_denormal: out", vs); 84 vfp_single_dump("normalise_denormal: out", vs);
89} 85}
90 86
91 87u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single* vs, u32 fpscr,
92u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, const char *func) 88 const char* func) {
93{
94 u32 significand, incr, rmode; 89 u32 significand, incr, rmode;
95 int exponent, shift, underflow; 90 int exponent, shift, underflow;
96 u32 exceptions = 0; 91 u32 exceptions = 0;
@@ -199,7 +194,7 @@ u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs,
199 vs->exponent = 253; 194 vs->exponent = 253;
200 vs->significand = 0x7fffffff; 195 vs->significand = 0x7fffffff;
201 } else { 196 } else {
202 vs->exponent = 255; /* infinity */ 197 vs->exponent = 255; /* infinity */
203 vs->significand = 0; 198 vs->significand = 0;
204 } 199 }
205 } else { 200 } else {
@@ -217,8 +212,7 @@ pack:
217 vfp_single_dump("pack: final", vs); 212 vfp_single_dump("pack: final", vs);
218 { 213 {
219 s32 d = vfp_single_pack(vs); 214 s32 d = vfp_single_pack(vs);
220 LOG_TRACE(Core_ARM11, "%s: d(s%d)=%08x exceptions=%08x", func, 215 LOG_TRACE(Core_ARM11, "%s: d(s%d)=%08x exceptions=%08x", func, sd, d, exceptions);
221 sd, d, exceptions);
222 vfp_put_float(state, d, sd); 216 vfp_put_float(state, d, sd);
223 } 217 }
224 218
@@ -229,11 +223,9 @@ pack:
229 * Propagate the NaN, setting exceptions if it is signalling. 223 * Propagate the NaN, setting exceptions if it is signalling.
230 * 'n' is always a NaN. 'm' may be a number, NaN or infinity. 224 * 'n' is always a NaN. 'm' may be a number, NaN or infinity.
231 */ 225 */
232static u32 226static u32 vfp_propagate_nan(struct vfp_single* vsd, struct vfp_single* vsn, struct vfp_single* vsm,
233vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn, 227 u32 fpscr) {
234 struct vfp_single *vsm, u32 fpscr) 228 struct vfp_single* nan;
235{
236 struct vfp_single *nan;
237 int tn, tm = 0; 229 int tn, tm = 0;
238 230
239 tn = vfp_single_type(vsn); 231 tn = vfp_single_type(vsn);
@@ -270,40 +262,33 @@ vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn,
270 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG; 262 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG;
271} 263}
272 264
273
274/* 265/*
275 * Extended operations 266 * Extended operations
276 */ 267 */
277static u32 vfp_single_fabs(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 268static u32 vfp_single_fabs(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
278{
279 vfp_put_float(state, vfp_single_packed_abs(m), sd); 269 vfp_put_float(state, vfp_single_packed_abs(m), sd);
280 return 0; 270 return 0;
281} 271}
282 272
283static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 273static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
284{
285 vfp_put_float(state, m, sd); 274 vfp_put_float(state, m, sd);
286 return 0; 275 return 0;
287} 276}
288 277
289static u32 vfp_single_fneg(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 278static u32 vfp_single_fneg(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
290{
291 vfp_put_float(state, vfp_single_packed_negate(m), sd); 279 vfp_put_float(state, vfp_single_packed_negate(m), sd);
292 return 0; 280 return 0;
293} 281}
294 282
295static const u16 sqrt_oddadjust[] = { 283static const u16 sqrt_oddadjust[] = {0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f,
296 0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0, 284 0x0236, 0x02e0, 0x039c, 0x0468, 0x0545, 0x0631,
297 0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67 285 0x072b, 0x0832, 0x0946, 0x0a67};
298};
299 286
300static const u16 sqrt_evenadjust[] = { 287static const u16 sqrt_evenadjust[] = {0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429,
301 0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e, 288 0x0356, 0x029e, 0x0200, 0x0179, 0x0109, 0x00af,
302 0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002 289 0x0068, 0x0034, 0x0012, 0x0002};
303};
304 290
305u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand) 291u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand) {
306{
307 int index; 292 int index;
308 u32 z, a; 293 u32 z, a;
309 294
@@ -331,25 +316,24 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand)
331 } 316 }
332} 317}
333 318
334static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 319static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
335{
336 struct vfp_single vsm, vsd, *vsp; 320 struct vfp_single vsm, vsd, *vsp;
337 int ret, tm; 321 int ret, tm;
338 u32 exceptions = 0; 322 u32 exceptions = 0;
339 323
340 exceptions |= vfp_single_unpack(&vsm, m, fpscr); 324 exceptions |= vfp_single_unpack(&vsm, m, fpscr);
341 tm = vfp_single_type(&vsm); 325 tm = vfp_single_type(&vsm);
342 if (tm & (VFP_NAN|VFP_INFINITY)) { 326 if (tm & (VFP_NAN | VFP_INFINITY)) {
343 vsp = &vsd; 327 vsp = &vsd;
344 328
345 if (tm & VFP_NAN) 329 if (tm & VFP_NAN)
346 ret = vfp_propagate_nan(vsp, &vsm, nullptr, fpscr); 330 ret = vfp_propagate_nan(vsp, &vsm, nullptr, fpscr);
347 else if (vsm.sign == 0) { 331 else if (vsm.sign == 0) {
348sqrt_copy: 332 sqrt_copy:
349 vsp = &vsm; 333 vsp = &vsm;
350 ret = 0; 334 ret = 0;
351 } else { 335 } else {
352sqrt_invalid: 336 sqrt_invalid:
353 vsp = &vfp_single_default_qnan; 337 vsp = &vfp_single_default_qnan;
354 ret = FPSCR_IOC; 338 ret = FPSCR_IOC;
355 } 339 }
@@ -420,15 +404,15 @@ sqrt_invalid:
420 * Greater than := C 404 * Greater than := C
421 * Unordered := CV 405 * Unordered := CV
422 */ 406 */
423static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u32 fpscr) 407static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u32 fpscr) {
424{
425 s32 d; 408 s32 d;
426 u32 ret = 0; 409 u32 ret = 0;
427 410
428 d = vfp_get_float(state, sd); 411 d = vfp_get_float(state, sd);
429 if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) { 412 if (vfp_single_packed_exponent(m) == 255 && vfp_single_packed_mantissa(m)) {
430 ret |= FPSCR_CFLAG | FPSCR_VFLAG; 413 ret |= FPSCR_CFLAG | FPSCR_VFLAG;
431 if (signal_on_qnan || !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) 414 if (signal_on_qnan ||
415 !(vfp_single_packed_mantissa(m) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
432 /* 416 /*
433 * Signalling NaN, or signalling on quiet NaN 417 * Signalling NaN, or signalling on quiet NaN
434 */ 418 */
@@ -437,7 +421,8 @@ static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u3
437 421
438 if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) { 422 if (vfp_single_packed_exponent(d) == 255 && vfp_single_packed_mantissa(d)) {
439 ret |= FPSCR_CFLAG | FPSCR_VFLAG; 423 ret |= FPSCR_CFLAG | FPSCR_VFLAG;
440 if (signal_on_qnan || !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1)))) 424 if (signal_on_qnan ||
425 !(vfp_single_packed_mantissa(d) & (1 << (VFP_SINGLE_MANTISSA_BITS - 1))))
441 /* 426 /*
442 * Signalling NaN, or signalling on quiet NaN 427 * Signalling NaN, or signalling on quiet NaN
443 */ 428 */
@@ -479,28 +464,23 @@ static u32 vfp_compare(ARMul_State* state, int sd, int signal_on_qnan, s32 m, u3
479 return ret; 464 return ret;
480} 465}
481 466
482static u32 vfp_single_fcmp(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 467static u32 vfp_single_fcmp(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
483{
484 return vfp_compare(state, sd, 0, m, fpscr); 468 return vfp_compare(state, sd, 0, m, fpscr);
485} 469}
486 470
487static u32 vfp_single_fcmpe(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 471static u32 vfp_single_fcmpe(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
488{
489 return vfp_compare(state, sd, 1, m, fpscr); 472 return vfp_compare(state, sd, 1, m, fpscr);
490} 473}
491 474
492static u32 vfp_single_fcmpz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 475static u32 vfp_single_fcmpz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
493{
494 return vfp_compare(state, sd, 0, 0, fpscr); 476 return vfp_compare(state, sd, 0, 0, fpscr);
495} 477}
496 478
497static u32 vfp_single_fcmpez(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 479static u32 vfp_single_fcmpez(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
498{
499 return vfp_compare(state, sd, 1, 0, fpscr); 480 return vfp_compare(state, sd, 1, 0, fpscr);
500} 481}
501 482
502static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr) 483static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 fpscr) {
503{
504 struct vfp_single vsm; 484 struct vfp_single vsm;
505 struct vfp_double vdd; 485 struct vfp_double vdd;
506 int tm; 486 int tm;
@@ -525,7 +505,7 @@ static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 f
525 /* 505 /*
526 * If we have an infinity or NaN, the exponent must be 2047. 506 * If we have an infinity or NaN, the exponent must be 2047.
527 */ 507 */
528 if (tm & (VFP_INFINITY|VFP_NAN)) { 508 if (tm & (VFP_INFINITY | VFP_NAN)) {
529 vdd.exponent = 2047; 509 vdd.exponent = 2047;
530 if (tm == VFP_QNAN) 510 if (tm == VFP_QNAN)
531 vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; 511 vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
@@ -543,8 +523,7 @@ pack_nan:
543 return exceptions; 523 return exceptions;
544} 524}
545 525
546static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 526static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
547{
548 struct vfp_single vs; 527 struct vfp_single vs;
549 u32 exceptions = 0; 528 u32 exceptions = 0;
550 529
@@ -556,8 +535,7 @@ static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 f
556 return exceptions; 535 return exceptions;
557} 536}
558 537
559static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 538static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
560{
561 struct vfp_single vs; 539 struct vfp_single vs;
562 u32 exceptions = 0; 540 u32 exceptions = 0;
563 541
@@ -569,8 +547,7 @@ static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 f
569 return exceptions; 547 return exceptions;
570} 548}
571 549
572static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 550static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
573{
574 struct vfp_single vsm; 551 struct vfp_single vsm;
575 u32 d, exceptions = 0; 552 u32 d, exceptions = 0;
576 int rmode = fpscr & FPSCR_RMODE_MASK; 553 int rmode = fpscr & FPSCR_RMODE_MASK;
@@ -656,13 +633,11 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f
656 return exceptions; 633 return exceptions;
657} 634}
658 635
659static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 636static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
660{
661 return vfp_single_ftoui(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); 637 return vfp_single_ftoui(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO);
662} 638}
663 639
664static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 640static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
665{
666 struct vfp_single vsm; 641 struct vfp_single vsm;
667 u32 d, exceptions = 0; 642 u32 d, exceptions = 0;
668 int rmode = fpscr & FPSCR_RMODE_MASK; 643 int rmode = fpscr & FPSCR_RMODE_MASK;
@@ -739,51 +714,44 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f
739 return exceptions; 714 return exceptions;
740} 715}
741 716
742static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 717static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
743{
744 return vfp_single_ftosi(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); 718 return vfp_single_ftosi(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO);
745} 719}
746 720
747static struct op fops_ext[] = { 721static struct op fops_ext[] = {
748 { vfp_single_fcpy, 0 }, //0x00000000 - FEXT_FCPY 722 {vfp_single_fcpy, 0}, // 0x00000000 - FEXT_FCPY
749 { vfp_single_fabs, 0 }, //0x00000001 - FEXT_FABS 723 {vfp_single_fabs, 0}, // 0x00000001 - FEXT_FABS
750 { vfp_single_fneg, 0 }, //0x00000002 - FEXT_FNEG 724 {vfp_single_fneg, 0}, // 0x00000002 - FEXT_FNEG
751 { vfp_single_fsqrt, 0 }, //0x00000003 - FEXT_FSQRT 725 {vfp_single_fsqrt, 0}, // 0x00000003 - FEXT_FSQRT
752 { nullptr, 0 }, 726 {nullptr, 0},
753 { nullptr, 0 }, 727 {nullptr, 0},
754 { nullptr, 0 }, 728 {nullptr, 0},
755 { nullptr, 0 }, 729 {nullptr, 0},
756 { vfp_single_fcmp, OP_SCALAR }, //0x00000008 - FEXT_FCMP 730 {vfp_single_fcmp, OP_SCALAR}, // 0x00000008 - FEXT_FCMP
757 { vfp_single_fcmpe, OP_SCALAR }, //0x00000009 - FEXT_FCMPE 731 {vfp_single_fcmpe, OP_SCALAR}, // 0x00000009 - FEXT_FCMPE
758 { vfp_single_fcmpz, OP_SCALAR }, //0x0000000A - FEXT_FCMPZ 732 {vfp_single_fcmpz, OP_SCALAR}, // 0x0000000A - FEXT_FCMPZ
759 { vfp_single_fcmpez, OP_SCALAR }, //0x0000000B - FEXT_FCMPEZ 733 {vfp_single_fcmpez, OP_SCALAR}, // 0x0000000B - FEXT_FCMPEZ
760 { nullptr, 0 }, 734 {nullptr, 0},
761 { nullptr, 0 }, 735 {nullptr, 0},
762 { nullptr, 0 }, 736 {nullptr, 0},
763 { vfp_single_fcvtd, OP_SCALAR|OP_DD }, //0x0000000F - FEXT_FCVT 737 {vfp_single_fcvtd, OP_SCALAR | OP_DD}, // 0x0000000F - FEXT_FCVT
764 { vfp_single_fuito, OP_SCALAR }, //0x00000010 - FEXT_FUITO 738 {vfp_single_fuito, OP_SCALAR}, // 0x00000010 - FEXT_FUITO
765 { vfp_single_fsito, OP_SCALAR }, //0x00000011 - FEXT_FSITO 739 {vfp_single_fsito, OP_SCALAR}, // 0x00000011 - FEXT_FSITO
766 { nullptr, 0 }, 740 {nullptr, 0},
767 { nullptr, 0 }, 741 {nullptr, 0},
768 { nullptr, 0 }, 742 {nullptr, 0},
769 { nullptr, 0 }, 743 {nullptr, 0},
770 { nullptr, 0 }, 744 {nullptr, 0},
771 { nullptr, 0 }, 745 {nullptr, 0},
772 { vfp_single_ftoui, OP_SCALAR }, //0x00000018 - FEXT_FTOUI 746 {vfp_single_ftoui, OP_SCALAR}, // 0x00000018 - FEXT_FTOUI
773 { vfp_single_ftouiz, OP_SCALAR }, //0x00000019 - FEXT_FTOUIZ 747 {vfp_single_ftouiz, OP_SCALAR}, // 0x00000019 - FEXT_FTOUIZ
774 { vfp_single_ftosi, OP_SCALAR }, //0x0000001A - FEXT_FTOSI 748 {vfp_single_ftosi, OP_SCALAR}, // 0x0000001A - FEXT_FTOSI
775 { vfp_single_ftosiz, OP_SCALAR }, //0x0000001B - FEXT_FTOSIZ 749 {vfp_single_ftosiz, OP_SCALAR}, // 0x0000001B - FEXT_FTOSIZ
776}; 750};
777 751
778 752static u32 vfp_single_fadd_nonnumber(struct vfp_single* vsd, struct vfp_single* vsn,
779 753 struct vfp_single* vsm, u32 fpscr) {
780 754 struct vfp_single* vsp;
781
782static u32
783vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn,
784 struct vfp_single *vsm, u32 fpscr)
785{
786 struct vfp_single *vsp;
787 u32 exceptions = 0; 755 u32 exceptions = 0;
788 int tn, tm; 756 int tn, tm;
789 757
@@ -821,14 +789,11 @@ vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn,
821 return exceptions; 789 return exceptions;
822} 790}
823 791
824static u32 792static u32 vfp_single_add(struct vfp_single* vsd, struct vfp_single* vsn, struct vfp_single* vsm,
825vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn, 793 u32 fpscr) {
826 struct vfp_single *vsm, u32 fpscr)
827{
828 u32 exp_diff, m_sig; 794 u32 exp_diff, m_sig;
829 795
830 if (vsn->significand & 0x80000000 || 796 if (vsn->significand & 0x80000000 || vsm->significand & 0x80000000) {
831 vsm->significand & 0x80000000) {
832 LOG_WARNING(Core_ARM11, "bad FP values"); 797 LOG_WARNING(Core_ARM11, "bad FP values");
833 vfp_single_dump("VSN", vsn); 798 vfp_single_dump("VSN", vsn);
834 vfp_single_dump("VSM", vsm); 799 vfp_single_dump("VSM", vsm);
@@ -872,8 +837,7 @@ vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
872 vsd->sign = vfp_sign_negate(vsd->sign); 837 vsd->sign = vfp_sign_negate(vsd->sign);
873 m_sig = (~m_sig + 1); 838 m_sig = (~m_sig + 1);
874 } else if (m_sig == 0) { 839 } else if (m_sig == 0) {
875 vsd->sign = (fpscr & FPSCR_RMODE_MASK) == 840 vsd->sign = (fpscr & FPSCR_RMODE_MASK) == FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
876 FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
877 } 841 }
878 } else { 842 } else {
879 m_sig = vsn->significand + m_sig; 843 m_sig = vsn->significand + m_sig;
@@ -883,9 +847,8 @@ vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
883 return 0; 847 return 0;
884} 848}
885 849
886static u32 850static u32 vfp_single_multiply(struct vfp_single* vsd, struct vfp_single* vsn,
887vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_single *vsm, u32 fpscr) 851 struct vfp_single* vsm, u32 fpscr) {
888{
889 vfp_single_dump("VSN", vsn); 852 vfp_single_dump("VSN", vsn);
890 vfp_single_dump("VSM", vsm); 853 vfp_single_dump("VSM", vsm);
891 854
@@ -938,12 +901,11 @@ vfp_single_multiply(struct vfp_single *vsd, struct vfp_single *vsn, struct vfp_s
938 return 0; 901 return 0;
939} 902}
940 903
941#define NEG_MULTIPLY (1 << 0) 904#define NEG_MULTIPLY (1 << 0)
942#define NEG_SUBTRACT (1 << 1) 905#define NEG_SUBTRACT (1 << 1)
943 906
944static u32 907static u32 vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr,
945vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr, u32 negate, const char *func) 908 u32 negate, const char* func) {
946{
947 vfp_single vsd, vsp, vsn, vsm; 909 vfp_single vsd, vsp, vsn, vsm;
948 u32 exceptions = 0; 910 u32 exceptions = 0;
949 s32 v; 911 s32 v;
@@ -985,8 +947,7 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp
985/* 947/*
986 * sd = sd + (sn * sm) 948 * sd = sd + (sn * sm)
987 */ 949 */
988static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 950static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
989{
990 u32 exceptions = 0; 951 u32 exceptions = 0;
991 LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); 952 LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd);
992 exceptions |= vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac"); 953 exceptions |= vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac");
@@ -996,8 +957,7 @@ static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
996/* 957/*
997 * sd = sd - (sn * sm) 958 * sd = sd - (sn * sm)
998 */ 959 */
999static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 960static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
1000{
1001 // TODO: this one has its arguments inverted, investigate. 961 // TODO: this one has its arguments inverted, investigate.
1002 LOG_TRACE(Core_ARM11, "s%u = %08x", sd, sn); 962 LOG_TRACE(Core_ARM11, "s%u = %08x", sd, sn);
1003 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac"); 963 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_MULTIPLY, "fnmac");
@@ -1006,8 +966,7 @@ static u32 vfp_single_fnmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
1006/* 966/*
1007 * sd = -sd + (sn * sm) 967 * sd = -sd + (sn * sm)
1008 */ 968 */
1009static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 969static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
1010{
1011 LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); 970 LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd);
1012 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc"); 971 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT, "fmsc");
1013} 972}
@@ -1015,17 +974,16 @@ static u32 vfp_single_fmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1015/* 974/*
1016 * sd = -sd - (sn * sm) 975 * sd = -sd - (sn * sm)
1017 */ 976 */
1018static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 977static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
1019{
1020 LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); 978 LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd);
1021 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY, "fnmsc"); 979 return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, NEG_SUBTRACT | NEG_MULTIPLY,
980 "fnmsc");
1022} 981}
1023 982
1024/* 983/*
1025 * sd = sn * sm 984 * sd = sn * sm
1026 */ 985 */
1027static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 986static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
1028{
1029 struct vfp_single vsd, vsn, vsm; 987 struct vfp_single vsd, vsn, vsm;
1030 u32 exceptions = 0; 988 u32 exceptions = 0;
1031 s32 n = vfp_get_float(state, sn); 989 s32 n = vfp_get_float(state, sn);
@@ -1049,8 +1007,7 @@ static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1049/* 1007/*
1050 * sd = -(sn * sm) 1008 * sd = -(sn * sm)
1051 */ 1009 */
1052static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1010static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
1053{
1054 struct vfp_single vsd, vsn, vsm; 1011 struct vfp_single vsd, vsn, vsm;
1055 u32 exceptions = 0; 1012 u32 exceptions = 0;
1056 s32 n = vfp_get_float(state, sn); 1013 s32 n = vfp_get_float(state, sn);
@@ -1075,8 +1032,7 @@ static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr
1075/* 1032/*
1076 * sd = sn + sm 1033 * sd = sn + sm
1077 */ 1034 */
1078static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1035static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
1079{
1080 struct vfp_single vsd, vsn, vsm; 1036 struct vfp_single vsd, vsn, vsm;
1081 u32 exceptions = 0; 1037 u32 exceptions = 0;
1082 s32 n = vfp_get_float(state, sn); 1038 s32 n = vfp_get_float(state, sn);
@@ -1103,8 +1059,7 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1103/* 1059/*
1104 * sd = sn - sm 1060 * sd = sn - sm
1105 */ 1061 */
1106static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1062static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
1107{
1108 LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); 1063 LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd);
1109 /* 1064 /*
1110 * Subtraction is addition with one sign inverted. 1065 * Subtraction is addition with one sign inverted.
@@ -1118,8 +1073,7 @@ static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1118/* 1073/*
1119 * sd = sn / sm 1074 * sd = sn / sm
1120 */ 1075 */
1121static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) 1076static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
1122{
1123 struct vfp_single vsd, vsn, vsm; 1077 struct vfp_single vsd, vsn, vsm;
1124 u32 exceptions = 0; 1078 u32 exceptions = 0;
1125 s32 n = vfp_get_float(state, sn); 1079 s32 n = vfp_get_float(state, sn);
@@ -1151,7 +1105,7 @@ static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1151 * If n and m are infinity, the result is invalid 1105 * If n and m are infinity, the result is invalid
1152 * If n and m are zero, the result is invalid 1106 * If n and m are zero, the result is invalid
1153 */ 1107 */
1154 if (tm & tn & (VFP_INFINITY|VFP_ZERO)) 1108 if (tm & tn & (VFP_INFINITY | VFP_ZERO))
1155 goto invalid; 1109 goto invalid;
1156 1110
1157 /* 1111 /*
@@ -1226,29 +1180,22 @@ invalid:
1226} 1180}
1227 1181
1228static struct op fops[] = { 1182static struct op fops[] = {
1229 { vfp_single_fmac, 0 }, 1183 {vfp_single_fmac, 0}, {vfp_single_fmsc, 0}, {vfp_single_fmul, 0},
1230 { vfp_single_fmsc, 0 }, 1184 {vfp_single_fadd, 0}, {vfp_single_fnmac, 0}, {vfp_single_fnmsc, 0},
1231 { vfp_single_fmul, 0 }, 1185 {vfp_single_fnmul, 0}, {vfp_single_fsub, 0}, {vfp_single_fdiv, 0},
1232 { vfp_single_fadd, 0 },
1233 { vfp_single_fnmac, 0 },
1234 { vfp_single_fnmsc, 0 },
1235 { vfp_single_fnmul, 0 },
1236 { vfp_single_fsub, 0 },
1237 { vfp_single_fdiv, 0 },
1238}; 1186};
1239 1187
1240#define FREG_BANK(x) ((x) & 0x18) 1188#define FREG_BANK(x) ((x)&0x18)
1241#define FREG_IDX(x) ((x) & 7) 1189#define FREG_IDX(x) ((x)&7)
1242 1190
1243u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr) 1191u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr) {
1244{
1245 u32 op = inst & FOP_MASK; 1192 u32 op = inst & FOP_MASK;
1246 u32 exceptions = 0; 1193 u32 exceptions = 0;
1247 unsigned int dest; 1194 unsigned int dest;
1248 unsigned int sn = vfp_get_sn(inst); 1195 unsigned int sn = vfp_get_sn(inst);
1249 unsigned int sm = vfp_get_sm(inst); 1196 unsigned int sm = vfp_get_sm(inst);
1250 unsigned int vecitr, veclen, vecstride; 1197 unsigned int vecitr, veclen, vecstride;
1251 struct op *fop; 1198 struct op* fop;
1252 1199
1253 vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK); 1200 vecstride = 1 + ((fpscr & FPSCR_STRIDE_MASK) == FPSCR_STRIDE_MASK);
1254 1201
@@ -1274,11 +1221,11 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1274 else 1221 else
1275 veclen = fpscr & FPSCR_LENGTH_MASK; 1222 veclen = fpscr & FPSCR_LENGTH_MASK;
1276 1223
1277 LOG_TRACE(Core_ARM11, "vecstride=%u veclen=%u", vecstride, 1224 LOG_TRACE(Core_ARM11, "vecstride=%u veclen=%u", vecstride, (veclen >> FPSCR_LENGTH_BIT) + 1);
1278 (veclen >> FPSCR_LENGTH_BIT) + 1);
1279 1225
1280 if (!fop->fn) { 1226 if (!fop->fn) {
1281 LOG_CRITICAL(Core_ARM11, "could not find single op %d, inst=0x%x@0x%x", FEXT_TO_IDX(inst), inst, state->Reg[15]); 1227 LOG_CRITICAL(Core_ARM11, "could not find single op %d, inst=0x%x@0x%x", FEXT_TO_IDX(inst),
1228 inst, state->Reg[15]);
1282 Crash(); 1229 Crash();
1283 goto invalid; 1230 goto invalid;
1284 } 1231 }
@@ -1290,17 +1237,14 @@ u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr)
1290 1237
1291 type = (fop->flags & OP_DD) ? 'd' : 's'; 1238 type = (fop->flags & OP_DD) ? 'd' : 's';
1292 if (op == FOP_EXT) 1239 if (op == FOP_EXT)
1293 LOG_TRACE(Core_ARM11, "itr%d (%c%u) = op[%u] (s%u=%08x)", 1240 LOG_TRACE(Core_ARM11, "itr%d (%c%u) = op[%u] (s%u=%08x)", vecitr >> FPSCR_LENGTH_BIT,
1294 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, 1241 type, dest, sn, sm, m);
1295 sm, m);
1296 else 1242 else
1297 LOG_TRACE(Core_ARM11, "itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)", 1243 LOG_TRACE(Core_ARM11, "itr%d (%c%u) = (s%u) op[%u] (s%u=%08x)",
1298 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, 1244 vecitr >> FPSCR_LENGTH_BIT, type, dest, sn, FOP_TO_IDX(op), sm, m);
1299 FOP_TO_IDX(op), sm, m);
1300 1245
1301 except = fop->fn(state, dest, sn, m, fpscr); 1246 except = fop->fn(state, dest, sn, m, fpscr);
1302 LOG_TRACE(Core_ARM11, "itr%d: exceptions=%08x", 1247 LOG_TRACE(Core_ARM11, "itr%d: exceptions=%08x", vecitr >> FPSCR_LENGTH_BIT, except);
1303 vecitr >> FPSCR_LENGTH_BIT, except);
1304 1248
1305 exceptions |= except; 1249 exceptions |= except;
1306 1250
diff --git a/src/core/core.cpp b/src/core/core.cpp
index a3834adae..4f9eca416 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -27,7 +27,8 @@ void RunLoop(int tight_loop) {
27 if (GDBStub::g_server_enabled) { 27 if (GDBStub::g_server_enabled) {
28 GDBStub::HandlePacket(); 28 GDBStub::HandlePacket();
29 29
30 // If the loop is halted and we want to step, use a tiny (1) number of instructions to execute. 30 // If the loop is halted and we want to step, use a tiny (1) number of instructions to
31 // execute.
31 // Otherwise get out of the loop function. 32 // Otherwise get out of the loop function.
32 if (GDBStub::GetCpuHaltFlag()) { 33 if (GDBStub::GetCpuHaltFlag()) {
33 if (GDBStub::GetCpuStepFlag()) { 34 if (GDBStub::GetCpuStepFlag()) {
@@ -62,7 +63,7 @@ void SingleStep() {
62} 63}
63 64
64/// Halt the core 65/// Halt the core
65void Halt(const char *msg) { 66void Halt(const char* msg) {
66 // TODO(ShizZy): ImplementMe 67 // TODO(ShizZy): ImplementMe
67} 68}
68 69
diff --git a/src/core/core.h b/src/core/core.h
index ad26dca3f..ffbfa91c3 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -40,13 +40,13 @@ void Start();
40 * is not guaranteed to run, as this will be interrupted preemptively if a hardware update is 40 * is not guaranteed to run, as this will be interrupted preemptively if a hardware update is
41 * requested (e.g. on a thread switch). 41 * requested (e.g. on a thread switch).
42 */ 42 */
43void RunLoop(int tight_loop=1000); 43void RunLoop(int tight_loop = 1000);
44 44
45/// Step the CPU one instruction 45/// Step the CPU one instruction
46void SingleStep(); 46void SingleStep();
47 47
48/// Halt the core 48/// Halt the core
49void Halt(const char *msg); 49void Halt(const char* msg);
50 50
51/// Kill the core 51/// Kill the core
52void Stop(); 52void Stop();
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index aba22cdd1..b7b988cf1 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -21,14 +21,13 @@ int g_clock_rate_arm11 = 268123480;
21#define INITIAL_SLICE_LENGTH 20000 21#define INITIAL_SLICE_LENGTH 20000
22#define MAX_SLICE_LENGTH 100000000 22#define MAX_SLICE_LENGTH 100000000
23 23
24namespace CoreTiming 24namespace CoreTiming {
25{ 25struct EventType {
26struct EventType 26 EventType() {
27{ 27 }
28 EventType() {}
29 28
30 EventType(TimedCallback cb, const char* n) 29 EventType(TimedCallback cb, const char* n) : callback(cb), name(n) {
31 : callback(cb), name(n) {} 30 }
32 31
33 TimedCallback callback; 32 TimedCallback callback;
34 const char* name; 33 const char* name;
@@ -36,8 +35,7 @@ struct EventType
36 35
37static std::vector<EventType> event_types; 36static std::vector<EventType> event_types;
38 37
39struct BaseEvent 38struct BaseEvent {
40{
41 s64 time; 39 s64 time;
42 u64 userdata; 40 u64 userdata;
43 int type; 41 int type;
@@ -200,7 +198,6 @@ u64 GetIdleTicks() {
200 return (u64)idled_cycles; 198 return (u64)idled_cycles;
201} 199}
202 200
203
204// This is to be called when outside threads, such as the graphics thread, wants to 201// This is to be called when outside threads, such as the graphics thread, wants to
205// schedule things to be executed on the main thread. 202// schedule things to be executed on the main thread.
206void ScheduleEvent_Threadsafe(s64 cycles_into_future, int event_type, u64 userdata) { 203void ScheduleEvent_Threadsafe(s64 cycles_into_future, int event_type, u64 userdata) {
@@ -222,12 +219,11 @@ void ScheduleEvent_Threadsafe(s64 cycles_into_future, int event_type, u64 userda
222// Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread 219// Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread
223// in which case the event will get handled immediately, before returning. 220// in which case the event will get handled immediately, before returning.
224void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata) { 221void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata) {
225 if (false) //Core::IsCPUThread()) 222 if (false) // Core::IsCPUThread())
226 { 223 {
227 std::lock_guard<std::recursive_mutex> lock(external_event_section); 224 std::lock_guard<std::recursive_mutex> lock(external_event_section);
228 event_types[event_type].callback(userdata, 0); 225 event_types[event_type].callback(userdata, 0);
229 } 226 } else
230 else
231 ScheduleEvent_Threadsafe(0, event_type, userdata); 227 ScheduleEvent_Threadsafe(0, event_type, userdata);
232} 228}
233 229
@@ -317,8 +313,7 @@ s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata) {
317 } 313 }
318 } 314 }
319 315
320 if (!ts_first) 316 if (!ts_first) {
321 {
322 ts_last = nullptr; 317 ts_last = nullptr;
323 return result; 318 return result;
324 } 319 }
@@ -369,7 +364,7 @@ void RemoveEvent(int event_type) {
369 return; 364 return;
370 while (first) { 365 while (first) {
371 if (first->type == event_type) { 366 if (first->type == event_type) {
372 Event *next = first->next; 367 Event* next = first->next;
373 FreeEvent(first); 368 FreeEvent(first);
374 first = next; 369 first = next;
375 } else { 370 } else {
@@ -509,7 +504,8 @@ void Advance() {
509void LogPendingEvents() { 504void LogPendingEvents() {
510 Event* event = first; 505 Event* event = first;
511 while (event) { 506 while (event) {
512 //LOG_TRACE(Core_Timing, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer, next->time, next->type); 507 // LOG_TRACE(Core_Timing, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer,
508 // next->time, next->type);
513 event = event->next; 509 event = event->next;
514 } 510 }
515} 511}
@@ -531,7 +527,8 @@ void Idle(int max_idle) {
531 } 527 }
532 } 528 }
533 529
534 LOG_TRACE(Core_Timing, "Idle for %" PRId64 " cycles! (%f ms)", cycles_down, cycles_down / (float)(g_clock_rate_arm11 * 0.001f)); 530 LOG_TRACE(Core_Timing, "Idle for %" PRId64 " cycles! (%f ms)", cycles_down,
531 cycles_down / (float)(g_clock_rate_arm11 * 0.001f));
535 532
536 idled_cycles += cycles_down; 533 idled_cycles += cycles_down;
537 Core::g_app_core->down_count -= cycles_down; 534 Core::g_app_core->down_count -= cycles_down;
@@ -551,7 +548,7 @@ std::string GetScheduledEventsSummary() {
551 if (!name) 548 if (!name)
552 name = "[unknown]"; 549 name = "[unknown]";
553 text += Common::StringFromFormat("%s : %i %08x%08x\n", name, (int)event->time, 550 text += Common::StringFromFormat("%s : %i %08x%08x\n", name, (int)event->time,
554 (u32)(event->userdata >> 32), (u32)(event->userdata)); 551 (u32)(event->userdata >> 32), (u32)(event->userdata));
555 event = event->next; 552 event = event->next;
556 } 553 }
557 return text; 554 return text;
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 3d8a7d0c0..64fd8dcd0 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -61,12 +61,11 @@ inline u64 cyclesToMs(s64 cycles) {
61 return cycles / (g_clock_rate_arm11 / 1000); 61 return cycles / (g_clock_rate_arm11 / 1000);
62} 62}
63 63
64namespace CoreTiming 64namespace CoreTiming {
65{
66void Init(); 65void Init();
67void Shutdown(); 66void Shutdown();
68 67
69typedef void(*MHzChangeCallback)(); 68typedef void (*MHzChangeCallback)();
70typedef std::function<void(u64 userdata, int cycles_late)> TimedCallback; 69typedef std::function<void(u64 userdata, int cycles_late)> TimedCallback;
71 70
72u64 GetTicks(); 71u64 GetTicks();
@@ -81,7 +80,7 @@ u64 GetGlobalTimeUs();
81 */ 80 */
82int RegisterEvent(const char* name, TimedCallback callback); 81int RegisterEvent(const char* name, TimedCallback callback);
83/// For save states. 82/// For save states.
84void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback); 83void RestoreRegisterEvent(int event_type, const char* name, TimedCallback callback);
85void UnregisterAllEvents(); 84void UnregisterAllEvents();
86 85
87/// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk, 86/// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk,
@@ -128,7 +127,7 @@ void ClearPendingEvents();
128void LogPendingEvents(); 127void LogPendingEvents();
129 128
130/// Warning: not included in save states. 129/// Warning: not included in save states.
131void RegisterAdvanceCallback(void(*callback)(int cycles_executed)); 130void RegisterAdvanceCallback(void (*callback)(int cycles_executed));
132void RegisterMHzChangeCallback(MHzChangeCallback callback); 131void RegisterMHzChangeCallback(MHzChangeCallback callback);
133 132
134std::string GetScheduledEventsSummary(); 133std::string GetScheduledEventsSummary();
diff --git a/src/core/file_sys/archive_backend.cpp b/src/core/file_sys/archive_backend.cpp
index cc0aa7022..6ea920ec1 100644
--- a/src/core/file_sys/archive_backend.cpp
+++ b/src/core/file_sys/archive_backend.cpp
@@ -12,27 +12,23 @@
12#include "core/file_sys/archive_backend.h" 12#include "core/file_sys/archive_backend.h"
13#include "core/memory.h" 13#include "core/memory.h"
14 14
15
16namespace FileSys { 15namespace FileSys {
17 16
18Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) { 17Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) {
19 switch (type) { 18 switch (type) {
20 case Binary: 19 case Binary: {
21 {
22 binary.resize(size); 20 binary.resize(size);
23 Memory::ReadBlock(pointer, binary.data(), binary.size()); 21 Memory::ReadBlock(pointer, binary.data(), binary.size());
24 break; 22 break;
25 } 23 }
26 24
27 case Char: 25 case Char: {
28 {
29 string.resize(size - 1); // Data is always null-terminated. 26 string.resize(size - 1); // Data is always null-terminated.
30 Memory::ReadBlock(pointer, &string[0], string.size()); 27 Memory::ReadBlock(pointer, &string[0], string.size());
31 break; 28 break;
32 } 29 }
33 30
34 case Wchar: 31 case Wchar: {
35 {
36 u16str.resize(size / 2 - 1); // Data is always null-terminated. 32 u16str.resize(size / 2 - 1); // Data is always null-terminated.
37 Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t)); 33 Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t));
38 break; 34 break;
@@ -50,8 +46,7 @@ std::string Path::DebugStr() const {
50 return "[Invalid]"; 46 return "[Invalid]";
51 case Empty: 47 case Empty:
52 return "[Empty]"; 48 return "[Empty]";
53 case Binary: 49 case Binary: {
54 {
55 std::stringstream res; 50 std::stringstream res;
56 res << "[Binary: "; 51 res << "[Binary: ";
57 for (unsigned byte : binary) 52 for (unsigned byte : binary)
@@ -73,13 +68,13 @@ std::string Path::AsString() const {
73 case Wchar: 68 case Wchar:
74 return Common::UTF16ToUTF8(u16str); 69 return Common::UTF16ToUTF8(u16str);
75 case Empty: 70 case Empty:
76 return{}; 71 return {};
77 case Invalid: 72 case Invalid:
78 case Binary: 73 case Binary:
79 default: 74 default:
80 // TODO(yuriks): Add assert 75 // TODO(yuriks): Add assert
81 LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); 76 LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!");
82 return{}; 77 return {};
83 } 78 }
84} 79}
85 80
@@ -90,12 +85,12 @@ std::u16string Path::AsU16Str() const {
90 case Wchar: 85 case Wchar:
91 return u16str; 86 return u16str;
92 case Empty: 87 case Empty:
93 return{}; 88 return {};
94 case Invalid: 89 case Invalid:
95 case Binary: 90 case Binary:
96 // TODO(yuriks): Add assert 91 // TODO(yuriks): Add assert
97 LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!"); 92 LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!");
98 return{}; 93 return {};
99 } 94 }
100} 95}
101 96
@@ -105,25 +100,23 @@ std::vector<u8> Path::AsBinary() const {
105 return binary; 100 return binary;
106 case Char: 101 case Char:
107 return std::vector<u8>(string.begin(), string.end()); 102 return std::vector<u8>(string.begin(), string.end());
108 case Wchar: 103 case Wchar: {
109 {
110 // use two u8 for each character of u16str 104 // use two u8 for each character of u16str
111 std::vector<u8> to_return(u16str.size() * 2); 105 std::vector<u8> to_return(u16str.size() * 2);
112 for (size_t i = 0; i < u16str.size(); ++i) { 106 for (size_t i = 0; i < u16str.size(); ++i) {
113 u16 tmp_char = u16str.at(i); 107 u16 tmp_char = u16str.at(i);
114 to_return[i*2] = (tmp_char & 0xFF00) >> 8; 108 to_return[i * 2] = (tmp_char & 0xFF00) >> 8;
115 to_return[i*2 + 1] = (tmp_char & 0x00FF); 109 to_return[i * 2 + 1] = (tmp_char & 0x00FF);
116 } 110 }
117 return to_return; 111 return to_return;
118 } 112 }
119 case Empty: 113 case Empty:
120 return{}; 114 return {};
121 case Invalid: 115 case Invalid:
122 default: 116 default:
123 // TODO(yuriks): Add assert 117 // TODO(yuriks): Add assert
124 LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); 118 LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!");
125 return{}; 119 return {};
126 } 120 }
127} 121}
128
129} 122}
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h
index 5d91e47f3..79fde9710 100644
--- a/src/core/file_sys/archive_backend.h
+++ b/src/core/file_sys/archive_backend.h
@@ -15,20 +15,13 @@
15 15
16#include "core/hle/result.h" 16#include "core/hle/result.h"
17 17
18
19namespace FileSys { 18namespace FileSys {
20 19
21class FileBackend; 20class FileBackend;
22class DirectoryBackend; 21class DirectoryBackend;
23 22
24// Path string type 23// Path string type
25enum LowPathType : u32 { 24enum LowPathType : u32 { Invalid = 0, Empty = 1, Binary = 2, Char = 3, Wchar = 4 };
26 Invalid = 0,
27 Empty = 1,
28 Binary = 2,
29 Char = 3,
30 Wchar = 4
31};
32 25
33union Mode { 26union Mode {
34 u32 hex; 27 u32 hex;
@@ -39,12 +32,17 @@ union Mode {
39 32
40class Path { 33class Path {
41public: 34public:
42 Path() : type(Invalid) {} 35 Path() : type(Invalid) {
43 Path(const char* path) : type(Char), string(path) {} 36 }
44 Path(std::vector<u8> binary_data) : type(Binary), binary(std::move(binary_data)) {} 37 Path(const char* path) : type(Char), string(path) {
38 }
39 Path(std::vector<u8> binary_data) : type(Binary), binary(std::move(binary_data)) {
40 }
45 Path(LowPathType type, u32 size, u32 pointer); 41 Path(LowPathType type, u32 size, u32 pointer);
46 42
47 LowPathType GetType() const { return type; } 43 LowPathType GetType() const {
44 return type;
45 }
48 46
49 /** 47 /**
50 * Gets the string representation of the path for debugging 48 * Gets the string representation of the path for debugging
@@ -64,10 +62,14 @@ private:
64}; 62};
65 63
66struct ArchiveFormatInfo { 64struct ArchiveFormatInfo {
67 u32_le total_size; ///< The pre-defined size of the archive, as specified in the Create or Format call 65 u32_le total_size; ///< The pre-defined size of the archive, as specified in the Create or
68 u32_le number_directories; ///< The pre-defined number of directories in the archive, as specified in the Create or Format call 66 /// Format call
69 u32_le number_files; ///< The pre-defined number of files in the archive, as specified in the Create or Format call 67 u32_le number_directories; ///< The pre-defined number of directories in the archive, as
70 u8 duplicate_data; ///< Whether the archive should duplicate the data, as specified in the Create or Format call 68 /// specified in the Create or Format call
69 u32_le number_files; ///< The pre-defined number of files in the archive, as specified in the
70 /// Create or Format call
71 u8 duplicate_data; ///< Whether the archive should duplicate the data, as specified in the
72 /// Create or Format call
71}; 73};
72static_assert(std::is_pod<ArchiveFormatInfo>::value, "ArchiveFormatInfo is not POD"); 74static_assert(std::is_pod<ArchiveFormatInfo>::value, "ArchiveFormatInfo is not POD");
73 75
@@ -87,7 +89,8 @@ public:
87 * @param mode Mode to open the file with 89 * @param mode Mode to open the file with
88 * @return Opened file, or error code 90 * @return Opened file, or error code
89 */ 91 */
90 virtual ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const = 0; 92 virtual ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path,
93 const Mode mode) const = 0;
91 94
92 /** 95 /**
93 * Delete a file specified by its path 96 * Delete a file specified by its path
diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp
index 1d9eaefcb..6b4af28bf 100644
--- a/src/core/file_sys/archive_extsavedata.cpp
+++ b/src/core/file_sys/archive_extsavedata.cpp
@@ -30,10 +30,11 @@ std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path)
30 30
31std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) { 31std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) {
32 if (shared) 32 if (shared)
33 return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(), SYSTEM_ID.c_str()); 33 return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(),
34 SYSTEM_ID.c_str());
34 35
35 return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(), 36 return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(),
36 SYSTEM_ID.c_str(), SDCARD_ID.c_str()); 37 SYSTEM_ID.c_str(), SDCARD_ID.c_str());
37} 38}
38 39
39Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) { 40Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) {
@@ -54,11 +55,12 @@ Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) {
54 for (unsigned i = 0; i < 4; ++i) 55 for (unsigned i = 0; i < 4; ++i)
55 binary_path.push_back((high >> (8 * i)) & 0xFF); 56 binary_path.push_back((high >> (8 * i)) & 0xFF);
56 57
57 return { binary_path }; 58 return {binary_path};
58} 59}
59 60
60ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, bool shared) 61ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location,
61 : shared(shared), mount_point(GetExtDataContainerPath(mount_location, shared)) { 62 bool shared)
63 : shared(shared), mount_point(GetExtDataContainerPath(mount_location, shared)) {
62 LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str()); 64 LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str());
63} 65}
64 66
@@ -88,7 +90,8 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons
88 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 90 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
89} 91}
90 92
91ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 93ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path,
94 const FileSys::ArchiveFormatInfo& format_info) {
92 // These folders are always created with the ExtSaveData 95 // These folders are always created with the ExtSaveData
93 std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/"; 96 std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/";
94 std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/"; 97 std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/";
@@ -115,7 +118,8 @@ ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Pat
115 if (!file.IsOpen()) { 118 if (!file.IsOpen()) {
116 LOG_ERROR(Service_FS, "Could not open metadata information for archive"); 119 LOG_ERROR(Service_FS, "Could not open metadata information for archive");
117 // TODO(Subv): Verify error code 120 // TODO(Subv): Verify error code
118 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); 121 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
122 ErrorSummary::InvalidState, ErrorLevel::Status);
119 } 123 }
120 124
121 ArchiveFormatInfo info = {}; 125 ArchiveFormatInfo info = {};
@@ -123,7 +127,8 @@ ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Pat
123 return MakeResult<ArchiveFormatInfo>(info); 127 return MakeResult<ArchiveFormatInfo>(info);
124} 128}
125 129
126void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data, size_t icon_size) { 130void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data,
131 size_t icon_size) {
127 std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path); 132 std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path);
128 FileUtil::IOFile icon_file(game_path + "icon", "wb"); 133 FileUtil::IOFile icon_file(game_path + "icon", "wb");
129 icon_file.WriteBytes(icon_data, icon_size); 134 icon_file.WriteBytes(icon_data, icon_size);
diff --git a/src/core/file_sys/archive_extsavedata.h b/src/core/file_sys/archive_extsavedata.h
index e9a72850d..2b942817e 100644
--- a/src/core/file_sys/archive_extsavedata.h
+++ b/src/core/file_sys/archive_extsavedata.h
@@ -28,13 +28,17 @@ public:
28 */ 28 */
29 bool Initialize(); 29 bool Initialize();
30 30
31 std::string GetName() const override { return "ExtSaveData"; } 31 std::string GetName() const override {
32 return "ExtSaveData";
33 }
32 34
33 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; 35 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
34 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 36 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
35 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; 37 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
36 38
37 const std::string& GetMountPoint() const { return mount_point; } 39 const std::string& GetMountPoint() const {
40 return mount_point;
41 }
38 42
39 /** 43 /**
40 * Writes the SMDH icon of the ExtSaveData to file 44 * Writes the SMDH icon of the ExtSaveData to file
@@ -45,7 +49,8 @@ public:
45 void WriteIcon(const Path& path, const u8* icon_data, size_t icon_size); 49 void WriteIcon(const Path& path, const u8* icon_data, size_t icon_size);
46 50
47private: 51private:
48 bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData archive 52 bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData
53 /// archive
49 54
50 /** 55 /**
51 * This holds the full directory path for this archive, it is only set after a successful call 56 * This holds the full directory path for this archive, it is only set after a successful call
@@ -65,7 +70,8 @@ private:
65std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path); 70std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path);
66 71
67/** 72/**
68 * Constructs a path to the base folder to hold concrete ExtSaveData archives in the host file system. 73 * Constructs a path to the base folder to hold concrete ExtSaveData archives in the host file
74 * system.
69 * @param mount_point The base folder where this folder resides, ie. SDMC or NAND. 75 * @param mount_point The base folder where this folder resides, ie. SDMC or NAND.
70 * @param shared Whether this ExtSaveData container is for SharedExtSaveDatas or not. 76 * @param shared Whether this ExtSaveData container is for SharedExtSaveDatas or not.
71 * @returns The path to the base ExtSaveData archives' folder in the host file system 77 * @returns The path to the base ExtSaveData archives' folder in the host file system
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp
index 38828b546..87455eb95 100644
--- a/src/core/file_sys/archive_romfs.cpp
+++ b/src/core/file_sys/archive_romfs.cpp
@@ -28,11 +28,12 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_RomFS::Open(const Path
28 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 28 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
29} 29}
30 30
31ResultCode ArchiveFactory_RomFS::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 31ResultCode ArchiveFactory_RomFS::Format(const Path& path,
32 const FileSys::ArchiveFormatInfo& format_info) {
32 LOG_ERROR(Service_FS, "Attempted to format a RomFS archive."); 33 LOG_ERROR(Service_FS, "Attempted to format a RomFS archive.");
33 // TODO: Verify error code 34 // TODO: Verify error code
34 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, 35 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported,
35 ErrorSummary::NotSupported, ErrorLevel::Permanent); 36 ErrorLevel::Permanent);
36} 37}
37 38
38ResultVal<ArchiveFormatInfo> ArchiveFactory_RomFS::GetFormatInfo(const Path& path) const { 39ResultVal<ArchiveFormatInfo> ArchiveFactory_RomFS::GetFormatInfo(const Path& path) const {
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h
index c5a329122..3c68a6b1c 100644
--- a/src/core/file_sys/archive_romfs.h
+++ b/src/core/file_sys/archive_romfs.h
@@ -24,7 +24,9 @@ class ArchiveFactory_RomFS final : public ArchiveFactory {
24public: 24public:
25 ArchiveFactory_RomFS(Loader::AppLoader& app_loader); 25 ArchiveFactory_RomFS(Loader::AppLoader& app_loader);
26 26
27 std::string GetName() const override { return "RomFS"; } 27 std::string GetName() const override {
28 return "RomFS";
29 }
28 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; 30 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
29 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 31 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
30 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; 32 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp
index fd5711e14..9a264091f 100644
--- a/src/core/file_sys/archive_savedata.cpp
+++ b/src/core/file_sys/archive_savedata.cpp
@@ -22,48 +22,55 @@ namespace FileSys {
22 22
23static std::string GetSaveDataContainerPath(const std::string& sdmc_directory) { 23static std::string GetSaveDataContainerPath(const std::string& sdmc_directory) {
24 return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(), 24 return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(),
25 SYSTEM_ID.c_str(), SDCARD_ID.c_str()); 25 SYSTEM_ID.c_str(), SDCARD_ID.c_str());
26} 26}
27 27
28static std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) { 28static std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) {
29 u32 high = (u32)(program_id >> 32); 29 u32 high = (u32)(program_id >> 32);
30 u32 low = (u32)(program_id & 0xFFFFFFFF); 30 u32 low = (u32)(program_id & 0xFFFFFFFF);
31 return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, low); 31 return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high,
32 low);
32} 33}
33 34
34static std::string GetSaveDataMetadataPath(const std::string& mount_location, u64 program_id) { 35static std::string GetSaveDataMetadataPath(const std::string& mount_location, u64 program_id) {
35 u32 high = (u32)(program_id >> 32); 36 u32 high = (u32)(program_id >> 32);
36 u32 low = (u32)(program_id & 0xFFFFFFFF); 37 u32 low = (u32)(program_id & 0xFFFFFFFF);
37 return Common::StringFromFormat("%s%08x/%08x/data/00000001.metadata", mount_location.c_str(), high, low); 38 return Common::StringFromFormat("%s%08x/%08x/data/00000001.metadata", mount_location.c_str(),
39 high, low);
38} 40}
39 41
40ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory) 42ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory)
41 : mount_point(GetSaveDataContainerPath(sdmc_directory)) { 43 : mount_point(GetSaveDataContainerPath(sdmc_directory)) {
42 LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str()); 44 LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str());
43} 45}
44 46
45ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { 47ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) {
46 std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); 48 std::string concrete_mount_point =
49 GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id);
47 if (!FileUtil::Exists(concrete_mount_point)) { 50 if (!FileUtil::Exists(concrete_mount_point)) {
48 // When a SaveData archive is created for the first time, it is not yet formatted 51 // When a SaveData archive is created for the first time, it is not yet formatted
49 // and the save file/directory structure expected by the game has not yet been initialized. 52 // and the save file/directory structure expected by the game has not yet been initialized.
50 // Returning the NotFormatted error code will signal the game to provision the SaveData archive 53 // Returning the NotFormatted error code will signal the game to provision the SaveData
54 // archive
51 // with the files and folders that it expects. 55 // with the files and folders that it expects.
52 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, 56 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
53 ErrorSummary::InvalidState, ErrorLevel::Status); 57 ErrorSummary::InvalidState, ErrorLevel::Status);
54 } 58 }
55 59
56 auto archive = std::make_unique<DiskArchive>(std::move(concrete_mount_point)); 60 auto archive = std::make_unique<DiskArchive>(std::move(concrete_mount_point));
57 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 61 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
58} 62}
59 63
60ResultCode ArchiveFactory_SaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 64ResultCode ArchiveFactory_SaveData::Format(const Path& path,
61 std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); 65 const FileSys::ArchiveFormatInfo& format_info) {
66 std::string concrete_mount_point =
67 GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id);
62 FileUtil::DeleteDirRecursively(concrete_mount_point); 68 FileUtil::DeleteDirRecursively(concrete_mount_point);
63 FileUtil::CreateFullPath(concrete_mount_point); 69 FileUtil::CreateFullPath(concrete_mount_point);
64 70
65 // Write the format metadata 71 // Write the format metadata
66 std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); 72 std::string metadata_path =
73 GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id);
67 FileUtil::IOFile file(metadata_path, "wb"); 74 FileUtil::IOFile file(metadata_path, "wb");
68 75
69 if (file.IsOpen()) { 76 if (file.IsOpen()) {
@@ -74,13 +81,15 @@ ResultCode ArchiveFactory_SaveData::Format(const Path& path, const FileSys::Arch
74} 81}
75 82
76ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const { 83ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const {
77 std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); 84 std::string metadata_path =
85 GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id);
78 FileUtil::IOFile file(metadata_path, "rb"); 86 FileUtil::IOFile file(metadata_path, "rb");
79 87
80 if (!file.IsOpen()) { 88 if (!file.IsOpen()) {
81 LOG_ERROR(Service_FS, "Could not open metadata information for archive"); 89 LOG_ERROR(Service_FS, "Could not open metadata information for archive");
82 // TODO(Subv): Verify error code 90 // TODO(Subv): Verify error code
83 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); 91 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
92 ErrorSummary::InvalidState, ErrorLevel::Status);
84 } 93 }
85 94
86 ArchiveFormatInfo info = {}; 95 ArchiveFormatInfo info = {};
diff --git a/src/core/file_sys/archive_savedata.h b/src/core/file_sys/archive_savedata.h
index 7a5a24089..4ac324985 100644
--- a/src/core/file_sys/archive_savedata.h
+++ b/src/core/file_sys/archive_savedata.h
@@ -20,7 +20,9 @@ class ArchiveFactory_SaveData final : public ArchiveFactory {
20public: 20public:
21 ArchiveFactory_SaveData(const std::string& mount_point); 21 ArchiveFactory_SaveData(const std::string& mount_point);
22 22
23 std::string GetName() const override { return "SaveData"; } 23 std::string GetName() const override {
24 return "SaveData";
25 }
24 26
25 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; 27 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
26 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 28 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
diff --git a/src/core/file_sys/archive_savedatacheck.cpp b/src/core/file_sys/archive_savedatacheck.cpp
index 9f65e5455..fd9b84302 100644
--- a/src/core/file_sys/archive_savedatacheck.cpp
+++ b/src/core/file_sys/archive_savedatacheck.cpp
@@ -25,12 +25,12 @@ static std::string GetSaveDataCheckContainerPath(const std::string& nand_directo
25} 25}
26 26
27static std::string GetSaveDataCheckPath(const std::string& mount_point, u32 high, u32 low) { 27static std::string GetSaveDataCheckPath(const std::string& mount_point, u32 high, u32 low) {
28 return Common::StringFromFormat("%s%08x/%08x/content/00000000.app.romfs", 28 return Common::StringFromFormat("%s%08x/%08x/content/00000000.app.romfs", mount_point.c_str(),
29 mount_point.c_str(), high, low); 29 high, low);
30} 30}
31 31
32ArchiveFactory_SaveDataCheck::ArchiveFactory_SaveDataCheck(const std::string& nand_directory) : 32ArchiveFactory_SaveDataCheck::ArchiveFactory_SaveDataCheck(const std::string& nand_directory)
33 mount_point(GetSaveDataCheckContainerPath(nand_directory)) { 33 : mount_point(GetSaveDataCheckContainerPath(nand_directory)) {
34} 34}
35 35
36ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(const Path& path) { 36ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(const Path& path) {
@@ -48,11 +48,12 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(co
48 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 48 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
49} 49}
50 50
51ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 51ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path,
52 const FileSys::ArchiveFormatInfo& format_info) {
52 LOG_ERROR(Service_FS, "Attempted to format a SaveDataCheck archive."); 53 LOG_ERROR(Service_FS, "Attempted to format a SaveDataCheck archive.");
53 // TODO: Verify error code 54 // TODO: Verify error code
54 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, 55 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported,
55 ErrorSummary::NotSupported, ErrorLevel::Permanent); 56 ErrorLevel::Permanent);
56} 57}
57 58
58ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveDataCheck::GetFormatInfo(const Path& path) const { 59ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveDataCheck::GetFormatInfo(const Path& path) const {
diff --git a/src/core/file_sys/archive_savedatacheck.h b/src/core/file_sys/archive_savedatacheck.h
index ea2624d64..4a4259260 100644
--- a/src/core/file_sys/archive_savedatacheck.h
+++ b/src/core/file_sys/archive_savedatacheck.h
@@ -20,7 +20,9 @@ class ArchiveFactory_SaveDataCheck final : public ArchiveFactory {
20public: 20public:
21 ArchiveFactory_SaveDataCheck(const std::string& mount_point); 21 ArchiveFactory_SaveDataCheck(const std::string& mount_point);
22 22
23 std::string GetName() const override { return "SaveDataCheck"; } 23 std::string GetName() const override {
24 return "SaveDataCheck";
25 }
24 26
25 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; 27 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
26 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 28 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
index 9b218af58..c1a28df6c 100644
--- a/src/core/file_sys/archive_sdmc.cpp
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -17,7 +17,8 @@
17 17
18namespace FileSys { 18namespace FileSys {
19 19
20ArchiveFactory_SDMC::ArchiveFactory_SDMC(const std::string& sdmc_directory) : sdmc_directory(sdmc_directory) { 20ArchiveFactory_SDMC::ArchiveFactory_SDMC(const std::string& sdmc_directory)
21 : sdmc_directory(sdmc_directory) {
21 LOG_INFO(Service_FS, "Directory %s set as SDMC.", sdmc_directory.c_str()); 22 LOG_INFO(Service_FS, "Directory %s set as SDMC.", sdmc_directory.c_str());
22} 23}
23 24
@@ -40,7 +41,8 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path&
40 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 41 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
41} 42}
42 43
43ResultCode ArchiveFactory_SDMC::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 44ResultCode ArchiveFactory_SDMC::Format(const Path& path,
45 const FileSys::ArchiveFormatInfo& format_info) {
44 // This is kind of an undesirable operation, so let's just ignore it. :) 46 // This is kind of an undesirable operation, so let's just ignore it. :)
45 return RESULT_SUCCESS; 47 return RESULT_SUCCESS;
46} 48}
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h
index 35c0f3725..2523c3979 100644
--- a/src/core/file_sys/archive_sdmc.h
+++ b/src/core/file_sys/archive_sdmc.h
@@ -26,7 +26,9 @@ public:
26 */ 26 */
27 bool Initialize(); 27 bool Initialize();
28 28
29 std::string GetName() const override { return "SDMC"; } 29 std::string GetName() const override {
30 return "SDMC";
31 }
30 32
31 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; 33 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
32 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 34 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
diff --git a/src/core/file_sys/archive_systemsavedata.cpp b/src/core/file_sys/archive_systemsavedata.cpp
index 1bcc228a1..1fb858247 100644
--- a/src/core/file_sys/archive_systemsavedata.cpp
+++ b/src/core/file_sys/archive_systemsavedata.cpp
@@ -45,11 +45,11 @@ Path ConstructSystemSaveDataBinaryPath(u32 high, u32 low) {
45 for (unsigned i = 0; i < 4; ++i) 45 for (unsigned i = 0; i < 4; ++i)
46 binary_path.push_back((low >> (8 * i)) & 0xFF); 46 binary_path.push_back((low >> (8 * i)) & 0xFF);
47 47
48 return { binary_path }; 48 return {binary_path};
49} 49}
50 50
51ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path) 51ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path)
52 : base_path(GetSystemSaveDataContainerPath(nand_path)) { 52 : base_path(GetSystemSaveDataContainerPath(nand_path)) {
53} 53}
54 54
55ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path) { 55ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path) {
@@ -57,13 +57,14 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(c
57 if (!FileUtil::Exists(fullpath)) { 57 if (!FileUtil::Exists(fullpath)) {
58 // TODO(Subv): Check error code, this one is probably wrong 58 // TODO(Subv): Check error code, this one is probably wrong
59 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, 59 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
60 ErrorSummary::InvalidState, ErrorLevel::Status); 60 ErrorSummary::InvalidState, ErrorLevel::Status);
61 } 61 }
62 auto archive = std::make_unique<DiskArchive>(fullpath); 62 auto archive = std::make_unique<DiskArchive>(fullpath);
63 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 63 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
64} 64}
65 65
66ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 66ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path,
67 const FileSys::ArchiveFormatInfo& format_info) {
67 std::string fullpath = GetSystemSaveDataPath(base_path, path); 68 std::string fullpath = GetSystemSaveDataPath(base_path, path);
68 FileUtil::DeleteDirRecursively(fullpath); 69 FileUtil::DeleteDirRecursively(fullpath);
69 FileUtil::CreateFullPath(fullpath); 70 FileUtil::CreateFullPath(fullpath);
diff --git a/src/core/file_sys/archive_systemsavedata.h b/src/core/file_sys/archive_systemsavedata.h
index 2bc13d4ee..61a002a7d 100644
--- a/src/core/file_sys/archive_systemsavedata.h
+++ b/src/core/file_sys/archive_systemsavedata.h
@@ -26,7 +26,9 @@ public:
26 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 26 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
27 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; 27 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
28 28
29 std::string GetName() const override { return "SystemSaveData"; } 29 std::string GetName() const override {
30 return "SystemSaveData";
31 }
30 32
31private: 33private:
32 std::string base_path; 34 std::string base_path;
@@ -42,7 +44,8 @@ private:
42std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& path); 44std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& path);
43 45
44/** 46/**
45 * Constructs a path to the base folder to hold concrete SystemSaveData archives in the host file system. 47 * Constructs a path to the base folder to hold concrete SystemSaveData archives in the host file
48 * system.
46 * @param mount_point The base folder where this folder resides, ie. SDMC or NAND. 49 * @param mount_point The base folder where this folder resides, ie. SDMC or NAND.
47 * @returns The path to the base SystemSaveData archives' folder in the host file system 50 * @returns The path to the base SystemSaveData archives' folder in the host file system
48 */ 51 */
diff --git a/src/core/file_sys/directory_backend.h b/src/core/file_sys/directory_backend.h
index a25dc0cfa..c402ee60b 100644
--- a/src/core/file_sys/directory_backend.h
+++ b/src/core/file_sys/directory_backend.h
@@ -19,15 +19,16 @@ const size_t FILENAME_LENGTH = 0x20C / 2;
19struct Entry { 19struct Entry {
20 char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) 20 char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated)
21 std::array<char, 9> short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated) 21 std::array<char, 9> short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated)
22 char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) 22 char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD)
23 std::array<char, 4> extension; // 8.3 file extension (set to spaces for directories, null-terminated) 23 std::array<char, 4>
24 char unknown2; // unknown (always 0x01) 24 extension; // 8.3 file extension (set to spaces for directories, null-terminated)
25 char unknown3; // unknown (0x00 or 0x08) 25 char unknown2; // unknown (always 0x01)
26 char unknown3; // unknown (0x00 or 0x08)
26 char is_directory; // directory flag 27 char is_directory; // directory flag
27 char is_hidden; // hidden flag 28 char is_hidden; // hidden flag
28 char is_archive; // archive flag 29 char is_archive; // archive flag
29 char is_read_only; // read-only flag 30 char is_read_only; // read-only flag
30 u64 file_size; // file size (for files only) 31 u64 file_size; // file size (for files only)
31}; 32};
32static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); 33static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!");
33static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry."); 34static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry.");
@@ -37,8 +38,10 @@ static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size i
37 38
38class DirectoryBackend : NonCopyable { 39class DirectoryBackend : NonCopyable {
39public: 40public:
40 DirectoryBackend() { } 41 DirectoryBackend() {
41 virtual ~DirectoryBackend() { } 42 }
43 virtual ~DirectoryBackend() {
44 }
42 45
43 /** 46 /**
44 * Open the directory 47 * Open the directory
diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp
index 489cc96fb..c084303c1 100644
--- a/src/core/file_sys/disk_archive.cpp
+++ b/src/core/file_sys/disk_archive.cpp
@@ -17,7 +17,8 @@
17 17
18namespace FileSys { 18namespace FileSys {
19 19
20ResultVal<std::unique_ptr<FileBackend>> DiskArchive::OpenFile(const Path& path, const Mode mode) const { 20ResultVal<std::unique_ptr<FileBackend>> DiskArchive::OpenFile(const Path& path,
21 const Mode mode) const {
21 LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex); 22 LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex);
22 auto file = std::make_unique<DiskFile>(*this, path, mode); 23 auto file = std::make_unique<DiskFile>(*this, path, mode);
23 ResultCode result = file->Open(); 24 ResultCode result = file->Open();
@@ -30,15 +31,18 @@ ResultCode DiskArchive::DeleteFile(const Path& path) const {
30 std::string file_path = mount_point + path.AsString(); 31 std::string file_path = mount_point + path.AsString();
31 32
32 if (FileUtil::IsDirectory(file_path)) 33 if (FileUtil::IsDirectory(file_path))
33 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 34 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled,
35 ErrorLevel::Status);
34 36
35 if (!FileUtil::Exists(file_path)) 37 if (!FileUtil::Exists(file_path))
36 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status); 38 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
39 ErrorLevel::Status);
37 40
38 if (FileUtil::Delete(file_path)) 41 if (FileUtil::Delete(file_path))
39 return RESULT_SUCCESS; 42 return RESULT_SUCCESS;
40 43
41 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 44 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled,
45 ErrorLevel::Status);
42} 46}
43 47
44bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const { 48bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const {
@@ -53,10 +57,12 @@ ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u64 size) const {
53 std::string full_path = mount_point + path.AsString(); 57 std::string full_path = mount_point + path.AsString();
54 58
55 if (FileUtil::IsDirectory(full_path)) 59 if (FileUtil::IsDirectory(full_path))
56 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 60 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled,
61 ErrorLevel::Status);
57 62
58 if (FileUtil::Exists(full_path)) 63 if (FileUtil::Exists(full_path))
59 return ResultCode(ErrorDescription::FS_AlreadyExists, ErrorModule::FS, ErrorSummary::NothingHappened, ErrorLevel::Status); 64 return ResultCode(ErrorDescription::FS_AlreadyExists, ErrorModule::FS,
65 ErrorSummary::NothingHappened, ErrorLevel::Status);
60 66
61 if (size == 0) { 67 if (size == 0) {
62 FileUtil::CreateEmptyFile(full_path); 68 FileUtil::CreateEmptyFile(full_path);
@@ -69,10 +75,10 @@ ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u64 size) const {
69 if (file.Seek(size - 1, SEEK_SET) && file.WriteBytes("", 1) == 1) 75 if (file.Seek(size - 1, SEEK_SET) && file.WriteBytes("", 1) == 1)
70 return RESULT_SUCCESS; 76 return RESULT_SUCCESS;
71 77
72 return ResultCode(ErrorDescription::TooLarge, ErrorModule::FS, ErrorSummary::OutOfResource, ErrorLevel::Info); 78 return ResultCode(ErrorDescription::TooLarge, ErrorModule::FS, ErrorSummary::OutOfResource,
79 ErrorLevel::Info);
73} 80}
74 81
75
76bool DiskArchive::CreateDirectory(const Path& path) const { 82bool DiskArchive::CreateDirectory(const Path& path) const {
77 return FileUtil::CreateDir(mount_point + path.AsString()); 83 return FileUtil::CreateDir(mount_point + path.AsString());
78} 84}
@@ -106,17 +112,21 @@ DiskFile::DiskFile(const DiskArchive& archive, const Path& path, const Mode mode
106 112
107ResultCode DiskFile::Open() { 113ResultCode DiskFile::Open() {
108 if (FileUtil::IsDirectory(path)) 114 if (FileUtil::IsDirectory(path))
109 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 115 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled,
116 ErrorLevel::Status);
110 117
111 // Specifying only the Create flag is invalid 118 // Specifying only the Create flag is invalid
112 if (mode.create_flag && !mode.read_flag && !mode.write_flag) { 119 if (mode.create_flag && !mode.read_flag && !mode.write_flag) {
113 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 120 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS,
121 ErrorSummary::Canceled, ErrorLevel::Status);
114 } 122 }
115 123
116 if (!FileUtil::Exists(path)) { 124 if (!FileUtil::Exists(path)) {
117 if (!mode.create_flag) { 125 if (!mode.create_flag) {
118 LOG_ERROR(Service_FS, "Non-existing file %s can't be open without mode create.", path.c_str()); 126 LOG_ERROR(Service_FS, "Non-existing file %s can't be open without mode create.",
119 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status); 127 path.c_str());
128 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS,
129 ErrorSummary::NotFound, ErrorLevel::Status);
120 } else { 130 } else {
121 // Create the file 131 // Create the file
122 FileUtil::CreateEmptyFile(path); 132 FileUtil::CreateEmptyFile(path);
@@ -135,20 +145,24 @@ ResultCode DiskFile::Open() {
135 file = std::make_unique<FileUtil::IOFile>(path, mode_string.c_str()); 145 file = std::make_unique<FileUtil::IOFile>(path, mode_string.c_str());
136 if (file->IsOpen()) 146 if (file->IsOpen())
137 return RESULT_SUCCESS; 147 return RESULT_SUCCESS;
138 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status); 148 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
149 ErrorLevel::Status);
139} 150}
140 151
141ResultVal<size_t> DiskFile::Read(const u64 offset, const size_t length, u8* buffer) const { 152ResultVal<size_t> DiskFile::Read(const u64 offset, const size_t length, u8* buffer) const {
142 if (!mode.read_flag && !mode.write_flag) 153 if (!mode.read_flag && !mode.write_flag)
143 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 154 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS,
155 ErrorSummary::Canceled, ErrorLevel::Status);
144 156
145 file->Seek(offset, SEEK_SET); 157 file->Seek(offset, SEEK_SET);
146 return MakeResult<size_t>(file->ReadBytes(buffer, length)); 158 return MakeResult<size_t>(file->ReadBytes(buffer, length));
147} 159}
148 160
149ResultVal<size_t> DiskFile::Write(const u64 offset, const size_t length, const bool flush, const u8* buffer) const { 161ResultVal<size_t> DiskFile::Write(const u64 offset, const size_t length, const bool flush,
162 const u8* buffer) const {
150 if (!mode.write_flag) 163 if (!mode.write_flag)
151 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 164 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS,
165 ErrorSummary::Canceled, ErrorLevel::Status);
152 166
153 file->Seek(offset, SEEK_SET); 167 file->Seek(offset, SEEK_SET);
154 size_t written = file->WriteBytes(buffer, length); 168 size_t written = file->WriteBytes(buffer, length);
@@ -198,7 +212,8 @@ u32 DiskDirectory::Read(const u32 count, Entry* entries) {
198 const std::string& filename = file.virtualName; 212 const std::string& filename = file.virtualName;
199 Entry& entry = entries[entries_read]; 213 Entry& entry = entries[entries_read];
200 214
201 LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, file.isDirectory); 215 LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size,
216 file.isDirectory);
202 217
203 // TODO(Link Mauve): use a proper conversion to UTF-16. 218 // TODO(Link Mauve): use a proper conversion to UTF-16.
204 for (size_t j = 0; j < FILENAME_LENGTH; ++j) { 219 for (size_t j = 0; j < FILENAME_LENGTH; ++j) {
diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h
index b4cc2f702..3f620128f 100644
--- a/src/core/file_sys/disk_archive.h
+++ b/src/core/file_sys/disk_archive.h
@@ -29,11 +29,15 @@ namespace FileSys {
29 */ 29 */
30class DiskArchive : public ArchiveBackend { 30class DiskArchive : public ArchiveBackend {
31public: 31public:
32 DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) {} 32 DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) {
33 }
33 34
34 virtual std::string GetName() const override { return "DiskArchive: " + mount_point; } 35 virtual std::string GetName() const override {
36 return "DiskArchive: " + mount_point;
37 }
35 38
36 ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const override; 39 ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path,
40 const Mode mode) const override;
37 ResultCode DeleteFile(const Path& path) const override; 41 ResultCode DeleteFile(const Path& path) const override;
38 bool RenameFile(const Path& src_path, const Path& dest_path) const override; 42 bool RenameFile(const Path& src_path, const Path& dest_path) const override;
39 bool DeleteDirectory(const Path& path) const override; 43 bool DeleteDirectory(const Path& path) const override;
diff --git a/src/core/file_sys/file_backend.h b/src/core/file_sys/file_backend.h
index 9137bbbad..9eae697c2 100644
--- a/src/core/file_sys/file_backend.h
+++ b/src/core/file_sys/file_backend.h
@@ -16,8 +16,10 @@ namespace FileSys {
16 16
17class FileBackend : NonCopyable { 17class FileBackend : NonCopyable {
18public: 18public:
19 FileBackend() { } 19 FileBackend() {
20 virtual ~FileBackend() { } 20 }
21 virtual ~FileBackend() {
22 }
21 23
22 /** 24 /**
23 * Open the file 25 * Open the file
@@ -42,7 +44,8 @@ public:
42 * @param buffer Buffer to read data from 44 * @param buffer Buffer to read data from
43 * @return Number of bytes written, or error code 45 * @return Number of bytes written, or error code
44 */ 46 */
45 virtual ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const = 0; 47 virtual ResultVal<size_t> Write(u64 offset, size_t length, bool flush,
48 const u8* buffer) const = 0;
46 49
47 /** 50 /**
48 * Get the size of the file in bytes 51 * Get the size of the file in bytes
diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp
index c61791ef7..235a962e9 100644
--- a/src/core/file_sys/ivfc_archive.cpp
+++ b/src/core/file_sys/ivfc_archive.cpp
@@ -19,40 +19,49 @@ std::string IVFCArchive::GetName() const {
19 return "IVFC"; 19 return "IVFC";
20} 20}
21 21
22ResultVal<std::unique_ptr<FileBackend>> IVFCArchive::OpenFile(const Path& path, const Mode mode) const { 22ResultVal<std::unique_ptr<FileBackend>> IVFCArchive::OpenFile(const Path& path,
23 return MakeResult<std::unique_ptr<FileBackend>>(std::make_unique<IVFCFile>(romfs_file, data_offset, data_size)); 23 const Mode mode) const {
24 return MakeResult<std::unique_ptr<FileBackend>>(
25 std::make_unique<IVFCFile>(romfs_file, data_offset, data_size));
24} 26}
25 27
26ResultCode IVFCArchive::DeleteFile(const Path& path) const { 28ResultCode IVFCArchive::DeleteFile(const Path& path) const {
27 LOG_CRITICAL(Service_FS, "Attempted to delete a file from an IVFC archive (%s).", GetName().c_str()); 29 LOG_CRITICAL(Service_FS, "Attempted to delete a file from an IVFC archive (%s).",
30 GetName().c_str());
28 // TODO(Subv): Verify error code 31 // TODO(Subv): Verify error code
29 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, 32 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, ErrorSummary::Canceled,
30 ErrorSummary::Canceled, ErrorLevel::Status); 33 ErrorLevel::Status);
31} 34}
32 35
33bool IVFCArchive::RenameFile(const Path& src_path, const Path& dest_path) const { 36bool IVFCArchive::RenameFile(const Path& src_path, const Path& dest_path) const {
34 LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", GetName().c_str()); 37 LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).",
38 GetName().c_str());
35 return false; 39 return false;
36} 40}
37 41
38bool IVFCArchive::DeleteDirectory(const Path& path) const { 42bool IVFCArchive::DeleteDirectory(const Path& path) const {
39 LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive (%s).", GetName().c_str()); 43 LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive (%s).",
44 GetName().c_str());
40 return false; 45 return false;
41} 46}
42 47
43ResultCode IVFCArchive::CreateFile(const Path& path, u64 size) const { 48ResultCode IVFCArchive::CreateFile(const Path& path, u64 size) const {
44 LOG_CRITICAL(Service_FS, "Attempted to create a file in an IVFC archive (%s).", GetName().c_str()); 49 LOG_CRITICAL(Service_FS, "Attempted to create a file in an IVFC archive (%s).",
50 GetName().c_str());
45 // TODO: Verify error code 51 // TODO: Verify error code
46 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent); 52 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported,
53 ErrorLevel::Permanent);
47} 54}
48 55
49bool IVFCArchive::CreateDirectory(const Path& path) const { 56bool IVFCArchive::CreateDirectory(const Path& path) const {
50 LOG_CRITICAL(Service_FS, "Attempted to create a directory in an IVFC archive (%s).", GetName().c_str()); 57 LOG_CRITICAL(Service_FS, "Attempted to create a directory in an IVFC archive (%s).",
58 GetName().c_str());
51 return false; 59 return false;
52} 60}
53 61
54bool IVFCArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { 62bool IVFCArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const {
55 LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).", GetName().c_str()); 63 LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).",
64 GetName().c_str());
56 return false; 65 return false;
57} 66}
58 67
@@ -75,7 +84,8 @@ ResultVal<size_t> IVFCFile::Read(const u64 offset, const size_t length, u8* buff
75 return MakeResult<size_t>(romfs_file->ReadBytes(buffer, read_length)); 84 return MakeResult<size_t>(romfs_file->ReadBytes(buffer, read_length));
76} 85}
77 86
78ResultVal<size_t> IVFCFile::Write(const u64 offset, const size_t length, const bool flush, const u8* buffer) const { 87ResultVal<size_t> IVFCFile::Write(const u64 offset, const size_t length, const bool flush,
88 const u8* buffer) const {
79 LOG_ERROR(Service_FS, "Attempted to write to IVFC file"); 89 LOG_ERROR(Service_FS, "Attempted to write to IVFC file");
80 // TODO(Subv): Find error code 90 // TODO(Subv): Find error code
81 return MakeResult<size_t>(0); 91 return MakeResult<size_t>(0);
diff --git a/src/core/file_sys/ivfc_archive.h b/src/core/file_sys/ivfc_archive.h
index 19d32dcca..dab1958f6 100644
--- a/src/core/file_sys/ivfc_archive.h
+++ b/src/core/file_sys/ivfc_archive.h
@@ -30,11 +30,13 @@ namespace FileSys {
30class IVFCArchive : public ArchiveBackend { 30class IVFCArchive : public ArchiveBackend {
31public: 31public:
32 IVFCArchive(std::shared_ptr<FileUtil::IOFile> file, u64 offset, u64 size) 32 IVFCArchive(std::shared_ptr<FileUtil::IOFile> file, u64 offset, u64 size)
33 : romfs_file(file), data_offset(offset), data_size(size) {} 33 : romfs_file(file), data_offset(offset), data_size(size) {
34 }
34 35
35 std::string GetName() const override; 36 std::string GetName() const override;
36 37
37 ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const override; 38 ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path,
39 const Mode mode) const override;
38 ResultCode DeleteFile(const Path& path) const override; 40 ResultCode DeleteFile(const Path& path) const override;
39 bool RenameFile(const Path& src_path, const Path& dest_path) const override; 41 bool RenameFile(const Path& src_path, const Path& dest_path) const override;
40 bool DeleteDirectory(const Path& path) const override; 42 bool DeleteDirectory(const Path& path) const override;
@@ -53,15 +55,21 @@ protected:
53class IVFCFile : public FileBackend { 55class IVFCFile : public FileBackend {
54public: 56public:
55 IVFCFile(std::shared_ptr<FileUtil::IOFile> file, u64 offset, u64 size) 57 IVFCFile(std::shared_ptr<FileUtil::IOFile> file, u64 offset, u64 size)
56 : romfs_file(file), data_offset(offset), data_size(size) {} 58 : romfs_file(file), data_offset(offset), data_size(size) {
59 }
57 60
58 ResultCode Open() override { return RESULT_SUCCESS; } 61 ResultCode Open() override {
62 return RESULT_SUCCESS;
63 }
59 ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override; 64 ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override;
60 ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override; 65 ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override;
61 u64 GetSize() const override; 66 u64 GetSize() const override;
62 bool SetSize(u64 size) const override; 67 bool SetSize(u64 size) const override;
63 bool Close() const override { return false; } 68 bool Close() const override {
64 void Flush() const override { } 69 return false;
70 }
71 void Flush() const override {
72 }
65 73
66private: 74private:
67 std::shared_ptr<FileUtil::IOFile> romfs_file; 75 std::shared_ptr<FileUtil::IOFile> romfs_file;
@@ -71,9 +79,15 @@ private:
71 79
72class IVFCDirectory : public DirectoryBackend { 80class IVFCDirectory : public DirectoryBackend {
73public: 81public:
74 bool Open() override { return false; } 82 bool Open() override {
75 u32 Read(const u32 count, Entry* entries) override { return 0; } 83 return false;
76 bool Close() const override { return false; } 84 }
85 u32 Read(const u32 count, Entry* entries) override {
86 return 0;
87 }
88 bool Close() const override {
89 return false;
90 }
77}; 91};
78 92
79} // namespace FileSys 93} // namespace FileSys
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 28d403158..6d709bd15 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -16,25 +16,25 @@
16 16
17#ifdef _MSC_VER 17#ifdef _MSC_VER
18#include <WinSock2.h> 18#include <WinSock2.h>
19#include <ws2tcpip.h>
20#include <common/x64/abi.h> 19#include <common/x64/abi.h>
21#include <io.h> 20#include <io.h>
22#include <iphlpapi.h> 21#include <iphlpapi.h>
22#include <ws2tcpip.h>
23#define SHUT_RDWR 2 23#define SHUT_RDWR 2
24#else 24#else
25#include <unistd.h> 25#include <netinet/in.h>
26#include <sys/select.h> 26#include <sys/select.h>
27#include <sys/socket.h> 27#include <sys/socket.h>
28#include <sys/un.h> 28#include <sys/un.h>
29#include <netinet/in.h> 29#include <unistd.h>
30#endif 30#endif
31 31
32#include "common/logging/log.h" 32#include "common/logging/log.h"
33#include "common/string_util.h" 33#include "common/string_util.h"
34#include "core/core.h"
35#include "core/memory.h"
36#include "core/arm/arm_interface.h" 34#include "core/arm/arm_interface.h"
35#include "core/core.h"
37#include "core/gdbstub/gdbstub.h" 36#include "core/gdbstub/gdbstub.h"
37#include "core/memory.h"
38 38
39const int GDB_BUFFER_SIZE = 10000; 39const int GDB_BUFFER_SIZE = 10000;
40 40
@@ -64,7 +64,7 @@ const u32 FPSCR_REGISTER = 58;
64// GDB also wants the l character at the start 64// GDB also wants the l character at the start
65// This XML defines what the registers are for this specific ARM device 65// This XML defines what the registers are for this specific ARM device
66static const char* target_xml = 66static const char* target_xml =
67R"(l<?xml version="1.0"?> 67 R"(l<?xml version="1.0"?>
68<!DOCTYPE target SYSTEM "gdb-target.dtd"> 68<!DOCTYPE target SYSTEM "gdb-target.dtd">
69<target version="1.0"> 69<target version="1.0">
70 <feature name="org.gnu.gdb.arm.core"> 70 <feature name="org.gnu.gdb.arm.core">
@@ -297,7 +297,8 @@ static void RemoveBreakpoint(BreakpointType type, PAddr addr) {
297 297
298 auto bp = p.find(addr); 298 auto bp = p.find(addr);
299 if (bp != p.end()) { 299 if (bp != p.end()) {
300 LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: %08x bytes at %08x of type %d\n", bp->second.len, bp->second.addr, type); 300 LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: %08x bytes at %08x of type %d\n",
301 bp->second.len, bp->second.addr, type);
301 p.erase(addr); 302 p.erase(addr);
302 } 303 }
303} 304}
@@ -342,7 +343,9 @@ bool CheckBreakpoint(PAddr addr, BreakpointType type) {
342 } 343 }
343 344
344 if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) { 345 if (bp->second.active && (addr >= bp->second.addr && addr < bp->second.addr + len)) {
345 LOG_DEBUG(Debug_GDBStub, "Found breakpoint type %d @ %08x, range: %08x - %08x (%d bytes)\n", type, addr, bp->second.addr, bp->second.addr + len, len); 346 LOG_DEBUG(Debug_GDBStub,
347 "Found breakpoint type %d @ %08x, range: %08x - %08x (%d bytes)\n", type,
348 addr, bp->second.addr, bp->second.addr + len, len);
346 return true; 349 return true;
347 } 350 }
348 } 351 }
@@ -408,12 +411,13 @@ static void HandleQuery() {
408 411
409 const char* query = reinterpret_cast<const char*>(command_buffer + 1); 412 const char* query = reinterpret_cast<const char*>(command_buffer + 1);
410 413
411 if (strcmp(query, "TStatus") == 0 ) { 414 if (strcmp(query, "TStatus") == 0) {
412 SendReply("T0"); 415 SendReply("T0");
413 } else if (strncmp(query, "Supported:", strlen("Supported:")) == 0) { 416 } else if (strncmp(query, "Supported:", strlen("Supported:")) == 0) {
414 // PacketSize needs to be large enough for target xml 417 // PacketSize needs to be large enough for target xml
415 SendReply("PacketSize=800;qXfer:features:read+"); 418 SendReply("PacketSize=800;qXfer:features:read+");
416 } else if (strncmp(query, "Xfer:features:read:target.xml:", strlen("Xfer:features:read:target.xml:")) == 0) { 419 } else if (strncmp(query, "Xfer:features:read:target.xml:",
420 strlen("Xfer:features:read:target.xml:")) == 0) {
417 SendReply(target_xml); 421 SendReply(target_xml);
418 } else { 422 } else {
419 SendReply(""); 423 SendReply("");
@@ -422,10 +426,8 @@ static void HandleQuery() {
422 426
423/// Handle set thread command from gdb client. 427/// Handle set thread command from gdb client.
424static void HandleSetThread() { 428static void HandleSetThread() {
425 if (memcmp(command_buffer, "Hg0", 3) == 0 || 429 if (memcmp(command_buffer, "Hg0", 3) == 0 || memcmp(command_buffer, "Hc-1", 4) == 0 ||
426 memcmp(command_buffer, "Hc-1", 4) == 0 || 430 memcmp(command_buffer, "Hc0", 4) == 0 || memcmp(command_buffer, "Hc1", 4) == 0) {
427 memcmp(command_buffer, "Hc0", 4) == 0 ||
428 memcmp(command_buffer, "Hc1", 4) == 0) {
429 return SendReply("OK"); 431 return SendReply("OK");
430 } 432 }
431 433
@@ -444,7 +446,9 @@ static void SendSignal(u32 signal) {
444 446
445 latest_signal = signal; 447 latest_signal = signal;
446 448
447 std::string buffer = Common::StringFromFormat("T%02x%02x:%08x;%02x:%08x;", latest_signal, 15, htonl(Core::g_app_core->GetPC()), 13, htonl(Core::g_app_core->GetReg(13))); 449 std::string buffer = Common::StringFromFormat("T%02x%02x:%08x;%02x:%08x;", latest_signal, 15,
450 htonl(Core::g_app_core->GetPC()), 13,
451 htonl(Core::g_app_core->GetReg(13)));
448 LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str()); 452 LOG_DEBUG(Debug_GDBStub, "Response: %s", buffer.c_str());
449 SendReply(buffer.c_str()); 453 SendReply(buffer.c_str());
450} 454}
@@ -456,7 +460,7 @@ static void ReadCommand() {
456 460
457 u8 c = ReadByte(); 461 u8 c = ReadByte();
458 if (c == '+') { 462 if (c == '+') {
459 //ignore ack 463 // ignore ack
460 return; 464 return;
461 } else if (c == 0x03) { 465 } else if (c == 0x03) {
462 LOG_INFO(Debug_GDBStub, "gdb: found break command\n"); 466 LOG_INFO(Debug_GDBStub, "gdb: found break command\n");
@@ -483,8 +487,9 @@ static void ReadCommand() {
483 u8 checksum_calculated = CalculateChecksum(command_buffer, command_length); 487 u8 checksum_calculated = CalculateChecksum(command_buffer, command_length);
484 488
485 if (checksum_received != checksum_calculated) { 489 if (checksum_received != checksum_calculated) {
486 LOG_ERROR(Debug_GDBStub, "gdb: invalid checksum: calculated %02x and read %02x for $%s# (length: %d)\n", 490 LOG_ERROR(Debug_GDBStub,
487 checksum_calculated, checksum_received, command_buffer, command_length); 491 "gdb: invalid checksum: calculated %02x and read %02x for $%s# (length: %d)\n",
492 checksum_calculated, checksum_received, command_buffer, command_length);
488 493
489 command_length = 0; 494 command_length = 0;
490 495
@@ -534,7 +539,9 @@ static void ReadRegister() {
534 } else if (id == CPSR_REGISTER) { 539 } else if (id == CPSR_REGISTER) {
535 IntToGdbHex(reply, Core::g_app_core->GetCPSR()); 540 IntToGdbHex(reply, Core::g_app_core->GetCPSR());
536 } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) { 541 } else if (id > CPSR_REGISTER && id < FPSCR_REGISTER) {
537 IntToGdbHex(reply, Core::g_app_core->GetVFPReg(id - CPSR_REGISTER - 1)); // VFP registers should start at 26, so one after CSPR_REGISTER 542 IntToGdbHex(reply, Core::g_app_core->GetVFPReg(
543 id - CPSR_REGISTER -
544 1)); // VFP registers should start at 26, so one after CSPR_REGISTER
538 } else if (id == FPSCR_REGISTER) { 545 } else if (id == FPSCR_REGISTER) {
539 IntToGdbHex(reply, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR 546 IntToGdbHex(reply, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR)); // Get FPSCR
540 IntToGdbHex(reply + 8, 0); 547 IntToGdbHex(reply + 8, 0);
@@ -617,7 +624,8 @@ static void WriteRegisters() {
617 // Dummy FPA registers, ignore 624 // Dummy FPA registers, ignore
618 i += 2; 625 i += 2;
619 } else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) { 626 } else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) {
620 Core::g_app_core->SetVFPReg(reg - CPSR_REGISTER - 1, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); 627 Core::g_app_core->SetVFPReg(reg - CPSR_REGISTER - 1,
628 GdbHexToInt(buffer_ptr + i * CHAR_BIT));
621 i++; // Skip padding 629 i++; // Skip padding
622 } else if (reg == FPSCR_REGISTER) { 630 } else if (reg == FPSCR_REGISTER) {
623 Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT)); 631 Core::g_app_core->SetVFPSystemReg(VFP_FPSCR, GdbHexToInt(buffer_ptr + i * CHAR_BIT));
@@ -631,12 +639,13 @@ static void WriteRegisters() {
631static void ReadMemory() { 639static void ReadMemory() {
632 static u8 reply[GDB_BUFFER_SIZE - 4]; 640 static u8 reply[GDB_BUFFER_SIZE - 4];
633 641
634 auto start_offset = command_buffer+1; 642 auto start_offset = command_buffer + 1;
635 auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); 643 auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
636 PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); 644 PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset));
637 645
638 start_offset = addr_pos+1; 646 start_offset = addr_pos + 1;
639 u32 len = HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset)); 647 u32 len =
648 HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset));
640 649
641 LOG_DEBUG(Debug_GDBStub, "gdb: addr: %08x len: %08x\n", addr, len); 650 LOG_DEBUG(Debug_GDBStub, "gdb: addr: %08x len: %08x\n", addr, len);
642 651
@@ -656,12 +665,12 @@ static void ReadMemory() {
656 665
657/// Modify location in memory with data received from the gdb client. 666/// Modify location in memory with data received from the gdb client.
658static void WriteMemory() { 667static void WriteMemory() {
659 auto start_offset = command_buffer+1; 668 auto start_offset = command_buffer + 1;
660 auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); 669 auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
661 PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); 670 PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset));
662 671
663 start_offset = addr_pos+1; 672 start_offset = addr_pos + 1;
664 auto len_pos = std::find(start_offset, command_buffer+command_length, ':'); 673 auto len_pos = std::find(start_offset, command_buffer + command_length, ':');
665 u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset)); 674 u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset));
666 675
667 u8* dst = Memory::GetPointer(addr); 676 u8* dst = Memory::GetPointer(addr);
@@ -720,9 +729,10 @@ static bool CommitBreakpoint(BreakpointType type, PAddr addr, u32 len) {
720 breakpoint.active = true; 729 breakpoint.active = true;
721 breakpoint.addr = addr; 730 breakpoint.addr = addr;
722 breakpoint.len = len; 731 breakpoint.len = len;
723 p.insert({ addr, breakpoint }); 732 p.insert({addr, breakpoint});
724 733
725 LOG_DEBUG(Debug_GDBStub, "gdb: added %d breakpoint: %08x bytes at %08x\n", type, breakpoint.len, breakpoint.addr); 734 LOG_DEBUG(Debug_GDBStub, "gdb: added %d breakpoint: %08x bytes at %08x\n", type, breakpoint.len,
735 breakpoint.addr);
726 736
727 return true; 737 return true;
728} 738}
@@ -750,12 +760,13 @@ static void AddBreakpoint() {
750 return SendReply("E01"); 760 return SendReply("E01");
751 } 761 }
752 762
753 auto start_offset = command_buffer+3; 763 auto start_offset = command_buffer + 3;
754 auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); 764 auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
755 PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); 765 PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset));
756 766
757 start_offset = addr_pos+1; 767 start_offset = addr_pos + 1;
758 u32 len = HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset)); 768 u32 len =
769 HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset));
759 770
760 if (type == BreakpointType::Access) { 771 if (type == BreakpointType::Access) {
761 // Access is made up of Read and Write types, so add both breakpoints 772 // Access is made up of Read and Write types, so add both breakpoints
@@ -798,12 +809,13 @@ static void RemoveBreakpoint() {
798 return SendReply("E01"); 809 return SendReply("E01");
799 } 810 }
800 811
801 auto start_offset = command_buffer+3; 812 auto start_offset = command_buffer + 3;
802 auto addr_pos = std::find(start_offset, command_buffer+command_length, ','); 813 auto addr_pos = std::find(start_offset, command_buffer + command_length, ',');
803 PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); 814 PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset));
804 815
805 start_offset = addr_pos+1; 816 start_offset = addr_pos + 1;
806 u32 len = HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset)); 817 u32 len =
818 HexToInt(start_offset, static_cast<u32>((command_buffer + command_length) - start_offset));
807 819
808 if (type == BreakpointType::Access) { 820 if (type == BreakpointType::Access) {
809 // Access is made up of Read and Write types, so add both breakpoints 821 // Access is made up of Read and Write types, so add both breakpoints
@@ -896,8 +908,7 @@ void ToggleServer(bool status) {
896 if (!IsConnected() && Core::g_sys_core != nullptr) { 908 if (!IsConnected() && Core::g_sys_core != nullptr) {
897 Init(); 909 Init();
898 } 910 }
899 } 911 } else {
900 else {
901 // Stop server 912 // Stop server
902 if (IsConnected()) { 913 if (IsConnected()) {
903 Shutdown(); 914 Shutdown();
@@ -943,7 +954,8 @@ static void Init(u16 port) {
943 954
944 // Set socket to SO_REUSEADDR so it can always bind on the same port 955 // Set socket to SO_REUSEADDR so it can always bind on the same port
945 int reuse_enabled = 1; 956 int reuse_enabled = 1;
946 if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled, sizeof(reuse_enabled)) < 0) { 957 if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled,
958 sizeof(reuse_enabled)) < 0) {
947 LOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option"); 959 LOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option");
948 } 960 }
949 961
@@ -964,13 +976,13 @@ static void Init(u16 port) {
964 socklen_t client_addrlen = sizeof(saddr_client); 976 socklen_t client_addrlen = sizeof(saddr_client);
965 gdbserver_socket = accept(tmpsock, client_addr, &client_addrlen); 977 gdbserver_socket = accept(tmpsock, client_addr, &client_addrlen);
966 if (gdbserver_socket < 0) { 978 if (gdbserver_socket < 0) {
967 // In the case that we couldn't start the server for whatever reason, just start CPU execution like normal. 979 // In the case that we couldn't start the server for whatever reason, just start CPU
980 // execution like normal.
968 halt_loop = false; 981 halt_loop = false;
969 step_loop = false; 982 step_loop = false;
970 983
971 LOG_ERROR(Debug_GDBStub, "Failed to accept gdb client"); 984 LOG_ERROR(Debug_GDBStub, "Failed to accept gdb client");
972 } 985 } else {
973 else {
974 LOG_INFO(Debug_GDBStub, "Client connected.\n"); 986 LOG_INFO(Debug_GDBStub, "Client connected.\n");
975 saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr); 987 saddr_client.sin_addr.s_addr = ntohl(saddr_client.sin_addr.s_addr);
976 } 988 }
@@ -1018,5 +1030,4 @@ bool GetCpuStepFlag() {
1018void SetCpuStepFlag(bool is_step) { 1030void SetCpuStepFlag(bool is_step) {
1019 step_loop = is_step; 1031 step_loop = is_step;
1020} 1032}
1021
1022}; 1033};
diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h
index 4f21da23b..fddc27a3e 100644
--- a/src/core/gdbstub/gdbstub.h
+++ b/src/core/gdbstub/gdbstub.h
@@ -13,11 +13,11 @@ namespace GDBStub {
13 13
14/// Breakpoint Method 14/// Breakpoint Method
15enum class BreakpointType { 15enum class BreakpointType {
16 None, ///< None 16 None, ///< None
17 Execute, ///< Execution Breakpoint 17 Execute, ///< Execution Breakpoint
18 Read, ///< Read Breakpoint 18 Read, ///< Read Breakpoint
19 Write, ///< Write Breakpoint 19 Write, ///< Write Breakpoint
20 Access ///< Access (R/W) Breakpoint 20 Access ///< Access (R/W) Breakpoint
21}; 21};
22 22
23struct BreakpointAddress { 23struct BreakpointAddress {
@@ -25,7 +25,8 @@ struct BreakpointAddress {
25 BreakpointType type; 25 BreakpointType type;
26}; 26};
27 27
28/// If set to false, the server will never be started and no gdbstub-related functions will be executed. 28/// If set to false, the server will never be started and no gdbstub-related functions will be
29/// executed.
29extern std::atomic<bool> g_server_enabled; 30extern std::atomic<bool> g_server_enabled;
30 31
31/** 32/**
@@ -92,5 +93,4 @@ bool GetCpuStepFlag();
92 * @param is_step 93 * @param is_step
93 */ 94 */
94void SetCpuStepFlag(bool is_step); 95void SetCpuStepFlag(bool is_step);
95
96} 96}
diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp
index ccf35fa07..2b4bd939d 100644
--- a/src/core/hle/applets/applet.cpp
+++ b/src/core/hle/applets/applet.cpp
@@ -23,23 +23,24 @@
23// Specializes std::hash for AppletId, so that we can use it in std::unordered_map. 23// Specializes std::hash for AppletId, so that we can use it in std::unordered_map.
24// Workaround for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970 24// Workaround for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970
25namespace std { 25namespace std {
26 template <> 26template <>
27 struct hash<Service::APT::AppletId> { 27struct hash<Service::APT::AppletId> {
28 typedef Service::APT::AppletId argument_type; 28 typedef Service::APT::AppletId argument_type;
29 typedef std::size_t result_type; 29 typedef std::size_t result_type;
30 30
31 result_type operator()(const argument_type& id_code) const { 31 result_type operator()(const argument_type& id_code) const {
32 typedef std::underlying_type<argument_type>::type Type; 32 typedef std::underlying_type<argument_type>::type Type;
33 return std::hash<Type>()(static_cast<Type>(id_code)); 33 return std::hash<Type>()(static_cast<Type>(id_code));
34 } 34 }
35 }; 35};
36} 36}
37 37
38namespace HLE { 38namespace HLE {
39namespace Applets { 39namespace Applets {
40 40
41static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets; 41static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets;
42static u32 applet_update_event = -1; ///< The CoreTiming event identifier for the Applet update callback. 42static u32 applet_update_event =
43 -1; ///< The CoreTiming event identifier for the Applet update callback.
43/// The interval at which the Applet update callback will be called, 16.6ms 44/// The interval at which the Applet update callback will be called, 16.6ms
44static const u64 applet_update_interval_us = 16666; 45static const u64 applet_update_interval_us = 16666;
45 46
@@ -60,7 +61,8 @@ ResultCode Applet::Create(Service::APT::AppletId id) {
60 default: 61 default:
61 LOG_ERROR(Service_APT, "Could not create applet %u", id); 62 LOG_ERROR(Service_APT, "Could not create applet %u", id);
62 // TODO(Subv): Find the right error code 63 // TODO(Subv): Find the right error code
63 return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported, ErrorLevel::Permanent); 64 return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet,
65 ErrorSummary::NotSupported, ErrorLevel::Permanent);
64 } 66 }
65 67
66 return RESULT_SUCCESS; 68 return RESULT_SUCCESS;
@@ -84,7 +86,7 @@ static void AppletUpdateEvent(u64 applet_id, int cycles_late) {
84 // If the applet is still running after the last update, reschedule the event 86 // If the applet is still running after the last update, reschedule the event
85 if (applet->IsRunning()) { 87 if (applet->IsRunning()) {
86 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late, 88 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late,
87 applet_update_event, applet_id); 89 applet_update_event, applet_id);
88 } else { 90 } else {
89 // Otherwise the applet has terminated, in which case we should clean it up 91 // Otherwise the applet has terminated, in which case we should clean it up
90 applets[id] = nullptr; 92 applets[id] = nullptr;
@@ -96,7 +98,8 @@ ResultCode Applet::Start(const Service::APT::AppletStartupParameter& parameter)
96 if (result.IsError()) 98 if (result.IsError())
97 return result; 99 return result;
98 // Schedule the update event 100 // Schedule the update event
99 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event, static_cast<u64>(id)); 101 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event,
102 static_cast<u64>(id));
100 return result; 103 return result;
101} 104}
102 105
@@ -116,6 +119,5 @@ void Init() {
116void Shutdown() { 119void Shutdown() {
117 CoreTiming::RemoveEvent(applet_update_event); 120 CoreTiming::RemoveEvent(applet_update_event);
118} 121}
119
120} 122}
121} // namespace 123} // namespace
diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h
index 754c6f7db..350a58594 100644
--- a/src/core/hle/applets/applet.h
+++ b/src/core/hle/applets/applet.h
@@ -14,8 +14,10 @@ namespace Applets {
14 14
15class Applet { 15class Applet {
16public: 16public:
17 virtual ~Applet() { } 17 virtual ~Applet() {
18 Applet(Service::APT::AppletId id) : id(id) { } 18 }
19 Applet(Service::APT::AppletId id) : id(id) {
20 }
19 21
20 /** 22 /**
21 * Creates an instance of the Applet subclass identified by the parameter. 23 * Creates an instance of the Applet subclass identified by the parameter.
@@ -64,7 +66,7 @@ protected:
64 */ 66 */
65 virtual ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) = 0; 67 virtual ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) = 0;
66 68
67 Service::APT::AppletId id; ///< Id of this Applet 69 Service::APT::AppletId id; ///< Id of this Applet
68 std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet 70 std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet
69}; 71};
70 72
@@ -76,6 +78,5 @@ void Init();
76 78
77/// Shuts down the HLE applets 79/// Shuts down the HLE applets
78void Shutdown(); 80void Shutdown();
79
80} 81}
81} // namespace 82} // namespace
diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp
index 92a4b2323..144d6a152 100644
--- a/src/core/hle/applets/erreula.cpp
+++ b/src/core/hle/applets/erreula.cpp
@@ -18,7 +18,8 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param
18 return ResultCode(-1); 18 return ResultCode(-1);
19 } 19 }
20 20
21 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. 21 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared
22 // memory.
22 // Create the SharedMemory that will hold the framebuffer data 23 // Create the SharedMemory that will hold the framebuffer data
23 Service::APT::CaptureBufferInfo capture_info; 24 Service::APT::CaptureBufferInfo capture_info;
24 ASSERT(sizeof(capture_info) == parameter.buffer.size()); 25 ASSERT(sizeof(capture_info) == parameter.buffer.size());
@@ -30,9 +31,9 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param
30 // Allocate a heap block of the required size for this applet. 31 // Allocate a heap block of the required size for this applet.
31 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); 32 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
32 // Create a SharedMemory that directly points to this heap block. 33 // Create a SharedMemory that directly points to this heap block.
33 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), 34 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
34 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 35 heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite,
35 "ErrEula Memory"); 36 MemoryPermission::ReadWrite, "ErrEula Memory");
36 37
37 // Send the response message with the newly created SharedMemory 38 // Send the response message with the newly created SharedMemory
38 Service::APT::MessageParameter result; 39 Service::APT::MessageParameter result;
@@ -49,7 +50,8 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param
49ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) { 50ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
50 started = true; 51 started = true;
51 52
52 // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. 53 // TODO(Subv): Set the expected fields in the response buffer before resending it to the
54 // application.
53 // TODO(Subv): Reverse the parameter format for the ErrEula applet 55 // TODO(Subv): Reverse the parameter format for the ErrEula applet
54 56
55 // Let the application know that we're closing 57 // Let the application know that we're closing
diff --git a/src/core/hle/applets/erreula.h b/src/core/hle/applets/erreula.h
index 9fe72ae07..dd1d1aee4 100644
--- a/src/core/hle/applets/erreula.h
+++ b/src/core/hle/applets/erreula.h
@@ -12,16 +12,21 @@ namespace Applets {
12 12
13class ErrEula final : public Applet { 13class ErrEula final : public Applet {
14public: 14public:
15 explicit ErrEula(Service::APT::AppletId id): Applet(id) { } 15 explicit ErrEula(Service::APT::AppletId id) : Applet(id) {
16 }
16 17
17 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; 18 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
18 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; 19 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
19 void Update() override; 20 void Update() override;
20 bool IsRunning() const override { return started; } 21 bool IsRunning() const override {
22 return started;
23 }
21 24
22 /// This SharedMemory will be created when we receive the LibAppJustStarted message. 25 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
23 /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo 26 /// It holds the framebuffer info retrieved by the application with
27 /// GSPGPU::ImportDisplayCaptureInfo
24 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; 28 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
29
25private: 30private:
26 /// Whether this applet is currently running instead of the host application or not. 31 /// Whether this applet is currently running instead of the host application or not.
27 bool started = false; 32 bool started = false;
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
index 77f01d208..19e603eda 100644
--- a/src/core/hle/applets/mii_selector.cpp
+++ b/src/core/hle/applets/mii_selector.cpp
@@ -29,7 +29,8 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
29 return ResultCode(-1); 29 return ResultCode(-1);
30 } 30 }
31 31
32 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. 32 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared
33 // memory.
33 // Create the SharedMemory that will hold the framebuffer data 34 // Create the SharedMemory that will hold the framebuffer data
34 Service::APT::CaptureBufferInfo capture_info; 35 Service::APT::CaptureBufferInfo capture_info;
35 ASSERT(sizeof(capture_info) == parameter.buffer.size()); 36 ASSERT(sizeof(capture_info) == parameter.buffer.size());
@@ -40,9 +41,9 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
40 // Allocate a heap block of the required size for this applet. 41 // Allocate a heap block of the required size for this applet.
41 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); 42 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
42 // Create a SharedMemory that directly points to this heap block. 43 // Create a SharedMemory that directly points to this heap block.
43 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), 44 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
44 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 45 heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite,
45 "MiiSelector Memory"); 46 MemoryPermission::ReadWrite, "MiiSelector Memory");
46 47
47 // Send the response message with the newly created SharedMemory 48 // Send the response message with the newly created SharedMemory
48 Service::APT::MessageParameter result; 49 Service::APT::MessageParameter result;
@@ -59,12 +60,14 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
59ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) { 60ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
60 started = true; 61 started = true;
61 62
62 // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. 63 // TODO(Subv): Set the expected fields in the response buffer before resending it to the
64 // application.
63 // TODO(Subv): Reverse the parameter format for the Mii Selector 65 // TODO(Subv): Reverse the parameter format for the Mii Selector
64 66
65 memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); 67 memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
66 68
67 // TODO(Subv): Find more about this structure, result code 0 is enough to let most games continue. 69 // TODO(Subv): Find more about this structure, result code 0 is enough to let most games
70 // continue.
68 MiiResult result; 71 MiiResult result;
69 memset(&result, 0, sizeof(result)); 72 memset(&result, 0, sizeof(result));
70 result.result_code = 0; 73 result.result_code = 0;
@@ -84,6 +87,5 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa
84 87
85void MiiSelector::Update() { 88void MiiSelector::Update() {
86} 89}
87
88} 90}
89} // namespace 91} // namespace
diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h
index 24e8e721d..dba4abc8d 100644
--- a/src/core/hle/applets/mii_selector.h
+++ b/src/core/hle/applets/mii_selector.h
@@ -4,8 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h"
8#include "common/common_funcs.h" 7#include "common/common_funcs.h"
8#include "common/common_types.h"
9 9
10#include "core/hle/applets/applet.h" 10#include "core/hle/applets/applet.h"
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
@@ -17,28 +17,30 @@ namespace HLE {
17namespace Applets { 17namespace Applets {
18 18
19struct MiiConfig { 19struct MiiConfig {
20 u8 unk_000; 20 u8 unk_000;
21 u8 unk_001; 21 u8 unk_001;
22 u8 unk_002; 22 u8 unk_002;
23 u8 unk_003; 23 u8 unk_003;
24 u8 unk_004; 24 u8 unk_004;
25 INSERT_PADDING_BYTES(3); 25 INSERT_PADDING_BYTES(3);
26 u16 unk_008; 26 u16 unk_008;
27 INSERT_PADDING_BYTES(0x82); 27 INSERT_PADDING_BYTES(0x82);
28 u8 unk_08C; 28 u8 unk_08C;
29 INSERT_PADDING_BYTES(3); 29 INSERT_PADDING_BYTES(3);
30 u16 unk_090; 30 u16 unk_090;
31 INSERT_PADDING_BYTES(2); 31 INSERT_PADDING_BYTES(2);
32 u32 unk_094; 32 u32 unk_094;
33 u16 unk_098; 33 u16 unk_098;
34 u8 unk_09A[0x64]; 34 u8 unk_09A[0x64];
35 u8 unk_0FE; 35 u8 unk_0FE;
36 u8 unk_0FF; 36 u8 unk_0FF;
37 u32 unk_100; 37 u32 unk_100;
38}; 38};
39 39
40static_assert(sizeof(MiiConfig) == 0x104, "MiiConfig structure has incorrect size"); 40static_assert(sizeof(MiiConfig) == 0x104, "MiiConfig structure has incorrect size");
41#define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(MiiConfig, field_name) == position, "Field "#field_name" has invalid position") 41#define ASSERT_REG_POSITION(field_name, position) \
42 static_assert(offsetof(MiiConfig, field_name) == position, \
43 "Field " #field_name " has invalid position")
42ASSERT_REG_POSITION(unk_008, 0x08); 44ASSERT_REG_POSITION(unk_008, 0x08);
43ASSERT_REG_POSITION(unk_08C, 0x8C); 45ASSERT_REG_POSITION(unk_08C, 0x8C);
44ASSERT_REG_POSITION(unk_090, 0x90); 46ASSERT_REG_POSITION(unk_090, 0x90);
@@ -55,22 +57,28 @@ struct MiiResult {
55 INSERT_PADDING_BYTES(2); 57 INSERT_PADDING_BYTES(2);
56}; 58};
57static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size"); 59static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size");
58#define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(MiiResult, field_name) == position, "Field "#field_name" has invalid position") 60#define ASSERT_REG_POSITION(field_name, position) \
61 static_assert(offsetof(MiiResult, field_name) == position, \
62 "Field " #field_name " has invalid position")
59ASSERT_REG_POSITION(unk_0C, 0x0C); 63ASSERT_REG_POSITION(unk_0C, 0x0C);
60ASSERT_REG_POSITION(unk_6C, 0x6C); 64ASSERT_REG_POSITION(unk_6C, 0x6C);
61#undef ASSERT_REG_POSITION 65#undef ASSERT_REG_POSITION
62 66
63class MiiSelector final : public Applet { 67class MiiSelector final : public Applet {
64public: 68public:
65 MiiSelector(Service::APT::AppletId id) : Applet(id), started(false) { } 69 MiiSelector(Service::APT::AppletId id) : Applet(id), started(false) {
70 }
66 71
67 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; 72 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
68 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; 73 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
69 void Update() override; 74 void Update() override;
70 bool IsRunning() const override { return started; } 75 bool IsRunning() const override {
76 return started;
77 }
71 78
72 /// This SharedMemory will be created when we receive the LibAppJustStarted message. 79 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
73 /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo 80 /// It holds the framebuffer info retrieved by the application with
81 /// GSPGPU::ImportDisplayCaptureInfo
74 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; 82 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
75 83
76 /// Whether this applet is currently running instead of the host application or not. 84 /// Whether this applet is currently running instead of the host application or not.
@@ -78,6 +86,5 @@ public:
78 86
79 MiiConfig config; 87 MiiConfig config;
80}; 88};
81
82} 89}
83} // namespace 90} // namespace
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp
index d87bf3d57..cf2775968 100644
--- a/src/core/hle/applets/swkbd.cpp
+++ b/src/core/hle/applets/swkbd.cpp
@@ -12,9 +12,9 @@
12#include "core/hle/applets/swkbd.h" 12#include "core/hle/applets/swkbd.h"
13#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/shared_memory.h" 14#include "core/hle/kernel/shared_memory.h"
15#include "core/hle/service/hid/hid.h"
16#include "core/hle/service/gsp_gpu.h"
17#include "core/hle/result.h" 15#include "core/hle/result.h"
16#include "core/hle/service/gsp_gpu.h"
17#include "core/hle/service/hid/hid.h"
18#include "core/memory.h" 18#include "core/memory.h"
19 19
20#include "video_core/video_core.h" 20#include "video_core/video_core.h"
@@ -32,7 +32,8 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
32 return ResultCode(-1); 32 return ResultCode(-1);
33 } 33 }
34 34
35 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. 35 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared
36 // memory.
36 // Create the SharedMemory that will hold the framebuffer data 37 // Create the SharedMemory that will hold the framebuffer data
37 Service::APT::CaptureBufferInfo capture_info; 38 Service::APT::CaptureBufferInfo capture_info;
38 ASSERT(sizeof(capture_info) == parameter.buffer.size()); 39 ASSERT(sizeof(capture_info) == parameter.buffer.size());
@@ -43,9 +44,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
43 // Allocate a heap block of the required size for this applet. 44 // Allocate a heap block of the required size for this applet.
44 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); 45 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
45 // Create a SharedMemory that directly points to this heap block. 46 // Create a SharedMemory that directly points to this heap block.
46 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), 47 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
47 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 48 heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite,
48 "SoftwareKeyboard Memory"); 49 MemoryPermission::ReadWrite, "SoftwareKeyboard Memory");
49 50
50 // Send the response message with the newly created SharedMemory 51 // Send the response message with the newly created SharedMemory
51 Service::APT::MessageParameter result; 52 Service::APT::MessageParameter result;
@@ -60,10 +61,12 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
60} 61}
61 62
62ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { 63ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) {
63 ASSERT_MSG(parameter.buffer.size() == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); 64 ASSERT_MSG(parameter.buffer.size() == sizeof(config),
65 "The size of the parameter (SoftwareKeyboardConfig) is wrong");
64 66
65 memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); 67 memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
66 text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); 68 text_memory =
69 boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object);
67 70
68 // TODO(Subv): Verify if this is the correct behavior 71 // TODO(Subv): Verify if this is the correct behavior
69 memset(text_memory->GetPointer(), 0, text_memory->size); 72 memset(text_memory->GetPointer(), 0, text_memory->size);
@@ -115,6 +118,5 @@ void SoftwareKeyboard::Finalize() {
115 118
116 started = false; 119 started = false;
117} 120}
118
119} 121}
120} // namespace 122} // namespace
diff --git a/src/core/hle/applets/swkbd.h b/src/core/hle/applets/swkbd.h
index cf26a8fb7..f50673912 100644
--- a/src/core/hle/applets/swkbd.h
+++ b/src/core/hle/applets/swkbd.h
@@ -4,8 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h"
8#include "common/common_funcs.h" 7#include "common/common_funcs.h"
8#include "common/common_types.h"
9 9
10#include "core/hle/applets/applet.h" 10#include "core/hle/applets/applet.h"
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
@@ -53,12 +53,15 @@ static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config
53 53
54class SoftwareKeyboard final : public Applet { 54class SoftwareKeyboard final : public Applet {
55public: 55public:
56 SoftwareKeyboard(Service::APT::AppletId id) : Applet(id), started(false) { } 56 SoftwareKeyboard(Service::APT::AppletId id) : Applet(id), started(false) {
57 }
57 58
58 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; 59 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
59 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; 60 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
60 void Update() override; 61 void Update() override;
61 bool IsRunning() const override { return started; } 62 bool IsRunning() const override {
63 return started;
64 }
62 65
63 /** 66 /**
64 * Draws a keyboard to the current bottom screen framebuffer. 67 * Draws a keyboard to the current bottom screen framebuffer.
@@ -72,7 +75,8 @@ public:
72 void Finalize(); 75 void Finalize();
73 76
74 /// This SharedMemory will be created when we receive the LibAppJustStarted message. 77 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
75 /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo 78 /// It holds the framebuffer info retrieved by the application with
79 /// GSPGPU::ImportDisplayCaptureInfo
76 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; 80 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
77 81
78 /// SharedMemory where the output text will be stored 82 /// SharedMemory where the output text will be stored
@@ -84,6 +88,5 @@ public:
84 /// Whether this applet is currently running instead of the host application or not. 88 /// Whether this applet is currently running instead of the host application or not.
85 bool started; 89 bool started;
86}; 90};
87
88} 91}
89} // namespace 92} // namespace
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp
index ccd73cfcb..00efc179e 100644
--- a/src/core/hle/config_mem.cpp
+++ b/src/core/hle/config_mem.cpp
@@ -2,8 +2,8 @@
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 <cstring>
6#include "core/hle/config_mem.h" 5#include "core/hle/config_mem.h"
6#include <cstring>
7 7
8//////////////////////////////////////////////////////////////////////////////////////////////////// 8////////////////////////////////////////////////////////////////////////////////////////////////////
9 9
diff --git a/src/core/hle/config_mem.h b/src/core/hle/config_mem.h
index 24a1254f2..50664dac6 100644
--- a/src/core/hle/config_mem.h
+++ b/src/core/hle/config_mem.h
@@ -20,16 +20,16 @@
20namespace ConfigMem { 20namespace ConfigMem {
21 21
22struct ConfigMemDef { 22struct ConfigMemDef {
23 u8 kernel_unk; // 0 23 u8 kernel_unk; // 0
24 u8 kernel_version_rev; // 1 24 u8 kernel_version_rev; // 1
25 u8 kernel_version_min; // 2 25 u8 kernel_version_min; // 2
26 u8 kernel_version_maj; // 3 26 u8 kernel_version_maj; // 3
27 u32_le update_flag; // 4 27 u32_le update_flag; // 4
28 u64_le ns_tid; // 8 28 u64_le ns_tid; // 8
29 u32_le sys_core_ver; // 10 29 u32_le sys_core_ver; // 10
30 u8 unit_info; // 14 30 u8 unit_info; // 14
31 u8 boot_firm; // 15 31 u8 boot_firm; // 15
32 u8 prev_firm; // 16 32 u8 prev_firm; // 16
33 INSERT_PADDING_BYTES(0x1); // 17 33 INSERT_PADDING_BYTES(0x1); // 17
34 u32_le ctr_sdk_ver; // 18 34 u32_le ctr_sdk_ver; // 18
35 INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C 35 INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C
@@ -39,15 +39,16 @@ struct ConfigMemDef {
39 u32_le sys_mem_alloc; // 44 39 u32_le sys_mem_alloc; // 44
40 u32_le base_mem_alloc; // 48 40 u32_le base_mem_alloc; // 48
41 INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C 41 INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C
42 u8 firm_unk; // 60 42 u8 firm_unk; // 60
43 u8 firm_version_rev; // 61 43 u8 firm_version_rev; // 61
44 u8 firm_version_min; // 62 44 u8 firm_version_min; // 62
45 u8 firm_version_maj; // 63 45 u8 firm_version_maj; // 63
46 u32_le firm_sys_core_ver; // 64 46 u32_le firm_sys_core_ver; // 64
47 u32_le firm_ctr_sdk_ver; // 68 47 u32_le firm_ctr_sdk_ver; // 68
48 INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C 48 INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C
49}; 49};
50static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong"); 50static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE,
51 "Config Memory structure size is wrong");
51 52
52extern ConfigMemDef config_mem; 53extern ConfigMemDef config_mem;
53 54
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 8839ce482..d5d989c29 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -7,14 +7,14 @@
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9#include "core/arm/arm_interface.h" 9#include "core/arm/arm_interface.h"
10#include "core/memory.h"
11#include "core/hle/hle.h" 10#include "core/hle/hle.h"
12#include "core/hle/result.h" 11#include "core/hle/result.h"
13#include "core/hle/svc.h" 12#include "core/hle/svc.h"
13#include "core/memory.h"
14 14
15namespace HLE { 15namespace HLE {
16 16
17#define PARAM(n) Core::g_app_core->GetReg(n) 17#define PARAM(n) Core::g_app_core->GetReg(n)
18 18
19/// An invalid result code that is meant to be overwritten when a thread resumes from waiting 19/// An invalid result code that is meant to be overwritten when a thread resumes from waiting
20static const ResultCode RESULT_INVALID(0xDEADC0DE); 20static const ResultCode RESULT_INVALID(0xDEADC0DE);
@@ -40,28 +40,33 @@ static inline void FuncReturn64(u64 res) {
40//////////////////////////////////////////////////////////////////////////////////////////////////// 40////////////////////////////////////////////////////////////////////////////////////////////////////
41// Function wrappers that return type ResultCode 41// Function wrappers that return type ResultCode
42 42
43template<ResultCode func(u32, u32, u32, u32)> void Wrap() { 43template <ResultCode func(u32, u32, u32, u32)>
44void Wrap() {
44 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)).raw); 45 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)).raw);
45} 46}
46 47
47template<ResultCode func(u32*, u32, u32, u32, u32, u32)> void Wrap(){ 48template <ResultCode func(u32*, u32, u32, u32, u32, u32)>
49void Wrap() {
48 u32 param_1 = 0; 50 u32 param_1 = 0;
49 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; 51 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
50 Core::g_app_core->SetReg(1, param_1); 52 Core::g_app_core->SetReg(1, param_1);
51 FuncReturn(retval); 53 FuncReturn(retval);
52} 54}
53 55
54template<ResultCode func(u32*, s32, u32, u32, u32, s32)> void Wrap() { 56template <ResultCode func(u32*, s32, u32, u32, u32, s32)>
57void Wrap() {
55 u32 param_1 = 0; 58 u32 param_1 = 0;
56 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; 59 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
57 Core::g_app_core->SetReg(1, param_1); 60 Core::g_app_core->SetReg(1, param_1);
58 FuncReturn(retval); 61 FuncReturn(retval);
59} 62}
60 63
61template<ResultCode func(s32*, u32*, s32, bool, s64)> void Wrap() { 64template <ResultCode func(s32*, u32*, s32, bool, s64)>
65void Wrap() {
62 s32 param_1 = 0; 66 s32 param_1 = 0;
63 s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), 67 s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2),
64 (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))).raw; 68 (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0)))
69 .raw;
65 70
66 if (retval != RESULT_INVALID.raw) { 71 if (retval != RESULT_INVALID.raw) {
67 Core::g_app_core->SetReg(1, (u32)param_1); 72 Core::g_app_core->SetReg(1, (u32)param_1);
@@ -69,18 +74,22 @@ template<ResultCode func(s32*, u32*, s32, bool, s64)> void Wrap() {
69 } 74 }
70} 75}
71 76
72template<ResultCode func(u32, u32, u32, u32, s64)> void Wrap() { 77template <ResultCode func(u32, u32, u32, u32, s64)>
73 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(5) << 32) | PARAM(4))).raw); 78void Wrap() {
79 FuncReturn(
80 func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(5) << 32) | PARAM(4))).raw);
74} 81}
75 82
76template<ResultCode func(u32*)> void Wrap(){ 83template <ResultCode func(u32*)>
84void Wrap() {
77 u32 param_1 = 0; 85 u32 param_1 = 0;
78 u32 retval = func(&param_1).raw; 86 u32 retval = func(&param_1).raw;
79 Core::g_app_core->SetReg(1, param_1); 87 Core::g_app_core->SetReg(1, param_1);
80 FuncReturn(retval); 88 FuncReturn(retval);
81} 89}
82 90
83template<ResultCode func(u32, s64)> void Wrap() { 91template <ResultCode func(u32, s64)>
92void Wrap() {
84 s32 retval = func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2))).raw; 93 s32 retval = func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2))).raw;
85 94
86 if (retval != RESULT_INVALID.raw) { 95 if (retval != RESULT_INVALID.raw) {
@@ -88,7 +97,8 @@ template<ResultCode func(u32, s64)> void Wrap() {
88 } 97 }
89} 98}
90 99
91template<ResultCode func(MemoryInfo*, PageInfo*, u32)> void Wrap() { 100template <ResultCode func(MemoryInfo*, PageInfo*, u32)>
101void Wrap() {
92 MemoryInfo memory_info = {}; 102 MemoryInfo memory_info = {};
93 PageInfo page_info = {}; 103 PageInfo page_info = {};
94 u32 retval = func(&memory_info, &page_info, PARAM(2)).raw; 104 u32 retval = func(&memory_info, &page_info, PARAM(2)).raw;
@@ -100,7 +110,8 @@ template<ResultCode func(MemoryInfo*, PageInfo*, u32)> void Wrap() {
100 FuncReturn(retval); 110 FuncReturn(retval);
101} 111}
102 112
103template<ResultCode func(MemoryInfo*, PageInfo*, Handle, u32)> void Wrap() { 113template <ResultCode func(MemoryInfo*, PageInfo*, Handle, u32)>
114void Wrap() {
104 MemoryInfo memory_info = {}; 115 MemoryInfo memory_info = {};
105 PageInfo page_info = {}; 116 PageInfo page_info = {};
106 u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw; 117 u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw;
@@ -112,55 +123,65 @@ template<ResultCode func(MemoryInfo*, PageInfo*, Handle, u32)> void Wrap() {
112 FuncReturn(retval); 123 FuncReturn(retval);
113} 124}
114 125
115template<ResultCode func(s32*, u32)> void Wrap(){ 126template <ResultCode func(s32*, u32)>
127void Wrap() {
116 s32 param_1 = 0; 128 s32 param_1 = 0;
117 u32 retval = func(&param_1, PARAM(1)).raw; 129 u32 retval = func(&param_1, PARAM(1)).raw;
118 Core::g_app_core->SetReg(1, param_1); 130 Core::g_app_core->SetReg(1, param_1);
119 FuncReturn(retval); 131 FuncReturn(retval);
120} 132}
121 133
122template<ResultCode func(u32, s32)> void Wrap() { 134template <ResultCode func(u32, s32)>
135void Wrap() {
123 FuncReturn(func(PARAM(0), (s32)PARAM(1)).raw); 136 FuncReturn(func(PARAM(0), (s32)PARAM(1)).raw);
124} 137}
125 138
126template<ResultCode func(u32*, u32)> void Wrap(){ 139template <ResultCode func(u32*, u32)>
140void Wrap() {
127 u32 param_1 = 0; 141 u32 param_1 = 0;
128 u32 retval = func(&param_1, PARAM(1)).raw; 142 u32 retval = func(&param_1, PARAM(1)).raw;
129 Core::g_app_core->SetReg(1, param_1); 143 Core::g_app_core->SetReg(1, param_1);
130 FuncReturn(retval); 144 FuncReturn(retval);
131} 145}
132 146
133template<ResultCode func(u32)> void Wrap() { 147template <ResultCode func(u32)>
148void Wrap() {
134 FuncReturn(func(PARAM(0)).raw); 149 FuncReturn(func(PARAM(0)).raw);
135} 150}
136 151
137template<ResultCode func(s64*, u32, u32*, u32)> void Wrap(){ 152template <ResultCode func(s64*, u32, u32*, u32)>
138 FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), (u32*)Memory::GetPointer(PARAM(2)), 153void Wrap() {
139 (s32)PARAM(3)).raw); 154 FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1),
155 (u32*)Memory::GetPointer(PARAM(2)), (s32)PARAM(3))
156 .raw);
140} 157}
141 158
142template<ResultCode func(u32*, const char*)> void Wrap() { 159template <ResultCode func(u32*, const char*)>
160void Wrap() {
143 u32 param_1 = 0; 161 u32 param_1 = 0;
144 u32 retval = func(&param_1, (char*)Memory::GetPointer(PARAM(1))).raw; 162 u32 retval = func(&param_1, (char*)Memory::GetPointer(PARAM(1))).raw;
145 Core::g_app_core->SetReg(1, param_1); 163 Core::g_app_core->SetReg(1, param_1);
146 FuncReturn(retval); 164 FuncReturn(retval);
147} 165}
148 166
149template<ResultCode func(u32*, s32, s32)> void Wrap() { 167template <ResultCode func(u32*, s32, s32)>
168void Wrap() {
150 u32 param_1 = 0; 169 u32 param_1 = 0;
151 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 170 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
152 Core::g_app_core->SetReg(1, param_1); 171 Core::g_app_core->SetReg(1, param_1);
153 FuncReturn(retval); 172 FuncReturn(retval);
154} 173}
155 174
156template<ResultCode func(s32*, u32, s32)> void Wrap() { 175template <ResultCode func(s32*, u32, s32)>
176void Wrap() {
157 s32 param_1 = 0; 177 s32 param_1 = 0;
158 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 178 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
159 Core::g_app_core->SetReg(1, param_1); 179 Core::g_app_core->SetReg(1, param_1);
160 FuncReturn(retval); 180 FuncReturn(retval);
161} 181}
162 182
163template<ResultCode func(s64*, u32, s32)> void Wrap() { 183template <ResultCode func(s64*, u32, s32)>
184void Wrap() {
164 s64 param_1 = 0; 185 s64 param_1 = 0;
165 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 186 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
166 Core::g_app_core->SetReg(1, (u32)param_1); 187 Core::g_app_core->SetReg(1, (u32)param_1);
@@ -168,7 +189,8 @@ template<ResultCode func(s64*, u32, s32)> void Wrap() {
168 FuncReturn(retval); 189 FuncReturn(retval);
169} 190}
170 191
171template<ResultCode func(u32*, u32, u32, u32, u32)> void Wrap() { 192template <ResultCode func(u32*, u32, u32, u32, u32)>
193void Wrap() {
172 u32 param_1 = 0; 194 u32 param_1 = 0;
173 // The last parameter is passed in R0 instead of R4 195 // The last parameter is passed in R0 instead of R4
174 u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw; 196 u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw;
@@ -176,13 +198,15 @@ template<ResultCode func(u32*, u32, u32, u32, u32)> void Wrap() {
176 FuncReturn(retval); 198 FuncReturn(retval);
177} 199}
178 200
179template<ResultCode func(u32, s64, s64)> void Wrap() { 201template <ResultCode func(u32, s64, s64)>
202void Wrap() {
180 s64 param1 = ((u64)PARAM(3) << 32) | PARAM(2); 203 s64 param1 = ((u64)PARAM(3) << 32) | PARAM(2);
181 s64 param2 = ((u64)PARAM(4) << 32) | PARAM(1); 204 s64 param2 = ((u64)PARAM(4) << 32) | PARAM(1);
182 FuncReturn(func(PARAM(0), param1, param2).raw); 205 FuncReturn(func(PARAM(0), param1, param2).raw);
183} 206}
184 207
185template<ResultCode func(s64*, Handle, u32)> void Wrap() { 208template <ResultCode func(s64*, Handle, u32)>
209void Wrap() {
186 s64 param_1 = 0; 210 s64 param_1 = 0;
187 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 211 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
188 Core::g_app_core->SetReg(1, (u32)param_1); 212 Core::g_app_core->SetReg(1, (u32)param_1);
@@ -190,14 +214,18 @@ template<ResultCode func(s64*, Handle, u32)> void Wrap() {
190 FuncReturn(retval); 214 FuncReturn(retval);
191} 215}
192 216
193template<ResultCode func(Handle, u32)> void Wrap() { 217template <ResultCode func(Handle, u32)>
218void Wrap() {
194 FuncReturn(func(PARAM(0), PARAM(1)).raw); 219 FuncReturn(func(PARAM(0), PARAM(1)).raw);
195} 220}
196 221
197template<ResultCode func(Handle*, Handle*, const char*, u32)> void Wrap() { 222template <ResultCode func(Handle*, Handle*, const char*, u32)>
223void Wrap() {
198 Handle param_1 = 0; 224 Handle param_1 = 0;
199 Handle param_2 = 0; 225 Handle param_2 = 0;
200 u32 retval = func(&param_1, &param_2, reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3)).raw; 226 u32 retval = func(&param_1, &param_2,
227 reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3))
228 .raw;
201 // The first out parameter is moved into R2 and the second is moved into R1. 229 // The first out parameter is moved into R2 and the second is moved into R1.
202 Core::g_app_core->SetReg(1, param_2); 230 Core::g_app_core->SetReg(1, param_2);
203 Core::g_app_core->SetReg(2, param_1); 231 Core::g_app_core->SetReg(2, param_1);
@@ -207,29 +235,34 @@ template<ResultCode func(Handle*, Handle*, const char*, u32)> void Wrap() {
207//////////////////////////////////////////////////////////////////////////////////////////////////// 235////////////////////////////////////////////////////////////////////////////////////////////////////
208// Function wrappers that return type u32 236// Function wrappers that return type u32
209 237
210template<u32 func()> void Wrap() { 238template <u32 func()>
239void Wrap() {
211 FuncReturn(func()); 240 FuncReturn(func());
212} 241}
213 242
214//////////////////////////////////////////////////////////////////////////////////////////////////// 243////////////////////////////////////////////////////////////////////////////////////////////////////
215// Function wrappers that return type s64 244// Function wrappers that return type s64
216 245
217template<s64 func()> void Wrap() { 246template <s64 func()>
247void Wrap() {
218 FuncReturn64(func()); 248 FuncReturn64(func());
219} 249}
220 250
221//////////////////////////////////////////////////////////////////////////////////////////////////// 251////////////////////////////////////////////////////////////////////////////////////////////////////
222/// Function wrappers that return type void 252/// Function wrappers that return type void
223 253
224template<void func(s64)> void Wrap() { 254template <void func(s64)>
255void Wrap() {
225 func(((s64)PARAM(1) << 32) | PARAM(0)); 256 func(((s64)PARAM(1) << 32) | PARAM(0));
226} 257}
227 258
228template<void func(const char*)> void Wrap() { 259template <void func(const char*)>
260void Wrap() {
229 func((char*)Memory::GetPointer(PARAM(0))); 261 func((char*)Memory::GetPointer(PARAM(0)));
230} 262}
231 263
232template<void func(u8)> void Wrap() { 264template <void func(u8)>
265void Wrap() {
233 func((u8)PARAM(0)); 266 func((u8)PARAM(0));
234} 267}
235 268
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp
index 5c5373517..480a73e80 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -15,13 +15,13 @@
15namespace { 15namespace {
16 16
17bool reschedule; ///< If true, immediately reschedules the CPU to a new thread 17bool reschedule; ///< If true, immediately reschedules the CPU to a new thread
18
19} 18}
20 19
21namespace HLE { 20namespace HLE {
22 21
23void Reschedule(const char *reason) { 22void Reschedule(const char* reason) {
24 DEBUG_ASSERT_MSG(reason != nullptr && strlen(reason) < 256, "Reschedule: Invalid or too long reason."); 23 DEBUG_ASSERT_MSG(reason != nullptr && strlen(reason) < 256,
24 "Reschedule: Invalid or too long reason.");
25 25
26 // TODO(bunnei): It seems that games depend on some CPU execution time elapsing during HLE 26 // TODO(bunnei): It seems that games depend on some CPU execution time elapsing during HLE
27 // routines. This simulates that time by artificially advancing the number of CPU "ticks". 27 // routines. This simulates that time by artificially advancing the number of CPU "ticks".
diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h
index 69ac0ade6..23859e129 100644
--- a/src/core/hle/hle.h
+++ b/src/core/hle/hle.h
@@ -13,7 +13,7 @@ const Handle INVALID_HANDLE = 0;
13 13
14namespace HLE { 14namespace HLE {
15 15
16void Reschedule(const char *reason); 16void Reschedule(const char* reason);
17bool IsReschedulePending(); 17bool IsReschedulePending();
18void DoneRescheduling(); 18void DoneRescheduling();
19 19
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 5c3c47acf..2ff652f13 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -16,8 +16,10 @@
16 16
17namespace Kernel { 17namespace Kernel {
18 18
19AddressArbiter::AddressArbiter() {} 19AddressArbiter::AddressArbiter() {
20AddressArbiter::~AddressArbiter() {} 20}
21AddressArbiter::~AddressArbiter() {
22}
21 23
22SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) { 24SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) {
23 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); 25 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter);
@@ -28,7 +30,7 @@ SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) {
28} 30}
29 31
30ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, 32ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value,
31 u64 nanoseconds) { 33 u64 nanoseconds) {
32 switch (type) { 34 switch (type) {
33 35
34 // Signal thread(s) waiting for arbitrate address... 36 // Signal thread(s) waiting for arbitrate address...
@@ -38,7 +40,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
38 ArbitrateAllThreads(address); 40 ArbitrateAllThreads(address);
39 } else { 41 } else {
40 // Resume first N threads 42 // Resume first N threads
41 for(int i = 0; i < value; i++) 43 for (int i = 0; i < value; i++)
42 ArbitrateHighestPriorityThread(address); 44 ArbitrateHighestPriorityThread(address);
43 } 45 }
44 break; 46 break;
@@ -55,8 +57,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
55 GetCurrentThread()->WakeAfterDelay(nanoseconds); 57 GetCurrentThread()->WakeAfterDelay(nanoseconds);
56 } 58 }
57 break; 59 break;
58 case ArbitrationType::DecrementAndWaitIfLessThan: 60 case ArbitrationType::DecrementAndWaitIfLessThan: {
59 {
60 s32 memory_value = Memory::Read32(address); 61 s32 memory_value = Memory::Read32(address);
61 if (memory_value < value) { 62 if (memory_value < value) {
62 // Only change the memory value if the thread should wait 63 // Only change the memory value if the thread should wait
@@ -65,8 +66,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
65 } 66 }
66 break; 67 break;
67 } 68 }
68 case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: 69 case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: {
69 {
70 s32 memory_value = Memory::Read32(address); 70 s32 memory_value = Memory::Read32(address);
71 if (memory_value < value) { 71 if (memory_value < value) {
72 // Only change the memory value if the thread should wait 72 // Only change the memory value if the thread should wait
@@ -79,17 +79,19 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
79 79
80 default: 80 default:
81 LOG_ERROR(Kernel, "unknown type=%d", type); 81 LOG_ERROR(Kernel, "unknown type=%d", type);
82 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage); 82 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
83 ErrorSummary::WrongArgument, ErrorLevel::Usage);
83 } 84 }
84 85
85 HLE::Reschedule(__func__); 86 HLE::Reschedule(__func__);
86 87
87 // The calls that use a timeout seem to always return a Timeout error even if they did not put the thread to sleep 88 // The calls that use a timeout seem to always return a Timeout error even if they did not put
89 // the thread to sleep
88 if (type == ArbitrationType::WaitIfLessThanWithTimeout || 90 if (type == ArbitrationType::WaitIfLessThanWithTimeout ||
89 type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) { 91 type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) {
90 92
91 return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, 93 return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, ErrorSummary::StatusChanged,
92 ErrorSummary::StatusChanged, ErrorLevel::Info); 94 ErrorLevel::Info);
93 } 95 }
94 return RESULT_SUCCESS; 96 return RESULT_SUCCESS;
95} 97}
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 8f6a1a8df..1a03993b2 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -36,13 +36,19 @@ public:
36 */ 36 */
37 static SharedPtr<AddressArbiter> Create(std::string name = "Unknown"); 37 static SharedPtr<AddressArbiter> Create(std::string name = "Unknown");
38 38
39 std::string GetTypeName() const override { return "Arbiter"; } 39 std::string GetTypeName() const override {
40 std::string GetName() const override { return name; } 40 return "Arbiter";
41 }
42 std::string GetName() const override {
43 return name;
44 }
41 45
42 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; 46 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter;
43 HandleType GetHandleType() const override { return HANDLE_TYPE; } 47 HandleType GetHandleType() const override {
48 return HANDLE_TYPE;
49 }
44 50
45 std::string name; ///< Name of address arbiter object (optional) 51 std::string name; ///< Name of address arbiter object (optional)
46 52
47 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); 53 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds);
48 54
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index 444ce8d45..5df769c6a 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -10,7 +10,9 @@
10 10
11namespace Kernel { 11namespace Kernel {
12 12
13ClientPort::ClientPort() {} 13ClientPort::ClientPort() {
14ClientPort::~ClientPort() {} 14}
15ClientPort::~ClientPort() {
16}
15 17
16} // namespace 18} // namespace
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index 480b6ddae..70e0d56cc 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -17,16 +17,22 @@ class ServerPort;
17class ClientPort : public Object { 17class ClientPort : public Object {
18public: 18public:
19 friend class ServerPort; 19 friend class ServerPort;
20 std::string GetTypeName() const override { return "ClientPort"; } 20 std::string GetTypeName() const override {
21 std::string GetName() const override { return name; } 21 return "ClientPort";
22 }
23 std::string GetName() const override {
24 return name;
25 }
22 26
23 static const HandleType HANDLE_TYPE = HandleType::ClientPort; 27 static const HandleType HANDLE_TYPE = HandleType::ClientPort;
24 HandleType GetHandleType() const override { return HANDLE_TYPE; } 28 HandleType GetHandleType() const override {
25 29 return HANDLE_TYPE;
26 SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. 30 }
27 u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have 31
28 u32 active_sessions; ///< Number of currently open sessions to this port 32 SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
29 std::string name; ///< Name of client port (optional) 33 u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have
34 u32 active_sessions; ///< Number of currently open sessions to this port
35 std::string name; ///< Name of client port (optional)
30 36
31protected: 37protected:
32 ClientPort(); 38 ClientPort();
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 2b7c6992a..63375818d 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -2,20 +2,22 @@
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 <map>
6#include <algorithm> 5#include <algorithm>
6#include <map>
7#include <vector> 7#include <vector>
8 8
9#include "common/assert.h" 9#include "common/assert.h"
10 10
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/event.h" 11#include "core/hle/kernel/event.h"
12#include "core/hle/kernel/kernel.h"
13#include "core/hle/kernel/thread.h" 13#include "core/hle/kernel/thread.h"
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17Event::Event() {} 17Event::Event() {
18Event::~Event() {} 18}
19Event::~Event() {
20}
19 21
20SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) { 22SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) {
21 SharedPtr<Event> evt(new Event); 23 SharedPtr<Event> evt(new Event);
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 73d0da419..e333a46ce 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -16,7 +16,6 @@ enum class ResetType {
16 Pulse, 16 Pulse,
17}; 17};
18 18
19
20class Event final : public WaitObject { 19class Event final : public WaitObject {
21public: 20public:
22 /** 21 /**
@@ -26,16 +25,22 @@ public:
26 */ 25 */
27 static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown"); 26 static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown");
28 27
29 std::string GetTypeName() const override { return "Event"; } 28 std::string GetTypeName() const override {
30 std::string GetName() const override { return name; } 29 return "Event";
30 }
31 std::string GetName() const override {
32 return name;
33 }
31 34
32 static const HandleType HANDLE_TYPE = HandleType::Event; 35 static const HandleType HANDLE_TYPE = HandleType::Event;
33 HandleType GetHandleType() const override { return HANDLE_TYPE; } 36 HandleType GetHandleType() const override {
37 return HANDLE_TYPE;
38 }
34 39
35 ResetType reset_type; ///< Current ResetType 40 ResetType reset_type; ///< Current ResetType
36 41
37 bool signaled; ///< Whether the event has already been signaled 42 bool signaled; ///< Whether the event has already been signaled
38 std::string name; ///< Name of event (optional) 43 std::string name; ///< Name of event (optional)
39 44
40 bool ShouldWait() override; 45 bool ShouldWait() override;
41 void Acquire() override; 46 void Acquire() override;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 7a401a965..1fd7c0326 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -61,7 +61,8 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
61 61
62 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. 62 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
63 // CTR-OS doesn't use generation 0, so skip straight to 1. 63 // CTR-OS doesn't use generation 0, so skip straight to 1.
64 if (next_generation >= (1 << 15)) next_generation = 1; 64 if (next_generation >= (1 << 15))
65 next_generation = 1;
65 66
66 generations[slot] = generation; 67 generations[slot] = generation;
67 objects[slot] = std::move(obj); 68 objects[slot] = std::move(obj);
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 27ba3f912..cc39652d5 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -23,48 +23,55 @@ class Thread;
23 23
24// TODO: Verify code 24// TODO: Verify code
25const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, 25const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
26 ErrorSummary::OutOfResource, ErrorLevel::Temporary); 26 ErrorSummary::OutOfResource, ErrorLevel::Temporary);
27// TOOD: Verify code 27// TOOD: Verify code
28const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, 28const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel,
29 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 29 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
30 30
31enum KernelHandle : Handle { 31enum KernelHandle : Handle {
32 CurrentThread = 0xFFFF8000, 32 CurrentThread = 0xFFFF8000,
33 CurrentProcess = 0xFFFF8001, 33 CurrentProcess = 0xFFFF8001,
34}; 34};
35 35
36enum class HandleType : u32 { 36enum class HandleType : u32 {
37 Unknown = 0, 37 Unknown = 0,
38 38
39 Session = 2, 39 Session = 2,
40 Event = 3, 40 Event = 3,
41 Mutex = 4, 41 Mutex = 4,
42 SharedMemory = 5, 42 SharedMemory = 5,
43 Redirection = 6, 43 Redirection = 6,
44 Thread = 7, 44 Thread = 7,
45 Process = 8, 45 Process = 8,
46 AddressArbiter = 9, 46 AddressArbiter = 9,
47 Semaphore = 10, 47 Semaphore = 10,
48 Timer = 11, 48 Timer = 11,
49 ResourceLimit = 12, 49 ResourceLimit = 12,
50 CodeSet = 13, 50 CodeSet = 13,
51 ClientPort = 14, 51 ClientPort = 14,
52 ServerPort = 15, 52 ServerPort = 15,
53}; 53};
54 54
55enum { 55enum {
56 DEFAULT_STACK_SIZE = 0x4000, 56 DEFAULT_STACK_SIZE = 0x4000,
57}; 57};
58 58
59class Object : NonCopyable { 59class Object : NonCopyable {
60public: 60public:
61 virtual ~Object() {} 61 virtual ~Object() {
62 }
62 63
63 /// Returns a unique identifier for the object. For debugging purposes only. 64 /// Returns a unique identifier for the object. For debugging purposes only.
64 unsigned int GetObjectId() const { return object_id; } 65 unsigned int GetObjectId() const {
66 return object_id;
67 }
65 68
66 virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } 69 virtual std::string GetTypeName() const {
67 virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } 70 return "[BAD KERNEL OBJECT TYPE]";
71 }
72 virtual std::string GetName() const {
73 return "[UNKNOWN KERNEL OBJECT]";
74 }
68 virtual Kernel::HandleType GetHandleType() const = 0; 75 virtual Kernel::HandleType GetHandleType() const = 0;
69 76
70 /** 77 /**
@@ -122,7 +129,6 @@ using SharedPtr = boost::intrusive_ptr<T>;
122/// Class that represents a Kernel object that a thread can be waiting on 129/// Class that represents a Kernel object that a thread can be waiting on
123class WaitObject : public Object { 130class WaitObject : public Object {
124public: 131public:
125
126 /** 132 /**
127 * Check if the current thread should wait until the object is available 133 * Check if the current thread should wait until the object is available
128 * @return True if the current thread should wait due to this object being unavailable 134 * @return True if the current thread should wait due to this object being unavailable
@@ -247,8 +253,12 @@ private:
247 */ 253 */
248 static const size_t MAX_COUNT = 4096; 254 static const size_t MAX_COUNT = 4096;
249 255
250 static u16 GetSlot(Handle handle) { return handle >> 15; } 256 static u16 GetSlot(Handle handle) {
251 static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; } 257 return handle >> 15;
258 }
259 static u16 GetGeneration(Handle handle) {
260 return handle & 0x7FFF;
261 }
252 262
253 /// Stores the Object referenced by the handle or null if the slot is empty. 263 /// Stores the Object referenced by the handle or null if the slot is empty.
254 std::array<SharedPtr<Object>, MAX_COUNT> objects; 264 std::array<SharedPtr<Object>, MAX_COUNT> objects;
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp
index 17ae87aef..89a72808a 100644
--- a/src/core/hle/kernel/memory.cpp
+++ b/src/core/hle/kernel/memory.cpp
@@ -31,7 +31,7 @@ static MemoryRegionInfo memory_regions[3];
31static const u32 memory_region_sizes[8][3] = { 31static const u32 memory_region_sizes[8][3] = {
32 // Old 3DS layouts 32 // Old 3DS layouts
33 {0x04000000, 0x02C00000, 0x01400000}, // 0 33 {0x04000000, 0x02C00000, 0x01400000}, // 0
34 { /* This appears to be unused. */ }, // 1 34 {/* This appears to be unused. */}, // 1
35 {0x06000000, 0x00C00000, 0x01400000}, // 2 35 {0x06000000, 0x00C00000, 0x01400000}, // 2
36 {0x05000000, 0x01C00000, 0x01400000}, // 3 36 {0x05000000, 0x01C00000, 0x01400000}, // 3
37 {0x04800000, 0x02400000, 0x01400000}, // 4 37 {0x04800000, 0x02400000, 0x01400000}, // 4
@@ -95,7 +95,6 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) {
95 UNREACHABLE(); 95 UNREACHABLE();
96 } 96 }
97} 97}
98
99} 98}
100 99
101namespace Memory { 100namespace Memory {
@@ -110,9 +109,8 @@ struct MemoryArea {
110 109
111// We don't declare the IO regions in here since its handled by other means. 110// We don't declare the IO regions in here since its handled by other means.
112static MemoryArea memory_areas[] = { 111static MemoryArea memory_areas[] = {
113 {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) 112 {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM)
114}; 113};
115
116} 114}
117 115
118void Init() { 116void Init() {
@@ -125,15 +123,21 @@ void InitLegacyAddressSpace(Kernel::VMManager& address_space) {
125 123
126 for (MemoryArea& area : memory_areas) { 124 for (MemoryArea& area : memory_areas) {
127 auto block = std::make_shared<std::vector<u8>>(area.size); 125 auto block = std::make_shared<std::vector<u8>>(area.size);
128 address_space.MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private).Unwrap(); 126 address_space
127 .MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private)
128 .Unwrap();
129 } 129 }
130 130
131 auto cfg_mem_vma = address_space.MapBackingMemory(CONFIG_MEMORY_VADDR, 131 auto cfg_mem_vma = address_space
132 (u8*)&ConfigMem::config_mem, CONFIG_MEMORY_SIZE, MemoryState::Shared).MoveFrom(); 132 .MapBackingMemory(CONFIG_MEMORY_VADDR, (u8*)&ConfigMem::config_mem,
133 CONFIG_MEMORY_SIZE, MemoryState::Shared)
134 .MoveFrom();
133 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); 135 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read);
134 136
135 auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR, 137 auto shared_page_vma = address_space
136 (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom(); 138 .MapBackingMemory(SHARED_PAGE_VADDR, (u8*)&SharedPage::shared_page,
139 SHARED_PAGE_SIZE, MemoryState::Shared)
140 .MoveFrom();
137 address_space.Reprotect(shared_page_vma, VMAPermission::Read); 141 address_space.Reprotect(shared_page_vma, VMAPermission::Read);
138 142
139 AudioCore::AddAddressSpace(address_space); 143 AudioCore::AddAddressSpace(address_space);
diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h
index 091c1f89f..b941c24b6 100644
--- a/src/core/hle/kernel/memory.h
+++ b/src/core/hle/kernel/memory.h
@@ -25,7 +25,6 @@ struct MemoryRegionInfo {
25void MemoryInit(u32 mem_type); 25void MemoryInit(u32 mem_type);
26void MemoryShutdown(); 26void MemoryShutdown();
27MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); 27MemoryRegionInfo* GetMemoryRegion(MemoryRegion region);
28
29} 28}
30 29
31namespace Memory { 30namespace Memory {
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index edb97d324..f92810804 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -33,8 +33,10 @@ void ReleaseThreadMutexes(Thread* thread) {
33 thread->held_mutexes.clear(); 33 thread->held_mutexes.clear();
34} 34}
35 35
36Mutex::Mutex() {} 36Mutex::Mutex() {
37Mutex::~Mutex() {} 37}
38Mutex::~Mutex() {
39}
38 40
39SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) { 41SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {
40 SharedPtr<Mutex> mutex(new Mutex); 42 SharedPtr<Mutex> mutex(new Mutex);
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 1746360e4..cf6a51fdf 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -24,15 +24,21 @@ public:
24 */ 24 */
25 static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown"); 25 static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown");
26 26
27 std::string GetTypeName() const override { return "Mutex"; } 27 std::string GetTypeName() const override {
28 std::string GetName() const override { return name; } 28 return "Mutex";
29 }
30 std::string GetName() const override {
31 return name;
32 }
29 33
30 static const HandleType HANDLE_TYPE = HandleType::Mutex; 34 static const HandleType HANDLE_TYPE = HandleType::Mutex;
31 HandleType GetHandleType() const override { return HANDLE_TYPE; } 35 HandleType GetHandleType() const override {
36 return HANDLE_TYPE;
37 }
32 38
33 int lock_count; ///< Number of times the mutex has been acquired 39 int lock_count; ///< Number of times the mutex has been acquired
34 std::string name; ///< Name of mutex (optional) 40 std::string name; ///< Name of mutex (optional)
35 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex 41 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
36 42
37 bool ShouldWait() override; 43 bool ShouldWait() override;
38 void Acquire() override; 44 void Acquire() override;
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 69302cc82..cc37e574c 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -26,8 +26,10 @@ SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) {
26 return codeset; 26 return codeset;
27} 27}
28 28
29CodeSet::CodeSet() {} 29CodeSet::CodeSet() {
30CodeSet::~CodeSet() {} 30}
31CodeSet::~CodeSet() {
32}
31 33
32u32 Process::next_process_id; 34u32 Process::next_process_id;
33 35
@@ -60,7 +62,8 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
60 62
61 while (bits && index < svc_access_mask.size()) { 63 while (bits && index < svc_access_mask.size()) {
62 svc_access_mask.set(index, bits & 1); 64 svc_access_mask.set(index, bits & 1);
63 ++index; bits >>= 1; 65 ++index;
66 bits >>= 1;
64 } 67 }
65 } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF 68 } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF
66 // Handle table size 69 // Handle table size
@@ -70,11 +73,11 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
70 flags.raw = descriptor & 0xFFFF; 73 flags.raw = descriptor & 0xFFFF;
71 } else if ((type & 0xFFE) == 0xFF8) { // 0x001F 74 } else if ((type & 0xFFE) == 0xFF8) { // 0x001F
72 // Mapped memory range 75 // Mapped memory range
73 if (i+1 >= len || ((kernel_caps[i+1] >> 20) & 0xFFE) != 0xFF8) { 76 if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) {
74 LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored."); 77 LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored.");
75 continue; 78 continue;
76 } 79 }
77 u32 end_desc = kernel_caps[i+1]; 80 u32 end_desc = kernel_caps[i + 1];
78 ++i; // Skip over the second descriptor on the next iteration 81 ++i; // Skip over the second descriptor on the next iteration
79 82
80 AddressMapping mapping; 83 AddressMapping mapping;
@@ -107,23 +110,28 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
107void Process::Run(s32 main_thread_priority, u32 stack_size) { 110void Process::Run(s32 main_thread_priority, u32 stack_size) {
108 memory_region = GetMemoryRegion(flags.memory_region); 111 memory_region = GetMemoryRegion(flags.memory_region);
109 112
110 auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { 113 auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
111 auto vma = vm_manager.MapMemoryBlock(segment.addr, codeset->memory, 114 MemoryState memory_state) {
112 segment.offset, segment.size, memory_state).Unwrap(); 115 auto vma = vm_manager
116 .MapMemoryBlock(segment.addr, codeset->memory, segment.offset, segment.size,
117 memory_state)
118 .Unwrap();
113 vm_manager.Reprotect(vma, permissions); 119 vm_manager.Reprotect(vma, permissions);
114 misc_memory_used += segment.size; 120 misc_memory_used += segment.size;
115 memory_region->used += segment.size; 121 memory_region->used += segment.size;
116 }; 122 };
117 123
118 // Map CodeSet segments 124 // Map CodeSet segments
119 MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code); 125 MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code);
120 MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code); 126 MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code);
121 MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private); 127 MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private);
122 128
123 // Allocate and map stack 129 // Allocate and map stack
124 vm_manager.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, 130 vm_manager
125 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked 131 .MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size,
126 ).Unwrap(); 132 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size,
133 MemoryState::Locked)
134 .Unwrap();
127 misc_memory_used += stack_size; 135 misc_memory_used += stack_size;
128 memory_region->used += stack_size; 136 memory_region->used += stack_size;
129 137
@@ -143,7 +151,8 @@ VAddr Process::GetLinearHeapLimit() const {
143} 151}
144 152
145ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) { 153ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) {
146 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { 154 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END ||
155 target + size < target) {
147 return ERR_INVALID_ADDRESS; 156 return ERR_INVALID_ADDRESS;
148 } 157 }
149 158
@@ -166,7 +175,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
166 } 175 }
167 ASSERT(heap_end - heap_start == heap_memory->size()); 176 ASSERT(heap_end - heap_start == heap_memory->size());
168 177
169 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, size, MemoryState::Private)); 178 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start,
179 size, MemoryState::Private));
170 vm_manager.Reprotect(vma, perms); 180 vm_manager.Reprotect(vma, perms);
171 181
172 heap_used += size; 182 heap_used += size;
@@ -176,7 +186,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
176} 186}
177 187
178ResultCode Process::HeapFree(VAddr target, u32 size) { 188ResultCode Process::HeapFree(VAddr target, u32 size) {
179 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { 189 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END ||
190 target + size < target) {
180 return ERR_INVALID_ADDRESS; 191 return ERR_INVALID_ADDRESS;
181 } 192 }
182 193
@@ -185,7 +196,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
185 } 196 }
186 197
187 ResultCode result = vm_manager.UnmapRange(target, size); 198 ResultCode result = vm_manager.UnmapRange(target, size);
188 if (result.IsError()) return result; 199 if (result.IsError())
200 return result;
189 201
190 heap_used -= size; 202 heap_used -= size;
191 memory_region->used -= size; 203 memory_region->used -= size;
@@ -203,8 +215,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p
203 target = heap_end; 215 target = heap_end;
204 } 216 }
205 217
206 if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || 218 if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || target > heap_end ||
207 target > heap_end || target + size < target) { 219 target + size < target) {
208 220
209 return ERR_INVALID_ADDRESS; 221 return ERR_INVALID_ADDRESS;
210 } 222 }
@@ -220,7 +232,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p
220 // TODO(yuriks): As is, this lets processes map memory allocated by other processes from the 232 // TODO(yuriks): As is, this lets processes map memory allocated by other processes from the
221 // same region. It is unknown if or how the 3DS kernel checks against this. 233 // same region. It is unknown if or how the 3DS kernel checks against this.
222 size_t offset = target - GetLinearHeapBase(); 234 size_t offset = target - GetLinearHeapBase();
223 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, MemoryState::Continuous)); 235 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size,
236 MemoryState::Continuous));
224 vm_manager.Reprotect(vma, perms); 237 vm_manager.Reprotect(vma, perms);
225 238
226 linear_heap_used += size; 239 linear_heap_used += size;
@@ -248,7 +261,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
248 } 261 }
249 262
250 ResultCode result = vm_manager.UnmapRange(target, size); 263 ResultCode result = vm_manager.UnmapRange(target, size);
251 if (result.IsError()) return result; 264 if (result.IsError())
265 return result;
252 266
253 linear_heap_used -= size; 267 linear_heap_used -= size;
254 memory_region->used -= size; 268 memory_region->used -= size;
@@ -268,9 +282,10 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
268 return RESULT_SUCCESS; 282 return RESULT_SUCCESS;
269} 283}
270 284
271Kernel::Process::Process() {} 285Kernel::Process::Process() {
272Kernel::Process::~Process() {} 286}
287Kernel::Process::~Process() {
288}
273 289
274SharedPtr<Process> g_current_process; 290SharedPtr<Process> g_current_process;
275
276} 291}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index d781ef32c..070b2b558 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -36,15 +36,18 @@ enum class MemoryRegion : u16 {
36union ProcessFlags { 36union ProcessFlags {
37 u16 raw; 37 u16 raw;
38 38
39 BitField< 0, 1, u16> allow_debug; ///< Allows other processes to attach to and debug this process. 39 BitField<0, 1, u16>
40 BitField< 1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they don't have allow_debug set. 40 allow_debug; ///< Allows other processes to attach to and debug this process.
41 BitField< 2, 1, u16> allow_nonalphanum; 41 BitField<1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they
42 BitField< 3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions. 42 /// don't have allow_debug set.
43 BitField< 4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24. 43 BitField<2, 1, u16> allow_nonalphanum;
44 BitField< 5, 1, u16> allow_main_args; 44 BitField<3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions.
45 BitField< 6, 1, u16> shared_device_mem; 45 BitField<4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24.
46 BitField< 7, 1, u16> runnable_on_sleep; 46 BitField<5, 1, u16> allow_main_args;
47 BitField< 8, 4, MemoryRegion> memory_region; ///< Default region for memory allocations for this process 47 BitField<6, 1, u16> shared_device_mem;
48 BitField<7, 1, u16> runnable_on_sleep;
49 BitField<8, 4, MemoryRegion>
50 memory_region; ///< Default region for memory allocations for this process
48 BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000). 51 BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
49}; 52};
50 53
@@ -54,11 +57,17 @@ struct MemoryRegionInfo;
54struct CodeSet final : public Object { 57struct CodeSet final : public Object {
55 static SharedPtr<CodeSet> Create(std::string name, u64 program_id); 58 static SharedPtr<CodeSet> Create(std::string name, u64 program_id);
56 59
57 std::string GetTypeName() const override { return "CodeSet"; } 60 std::string GetTypeName() const override {
58 std::string GetName() const override { return name; } 61 return "CodeSet";
62 }
63 std::string GetName() const override {
64 return name;
65 }
59 66
60 static const HandleType HANDLE_TYPE = HandleType::CodeSet; 67 static const HandleType HANDLE_TYPE = HandleType::CodeSet;
61 HandleType GetHandleType() const override { return HANDLE_TYPE; } 68 HandleType GetHandleType() const override {
69 return HANDLE_TYPE;
70 }
62 71
63 /// Name of the process 72 /// Name of the process
64 std::string name; 73 std::string name;
@@ -85,11 +94,17 @@ class Process final : public Object {
85public: 94public:
86 static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set); 95 static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set);
87 96
88 std::string GetTypeName() const override { return "Process"; } 97 std::string GetTypeName() const override {
89 std::string GetName() const override { return codeset->name; } 98 return "Process";
99 }
100 std::string GetName() const override {
101 return codeset->name;
102 }
90 103
91 static const HandleType HANDLE_TYPE = HandleType::Process; 104 static const HandleType HANDLE_TYPE = HandleType::Process;
92 HandleType GetHandleType() const override { return HANDLE_TYPE; } 105 HandleType GetHandleType() const override {
106 return HANDLE_TYPE;
107 }
93 108
94 static u32 next_process_id; 109 static u32 next_process_id;
95 110
@@ -124,7 +139,6 @@ public:
124 */ 139 */
125 void Run(s32 main_thread_priority, u32 stack_size); 140 void Run(s32 main_thread_priority, u32 stack_size);
126 141
127
128 /////////////////////////////////////////////////////////////////////////////////////////////// 142 ///////////////////////////////////////////////////////////////////////////////////////////////
129 // Memory Management 143 // Memory Management
130 144
@@ -144,7 +158,8 @@ public:
144 158
145 /// The Thread Local Storage area is allocated as processes create threads, 159 /// The Thread Local Storage area is allocated as processes create threads,
146 /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part 160 /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part
147 /// holds the TLS for a specific thread. This vector contains which parts are in use for each page as a bitmask. 161 /// holds the TLS for a specific thread. This vector contains which parts are in use for each
162 /// page as a bitmask.
148 /// This vector will grow as more pages are allocated for new threads. 163 /// This vector will grow as more pages are allocated for new threads.
149 std::vector<std::bitset<8>> tls_slots; 164 std::vector<std::bitset<8>> tls_slots;
150 165
@@ -164,5 +179,4 @@ private:
164}; 179};
165 180
166extern SharedPtr<Process> g_current_process; 181extern SharedPtr<Process> g_current_process;
167
168} 182}
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
index 67dde08c2..7bd1c1e08 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -12,8 +12,10 @@ namespace Kernel {
12 12
13static SharedPtr<ResourceLimit> resource_limits[4]; 13static SharedPtr<ResourceLimit> resource_limits[4];
14 14
15ResourceLimit::ResourceLimit() {} 15ResourceLimit::ResourceLimit() {
16ResourceLimit::~ResourceLimit() {} 16}
17ResourceLimit::~ResourceLimit() {
18}
17 19
18SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { 20SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) {
19 SharedPtr<ResourceLimit> resource_limit(new ResourceLimit); 21 SharedPtr<ResourceLimit> resource_limit(new ResourceLimit);
@@ -23,70 +25,69 @@ SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) {
23} 25}
24 26
25SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { 27SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) {
26 switch (category) 28 switch (category) {
27 { 29 case ResourceLimitCategory::APPLICATION:
28 case ResourceLimitCategory::APPLICATION: 30 case ResourceLimitCategory::SYS_APPLET:
29 case ResourceLimitCategory::SYS_APPLET: 31 case ResourceLimitCategory::LIB_APPLET:
30 case ResourceLimitCategory::LIB_APPLET: 32 case ResourceLimitCategory::OTHER:
31 case ResourceLimitCategory::OTHER: 33 return resource_limits[static_cast<u8>(category)];
32 return resource_limits[static_cast<u8>(category)]; 34 default:
33 default: 35 LOG_CRITICAL(Kernel, "Unknown resource limit category");
34 LOG_CRITICAL(Kernel, "Unknown resource limit category"); 36 UNREACHABLE();
35 UNREACHABLE();
36 } 37 }
37} 38}
38 39
39s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { 40s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const {
40 switch (resource) { 41 switch (resource) {
41 case COMMIT: 42 case COMMIT:
42 return current_commit; 43 return current_commit;
43 case THREAD: 44 case THREAD:
44 return current_threads; 45 return current_threads;
45 case EVENT: 46 case EVENT:
46 return current_events; 47 return current_events;
47 case MUTEX: 48 case MUTEX:
48 return current_mutexes; 49 return current_mutexes;
49 case SEMAPHORE: 50 case SEMAPHORE:
50 return current_semaphores; 51 return current_semaphores;
51 case TIMER: 52 case TIMER:
52 return current_timers; 53 return current_timers;
53 case SHARED_MEMORY: 54 case SHARED_MEMORY:
54 return current_shared_mems; 55 return current_shared_mems;
55 case ADDRESS_ARBITER: 56 case ADDRESS_ARBITER:
56 return current_address_arbiters; 57 return current_address_arbiters;
57 case CPU_TIME: 58 case CPU_TIME:
58 return current_cpu_time; 59 return current_cpu_time;
59 default: 60 default:
60 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); 61 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
61 UNIMPLEMENTED(); 62 UNIMPLEMENTED();
62 return 0; 63 return 0;
63 } 64 }
64} 65}
65 66
66s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { 67s32 ResourceLimit::GetMaxResourceValue(u32 resource) const {
67 switch (resource) { 68 switch (resource) {
68 case COMMIT: 69 case COMMIT:
69 return max_commit; 70 return max_commit;
70 case THREAD: 71 case THREAD:
71 return max_threads; 72 return max_threads;
72 case EVENT: 73 case EVENT:
73 return max_events; 74 return max_events;
74 case MUTEX: 75 case MUTEX:
75 return max_mutexes; 76 return max_mutexes;
76 case SEMAPHORE: 77 case SEMAPHORE:
77 return max_semaphores; 78 return max_semaphores;
78 case TIMER: 79 case TIMER:
79 return max_timers; 80 return max_timers;
80 case SHARED_MEMORY: 81 case SHARED_MEMORY:
81 return max_shared_mems; 82 return max_shared_mems;
82 case ADDRESS_ARBITER: 83 case ADDRESS_ARBITER:
83 return max_address_arbiters; 84 return max_address_arbiters;
84 case CPU_TIME: 85 case CPU_TIME:
85 return max_cpu_time; 86 return max_cpu_time;
86 default: 87 default:
87 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); 88 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
88 UNIMPLEMENTED(); 89 UNIMPLEMENTED();
89 return 0; 90 return 0;
90 } 91 }
91} 92}
92 93
@@ -150,7 +151,6 @@ void ResourceLimitsInit() {
150} 151}
151 152
152void ResourceLimitsShutdown() { 153void ResourceLimitsShutdown() {
153
154} 154}
155 155
156} // namespace 156} // namespace
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index 1b8249c74..c08e744e6 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -12,22 +12,22 @@ namespace Kernel {
12 12
13enum class ResourceLimitCategory : u8 { 13enum class ResourceLimitCategory : u8 {
14 APPLICATION = 0, 14 APPLICATION = 0,
15 SYS_APPLET = 1, 15 SYS_APPLET = 1,
16 LIB_APPLET = 2, 16 LIB_APPLET = 2,
17 OTHER = 3 17 OTHER = 3
18}; 18};
19 19
20enum ResourceTypes { 20enum ResourceTypes {
21 PRIORITY = 0, 21 PRIORITY = 0,
22 COMMIT = 1, 22 COMMIT = 1,
23 THREAD = 2, 23 THREAD = 2,
24 EVENT = 3, 24 EVENT = 3,
25 MUTEX = 4, 25 MUTEX = 4,
26 SEMAPHORE = 5, 26 SEMAPHORE = 5,
27 TIMER = 6, 27 TIMER = 6,
28 SHARED_MEMORY = 7, 28 SHARED_MEMORY = 7,
29 ADDRESS_ARBITER = 8, 29 ADDRESS_ARBITER = 8,
30 CPU_TIME = 9, 30 CPU_TIME = 9,
31}; 31};
32 32
33class ResourceLimit final : public Object { 33class ResourceLimit final : public Object {
@@ -44,11 +44,17 @@ public:
44 */ 44 */
45 static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category); 45 static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
46 46
47 std::string GetTypeName() const override { return "ResourceLimit"; } 47 std::string GetTypeName() const override {
48 std::string GetName() const override { return name; } 48 return "ResourceLimit";
49 }
50 std::string GetName() const override {
51 return name;
52 }
49 53
50 static const HandleType HANDLE_TYPE = HandleType::ResourceLimit; 54 static const HandleType HANDLE_TYPE = HandleType::ResourceLimit;
51 HandleType GetHandleType() const override { return HANDLE_TYPE; } 55 HandleType GetHandleType() const override {
56 return HANDLE_TYPE;
57 }
52 58
53 /** 59 /**
54 * Gets the current value for the specified resource. 60 * Gets the current value for the specified resource.
@@ -85,10 +91,12 @@ public:
85 /// Max CPU time that the processes in this category can utilize 91 /// Max CPU time that the processes in this category can utilize
86 s32 max_cpu_time = 0; 92 s32 max_cpu_time = 0;
87 93
88 // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that 94 // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind
95 // that
89 // APPLICATION resource limits should not be affected by the objects created by service modules. 96 // APPLICATION resource limits should not be affected by the objects created by service modules.
90 // Currently we have no way of distinguishing if a Create was called by the running application, 97 // Currently we have no way of distinguishing if a Create was called by the running application,
91 // or by a service module. Approach this once we have separated the service modules into their own processes 98 // or by a service module. Approach this once we have separated the service modules into their
99 // own processes
92 100
93 /// Current memory that the processes in this category are using 101 /// Current memory that the processes in this category are using
94 s32 current_commit = 0; 102 s32 current_commit = 0;
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 4b359ed07..71e41079b 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -10,11 +10,13 @@
10 10
11namespace Kernel { 11namespace Kernel {
12 12
13Semaphore::Semaphore() {} 13Semaphore::Semaphore() {
14Semaphore::~Semaphore() {} 14}
15Semaphore::~Semaphore() {
16}
15 17
16ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, 18ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
17 std::string name) { 19 std::string name) {
18 20
19 if (initial_count > max_count) 21 if (initial_count > max_count)
20 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, 22 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 390f5e495..ed7d9a85c 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -23,17 +23,23 @@ public:
23 * @return The created semaphore 23 * @return The created semaphore
24 */ 24 */
25 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, 25 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count,
26 std::string name = "Unknown"); 26 std::string name = "Unknown");
27 27
28 std::string GetTypeName() const override { return "Semaphore"; } 28 std::string GetTypeName() const override {
29 std::string GetName() const override { return name; } 29 return "Semaphore";
30 }
31 std::string GetName() const override {
32 return name;
33 }
30 34
31 static const HandleType HANDLE_TYPE = HandleType::Semaphore; 35 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
32 HandleType GetHandleType() const override { return HANDLE_TYPE; } 36 HandleType GetHandleType() const override {
37 return HANDLE_TYPE;
38 }
33 39
34 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have 40 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
35 s32 available_count; ///< Number of free slots left in the semaphore 41 s32 available_count; ///< Number of free slots left in the semaphore
36 std::string name; ///< Name of semaphore (optional) 42 std::string name; ///< Name of semaphore (optional)
37 43
38 bool ShouldWait() override; 44 bool ShouldWait() override;
39 void Acquire() override; 45 void Acquire() override;
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index fcc684a20..7c690fa7f 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -13,8 +13,10 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16ServerPort::ServerPort() {} 16ServerPort::ServerPort() {
17ServerPort::~ServerPort() {} 17}
18ServerPort::~ServerPort() {
19}
18 20
19bool ServerPort::ShouldWait() { 21bool ServerPort::ShouldWait() {
20 // If there are no pending sessions, we wait until a new one is added. 22 // If there are no pending sessions, we wait until a new one is added.
@@ -25,7 +27,8 @@ void ServerPort::Acquire() {
25 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 27 ASSERT_MSG(!ShouldWait(), "object unavailable!");
26} 28}
27 29
28std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(u32 max_sessions, std::string name) { 30std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>>
31ServerPort::CreatePortPair(u32 max_sessions, std::string name) {
29 SharedPtr<ServerPort> server_port(new ServerPort); 32 SharedPtr<ServerPort> server_port(new ServerPort);
30 SharedPtr<ClientPort> client_port(new ClientPort); 33 SharedPtr<ClientPort> client_port(new ClientPort);
31 34
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index e9c972ce6..e43d48674 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -23,17 +23,25 @@ public:
23 * @param name Optional name of the ports 23 * @param name Optional name of the ports
24 * @return The created port tuple 24 * @return The created port tuple
25 */ 25 */
26 static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(u32 max_sessions, std::string name = "UnknownPort"); 26 static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>>
27 CreatePortPair(u32 max_sessions, std::string name = "UnknownPort");
27 28
28 std::string GetTypeName() const override { return "ServerPort"; } 29 std::string GetTypeName() const override {
29 std::string GetName() const override { return name; } 30 return "ServerPort";
31 }
32 std::string GetName() const override {
33 return name;
34 }
30 35
31 static const HandleType HANDLE_TYPE = HandleType::ServerPort; 36 static const HandleType HANDLE_TYPE = HandleType::ServerPort;
32 HandleType GetHandleType() const override { return HANDLE_TYPE; } 37 HandleType GetHandleType() const override {
38 return HANDLE_TYPE;
39 }
33 40
34 std::string name; ///< Name of port (optional) 41 std::string name; ///< Name of port (optional)
35 42
36 std::vector<SharedPtr<WaitObject>> pending_sessions; ///< ServerSessions waiting to be accepted by the port 43 std::vector<SharedPtr<WaitObject>>
44 pending_sessions; ///< ServerSessions waiting to be accepted by the port
37 45
38 bool ShouldWait() override; 46 bool ShouldWait() override;
39 void Acquire() override; 47 void Acquire() override;
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp
index 0594967f8..61457845a 100644
--- a/src/core/hle/kernel/session.cpp
+++ b/src/core/hle/kernel/session.cpp
@@ -7,7 +7,8 @@
7 7
8namespace Kernel { 8namespace Kernel {
9 9
10Session::Session() {} 10Session::Session() {
11Session::~Session() {} 11}
12 12Session::~Session() {
13}
13} 14}
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index 8ec889967..8e4e010b8 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -19,12 +19,13 @@ namespace IPC {
19enum DescriptorType : u32 { 19enum DescriptorType : u32 {
20 // Buffer related desciptors types (mask : 0x0F) 20 // Buffer related desciptors types (mask : 0x0F)
21 StaticBuffer = 0x02, 21 StaticBuffer = 0x02,
22 PXIBuffer = 0x04, 22 PXIBuffer = 0x04,
23 MappedBuffer = 0x08, 23 MappedBuffer = 0x08,
24 // Handle related descriptors types (mask : 0x30, but need to check for buffer related descriptors first ) 24 // Handle related descriptors types (mask : 0x30, but need to check for buffer related
25 CopyHandle = 0x00, 25 // descriptors first )
26 MoveHandle = 0x10, 26 CopyHandle = 0x00,
27 CallingPid = 0x20, 27 MoveHandle = 0x10,
28 CallingPid = 0x20,
28}; 29};
29 30
30/** 31/**
@@ -34,24 +35,28 @@ enum DescriptorType : u32 {
34 * @param translate_params_size Size of the translate parameters in words. Up to 63. 35 * @param translate_params_size Size of the translate parameters in words. Up to 63.
35 * @return The created IPC header. 36 * @return The created IPC header.
36 * 37 *
37 * Normal parameters are sent directly to the process while the translate parameters might go through modifications and checks by the kernel. 38 * Normal parameters are sent directly to the process while the translate parameters might go
39 * through modifications and checks by the kernel.
38 * The translate parameters are described by headers generated with the IPC::*Desc functions. 40 * The translate parameters are described by headers generated with the IPC::*Desc functions.
39 * 41 *
40 * @note While #normal_params is equivalent to the number of normal parameters, #translate_params_size includes the size occupied by the translate parameters headers. 42 * @note While #normal_params is equivalent to the number of normal parameters,
43 * #translate_params_size includes the size occupied by the translate parameters headers.
41 */ 44 */
42constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, unsigned int translate_params_size) { 45constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params,
43 return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) | (u32(translate_params_size) & 0x3F); 46 unsigned int translate_params_size) {
47 return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) |
48 (u32(translate_params_size) & 0x3F);
44} 49}
45 50
46union Header { 51union Header {
47 u32 raw; 52 u32 raw;
48 BitField< 0, 6, u32> translate_params_size; 53 BitField<0, 6, u32> translate_params_size;
49 BitField< 6, 6, u32> normal_params; 54 BitField<6, 6, u32> normal_params;
50 BitField<16, 16, u32> command_id; 55 BitField<16, 16, u32> command_id;
51}; 56};
52 57
53inline Header ParseHeader(u32 header) { 58inline Header ParseHeader(u32 header) {
54 return{ header }; 59 return {header};
55} 60}
56 61
57constexpr u32 MoveHandleDesc(u32 num_handles = 1) { 62constexpr u32 MoveHandleDesc(u32 num_handles = 1) {
@@ -80,27 +85,29 @@ constexpr u32 StaticBufferDesc(u32 size, u8 buffer_id) {
80 85
81union StaticBufferDescInfo { 86union StaticBufferDescInfo {
82 u32 raw; 87 u32 raw;
83 BitField< 10, 4, u32> buffer_id; 88 BitField<10, 4, u32> buffer_id;
84 BitField< 14, 18, u32> size; 89 BitField<14, 18, u32> size;
85}; 90};
86 91
87inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { 92inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) {
88 return{ desc }; 93 return {desc};
89} 94}
90 95
91/** 96/**
92 * @brief Creates a header describing a buffer to be sent over PXI. 97 * @brief Creates a header describing a buffer to be sent over PXI.
93 * @param size Size of the buffer. Max 0x00FFFFFF. 98 * @param size Size of the buffer. Max 0x00FFFFFF.
94 * @param buffer_id The Id of the buffer. Max 0xF. 99 * @param buffer_id The Id of the buffer. Max 0xF.
95 * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have read-write access. 100 * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have
101 * read-write access.
96 * @return The created PXI buffer header. 102 * @return The created PXI buffer header.
97 * 103 *
98 * The next value is a phys-address of a table located in the BASE memregion. 104 * The next value is a phys-address of a table located in the BASE memregion.
99 */ 105 */
100inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) { 106inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) {
101 u32 type = PXIBuffer; 107 u32 type = PXIBuffer;
102 if (is_read_only) type |= 0x2; 108 if (is_read_only)
103 return type | (size << 8) | ((buffer_id & 0xF) << 4); 109 type |= 0x2;
110 return type | (size << 8) | ((buffer_id & 0xF) << 4);
104} 111}
105 112
106enum MappedBufferPermissions { 113enum MappedBufferPermissions {
@@ -115,12 +122,12 @@ constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) {
115 122
116union MappedBufferDescInfo { 123union MappedBufferDescInfo {
117 u32 raw; 124 u32 raw;
118 BitField< 4, 28, u32> size; 125 BitField<4, 28, u32> size;
119 BitField< 1, 2, MappedBufferPermissions> perms; 126 BitField<1, 2, MappedBufferPermissions> perms;
120}; 127};
121 128
122inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { 129inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) {
123 return{ desc }; 130 return {desc};
124} 131}
125 132
126inline DescriptorType GetDescriptorType(u32 descriptor) { 133inline DescriptorType GetDescriptorType(u32 descriptor) {
@@ -153,7 +160,8 @@ static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of
153 * @return Pointer to command buffer 160 * @return Pointer to command buffer
154 */ 161 */
155inline u32* GetCommandBuffer(const int offset = 0) { 162inline u32* GetCommandBuffer(const int offset = 0) {
156 return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset + offset); 163 return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset +
164 offset);
157} 165}
158 166
159/** 167/**
@@ -183,10 +191,14 @@ public:
183 Session(); 191 Session();
184 ~Session() override; 192 ~Session() override;
185 193
186 std::string GetTypeName() const override { return "Session"; } 194 std::string GetTypeName() const override {
195 return "Session";
196 }
187 197
188 static const HandleType HANDLE_TYPE = HandleType::Session; 198 static const HandleType HANDLE_TYPE = HandleType::Session;
189 HandleType GetHandleType() const override { return HANDLE_TYPE; } 199 HandleType GetHandleType() const override {
200 return HANDLE_TYPE;
201 }
190 202
191 /** 203 /**
192 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls 204 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls
@@ -205,5 +217,4 @@ public:
205 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 217 ASSERT_MSG(!ShouldWait(), "object unavailable!");
206 } 218 }
207}; 219};
208
209} 220}
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 6a22c8986..74f40930c 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -6,17 +6,21 @@
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8 8
9#include "core/memory.h"
10#include "core/hle/kernel/memory.h" 9#include "core/hle/kernel/memory.h"
11#include "core/hle/kernel/shared_memory.h" 10#include "core/hle/kernel/shared_memory.h"
11#include "core/memory.h"
12 12
13namespace Kernel { 13namespace Kernel {
14 14
15SharedMemory::SharedMemory() {} 15SharedMemory::SharedMemory() {
16SharedMemory::~SharedMemory() {} 16}
17SharedMemory::~SharedMemory() {
18}
17 19
18SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, 20SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size,
19 MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) { 21 MemoryPermission permissions,
22 MemoryPermission other_permissions, VAddr address,
23 MemoryRegion region, std::string name) {
20 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 24 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
21 25
22 shared_memory->owner_process = owner_process; 26 shared_memory->owner_process = owner_process;
@@ -31,7 +35,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
31 MemoryRegionInfo* memory_region = GetMemoryRegion(region); 35 MemoryRegionInfo* memory_region = GetMemoryRegion(region);
32 auto& linheap_memory = memory_region->linear_heap_memory; 36 auto& linheap_memory = memory_region->linear_heap_memory;
33 37
34 ASSERT_MSG(linheap_memory->size() + size <= memory_region->size, "Not enough space in region to allocate shared memory!"); 38 ASSERT_MSG(linheap_memory->size() + size <= memory_region->size,
39 "Not enough space in region to allocate shared memory!");
35 40
36 shared_memory->backing_block = linheap_memory; 41 shared_memory->backing_block = linheap_memory;
37 shared_memory->backing_block_offset = linheap_memory->size(); 42 shared_memory->backing_block_offset = linheap_memory->size();
@@ -39,7 +44,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
39 linheap_memory->insert(linheap_memory->end(), size, 0); 44 linheap_memory->insert(linheap_memory->end(), size, 0);
40 memory_region->used += size; 45 memory_region->used += size;
41 46
42 shared_memory->linear_heap_phys_address = Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset; 47 shared_memory->linear_heap_phys_address =
48 Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset;
43 49
44 // Increase the amount of used linear heap memory for the owner process. 50 // Increase the amount of used linear heap memory for the owner process.
45 if (shared_memory->owner_process != nullptr) { 51 if (shared_memory->owner_process != nullptr) {
@@ -51,18 +57,20 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
51 Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); 57 Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
52 } 58 }
53 } else { 59 } else {
54 // TODO(Subv): What happens if an application tries to create multiple memory blocks pointing to the same address? 60 // TODO(Subv): What happens if an application tries to create multiple memory blocks
61 // pointing to the same address?
55 auto& vm_manager = shared_memory->owner_process->vm_manager; 62 auto& vm_manager = shared_memory->owner_process->vm_manager;
56 // The memory is already available and mapped in the owner process. 63 // The memory is already available and mapped in the owner process.
57 auto vma = vm_manager.FindVMA(address)->second; 64 auto vma = vm_manager.FindVMA(address)->second;
58 // Copy it over to our own storage 65 // Copy it over to our own storage
59 shared_memory->backing_block = std::make_shared<std::vector<u8>>(vma.backing_block->data() + vma.offset, 66 shared_memory->backing_block = std::make_shared<std::vector<u8>>(
60 vma.backing_block->data() + vma.offset + size); 67 vma.backing_block->data() + vma.offset, vma.backing_block->data() + vma.offset + size);
61 shared_memory->backing_block_offset = 0; 68 shared_memory->backing_block_offset = 0;
62 // Unmap the existing pages 69 // Unmap the existing pages
63 vm_manager.UnmapRange(address, size); 70 vm_manager.UnmapRange(address, size);
64 // Map our own block into the address space 71 // Map our own block into the address space
65 vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size, MemoryState::Shared); 72 vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size,
73 MemoryState::Shared);
66 // Reprotect the block with the new permissions 74 // Reprotect the block with the new permissions
67 vm_manager.ReprotectRange(address, size, ConvertPermissions(permissions)); 75 vm_manager.ReprotectRange(address, size, ConvertPermissions(permissions));
68 } 76 }
@@ -71,8 +79,11 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
71 return shared_memory; 79 return shared_memory;
72} 80}
73 81
74SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, 82SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block,
75 MemoryPermission permissions, MemoryPermission other_permissions, std::string name) { 83 u32 offset, u32 size,
84 MemoryPermission permissions,
85 MemoryPermission other_permissions,
86 std::string name) {
76 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 87 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
77 88
78 shared_memory->owner_process = nullptr; 89 shared_memory->owner_process = nullptr;
@@ -88,27 +99,31 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vecto
88} 99}
89 100
90ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions, 101ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions,
91 MemoryPermission other_permissions) { 102 MemoryPermission other_permissions) {
92 103
93 MemoryPermission own_other_permissions = target_process == owner_process ? this->permissions : this->other_permissions; 104 MemoryPermission own_other_permissions =
105 target_process == owner_process ? this->permissions : this->other_permissions;
94 106
95 // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare 107 // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare
96 if (base_address == 0 && other_permissions != MemoryPermission::DontCare) { 108 if (base_address == 0 && other_permissions != MemoryPermission::DontCare) {
97 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 109 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
110 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
98 } 111 }
99 112
100 // Error out if the requested permissions don't match what the creator process allows. 113 // Error out if the requested permissions don't match what the creator process allows.
101 if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) { 114 if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) {
102 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", 115 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
103 GetObjectId(), address, name.c_str()); 116 GetObjectId(), address, name.c_str());
104 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 117 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
118 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
105 } 119 }
106 120
107 // Heap-backed memory blocks can not be mapped with other_permissions = DontCare 121 // Heap-backed memory blocks can not be mapped with other_permissions = DontCare
108 if (base_address != 0 && other_permissions == MemoryPermission::DontCare) { 122 if (base_address != 0 && other_permissions == MemoryPermission::DontCare) {
109 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", 123 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
110 GetObjectId(), address, name.c_str()); 124 GetObjectId(), address, name.c_str());
111 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 125 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
126 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
112 } 127 }
113 128
114 // Error out if the provided permissions are not compatible with what the creator process needs. 129 // Error out if the provided permissions are not compatible with what the creator process needs.
@@ -116,12 +131,14 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
116 static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) { 131 static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) {
117 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", 132 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
118 GetObjectId(), address, name.c_str()); 133 GetObjectId(), address, name.c_str());
119 return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 134 return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS,
135 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
120 } 136 }
121 137
122 // TODO(Subv): Check for the Shared Device Mem flag in the creator process. 138 // TODO(Subv): Check for the Shared Device Mem flag in the creator process.
123 /*if (was_created_with_shared_device_mem && address != 0) { 139 /*if (was_created_with_shared_device_mem && address != 0) {
124 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 140 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
141 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
125 }*/ 142 }*/
126 143
127 // TODO(Subv): The same process that created a SharedMemory object 144 // TODO(Subv): The same process that created a SharedMemory object
@@ -144,23 +161,29 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
144 } 161 }
145 162
146 // Map the memory block into the target process 163 // Map the memory block into the target process
147 auto result = target_process->vm_manager.MapMemoryBlock(target_address, backing_block, backing_block_offset, size, MemoryState::Shared); 164 auto result = target_process->vm_manager.MapMemoryBlock(
165 target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
148 if (result.Failed()) { 166 if (result.Failed()) {
149 LOG_ERROR(Kernel, "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory", 167 LOG_ERROR(
150 GetObjectId(), target_address, name.c_str()); 168 Kernel,
169 "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory",
170 GetObjectId(), target_address, name.c_str());
151 return result.Code(); 171 return result.Code();
152 } 172 }
153 173
154 return target_process->vm_manager.ReprotectRange(target_address, size, ConvertPermissions(permissions)); 174 return target_process->vm_manager.ReprotectRange(target_address, size,
175 ConvertPermissions(permissions));
155} 176}
156 177
157ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) { 178ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) {
158 // TODO(Subv): Verify what happens if the application tries to unmap an address that is not mapped to a SharedMemory. 179 // TODO(Subv): Verify what happens if the application tries to unmap an address that is not
180 // mapped to a SharedMemory.
159 return target_process->vm_manager.UnmapRange(address, size); 181 return target_process->vm_manager.UnmapRange(address, size);
160} 182}
161 183
162VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) { 184VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
163 u32 masked_permissions = static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute); 185 u32 masked_permissions =
186 static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute);
164 return static_cast<VMAPermission>(masked_permissions); 187 return static_cast<VMAPermission>(masked_permissions);
165}; 188};
166 189
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 0c404a9f8..afb142380 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -16,15 +16,15 @@ namespace Kernel {
16 16
17/// Permissions for mapped shared memory blocks 17/// Permissions for mapped shared memory blocks
18enum class MemoryPermission : u32 { 18enum class MemoryPermission : u32 {
19 None = 0, 19 None = 0,
20 Read = (1u << 0), 20 Read = (1u << 0),
21 Write = (1u << 1), 21 Write = (1u << 1),
22 ReadWrite = (Read | Write), 22 ReadWrite = (Read | Write),
23 Execute = (1u << 2), 23 Execute = (1u << 2),
24 ReadExecute = (Read | Execute), 24 ReadExecute = (Read | Execute),
25 WriteExecute = (Write | Execute), 25 WriteExecute = (Write | Execute),
26 ReadWriteExecute = (Read | Write | Execute), 26 ReadWriteExecute = (Read | Write | Execute),
27 DontCare = (1u << 28) 27 DontCare = (1u << 28)
28}; 28};
29 29
30class SharedMemory final : public Object { 30class SharedMemory final : public Object {
@@ -34,13 +34,18 @@ public:
34 * @param owner_process Process that created this shared memory object. 34 * @param owner_process Process that created this shared memory object.
35 * @param size Size of the memory block. Must be page-aligned. 35 * @param size Size of the memory block. Must be page-aligned.
36 * @param permissions Permission restrictions applied to the process which created the block. 36 * @param permissions Permission restrictions applied to the process which created the block.
37 * @param other_permissions Permission restrictions applied to other processes mapping the block. 37 * @param other_permissions Permission restrictions applied to other processes mapping the
38 * block.
38 * @param address The address from which to map the Shared Memory. 39 * @param address The address from which to map the Shared Memory.
39 * @param region If the address is 0, the shared memory will be allocated in this region of the linear heap. 40 * @param region If the address is 0, the shared memory will be allocated in this region of the
41 * linear heap.
40 * @param name Optional object name, used for debugging purposes. 42 * @param name Optional object name, used for debugging purposes.
41 */ 43 */
42 static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, 44 static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size,
43 MemoryPermission other_permissions, VAddr address = 0, MemoryRegion region = MemoryRegion::BASE, std::string name = "Unknown"); 45 MemoryPermission permissions,
46 MemoryPermission other_permissions, VAddr address = 0,
47 MemoryRegion region = MemoryRegion::BASE,
48 std::string name = "Unknown");
44 49
45 /** 50 /**
46 * Creates a shared memory object from a block of memory managed by an HLE applet. 51 * Creates a shared memory object from a block of memory managed by an HLE applet.
@@ -48,17 +53,27 @@ public:
48 * @param offset The offset into the heap block that the SharedMemory will map. 53 * @param offset The offset into the heap block that the SharedMemory will map.
49 * @param size Size of the memory block. Must be page-aligned. 54 * @param size Size of the memory block. Must be page-aligned.
50 * @param permissions Permission restrictions applied to the process which created the block. 55 * @param permissions Permission restrictions applied to the process which created the block.
51 * @param other_permissions Permission restrictions applied to other processes mapping the block. 56 * @param other_permissions Permission restrictions applied to other processes mapping the
57 * block.
52 * @param name Optional object name, used for debugging purposes. 58 * @param name Optional object name, used for debugging purposes.
53 */ 59 */
54 static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, 60 static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block,
55 MemoryPermission permissions, MemoryPermission other_permissions, std::string name = "Unknown Applet"); 61 u32 offset, u32 size,
56 62 MemoryPermission permissions,
57 std::string GetTypeName() const override { return "SharedMemory"; } 63 MemoryPermission other_permissions,
58 std::string GetName() const override { return name; } 64 std::string name = "Unknown Applet");
65
66 std::string GetTypeName() const override {
67 return "SharedMemory";
68 }
69 std::string GetName() const override {
70 return name;
71 }
59 72
60 static const HandleType HANDLE_TYPE = HandleType::SharedMemory; 73 static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
61 HandleType GetHandleType() const override { return HANDLE_TYPE; } 74 HandleType GetHandleType() const override {
75 return HANDLE_TYPE;
76 }
62 77
63 /** 78 /**
64 * Converts the specified MemoryPermission into the equivalent VMAPermission. 79 * Converts the specified MemoryPermission into the equivalent VMAPermission.
@@ -73,7 +88,8 @@ public:
73 * @param permissions Memory block map permissions (specified by SVC field) 88 * @param permissions Memory block map permissions (specified by SVC field)
74 * @param other_permissions Memory block map other permissions (specified by SVC field) 89 * @param other_permissions Memory block map other permissions (specified by SVC field)
75 */ 90 */
76 ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions, MemoryPermission other_permissions); 91 ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions,
92 MemoryPermission other_permissions);
77 93
78 /** 94 /**
79 * Unmaps a shared memory block from the specified address in system memory 95 * Unmaps a shared memory block from the specified address in system memory
@@ -94,7 +110,8 @@ public:
94 SharedPtr<Process> owner_process; 110 SharedPtr<Process> owner_process;
95 /// Address of shared memory block in the owner process if specified. 111 /// Address of shared memory block in the owner process if specified.
96 VAddr base_address; 112 VAddr base_address;
97 /// Physical address of the shared memory block in the linear heap if no address was specified during creation. 113 /// Physical address of the shared memory block in the linear heap if no address was specified
114 /// during creation.
98 PAddr linear_heap_phys_address; 115 PAddr linear_heap_phys_address;
99 /// Backing memory for this shared memory block. 116 /// Backing memory for this shared memory block.
100 std::shared_ptr<std::vector<u8>> backing_block; 117 std::shared_ptr<std::vector<u8>> backing_block;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index f1e5cf3cb..59272715f 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -18,10 +18,10 @@
18#include "core/core_timing.h" 18#include "core/core_timing.h"
19#include "core/hle/hle.h" 19#include "core/hle/hle.h"
20#include "core/hle/kernel/kernel.h" 20#include "core/hle/kernel/kernel.h"
21#include "core/hle/kernel/process.h"
22#include "core/hle/kernel/thread.h"
23#include "core/hle/kernel/memory.h" 21#include "core/hle/kernel/memory.h"
24#include "core/hle/kernel/mutex.h" 22#include "core/hle/kernel/mutex.h"
23#include "core/hle/kernel/process.h"
24#include "core/hle/kernel/thread.h"
25#include "core/hle/result.h" 25#include "core/hle/result.h"
26#include "core/memory.h" 26#include "core/memory.h"
27 27
@@ -46,7 +46,7 @@ static Kernel::HandleTable wakeup_callback_handle_table;
46static std::vector<SharedPtr<Thread>> thread_list; 46static std::vector<SharedPtr<Thread>> thread_list;
47 47
48// Lists only ready thread ids. 48// Lists only ready thread ids.
49static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> ready_queue; 49static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST + 1> ready_queue;
50 50
51static Thread* current_thread; 51static Thread* current_thread;
52 52
@@ -61,8 +61,10 @@ inline static u32 const NewThreadId() {
61 return next_thread_id++; 61 return next_thread_id++;
62} 62}
63 63
64Thread::Thread() {} 64Thread::Thread() {
65Thread::~Thread() {} 65}
66Thread::~Thread() {
67}
66 68
67Thread* GetCurrentThread() { 69Thread* GetCurrentThread() {
68 return current_thread; 70 return current_thread;
@@ -103,7 +105,7 @@ void Thread::Stop() {
103 105
104 // Clean up thread from ready queue 106 // Clean up thread from ready queue
105 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) 107 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
106 if (status == THREADSTATUS_READY){ 108 if (status == THREADSTATUS_READY) {
107 ready_queue.remove(current_priority, this); 109 ready_queue.remove(current_priority, this);
108 } 110 }
109 111
@@ -119,7 +121,8 @@ void Thread::Stop() {
119 121
120 // Mark the TLS slot in the thread's page as free. 122 // Mark the TLS slot in the thread's page as free.
121 u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; 123 u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
122 u32 tls_slot = ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; 124 u32 tls_slot =
125 ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE;
123 Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot); 126 Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot);
124 127
125 HLE::Reschedule(__func__); 128 HLE::Reschedule(__func__);
@@ -137,7 +140,7 @@ Thread* ArbitrateHighestPriorityThread(u32 address) {
137 if (thread == nullptr) 140 if (thread == nullptr)
138 continue; 141 continue;
139 142
140 if(thread->current_priority <= priority) { 143 if (thread->current_priority <= priority) {
141 highest_priority_thread = thread.get(); 144 highest_priority_thread = thread.get();
142 priority = thread->current_priority; 145 priority = thread->current_priority;
143 } 146 }
@@ -170,7 +173,7 @@ static void PriorityBoostStarvedThreads() {
170 // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler 173 // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler
171 // should probably be reversed to verify this. 174 // should probably be reversed to verify this.
172 175
173 const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long 176 const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long
174 177
175 u64 delta = current_ticks - thread->last_running_ticks; 178 u64 delta = current_ticks - thread->last_running_ticks;
176 179
@@ -193,10 +196,12 @@ static std::tuple<u32*, u32*> GetWaitSynchTimeoutParameterRegister(Thread* threa
193 196
194 if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) { 197 if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) {
195 // svc #0x24 (WaitSynchronization1) 198 // svc #0x24 (WaitSynchronization1)
196 return std::make_tuple(&thread->context.cpu_registers[2], &thread->context.cpu_registers[3]); 199 return std::make_tuple(&thread->context.cpu_registers[2],
200 &thread->context.cpu_registers[3]);
197 } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) { 201 } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) {
198 // svc #0x25 (WaitSynchronizationN) 202 // svc #0x25 (WaitSynchronizationN)
199 return std::make_tuple(&thread->context.cpu_registers[0], &thread->context.cpu_registers[4]); 203 return std::make_tuple(&thread->context.cpu_registers[0],
204 &thread->context.cpu_registers[4]);
200 } 205 }
201 206
202 UNREACHABLE(); 207 UNREACHABLE();
@@ -245,7 +250,8 @@ static void SwitchContext(Thread* new_thread) {
245 250
246 // Load context of new thread 251 // Load context of new thread
247 if (new_thread) { 252 if (new_thread) {
248 DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); 253 DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY,
254 "Thread must be ready to become running.");
249 255
250 // Cancel any outstanding wakeup events for this thread 256 // Cancel any outstanding wakeup events for this thread
251 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle); 257 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle);
@@ -263,7 +269,7 @@ static void SwitchContext(Thread* new_thread) {
263 new_thread->context.pc -= thumb_mode ? 2 : 4; 269 new_thread->context.pc -= thumb_mode ? 2 : 4;
264 270
265 // Get the register for timeout parameter 271 // Get the register for timeout parameter
266 u32* timeout_low, *timeout_high; 272 u32 *timeout_low, *timeout_high;
267 std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread); 273 std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread);
268 274
269 // Update the timeout parameter 275 // Update the timeout parameter
@@ -307,7 +313,7 @@ static Thread* PopNextReadyThread() {
307 // Otherwise just keep going with the current thread 313 // Otherwise just keep going with the current thread
308 next = thread; 314 next = thread;
309 } 315 }
310 } else { 316 } else {
311 next = ready_queue.pop_first(); 317 next = ready_queue.pop_first();
312 } 318 }
313 319
@@ -321,7 +327,8 @@ void WaitCurrentThread_Sleep() {
321 HLE::Reschedule(__func__); 327 HLE::Reschedule(__func__);
322} 328}
323 329
324void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all) { 330void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects,
331 bool wait_set_output, bool wait_all) {
325 Thread* thread = GetCurrentThread(); 332 Thread* thread = GetCurrentThread();
326 thread->wait_set_output = wait_set_output; 333 thread->wait_set_output = wait_set_output;
327 thread->wait_all = wait_all; 334 thread->wait_all = wait_all;
@@ -352,7 +359,8 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
352 359
353 if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) { 360 if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) {
354 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, 361 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
355 ErrorSummary::StatusChanged, ErrorLevel::Info)); 362 ErrorSummary::StatusChanged,
363 ErrorLevel::Info));
356 364
357 if (thread->wait_set_output) 365 if (thread->wait_set_output)
358 thread->SetWaitSynchronizationOutput(-1); 366 thread->SetWaitSynchronizationOutput(-1);
@@ -372,25 +380,25 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
372 380
373void Thread::ResumeFromWait() { 381void Thread::ResumeFromWait() {
374 switch (status) { 382 switch (status) {
375 case THREADSTATUS_WAIT_SYNCH: 383 case THREADSTATUS_WAIT_SYNCH:
376 case THREADSTATUS_WAIT_ARB: 384 case THREADSTATUS_WAIT_ARB:
377 case THREADSTATUS_WAIT_SLEEP: 385 case THREADSTATUS_WAIT_SLEEP:
378 break; 386 break;
379 387
380 case THREADSTATUS_READY: 388 case THREADSTATUS_READY:
381 // If the thread is waiting on multiple wait objects, it might be awoken more than once 389 // If the thread is waiting on multiple wait objects, it might be awoken more than once
382 // before actually resuming. We can ignore subsequent wakeups if the thread status has 390 // before actually resuming. We can ignore subsequent wakeups if the thread status has
383 // already been set to THREADSTATUS_READY. 391 // already been set to THREADSTATUS_READY.
384 return; 392 return;
385 393
386 case THREADSTATUS_RUNNING: 394 case THREADSTATUS_RUNNING:
387 DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId()); 395 DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId());
388 return; 396 return;
389 case THREADSTATUS_DEAD: 397 case THREADSTATUS_DEAD:
390 // This should never happen, as threads must complete before being stopped. 398 // This should never happen, as threads must complete before being stopped.
391 DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.", 399 DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.",
392 GetObjectId()); 400 GetObjectId());
393 return; 401 return;
394 } 402 }
395 403
396 ready_queue.push_back(current_priority, this); 404 ready_queue.push_back(current_priority, this);
@@ -405,7 +413,8 @@ static void DebugThreadQueue() {
405 if (!thread) { 413 if (!thread) {
406 LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD"); 414 LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD");
407 } else { 415 } else {
408 LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, GetCurrentThread()->GetObjectId()); 416 LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority,
417 GetCurrentThread()->GetObjectId());
409 } 418 }
410 419
411 for (auto& t : thread_list) { 420 for (auto& t : thread_list) {
@@ -448,7 +457,8 @@ std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& t
448 * @param entry_point Address of entry point for execution 457 * @param entry_point Address of entry point for execution
449 * @param arg User argument for thread 458 * @param arg User argument for thread
450 */ 459 */
451static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) { 460static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point,
461 u32 arg) {
452 memset(&context, 0, sizeof(Core::ThreadContext)); 462 memset(&context, 0, sizeof(Core::ThreadContext));
453 463
454 context.cpu_registers[0] = arg; 464 context.cpu_registers[0] = arg;
@@ -458,11 +468,11 @@ static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32
458} 468}
459 469
460ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, 470ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority,
461 u32 arg, s32 processor_id, VAddr stack_top) { 471 u32 arg, s32 processor_id, VAddr stack_top) {
462 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { 472 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
463 s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 473 s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
464 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", 474 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", name.c_str(),
465 name.c_str(), priority, new_priority); 475 priority, new_priority);
466 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm 476 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
467 // validity of this 477 // validity of this
468 priority = new_priority; 478 priority = new_priority;
@@ -472,7 +482,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
472 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); 482 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point);
473 // TODO: Verify error 483 // TODO: Verify error
474 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 484 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
475 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 485 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
476 } 486 }
477 487
478 SharedPtr<Thread> thread(new Thread); 488 SharedPtr<Thread> thread(new Thread);
@@ -511,8 +521,10 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
511 auto& linheap_memory = memory_region->linear_heap_memory; 521 auto& linheap_memory = memory_region->linear_heap_memory;
512 522
513 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { 523 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) {
514 LOG_ERROR(Kernel_SVC, "Not enough space in region to allocate a new TLS page for thread"); 524 LOG_ERROR(Kernel_SVC,
515 return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel, ErrorSummary::OutOfResource, ErrorLevel::Permanent); 525 "Not enough space in region to allocate a new TLS page for thread");
526 return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
527 ErrorSummary::OutOfResource, ErrorLevel::Permanent);
516 } 528 }
517 529
518 u32 offset = linheap_memory->size(); 530 u32 offset = linheap_memory->size();
@@ -537,7 +549,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
537 549
538 // Mark the slot as used 550 // Mark the slot as used
539 tls_slots[available_page].set(available_slot); 551 tls_slots[available_page].set(available_slot);
540 thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + available_slot * Memory::TLS_ENTRY_SIZE; 552 thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE +
553 available_slot * Memory::TLS_ENTRY_SIZE;
541 554
542 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used 555 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
543 // to initialize the context 556 // to initialize the context
@@ -551,10 +564,12 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
551 return MakeResult<SharedPtr<Thread>>(std::move(thread)); 564 return MakeResult<SharedPtr<Thread>>(std::move(thread));
552} 565}
553 566
554// TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be returned. 567// TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be
568// returned.
555static void ClampPriority(const Thread* thread, s32* priority) { 569static void ClampPriority(const Thread* thread, s32* priority) {
556 if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) { 570 if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) {
557 DEBUG_ASSERT_MSG(false, "Application passed an out of range priority. An error should be returned."); 571 DEBUG_ASSERT_MSG(
572 false, "Application passed an out of range priority. An error should be returned.");
558 573
559 s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 574 s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
560 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", 575 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d",
@@ -586,12 +601,13 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) {
586 DEBUG_ASSERT(!GetCurrentThread()); 601 DEBUG_ASSERT(!GetCurrentThread());
587 602
588 // Initialize new "main" thread 603 // Initialize new "main" thread
589 auto thread_res = Thread::Create("main", entry_point, priority, 0, 604 auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0,
590 THREADPROCESSORID_0, Memory::HEAP_VADDR_END); 605 Memory::HEAP_VADDR_END);
591 606
592 SharedPtr<Thread> thread = thread_res.MoveFrom(); 607 SharedPtr<Thread> thread = thread_res.MoveFrom();
593 608
594 thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010 609 thread->context.fpscr =
610 FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010
595 611
596 // Run new "main" thread 612 // Run new "main" thread
597 SwitchContext(thread.get()); 613 SwitchContext(thread.get());
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index deab5d5a6..2ed5cf74e 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -17,29 +17,29 @@
17#include "core/hle/kernel/kernel.h" 17#include "core/hle/kernel/kernel.h"
18#include "core/hle/result.h" 18#include "core/hle/result.h"
19 19
20enum ThreadPriority : s32{ 20enum ThreadPriority : s32 {
21 THREADPRIO_HIGHEST = 0, ///< Highest thread priority 21 THREADPRIO_HIGHEST = 0, ///< Highest thread priority
22 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps 22 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps
23 THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps 23 THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps
24 THREADPRIO_LOWEST = 63, ///< Lowest thread priority 24 THREADPRIO_LOWEST = 63, ///< Lowest thread priority
25}; 25};
26 26
27enum ThreadProcessorId : s32 { 27enum ThreadProcessorId : s32 {
28 THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader 28 THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader
29 THREADPROCESSORID_ALL = -1, ///< Run thread on either core 29 THREADPROCESSORID_ALL = -1, ///< Run thread on either core
30 THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore) 30 THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore)
31 THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore) 31 THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore)
32 THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this 32 THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this
33}; 33};
34 34
35enum ThreadStatus { 35enum ThreadStatus {
36 THREADSTATUS_RUNNING, ///< Currently running 36 THREADSTATUS_RUNNING, ///< Currently running
37 THREADSTATUS_READY, ///< Ready to run 37 THREADSTATUS_READY, ///< Ready to run
38 THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter 38 THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter
39 THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC 39 THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC
40 THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC 40 THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC
41 THREADSTATUS_DORMANT, ///< Created but not yet made ready 41 THREADSTATUS_DORMANT, ///< Created but not yet made ready
42 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated 42 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
43}; 43};
44 44
45namespace Kernel { 45namespace Kernel {
@@ -60,13 +60,19 @@ public:
60 * @return A shared pointer to the newly created thread 60 * @return A shared pointer to the newly created thread
61 */ 61 */
62 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, 62 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
63 u32 arg, s32 processor_id, VAddr stack_top); 63 u32 arg, s32 processor_id, VAddr stack_top);
64 64
65 std::string GetName() const override { return name; } 65 std::string GetName() const override {
66 std::string GetTypeName() const override { return "Thread"; } 66 return name;
67 }
68 std::string GetTypeName() const override {
69 return "Thread";
70 }
67 71
68 static const HandleType HANDLE_TYPE = HandleType::Thread; 72 static const HandleType HANDLE_TYPE = HandleType::Thread;
69 HandleType GetHandleType() const override { return HANDLE_TYPE; } 73 HandleType GetHandleType() const override {
74 return HANDLE_TYPE;
75 }
70 76
71 bool ShouldWait() override; 77 bool ShouldWait() override;
72 void Acquire() override; 78 void Acquire() override;
@@ -75,7 +81,9 @@ public:
75 * Gets the thread's current priority 81 * Gets the thread's current priority
76 * @return The current thread's priority 82 * @return The current thread's priority
77 */ 83 */
78 s32 GetPriority() const { return current_priority; } 84 s32 GetPriority() const {
85 return current_priority;
86 }
79 87
80 /** 88 /**
81 * Sets the thread's current priority 89 * Sets the thread's current priority
@@ -93,7 +101,9 @@ public:
93 * Gets the thread's thread ID 101 * Gets the thread's thread ID
94 * @return The thread's ID 102 * @return The thread's ID
95 */ 103 */
96 u32 GetThreadId() const { return thread_id; } 104 u32 GetThreadId() const {
105 return thread_id;
106 }
97 107
98 /** 108 /**
99 * Resumes a thread from waiting 109 * Resumes a thread from waiting
@@ -127,7 +137,9 @@ public:
127 * Returns the Thread Local Storage address of the current thread 137 * Returns the Thread Local Storage address of the current thread
128 * @returns VAddr of the thread's TLS 138 * @returns VAddr of the thread's TLS
129 */ 139 */
130 VAddr GetTLSAddress() const { return tls_address; } 140 VAddr GetTLSAddress() const {
141 return tls_address;
142 }
131 143
132 Core::ThreadContext context; 144 Core::ThreadContext context;
133 145
@@ -137,8 +149,8 @@ public:
137 u32 entry_point; 149 u32 entry_point;
138 u32 stack_top; 150 u32 stack_top;
139 151
140 s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application 152 s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application
141 s32 current_priority; ///< Current thread priority, can be temporarily changed 153 s32 current_priority; ///< Current thread priority, can be temporarily changed
142 154
143 u64 last_running_ticks; ///< CPU tick when thread was last running 155 u64 last_running_ticks; ///< CPU tick when thread was last running
144 156
@@ -151,11 +163,11 @@ public:
151 /// Mutexes currently held by this thread, which will be released when it exits. 163 /// Mutexes currently held by this thread, which will be released when it exits.
152 boost::container::flat_set<SharedPtr<Mutex>> held_mutexes; 164 boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
153 165
154 SharedPtr<Process> owner_process; ///< Process that owns this thread 166 SharedPtr<Process> owner_process; ///< Process that owns this thread
155 std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on 167 std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on
156 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address 168 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
157 bool wait_all; ///< True if the thread is waiting on all objects before resuming 169 bool wait_all; ///< True if the thread is waiting on all objects before resuming
158 bool wait_set_output; ///< True if the output parameter should be set on thread wakeup 170 bool wait_set_output; ///< True if the output parameter should be set on thread wakeup
159 171
160 std::string name; 172 std::string name;
161 173
@@ -205,10 +217,12 @@ void WaitCurrentThread_Sleep();
205/** 217/**
206 * Waits the current thread from a WaitSynchronization call 218 * Waits the current thread from a WaitSynchronization call
207 * @param wait_objects Kernel objects that we are waiting on 219 * @param wait_objects Kernel objects that we are waiting on
208 * @param wait_set_output If true, set the output parameter on thread wakeup (for WaitSynchronizationN only) 220 * @param wait_set_output If true, set the output parameter on thread wakeup (for
221 * WaitSynchronizationN only)
209 * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only) 222 * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only)
210 */ 223 */
211void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all); 224void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects,
225 bool wait_set_output, bool wait_all);
212 226
213/** 227/**
214 * Waits the current thread from an ArbitrateAddress call 228 * Waits the current thread from an ArbitrateAddress call
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index b8daaeede..255cb1aca 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -9,8 +9,8 @@
9 9
10#include "core/core_timing.h" 10#include "core/core_timing.h"
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/timer.h"
13#include "core/hle/kernel/thread.h" 12#include "core/hle/kernel/thread.h"
13#include "core/hle/kernel/timer.h"
14 14
15namespace Kernel { 15namespace Kernel {
16 16
@@ -20,8 +20,10 @@ static int timer_callback_event_type;
20// us to simply use a pool index or similar. 20// us to simply use a pool index or similar.
21static Kernel::HandleTable timer_callback_handle_table; 21static Kernel::HandleTable timer_callback_handle_table;
22 22
23Timer::Timer() {} 23Timer::Timer() {
24Timer::~Timer() {} 24}
25Timer::~Timer() {
26}
25 27
26SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) { 28SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) {
27 SharedPtr<Timer> timer(new Timer); 29 SharedPtr<Timer> timer(new Timer);
@@ -41,7 +43,7 @@ bool Timer::ShouldWait() {
41} 43}
42 44
43void Timer::Acquire() { 45void Timer::Acquire() {
44 ASSERT_MSG( !ShouldWait(), "object unavailable!"); 46 ASSERT_MSG(!ShouldWait(), "object unavailable!");
45 47
46 if (reset_type == ResetType::OneShot) 48 if (reset_type == ResetType::OneShot)
47 signaled = false; 49 signaled = false;
@@ -55,8 +57,8 @@ void Timer::Set(s64 initial, s64 interval) {
55 interval_delay = interval; 57 interval_delay = interval;
56 58
57 u64 initial_microseconds = initial / 1000; 59 u64 initial_microseconds = initial / 1000;
58 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), 60 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type,
59 timer_callback_event_type, callback_handle); 61 callback_handle);
60 62
61 HLE::Reschedule(__func__); 63 HLE::Reschedule(__func__);
62} 64}
@@ -73,7 +75,8 @@ void Timer::Clear() {
73 75
74/// The timer callback event, called when a timer is fired 76/// The timer callback event, called when a timer is fired
75static void TimerCallback(u64 timer_handle, int cycles_late) { 77static void TimerCallback(u64 timer_handle, int cycles_late) {
76 SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); 78 SharedPtr<Timer> timer =
79 timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle));
77 80
78 if (timer == nullptr) { 81 if (timer == nullptr) {
79 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle); 82 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle);
@@ -91,7 +94,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
91 // Reschedule the timer with the interval delay 94 // Reschedule the timer with the interval delay
92 u64 interval_microseconds = timer->interval_delay / 1000; 95 u64 interval_microseconds = timer->interval_delay / 1000;
93 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, 96 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
94 timer_callback_event_type, timer_handle); 97 timer_callback_event_type, timer_handle);
95 } 98 }
96} 99}
97 100
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index b1db60e8f..97cd0d63c 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -21,19 +21,25 @@ public:
21 */ 21 */
22 static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown"); 22 static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown");
23 23
24 std::string GetTypeName() const override { return "Timer"; } 24 std::string GetTypeName() const override {
25 std::string GetName() const override { return name; } 25 return "Timer";
26 }
27 std::string GetName() const override {
28 return name;
29 }
26 30
27 static const HandleType HANDLE_TYPE = HandleType::Timer; 31 static const HandleType HANDLE_TYPE = HandleType::Timer;
28 HandleType GetHandleType() const override { return HANDLE_TYPE; } 32 HandleType GetHandleType() const override {
33 return HANDLE_TYPE;
34 }
29 35
30 ResetType reset_type; ///< The ResetType of this timer 36 ResetType reset_type; ///< The ResetType of this timer
31 37
32 bool signaled; ///< Whether the timer has been signaled or not 38 bool signaled; ///< Whether the timer has been signaled or not
33 std::string name; ///< Name of timer (optional) 39 std::string name; ///< Name of timer (optional)
34 40
35 u64 initial_delay; ///< The delay until the timer fires for the first time 41 u64 initial_delay; ///< The delay until the timer fires for the first time
36 u64 interval_delay; ///< The delay until the timer fires after the first time 42 u64 interval_delay; ///< The delay until the timer fires after the first time
37 43
38 bool ShouldWait() override; 44 bool ShouldWait() override;
39 void Acquire() override; 45 void Acquire() override;
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 066146cff..4ad86cf48 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -15,8 +15,8 @@ namespace Kernel {
15 15
16static const char* GetMemoryStateName(MemoryState state) { 16static const char* GetMemoryStateName(MemoryState state) {
17 static const char* names[] = { 17 static const char* names[] = {
18 "Free", "Reserved", "IO", "Static", "Code", "Private", "Shared", "Continuous", "Aliased", 18 "Free", "Reserved", "IO", "Static", "Code", "Private",
19 "Alias", "AliasCode", "Locked", 19 "Shared", "Continuous", "Aliased", "Alias", "AliasCode", "Locked",
20 }; 20 };
21 21
22 return names[(int)state]; 22 return names[(int)state];
@@ -24,13 +24,12 @@ static const char* GetMemoryStateName(MemoryState state) {
24 24
25bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { 25bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
26 ASSERT(base + size == next.base); 26 ASSERT(base + size == next.base);
27 if (permissions != next.permissions || 27 if (permissions != next.permissions || meminfo_state != next.meminfo_state ||
28 meminfo_state != next.meminfo_state || 28 type != next.type) {
29 type != next.type) {
30 return false; 29 return false;
31 } 30 }
32 if (type == VMAType::AllocatedMemoryBlock && 31 if (type == VMAType::AllocatedMemoryBlock &&
33 (backing_block != next.backing_block || offset + size != next.offset)) { 32 (backing_block != next.backing_block || offset + size != next.offset)) {
34 return false; 33 return false;
35 } 34 }
36 if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) { 35 if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) {
@@ -70,7 +69,9 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const {
70} 69}
71 70
72ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, 71ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
73 std::shared_ptr<std::vector<u8>> block, size_t offset, u32 size, MemoryState state) { 72 std::shared_ptr<std::vector<u8>> block,
73 size_t offset, u32 size,
74 MemoryState state) {
74 ASSERT(block != nullptr); 75 ASSERT(block != nullptr);
75 ASSERT(offset + size <= block->size()); 76 ASSERT(offset + size <= block->size());
76 77
@@ -89,7 +90,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
89 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); 90 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
90} 91}
91 92
92ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * memory, u32 size, MemoryState state) { 93ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* memory, u32 size,
94 MemoryState state) {
93 ASSERT(memory != nullptr); 95 ASSERT(memory != nullptr);
94 96
95 // This is the appropriately sized VMA that will turn into our allocation. 97 // This is the appropriately sized VMA that will turn into our allocation.
@@ -106,7 +108,9 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * m
106 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); 108 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
107} 109}
108 110
109ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler) { 111ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size,
112 MemoryState state,
113 Memory::MMIORegionPointer mmio_handler) {
110 // This is the appropriately sized VMA that will turn into our allocation. 114 // This is the appropriately sized VMA that will turn into our allocation.
111 CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size)); 115 CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size));
112 VirtualMemoryArea& final_vma = vma_handle->second; 116 VirtualMemoryArea& final_vma = vma_handle->second;
@@ -191,15 +195,16 @@ void VMManager::RefreshMemoryBlockMappings(const std::vector<u8>* block) {
191void VMManager::LogLayout(Log::Level log_level) const { 195void VMManager::LogLayout(Log::Level log_level) const {
192 for (const auto& p : vma_map) { 196 for (const auto& p : vma_map) {
193 const VirtualMemoryArea& vma = p.second; 197 const VirtualMemoryArea& vma = p.second;
194 LOG_GENERIC(Log::Class::Kernel, log_level, "%08X - %08X size: %8X %c%c%c %s", 198 LOG_GENERIC(Log::Class::Kernel, log_level, "%08X - %08X size: %8X %c%c%c %s", vma.base,
195 vma.base, vma.base + vma.size, vma.size, 199 vma.base + vma.size, vma.size,
196 (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-', 200 (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-',
197 (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-', 201 (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-',
198 (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-', GetMemoryStateName(vma.meminfo_state)); 202 (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-',
203 GetMemoryStateName(vma.meminfo_state));
199 } 204 }
200} 205}
201 206
202VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { 207VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) {
203 // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given 208 // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given
204 // non-const access to its container. 209 // non-const access to its container.
205 return vma_map.erase(iter, iter); // Erases an empty range of elements 210 return vma_map.erase(iter, iter); // Erases an empty range of elements
@@ -337,5 +342,4 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
337 break; 342 break;
338 } 343 }
339} 344}
340
341} 345}
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 91d40655b..fbcd9870f 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -15,13 +15,13 @@
15 15
16namespace Kernel { 16namespace Kernel {
17 17
18const ResultCode ERR_INVALID_ADDRESS{ // 0xE0E01BF5 18const ResultCode ERR_INVALID_ADDRESS{// 0xE0E01BF5
19 ErrorDescription::InvalidAddress, ErrorModule::OS, 19 ErrorDescription::InvalidAddress, ErrorModule::OS,
20 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 20 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
21 21
22const ResultCode ERR_INVALID_ADDRESS_STATE{ // 0xE0A01BF5 22const ResultCode ERR_INVALID_ADDRESS_STATE{// 0xE0A01BF5
23 ErrorDescription::InvalidAddress, ErrorModule::OS, 23 ErrorDescription::InvalidAddress, ErrorModule::OS,
24 ErrorSummary::InvalidState, ErrorLevel::Usage}; 24 ErrorSummary::InvalidState, ErrorLevel::Usage};
25 25
26enum class VMAType : u8 { 26enum class VMAType : u8 {
27 /// VMA represents an unmapped region of the address space. 27 /// VMA represents an unmapped region of the address space.
@@ -115,7 +115,8 @@ class VMManager final {
115 // TODO(yuriks): Make page tables switchable to support multiple VMManagers 115 // TODO(yuriks): Make page tables switchable to support multiple VMManagers
116public: 116public:
117 /** 117 /**
118 * The maximum amount of address space managed by the kernel. Addresses above this are never used. 118 * The maximum amount of address space managed by the kernel. Addresses above this are never
119 * used.
119 * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000. 120 * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000.
120 */ 121 */
121 static const u32 MAX_ADDRESS = 0x40000000; 122 static const u32 MAX_ADDRESS = 0x40000000;
@@ -151,7 +152,7 @@ public:
151 * @param state MemoryState tag to attach to the VMA. 152 * @param state MemoryState tag to attach to the VMA.
152 */ 153 */
153 ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block, 154 ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block,
154 size_t offset, u32 size, MemoryState state); 155 size_t offset, u32 size, MemoryState state);
155 156
156 /** 157 /**
157 * Maps an unmanaged host memory pointer at a given address. 158 * Maps an unmanaged host memory pointer at a given address.
@@ -172,7 +173,8 @@ public:
172 * @param state MemoryState tag to attach to the VMA. 173 * @param state MemoryState tag to attach to the VMA.
173 * @param mmio_handler The handler that will implement read and write for this MMIO region. 174 * @param mmio_handler The handler that will implement read and write for this MMIO region.
174 */ 175 */
175 ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler); 176 ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state,
177 Memory::MMIORegionPointer mmio_handler);
176 178
177 /// Unmaps a range of addresses, splitting VMAs as necessary. 179 /// Unmaps a range of addresses, splitting VMAs as necessary.
178 ResultCode UnmapRange(VAddr target, u32 size); 180 ResultCode UnmapRange(VAddr target, u32 size);
@@ -228,5 +230,4 @@ private:
228 /// Updates the pages corresponding to this VMA so they match the VMA's attributes. 230 /// Updates the pages corresponding to this VMA so they match the VMA's attributes.
229 void UpdatePageTableForVMA(const VirtualMemoryArea& vma); 231 void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
230}; 232};
231
232} 233}
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 268a8dad2..6e3dd9cd2 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -26,7 +26,8 @@ enum class ErrorDescription : u32 {
26 FS_InvalidOpenFlags = 230, 26 FS_InvalidOpenFlags = 230,
27 FS_NotAFile = 250, 27 FS_NotAFile = 250,
28 FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive 28 FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive
29 OutofRangeOrMisalignedAddress = 513, // TODO(purpasmart): Check if this name fits its actual usage 29 OutofRangeOrMisalignedAddress =
30 513, // TODO(purpasmart): Check if this name fits its actual usage
30 GPU_FirstInitialization = 519, 31 GPU_FirstInitialization = 519,
31 FS_InvalidPath = 702, 32 FS_InvalidPath = 702,
32 InvalidSection = 1000, 33 InvalidSection = 1000,
@@ -168,15 +169,15 @@ enum class ErrorSummary : u32 {
168 Success = 0, 169 Success = 0,
169 NothingHappened = 1, 170 NothingHappened = 1,
170 WouldBlock = 2, 171 WouldBlock = 2,
171 OutOfResource = 3, ///< There are no more kernel resources (memory, table slots) to 172 OutOfResource = 3, ///< There are no more kernel resources (memory, table slots) to
172 ///< execute the operation. 173 ///< execute the operation.
173 NotFound = 4, ///< A file or resource was not found. 174 NotFound = 4, ///< A file or resource was not found.
174 InvalidState = 5, 175 InvalidState = 5,
175 NotSupported = 6, ///< The operation is not supported or not implemented. 176 NotSupported = 6, ///< The operation is not supported or not implemented.
176 InvalidArgument = 7, ///< Returned when a passed argument is invalid in the current runtime 177 InvalidArgument = 7, ///< Returned when a passed argument is invalid in the current runtime
177 ///< context. (Invalid handle, out-of-bounds pointer or size, etc.) 178 ///< context. (Invalid handle, out-of-bounds pointer or size, etc.)
178 WrongArgument = 8, ///< Returned when a passed argument is in an incorrect format for use 179 WrongArgument = 8, ///< Returned when a passed argument is in an incorrect format for use
179 ///< with the function. (E.g. Invalid enum value) 180 ///< with the function. (E.g. Invalid enum value)
180 Canceled = 9, 181 Canceled = 9,
181 StatusChanged = 10, 182 StatusChanged = 10,
182 Internal = 11, 183 Internal = 11,
@@ -208,19 +209,25 @@ union ResultCode {
208 BitField<21, 6, ErrorSummary> summary; 209 BitField<21, 6, ErrorSummary> summary;
209 BitField<27, 5, ErrorLevel> level; 210 BitField<27, 5, ErrorLevel> level;
210 211
211 // The last bit of `level` is checked by apps and the kernel to determine if a result code is an error 212 // The last bit of `level` is checked by apps and the kernel to determine if a result code is an
213 // error
212 BitField<31, 1, u32> is_error; 214 BitField<31, 1, u32> is_error;
213 215
214 explicit ResultCode(u32 raw) : raw(raw) {} 216 explicit ResultCode(u32 raw) : raw(raw) {
215 ResultCode(ErrorDescription description_, ErrorModule module_, 217 }
216 ErrorSummary summary_, ErrorLevel level_) : raw(0) { 218 ResultCode(ErrorDescription description_, ErrorModule module_, ErrorSummary summary_,
219 ErrorLevel level_)
220 : raw(0) {
217 description.Assign(description_); 221 description.Assign(description_);
218 module.Assign(module_); 222 module.Assign(module_);
219 summary.Assign(summary_); 223 summary.Assign(summary_);
220 level.Assign(level_); 224 level.Assign(level_);
221 } 225 }
222 226
223 ResultCode& operator=(const ResultCode& o) { raw = o.raw; return *this; } 227 ResultCode& operator=(const ResultCode& o) {
228 raw = o.raw;
229 return *this;
230 }
224 231
225 bool IsSuccess() const { 232 bool IsSuccess() const {
226 return is_error == 0; 233 return is_error == 0;
@@ -246,8 +253,8 @@ const ResultCode RESULT_SUCCESS(0);
246 253
247/// Might be returned instead of a dummy success for unimplemented APIs. 254/// Might be returned instead of a dummy success for unimplemented APIs.
248inline ResultCode UnimplementedFunction(ErrorModule module) { 255inline ResultCode UnimplementedFunction(ErrorModule module) {
249 return ResultCode(ErrorDescription::NotImplemented, module, 256 return ResultCode(ErrorDescription::NotImplemented, module, ErrorSummary::NotSupported,
250 ErrorSummary::NotSupported, ErrorLevel::Permanent); 257 ErrorLevel::Permanent);
251} 258}
252 259
253/** 260/**
@@ -285,10 +292,9 @@ inline ResultCode UnimplementedFunction(ErrorModule module) {
285template <typename T> 292template <typename T>
286class ResultVal { 293class ResultVal {
287public: 294public:
288 /// Constructs an empty `ResultVal` with the given error code. The code must not be a success code. 295 /// Constructs an empty `ResultVal` with the given error code. The code must not be a success
289 ResultVal(ResultCode error_code = ResultCode(-1)) 296 /// code.
290 : result_code(error_code) 297 ResultVal(ResultCode error_code = ResultCode(-1)) : result_code(error_code) {
291 {
292 ASSERT(error_code.IsError()); 298 ASSERT(error_code.IsError());
293 } 299 }
294 300
@@ -303,17 +309,13 @@ public:
303 return result; 309 return result;
304 } 310 }
305 311
306 ResultVal(const ResultVal& o) 312 ResultVal(const ResultVal& o) : result_code(o.result_code) {
307 : result_code(o.result_code)
308 {
309 if (!o.empty()) { 313 if (!o.empty()) {
310 new (&object) T(o.object); 314 new (&object) T(o.object);
311 } 315 }
312 } 316 }
313 317
314 ResultVal(ResultVal&& o) 318 ResultVal(ResultVal&& o) : result_code(o.result_code) {
315 : result_code(o.result_code)
316 {
317 if (!o.empty()) { 319 if (!o.empty()) {
318 new (&object) T(std::move(o.object)); 320 new (&object) T(std::move(o.object));
319 } 321 }
@@ -357,19 +359,35 @@ public:
357 } 359 }
358 360
359 /// Returns true if the `ResultVal` contains an error code and no value. 361 /// Returns true if the `ResultVal` contains an error code and no value.
360 bool empty() const { return result_code.IsError(); } 362 bool empty() const {
363 return result_code.IsError();
364 }
361 365
362 /// Returns true if the `ResultVal` contains a return value. 366 /// Returns true if the `ResultVal` contains a return value.
363 bool Succeeded() const { return result_code.IsSuccess(); } 367 bool Succeeded() const {
368 return result_code.IsSuccess();
369 }
364 /// Returns true if the `ResultVal` contains an error code and no value. 370 /// Returns true if the `ResultVal` contains an error code and no value.
365 bool Failed() const { return empty(); } 371 bool Failed() const {
372 return empty();
373 }
366 374
367 ResultCode Code() const { return result_code; } 375 ResultCode Code() const {
376 return result_code;
377 }
368 378
369 const T& operator* () const { return object; } 379 const T& operator*() const {
370 T& operator* () { return object; } 380 return object;
371 const T* operator->() const { return &object; } 381 }
372 T* operator->() { return &object; } 382 T& operator*() {
383 return object;
384 }
385 const T* operator->() const {
386 return &object;
387 }
388 T* operator->() {
389 return &object;
390 }
373 391
374 /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing. 392 /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
375 template <typename U> 393 template <typename U>
@@ -390,7 +408,9 @@ public:
390private: 408private:
391 // A union is used to allocate the storage for the value, while allowing us to construct and 409 // A union is used to allocate the storage for the value, while allowing us to construct and
392 // destruct it at will. 410 // destruct it at will.
393 union { T object; }; 411 union {
412 T object;
413 };
394 ResultCode result_code; 414 ResultCode result_code;
395}; 415};
396 416
@@ -409,8 +429,8 @@ ResultVal<T> MakeResult(Args&&... args) {
409 * variable declaration. If it fails the return code is returned from the current function. Thus it 429 * variable declaration. If it fails the return code is returned from the current function. Thus it
410 * can be used to cascade errors out, achieving something akin to exception handling. 430 * can be used to cascade errors out, achieving something akin to exception handling.
411 */ 431 */
412#define CASCADE_RESULT(target, source) \ 432#define CASCADE_RESULT(target, source) \
413 auto CONCAT2(check_result_L, __LINE__) = source; \ 433 auto CONCAT2(check_result_L, __LINE__) = source; \
414 if (CONCAT2(check_result_L, __LINE__).Failed()) \ 434 if (CONCAT2(check_result_L, __LINE__).Failed()) \
415 return CONCAT2(check_result_L, __LINE__).Code(); \ 435 return CONCAT2(check_result_L, __LINE__).Code(); \
416 target = std::move(*CONCAT2(check_result_L, __LINE__)) 436 target = std::move(*CONCAT2(check_result_L, __LINE__))
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index 5241dd3e7..887b57529 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -47,7 +47,7 @@ static void GetWifiStatus(Service::Interface* self) {
47 // it returns a valid result without implementing full functionality. 47 // it returns a valid result without implementing full functionality.
48 48
49 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 49 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
50 cmd_buff[2] = 0; // Connection type set to none 50 cmd_buff[2] = 0; // Connection type set to none
51 51
52 LOG_WARNING(Service_AC, "(STUBBED) called"); 52 LOG_WARNING(Service_AC, "(STUBBED) called");
53} 53}
@@ -62,29 +62,29 @@ static void IsConnected(Service::Interface* self) {
62 u32* cmd_buff = Kernel::GetCommandBuffer(); 62 u32* cmd_buff = Kernel::GetCommandBuffer();
63 63
64 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 64 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
65 cmd_buff[2] = false; // Not connected to ac:u service 65 cmd_buff[2] = false; // Not connected to ac:u service
66 66
67 LOG_WARNING(Service_AC, "(STUBBED) called"); 67 LOG_WARNING(Service_AC, "(STUBBED) called");
68} 68}
69 69
70const Interface::FunctionInfo FunctionTable[] = { 70const Interface::FunctionInfo FunctionTable[] = {
71 {0x00010000, nullptr, "CreateDefaultConfig"}, 71 {0x00010000, nullptr, "CreateDefaultConfig"},
72 {0x00040006, nullptr, "ConnectAsync"}, 72 {0x00040006, nullptr, "ConnectAsync"},
73 {0x00050002, nullptr, "GetConnectResult"}, 73 {0x00050002, nullptr, "GetConnectResult"},
74 {0x00080004, CloseAsync, "CloseAsync"}, 74 {0x00080004, CloseAsync, "CloseAsync"},
75 {0x00090002, nullptr, "GetCloseResult"}, 75 {0x00090002, nullptr, "GetCloseResult"},
76 {0x000A0000, nullptr, "GetLastErrorCode"}, 76 {0x000A0000, nullptr, "GetLastErrorCode"},
77 {0x000D0000, GetWifiStatus, "GetWifiStatus"}, 77 {0x000D0000, GetWifiStatus, "GetWifiStatus"},
78 {0x000E0042, nullptr, "GetCurrentAPInfo"}, 78 {0x000E0042, nullptr, "GetCurrentAPInfo"},
79 {0x00100042, nullptr, "GetCurrentNZoneInfo"}, 79 {0x00100042, nullptr, "GetCurrentNZoneInfo"},
80 {0x00110042, nullptr, "GetNZoneApNumService"}, 80 {0x00110042, nullptr, "GetNZoneApNumService"},
81 {0x00240042, nullptr, "AddDenyApType"}, 81 {0x00240042, nullptr, "AddDenyApType"},
82 {0x00270002, nullptr, "GetInfraPriority"}, 82 {0x00270002, nullptr, "GetInfraPriority"},
83 {0x002D0082, nullptr, "SetRequestEulaVersion"}, 83 {0x002D0082, nullptr, "SetRequestEulaVersion"},
84 {0x00300004, nullptr, "RegisterDisconnectEvent"}, 84 {0x00300004, nullptr, "RegisterDisconnectEvent"},
85 {0x003C0042, nullptr, "GetAPSSIDList"}, 85 {0x003C0042, nullptr, "GetAPSSIDList"},
86 {0x003E0042, IsConnected, "IsConnected"}, 86 {0x003E0042, IsConnected, "IsConnected"},
87 {0x00400042, nullptr, "SetClientVersion"}, 87 {0x00400042, nullptr, "SetClientVersion"},
88}; 88};
89 89
90//////////////////////////////////////////////////////////////////////////////////////////////////// 90////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 3f71e7f2b..b653523a4 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -6,19 +6,19 @@
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8 8
9#include "core/hle/service/service.h"
10#include "core/hle/service/am/am.h" 9#include "core/hle/service/am/am.h"
11#include "core/hle/service/am/am_app.h" 10#include "core/hle/service/am/am_app.h"
12#include "core/hle/service/am/am_net.h" 11#include "core/hle/service/am/am_net.h"
13#include "core/hle/service/am/am_sys.h" 12#include "core/hle/service/am/am_sys.h"
14#include "core/hle/service/am/am_u.h" 13#include "core/hle/service/am/am_u.h"
14#include "core/hle/service/service.h"
15 15
16namespace Service { 16namespace Service {
17namespace AM { 17namespace AM {
18 18
19static std::array<u32, 3> am_content_count = { 0, 0, 0 }; 19static std::array<u32, 3> am_content_count = {0, 0, 0};
20static std::array<u32, 3> am_titles_count = { 0, 0, 0 }; 20static std::array<u32, 3> am_titles_count = {0, 0, 0};
21static std::array<u32, 3> am_titles_list_count = { 0, 0, 0 }; 21static std::array<u32, 3> am_titles_list_count = {0, 0, 0};
22static u32 am_ticket_count = 0; 22static u32 am_ticket_count = 0;
23static u32 am_ticket_list_count = 0; 23static u32 am_ticket_list_count = 0;
24 24
@@ -29,7 +29,8 @@ void GetTitleCount(Service::Interface* self) {
29 29
30 cmd_buff[1] = RESULT_SUCCESS.raw; 30 cmd_buff[1] = RESULT_SUCCESS.raw;
31 cmd_buff[2] = am_titles_count[media_type]; 31 cmd_buff[2] = am_titles_count[media_type];
32 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_count=0x%08x", media_type, am_titles_count[media_type]); 32 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_count=0x%08x", media_type,
33 am_titles_count[media_type]);
33} 34}
34 35
35void FindContentInfos(Service::Interface* self) { 36void FindContentInfos(Service::Interface* self) {
@@ -43,8 +44,10 @@ void FindContentInfos(Service::Interface* self) {
43 am_content_count[media_type] = cmd_buff[4]; 44 am_content_count[media_type] = cmd_buff[4];
44 45
45 cmd_buff[1] = RESULT_SUCCESS.raw; 46 cmd_buff[1] = RESULT_SUCCESS.raw;
46 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016llx, content_cound=%u, content_ids_pointer=0x%08x, content_info_pointer=0x%08x", 47 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016llx, content_cound=%u, "
47 media_type, title_id, am_content_count[media_type], content_ids_pointer, content_info_pointer); 48 "content_ids_pointer=0x%08x, content_info_pointer=0x%08x",
49 media_type, title_id, am_content_count[media_type], content_ids_pointer,
50 content_info_pointer);
48} 51}
49 52
50void ListContentInfos(Service::Interface* self) { 53void ListContentInfos(Service::Interface* self) {
@@ -59,8 +62,10 @@ void ListContentInfos(Service::Interface* self) {
59 62
60 cmd_buff[1] = RESULT_SUCCESS.raw; 63 cmd_buff[1] = RESULT_SUCCESS.raw;
61 cmd_buff[2] = am_content_count[media_type]; 64 cmd_buff[2] = am_content_count[media_type];
62 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, content_count=%u, title_id=0x%016" PRIx64 ", start_index=0x%08x, content_info_pointer=0x%08X", 65 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, content_count=%u, title_id=0x%016" PRIx64
63 media_type, am_content_count[media_type], title_id, start_index, content_info_pointer); 66 ", start_index=0x%08x, content_info_pointer=0x%08X",
67 media_type, am_content_count[media_type], title_id, start_index,
68 content_info_pointer);
64} 69}
65 70
66void DeleteContents(Service::Interface* self) { 71void DeleteContents(Service::Interface* self) {
@@ -73,8 +78,9 @@ void DeleteContents(Service::Interface* self) {
73 am_content_count[media_type] = cmd_buff[4]; 78 am_content_count[media_type] = cmd_buff[4];
74 79
75 cmd_buff[1] = RESULT_SUCCESS.raw; 80 cmd_buff[1] = RESULT_SUCCESS.raw;
76 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016" PRIx64 ", content_count=%u, content_ids_pointer=0x%08x", 81 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016" PRIx64
77 media_type, title_id, am_content_count[media_type], content_ids_pointer); 82 ", content_count=%u, content_ids_pointer=0x%08x",
83 media_type, title_id, am_content_count[media_type], content_ids_pointer);
78} 84}
79 85
80void GetTitleList(Service::Interface* self) { 86void GetTitleList(Service::Interface* self) {
@@ -87,8 +93,10 @@ void GetTitleList(Service::Interface* self) {
87 93
88 cmd_buff[1] = RESULT_SUCCESS.raw; 94 cmd_buff[1] = RESULT_SUCCESS.raw;
89 cmd_buff[2] = am_titles_list_count[media_type]; 95 cmd_buff[2] = am_titles_list_count[media_type];
90 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, titles_list_count=0x%08X, title_ids_output_pointer=0x%08X", 96 LOG_WARNING(
91 media_type, am_titles_list_count[media_type], title_ids_output_pointer); 97 Service_AM,
98 "(STUBBED) media_type=%u, titles_list_count=0x%08X, title_ids_output_pointer=0x%08X",
99 media_type, am_titles_list_count[media_type], title_ids_output_pointer);
92} 100}
93 101
94void GetTitleInfo(Service::Interface* self) { 102void GetTitleInfo(Service::Interface* self) {
@@ -101,7 +109,8 @@ void GetTitleInfo(Service::Interface* self) {
101 am_titles_count[media_type] = cmd_buff[2]; 109 am_titles_count[media_type] = cmd_buff[2];
102 110
103 cmd_buff[1] = RESULT_SUCCESS.raw; 111 cmd_buff[1] = RESULT_SUCCESS.raw;
104 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, total_titles=0x%08X, title_id_list_pointer=0x%08X, title_list_pointer=0x%08X", 112 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, total_titles=0x%08X, "
113 "title_id_list_pointer=0x%08X, title_list_pointer=0x%08X",
105 media_type, am_titles_count[media_type], title_id_list_pointer, title_list_pointer); 114 media_type, am_titles_count[media_type], title_id_list_pointer, title_list_pointer);
106} 115}
107 116
@@ -122,8 +131,9 @@ void ListDataTitleTicketInfos(Service::Interface* self) {
122 131
123 cmd_buff[1] = RESULT_SUCCESS.raw; 132 cmd_buff[1] = RESULT_SUCCESS.raw;
124 cmd_buff[2] = am_ticket_count; 133 cmd_buff[2] = am_ticket_count;
125 LOG_WARNING(Service_AM, "(STUBBED) ticket_count=0x%08X, title_id=0x%016" PRIx64 ", start_index=0x%08X, ticket_info_pointer=0x%08X", 134 LOG_WARNING(Service_AM, "(STUBBED) ticket_count=0x%08X, title_id=0x%016" PRIx64
126 am_ticket_count, title_id, start_index, ticket_info_pointer); 135 ", start_index=0x%08X, ticket_info_pointer=0x%08X",
136 am_ticket_count, title_id, start_index, ticket_info_pointer);
127} 137}
128 138
129void GetNumContentInfos(Service::Interface* self) { 139void GetNumContentInfos(Service::Interface* self) {
@@ -140,7 +150,7 @@ void DeleteTicket(Service::Interface* self) {
140 u64 title_id = (static_cast<u64>(cmd_buff[2]) << 32) | cmd_buff[1]; 150 u64 title_id = (static_cast<u64>(cmd_buff[2]) << 32) | cmd_buff[1];
141 151
142 cmd_buff[1] = RESULT_SUCCESS.raw; 152 cmd_buff[1] = RESULT_SUCCESS.raw;
143 LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "",title_id); 153 LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "", title_id);
144} 154}
145 155
146void GetTicketCount(Service::Interface* self) { 156void GetTicketCount(Service::Interface* self) {
@@ -148,7 +158,7 @@ void GetTicketCount(Service::Interface* self) {
148 158
149 cmd_buff[1] = RESULT_SUCCESS.raw; 159 cmd_buff[1] = RESULT_SUCCESS.raw;
150 cmd_buff[2] = am_ticket_count; 160 cmd_buff[2] = am_ticket_count;
151 LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x",am_ticket_count); 161 LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x", am_ticket_count);
152} 162}
153 163
154void GetTicketList(Service::Interface* self) { 164void GetTicketList(Service::Interface* self) {
@@ -161,8 +171,10 @@ void GetTicketList(Service::Interface* self) {
161 171
162 cmd_buff[1] = RESULT_SUCCESS.raw; 172 cmd_buff[1] = RESULT_SUCCESS.raw;
163 cmd_buff[2] = am_ticket_list_count; 173 cmd_buff[2] = am_ticket_list_count;
164 LOG_WARNING(Service_AM, "(STUBBED) ticket_list_count=0x%08x, num_of_skip=0x%08x, ticket_list_pointer=0x%08x", 174 LOG_WARNING(
165 am_ticket_list_count, num_of_skip, ticket_list_pointer); 175 Service_AM,
176 "(STUBBED) ticket_list_count=0x%08x, num_of_skip=0x%08x, ticket_list_pointer=0x%08x",
177 am_ticket_list_count, num_of_skip, ticket_list_pointer);
166} 178}
167 179
168void Init() { 180void Init() {
@@ -175,7 +187,6 @@ void Init() {
175} 187}
176 188
177void Shutdown() { 189void Shutdown() {
178
179} 190}
180 191
181} // namespace AM 192} // namespace AM
diff --git a/src/core/hle/service/am/am_app.cpp b/src/core/hle/service/am/am_app.cpp
index d27b3defd..bfc1ca6bd 100644
--- a/src/core/hle/service/am/am_app.cpp
+++ b/src/core/hle/service/am/am_app.cpp
@@ -9,14 +9,14 @@ namespace Service {
9namespace AM { 9namespace AM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x100100C0, GetNumContentInfos, "GetNumContentInfos"}, 12 {0x100100C0, GetNumContentInfos, "GetNumContentInfos"},
13 {0x10020104, FindContentInfos, "FindContentInfos"}, 13 {0x10020104, FindContentInfos, "FindContentInfos"},
14 {0x10030142, ListContentInfos, "ListContentInfos"}, 14 {0x10030142, ListContentInfos, "ListContentInfos"},
15 {0x10040102, DeleteContents, "DeleteContents"}, 15 {0x10040102, DeleteContents, "DeleteContents"},
16 {0x10050084, GetDataTitleInfos, "GetDataTitleInfos"}, 16 {0x10050084, GetDataTitleInfos, "GetDataTitleInfos"},
17 {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, 17 {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"},
18 {0x100900C0, nullptr, "IsDataTitleInUse"}, 18 {0x100900C0, nullptr, "IsDataTitleInUse"},
19 {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, 19 {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"},
20}; 20};
21 21
22AM_APP_Interface::AM_APP_Interface() { 22AM_APP_Interface::AM_APP_Interface() {
diff --git a/src/core/hle/service/am/am_net.cpp b/src/core/hle/service/am/am_net.cpp
index e75755245..3a597a34c 100644
--- a/src/core/hle/service/am/am_net.cpp
+++ b/src/core/hle/service/am/am_net.cpp
@@ -9,61 +9,61 @@ namespace Service {
9namespace AM { 9namespace AM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010040, GetTitleCount, "GetTitleCount"}, 12 {0x00010040, GetTitleCount, "GetTitleCount"},
13 {0x00020082, GetTitleList, "GetTitleList"}, 13 {0x00020082, GetTitleList, "GetTitleList"},
14 {0x00030084, GetTitleInfo, "GetTitleInfo"}, 14 {0x00030084, GetTitleInfo, "GetTitleInfo"},
15 {0x000400C0, nullptr, "DeleteApplicationTitle"}, 15 {0x000400C0, nullptr, "DeleteApplicationTitle"},
16 {0x000500C0, nullptr, "GetTitleProductCode"}, 16 {0x000500C0, nullptr, "GetTitleProductCode"},
17 {0x000600C0, nullptr, "GetTitleExtDataId"}, 17 {0x000600C0, nullptr, "GetTitleExtDataId"},
18 {0x00070080, DeleteTicket, "DeleteTicket"}, 18 {0x00070080, DeleteTicket, "DeleteTicket"},
19 {0x00080000, GetTicketCount, "GetTicketCount"}, 19 {0x00080000, GetTicketCount, "GetTicketCount"},
20 {0x00090082, GetTicketList, "GetTicketList"}, 20 {0x00090082, GetTicketList, "GetTicketList"},
21 {0x000A0000, nullptr, "GetDeviceID"}, 21 {0x000A0000, nullptr, "GetDeviceID"},
22 {0x000D0084, nullptr, "GetPendingTitleInfo"}, 22 {0x000D0084, nullptr, "GetPendingTitleInfo"},
23 {0x000E00C0, nullptr, "DeletePendingTitle"}, 23 {0x000E00C0, nullptr, "DeletePendingTitle"},
24 {0x00140040, nullptr, "FinalizePendingTitles"}, 24 {0x00140040, nullptr, "FinalizePendingTitles"},
25 {0x00150040, nullptr, "DeleteAllPendingTitles"}, 25 {0x00150040, nullptr, "DeleteAllPendingTitles"},
26 {0x00180080, nullptr, "InitializeTitleDatabase"}, 26 {0x00180080, nullptr, "InitializeTitleDatabase"},
27 {0x00190040, nullptr, "ReloadDBS"}, 27 {0x00190040, nullptr, "ReloadDBS"},
28 {0x001A00C0, nullptr, "GetDSiWareExportSize"}, 28 {0x001A00C0, nullptr, "GetDSiWareExportSize"},
29 {0x001B0144, nullptr, "ExportDSiWare"}, 29 {0x001B0144, nullptr, "ExportDSiWare"},
30 {0x001C0084, nullptr, "ImportDSiWare"}, 30 {0x001C0084, nullptr, "ImportDSiWare"},
31 {0x00230080, nullptr, "TitleIDListGetTotal2"}, 31 {0x00230080, nullptr, "TitleIDListGetTotal2"},
32 {0x002400C2, nullptr, "GetTitleIDList2"}, 32 {0x002400C2, nullptr, "GetTitleIDList2"},
33 {0x04010080, nullptr, "InstallFIRM"}, 33 {0x04010080, nullptr, "InstallFIRM"},
34 {0x04020040, nullptr, "StartInstallCIADB0"}, 34 {0x04020040, nullptr, "StartInstallCIADB0"},
35 {0x04030000, nullptr, "StartInstallCIADB1"}, 35 {0x04030000, nullptr, "StartInstallCIADB1"},
36 {0x04040002, nullptr, "AbortCIAInstall"}, 36 {0x04040002, nullptr, "AbortCIAInstall"},
37 {0x04050002, nullptr, "CloseCIAFinalizeInstall"}, 37 {0x04050002, nullptr, "CloseCIAFinalizeInstall"},
38 {0x04060002, nullptr, "CloseCIA"}, 38 {0x04060002, nullptr, "CloseCIA"},
39 {0x040700C2, nullptr, "FinalizeTitlesInstall"}, 39 {0x040700C2, nullptr, "FinalizeTitlesInstall"},
40 {0x04080042, nullptr, "GetCiaFileInfo"}, 40 {0x04080042, nullptr, "GetCiaFileInfo"},
41 {0x040E00C2, nullptr, "InstallTitlesFinish"}, 41 {0x040E00C2, nullptr, "InstallTitlesFinish"},
42 {0x040F0000, nullptr, "InstallNATIVEFIRM"}, 42 {0x040F0000, nullptr, "InstallNATIVEFIRM"},
43 {0x041000C0, nullptr, "DeleteTitle"}, 43 {0x041000C0, nullptr, "DeleteTitle"},
44 {0x04120000, nullptr, "Initialize"}, 44 {0x04120000, nullptr, "Initialize"},
45 {0x041700C0, nullptr, "MigrateAGBtoSAV"}, 45 {0x041700C0, nullptr, "MigrateAGBtoSAV"},
46 {0x08010000, nullptr, "OpenTicket"}, 46 {0x08010000, nullptr, "OpenTicket"},
47 {0x08020002, nullptr, "TicketAbortInstall"}, 47 {0x08020002, nullptr, "TicketAbortInstall"},
48 {0x08030002, nullptr, "TicketFinalizeInstall"}, 48 {0x08030002, nullptr, "TicketFinalizeInstall"},
49 {0x08040100, nullptr, "InstallTitleBegin"}, 49 {0x08040100, nullptr, "InstallTitleBegin"},
50 {0x08050000, nullptr, "InstallTitleAbort"}, 50 {0x08050000, nullptr, "InstallTitleAbort"},
51 {0x080600C0, nullptr, "InstallTitleResume"}, 51 {0x080600C0, nullptr, "InstallTitleResume"},
52 {0x08070000, nullptr, "InstallTitleAbortTMD"}, 52 {0x08070000, nullptr, "InstallTitleAbortTMD"},
53 {0x08080000, nullptr, "InstallTitleFinish"}, 53 {0x08080000, nullptr, "InstallTitleFinish"},
54 {0x080A0000, nullptr, "OpenTMD"}, 54 {0x080A0000, nullptr, "OpenTMD"},
55 {0x080B0002, nullptr, "TMDAbortInstall"}, 55 {0x080B0002, nullptr, "TMDAbortInstall"},
56 {0x080C0042, nullptr, "TMDFinalizeInstall"}, 56 {0x080C0042, nullptr, "TMDFinalizeInstall"},
57 {0x080E0040, nullptr, "OpenContentCreate"}, 57 {0x080E0040, nullptr, "OpenContentCreate"},
58 {0x080F0002, nullptr, "ContentAbortInstall"}, 58 {0x080F0002, nullptr, "ContentAbortInstall"},
59 {0x08100040, nullptr, "OpenContentResume"}, 59 {0x08100040, nullptr, "OpenContentResume"},
60 {0x08120002, nullptr, "ContentFinalizeInstall"}, 60 {0x08120002, nullptr, "ContentFinalizeInstall"},
61 {0x08130000, nullptr, "GetTotalContents"}, 61 {0x08130000, nullptr, "GetTotalContents"},
62 {0x08140042, nullptr, "GetContentIndexes"}, 62 {0x08140042, nullptr, "GetContentIndexes"},
63 {0x08150044, nullptr, "GetContentsInfo"}, 63 {0x08150044, nullptr, "GetContentsInfo"},
64 {0x08180042, nullptr, "GetCTCert"}, 64 {0x08180042, nullptr, "GetCTCert"},
65 {0x08190108, nullptr, "SetCertificates"}, 65 {0x08190108, nullptr, "SetCertificates"},
66 {0x081B00C2, nullptr, "InstallTitlesFinish"}, 66 {0x081B00C2, nullptr, "InstallTitlesFinish"},
67}; 67};
68 68
69AM_NET_Interface::AM_NET_Interface() { 69AM_NET_Interface::AM_NET_Interface() {
diff --git a/src/core/hle/service/am/am_sys.cpp b/src/core/hle/service/am/am_sys.cpp
index 8bad5e1c9..8bb58cab7 100644
--- a/src/core/hle/service/am/am_sys.cpp
+++ b/src/core/hle/service/am/am_sys.cpp
@@ -8,29 +8,27 @@
8namespace Service { 8namespace Service {
9namespace AM { 9namespace AM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {{0x00010040, GetTitleCount, "GetTitleCount"},
12 {0x00010040, GetTitleCount, "GetTitleCount"}, 12 {0x00020082, GetTitleList, "GetTitleList"},
13 {0x00020082, GetTitleList, "GetTitleList"}, 13 {0x00030084, GetTitleInfo, "GetTitleInfo"},
14 {0x00030084, GetTitleInfo, "GetTitleInfo"}, 14 {0x000400C0, nullptr, "DeleteApplicationTitle"},
15 {0x000400C0, nullptr, "DeleteApplicationTitle"}, 15 {0x000500C0, nullptr, "GetTitleProductCode"},
16 {0x000500C0, nullptr, "GetTitleProductCode"}, 16 {0x000600C0, nullptr, "GetTitleExtDataId"},
17 {0x000600C0, nullptr, "GetTitleExtDataId"}, 17 {0x00070080, DeleteTicket, "DeleteTicket"},
18 {0x00070080, DeleteTicket, "DeleteTicket"}, 18 {0x00080000, GetTicketCount, "GetTicketCount"},
19 {0x00080000, GetTicketCount, "GetTicketCount"}, 19 {0x00090082, GetTicketList, "GetTicketList"},
20 {0x00090082, GetTicketList, "GetTicketList"}, 20 {0x000A0000, nullptr, "GetDeviceID"},
21 {0x000A0000, nullptr, "GetDeviceID"}, 21 {0x000D0084, nullptr, "GetPendingTitleInfo"},
22 {0x000D0084, nullptr, "GetPendingTitleInfo"}, 22 {0x000E00C0, nullptr, "DeletePendingTitle"},
23 {0x000E00C0, nullptr, "DeletePendingTitle"}, 23 {0x00140040, nullptr, "FinalizePendingTitles"},
24 {0x00140040, nullptr, "FinalizePendingTitles"}, 24 {0x00150040, nullptr, "DeleteAllPendingTitles"},
25 {0x00150040, nullptr, "DeleteAllPendingTitles"}, 25 {0x00180080, nullptr, "InitializeTitleDatabase"},
26 {0x00180080, nullptr, "InitializeTitleDatabase"}, 26 {0x00190040, nullptr, "ReloadDBS"},
27 {0x00190040, nullptr, "ReloadDBS"}, 27 {0x001A00C0, nullptr, "GetDSiWareExportSize"},
28 {0x001A00C0, nullptr, "GetDSiWareExportSize"}, 28 {0x001B0144, nullptr, "ExportDSiWare"},
29 {0x001B0144, nullptr, "ExportDSiWare"}, 29 {0x001C0084, nullptr, "ImportDSiWare"},
30 {0x001C0084, nullptr, "ImportDSiWare"}, 30 {0x00230080, nullptr, "GetPendingTitleCount"},
31 {0x00230080, nullptr, "GetPendingTitleCount"}, 31 {0x002400C2, nullptr, "GetPendingTitleList"}};
32 {0x002400C2, nullptr, "GetPendingTitleList"}
33};
34 32
35AM_SYS_Interface::AM_SYS_Interface() { 33AM_SYS_Interface::AM_SYS_Interface() {
36 Register(FunctionTable); 34 Register(FunctionTable);
diff --git a/src/core/hle/service/am/am_u.cpp b/src/core/hle/service/am/am_u.cpp
index d583dd9e6..32d47741f 100644
--- a/src/core/hle/service/am/am_u.cpp
+++ b/src/core/hle/service/am/am_u.cpp
@@ -8,42 +8,40 @@
8namespace Service { 8namespace Service {
9namespace AM { 9namespace AM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {{0x00010040, GetTitleCount, "GetTitleCount"},
12 {0x00010040, GetTitleCount, "GetTitleCount"}, 12 {0x00020082, GetTitleList, "GetTitleList"},
13 {0x00020082, GetTitleList, "GetTitleList"}, 13 {0x00030084, GetTitleInfo, "GetTitleInfo"},
14 {0x00030084, GetTitleInfo, "GetTitleInfo"}, 14 {0x000400C0, nullptr, "DeleteApplicationTitle"},
15 {0x000400C0, nullptr, "DeleteApplicationTitle"}, 15 {0x000500C0, nullptr, "GetTitleProductCode"},
16 {0x000500C0, nullptr, "GetTitleProductCode"}, 16 {0x000600C0, nullptr, "GetTitleExtDataId"},
17 {0x000600C0, nullptr, "GetTitleExtDataId"}, 17 {0x00070080, DeleteTicket, "DeleteTicket"},
18 {0x00070080, DeleteTicket, "DeleteTicket"}, 18 {0x00080000, GetTicketCount, "GetTicketCount"},
19 {0x00080000, GetTicketCount, "GetTicketCount"}, 19 {0x00090082, GetTicketList, "GetTicketList"},
20 {0x00090082, GetTicketList, "GetTicketList"}, 20 {0x000A0000, nullptr, "GetDeviceID"},
21 {0x000A0000, nullptr, "GetDeviceID"}, 21 {0x000D0084, nullptr, "GetPendingTitleInfo"},
22 {0x000D0084, nullptr, "GetPendingTitleInfo"}, 22 {0x000E00C0, nullptr, "DeletePendingTitle"},
23 {0x000E00C0, nullptr, "DeletePendingTitle"}, 23 {0x00140040, nullptr, "FinalizePendingTitles"},
24 {0x00140040, nullptr, "FinalizePendingTitles"}, 24 {0x00150040, nullptr, "DeleteAllPendingTitles"},
25 {0x00150040, nullptr, "DeleteAllPendingTitles"}, 25 {0x00180080, nullptr, "InitializeTitleDatabase"},
26 {0x00180080, nullptr, "InitializeTitleDatabase"}, 26 {0x00190040, nullptr, "ReloadDBS"},
27 {0x00190040, nullptr, "ReloadDBS"}, 27 {0x001A00C0, nullptr, "GetDSiWareExportSize"},
28 {0x001A00C0, nullptr, "GetDSiWareExportSize"}, 28 {0x001B0144, nullptr, "ExportDSiWare"},
29 {0x001B0144, nullptr, "ExportDSiWare"}, 29 {0x001C0084, nullptr, "ImportDSiWare"},
30 {0x001C0084, nullptr, "ImportDSiWare"}, 30 {0x00230080, nullptr, "TitleIDListGetTotal2"},
31 {0x00230080, nullptr, "TitleIDListGetTotal2"}, 31 {0x002400C2, nullptr, "GetTitleIDList2"},
32 {0x002400C2, nullptr, "GetTitleIDList2"}, 32 {0x04010080, nullptr, "InstallFIRM"},
33 {0x04010080, nullptr, "InstallFIRM"}, 33 {0x04020040, nullptr, "StartInstallCIADB0"},
34 {0x04020040, nullptr, "StartInstallCIADB0"}, 34 {0x04030000, nullptr, "StartInstallCIADB1"},
35 {0x04030000, nullptr, "StartInstallCIADB1"}, 35 {0x04040002, nullptr, "AbortCIAInstall"},
36 {0x04040002, nullptr, "AbortCIAInstall"}, 36 {0x04050002, nullptr, "CloseCIAFinalizeInstall"},
37 {0x04050002, nullptr, "CloseCIAFinalizeInstall"}, 37 {0x04060002, nullptr, "CloseCIA"},
38 {0x04060002, nullptr, "CloseCIA"}, 38 {0x040700C2, nullptr, "FinalizeTitlesInstall"},
39 {0x040700C2, nullptr, "FinalizeTitlesInstall"}, 39 {0x04080042, nullptr, "GetCiaFileInfo"},
40 {0x04080042, nullptr, "GetCiaFileInfo"}, 40 {0x040E00C2, nullptr, "InstallTitlesFinish"},
41 {0x040E00C2, nullptr, "InstallTitlesFinish"}, 41 {0x040F0000, nullptr, "InstallNATIVEFIRM"},
42 {0x040F0000, nullptr, "InstallNATIVEFIRM"}, 42 {0x041000C0, nullptr, "DeleteTitle"},
43 {0x041000C0, nullptr, "DeleteTitle"}, 43 {0x04120000, nullptr, "Initialize"},
44 {0x04120000, nullptr, "Initialize"}, 44 {0x041700C0, nullptr, "MigrateAGBtoSAV"}};
45 {0x041700C0, nullptr, "MigrateAGBtoSAV"}
46};
47 45
48AM_U_Interface::AM_U_Interface() { 46AM_U_Interface::AM_U_Interface() {
49 Register(FunctionTable); 47 Register(FunctionTable);
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 4d2956638..c798e8752 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -7,7 +7,6 @@
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8 8
9#include "core/hle/applets/applet.h" 9#include "core/hle/applets/applet.h"
10#include "core/hle/service/service.h"
11#include "core/hle/service/apt/apt.h" 10#include "core/hle/service/apt/apt.h"
12#include "core/hle/service/apt/apt_a.h" 11#include "core/hle/service/apt/apt_a.h"
13#include "core/hle/service/apt/apt_s.h" 12#include "core/hle/service/apt/apt_s.h"
@@ -15,6 +14,7 @@
15#include "core/hle/service/apt/bcfnt/bcfnt.h" 14#include "core/hle/service/apt/bcfnt/bcfnt.h"
16#include "core/hle/service/fs/archive.h" 15#include "core/hle/service/fs/archive.h"
17#include "core/hle/service/ptm/ptm.h" 16#include "core/hle/service/ptm/ptm.h"
17#include "core/hle/service/service.h"
18 18
19#include "core/hle/kernel/event.h" 19#include "core/hle/kernel/event.h"
20#include "core/hle/kernel/mutex.h" 20#include "core/hle/kernel/mutex.h"
@@ -30,7 +30,7 @@ static bool shared_font_relocated = false;
30 30
31static Kernel::SharedPtr<Kernel::Mutex> lock; 31static Kernel::SharedPtr<Kernel::Mutex> lock;
32static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event 32static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event
33static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event 33static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event
34 34
35static u32 cpu_percent; ///< CPU time available to the running application 35static u32 cpu_percent; ///< CPU time available to the running application
36 36
@@ -51,7 +51,7 @@ void SendParameter(const MessageParameter& parameter) {
51void Initialize(Service::Interface* self) { 51void Initialize(Service::Interface* self) {
52 u32* cmd_buff = Kernel::GetCommandBuffer(); 52 u32* cmd_buff = Kernel::GetCommandBuffer();
53 u32 app_id = cmd_buff[1]; 53 u32 app_id = cmd_buff[1];
54 u32 flags = cmd_buff[2]; 54 u32 flags = cmd_buff[2];
55 55
56 cmd_buff[2] = IPC::CopyHandleDesc(2); 56 cmd_buff[2] = IPC::CopyHandleDesc(2);
57 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); 57 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom();
@@ -75,20 +75,24 @@ void GetSharedFont(Service::Interface* self) {
75 if (!shared_font_mem) { 75 if (!shared_font_mem) {
76 LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds"); 76 LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds");
77 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); 77 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2);
78 cmd_buff[1] = -1; // TODO: Find the right error code 78 cmd_buff[1] = -1; // TODO: Find the right error code
79 return; 79 return;
80 } 80 }
81 81
82 // The shared font has to be relocated to the new address before being passed to the application. 82 // The shared font has to be relocated to the new address before being passed to the
83 VAddr target_address = Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address); 83 // application.
84 VAddr target_address =
85 Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address);
84 if (!shared_font_relocated) { 86 if (!shared_font_relocated) {
85 BCFNT::RelocateSharedFont(shared_font_mem, target_address); 87 BCFNT::RelocateSharedFont(shared_font_mem, target_address);
86 shared_font_relocated = true; 88 shared_font_relocated = true;
87 } 89 }
88 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); 90 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2);
89 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 91 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
90 // Since the SharedMemory interface doesn't provide the address at which the memory was allocated, 92 // Since the SharedMemory interface doesn't provide the address at which the memory was
91 // the real APT service calculates this address by scanning the entire address space (using svcQueryMemory) 93 // allocated,
94 // the real APT service calculates this address by scanning the entire address space (using
95 // svcQueryMemory)
92 // and searches for an allocation of the same size as the Shared Font. 96 // and searches for an allocation of the same size as the Shared Font.
93 cmd_buff[2] = target_address; 97 cmd_buff[2] = target_address;
94 cmd_buff[3] = IPC::CopyHandleDesc(); 98 cmd_buff[3] = IPC::CopyHandleDesc();
@@ -112,18 +116,19 @@ void GetLockHandle(Service::Interface* self) {
112 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 116 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
113 117
114 cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable. 118 cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable.
115 cmd_buff[3] = 0; // Least significant bit = power button state 119 cmd_buff[3] = 0; // Least significant bit = power button state
116 cmd_buff[4] = IPC::CopyHandleDesc(); 120 cmd_buff[4] = IPC::CopyHandleDesc();
117 cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom(); 121 cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom();
118 122
119 LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5], applet_attributes); 123 LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5],
124 applet_attributes);
120} 125}
121 126
122void Enable(Service::Interface* self) { 127void Enable(Service::Interface* self) {
123 u32* cmd_buff = Kernel::GetCommandBuffer(); 128 u32* cmd_buff = Kernel::GetCommandBuffer();
124 u32 attributes = cmd_buff[1]; 129 u32 attributes = cmd_buff[1];
125 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 130 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
126 parameter_event->Signal(); // Let the application know that it has been started 131 parameter_event->Signal(); // Let the application know that it has been started
127 LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes); 132 LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes);
128} 133}
129 134
@@ -133,7 +138,7 @@ void GetAppletManInfo(Service::Interface* self) {
133 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 138 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
134 cmd_buff[2] = 0; 139 cmd_buff[2] = 0;
135 cmd_buff[3] = 0; 140 cmd_buff[3] = 0;
136 cmd_buff[4] = static_cast<u32>(AppletId::HomeMenu); // Home menu AppID 141 cmd_buff[4] = static_cast<u32>(AppletId::HomeMenu); // Home menu AppID
137 cmd_buff[5] = static_cast<u32>(AppletId::Application); // TODO(purpasmart96): Do this correctly 142 cmd_buff[5] = static_cast<u32>(AppletId::Application); // TODO(purpasmart96): Do this correctly
138 143
139 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); 144 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk);
@@ -159,23 +164,24 @@ void IsRegistered(Service::Interface* self) {
159void InquireNotification(Service::Interface* self) { 164void InquireNotification(Service::Interface* self) {
160 u32* cmd_buff = Kernel::GetCommandBuffer(); 165 u32* cmd_buff = Kernel::GetCommandBuffer();
161 u32 app_id = cmd_buff[1]; 166 u32 app_id = cmd_buff[1];
162 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 167 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
163 cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type 168 cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type
164 LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); 169 LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id);
165} 170}
166 171
167void SendParameter(Service::Interface* self) { 172void SendParameter(Service::Interface* self) {
168 u32* cmd_buff = Kernel::GetCommandBuffer(); 173 u32* cmd_buff = Kernel::GetCommandBuffer();
169 u32 src_app_id = cmd_buff[1]; 174 u32 src_app_id = cmd_buff[1];
170 u32 dst_app_id = cmd_buff[2]; 175 u32 dst_app_id = cmd_buff[2];
171 u32 signal_type = cmd_buff[3]; 176 u32 signal_type = cmd_buff[3];
172 u32 buffer_size = cmd_buff[4]; 177 u32 buffer_size = cmd_buff[4];
173 u32 value = cmd_buff[5]; 178 u32 value = cmd_buff[5];
174 u32 handle = cmd_buff[6]; 179 u32 handle = cmd_buff[6];
175 u32 size = cmd_buff[7]; 180 u32 size = cmd_buff[7];
176 u32 buffer = cmd_buff[8]; 181 u32 buffer = cmd_buff[8];
177 182
178 std::shared_ptr<HLE::Applets::Applet> dest_applet = HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id)); 183 std::shared_ptr<HLE::Applets::Applet> dest_applet =
184 HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id));
179 185
180 if (dest_applet == nullptr) { 186 if (dest_applet == nullptr) {
181 LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id); 187 LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id);
@@ -193,9 +199,11 @@ void SendParameter(Service::Interface* self) {
193 199
194 cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; 200 cmd_buff[1] = dest_applet->ReceiveParameter(param).raw;
195 201
196 LOG_WARNING(Service_APT, "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," 202 LOG_WARNING(
197 "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X", 203 Service_APT,
198 src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, buffer); 204 "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X,"
205 "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X",
206 src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, buffer);
199} 207}
200 208
201void ReceiveParameter(Service::Interface* self) { 209void ReceiveParameter(Service::Interface* self) {
@@ -206,7 +214,7 @@ void ReceiveParameter(Service::Interface* self) {
206 214
207 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 215 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
208 cmd_buff[2] = next_parameter.sender_id; 216 cmd_buff[2] = next_parameter.sender_id;
209 cmd_buff[3] = next_parameter.signal; // Signal type 217 cmd_buff[3] = next_parameter.signal; // Signal type
210 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size 218 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size
211 cmd_buff[5] = 0x10; 219 cmd_buff[5] = 0x10;
212 cmd_buff[6] = 0; 220 cmd_buff[6] = 0;
@@ -228,7 +236,7 @@ void GlanceParameter(Service::Interface* self) {
228 236
229 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 237 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
230 cmd_buff[2] = next_parameter.sender_id; 238 cmd_buff[2] = next_parameter.sender_id;
231 cmd_buff[3] = next_parameter.signal; // Signal type 239 cmd_buff[3] = next_parameter.signal; // Signal type
232 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size 240 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size
233 cmd_buff[5] = 0x10; 241 cmd_buff[5] = 0x10;
234 cmd_buff[6] = 0; 242 cmd_buff[6] = 0;
@@ -237,32 +245,34 @@ void GlanceParameter(Service::Interface* self) {
237 cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; 245 cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2;
238 cmd_buff[8] = buffer; 246 cmd_buff[8] = buffer;
239 247
240 Memory::WriteBlock(buffer, next_parameter.buffer.data(), std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size())); 248 Memory::WriteBlock(buffer, next_parameter.buffer.data(),
249 std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size()));
241 250
242 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); 251 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size);
243} 252}
244 253
245void CancelParameter(Service::Interface* self) { 254void CancelParameter(Service::Interface* self) {
246 u32* cmd_buff = Kernel::GetCommandBuffer(); 255 u32* cmd_buff = Kernel::GetCommandBuffer();
247 u32 flag1 = cmd_buff[1]; 256 u32 flag1 = cmd_buff[1];
248 u32 unk = cmd_buff[2]; 257 u32 unk = cmd_buff[2];
249 u32 flag2 = cmd_buff[3]; 258 u32 flag2 = cmd_buff[3];
250 u32 app_id = cmd_buff[4]; 259 u32 app_id = cmd_buff[4];
251 260
252 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 261 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
253 cmd_buff[2] = 1; // Set to Success 262 cmd_buff[2] = 1; // Set to Success
254 263
255 LOG_WARNING(Service_APT, "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X", 264 LOG_WARNING(Service_APT,
256 flag1, unk, flag2, app_id); 265 "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X", flag1,
266 unk, flag2, app_id);
257} 267}
258 268
259void PrepareToStartApplication(Service::Interface* self) { 269void PrepareToStartApplication(Service::Interface* self) {
260 u32* cmd_buff = Kernel::GetCommandBuffer(); 270 u32* cmd_buff = Kernel::GetCommandBuffer();
261 u32 title_info1 = cmd_buff[1]; 271 u32 title_info1 = cmd_buff[1];
262 u32 title_info2 = cmd_buff[2]; 272 u32 title_info2 = cmd_buff[2];
263 u32 title_info3 = cmd_buff[3]; 273 u32 title_info3 = cmd_buff[3];
264 u32 title_info4 = cmd_buff[4]; 274 u32 title_info4 = cmd_buff[4];
265 u32 flags = cmd_buff[5]; 275 u32 flags = cmd_buff[5];
266 276
267 if (flags & 0x00000100) { 277 if (flags & 0x00000100) {
268 unknown_ns_state_field = 1; 278 unknown_ns_state_field = 1;
@@ -270,25 +280,28 @@ void PrepareToStartApplication(Service::Interface* self) {
270 280
271 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 281 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
272 282
273 LOG_WARNING(Service_APT, "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X," 283 LOG_WARNING(Service_APT,
274 "title_info4=0x%08X, flags=0x%08X", title_info1, title_info2, title_info3, title_info4, flags); 284 "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X,"
285 "title_info4=0x%08X, flags=0x%08X",
286 title_info1, title_info2, title_info3, title_info4, flags);
275} 287}
276 288
277void StartApplication(Service::Interface* self) { 289void StartApplication(Service::Interface* self) {
278 u32* cmd_buff = Kernel::GetCommandBuffer(); 290 u32* cmd_buff = Kernel::GetCommandBuffer();
279 u32 buffer1_size = cmd_buff[1]; 291 u32 buffer1_size = cmd_buff[1];
280 u32 buffer2_size = cmd_buff[2]; 292 u32 buffer2_size = cmd_buff[2];
281 u32 flag = cmd_buff[3]; 293 u32 flag = cmd_buff[3];
282 u32 size1 = cmd_buff[4]; 294 u32 size1 = cmd_buff[4];
283 u32 buffer1_ptr = cmd_buff[5]; 295 u32 buffer1_ptr = cmd_buff[5];
284 u32 size2 = cmd_buff[6]; 296 u32 size2 = cmd_buff[6];
285 u32 buffer2_ptr = cmd_buff[7]; 297 u32 buffer2_ptr = cmd_buff[7];
286 298
287 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 299 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
288 300
289 LOG_WARNING(Service_APT, "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X," 301 LOG_WARNING(Service_APT,
290 "size1=0x%08X, buffer1_ptr=0x%08X, size2=0x%08X, buffer2_ptr=0x%08X", 302 "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X,"
291 buffer1_size, buffer2_size, flag, size1, buffer1_ptr, size2, buffer2_ptr); 303 "size1=0x%08X, buffer1_ptr=0x%08X, size2=0x%08X, buffer2_ptr=0x%08X",
304 buffer1_size, buffer2_size, flag, size1, buffer1_ptr, size2, buffer2_ptr);
292} 305}
293 306
294void AppletUtility(Service::Interface* self) { 307void AppletUtility(Service::Interface* self) {
@@ -303,14 +316,15 @@ void AppletUtility(Service::Interface* self) {
303 316
304 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 317 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
305 318
306 LOG_WARNING(Service_APT, "(STUBBED) called command=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, " 319 LOG_WARNING(Service_APT,
307 "buffer1_addr=0x%08X, buffer2_addr=0x%08X", command, buffer1_size, buffer2_size, 320 "(STUBBED) called command=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, "
308 buffer1_addr, buffer2_addr); 321 "buffer1_addr=0x%08X, buffer2_addr=0x%08X",
322 command, buffer1_size, buffer2_size, buffer1_addr, buffer2_addr);
309} 323}
310 324
311void SetAppCpuTimeLimit(Service::Interface* self) { 325void SetAppCpuTimeLimit(Service::Interface* self) {
312 u32* cmd_buff = Kernel::GetCommandBuffer(); 326 u32* cmd_buff = Kernel::GetCommandBuffer();
313 u32 value = cmd_buff[1]; 327 u32 value = cmd_buff[1];
314 cpu_percent = cmd_buff[2]; 328 cpu_percent = cmd_buff[2];
315 329
316 if (value != 1) { 330 if (value != 1) {
@@ -393,7 +407,8 @@ void SetScreenCapPostPermission(Service::Interface* self) {
393 407
394 cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0); 408 cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0);
395 cmd_buff[1] = RESULT_SUCCESS.raw; 409 cmd_buff[1] = RESULT_SUCCESS.raw;
396 LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", screen_capture_post_permission); 410 LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u",
411 screen_capture_post_permission);
397} 412}
398 413
399void GetScreenCapPostPermission(Service::Interface* self) { 414void GetScreenCapPostPermission(Service::Interface* self) {
@@ -402,7 +417,8 @@ void GetScreenCapPostPermission(Service::Interface* self) {
402 cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0); 417 cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0);
403 cmd_buff[1] = RESULT_SUCCESS.raw; 418 cmd_buff[1] = RESULT_SUCCESS.raw;
404 cmd_buff[2] = static_cast<u32>(screen_capture_post_permission); 419 cmd_buff[2] = static_cast<u32>(screen_capture_post_permission);
405 LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", screen_capture_post_permission); 420 LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u",
421 screen_capture_post_permission);
406} 422}
407 423
408void GetAppletInfo(Service::Interface* self) { 424void GetAppletInfo(Service::Interface* self) {
@@ -418,7 +434,8 @@ void GetAppletInfo(Service::Interface* self) {
418 cmd_buff[7] = 0; // Applet Attributes 434 cmd_buff[7] = 0; // Applet Attributes
419 } else { 435 } else {
420 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, 436 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Applet,
421 ErrorSummary::NotFound, ErrorLevel::Status).raw; 437 ErrorSummary::NotFound, ErrorLevel::Status)
438 .raw;
422 } 439 }
423 LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id); 440 LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id);
424} 441}
@@ -429,11 +446,15 @@ void GetStartupArgument(Service::Interface* self) {
429 StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(cmd_buff[2]); 446 StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(cmd_buff[2]);
430 447
431 if (parameter_size >= 0x300) { 448 if (parameter_size >= 0x300) {
432 LOG_ERROR(Service_APT, "Parameter size is outside the valid range (capped to 0x300): parameter_size=0x%08x", parameter_size); 449 LOG_ERROR(
450 Service_APT,
451 "Parameter size is outside the valid range (capped to 0x300): parameter_size=0x%08x",
452 parameter_size);
433 return; 453 return;
434 } 454 }
435 455
436 LOG_WARNING(Service_APT,"(stubbed) called startup_argument_type=%u , parameter_size=0x%08x , parameter_value=0x%08x", 456 LOG_WARNING(Service_APT, "(stubbed) called startup_argument_type=%u , parameter_size=0x%08x , "
457 "parameter_value=0x%08x",
437 startup_argument_type, parameter_size, Memory::Read32(cmd_buff[41])); 458 startup_argument_type, parameter_size, Memory::Read32(cmd_buff[41]));
438 459
439 cmd_buff[1] = RESULT_SUCCESS.raw; 460 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -484,8 +505,10 @@ void Init() {
484 if (file.IsOpen()) { 505 if (file.IsOpen()) {
485 // Create shared font memory object 506 // Create shared font memory object
486 using Kernel::MemoryPermission; 507 using Kernel::MemoryPermission;
487 shared_font_mem = Kernel::SharedMemory::Create(nullptr, 0x332000, // 3272 KB 508 shared_font_mem =
488 MemoryPermission::ReadWrite, MemoryPermission::Read, 0, Kernel::MemoryRegion::SYSTEM, "APT:SharedFont"); 509 Kernel::SharedMemory::Create(nullptr, 0x332000, // 3272 KB
510 MemoryPermission::ReadWrite, MemoryPermission::Read, 0,
511 Kernel::MemoryRegion::SYSTEM, "APT:SharedFont");
489 // Read shared font data 512 // Read shared font data
490 file.ReadBytes(shared_font_mem->GetPointer(), file.GetSize()); 513 file.ReadBytes(shared_font_mem->GetPointer(), file.GetSize());
491 } else { 514 } else {
@@ -497,7 +520,8 @@ void Init() {
497 520
498 cpu_percent = 0; 521 cpu_percent = 0;
499 unknown_ns_state_field = 0; 522 unknown_ns_state_field = 0;
500 screen_capture_post_permission = ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value 523 screen_capture_post_permission =
524 ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value
501 525
502 // TODO(bunnei): Check if these are created in Initialize or on APT process startup. 526 // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
503 notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification"); 527 notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification");
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index 077a6a316..fe8b8a7b8 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -46,58 +46,58 @@ static_assert(sizeof(CaptureBufferInfo) == 0x20, "CaptureBufferInfo struct has i
46 46
47/// Signals used by APT functions 47/// Signals used by APT functions
48enum class SignalType : u32 { 48enum class SignalType : u32 {
49 None = 0x0, 49 None = 0x0,
50 AppJustStarted = 0x1, 50 AppJustStarted = 0x1,
51 LibAppJustStarted = 0x2, 51 LibAppJustStarted = 0x2,
52 LibAppFinished = 0x3, 52 LibAppFinished = 0x3,
53 LibAppClosed = 0xA, 53 LibAppClosed = 0xA,
54 ReturningToApp = 0xB, 54 ReturningToApp = 0xB,
55 ExitingApp = 0xC, 55 ExitingApp = 0xC,
56}; 56};
57 57
58/// App Id's used by APT functions 58/// App Id's used by APT functions
59enum class AppletId : u32 { 59enum class AppletId : u32 {
60 HomeMenu = 0x101, 60 HomeMenu = 0x101,
61 AlternateMenu = 0x103, 61 AlternateMenu = 0x103,
62 Camera = 0x110, 62 Camera = 0x110,
63 FriendsList = 0x112, 63 FriendsList = 0x112,
64 GameNotes = 0x113, 64 GameNotes = 0x113,
65 InternetBrowser = 0x114, 65 InternetBrowser = 0x114,
66 InstructionManual = 0x115, 66 InstructionManual = 0x115,
67 Notifications = 0x116, 67 Notifications = 0x116,
68 Miiverse = 0x117, 68 Miiverse = 0x117,
69 MiiversePost = 0x118, 69 MiiversePost = 0x118,
70 AmiiboSettings = 0x119, 70 AmiiboSettings = 0x119,
71 SoftwareKeyboard1 = 0x201, 71 SoftwareKeyboard1 = 0x201,
72 Ed1 = 0x202, 72 Ed1 = 0x202,
73 PnoteApp = 0x204, 73 PnoteApp = 0x204,
74 SnoteApp = 0x205, 74 SnoteApp = 0x205,
75 Error = 0x206, 75 Error = 0x206,
76 Mint = 0x207, 76 Mint = 0x207,
77 Extrapad = 0x208, 77 Extrapad = 0x208,
78 Memolib = 0x209, 78 Memolib = 0x209,
79 Application = 0x300, 79 Application = 0x300,
80 AnyLibraryApplet = 0x400, 80 AnyLibraryApplet = 0x400,
81 SoftwareKeyboard2 = 0x401, 81 SoftwareKeyboard2 = 0x401,
82 Ed2 = 0x402, 82 Ed2 = 0x402,
83 PnoteApp2 = 0x404, 83 PnoteApp2 = 0x404,
84 SnoteApp2 = 0x405, 84 SnoteApp2 = 0x405,
85 Error2 = 0x406, 85 Error2 = 0x406,
86 Mint2 = 0x407, 86 Mint2 = 0x407,
87 Extrapad2 = 0x408, 87 Extrapad2 = 0x408,
88 Memolib2 = 0x409, 88 Memolib2 = 0x409,
89}; 89};
90 90
91enum class StartupArgumentType : u32 { 91enum class StartupArgumentType : u32 {
92 OtherApp = 0, 92 OtherApp = 0,
93 Restart = 1, 93 Restart = 1,
94 OtherMedia = 2, 94 OtherMedia = 2,
95}; 95};
96 96
97enum class ScreencapPostPermission : u32 { 97enum class ScreencapPostPermission : u32 {
98 CleanThePermission = 0, //TODO(JamePeng): verify what "zero" means 98 CleanThePermission = 0, // TODO(JamePeng): verify what "zero" means
99 NoExplicitSetting = 1, 99 NoExplicitSetting = 1,
100 EnableScreenshotPostingToMiiverse = 2, 100 EnableScreenshotPostingToMiiverse = 2,
101 DisableScreenshotPostingToMiiverse = 3 101 DisableScreenshotPostingToMiiverse = 3
102}; 102};
103 103
@@ -182,9 +182,12 @@ void GetAppletManInfo(Service::Interface* self);
182void GetAppletInfo(Service::Interface* self); 182void GetAppletInfo(Service::Interface* self);
183 183
184/** 184/**
185 * APT::IsRegistered service function. This returns whether the specified AppID is registered with NS yet. 185 * APT::IsRegistered service function. This returns whether the specified AppID is registered with
186 * An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home Menu uses this 186 * NS yet.
187 * command to determine when the launched process is running and to determine when to stop using GSP etc, 187 * An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home Menu
188 * uses this
189 * command to determine when the launched process is running and to determine when to stop using GSP
190 * etc,
188 * while displaying the "Nintendo 3DS" loading screen. 191 * while displaying the "Nintendo 3DS" loading screen.
189 * Inputs: 192 * Inputs:
190 * 1 : AppID 193 * 1 : AppID
@@ -260,9 +263,11 @@ void GlanceParameter(Service::Interface* self);
260 * clears the flag which indicates that parameter data is available 263 * clears the flag which indicates that parameter data is available
261 * (same flag cleared by APT:ReceiveParameter). 264 * (same flag cleared by APT:ReceiveParameter).
262 * Inputs: 265 * Inputs:
263 * 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS state. 266 * 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS
267 * state.
264 * 2 : Unknown, this is the same as the first unknown field returned by APT:ReceiveParameter. 268 * 2 : Unknown, this is the same as the first unknown field returned by APT:ReceiveParameter.
265 * 3 : Flag, when non-zero NS will compare the word after this one with a field in the NS state. 269 * 3 : Flag, when non-zero NS will compare the word after this one with a field in the NS
270 * state.
266 * 4 : AppID 271 * 4 : AppID
267 * Outputs: 272 * Outputs:
268 * 0 : Return header 273 * 0 : Return header
diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp
index 6c44c491c..7d47d7675 100644
--- a/src/core/hle/service/apt/apt_a.cpp
+++ b/src/core/hle/service/apt/apt_a.cpp
@@ -9,35 +9,34 @@ namespace Service {
9namespace APT { 9namespace APT {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010040, GetLockHandle, "GetLockHandle?"}, 12 {0x00010040, GetLockHandle, "GetLockHandle?"},
13 {0x00020080, Initialize, "Initialize?"}, 13 {0x00020080, Initialize, "Initialize?"},
14 {0x00030040, Enable, "Enable?"}, 14 {0x00030040, Enable, "Enable?"},
15 {0x00040040, nullptr, "Finalize?"}, 15 {0x00040040, nullptr, "Finalize?"},
16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, 16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"},
17 {0x00060040, GetAppletInfo, "GetAppletInfo"}, 17 {0x00060040, GetAppletInfo, "GetAppletInfo"},
18 {0x00090040, IsRegistered, "IsRegistered"}, 18 {0x00090040, IsRegistered, "IsRegistered"},
19 {0x000B0040, InquireNotification, "InquireNotification"}, 19 {0x000B0040, InquireNotification, "InquireNotification"},
20 {0x000C0104, SendParameter, "SendParameter"}, 20 {0x000C0104, SendParameter, "SendParameter"},
21 {0x000D0080, ReceiveParameter, "ReceiveParameter"}, 21 {0x000D0080, ReceiveParameter, "ReceiveParameter"},
22 {0x000E0080, GlanceParameter, "GlanceParameter"}, 22 {0x000E0080, GlanceParameter, "GlanceParameter"},
23 {0x000F0100, CancelParameter, "CancelParameter"}, 23 {0x000F0100, CancelParameter, "CancelParameter"},
24 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, 24 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"},
25 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, 25 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
26 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, 26 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
27 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, 27 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
28 {0x003B0040, nullptr, "CancelLibraryApplet?"}, 28 {0x003B0040, nullptr, "CancelLibraryApplet?"},
29 {0x003E0080, nullptr, "ReplySleepQuery"}, 29 {0x003E0080, nullptr, "ReplySleepQuery"},
30 {0x00430040, NotifyToWait, "NotifyToWait?"}, 30 {0x00430040, NotifyToWait, "NotifyToWait?"},
31 {0x00440000, GetSharedFont, "GetSharedFont?"}, 31 {0x00440000, GetSharedFont, "GetSharedFont?"},
32 {0x004B00C2, AppletUtility, "AppletUtility?"}, 32 {0x004B00C2, AppletUtility, "AppletUtility?"},
33 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, 33 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
34 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, 34 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
35 {0x00510080, GetStartupArgument, "GetStartupArgument"}, 35 {0x00510080, GetStartupArgument, "GetStartupArgument"},
36 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, 36 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"},
37 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, 37 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"},
38 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, 38 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"},
39 {0x01020000, CheckNew3DS, "CheckNew3DS"} 39 {0x01020000, CheckNew3DS, "CheckNew3DS"}};
40};
41 40
42APT_A_Interface::APT_A_Interface() { 41APT_A_Interface::APT_A_Interface() {
43 Register(FunctionTable); 42 Register(FunctionTable);
diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp
index c70f2201f..76e71669c 100644
--- a/src/core/hle/service/apt/apt_s.cpp
+++ b/src/core/hle/service/apt/apt_s.cpp
@@ -9,95 +9,94 @@ namespace Service {
9namespace APT { 9namespace APT {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010040, GetLockHandle, "GetLockHandle"}, 12 {0x00010040, GetLockHandle, "GetLockHandle"},
13 {0x00020080, Initialize, "Initialize"}, 13 {0x00020080, Initialize, "Initialize"},
14 {0x00030040, Enable, "Enable"}, 14 {0x00030040, Enable, "Enable"},
15 {0x00040040, nullptr, "Finalize"}, 15 {0x00040040, nullptr, "Finalize"},
16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, 16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"},
17 {0x00060040, GetAppletInfo, "GetAppletInfo"}, 17 {0x00060040, GetAppletInfo, "GetAppletInfo"},
18 {0x00070000, nullptr, "GetLastSignaledAppletId"}, 18 {0x00070000, nullptr, "GetLastSignaledAppletId"},
19 {0x00080000, nullptr, "CountRegisteredApplet"}, 19 {0x00080000, nullptr, "CountRegisteredApplet"},
20 {0x00090040, nullptr, "IsRegistered"}, 20 {0x00090040, nullptr, "IsRegistered"},
21 {0x000A0040, nullptr, "GetAttribute"}, 21 {0x000A0040, nullptr, "GetAttribute"},
22 {0x000B0040, InquireNotification, "InquireNotification"}, 22 {0x000B0040, InquireNotification, "InquireNotification"},
23 {0x000C0104, nullptr, "SendParameter"}, 23 {0x000C0104, nullptr, "SendParameter"},
24 {0x000D0080, ReceiveParameter, "ReceiveParameter"}, 24 {0x000D0080, ReceiveParameter, "ReceiveParameter"},
25 {0x000E0080, GlanceParameter, "GlanceParameter"}, 25 {0x000E0080, GlanceParameter, "GlanceParameter"},
26 {0x000F0100, nullptr, "CancelParameter"}, 26 {0x000F0100, nullptr, "CancelParameter"},
27 {0x001000C2, nullptr, "DebugFunc"}, 27 {0x001000C2, nullptr, "DebugFunc"},
28 {0x001100C0, nullptr, "MapProgramIdForDebug"}, 28 {0x001100C0, nullptr, "MapProgramIdForDebug"},
29 {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, 29 {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"},
30 {0x00130000, nullptr, "GetPreparationState"}, 30 {0x00130000, nullptr, "GetPreparationState"},
31 {0x00140040, nullptr, "SetPreparationState"}, 31 {0x00140040, nullptr, "SetPreparationState"},
32 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, 32 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"},
33 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, 33 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
34 {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, 34 {0x00170040, nullptr, "FinishPreloadingLibraryApplet"},
35 {0x00180040, PrepareToStartLibraryApplet,"PrepareToStartLibraryApplet"}, 35 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
36 {0x00190040, nullptr, "PrepareToStartSystemApplet"}, 36 {0x00190040, nullptr, "PrepareToStartSystemApplet"},
37 {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, 37 {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"},
38 {0x001B00C4, nullptr, "StartApplication"}, 38 {0x001B00C4, nullptr, "StartApplication"},
39 {0x001C0000, nullptr, "WakeupApplication"}, 39 {0x001C0000, nullptr, "WakeupApplication"},
40 {0x001D0000, nullptr, "CancelApplication"}, 40 {0x001D0000, nullptr, "CancelApplication"},
41 {0x001E0084, nullptr, "StartLibraryApplet"}, 41 {0x001E0084, nullptr, "StartLibraryApplet"},
42 {0x001F0084, nullptr, "StartSystemApplet"}, 42 {0x001F0084, nullptr, "StartSystemApplet"},
43 {0x00200044, nullptr, "StartNewestHomeMenu"}, 43 {0x00200044, nullptr, "StartNewestHomeMenu"},
44 {0x00210000, nullptr, "OrderToCloseApplication"}, 44 {0x00210000, nullptr, "OrderToCloseApplication"},
45 {0x00220040, nullptr, "PrepareToCloseApplication"}, 45 {0x00220040, nullptr, "PrepareToCloseApplication"},
46 {0x00230040, nullptr, "PrepareToJumpToApplication"}, 46 {0x00230040, nullptr, "PrepareToJumpToApplication"},
47 {0x00240044, nullptr, "JumpToApplication"}, 47 {0x00240044, nullptr, "JumpToApplication"},
48 {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, 48 {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"},
49 {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, 49 {0x00260000, nullptr, "PrepareToCloseSystemApplet"},
50 {0x00270044, nullptr, "CloseApplication"}, 50 {0x00270044, nullptr, "CloseApplication"},
51 {0x00280044, nullptr, "CloseLibraryApplet"}, 51 {0x00280044, nullptr, "CloseLibraryApplet"},
52 {0x00290044, nullptr, "CloseSystemApplet"}, 52 {0x00290044, nullptr, "CloseSystemApplet"},
53 {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, 53 {0x002A0000, nullptr, "OrderToCloseSystemApplet"},
54 {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, 54 {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"},
55 {0x002C0044, nullptr, "JumpToHomeMenu"}, 55 {0x002C0044, nullptr, "JumpToHomeMenu"},
56 {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, 56 {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"},
57 {0x002E0044, nullptr, "LeaveHomeMenu"}, 57 {0x002E0044, nullptr, "LeaveHomeMenu"},
58 {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, 58 {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"},
59 {0x00300044, nullptr, "LeaveResidentApplet"}, 59 {0x00300044, nullptr, "LeaveResidentApplet"},
60 {0x00310100, nullptr, "PrepareToDoApplicationJump"}, 60 {0x00310100, nullptr, "PrepareToDoApplicationJump"},
61 {0x00320084, nullptr, "DoApplicationJump"}, 61 {0x00320084, nullptr, "DoApplicationJump"},
62 {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, 62 {0x00330000, nullptr, "GetProgramIdOnApplicationJump"},
63 {0x00340084, nullptr, "SendDeliverArg"}, 63 {0x00340084, nullptr, "SendDeliverArg"},
64 {0x00350080, nullptr, "ReceiveDeliverArg"}, 64 {0x00350080, nullptr, "ReceiveDeliverArg"},
65 {0x00360040, nullptr, "LoadSysMenuArg"}, 65 {0x00360040, nullptr, "LoadSysMenuArg"},
66 {0x00370042, nullptr, "StoreSysMenuArg"}, 66 {0x00370042, nullptr, "StoreSysMenuArg"},
67 {0x00380040, nullptr, "PreloadResidentApplet"}, 67 {0x00380040, nullptr, "PreloadResidentApplet"},
68 {0x00390040, nullptr, "PrepareToStartResidentApplet"}, 68 {0x00390040, nullptr, "PrepareToStartResidentApplet"},
69 {0x003A0044, nullptr, "StartResidentApplet"}, 69 {0x003A0044, nullptr, "StartResidentApplet"},
70 {0x003B0040, nullptr, "CancelLibraryApplet"}, 70 {0x003B0040, nullptr, "CancelLibraryApplet"},
71 {0x003C0042, nullptr, "SendDspSleep"}, 71 {0x003C0042, nullptr, "SendDspSleep"},
72 {0x003D0042, nullptr, "SendDspWakeUp"}, 72 {0x003D0042, nullptr, "SendDspWakeUp"},
73 {0x003E0080, nullptr, "ReplySleepQuery"}, 73 {0x003E0080, nullptr, "ReplySleepQuery"},
74 {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, 74 {0x003F0040, nullptr, "ReplySleepNotificationComplete"},
75 {0x00400042, nullptr, "SendCaptureBufferInfo"}, 75 {0x00400042, nullptr, "SendCaptureBufferInfo"},
76 {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, 76 {0x00410040, nullptr, "ReceiveCaptureBufferInfo"},
77 {0x00420080, nullptr, "SleepSystem"}, 77 {0x00420080, nullptr, "SleepSystem"},
78 {0x00430040, NotifyToWait, "NotifyToWait"}, 78 {0x00430040, NotifyToWait, "NotifyToWait"},
79 {0x00440000, GetSharedFont, "GetSharedFont"}, 79 {0x00440000, GetSharedFont, "GetSharedFont"},
80 {0x00450040, nullptr, "GetWirelessRebootInfo"}, 80 {0x00450040, nullptr, "GetWirelessRebootInfo"},
81 {0x00460104, nullptr, "Wrap"}, 81 {0x00460104, nullptr, "Wrap"},
82 {0x00470104, nullptr, "Unwrap"}, 82 {0x00470104, nullptr, "Unwrap"},
83 {0x00480100, nullptr, "GetProgramInfo"}, 83 {0x00480100, nullptr, "GetProgramInfo"},
84 {0x00490180, nullptr, "Reboot"}, 84 {0x00490180, nullptr, "Reboot"},
85 {0x004A0040, nullptr, "GetCaptureInfo"}, 85 {0x004A0040, nullptr, "GetCaptureInfo"},
86 {0x004B00C2, AppletUtility, "AppletUtility"}, 86 {0x004B00C2, AppletUtility, "AppletUtility"},
87 {0x004C0000, nullptr, "SetFatalErrDispMode"}, 87 {0x004C0000, nullptr, "SetFatalErrDispMode"},
88 {0x004D0080, nullptr, "GetAppletProgramInfo"}, 88 {0x004D0080, nullptr, "GetAppletProgramInfo"},
89 {0x004E0000, nullptr, "HardwareResetAsync"}, 89 {0x004E0000, nullptr, "HardwareResetAsync"},
90 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, 90 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
91 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, 91 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
92 {0x00510080, GetStartupArgument, "GetStartupArgument"}, 92 {0x00510080, GetStartupArgument, "GetStartupArgument"},
93 {0x00520104, nullptr, "Wrap1"}, 93 {0x00520104, nullptr, "Wrap1"},
94 {0x00530104, nullptr, "Unwrap1"}, 94 {0x00530104, nullptr, "Unwrap1"},
95 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, 95 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"},
96 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, 96 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"},
97 {0x00580002, nullptr, "GetProgramID"}, 97 {0x00580002, nullptr, "GetProgramID"},
98 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, 98 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"},
99 {0x01020000, CheckNew3DS, "CheckNew3DS"} 99 {0x01020000, CheckNew3DS, "CheckNew3DS"}};
100};
101 100
102APT_S_Interface::APT_S_Interface() { 101APT_S_Interface::APT_S_Interface() {
103 Register(FunctionTable); 102 Register(FunctionTable);
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp
index 7bb804ffa..9c6223dd7 100644
--- a/src/core/hle/service/apt/apt_u.cpp
+++ b/src/core/hle/service/apt/apt_u.cpp
@@ -9,95 +9,94 @@ namespace Service {
9namespace APT { 9namespace APT {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010040, GetLockHandle, "GetLockHandle"}, 12 {0x00010040, GetLockHandle, "GetLockHandle"},
13 {0x00020080, Initialize, "Initialize"}, 13 {0x00020080, Initialize, "Initialize"},
14 {0x00030040, Enable, "Enable"}, 14 {0x00030040, Enable, "Enable"},
15 {0x00040040, nullptr, "Finalize"}, 15 {0x00040040, nullptr, "Finalize"},
16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, 16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"},
17 {0x00060040, GetAppletInfo, "GetAppletInfo"}, 17 {0x00060040, GetAppletInfo, "GetAppletInfo"},
18 {0x00070000, nullptr, "GetLastSignaledAppletId"}, 18 {0x00070000, nullptr, "GetLastSignaledAppletId"},
19 {0x00080000, nullptr, "CountRegisteredApplet"}, 19 {0x00080000, nullptr, "CountRegisteredApplet"},
20 {0x00090040, IsRegistered, "IsRegistered"}, 20 {0x00090040, IsRegistered, "IsRegistered"},
21 {0x000A0040, nullptr, "GetAttribute"}, 21 {0x000A0040, nullptr, "GetAttribute"},
22 {0x000B0040, InquireNotification, "InquireNotification"}, 22 {0x000B0040, InquireNotification, "InquireNotification"},
23 {0x000C0104, SendParameter, "SendParameter"}, 23 {0x000C0104, SendParameter, "SendParameter"},
24 {0x000D0080, ReceiveParameter, "ReceiveParameter"}, 24 {0x000D0080, ReceiveParameter, "ReceiveParameter"},
25 {0x000E0080, GlanceParameter, "GlanceParameter"}, 25 {0x000E0080, GlanceParameter, "GlanceParameter"},
26 {0x000F0100, CancelParameter, "CancelParameter"}, 26 {0x000F0100, CancelParameter, "CancelParameter"},
27 {0x001000C2, nullptr, "DebugFunc"}, 27 {0x001000C2, nullptr, "DebugFunc"},
28 {0x001100C0, nullptr, "MapProgramIdForDebug"}, 28 {0x001100C0, nullptr, "MapProgramIdForDebug"},
29 {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, 29 {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"},
30 {0x00130000, nullptr, "GetPreparationState"}, 30 {0x00130000, nullptr, "GetPreparationState"},
31 {0x00140040, nullptr, "SetPreparationState"}, 31 {0x00140040, nullptr, "SetPreparationState"},
32 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, 32 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"},
33 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, 33 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
34 {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, 34 {0x00170040, nullptr, "FinishPreloadingLibraryApplet"},
35 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, 35 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
36 {0x00190040, nullptr, "PrepareToStartSystemApplet"}, 36 {0x00190040, nullptr, "PrepareToStartSystemApplet"},
37 {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, 37 {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"},
38 {0x001B00C4, nullptr, "StartApplication"}, 38 {0x001B00C4, nullptr, "StartApplication"},
39 {0x001C0000, nullptr, "WakeupApplication"}, 39 {0x001C0000, nullptr, "WakeupApplication"},
40 {0x001D0000, nullptr, "CancelApplication"}, 40 {0x001D0000, nullptr, "CancelApplication"},
41 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, 41 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
42 {0x001F0084, nullptr, "StartSystemApplet"}, 42 {0x001F0084, nullptr, "StartSystemApplet"},
43 {0x00200044, nullptr, "StartNewestHomeMenu"}, 43 {0x00200044, nullptr, "StartNewestHomeMenu"},
44 {0x00210000, nullptr, "OrderToCloseApplication"}, 44 {0x00210000, nullptr, "OrderToCloseApplication"},
45 {0x00220040, nullptr, "PrepareToCloseApplication"}, 45 {0x00220040, nullptr, "PrepareToCloseApplication"},
46 {0x00230040, nullptr, "PrepareToJumpToApplication"}, 46 {0x00230040, nullptr, "PrepareToJumpToApplication"},
47 {0x00240044, nullptr, "JumpToApplication"}, 47 {0x00240044, nullptr, "JumpToApplication"},
48 {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, 48 {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"},
49 {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, 49 {0x00260000, nullptr, "PrepareToCloseSystemApplet"},
50 {0x00270044, nullptr, "CloseApplication"}, 50 {0x00270044, nullptr, "CloseApplication"},
51 {0x00280044, nullptr, "CloseLibraryApplet"}, 51 {0x00280044, nullptr, "CloseLibraryApplet"},
52 {0x00290044, nullptr, "CloseSystemApplet"}, 52 {0x00290044, nullptr, "CloseSystemApplet"},
53 {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, 53 {0x002A0000, nullptr, "OrderToCloseSystemApplet"},
54 {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, 54 {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"},
55 {0x002C0044, nullptr, "JumpToHomeMenu"}, 55 {0x002C0044, nullptr, "JumpToHomeMenu"},
56 {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, 56 {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"},
57 {0x002E0044, nullptr, "LeaveHomeMenu"}, 57 {0x002E0044, nullptr, "LeaveHomeMenu"},
58 {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, 58 {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"},
59 {0x00300044, nullptr, "LeaveResidentApplet"}, 59 {0x00300044, nullptr, "LeaveResidentApplet"},
60 {0x00310100, nullptr, "PrepareToDoApplicationJump"}, 60 {0x00310100, nullptr, "PrepareToDoApplicationJump"},
61 {0x00320084, nullptr, "DoApplicationJump"}, 61 {0x00320084, nullptr, "DoApplicationJump"},
62 {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, 62 {0x00330000, nullptr, "GetProgramIdOnApplicationJump"},
63 {0x00340084, nullptr, "SendDeliverArg"}, 63 {0x00340084, nullptr, "SendDeliverArg"},
64 {0x00350080, nullptr, "ReceiveDeliverArg"}, 64 {0x00350080, nullptr, "ReceiveDeliverArg"},
65 {0x00360040, nullptr, "LoadSysMenuArg"}, 65 {0x00360040, nullptr, "LoadSysMenuArg"},
66 {0x00370042, nullptr, "StoreSysMenuArg"}, 66 {0x00370042, nullptr, "StoreSysMenuArg"},
67 {0x00380040, nullptr, "PreloadResidentApplet"}, 67 {0x00380040, nullptr, "PreloadResidentApplet"},
68 {0x00390040, nullptr, "PrepareToStartResidentApplet"}, 68 {0x00390040, nullptr, "PrepareToStartResidentApplet"},
69 {0x003A0044, nullptr, "StartResidentApplet"}, 69 {0x003A0044, nullptr, "StartResidentApplet"},
70 {0x003B0040, nullptr, "CancelLibraryApplet"}, 70 {0x003B0040, nullptr, "CancelLibraryApplet"},
71 {0x003C0042, nullptr, "SendDspSleep"}, 71 {0x003C0042, nullptr, "SendDspSleep"},
72 {0x003D0042, nullptr, "SendDspWakeUp"}, 72 {0x003D0042, nullptr, "SendDspWakeUp"},
73 {0x003E0080, nullptr, "ReplySleepQuery"}, 73 {0x003E0080, nullptr, "ReplySleepQuery"},
74 {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, 74 {0x003F0040, nullptr, "ReplySleepNotificationComplete"},
75 {0x00400042, nullptr, "SendCaptureBufferInfo"}, 75 {0x00400042, nullptr, "SendCaptureBufferInfo"},
76 {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, 76 {0x00410040, nullptr, "ReceiveCaptureBufferInfo"},
77 {0x00420080, nullptr, "SleepSystem"}, 77 {0x00420080, nullptr, "SleepSystem"},
78 {0x00430040, NotifyToWait, "NotifyToWait"}, 78 {0x00430040, NotifyToWait, "NotifyToWait"},
79 {0x00440000, GetSharedFont, "GetSharedFont"}, 79 {0x00440000, GetSharedFont, "GetSharedFont"},
80 {0x00450040, nullptr, "GetWirelessRebootInfo"}, 80 {0x00450040, nullptr, "GetWirelessRebootInfo"},
81 {0x00460104, nullptr, "Wrap"}, 81 {0x00460104, nullptr, "Wrap"},
82 {0x00470104, nullptr, "Unwrap"}, 82 {0x00470104, nullptr, "Unwrap"},
83 {0x00480100, nullptr, "GetProgramInfo"}, 83 {0x00480100, nullptr, "GetProgramInfo"},
84 {0x00490180, nullptr, "Reboot"}, 84 {0x00490180, nullptr, "Reboot"},
85 {0x004A0040, nullptr, "GetCaptureInfo"}, 85 {0x004A0040, nullptr, "GetCaptureInfo"},
86 {0x004B00C2, AppletUtility, "AppletUtility"}, 86 {0x004B00C2, AppletUtility, "AppletUtility"},
87 {0x004C0000, nullptr, "SetFatalErrDispMode"}, 87 {0x004C0000, nullptr, "SetFatalErrDispMode"},
88 {0x004D0080, nullptr, "GetAppletProgramInfo"}, 88 {0x004D0080, nullptr, "GetAppletProgramInfo"},
89 {0x004E0000, nullptr, "HardwareResetAsync"}, 89 {0x004E0000, nullptr, "HardwareResetAsync"},
90 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, 90 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
91 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, 91 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
92 {0x00510080, GetStartupArgument, "GetStartupArgument"}, 92 {0x00510080, GetStartupArgument, "GetStartupArgument"},
93 {0x00520104, nullptr, "Wrap1"}, 93 {0x00520104, nullptr, "Wrap1"},
94 {0x00530104, nullptr, "Unwrap1"}, 94 {0x00530104, nullptr, "Unwrap1"},
95 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, 95 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"},
96 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, 96 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"},
97 {0x00580002, nullptr, "GetProgramID"}, 97 {0x00580002, nullptr, "GetProgramID"},
98 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, 98 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"},
99 {0x01020000, CheckNew3DS, "CheckNew3DS"} 99 {0x01020000, CheckNew3DS, "CheckNew3DS"}};
100};
101 100
102APT_U_Interface::APT_U_Interface() { 101APT_U_Interface::APT_U_Interface() {
103 Register(FunctionTable); 102 Register(FunctionTable);
diff --git a/src/core/hle/service/boss/boss.cpp b/src/core/hle/service/boss/boss.cpp
index 419ec976e..867b31fbf 100644
--- a/src/core/hle/service/boss/boss.cpp
+++ b/src/core/hle/service/boss/boss.cpp
@@ -2,10 +2,10 @@
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 "core/hle/service/service.h"
6#include "core/hle/service/boss/boss.h" 5#include "core/hle/service/boss/boss.h"
7#include "core/hle/service/boss/boss_p.h" 6#include "core/hle/service/boss/boss_p.h"
8#include "core/hle/service/boss/boss_u.h" 7#include "core/hle/service/boss/boss_u.h"
8#include "core/hle/service/service.h"
9 9
10namespace Service { 10namespace Service {
11namespace BOSS { 11namespace BOSS {
diff --git a/src/core/hle/service/boss/boss_p.cpp b/src/core/hle/service/boss/boss_p.cpp
index c498abe4e..dfee8d055 100644
--- a/src/core/hle/service/boss/boss_p.cpp
+++ b/src/core/hle/service/boss/boss_p.cpp
@@ -11,7 +11,7 @@ namespace BOSS {
11// const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13BOSS_P_Interface::BOSS_P_Interface() { 13BOSS_P_Interface::BOSS_P_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace BOSS 17} // namespace BOSS
diff --git a/src/core/hle/service/boss/boss_u.cpp b/src/core/hle/service/boss/boss_u.cpp
index d59babe71..6affa23b1 100644
--- a/src/core/hle/service/boss/boss_u.cpp
+++ b/src/core/hle/service/boss/boss_u.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace BOSS { 8namespace BOSS {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x00020100, nullptr, "GetStorageInfo"}, 11 {0x00020100, nullptr, "GetStorageInfo"},
12 {0x000C0082, nullptr, "UnregisterTask"}, 12 {0x000C0082, nullptr, "UnregisterTask"},
13 {0x001E0042, nullptr, "CancelTask"}, 13 {0x001E0042, nullptr, "CancelTask"},
14 {0x00330042, nullptr, "StartBgImmediate"}, 14 {0x00330042, nullptr, "StartBgImmediate"},
15}; 15};
16 16
17BOSS_U_Interface::BOSS_U_Interface() { 17BOSS_U_Interface::BOSS_U_Interface() {
diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp
index 6edcf9610..ec1f9c749 100644
--- a/src/core/hle/service/cam/cam.cpp
+++ b/src/core/hle/service/cam/cam.cpp
@@ -71,15 +71,15 @@ void GetBufferErrorInterruptEvent(Service::Interface* self) {
71} 71}
72 72
73void SetReceiving(Service::Interface* self) { 73void SetReceiving(Service::Interface* self) {
74 u32* cmd_buff = Kernel::GetCommandBuffer(); 74 u32* cmd_buff = Kernel::GetCommandBuffer();
75 75
76 VAddr dest = cmd_buff[1]; 76 VAddr dest = cmd_buff[1];
77 u8 port = cmd_buff[2] & 0xFF; 77 u8 port = cmd_buff[2] & 0xFF;
78 u32 image_size = cmd_buff[3]; 78 u32 image_size = cmd_buff[3];
79 u16 trans_unit = cmd_buff[4] & 0xFFFF; 79 u16 trans_unit = cmd_buff[4] & 0xFFFF;
80 80
81 Kernel::Event* completion_event = (Port)port == Port::Cam2 ? 81 Kernel::Event* completion_event =
82 completion_event_cam2.get() : completion_event_cam1.get(); 82 (Port)port == Port::Cam2 ? completion_event_cam2.get() : completion_event_cam1.get();
83 83
84 completion_event->Signal(); 84 completion_event->Signal();
85 85
@@ -89,36 +89,36 @@ void SetReceiving(Service::Interface* self) {
89 cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom(); 89 cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom();
90 90
91 LOG_WARNING(Service_CAM, "(STUBBED) called, addr=0x%X, port=%d, image_size=%d, trans_unit=%d", 91 LOG_WARNING(Service_CAM, "(STUBBED) called, addr=0x%X, port=%d, image_size=%d, trans_unit=%d",
92 dest, port, image_size, trans_unit); 92 dest, port, image_size, trans_unit);
93} 93}
94 94
95void SetTransferLines(Service::Interface* self) { 95void SetTransferLines(Service::Interface* self) {
96 u32* cmd_buff = Kernel::GetCommandBuffer(); 96 u32* cmd_buff = Kernel::GetCommandBuffer();
97 97
98 u8 port = cmd_buff[1] & 0xFF; 98 u8 port = cmd_buff[1] & 0xFF;
99 u16 transfer_lines = cmd_buff[2] & 0xFFFF; 99 u16 transfer_lines = cmd_buff[2] & 0xFFFF;
100 u16 width = cmd_buff[3] & 0xFFFF; 100 u16 width = cmd_buff[3] & 0xFFFF;
101 u16 height = cmd_buff[4] & 0xFFFF; 101 u16 height = cmd_buff[4] & 0xFFFF;
102 102
103 cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0); 103 cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0);
104 cmd_buff[1] = RESULT_SUCCESS.raw; 104 cmd_buff[1] = RESULT_SUCCESS.raw;
105 105
106 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, lines=%d, width=%d, height=%d", 106 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, lines=%d, width=%d, height=%d", port,
107 port, transfer_lines, width, height); 107 transfer_lines, width, height);
108} 108}
109 109
110void GetMaxLines(Service::Interface* self) { 110void GetMaxLines(Service::Interface* self) {
111 u32* cmd_buff = Kernel::GetCommandBuffer(); 111 u32* cmd_buff = Kernel::GetCommandBuffer();
112 112
113 u16 width = cmd_buff[1] & 0xFFFF; 113 u16 width = cmd_buff[1] & 0xFFFF;
114 u16 height = cmd_buff[2] & 0xFFFF; 114 u16 height = cmd_buff[2] & 0xFFFF;
115 115
116 cmd_buff[0] = IPC::MakeHeader(0xA, 2, 0); 116 cmd_buff[0] = IPC::MakeHeader(0xA, 2, 0);
117 cmd_buff[1] = RESULT_SUCCESS.raw; 117 cmd_buff[1] = RESULT_SUCCESS.raw;
118 cmd_buff[2] = TRANSFER_BYTES / (2 * width); 118 cmd_buff[2] = TRANSFER_BYTES / (2 * width);
119 119
120 LOG_WARNING(Service_CAM, "(STUBBED) called, width=%d, height=%d, lines = %d", 120 LOG_WARNING(Service_CAM, "(STUBBED) called, width=%d, height=%d, lines = %d", width, height,
121 width, height, cmd_buff[2]); 121 cmd_buff[2]);
122} 122}
123 123
124void GetTransferBytes(Service::Interface* self) { 124void GetTransferBytes(Service::Interface* self) {
@@ -136,7 +136,7 @@ void GetTransferBytes(Service::Interface* self) {
136void SetTrimming(Service::Interface* self) { 136void SetTrimming(Service::Interface* self) {
137 u32* cmd_buff = Kernel::GetCommandBuffer(); 137 u32* cmd_buff = Kernel::GetCommandBuffer();
138 138
139 u8 port = cmd_buff[1] & 0xFF; 139 u8 port = cmd_buff[1] & 0xFF;
140 bool trim = (cmd_buff[2] & 0xFF) != 0; 140 bool trim = (cmd_buff[2] & 0xFF) != 0;
141 141
142 cmd_buff[0] = IPC::MakeHeader(0xE, 1, 0); 142 cmd_buff[0] = IPC::MakeHeader(0xE, 1, 0);
@@ -148,17 +148,17 @@ void SetTrimming(Service::Interface* self) {
148void SetTrimmingParamsCenter(Service::Interface* self) { 148void SetTrimmingParamsCenter(Service::Interface* self) {
149 u32* cmd_buff = Kernel::GetCommandBuffer(); 149 u32* cmd_buff = Kernel::GetCommandBuffer();
150 150
151 u8 port = cmd_buff[1] & 0xFF; 151 u8 port = cmd_buff[1] & 0xFF;
152 s16 trimW = cmd_buff[2] & 0xFFFF; 152 s16 trimW = cmd_buff[2] & 0xFFFF;
153 s16 trimH = cmd_buff[3] & 0xFFFF; 153 s16 trimH = cmd_buff[3] & 0xFFFF;
154 s16 camW = cmd_buff[4] & 0xFFFF; 154 s16 camW = cmd_buff[4] & 0xFFFF;
155 s16 camH = cmd_buff[5] & 0xFFFF; 155 s16 camH = cmd_buff[5] & 0xFFFF;
156 156
157 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); 157 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0);
158 cmd_buff[1] = RESULT_SUCCESS.raw; 158 cmd_buff[1] = RESULT_SUCCESS.raw;
159 159
160 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trimW=%d, trimH=%d, camW=%d, camH=%d", 160 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trimW=%d, trimH=%d, camW=%d, camH=%d",
161 port, trimW, trimH, camW, camH); 161 port, trimW, trimH, camW, camH);
162} 162}
163 163
164void Activate(Service::Interface* self) { 164void Activate(Service::Interface* self) {
@@ -169,36 +169,35 @@ void Activate(Service::Interface* self) {
169 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); 169 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0);
170 cmd_buff[1] = RESULT_SUCCESS.raw; 170 cmd_buff[1] = RESULT_SUCCESS.raw;
171 171
172 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d", 172 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d", cam_select);
173 cam_select);
174} 173}
175 174
176void FlipImage(Service::Interface* self) { 175void FlipImage(Service::Interface* self) {
177 u32* cmd_buff = Kernel::GetCommandBuffer(); 176 u32* cmd_buff = Kernel::GetCommandBuffer();
178 177
179 u8 cam_select = cmd_buff[1] & 0xFF; 178 u8 cam_select = cmd_buff[1] & 0xFF;
180 u8 flip = cmd_buff[2] & 0xFF; 179 u8 flip = cmd_buff[2] & 0xFF;
181 u8 context = cmd_buff[3] & 0xFF; 180 u8 context = cmd_buff[3] & 0xFF;
182 181
183 cmd_buff[0] = IPC::MakeHeader(0x1D, 1, 0); 182 cmd_buff[0] = IPC::MakeHeader(0x1D, 1, 0);
184 cmd_buff[1] = RESULT_SUCCESS.raw; 183 cmd_buff[1] = RESULT_SUCCESS.raw;
185 184
186 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, flip=%d, context=%d", 185 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, flip=%d, context=%d", cam_select,
187 cam_select, flip, context); 186 flip, context);
188} 187}
189 188
190void SetSize(Service::Interface* self) { 189void SetSize(Service::Interface* self) {
191 u32* cmd_buff = Kernel::GetCommandBuffer(); 190 u32* cmd_buff = Kernel::GetCommandBuffer();
192 191
193 u8 cam_select = cmd_buff[1] & 0xFF; 192 u8 cam_select = cmd_buff[1] & 0xFF;
194 u8 size = cmd_buff[2] & 0xFF; 193 u8 size = cmd_buff[2] & 0xFF;
195 u8 context = cmd_buff[3] & 0xFF; 194 u8 context = cmd_buff[3] & 0xFF;
196 195
197 cmd_buff[0] = IPC::MakeHeader(0x1F, 1, 0); 196 cmd_buff[0] = IPC::MakeHeader(0x1F, 1, 0);
198 cmd_buff[1] = RESULT_SUCCESS.raw; 197 cmd_buff[1] = RESULT_SUCCESS.raw;
199 198
200 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, size=%d, context=%d", 199 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, size=%d, context=%d", cam_select,
201 cam_select, size, context); 200 size, context);
202} 201}
203 202
204void SetFrameRate(Service::Interface* self) { 203void SetFrameRate(Service::Interface* self) {
@@ -210,8 +209,8 @@ void SetFrameRate(Service::Interface* self) {
210 cmd_buff[0] = IPC::MakeHeader(0x20, 1, 0); 209 cmd_buff[0] = IPC::MakeHeader(0x20, 1, 0);
211 cmd_buff[1] = RESULT_SUCCESS.raw; 210 cmd_buff[1] = RESULT_SUCCESS.raw;
212 211
213 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, frame_rate=%d", 212 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, frame_rate=%d", cam_select,
214 cam_select, frame_rate); 213 frame_rate);
215} 214}
216 215
217void GetStereoCameraCalibrationData(Service::Interface* self) { 216void GetStereoCameraCalibrationData(Service::Interface* self) {
@@ -293,10 +292,14 @@ void Init() {
293 AddService(new CAM_S_Interface); 292 AddService(new CAM_S_Interface);
294 AddService(new CAM_U_Interface); 293 AddService(new CAM_U_Interface);
295 294
296 completion_event_cam1 = Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam1"); 295 completion_event_cam1 =
297 completion_event_cam2 = Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam2"); 296 Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam1");
298 interrupt_error_event = Kernel::Event::Create(ResetType::OneShot, "CAM_U::interrupt_error_event"); 297 completion_event_cam2 =
299 vsync_interrupt_error_event = Kernel::Event::Create(ResetType::OneShot, "CAM_U::vsync_interrupt_error_event"); 298 Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam2");
299 interrupt_error_event =
300 Kernel::Event::Create(ResetType::OneShot, "CAM_U::interrupt_error_event");
301 vsync_interrupt_error_event =
302 Kernel::Event::Create(ResetType::OneShot, "CAM_U::vsync_interrupt_error_event");
300} 303}
301 304
302void Shutdown() { 305void Shutdown() {
diff --git a/src/core/hle/service/cam/cam.h b/src/core/hle/service/cam/cam.h
index 2f4923728..a87183493 100644
--- a/src/core/hle/service/cam/cam.h
+++ b/src/core/hle/service/cam/cam.h
@@ -14,12 +14,7 @@
14namespace Service { 14namespace Service {
15namespace CAM { 15namespace CAM {
16 16
17enum class Port : u8 { 17enum class Port : u8 { None = 0, Cam1 = 1, Cam2 = 2, Both = Cam1 | Cam2 };
18 None = 0,
19 Cam1 = 1,
20 Cam2 = 2,
21 Both = Cam1 | Cam2
22};
23 18
24enum class CameraSelect : u8 { 19enum class CameraSelect : u8 {
25 None = 0, 20 None = 0,
@@ -32,28 +27,11 @@ enum class CameraSelect : u8 {
32 All = Out1 | In1 | Out2 27 All = Out1 | In1 | Out2
33}; 28};
34 29
35enum class Effect : u8 { 30enum class Effect : u8 { None = 0, Mono = 1, Sepia = 2, Negative = 3, Negafilm = 4, Sepia01 = 5 };
36 None = 0,
37 Mono = 1,
38 Sepia = 2,
39 Negative = 3,
40 Negafilm = 4,
41 Sepia01 = 5
42};
43 31
44enum class Context : u8 { 32enum class Context : u8 { None = 0, A = 1, B = 2, Both = A | B };
45 None = 0,
46 A = 1,
47 B = 2,
48 Both = A | B
49};
50 33
51enum class Flip : u8 { 34enum class Flip : u8 { None = 0, Horizontal = 1, Vertical = 2, Reverse = 3 };
52 None = 0,
53 Horizontal = 1,
54 Vertical = 2,
55 Reverse = 3
56};
57 35
58enum class Size : u8 { 36enum class Size : u8 {
59 VGA = 0, 37 VGA = 0,
@@ -83,11 +61,7 @@ enum class FrameRate : u8 {
83 Rate_30_To_10 = 12 61 Rate_30_To_10 = 12
84}; 62};
85 63
86enum class ShutterSoundType : u8 { 64enum class ShutterSoundType : u8 { Normal = 0, Movie = 1, MovieEnd = 2 };
87 Normal = 0,
88 Movie = 1,
89 MovieEnd = 2
90};
91 65
92enum class WhiteBalance : u8 { 66enum class WhiteBalance : u8 {
93 BalanceAuto = 0, 67 BalanceAuto = 0,
@@ -106,13 +80,7 @@ enum class WhiteBalance : u8 {
106 BalanceShade = Balance7000K 80 BalanceShade = Balance7000K
107}; 81};
108 82
109enum class PhotoMode : u8 { 83enum class PhotoMode : u8 { Normal = 0, Portrait = 1, Landscape = 2, Nightview = 3, Letter0 = 4 };
110 Normal = 0,
111 Portrait = 1,
112 Landscape = 2,
113 Nightview = 3,
114 Letter0 = 4
115};
116 84
117enum class LensCorrection : u8 { 85enum class LensCorrection : u8 {
118 Off = 0, 86 Off = 0,
@@ -140,21 +108,18 @@ enum class Contrast : u8 {
140 High = Pattern07 108 High = Pattern07
141}; 109};
142 110
143enum class OutputFormat : u8 { 111enum class OutputFormat : u8 { YUV422 = 0, RGB565 = 1 };
144 YUV422 = 0,
145 RGB565 = 1
146};
147 112
148/// Stereo camera calibration data. 113/// Stereo camera calibration data.
149struct StereoCameraCalibrationData { 114struct StereoCameraCalibrationData {
150 u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid. 115 u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid.
151 INSERT_PADDING_BYTES(3); 116 INSERT_PADDING_BYTES(3);
152 float_le scale; ///< Scale to match the left camera image with the right. 117 float_le scale; ///< Scale to match the left camera image with the right.
153 float_le rotationZ; ///< Z axis rotation to match the left camera image with the right. 118 float_le rotationZ; ///< Z axis rotation to match the left camera image with the right.
154 float_le translationX; ///< X axis translation to match the left camera image with the right. 119 float_le translationX; ///< X axis translation to match the left camera image with the right.
155 float_le translationY; ///< Y axis translation to match the left camera image with the right. 120 float_le translationY; ///< Y axis translation to match the left camera image with the right.
156 float_le rotationX; ///< X axis rotation to match the left camera image with the right. 121 float_le rotationX; ///< X axis rotation to match the left camera image with the right.
157 float_le rotationY; ///< Y axis rotation to match the left camera image with the right. 122 float_le rotationY; ///< Y axis rotation to match the left camera image with the right.
158 float_le angleOfViewRight; ///< Right camera angle of view. 123 float_le angleOfViewRight; ///< Right camera angle of view.
159 float_le angleOfViewLeft; ///< Left camera angle of view. 124 float_le angleOfViewLeft; ///< Left camera angle of view.
160 float_le distanceToChart; ///< Distance between cameras and measurement chart. 125 float_le distanceToChart; ///< Distance between cameras and measurement chart.
@@ -163,7 +128,8 @@ struct StereoCameraCalibrationData {
163 s16_le imageHeight; ///< Image height. 128 s16_le imageHeight; ///< Image height.
164 INSERT_PADDING_BYTES(16); 129 INSERT_PADDING_BYTES(16);
165}; 130};
166static_assert(sizeof(StereoCameraCalibrationData) == 64, "StereoCameraCalibrationData structure size is wrong"); 131static_assert(sizeof(StereoCameraCalibrationData) == 64,
132 "StereoCameraCalibrationData structure size is wrong");
167 133
168struct PackageParameterCameraSelect { 134struct PackageParameterCameraSelect {
169 CameraSelect camera; 135 CameraSelect camera;
@@ -188,7 +154,8 @@ struct PackageParameterCameraSelect {
188 s16 auto_white_balance_window_height; 154 s16 auto_white_balance_window_height;
189}; 155};
190 156
191static_assert(sizeof(PackageParameterCameraSelect) == 28, "PackageParameterCameraSelect structure size is wrong"); 157static_assert(sizeof(PackageParameterCameraSelect) == 28,
158 "PackageParameterCameraSelect structure size is wrong");
192 159
193/** 160/**
194 * Unknown 161 * Unknown
diff --git a/src/core/hle/service/cam/cam_c.cpp b/src/core/hle/service/cam/cam_c.cpp
index 8fa7abc85..93b047c1a 100644
--- a/src/core/hle/service/cam/cam_c.cpp
+++ b/src/core/hle/service/cam/cam_c.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace CAM { 8namespace CAM {
9 9
10// Empty arrays are illegal -- commented out until an entry is added. 10// Empty arrays are illegal -- commented out until an entry is added.
11//const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13CAM_C_Interface::CAM_C_Interface() { 13CAM_C_Interface::CAM_C_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace CAM 17} // namespace CAM
diff --git a/src/core/hle/service/cam/cam_q.cpp b/src/core/hle/service/cam/cam_q.cpp
index d3ba91e9d..2ba853606 100644
--- a/src/core/hle/service/cam/cam_q.cpp
+++ b/src/core/hle/service/cam/cam_q.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace CAM { 8namespace CAM {
9 9
10// Empty arrays are illegal -- commented out until an entry is added. 10// Empty arrays are illegal -- commented out until an entry is added.
11//const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13CAM_Q_Interface::CAM_Q_Interface() { 13CAM_Q_Interface::CAM_Q_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace CAM 17} // namespace CAM
diff --git a/src/core/hle/service/cam/cam_s.cpp b/src/core/hle/service/cam/cam_s.cpp
index 2a13984d8..f1c6da587 100644
--- a/src/core/hle/service/cam/cam_s.cpp
+++ b/src/core/hle/service/cam/cam_s.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace CAM { 8namespace CAM {
9 9
10// Empty arrays are illegal -- commented out until an entry is added. 10// Empty arrays are illegal -- commented out until an entry is added.
11//const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13CAM_S_Interface::CAM_S_Interface() { 13CAM_S_Interface::CAM_S_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace CAM 17} // namespace CAM
diff --git a/src/core/hle/service/cam/cam_u.cpp b/src/core/hle/service/cam/cam_u.cpp
index a1070ebb2..af2123e5b 100644
--- a/src/core/hle/service/cam/cam_u.cpp
+++ b/src/core/hle/service/cam/cam_u.cpp
@@ -9,68 +9,68 @@ namespace Service {
9namespace CAM { 9namespace CAM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010040, StartCapture, "StartCapture"}, 12 {0x00010040, StartCapture, "StartCapture"},
13 {0x00020040, StopCapture, "StopCapture"}, 13 {0x00020040, StopCapture, "StopCapture"},
14 {0x00030040, nullptr, "IsBusy"}, 14 {0x00030040, nullptr, "IsBusy"},
15 {0x00040040, nullptr, "ClearBuffer"}, 15 {0x00040040, nullptr, "ClearBuffer"},
16 {0x00050040, GetVsyncInterruptEvent, "GetVsyncInterruptEvent"}, 16 {0x00050040, GetVsyncInterruptEvent, "GetVsyncInterruptEvent"},
17 {0x00060040, GetBufferErrorInterruptEvent, "GetBufferErrorInterruptEvent"}, 17 {0x00060040, GetBufferErrorInterruptEvent, "GetBufferErrorInterruptEvent"},
18 {0x00070102, SetReceiving, "SetReceiving"}, 18 {0x00070102, SetReceiving, "SetReceiving"},
19 {0x00080040, nullptr, "IsFinishedReceiving"}, 19 {0x00080040, nullptr, "IsFinishedReceiving"},
20 {0x00090100, SetTransferLines, "SetTransferLines"}, 20 {0x00090100, SetTransferLines, "SetTransferLines"},
21 {0x000A0080, GetMaxLines, "GetMaxLines"}, 21 {0x000A0080, GetMaxLines, "GetMaxLines"},
22 {0x000B0100, nullptr, "SetTransferBytes"}, 22 {0x000B0100, nullptr, "SetTransferBytes"},
23 {0x000C0040, GetTransferBytes, "GetTransferBytes"}, 23 {0x000C0040, GetTransferBytes, "GetTransferBytes"},
24 {0x000D0080, nullptr, "GetMaxBytes"}, 24 {0x000D0080, nullptr, "GetMaxBytes"},
25 {0x000E0080, SetTrimming, "SetTrimming"}, 25 {0x000E0080, SetTrimming, "SetTrimming"},
26 {0x000F0040, nullptr, "IsTrimming"}, 26 {0x000F0040, nullptr, "IsTrimming"},
27 {0x00100140, nullptr, "SetTrimmingParams"}, 27 {0x00100140, nullptr, "SetTrimmingParams"},
28 {0x00110040, nullptr, "GetTrimmingParams"}, 28 {0x00110040, nullptr, "GetTrimmingParams"},
29 {0x00120140, SetTrimmingParamsCenter, "SetTrimmingParamsCenter"}, 29 {0x00120140, SetTrimmingParamsCenter, "SetTrimmingParamsCenter"},
30 {0x00130040, Activate, "Activate"}, 30 {0x00130040, Activate, "Activate"},
31 {0x00140080, nullptr, "SwitchContext"}, 31 {0x00140080, nullptr, "SwitchContext"},
32 {0x00150080, nullptr, "SetExposure"}, 32 {0x00150080, nullptr, "SetExposure"},
33 {0x00160080, nullptr, "SetWhiteBalance"}, 33 {0x00160080, nullptr, "SetWhiteBalance"},
34 {0x00170080, nullptr, "SetWhiteBalanceWithoutBaseUp"}, 34 {0x00170080, nullptr, "SetWhiteBalanceWithoutBaseUp"},
35 {0x00180080, nullptr, "SetSharpness"}, 35 {0x00180080, nullptr, "SetSharpness"},
36 {0x00190080, nullptr, "SetAutoExposure"}, 36 {0x00190080, nullptr, "SetAutoExposure"},
37 {0x001A0040, nullptr, "IsAutoExposure"}, 37 {0x001A0040, nullptr, "IsAutoExposure"},
38 {0x001B0080, nullptr, "SetAutoWhiteBalance"}, 38 {0x001B0080, nullptr, "SetAutoWhiteBalance"},
39 {0x001C0040, nullptr, "IsAutoWhiteBalance"}, 39 {0x001C0040, nullptr, "IsAutoWhiteBalance"},
40 {0x001D00C0, FlipImage, "FlipImage"}, 40 {0x001D00C0, FlipImage, "FlipImage"},
41 {0x001E0200, nullptr, "SetDetailSize"}, 41 {0x001E0200, nullptr, "SetDetailSize"},
42 {0x001F00C0, SetSize, "SetSize"}, 42 {0x001F00C0, SetSize, "SetSize"},
43 {0x00200080, SetFrameRate, "SetFrameRate"}, 43 {0x00200080, SetFrameRate, "SetFrameRate"},
44 {0x00210080, nullptr, "SetPhotoMode"}, 44 {0x00210080, nullptr, "SetPhotoMode"},
45 {0x002200C0, nullptr, "SetEffect"}, 45 {0x002200C0, nullptr, "SetEffect"},
46 {0x00230080, nullptr, "SetContrast"}, 46 {0x00230080, nullptr, "SetContrast"},
47 {0x00240080, nullptr, "SetLensCorrection"}, 47 {0x00240080, nullptr, "SetLensCorrection"},
48 {0x002500C0, nullptr, "SetOutputFormat"}, 48 {0x002500C0, nullptr, "SetOutputFormat"},
49 {0x00260140, nullptr, "SetAutoExposureWindow"}, 49 {0x00260140, nullptr, "SetAutoExposureWindow"},
50 {0x00270140, nullptr, "SetAutoWhiteBalanceWindow"}, 50 {0x00270140, nullptr, "SetAutoWhiteBalanceWindow"},
51 {0x00280080, nullptr, "SetNoiseFilter"}, 51 {0x00280080, nullptr, "SetNoiseFilter"},
52 {0x00290080, nullptr, "SynchronizeVsyncTiming"}, 52 {0x00290080, nullptr, "SynchronizeVsyncTiming"},
53 {0x002A0080, nullptr, "GetLatestVsyncTiming"}, 53 {0x002A0080, nullptr, "GetLatestVsyncTiming"},
54 {0x002B0000, GetStereoCameraCalibrationData, "GetStereoCameraCalibrationData"}, 54 {0x002B0000, GetStereoCameraCalibrationData, "GetStereoCameraCalibrationData"},
55 {0x002C0400, nullptr, "SetStereoCameraCalibrationData"}, 55 {0x002C0400, nullptr, "SetStereoCameraCalibrationData"},
56 {0x002D00C0, nullptr, "WriteRegisterI2c"}, 56 {0x002D00C0, nullptr, "WriteRegisterI2c"},
57 {0x002E00C0, nullptr, "WriteMcuVariableI2c"}, 57 {0x002E00C0, nullptr, "WriteMcuVariableI2c"},
58 {0x002F0080, nullptr, "ReadRegisterI2cExclusive"}, 58 {0x002F0080, nullptr, "ReadRegisterI2cExclusive"},
59 {0x00300080, nullptr, "ReadMcuVariableI2cExclusive"}, 59 {0x00300080, nullptr, "ReadMcuVariableI2cExclusive"},
60 {0x00310180, nullptr, "SetImageQualityCalibrationData"}, 60 {0x00310180, nullptr, "SetImageQualityCalibrationData"},
61 {0x00320000, nullptr, "GetImageQualityCalibrationData"}, 61 {0x00320000, nullptr, "GetImageQualityCalibrationData"},
62 {0x003302C0, nullptr, "SetPackageParameterWithoutContext"}, 62 {0x003302C0, nullptr, "SetPackageParameterWithoutContext"},
63 {0x00340140, nullptr, "SetPackageParameterWithContext"}, 63 {0x00340140, nullptr, "SetPackageParameterWithContext"},
64 {0x003501C0, nullptr, "SetPackageParameterWithContextDetail"}, 64 {0x003501C0, nullptr, "SetPackageParameterWithContextDetail"},
65 {0x00360000, GetSuitableY2rStandardCoefficient, "GetSuitableY2rStandardCoefficient"}, 65 {0x00360000, GetSuitableY2rStandardCoefficient, "GetSuitableY2rStandardCoefficient"},
66 {0x00370202, nullptr, "PlayShutterSoundWithWave"}, 66 {0x00370202, nullptr, "PlayShutterSoundWithWave"},
67 {0x00380040, PlayShutterSound, "PlayShutterSound"}, 67 {0x00380040, PlayShutterSound, "PlayShutterSound"},
68 {0x00390000, DriverInitialize, "DriverInitialize"}, 68 {0x00390000, DriverInitialize, "DriverInitialize"},
69 {0x003A0000, DriverFinalize, "DriverFinalize"}, 69 {0x003A0000, DriverFinalize, "DriverFinalize"},
70 {0x003B0000, nullptr, "GetActivatedCamera"}, 70 {0x003B0000, nullptr, "GetActivatedCamera"},
71 {0x003C0000, nullptr, "GetSleepCamera"}, 71 {0x003C0000, nullptr, "GetSleepCamera"},
72 {0x003D0040, nullptr, "SetSleepCamera"}, 72 {0x003D0040, nullptr, "SetSleepCamera"},
73 {0x003E0040, nullptr, "SetBrightnessSynchronization"}, 73 {0x003E0040, nullptr, "SetBrightnessSynchronization"},
74}; 74};
75 75
76CAM_U_Interface::CAM_U_Interface() { 76CAM_U_Interface::CAM_U_Interface() {
diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp
index 50c03495e..65a1d850b 100644
--- a/src/core/hle/service/cecd/cecd.cpp
+++ b/src/core/hle/service/cecd/cecd.cpp
@@ -5,10 +5,10 @@
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6 6
7#include "core/hle/kernel/event.h" 7#include "core/hle/kernel/event.h"
8#include "core/hle/service/service.h"
9#include "core/hle/service/cecd/cecd.h" 8#include "core/hle/service/cecd/cecd.h"
10#include "core/hle/service/cecd/cecd_s.h" 9#include "core/hle/service/cecd/cecd_s.h"
11#include "core/hle/service/cecd/cecd_u.h" 10#include "core/hle/service/cecd/cecd_u.h"
11#include "core/hle/service/service.h"
12 12
13namespace Service { 13namespace Service {
14namespace CECD { 14namespace CECD {
@@ -28,7 +28,7 @@ void GetCecStateAbbreviated(Service::Interface* self) {
28void GetCecInfoEventHandle(Service::Interface* self) { 28void GetCecInfoEventHandle(Service::Interface* self) {
29 u32* cmd_buff = Kernel::GetCommandBuffer(); 29 u32* cmd_buff = Kernel::GetCommandBuffer();
30 30
31 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 31 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
32 cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle 32 cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle
33 33
34 LOG_WARNING(Service_CECD, "(STUBBED) called"); 34 LOG_WARNING(Service_CECD, "(STUBBED) called");
@@ -37,7 +37,7 @@ void GetCecInfoEventHandle(Service::Interface* self) {
37void GetChangeStateEventHandle(Service::Interface* self) { 37void GetChangeStateEventHandle(Service::Interface* self) {
38 u32* cmd_buff = Kernel::GetCommandBuffer(); 38 u32* cmd_buff = Kernel::GetCommandBuffer();
39 39
40 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 40 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
41 cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle 41 cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle
42 42
43 LOG_WARNING(Service_CECD, "(STUBBED) called"); 43 LOG_WARNING(Service_CECD, "(STUBBED) called");
@@ -48,7 +48,8 @@ void Init() {
48 AddService(new CECD_U_Interface); 48 AddService(new CECD_U_Interface);
49 49
50 cecinfo_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::cecinfo_event"); 50 cecinfo_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::cecinfo_event");
51 change_state_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::change_state_event"); 51 change_state_event =
52 Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::change_state_event");
52} 53}
53 54
54void Shutdown() { 55void Shutdown() {
diff --git a/src/core/hle/service/cecd/cecd.h b/src/core/hle/service/cecd/cecd.h
index 435611363..ea97f9266 100644
--- a/src/core/hle/service/cecd/cecd.h
+++ b/src/core/hle/service/cecd/cecd.h
@@ -11,11 +11,13 @@ class Interface;
11namespace CECD { 11namespace CECD {
12 12
13enum class CecStateAbbreviated { 13enum class CecStateAbbreviated {
14 CEC_STATE_ABBREV_IDLE = 1, ///< Corresponds to CEC_STATE_IDLE 14 CEC_STATE_ABBREV_IDLE = 1, ///< Corresponds to CEC_STATE_IDLE
15 CEC_STATE_ABBREV_NOT_LOCAL = 2, ///< Corresponds to CEC_STATEs *FINISH*, *POST, and OVER_BOSS 15 CEC_STATE_ABBREV_NOT_LOCAL = 2, ///< Corresponds to CEC_STATEs *FINISH*, *POST, and OVER_BOSS
16 CEC_STATE_ABBREV_SCANNING = 3, ///< Corresponds to CEC_STATE_SCANNING 16 CEC_STATE_ABBREV_SCANNING = 3, ///< Corresponds to CEC_STATE_SCANNING
17 CEC_STATE_ABBREV_WLREADY = 4, ///< Corresponds to CEC_STATE_WIRELESS_READY when some unknown bool is true 17 CEC_STATE_ABBREV_WLREADY =
18 CEC_STATE_ABBREV_OTHER = 5, ///< Corresponds to CEC_STATEs besides *FINISH*, *POST, and OVER_BOSS and those listed here 18 4, ///< Corresponds to CEC_STATE_WIRELESS_READY when some unknown bool is true
19 CEC_STATE_ABBREV_OTHER = 5, ///< Corresponds to CEC_STATEs besides *FINISH*, *POST, and
20 /// OVER_BOSS and those listed here
19}; 21};
20 22
21/** 23/**
diff --git a/src/core/hle/service/cecd/cecd_s.cpp b/src/core/hle/service/cecd/cecd_s.cpp
index bfd821c07..7477b9320 100644
--- a/src/core/hle/service/cecd/cecd_s.cpp
+++ b/src/core/hle/service/cecd/cecd_s.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace CECD { 8namespace CECD {
9 9
10// Empty arrays are illegal -- commented out until an entry is added. 10// Empty arrays are illegal -- commented out until an entry is added.
11//const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13CECD_S_Interface::CECD_S_Interface() { 13CECD_S_Interface::CECD_S_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace CECD 17} // namespace CECD
diff --git a/src/core/hle/service/cecd/cecd_u.cpp b/src/core/hle/service/cecd/cecd_u.cpp
index be6d4d8f6..4b747de7b 100644
--- a/src/core/hle/service/cecd/cecd_u.cpp
+++ b/src/core/hle/service/cecd/cecd_u.cpp
@@ -9,10 +9,10 @@ namespace Service {
9namespace CECD { 9namespace CECD {
10 10
11static const Interface::FunctionInfo FunctionTable[] = { 11static const Interface::FunctionInfo FunctionTable[] = {
12 {0x000E0000, GetCecStateAbbreviated, "GetCecStateAbbreviated"}, 12 {0x000E0000, GetCecStateAbbreviated, "GetCecStateAbbreviated"},
13 {0x000F0000, GetCecInfoEventHandle, "GetCecInfoEventHandle"}, 13 {0x000F0000, GetCecInfoEventHandle, "GetCecInfoEventHandle"},
14 {0x00100000, GetChangeStateEventHandle, "GetChangeStateEventHandle"}, 14 {0x00100000, GetChangeStateEventHandle, "GetChangeStateEventHandle"},
15 {0x00120104, nullptr, "ReadSavedData"}, 15 {0x00120104, nullptr, "ReadSavedData"},
16}; 16};
17 17
18CECD_U_Interface::CECD_U_Interface() { 18CECD_U_Interface::CECD_U_Interface() {
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
index a5dc47322..fe97a69d1 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -11,7 +11,6 @@
11 11
12#include "core/file_sys/archive_systemsavedata.h" 12#include "core/file_sys/archive_systemsavedata.h"
13#include "core/file_sys/file_backend.h" 13#include "core/file_sys/file_backend.h"
14#include "core/settings.h"
15#include "core/hle/result.h" 14#include "core/hle/result.h"
16#include "core/hle/service/cfg/cfg.h" 15#include "core/hle/service/cfg/cfg.h"
17#include "core/hle/service/cfg/cfg_i.h" 16#include "core/hle/service/cfg/cfg_i.h"
@@ -19,6 +18,7 @@
19#include "core/hle/service/cfg/cfg_u.h" 18#include "core/hle/service/cfg/cfg_u.h"
20#include "core/hle/service/fs/archive.h" 19#include "core/hle/service/fs/archive.h"
21#include "core/hle/service/service.h" 20#include "core/hle/service/service.h"
21#include "core/settings.h"
22 22
23namespace Service { 23namespace Service {
24namespace CFG { 24namespace CFG {
@@ -33,25 +33,29 @@ namespace {
33 * contains information about the blocks in the file 33 * contains information about the blocks in the file
34 */ 34 */
35struct SaveFileConfig { 35struct SaveFileConfig {
36 u16 total_entries; ///< The total number of set entries in the config file 36 u16 total_entries; ///< The total number of set entries in the config file
37 u16 data_entries_offset; ///< The offset where the data for the blocks start, this is hardcoded to 0x455C as per hardware 37 u16 data_entries_offset; ///< The offset where the data for the blocks start, this is hardcoded
38 SaveConfigBlockEntry block_entries[CONFIG_FILE_MAX_BLOCK_ENTRIES]; ///< The block headers, the maximum possible value is 1479 as per hardware 38 /// to 0x455C as per hardware
39 u32 unknown; ///< This field is unknown, possibly padding, 0 has been observed in hardware 39 SaveConfigBlockEntry block_entries[CONFIG_FILE_MAX_BLOCK_ENTRIES]; ///< The block headers, the
40 /// maximum possible value is
41 /// 1479 as per hardware
42 u32 unknown; ///< This field is unknown, possibly padding, 0 has been observed in hardware
40}; 43};
41static_assert(sizeof(SaveFileConfig) == 0x455C, "SaveFileConfig header must be exactly 0x455C bytes"); 44static_assert(sizeof(SaveFileConfig) == 0x455C,
45 "SaveFileConfig header must be exactly 0x455C bytes");
42 46
43enum ConfigBlockID { 47enum ConfigBlockID {
44 StereoCameraSettingsBlockID = 0x00050005, 48 StereoCameraSettingsBlockID = 0x00050005,
45 SoundOutputModeBlockID = 0x00070001, 49 SoundOutputModeBlockID = 0x00070001,
46 ConsoleUniqueIDBlockID = 0x00090001, 50 ConsoleUniqueIDBlockID = 0x00090001,
47 UsernameBlockID = 0x000A0000, 51 UsernameBlockID = 0x000A0000,
48 BirthdayBlockID = 0x000A0001, 52 BirthdayBlockID = 0x000A0001,
49 LanguageBlockID = 0x000A0002, 53 LanguageBlockID = 0x000A0002,
50 CountryInfoBlockID = 0x000B0000, 54 CountryInfoBlockID = 0x000B0000,
51 CountryNameBlockID = 0x000B0001, 55 CountryNameBlockID = 0x000B0001,
52 StateNameBlockID = 0x000B0002, 56 StateNameBlockID = 0x000B0002,
53 EULAVersionBlockID = 0x000D0000, 57 EULAVersionBlockID = 0x000D0000,
54 ConsoleModelBlockID = 0x000F0004, 58 ConsoleModelBlockID = 0x000F0004,
55}; 59};
56 60
57struct UsernameBlock { 61struct UsernameBlock {
@@ -68,8 +72,8 @@ struct BirthdayBlock {
68static_assert(sizeof(BirthdayBlock) == 2, "BirthdayBlock must be exactly 2 bytes"); 72static_assert(sizeof(BirthdayBlock) == 2, "BirthdayBlock must be exactly 2 bytes");
69 73
70struct ConsoleModelInfo { 74struct ConsoleModelInfo {
71 u8 model; ///< The console model (3DS, 2DS, etc) 75 u8 model; ///< The console model (3DS, 2DS, etc)
72 u8 unknown[3]; ///< Unknown data 76 u8 unknown[3]; ///< Unknown data
73}; 77};
74static_assert(sizeof(ConsoleModelInfo) == 4, "ConsoleModelInfo must be exactly 4 bytes"); 78static_assert(sizeof(ConsoleModelInfo) == 4, "ConsoleModelInfo must be exactly 4 bytes");
75 79
@@ -78,36 +82,36 @@ struct ConsoleCountryInfo {
78 u8 country_code; ///< The country code of the console 82 u8 country_code; ///< The country code of the console
79}; 83};
80static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes"); 84static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes");
81
82} 85}
83 86
84static const u64 CFG_SAVE_ID = 0x00010017; 87static const u64 CFG_SAVE_ID = 0x00010017;
85static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; 88static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE;
86static const ConsoleModelInfo CONSOLE_MODEL = { NINTENDO_3DS_XL, { 0, 0, 0 } }; 89static const ConsoleModelInfo CONSOLE_MODEL = {NINTENDO_3DS_XL, {0, 0, 0}};
87static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; 90static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN;
88static const UsernameBlock CONSOLE_USERNAME_BLOCK = { u"CITRA", 0, 0 }; 91static const UsernameBlock CONSOLE_USERNAME_BLOCK = {u"CITRA", 0, 0};
89static const BirthdayBlock PROFILE_BIRTHDAY = { 3, 25 }; // March 25th, 2014 92static const BirthdayBlock PROFILE_BIRTHDAY = {3, 25}; // March 25th, 2014
90static const u8 SOUND_OUTPUT_MODE = SOUND_SURROUND; 93static const u8 SOUND_OUTPUT_MODE = SOUND_SURROUND;
91static const u8 UNITED_STATES_COUNTRY_ID = 49; 94static const u8 UNITED_STATES_COUNTRY_ID = 49;
92/// TODO(Subv): Find what the other bytes are 95/// TODO(Subv): Find what the other bytes are
93static const ConsoleCountryInfo COUNTRY_INFO = { { 0, 0, 0 }, UNITED_STATES_COUNTRY_ID }; 96static const ConsoleCountryInfo COUNTRY_INFO = {{0, 0, 0}, UNITED_STATES_COUNTRY_ID};
94 97
95/** 98/**
96 * TODO(Subv): Find out what this actually is, these values fix some NaN uniforms in some games, 99 * TODO(Subv): Find out what this actually is, these values fix some NaN uniforms in some games,
97 * for example Nintendo Zone 100 * for example Nintendo Zone
98 * Thanks Normmatt for providing this information 101 * Thanks Normmatt for providing this information
99 */ 102 */
100static const std::array<float, 8> STEREO_CAMERA_SETTINGS = {{ 103static const std::array<float, 8> STEREO_CAMERA_SETTINGS = {
101 62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f, 104 {62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f, 10.0f, 5.0f, 55.58000183105469f,
102 10.0f, 5.0f, 55.58000183105469f, 21.56999969482422f 105 21.56999969482422f}};
103}}; 106static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20,
104static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20, "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes"); 107 "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes");
105 108
106static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; 109static const u32 CONFIG_SAVEFILE_SIZE = 0x8000;
107static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer; 110static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
108 111
109static Service::FS::ArchiveHandle cfg_system_save_data_archive; 112static Service::FS::ArchiveHandle cfg_system_save_data_archive;
110static const std::vector<u8> cfg_system_savedata_id = { 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00 }; 113static const std::vector<u8> cfg_system_savedata_id = {0x00, 0x00, 0x00, 0x00,
114 0x17, 0x00, 0x01, 0x00};
111 115
112void GetCountryCodeString(Service::Interface* self) { 116void GetCountryCodeString(Service::Interface* self) {
113 u32* cmd_buff = Kernel::GetCommandBuffer(); 117 u32* cmd_buff = Kernel::GetCommandBuffer();
@@ -115,7 +119,9 @@ void GetCountryCodeString(Service::Interface* self) {
115 119
116 if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) { 120 if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) {
117 LOG_ERROR(Service_CFG, "requested country code id=%d is invalid", country_code_id); 121 LOG_ERROR(Service_CFG, "requested country code id=%d is invalid", country_code_id);
118 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; 122 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config,
123 ErrorSummary::WrongArgument, ErrorLevel::Permanent)
124 .raw;
119 return; 125 return;
120 } 126 }
121 127
@@ -139,8 +145,11 @@ void GetCountryCodeID(Service::Interface* self) {
139 } 145 }
140 146
141 if (0 == country_code_id) { 147 if (0 == country_code_id) {
142 LOG_ERROR(Service_CFG, "requested country code name=%c%c is invalid", country_code & 0xff, country_code >> 8); 148 LOG_ERROR(Service_CFG, "requested country code name=%c%c is invalid", country_code & 0xff,
143 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; 149 country_code >> 8);
150 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config,
151 ErrorSummary::WrongArgument, ErrorLevel::Permanent)
152 .raw;
144 cmd_buff[2] = 0xFFFF; 153 cmd_buff[2] = 0xFFFF;
145 return; 154 return;
146 } 155 }
@@ -185,8 +194,8 @@ void GetSystemModel(Service::Interface* self) {
185 u32 data; 194 u32 data;
186 195
187 // TODO(Subv): Find out the correct error codes 196 // TODO(Subv): Find out the correct error codes
188 cmd_buff[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, 197 cmd_buff[1] =
189 reinterpret_cast<u8*>(&data)).raw; 198 Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, reinterpret_cast<u8*>(&data)).raw;
190 cmd_buff[2] = data & 0xFF; 199 cmd_buff[2] = data & 0xFF;
191} 200}
192 201
@@ -195,8 +204,8 @@ void GetModelNintendo2DS(Service::Interface* self) {
195 u32 data; 204 u32 data;
196 205
197 // TODO(Subv): Find out the correct error codes 206 // TODO(Subv): Find out the correct error codes
198 cmd_buff[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, 207 cmd_buff[1] =
199 reinterpret_cast<u8*>(&data)).raw; 208 Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, reinterpret_cast<u8*>(&data)).raw;
200 209
201 u8 model = data & 0xFF; 210 u8 model = data & 0xFF;
202 if (model == Service::CFG::NINTENDO_2DS) 211 if (model == Service::CFG::NINTENDO_2DS)
@@ -267,24 +276,29 @@ static ResultVal<void*> GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 fl
267 // Read the header 276 // Read the header
268 SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data()); 277 SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data());
269 278
270 auto itr = std::find_if(std::begin(config->block_entries), std::end(config->block_entries), 279 auto itr =
271 [&](const SaveConfigBlockEntry& entry) { 280 std::find_if(std::begin(config->block_entries), std::end(config->block_entries),
272 return entry.block_id == block_id; 281 [&](const SaveConfigBlockEntry& entry) { return entry.block_id == block_id; });
273 });
274 282
275 if (itr == std::end(config->block_entries)) { 283 if (itr == std::end(config->block_entries)) {
276 LOG_ERROR(Service_CFG, "Config block 0x%X with flags %u and size %u was not found", block_id, flag, size); 284 LOG_ERROR(Service_CFG, "Config block 0x%X with flags %u and size %u was not found",
277 return ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 285 block_id, flag, size);
286 return ResultCode(ErrorDescription::NotFound, ErrorModule::Config,
287 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
278 } 288 }
279 289
280 if ((itr->flags & flag) == 0) { 290 if ((itr->flags & flag) == 0) {
281 LOG_ERROR(Service_CFG, "Invalid flag %u for config block 0x%X with size %u", flag, block_id, size); 291 LOG_ERROR(Service_CFG, "Invalid flag %u for config block 0x%X with size %u", flag, block_id,
282 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 292 size);
293 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::Config,
294 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
283 } 295 }
284 296
285 if (itr->size != size) { 297 if (itr->size != size) {
286 LOG_ERROR(Service_CFG, "Invalid size %u for config block 0x%X with flags %u", size, block_id, flag); 298 LOG_ERROR(Service_CFG, "Invalid size %u for config block 0x%X with flags %u", size,
287 return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 299 block_id, flag);
300 return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Config,
301 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
288 } 302 }
289 303
290 void* pointer; 304 void* pointer;
@@ -318,7 +332,7 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da
318 return ResultCode(-1); // TODO(Subv): Find the right error code 332 return ResultCode(-1); // TODO(Subv): Find the right error code
319 333
320 // Insert the block header with offset 0 for now 334 // Insert the block header with offset 0 for now
321 config->block_entries[config->total_entries] = { block_id, 0, size, flags }; 335 config->block_entries[config->total_entries] = {block_id, 0, size, flags};
322 if (size > 4) { 336 if (size > 4) {
323 u32 offset = config->data_entries_offset; 337 u32 offset = config->data_entries_offset;
324 // Perform a search to locate the next offset for the new data 338 // Perform a search to locate the next offset for the new data
@@ -326,8 +340,7 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da
326 for (int i = config->total_entries - 1; i >= 0; --i) { 340 for (int i = config->total_entries - 1; i >= 0; --i) {
327 // Ignore the blocks that don't have a separate data offset 341 // Ignore the blocks that don't have a separate data offset
328 if (config->block_entries[i].size > 4) { 342 if (config->block_entries[i].size > 4) {
329 offset = config->block_entries[i].offset_or_data + 343 offset = config->block_entries[i].offset_or_data + config->block_entries[i].size;
330 config->block_entries[i].size;
331 break; 344 break;
332 } 345 }
333 } 346 }
@@ -336,8 +349,7 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da
336 349
337 // Write the data at the new offset 350 // Write the data at the new offset
338 memcpy(&cfg_config_file_buffer[offset], data, size); 351 memcpy(&cfg_config_file_buffer[offset], data, size);
339 } 352 } else {
340 else {
341 // The offset_or_data field in the header contains the data itself if it's 4 bytes or less 353 // The offset_or_data field in the header contains the data itself if it's 4 bytes or less
342 memcpy(&config->block_entries[config->total_entries].offset_or_data, data, size); 354 memcpy(&config->block_entries[config->total_entries].offset_or_data, data, size);
343 } 355 }
@@ -384,28 +396,40 @@ ResultCode FormatConfig() {
384 396
385 // 0x00030001 - Unknown 397 // 0x00030001 - Unknown
386 res = CreateConfigInfoBlk(0x00030001, 0x8, 0xE, zero_buffer); 398 res = CreateConfigInfoBlk(0x00030001, 0x8, 0xE, zero_buffer);
387 if (!res.IsSuccess()) return res; 399 if (!res.IsSuccess())
400 return res;
388 401
389 res = CreateConfigInfoBlk(StereoCameraSettingsBlockID, sizeof(STEREO_CAMERA_SETTINGS), 0xE, STEREO_CAMERA_SETTINGS.data()); 402 res = CreateConfigInfoBlk(StereoCameraSettingsBlockID, sizeof(STEREO_CAMERA_SETTINGS), 0xE,
390 if (!res.IsSuccess()) return res; 403 STEREO_CAMERA_SETTINGS.data());
404 if (!res.IsSuccess())
405 return res;
391 406
392 res = CreateConfigInfoBlk(SoundOutputModeBlockID, sizeof(SOUND_OUTPUT_MODE), 0xE, &SOUND_OUTPUT_MODE); 407 res = CreateConfigInfoBlk(SoundOutputModeBlockID, sizeof(SOUND_OUTPUT_MODE), 0xE,
393 if (!res.IsSuccess()) return res; 408 &SOUND_OUTPUT_MODE);
409 if (!res.IsSuccess())
410 return res;
394 411
395 res = CreateConfigInfoBlk(ConsoleUniqueIDBlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE, &CONSOLE_UNIQUE_ID); 412 res = CreateConfigInfoBlk(ConsoleUniqueIDBlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE,
396 if (!res.IsSuccess()) return res; 413 &CONSOLE_UNIQUE_ID);
414 if (!res.IsSuccess())
415 return res;
397 416
398 res = CreateConfigInfoBlk(UsernameBlockID, sizeof(CONSOLE_USERNAME_BLOCK), 0xE, &CONSOLE_USERNAME_BLOCK); 417 res = CreateConfigInfoBlk(UsernameBlockID, sizeof(CONSOLE_USERNAME_BLOCK), 0xE,
399 if (!res.IsSuccess()) return res; 418 &CONSOLE_USERNAME_BLOCK);
419 if (!res.IsSuccess())
420 return res;
400 421
401 res = CreateConfigInfoBlk(BirthdayBlockID, sizeof(PROFILE_BIRTHDAY), 0xE, &PROFILE_BIRTHDAY); 422 res = CreateConfigInfoBlk(BirthdayBlockID, sizeof(PROFILE_BIRTHDAY), 0xE, &PROFILE_BIRTHDAY);
402 if (!res.IsSuccess()) return res; 423 if (!res.IsSuccess())
424 return res;
403 425
404 res = CreateConfigInfoBlk(LanguageBlockID, sizeof(CONSOLE_LANGUAGE), 0xE, &CONSOLE_LANGUAGE); 426 res = CreateConfigInfoBlk(LanguageBlockID, sizeof(CONSOLE_LANGUAGE), 0xE, &CONSOLE_LANGUAGE);
405 if (!res.IsSuccess()) return res; 427 if (!res.IsSuccess())
428 return res;
406 429
407 res = CreateConfigInfoBlk(CountryInfoBlockID, sizeof(COUNTRY_INFO), 0xE, &COUNTRY_INFO); 430 res = CreateConfigInfoBlk(CountryInfoBlockID, sizeof(COUNTRY_INFO), 0xE, &COUNTRY_INFO);
408 if (!res.IsSuccess()) return res; 431 if (!res.IsSuccess())
432 return res;
409 433
410 u16_le country_name_buffer[16][0x40] = {}; 434 u16_le country_name_buffer[16][0x40] = {};
411 std::u16string region_name = Common::UTF8ToUTF16("Gensokyo"); 435 std::u16string region_name = Common::UTF8ToUTF16("Gensokyo");
@@ -413,34 +437,44 @@ ResultCode FormatConfig() {
413 std::copy(region_name.cbegin(), region_name.cend(), country_name_buffer[i]); 437 std::copy(region_name.cbegin(), region_name.cend(), country_name_buffer[i]);
414 } 438 }
415 // 0x000B0001 - Localized names for the profile Country 439 // 0x000B0001 - Localized names for the profile Country
416 res = CreateConfigInfoBlk(CountryNameBlockID, sizeof(country_name_buffer), 0xE, country_name_buffer); 440 res = CreateConfigInfoBlk(CountryNameBlockID, sizeof(country_name_buffer), 0xE,
417 if (!res.IsSuccess()) return res; 441 country_name_buffer);
442 if (!res.IsSuccess())
443 return res;
418 // 0x000B0002 - Localized names for the profile State/Province 444 // 0x000B0002 - Localized names for the profile State/Province
419 res = CreateConfigInfoBlk(StateNameBlockID, sizeof(country_name_buffer), 0xE, country_name_buffer); 445 res = CreateConfigInfoBlk(StateNameBlockID, sizeof(country_name_buffer), 0xE,
420 if (!res.IsSuccess()) return res; 446 country_name_buffer);
447 if (!res.IsSuccess())
448 return res;
421 449
422 // 0x000B0003 - Unknown, related to country/address (zip code?) 450 // 0x000B0003 - Unknown, related to country/address (zip code?)
423 res = CreateConfigInfoBlk(0x000B0003, 0x4, 0xE, zero_buffer); 451 res = CreateConfigInfoBlk(0x000B0003, 0x4, 0xE, zero_buffer);
424 if (!res.IsSuccess()) return res; 452 if (!res.IsSuccess())
453 return res;
425 454
426 // 0x000C0000 - Unknown 455 // 0x000C0000 - Unknown
427 res = CreateConfigInfoBlk(0x000C0000, 0xC0, 0xE, zero_buffer); 456 res = CreateConfigInfoBlk(0x000C0000, 0xC0, 0xE, zero_buffer);
428 if (!res.IsSuccess()) return res; 457 if (!res.IsSuccess())
458 return res;
429 459
430 // 0x000C0001 - Unknown 460 // 0x000C0001 - Unknown
431 res = CreateConfigInfoBlk(0x000C0001, 0x14, 0xE, zero_buffer); 461 res = CreateConfigInfoBlk(0x000C0001, 0x14, 0xE, zero_buffer);
432 if (!res.IsSuccess()) return res; 462 if (!res.IsSuccess())
463 return res;
433 464
434 // 0x000D0000 - Accepted EULA version 465 // 0x000D0000 - Accepted EULA version
435 res = CreateConfigInfoBlk(EULAVersionBlockID, 0x4, 0xE, zero_buffer); 466 res = CreateConfigInfoBlk(EULAVersionBlockID, 0x4, 0xE, zero_buffer);
436 if (!res.IsSuccess()) return res; 467 if (!res.IsSuccess())
468 return res;
437 469
438 res = CreateConfigInfoBlk(ConsoleModelBlockID, sizeof(CONSOLE_MODEL), 0xC, &CONSOLE_MODEL); 470 res = CreateConfigInfoBlk(ConsoleModelBlockID, sizeof(CONSOLE_MODEL), 0xC, &CONSOLE_MODEL);
439 if (!res.IsSuccess()) return res; 471 if (!res.IsSuccess())
472 return res;
440 473
441 // 0x00170000 - Unknown 474 // 0x00170000 - Unknown
442 res = CreateConfigInfoBlk(0x00170000, 0x4, 0xE, zero_buffer); 475 res = CreateConfigInfoBlk(0x00170000, 0x4, 0xE, zero_buffer);
443 if (!res.IsSuccess()) return res; 476 if (!res.IsSuccess())
477 return res;
444 478
445 // Save the buffer to the file 479 // Save the buffer to the file
446 res = UpdateConfigNANDSavegame(); 480 res = UpdateConfigNANDSavegame();
@@ -452,15 +486,18 @@ ResultCode FormatConfig() {
452ResultCode LoadConfigNANDSaveFile() { 486ResultCode LoadConfigNANDSaveFile() {
453 // Open the SystemSaveData archive 0x00010017 487 // Open the SystemSaveData archive 0x00010017
454 FileSys::Path archive_path(cfg_system_savedata_id); 488 FileSys::Path archive_path(cfg_system_savedata_id);
455 auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); 489 auto archive_result =
490 Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path);
456 491
457 // If the archive didn't exist, create the files inside 492 // If the archive didn't exist, create the files inside
458 if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { 493 if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) {
459 // Format the archive to create the directories 494 // Format the archive to create the directories
460 Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData, FileSys::ArchiveFormatInfo(), archive_path); 495 Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData,
496 FileSys::ArchiveFormatInfo(), archive_path);
461 497
462 // Open it again to get a valid archive now that the folder exists 498 // Open it again to get a valid archive now that the folder exists
463 archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); 499 archive_result =
500 Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path);
464 } 501 }
465 502
466 ASSERT_MSG(archive_result.Succeeded(), "Could not open the CFG SystemSaveData archive!"); 503 ASSERT_MSG(archive_result.Succeeded(), "Could not open the CFG SystemSaveData archive!");
@@ -515,7 +552,7 @@ std::u16string GetUsername() {
515} 552}
516 553
517void SetBirthday(u8 month, u8 day) { 554void SetBirthday(u8 month, u8 day) {
518 BirthdayBlock block = { month, day }; 555 BirthdayBlock block = {month, day};
519 SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block); 556 SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block);
520} 557}
521 558
diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h
index 18f60f4ca..8cb231d72 100644
--- a/src/core/hle/service/cfg/cfg.h
+++ b/src/core/hle/service/cfg/cfg.h
@@ -40,16 +40,13 @@ enum SystemLanguage {
40 LANGUAGE_TW = 11 40 LANGUAGE_TW = 11
41}; 41};
42 42
43enum SoundOutputMode { 43enum SoundOutputMode { SOUND_MONO = 0, SOUND_STEREO = 1, SOUND_SURROUND = 2 };
44 SOUND_MONO = 0,
45 SOUND_STEREO = 1,
46 SOUND_SURROUND = 2
47};
48 44
49/// Block header in the config savedata file 45/// Block header in the config savedata file
50struct SaveConfigBlockEntry { 46struct SaveConfigBlockEntry {
51 u32 block_id; ///< The id of the current block 47 u32 block_id; ///< The id of the current block
52 u32 offset_or_data; ///< This is the absolute offset to the block data if the size is greater than 4 bytes, otherwise it contains the data itself 48 u32 offset_or_data; ///< This is the absolute offset to the block data if the size is greater
49 /// than 4 bytes, otherwise it contains the data itself
53 u16 size; ///< The size of the block 50 u16 size; ///< The size of the block
54 u16 flags; ///< The flags of the block, possibly used for access control 51 u16 flags; ///< The flags of the block, possibly used for access control
55}; 52};
@@ -244,7 +241,8 @@ ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output);
244ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input); 241ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input);
245 242
246/** 243/**
247 * Creates a block with the specified id and writes the input data to the cfg savegame buffer in memory. 244 * Creates a block with the specified id and writes the input data to the cfg savegame buffer in
245 * memory.
248 * The config savegame file in the filesystem is not updated. 246 * The config savegame file in the filesystem is not updated.
249 * @param block_id The id of the block we want to create 247 * @param block_id The id of the block we want to create
250 * @param size The size of the block we want to create 248 * @param size The size of the block we want to create
diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp
index 8b0db785f..2ff52c8b8 100644
--- a/src/core/hle/service/cfg/cfg_i.cpp
+++ b/src/core/hle/service/cfg/cfg_i.cpp
@@ -10,49 +10,49 @@ namespace CFG {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 // cfg common 12 // cfg common
13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, 13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, 14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, 15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, 16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"},
17 {0x00050000, GetSystemModel, "GetSystemModel"}, 17 {0x00050000, GetSystemModel, "GetSystemModel"},
18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, 18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, 19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
20 {0x00080080, nullptr, "GoThroughTable"}, 20 {0x00080080, nullptr, "GoThroughTable"},
21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, 21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, 22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
23 // cfg:i 23 // cfg:i
24 {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, 24 {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
25 {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, 25 {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"},
26 {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, 26 {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
27 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, 27 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
28 {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, 28 {0x04050000, nullptr, "GetLocalFriendCodeSeed"},
29 {0x04060000, SecureInfoGetRegion, "SecureInfoGetRegion"}, 29 {0x04060000, SecureInfoGetRegion, "SecureInfoGetRegion"},
30 {0x04070000, nullptr, "SecureInfoGetByte101"}, 30 {0x04070000, nullptr, "SecureInfoGetByte101"},
31 {0x04080042, nullptr, "SecureInfoGetSerialNo"}, 31 {0x04080042, nullptr, "SecureInfoGetSerialNo"},
32 {0x04090000, nullptr, "UpdateConfigBlk00040003"}, 32 {0x04090000, nullptr, "UpdateConfigBlk00040003"},
33 {0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, 33 {0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
34 {0x08020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, 34 {0x08020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"},
35 {0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, 35 {0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
36 {0x080400C2, nullptr, "CreateConfigInfoBlk"}, 36 {0x080400C2, nullptr, "CreateConfigInfoBlk"},
37 {0x08050000, nullptr, "DeleteConfigNANDSavefile"}, 37 {0x08050000, nullptr, "DeleteConfigNANDSavefile"},
38 {0x08060000, FormatConfig, "FormatConfig"}, 38 {0x08060000, FormatConfig, "FormatConfig"},
39 {0x08080000, nullptr, "UpdateConfigBlk1"}, 39 {0x08080000, nullptr, "UpdateConfigBlk1"},
40 {0x08090000, nullptr, "UpdateConfigBlk2"}, 40 {0x08090000, nullptr, "UpdateConfigBlk2"},
41 {0x080A0000, nullptr, "UpdateConfigBlk3"}, 41 {0x080A0000, nullptr, "UpdateConfigBlk3"},
42 {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"}, 42 {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"},
43 {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"}, 43 {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"},
44 {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"}, 44 {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"},
45 {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"}, 45 {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"},
46 {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"}, 46 {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"},
47 {0x08100000, nullptr, "GetLocalFriendCodeSeed"}, 47 {0x08100000, nullptr, "GetLocalFriendCodeSeed"},
48 {0x08110084, nullptr, "SetSecureInfo"}, 48 {0x08110084, nullptr, "SetSecureInfo"},
49 {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"}, 49 {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"},
50 {0x08130000, nullptr, "VerifySigSecureInfo"}, 50 {0x08130000, nullptr, "VerifySigSecureInfo"},
51 {0x08140042, nullptr, "SecureInfoGetData"}, 51 {0x08140042, nullptr, "SecureInfoGetData"},
52 {0x08150042, nullptr, "SecureInfoGetSignature"}, 52 {0x08150042, nullptr, "SecureInfoGetSignature"},
53 {0x08160000, SecureInfoGetRegion, "SecureInfoGetRegion"}, 53 {0x08160000, SecureInfoGetRegion, "SecureInfoGetRegion"},
54 {0x08170000, nullptr, "SecureInfoGetByte101"}, 54 {0x08170000, nullptr, "SecureInfoGetByte101"},
55 {0x08180042, nullptr, "SecureInfoGetSerialNo"}, 55 {0x08180042, nullptr, "SecureInfoGetSerialNo"},
56}; 56};
57 57
58CFG_I_Interface::CFG_I_Interface() { 58CFG_I_Interface::CFG_I_Interface() {
diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp
index 12b458783..eed26dec7 100644
--- a/src/core/hle/service/cfg/cfg_s.cpp
+++ b/src/core/hle/service/cfg/cfg_s.cpp
@@ -10,26 +10,26 @@ namespace CFG {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 // cfg common 12 // cfg common
13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, 13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, 14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, 15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, 16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"},
17 {0x00050000, GetSystemModel, "GetSystemModel"}, 17 {0x00050000, GetSystemModel, "GetSystemModel"},
18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, 18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, 19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
20 {0x00080080, nullptr, "GoThroughTable"}, 20 {0x00080080, nullptr, "GoThroughTable"},
21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, 21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, 22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
23 // cfg:s 23 // cfg:s
24 {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, 24 {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
25 {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, 25 {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"},
26 {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, 26 {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
27 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, 27 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
28 {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, 28 {0x04050000, nullptr, "GetLocalFriendCodeSeed"},
29 {0x04060000, nullptr, "SecureInfoGetRegion"}, 29 {0x04060000, nullptr, "SecureInfoGetRegion"},
30 {0x04070000, nullptr, "SecureInfoGetByte101"}, 30 {0x04070000, nullptr, "SecureInfoGetByte101"},
31 {0x04080042, nullptr, "SecureInfoGetSerialNo"}, 31 {0x04080042, nullptr, "SecureInfoGetSerialNo"},
32 {0x04090000, nullptr, "UpdateConfigBlk00040003"}, 32 {0x04090000, nullptr, "UpdateConfigBlk00040003"},
33}; 33};
34 34
35CFG_S_Interface::CFG_S_Interface() { 35CFG_S_Interface::CFG_S_Interface() {
diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp
index 606f7b2eb..f28217134 100644
--- a/src/core/hle/service/cfg/cfg_u.cpp
+++ b/src/core/hle/service/cfg/cfg_u.cpp
@@ -10,16 +10,16 @@ namespace CFG {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 // cfg common 12 // cfg common
13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, 13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, 14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, 15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, 16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"},
17 {0x00050000, GetSystemModel, "GetSystemModel"}, 17 {0x00050000, GetSystemModel, "GetSystemModel"},
18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, 18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, 19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
20 {0x00080080, nullptr, "GoThroughTable"}, 20 {0x00080080, nullptr, "GoThroughTable"},
21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, 21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, 22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
23}; 23};
24 24
25CFG_U_Interface::CFG_U_Interface() { 25CFG_U_Interface::CFG_U_Interface() {
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp
index 913c8dc09..e777ea9d6 100644
--- a/src/core/hle/service/csnd_snd.cpp
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -2,12 +2,12 @@
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 "core/hle/service/csnd_snd.h"
5#include <cstring> 6#include <cstring>
6#include "common/alignment.h" 7#include "common/alignment.h"
7#include "core/hle/hle.h" 8#include "core/hle/hle.h"
8#include "core/hle/kernel/mutex.h" 9#include "core/hle/kernel/mutex.h"
9#include "core/hle/kernel/shared_memory.h" 10#include "core/hle/kernel/shared_memory.h"
10#include "core/hle/service/csnd_snd.h"
11 11
12//////////////////////////////////////////////////////////////////////////////////////////////////// 12////////////////////////////////////////////////////////////////////////////////////////////////////
13// Namespace CSND_SND 13// Namespace CSND_SND
@@ -15,18 +15,18 @@
15namespace CSND_SND { 15namespace CSND_SND {
16 16
17const Interface::FunctionInfo FunctionTable[] = { 17const Interface::FunctionInfo FunctionTable[] = {
18 {0x00010140, Initialize, "Initialize"}, 18 {0x00010140, Initialize, "Initialize"},
19 {0x00020000, Shutdown, "Shutdown"}, 19 {0x00020000, Shutdown, "Shutdown"},
20 {0x00030040, ExecuteType0Commands, "ExecuteType0Commands"}, 20 {0x00030040, ExecuteType0Commands, "ExecuteType0Commands"},
21 {0x00040080, nullptr, "ExecuteType1Commands"}, 21 {0x00040080, nullptr, "ExecuteType1Commands"},
22 {0x00050000, AcquireSoundChannels, "AcquireSoundChannels"}, 22 {0x00050000, AcquireSoundChannels, "AcquireSoundChannels"},
23 {0x00060000, nullptr, "ReleaseSoundChannels"}, 23 {0x00060000, nullptr, "ReleaseSoundChannels"},
24 {0x00070000, nullptr, "AcquireCaptureDevice"}, 24 {0x00070000, nullptr, "AcquireCaptureDevice"},
25 {0x00080040, nullptr, "ReleaseCaptureDevice"}, 25 {0x00080040, nullptr, "ReleaseCaptureDevice"},
26 {0x00090082, nullptr, "FlushDataCache"}, 26 {0x00090082, nullptr, "FlushDataCache"},
27 {0x000A0082, nullptr, "StoreDataCache"}, 27 {0x000A0082, nullptr, "StoreDataCache"},
28 {0x000B0082, nullptr, "InvalidateDataCache"}, 28 {0x000B0082, nullptr, "InvalidateDataCache"},
29 {0x000C0000, nullptr, "Reset"}, 29 {0x000C0000, nullptr, "Reset"},
30}; 30};
31 31
32//////////////////////////////////////////////////////////////////////////////////////////////////// 32////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -44,9 +44,9 @@ void Initialize(Service::Interface* self) {
44 44
45 u32 size = Common::AlignUp(cmd_buff[1], Memory::PAGE_SIZE); 45 u32 size = Common::AlignUp(cmd_buff[1], Memory::PAGE_SIZE);
46 using Kernel::MemoryPermission; 46 using Kernel::MemoryPermission;
47 shared_memory = Kernel::SharedMemory::Create(nullptr, size, 47 shared_memory = Kernel::SharedMemory::Create(nullptr, size, MemoryPermission::ReadWrite,
48 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 48 MemoryPermission::ReadWrite, 0,
49 0, Kernel::MemoryRegion::BASE, "CSND:SharedMemory"); 49 Kernel::MemoryRegion::BASE, "CSND:SharedMemory");
50 50
51 mutex = Kernel::Mutex::Create(false); 51 mutex = Kernel::Mutex::Create(false);
52 52
@@ -58,7 +58,7 @@ void Initialize(Service::Interface* self) {
58 58
59void ExecuteType0Commands(Service::Interface* self) { 59void ExecuteType0Commands(Service::Interface* self) {
60 u32* const cmd_buff = Kernel::GetCommandBuffer(); 60 u32* const cmd_buff = Kernel::GetCommandBuffer();
61 u8* const ptr = shared_memory->GetPointer(cmd_buff[1]); 61 u8* const ptr = shared_memory->GetPointer(cmd_buff[1]);
62 62
63 if (shared_memory != nullptr && ptr != nullptr) { 63 if (shared_memory != nullptr && ptr != nullptr) {
64 Type0Command command; 64 Type0Command command;
diff --git a/src/core/hle/service/csnd_snd.h b/src/core/hle/service/csnd_snd.h
index e861f3327..a146d116b 100644
--- a/src/core/hle/service/csnd_snd.h
+++ b/src/core/hle/service/csnd_snd.h
@@ -25,7 +25,7 @@ struct Type0Command {
25 u32 command_id; 25 u32 command_id;
26 u32 finished; 26 u32 finished;
27 u32 flags; 27 u32 flags;
28 u8 parameters[20]; 28 u8 parameters[20];
29}; 29};
30 30
31void Initialize(Service::Interface* self); 31void Initialize(Service::Interface* self);
diff --git a/src/core/hle/service/dlp/dlp.cpp b/src/core/hle/service/dlp/dlp.cpp
index 7c8db794b..fd124e819 100644
--- a/src/core/hle/service/dlp/dlp.cpp
+++ b/src/core/hle/service/dlp/dlp.cpp
@@ -2,11 +2,11 @@
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 "core/hle/service/service.h"
6#include "core/hle/service/dlp/dlp.h" 5#include "core/hle/service/dlp/dlp.h"
7#include "core/hle/service/dlp/dlp_clnt.h" 6#include "core/hle/service/dlp/dlp_clnt.h"
8#include "core/hle/service/dlp/dlp_fkcl.h" 7#include "core/hle/service/dlp/dlp_fkcl.h"
9#include "core/hle/service/dlp/dlp_srvr.h" 8#include "core/hle/service/dlp/dlp_srvr.h"
9#include "core/hle/service/service.h"
10 10
11namespace Service { 11namespace Service {
12namespace DLP { 12namespace DLP {
diff --git a/src/core/hle/service/dlp/dlp_clnt.cpp b/src/core/hle/service/dlp/dlp_clnt.cpp
index 0b31d47df..56f934b3f 100644
--- a/src/core/hle/service/dlp/dlp_clnt.cpp
+++ b/src/core/hle/service/dlp/dlp_clnt.cpp
@@ -8,8 +8,7 @@ namespace Service {
8namespace DLP { 8namespace DLP {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x000100C3, nullptr, "Initialize"}, 11 {0x000100C3, nullptr, "Initialize"}, {0x00110000, nullptr, "GetWirelessRebootPassphrase"},
12 {0x00110000, nullptr, "GetWirelessRebootPassphrase"},
13}; 12};
14 13
15DLP_CLNT_Interface::DLP_CLNT_Interface() { 14DLP_CLNT_Interface::DLP_CLNT_Interface() {
diff --git a/src/core/hle/service/dlp/dlp_fkcl.cpp b/src/core/hle/service/dlp/dlp_fkcl.cpp
index a845260e5..29b9d52e0 100644
--- a/src/core/hle/service/dlp/dlp_fkcl.cpp
+++ b/src/core/hle/service/dlp/dlp_fkcl.cpp
@@ -8,8 +8,7 @@ namespace Service {
8namespace DLP { 8namespace DLP {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x00010083, nullptr, "Initialize"}, 11 {0x00010083, nullptr, "Initialize"}, {0x000F0000, nullptr, "GetWirelessRebootPassphrase"},
12 {0x000F0000, nullptr, "GetWirelessRebootPassphrase"},
13}; 12};
14 13
15DLP_FKCL_Interface::DLP_FKCL_Interface() { 14DLP_FKCL_Interface::DLP_FKCL_Interface() {
diff --git a/src/core/hle/service/dlp/dlp_srvr.cpp b/src/core/hle/service/dlp/dlp_srvr.cpp
index da9b30f56..113f6a79f 100644
--- a/src/core/hle/service/dlp/dlp_srvr.cpp
+++ b/src/core/hle/service/dlp/dlp_srvr.cpp
@@ -2,10 +2,10 @@
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 "core/hle/service/dlp/dlp_srvr.h"
5#include "common/common_types.h" 6#include "common/common_types.h"
6#include "common/logging/log.h" 7#include "common/logging/log.h"
7#include "core/hle/result.h" 8#include "core/hle/result.h"
8#include "core/hle/service/dlp/dlp_srvr.h"
9 9
10namespace Service { 10namespace Service {
11namespace DLP { 11namespace DLP {
@@ -20,10 +20,10 @@ static void unk_0x000E0040(Interface* self) {
20} 20}
21 21
22const Interface::FunctionInfo FunctionTable[] = { 22const Interface::FunctionInfo FunctionTable[] = {
23 {0x00010183, nullptr, "Initialize"}, 23 {0x00010183, nullptr, "Initialize"},
24 {0x00020000, nullptr, "Finalize"}, 24 {0x00020000, nullptr, "Finalize"},
25 {0x000800C0, nullptr, "SendWirelessRebootPassphrase"}, 25 {0x000800C0, nullptr, "SendWirelessRebootPassphrase"},
26 {0x000E0040, unk_0x000E0040, "unk_0x000E0040"}, 26 {0x000E0040, unk_0x000E0040, "unk_0x000E0040"},
27}; 27};
28 28
29DLP_SRVR_Interface::DLP_SRVR_Interface() { 29DLP_SRVR_Interface::DLP_SRVR_Interface() {
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index c8aadd9db..70e92c30c 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -23,9 +23,7 @@ namespace DSP_DSP {
23static Kernel::SharedPtr<Kernel::Event> semaphore_event; 23static Kernel::SharedPtr<Kernel::Event> semaphore_event;
24 24
25/// There are three types of interrupts 25/// There are three types of interrupts
26enum class InterruptType { 26enum class InterruptType { Zero, One, Pipe };
27 Zero, One, Pipe
28};
29constexpr size_t NUM_INTERRUPT_TYPE = 3; 27constexpr size_t NUM_INTERRUPT_TYPE = 3;
30 28
31class InterruptEvents final { 29class InterruptEvents final {
@@ -57,9 +55,8 @@ public:
57 // Actual service implementation only has 6 'slots' for interrupts. 55 // Actual service implementation only has 6 'slots' for interrupts.
58 constexpr size_t max_number_of_interrupt_events = 6; 56 constexpr size_t max_number_of_interrupt_events = 6;
59 57
60 size_t number = std::count_if(pipe.begin(), pipe.end(), [](const auto& evt) { 58 size_t number =
61 return evt != nullptr; 59 std::count_if(pipe.begin(), pipe.end(), [](const auto& evt) { return evt != nullptr; });
62 });
63 60
64 if (zero != nullptr) 61 if (zero != nullptr)
65 number++; 62 number++;
@@ -105,7 +102,8 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) {
105 cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0); 102 cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0);
106 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 103 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
107 104
108 // TODO(merry): There is a per-region offset missing in this calculation (that seems to be always zero). 105 // TODO(merry): There is a per-region offset missing in this calculation (that seems to be
106 // always zero).
109 cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000); 107 cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000);
110 108
111 LOG_DEBUG(Service_DSP, "addr=0x%08X", addr); 109 LOG_DEBUG(Service_DSP, "addr=0x%08X", addr);
@@ -126,15 +124,15 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) {
126static void LoadComponent(Service::Interface* self) { 124static void LoadComponent(Service::Interface* self) {
127 u32* cmd_buff = Kernel::GetCommandBuffer(); 125 u32* cmd_buff = Kernel::GetCommandBuffer();
128 126
129 u32 size = cmd_buff[1]; 127 u32 size = cmd_buff[1];
130 u32 prog_mask = cmd_buff[2]; 128 u32 prog_mask = cmd_buff[2];
131 u32 data_mask = cmd_buff[3]; 129 u32 data_mask = cmd_buff[3];
132 u32 desc = cmd_buff[4]; 130 u32 desc = cmd_buff[4];
133 u32 buffer = cmd_buff[5]; 131 u32 buffer = cmd_buff[5];
134 132
135 cmd_buff[0] = IPC::MakeHeader(0x11, 2, 2); 133 cmd_buff[0] = IPC::MakeHeader(0x11, 2, 2);
136 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 134 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
137 cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware 135 cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware
138 cmd_buff[3] = desc; 136 cmd_buff[3] = desc;
139 cmd_buff[4] = buffer; 137 cmd_buff[4] = buffer;
140 138
@@ -145,12 +143,15 @@ static void LoadComponent(Service::Interface* self) {
145 std::vector<u8> component_data(size); 143 std::vector<u8> component_data(size);
146 Memory::ReadBlock(buffer, component_data.data(), component_data.size()); 144 Memory::ReadBlock(buffer, component_data.data(), component_data.size());
147 145
148 LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(component_data.data(), component_data.size())); 146 LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64,
147 Common::ComputeHash64(component_data.data(), component_data.size()));
149 // Some versions of the firmware have the location of DSP structures listed here. 148 // Some versions of the firmware have the location of DSP structures listed here.
150 ASSERT(size > 0x37C); 149 ASSERT(size > 0x37C);
151 LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(component_data.data() + 0x340, 60)); 150 LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64,
151 Common::ComputeHash64(component_data.data() + 0x340, 60));
152 152
153 LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X", 153 LOG_WARNING(Service_DSP,
154 "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X",
154 size, prog_mask, data_mask, buffer); 155 size, prog_mask, data_mask, buffer);
155} 156}
156 157
@@ -187,13 +188,14 @@ static void GetSemaphoreEventHandle(Service::Interface* self) {
187static void FlushDataCache(Service::Interface* self) { 188static void FlushDataCache(Service::Interface* self) {
188 u32* cmd_buff = Kernel::GetCommandBuffer(); 189 u32* cmd_buff = Kernel::GetCommandBuffer();
189 u32 address = cmd_buff[1]; 190 u32 address = cmd_buff[1];
190 u32 size = cmd_buff[2]; 191 u32 size = cmd_buff[2];
191 u32 process = cmd_buff[4]; 192 u32 process = cmd_buff[4];
192 193
193 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); 194 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0);
194 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 195 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
195 196
196 LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size, process); 197 LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size,
198 process);
197} 199}
198 200
199/** 201/**
@@ -224,23 +226,29 @@ static void RegisterInterruptEvents(Service::Interface* self) {
224 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]); 226 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
225 227
226 if (!evt) { 228 if (!evt) {
227 LOG_INFO(Service_DSP, "Invalid event handle! type=%u, pipe=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); 229 LOG_INFO(Service_DSP, "Invalid event handle! type=%u, pipe=%u, event_handle=0x%08X",
230 type_index, pipe_index, event_handle);
228 ASSERT(false); // TODO: This should really be handled at an IPC translation layer. 231 ASSERT(false); // TODO: This should really be handled at an IPC translation layer.
229 } 232 }
230 233
231 if (interrupt_events.HasTooManyEventsRegistered()) { 234 if (interrupt_events.HasTooManyEventsRegistered()) {
232 LOG_INFO(Service_DSP, "Ran out of space to register interrupts (Attempted to register type=%u, pipe=%u, event_handle=0x%08X)", 235 LOG_INFO(Service_DSP, "Ran out of space to register interrupts (Attempted to register "
236 "type=%u, pipe=%u, event_handle=0x%08X)",
233 type_index, pipe_index, event_handle); 237 type_index, pipe_index, event_handle);
234 cmd_buff[1] = ResultCode(ErrorDescription::InvalidResultValue, ErrorModule::DSP, ErrorSummary::OutOfResource, ErrorLevel::Status).raw; 238 cmd_buff[1] = ResultCode(ErrorDescription::InvalidResultValue, ErrorModule::DSP,
239 ErrorSummary::OutOfResource, ErrorLevel::Status)
240 .raw;
235 return; 241 return;
236 } 242 }
237 243
238 interrupt_events.Get(type, pipe) = evt; 244 interrupt_events.Get(type, pipe) = evt;
239 LOG_INFO(Service_DSP, "Registered type=%u, pipe=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); 245 LOG_INFO(Service_DSP, "Registered type=%u, pipe=%u, event_handle=0x%08X", type_index,
246 pipe_index, event_handle);
240 cmd_buff[1] = RESULT_SUCCESS.raw; 247 cmd_buff[1] = RESULT_SUCCESS.raw;
241 } else { 248 } else {
242 interrupt_events.Get(type, pipe) = nullptr; 249 interrupt_events.Get(type, pipe) = nullptr;
243 LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); 250 LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X",
251 type_index, pipe_index, event_handle);
244 cmd_buff[1] = RESULT_SUCCESS.raw; 252 cmd_buff[1] = RESULT_SUCCESS.raw;
245 } 253 }
246} 254}
@@ -282,13 +290,18 @@ static void WriteProcessPipe(Service::Interface* self) {
282 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); 290 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index);
283 291
284 if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) { 292 if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) {
285 LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). pipe=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], pipe_index, size, buffer); 293 LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). pipe=%u, "
294 "size=0x%X, buffer=0x%08X",
295 cmd_buff[3], pipe_index, size, buffer);
286 cmd_buff[0] = IPC::MakeHeader(0, 1, 0); 296 cmd_buff[0] = IPC::MakeHeader(0, 1, 0);
287 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; 297 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
298 ErrorSummary::WrongArgument, ErrorLevel::Permanent)
299 .raw;
288 return; 300 return;
289 } 301 }
290 302
291 ASSERT_MSG(Memory::IsValidVirtualAddress(buffer), "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); 303 ASSERT_MSG(Memory::IsValidVirtualAddress(buffer),
304 "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
292 305
293 std::vector<u8> message(size); 306 std::vector<u8> message(size);
294 for (u32 i = 0; i < size; i++) { 307 for (u32 i = 0; i < size; i++) {
@@ -327,7 +340,9 @@ static void ReadPipeIfPossible(Service::Interface* self) {
327 340
328 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); 341 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index);
329 342
330 ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); 343 ASSERT_MSG(Memory::IsValidVirtualAddress(addr),
344 "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown,
345 size, addr);
331 346
332 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); 347 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2);
333 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 348 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
@@ -343,7 +358,9 @@ static void ReadPipeIfPossible(Service::Interface* self) {
343 cmd_buff[3] = IPC::StaticBufferDesc(size, 0); 358 cmd_buff[3] = IPC::StaticBufferDesc(size, 0);
344 cmd_buff[4] = addr; 359 cmd_buff[4] = addr;
345 360
346 LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, size, addr, cmd_buff[2]); 361 LOG_DEBUG(Service_DSP,
362 "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X",
363 pipe_index, unknown, size, addr, cmd_buff[2]);
347} 364}
348 365
349/** 366/**
@@ -367,7 +384,9 @@ static void ReadPipe(Service::Interface* self) {
367 384
368 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); 385 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index);
369 386
370 ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); 387 ASSERT_MSG(Memory::IsValidVirtualAddress(addr),
388 "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown,
389 size, addr);
371 390
372 if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { 391 if (DSP::HLE::GetPipeReadableSize(pipe) >= size) {
373 std::vector<u8> response = DSP::HLE::PipeRead(pipe, size); 392 std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
@@ -384,7 +403,9 @@ static void ReadPipe(Service::Interface* self) {
384 UNREACHABLE(); 403 UNREACHABLE();
385 } 404 }
386 405
387 LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, size, addr, cmd_buff[2]); 406 LOG_DEBUG(Service_DSP,
407 "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X",
408 pipe_index, unknown, size, addr, cmd_buff[2]);
388} 409}
389 410
390/** 411/**
@@ -408,7 +429,8 @@ static void GetPipeReadableSize(Service::Interface* self) {
408 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 429 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
409 cmd_buff[2] = static_cast<u32>(DSP::HLE::GetPipeReadableSize(pipe)); 430 cmd_buff[2] = static_cast<u32>(DSP::HLE::GetPipeReadableSize(pipe));
410 431
411 LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, cmd_buff[2]); 432 LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe_index,
433 unknown, cmd_buff[2]);
412} 434}
413 435
414/** 436/**
@@ -443,7 +465,7 @@ static void GetHeadphoneStatus(Service::Interface* self) {
443 465
444 cmd_buff[0] = IPC::MakeHeader(0x1F, 2, 0); 466 cmd_buff[0] = IPC::MakeHeader(0x1F, 2, 0);
445 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 467 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
446 cmd_buff[2] = 0; // Not using headphones 468 cmd_buff[2] = 0; // Not using headphones
447 469
448 LOG_DEBUG(Service_DSP, "called"); 470 LOG_DEBUG(Service_DSP, "called");
449} 471}
@@ -466,7 +488,8 @@ static void RecvData(Service::Interface* self) {
466 488
467 ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number); 489 ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number);
468 490
469 // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown or slept. 491 // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown
492 // or slept.
470 493
471 cmd_buff[0] = IPC::MakeHeader(0x1, 2, 0); 494 cmd_buff[0] = IPC::MakeHeader(0x1, 2, 0);
472 cmd_buff[1] = RESULT_SUCCESS.raw; 495 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -512,39 +535,39 @@ static void RecvDataIsReady(Service::Interface* self) {
512} 535}
513 536
514const Interface::FunctionInfo FunctionTable[] = { 537const Interface::FunctionInfo FunctionTable[] = {
515 {0x00010040, RecvData, "RecvData"}, 538 {0x00010040, RecvData, "RecvData"},
516 {0x00020040, RecvDataIsReady, "RecvDataIsReady"}, 539 {0x00020040, RecvDataIsReady, "RecvDataIsReady"},
517 {0x00030080, nullptr, "SendData"}, 540 {0x00030080, nullptr, "SendData"},
518 {0x00040040, nullptr, "SendDataIsEmpty"}, 541 {0x00040040, nullptr, "SendDataIsEmpty"},
519 {0x000500C2, nullptr, "SendFifoEx"}, 542 {0x000500C2, nullptr, "SendFifoEx"},
520 {0x000600C0, nullptr, "RecvFifoEx"}, 543 {0x000600C0, nullptr, "RecvFifoEx"},
521 {0x00070040, SetSemaphore, "SetSemaphore"}, 544 {0x00070040, SetSemaphore, "SetSemaphore"},
522 {0x00080000, nullptr, "GetSemaphore"}, 545 {0x00080000, nullptr, "GetSemaphore"},
523 {0x00090040, nullptr, "ClearSemaphore"}, 546 {0x00090040, nullptr, "ClearSemaphore"},
524 {0x000A0040, nullptr, "MaskSemaphore"}, 547 {0x000A0040, nullptr, "MaskSemaphore"},
525 {0x000B0000, nullptr, "CheckSemaphoreRequest"}, 548 {0x000B0000, nullptr, "CheckSemaphoreRequest"},
526 {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"}, 549 {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"},
527 {0x000D0082, WriteProcessPipe, "WriteProcessPipe"}, 550 {0x000D0082, WriteProcessPipe, "WriteProcessPipe"},
528 {0x000E00C0, ReadPipe, "ReadPipe"}, 551 {0x000E00C0, ReadPipe, "ReadPipe"},
529 {0x000F0080, GetPipeReadableSize, "GetPipeReadableSize"}, 552 {0x000F0080, GetPipeReadableSize, "GetPipeReadableSize"},
530 {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"}, 553 {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"},
531 {0x001100C2, LoadComponent, "LoadComponent"}, 554 {0x001100C2, LoadComponent, "LoadComponent"},
532 {0x00120000, nullptr, "UnloadComponent"}, 555 {0x00120000, nullptr, "UnloadComponent"},
533 {0x00130082, FlushDataCache, "FlushDataCache"}, 556 {0x00130082, FlushDataCache, "FlushDataCache"},
534 {0x00140082, nullptr, "InvalidateDCache"}, 557 {0x00140082, nullptr, "InvalidateDCache"},
535 {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"}, 558 {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"},
536 {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"}, 559 {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"},
537 {0x00170040, SetSemaphoreMask, "SetSemaphoreMask"}, 560 {0x00170040, SetSemaphoreMask, "SetSemaphoreMask"},
538 {0x00180040, nullptr, "GetPhysicalAddress"}, 561 {0x00180040, nullptr, "GetPhysicalAddress"},
539 {0x00190040, nullptr, "GetVirtualAddress"}, 562 {0x00190040, nullptr, "GetVirtualAddress"},
540 {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"}, 563 {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"},
541 {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"}, 564 {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"},
542 {0x001C0082, nullptr, "SetIirFilterEQ"}, 565 {0x001C0082, nullptr, "SetIirFilterEQ"},
543 {0x001D00C0, nullptr, "ReadMultiEx_SPI2"}, 566 {0x001D00C0, nullptr, "ReadMultiEx_SPI2"},
544 {0x001E00C2, nullptr, "WriteMultiEx_SPI2"}, 567 {0x001E00C2, nullptr, "WriteMultiEx_SPI2"},
545 {0x001F0000, GetHeadphoneStatus, "GetHeadphoneStatus"}, 568 {0x001F0000, GetHeadphoneStatus, "GetHeadphoneStatus"},
546 {0x00200040, nullptr, "ForceHeadphoneOut"}, 569 {0x00200040, nullptr, "ForceHeadphoneOut"},
547 {0x00210000, nullptr, "GetIsDspOccupied"}, 570 {0x00210000, nullptr, "GetIsDspOccupied"},
548}; 571};
549 572
550//////////////////////////////////////////////////////////////////////////////////////////////////// 573////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 5f9cf6e94..2cd8269de 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -35,70 +35,70 @@ union ErrInfo {
35 u8 specifier; 35 u8 specifier;
36 36
37 struct { 37 struct {
38 u8 specifier; // 0x0 38 u8 specifier; // 0x0
39 u8 rev_high; // 0x1 39 u8 rev_high; // 0x1
40 u16 rev_low; // 0x2 40 u16 rev_low; // 0x2
41 RSL result_code; // 0x4 41 RSL result_code; // 0x4
42 u32 address; // 0x8 42 u32 address; // 0x8
43 INSERT_PADDING_BYTES(4); // 0xC 43 INSERT_PADDING_BYTES(4); // 0xC
44 u32 pid_low; // 0x10 44 u32 pid_low; // 0x10
45 u32 pid_high; // 0x14 45 u32 pid_high; // 0x14
46 u32 aid_low; // 0x18 46 u32 aid_low; // 0x18
47 u32 aid_high; // 0x1C 47 u32 aid_high; // 0x1C
48 } errtype1; 48 } errtype1;
49 49
50 struct { 50 struct {
51 u8 specifier; // 0x0 51 u8 specifier; // 0x0
52 u8 rev_high; // 0x1 52 u8 rev_high; // 0x1
53 u16 rev_low; // 0x2 53 u16 rev_low; // 0x2
54 INSERT_PADDING_BYTES(0xC); // 0x4 54 INSERT_PADDING_BYTES(0xC); // 0x4
55 u32 pid_low; // 0x10 55 u32 pid_low; // 0x10
56 u32 pid_high; // 0x14 56 u32 pid_high; // 0x14
57 u32 aid_low; // 0x18 57 u32 aid_low; // 0x18
58 u32 aid_high; // 0x1C 58 u32 aid_high; // 0x1C
59 u8 error_type; // 0x20 59 u8 error_type; // 0x20
60 INSERT_PADDING_BYTES(3); // 0x21 60 INSERT_PADDING_BYTES(3); // 0x21
61 u32 fault_status_reg; // 0x24 61 u32 fault_status_reg; // 0x24
62 u32 fault_addr; // 0x28 62 u32 fault_addr; // 0x28
63 u32 fpexc; // 0x2C 63 u32 fpexc; // 0x2C
64 u32 finst; // 0x30 64 u32 finst; // 0x30
65 u32 finst2; // 0x34 65 u32 finst2; // 0x34
66 INSERT_PADDING_BYTES(0x34); // 0x38 66 INSERT_PADDING_BYTES(0x34); // 0x38
67 u32 sp; // 0x6C 67 u32 sp; // 0x6C
68 u32 pc; // 0x70 68 u32 pc; // 0x70
69 u32 lr; // 0x74 69 u32 lr; // 0x74
70 u32 cpsr; // 0x78 70 u32 cpsr; // 0x78
71 } errtype3; 71 } errtype3;
72 72
73 struct { 73 struct {
74 u8 specifier; // 0x0 74 u8 specifier; // 0x0
75 u8 rev_high; // 0x1 75 u8 rev_high; // 0x1
76 u16 rev_low; // 0x2 76 u16 rev_low; // 0x2
77 RSL result_code; // 0x4 77 RSL result_code; // 0x4
78 INSERT_PADDING_BYTES(8); // 0x8 78 INSERT_PADDING_BYTES(8); // 0x8
79 u32 pid_low; // 0x10 79 u32 pid_low; // 0x10
80 u32 pid_high; // 0x14 80 u32 pid_high; // 0x14
81 u32 aid_low; // 0x18 81 u32 aid_low; // 0x18
82 u32 aid_high; // 0x1C 82 u32 aid_high; // 0x1C
83 char debug_string1[0x2E]; // 0x20 83 char debug_string1[0x2E]; // 0x20
84 char debug_string2[0x2E]; // 0x4E 84 char debug_string2[0x2E]; // 0x4E
85 } errtype4; 85 } errtype4;
86}; 86};
87 87
88enum { 88enum { PrefetchAbort = 0, DataAbort = 1, UndefInstr = 2, VectorFP = 3 };
89 PrefetchAbort = 0,
90 DataAbort = 1,
91 UndefInstr = 2,
92 VectorFP = 3
93};
94 89
95static std::string GetErrInfo3Type(u8 type_code) { 90static std::string GetErrInfo3Type(u8 type_code) {
96 switch (type_code) { 91 switch (type_code) {
97 case PrefetchAbort: return "Prefetch Abort"; 92 case PrefetchAbort:
98 case DataAbort: return "Data Abort"; 93 return "Prefetch Abort";
99 case UndefInstr: return "Undefined Instruction"; 94 case DataAbort:
100 case VectorFP: return "Vector Floating Point"; 95 return "Data Abort";
101 default: return "unknown"; 96 case UndefInstr:
97 return "Undefined Instruction";
98 case VectorFP:
99 return "Vector Floating Point";
100 default:
101 return "unknown";
102 } 102 }
103} 103}
104 104
@@ -110,8 +110,7 @@ static void ThrowFatalError(Service::Interface* self) {
110 110
111 switch (errinfo->specifier) { 111 switch (errinfo->specifier) {
112 case ErrSpecifier0: 112 case ErrSpecifier0:
113 case ErrSpecifier1: 113 case ErrSpecifier1: {
114 {
115 const auto& errtype = errinfo->errtype1; 114 const auto& errtype = errinfo->errtype1;
116 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); 115 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
117 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); 116 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
@@ -119,15 +118,14 @@ static void ThrowFatalError(Service::Interface* self) {
119 LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address); 118 LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address);
120 119
121 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); 120 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
122 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value()); 121 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
123 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value()); 122 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
124 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value()); 123 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
125 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value()); 124 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
126 break; 125 break;
127 } 126 }
128 127
129 case ErrSpecifier3: 128 case ErrSpecifier3: {
130 {
131 const auto& errtype = errinfo->errtype3; 129 const auto& errtype = errinfo->errtype3;
132 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); 130 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
133 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); 131 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
@@ -154,18 +152,17 @@ static void ThrowFatalError(Service::Interface* self) {
154 break; 152 break;
155 } 153 }
156 154
157 case ErrSpecifier4: 155 case ErrSpecifier4: {
158 {
159 const auto& errtype = errinfo->errtype4; 156 const auto& errtype = errinfo->errtype4;
160 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); 157 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
161 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); 158 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
162 LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high); 159 LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
163 160
164 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); 161 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
165 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value()); 162 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
166 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value()); 163 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
167 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value()); 164 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
168 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value()); 165 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
169 166
170 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1); 167 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1);
171 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2); 168 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2);
@@ -176,9 +173,7 @@ static void ThrowFatalError(Service::Interface* self) {
176 cmd_buff[1] = 0; // No error 173 cmd_buff[1] = 0; // No error
177} 174}
178 175
179const Interface::FunctionInfo FunctionTable[] = { 176const Interface::FunctionInfo FunctionTable[] = {{0x00010800, ThrowFatalError, "ThrowFatalError"}};
180 {0x00010800, ThrowFatalError, "ThrowFatalError"}
181};
182 177
183//////////////////////////////////////////////////////////////////////////////////////////////////// 178////////////////////////////////////////////////////////////////////////////////////////////////////
184// Interface class 179// Interface class
diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp
index 29d144365..1e9fe178f 100644
--- a/src/core/hle/service/frd/frd.cpp
+++ b/src/core/hle/service/frd/frd.cpp
@@ -4,10 +4,10 @@
4 4
5#include "common/string_util.h" 5#include "common/string_util.h"
6 6
7#include "core/hle/service/service.h"
8#include "core/hle/service/frd/frd.h" 7#include "core/hle/service/frd/frd.h"
9#include "core/hle/service/frd/frd_a.h" 8#include "core/hle/service/frd/frd_a.h"
10#include "core/hle/service/frd/frd_u.h" 9#include "core/hle/service/frd/frd_u.h"
10#include "core/hle/service/service.h"
11 11
12namespace Service { 12namespace Service {
13namespace FRD { 13namespace FRD {
@@ -43,7 +43,7 @@ void GetFriendKeyList(Service::Interface* self) {
43 } 43 }
44 44
45 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 45 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
46 cmd_buff[2] = 0; // 0 friends 46 cmd_buff[2] = 0; // 0 friends
47 LOG_WARNING(Service_FRD, "(STUBBED) called, unknown=%d, frd_count=%d, frd_key_addr=0x%08X", 47 LOG_WARNING(Service_FRD, "(STUBBED) called, unknown=%d, frd_count=%d, frd_key_addr=0x%08X",
48 unknown, frd_count, frd_key_addr); 48 unknown, frd_count, frd_key_addr);
49} 49}
@@ -61,25 +61,27 @@ void GetFriendProfile(Service::Interface* self) {
61 } 61 }
62 62
63 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 63 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
64 LOG_WARNING(Service_FRD, "(STUBBED) called, count=%d, frd_key_addr=0x%08X, profiles_addr=0x%08X", 64 LOG_WARNING(Service_FRD,
65 count, frd_key_addr, profiles_addr); 65 "(STUBBED) called, count=%d, frd_key_addr=0x%08X, profiles_addr=0x%08X", count,
66 frd_key_addr, profiles_addr);
66} 67}
67 68
68void GetFriendAttributeFlags(Service::Interface* self) { 69void GetFriendAttributeFlags(Service::Interface* self) {
69 u32* cmd_buff = Kernel::GetCommandBuffer(); 70 u32* cmd_buff = Kernel::GetCommandBuffer();
70 71
71 u32 count = cmd_buff[1]; 72 u32 count = cmd_buff[1];
72 u32 frd_key_addr = cmd_buff[3]; 73 u32 frd_key_addr = cmd_buff[3];
73 u32 attr_flags_addr = cmd_buff[65]; 74 u32 attr_flags_addr = cmd_buff[65];
74 75
75 for (u32 i = 0; i < count; ++i) { 76 for (u32 i = 0; i < count; ++i) {
76 //TODO:(mailwl) figure out AttributeFlag size and zero all buffer. Assume 1 byte 77 // TODO:(mailwl) figure out AttributeFlag size and zero all buffer. Assume 1 byte
77 Memory::Write8(attr_flags_addr + i, 0); 78 Memory::Write8(attr_flags_addr + i, 0);
78 } 79 }
79 80
80 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 81 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
81 LOG_WARNING(Service_FRD, "(STUBBED) called, count=%d, frd_key_addr=0x%08X, attr_flags_addr=0x%08X", 82 LOG_WARNING(Service_FRD,
82 count, frd_key_addr, attr_flags_addr); 83 "(STUBBED) called, count=%d, frd_key_addr=0x%08X, attr_flags_addr=0x%08X", count,
84 frd_key_addr, attr_flags_addr);
83} 85}
84 86
85void GetMyFriendKey(Service::Interface* self) { 87void GetMyFriendKey(Service::Interface* self) {
diff --git a/src/core/hle/service/frd/frd_a.cpp b/src/core/hle/service/frd/frd_a.cpp
index 818d610f3..cfc37210b 100644
--- a/src/core/hle/service/frd/frd_a.cpp
+++ b/src/core/hle/service/frd/frd_a.cpp
@@ -11,7 +11,7 @@ namespace FRD {
11// const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13FRD_A_Interface::FRD_A_Interface() { 13FRD_A_Interface::FRD_A_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace FRD 17} // namespace FRD
diff --git a/src/core/hle/service/frd/frd_u.cpp b/src/core/hle/service/frd/frd_u.cpp
index db8666416..bd1c9c16b 100644
--- a/src/core/hle/service/frd/frd_u.cpp
+++ b/src/core/hle/service/frd/frd_u.cpp
@@ -9,59 +9,59 @@ namespace Service {
9namespace FRD { 9namespace FRD {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010000, nullptr, "HasLoggedIn"}, 12 {0x00010000, nullptr, "HasLoggedIn"},
13 {0x00020000, nullptr, "IsOnline"}, 13 {0x00020000, nullptr, "IsOnline"},
14 {0x00030000, nullptr, "Login"}, 14 {0x00030000, nullptr, "Login"},
15 {0x00040000, nullptr, "Logout"}, 15 {0x00040000, nullptr, "Logout"},
16 {0x00050000, GetMyFriendKey, "GetMyFriendKey"}, 16 {0x00050000, GetMyFriendKey, "GetMyFriendKey"},
17 {0x00060000, nullptr, "GetMyPreference"}, 17 {0x00060000, nullptr, "GetMyPreference"},
18 {0x00070000, nullptr, "GetMyProfile"}, 18 {0x00070000, nullptr, "GetMyProfile"},
19 {0x00080000, GetMyPresence, "GetMyPresence"}, 19 {0x00080000, GetMyPresence, "GetMyPresence"},
20 {0x00090000, GetMyScreenName, "GetMyScreenName"}, 20 {0x00090000, GetMyScreenName, "GetMyScreenName"},
21 {0x000A0000, nullptr, "GetMyMii"}, 21 {0x000A0000, nullptr, "GetMyMii"},
22 {0x000B0000, nullptr, "GetMyLocalAccountId"}, 22 {0x000B0000, nullptr, "GetMyLocalAccountId"},
23 {0x000C0000, nullptr, "GetMyPlayingGame"}, 23 {0x000C0000, nullptr, "GetMyPlayingGame"},
24 {0x000D0000, nullptr, "GetMyFavoriteGame"}, 24 {0x000D0000, nullptr, "GetMyFavoriteGame"},
25 {0x000E0000, nullptr, "GetMyNcPrincipalId"}, 25 {0x000E0000, nullptr, "GetMyNcPrincipalId"},
26 {0x000F0000, nullptr, "GetMyComment"}, 26 {0x000F0000, nullptr, "GetMyComment"},
27 {0x00100040, nullptr, "GetMyPassword"}, 27 {0x00100040, nullptr, "GetMyPassword"},
28 {0x00110080, GetFriendKeyList, "GetFriendKeyList"}, 28 {0x00110080, GetFriendKeyList, "GetFriendKeyList"},
29 {0x00120042, nullptr, "GetFriendPresence"}, 29 {0x00120042, nullptr, "GetFriendPresence"},
30 {0x00130142, nullptr, "GetFriendScreenName"}, 30 {0x00130142, nullptr, "GetFriendScreenName"},
31 {0x00140044, nullptr, "GetFriendMii"}, 31 {0x00140044, nullptr, "GetFriendMii"},
32 {0x00150042, GetFriendProfile, "GetFriendProfile"}, 32 {0x00150042, GetFriendProfile, "GetFriendProfile"},
33 {0x00160042, nullptr, "GetFriendRelationship"}, 33 {0x00160042, nullptr, "GetFriendRelationship"},
34 {0x00170042, GetFriendAttributeFlags, "GetFriendAttributeFlags"}, 34 {0x00170042, GetFriendAttributeFlags, "GetFriendAttributeFlags"},
35 {0x00180044, nullptr, "GetFriendPlayingGame"}, 35 {0x00180044, nullptr, "GetFriendPlayingGame"},
36 {0x00190042, nullptr, "GetFriendFavoriteGame"}, 36 {0x00190042, nullptr, "GetFriendFavoriteGame"},
37 {0x001A00C4, nullptr, "GetFriendInfo"}, 37 {0x001A00C4, nullptr, "GetFriendInfo"},
38 {0x001B0080, nullptr, "IsIncludedInFriendList"}, 38 {0x001B0080, nullptr, "IsIncludedInFriendList"},
39 {0x001C0042, nullptr, "UnscrambleLocalFriendCode"}, 39 {0x001C0042, nullptr, "UnscrambleLocalFriendCode"},
40 {0x001D0002, nullptr, "UpdateGameModeDescription"}, 40 {0x001D0002, nullptr, "UpdateGameModeDescription"},
41 {0x001E02C2, nullptr, "UpdateGameMode"}, 41 {0x001E02C2, nullptr, "UpdateGameMode"},
42 {0x001F0042, nullptr, "SendInvitation"}, 42 {0x001F0042, nullptr, "SendInvitation"},
43 {0x00200002, nullptr, "AttachToEventNotification"}, 43 {0x00200002, nullptr, "AttachToEventNotification"},
44 {0x00210040, nullptr, "SetNotificationMask"}, 44 {0x00210040, nullptr, "SetNotificationMask"},
45 {0x00220040, nullptr, "GetEventNotification"}, 45 {0x00220040, nullptr, "GetEventNotification"},
46 {0x00230000, nullptr, "GetLastResponseResult"}, 46 {0x00230000, nullptr, "GetLastResponseResult"},
47 {0x00240040, nullptr, "PrincipalIdToFriendCode"}, 47 {0x00240040, nullptr, "PrincipalIdToFriendCode"},
48 {0x00250080, nullptr, "FriendCodeToPrincipalId"}, 48 {0x00250080, nullptr, "FriendCodeToPrincipalId"},
49 {0x00260080, nullptr, "IsValidFriendCode"}, 49 {0x00260080, nullptr, "IsValidFriendCode"},
50 {0x00270040, nullptr, "ResultToErrorCode"}, 50 {0x00270040, nullptr, "ResultToErrorCode"},
51 {0x00280244, nullptr, "RequestGameAuthentication"}, 51 {0x00280244, nullptr, "RequestGameAuthentication"},
52 {0x00290000, nullptr, "GetGameAuthenticationData"}, 52 {0x00290000, nullptr, "GetGameAuthenticationData"},
53 {0x002A0204, nullptr, "RequestServiceLocator"}, 53 {0x002A0204, nullptr, "RequestServiceLocator"},
54 {0x002B0000, nullptr, "GetServiceLocatorData"}, 54 {0x002B0000, nullptr, "GetServiceLocatorData"},
55 {0x002C0002, nullptr, "DetectNatProperties"}, 55 {0x002C0002, nullptr, "DetectNatProperties"},
56 {0x002D0000, nullptr, "GetNatProperties"}, 56 {0x002D0000, nullptr, "GetNatProperties"},
57 {0x002E0000, nullptr, "GetServerTimeInterval"}, 57 {0x002E0000, nullptr, "GetServerTimeInterval"},
58 {0x002F0040, nullptr, "AllowHalfAwake"}, 58 {0x002F0040, nullptr, "AllowHalfAwake"},
59 {0x00300000, nullptr, "GetServerTypes"}, 59 {0x00300000, nullptr, "GetServerTypes"},
60 {0x00310082, nullptr, "GetFriendComment"}, 60 {0x00310082, nullptr, "GetFriendComment"},
61 {0x00320042, nullptr, "SetClientSdkVersion"}, 61 {0x00320042, nullptr, "SetClientSdkVersion"},
62 {0x00330000, nullptr, "GetMyApproachContext"}, 62 {0x00330000, nullptr, "GetMyApproachContext"},
63 {0x00340046, nullptr, "AddFriendWithApproach"}, 63 {0x00340046, nullptr, "AddFriendWithApproach"},
64 {0x00350082, nullptr, "DecryptApproachContext"}, 64 {0x00350082, nullptr, "DecryptApproachContext"},
65}; 65};
66 66
67FRD_U_Interface::FRD_U_Interface() { 67FRD_U_Interface::FRD_U_Interface() {
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 4c7aaa7f2..1b851eade 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -3,9 +3,9 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstddef> 5#include <cstddef>
6#include <memory>
6#include <system_error> 7#include <system_error>
7#include <type_traits> 8#include <type_traits>
8#include <memory>
9#include <unordered_map> 9#include <unordered_map>
10#include <utility> 10#include <utility>
11 11
@@ -25,25 +25,25 @@
25#include "core/file_sys/directory_backend.h" 25#include "core/file_sys/directory_backend.h"
26#include "core/file_sys/file_backend.h" 26#include "core/file_sys/file_backend.h"
27#include "core/hle/hle.h" 27#include "core/hle/hle.h"
28#include "core/hle/service/service.h" 28#include "core/hle/result.h"
29#include "core/hle/service/fs/archive.h" 29#include "core/hle/service/fs/archive.h"
30#include "core/hle/service/fs/fs_user.h" 30#include "core/hle/service/fs/fs_user.h"
31#include "core/hle/result.h" 31#include "core/hle/service/service.h"
32#include "core/memory.h" 32#include "core/memory.h"
33 33
34// Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. 34// Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map.
35// Workaroung for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970 35// Workaroung for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970
36namespace std { 36namespace std {
37 template <> 37template <>
38 struct hash<Service::FS::ArchiveIdCode> { 38struct hash<Service::FS::ArchiveIdCode> {
39 typedef Service::FS::ArchiveIdCode argument_type; 39 typedef Service::FS::ArchiveIdCode argument_type;
40 typedef std::size_t result_type; 40 typedef std::size_t result_type;
41 41
42 result_type operator()(const argument_type& id_code) const { 42 result_type operator()(const argument_type& id_code) const {
43 typedef std::underlying_type<argument_type>::type Type; 43 typedef std::underlying_type<argument_type>::type Type;
44 return std::hash<Type>()(static_cast<Type>(id_code)); 44 return std::hash<Type>()(static_cast<Type>(id_code));
45 } 45 }
46 }; 46};
47} 47}
48 48
49/// TODO(Subv): Confirm length of these strings 49/// TODO(Subv): Confirm length of these strings
@@ -56,197 +56,193 @@ namespace FS {
56// TODO: Verify code 56// TODO: Verify code
57/// Returned when a function is passed an invalid handle. 57/// Returned when a function is passed an invalid handle.
58const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS, 58const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS,
59 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 59 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
60 60
61/// Returned when a function is passed an invalid archive handle. 61/// Returned when a function is passed an invalid archive handle.
62const ResultCode ERR_INVALID_ARCHIVE_HANDLE(ErrorDescription::FS_ArchiveNotMounted, ErrorModule::FS, 62const ResultCode ERR_INVALID_ARCHIVE_HANDLE(ErrorDescription::FS_ArchiveNotMounted, ErrorModule::FS,
63 ErrorSummary::NotFound, ErrorLevel::Status); // 0xC8804465 63 ErrorSummary::NotFound,
64 ErrorLevel::Status); // 0xC8804465
64 65
65// Command to access archive file 66// Command to access archive file
66enum class FileCommand : u32 { 67enum class FileCommand : u32 {
67 Dummy1 = 0x000100C6, 68 Dummy1 = 0x000100C6,
68 Control = 0x040100C4, 69 Control = 0x040100C4,
69 OpenSubFile = 0x08010100, 70 OpenSubFile = 0x08010100,
70 Read = 0x080200C2, 71 Read = 0x080200C2,
71 Write = 0x08030102, 72 Write = 0x08030102,
72 GetSize = 0x08040000, 73 GetSize = 0x08040000,
73 SetSize = 0x08050080, 74 SetSize = 0x08050080,
74 GetAttributes = 0x08060000, 75 GetAttributes = 0x08060000,
75 SetAttributes = 0x08070040, 76 SetAttributes = 0x08070040,
76 Close = 0x08080000, 77 Close = 0x08080000,
77 Flush = 0x08090000, 78 Flush = 0x08090000,
78 SetPriority = 0x080A0040, 79 SetPriority = 0x080A0040,
79 GetPriority = 0x080B0000, 80 GetPriority = 0x080B0000,
80 OpenLinkFile = 0x080C0000, 81 OpenLinkFile = 0x080C0000,
81}; 82};
82 83
83// Command to access directory 84// Command to access directory
84enum class DirectoryCommand : u32 { 85enum class DirectoryCommand : u32 {
85 Dummy1 = 0x000100C6, 86 Dummy1 = 0x000100C6,
86 Control = 0x040100C4, 87 Control = 0x040100C4,
87 Read = 0x08010042, 88 Read = 0x08010042,
88 Close = 0x08020000, 89 Close = 0x08020000,
89}; 90};
90 91
91File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path & path) 92File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path)
92 : path(path), priority(0), backend(std::move(backend)) {} 93 : path(path), priority(0), backend(std::move(backend)) {
94}
93 95
94File::~File() {} 96File::~File() {
97}
95 98
96ResultVal<bool> File::SyncRequest() { 99ResultVal<bool> File::SyncRequest() {
97 u32* cmd_buff = Kernel::GetCommandBuffer(); 100 u32* cmd_buff = Kernel::GetCommandBuffer();
98 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 101 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
99 switch (cmd) { 102 switch (cmd) {
100 103
101 // Read from file... 104 // Read from file...
102 case FileCommand::Read: 105 case FileCommand::Read: {
103 { 106 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32;
104 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; 107 u32 length = cmd_buff[3];
105 u32 length = cmd_buff[3]; 108 u32 address = cmd_buff[5];
106 u32 address = cmd_buff[5]; 109 LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x",
107 LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", 110 GetTypeName().c_str(), GetName().c_str(), offset, length, address);
108 GetTypeName().c_str(), GetName().c_str(), offset, length, address); 111
109 112 if (offset + length > backend->GetSize()) {
110 if (offset + length > backend->GetSize()) { 113 LOG_ERROR(Service_FS,
111 LOG_ERROR(Service_FS, "Reading from out of bounds offset=0x%llX length=0x%08X file_size=0x%llX", 114 "Reading from out of bounds offset=0x%llX length=0x%08X file_size=0x%llX",
112 offset, length, backend->GetSize()); 115 offset, length, backend->GetSize());
113 }
114
115 std::vector<u8> data(length);
116 ResultVal<size_t> read = backend->Read(offset, data.size(), data.data());
117 if (read.Failed()) {
118 cmd_buff[1] = read.Code().raw;
119 return read.Code();
120 }
121 Memory::WriteBlock(address, data.data(), *read);
122 cmd_buff[2] = static_cast<u32>(*read);
123 break;
124 } 116 }
125 117
126 // Write to file... 118 std::vector<u8> data(length);
127 case FileCommand::Write: 119 ResultVal<size_t> read = backend->Read(offset, data.size(), data.data());
128 { 120 if (read.Failed()) {
129 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; 121 cmd_buff[1] = read.Code().raw;
130 u32 length = cmd_buff[3]; 122 return read.Code();
131 u32 flush = cmd_buff[4];
132 u32 address = cmd_buff[6];
133 LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x",
134 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush);
135
136 std::vector<u8> data(length);
137 Memory::ReadBlock(address, data.data(), data.size());
138 ResultVal<size_t> written = backend->Write(offset, data.size(), flush != 0, data.data());
139 if (written.Failed()) {
140 cmd_buff[1] = written.Code().raw;
141 return written.Code();
142 }
143 cmd_buff[2] = static_cast<u32>(*written);
144 break;
145 } 123 }
124 Memory::WriteBlock(address, data.data(), *read);
125 cmd_buff[2] = static_cast<u32>(*read);
126 break;
127 }
146 128
147 case FileCommand::GetSize: 129 // Write to file...
148 { 130 case FileCommand::Write: {
149 LOG_TRACE(Service_FS, "GetSize %s %s", GetTypeName().c_str(), GetName().c_str()); 131 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32;
150 u64 size = backend->GetSize(); 132 u32 length = cmd_buff[3];
151 cmd_buff[2] = (u32)size; 133 u32 flush = cmd_buff[4];
152 cmd_buff[3] = size >> 32; 134 u32 address = cmd_buff[6];
153 break; 135 LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x",
136 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush);
137
138 std::vector<u8> data(length);
139 Memory::ReadBlock(address, data.data(), data.size());
140 ResultVal<size_t> written = backend->Write(offset, data.size(), flush != 0, data.data());
141 if (written.Failed()) {
142 cmd_buff[1] = written.Code().raw;
143 return written.Code();
154 } 144 }
145 cmd_buff[2] = static_cast<u32>(*written);
146 break;
147 }
155 148
156 case FileCommand::SetSize: 149 case FileCommand::GetSize: {
157 { 150 LOG_TRACE(Service_FS, "GetSize %s %s", GetTypeName().c_str(), GetName().c_str());
158 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); 151 u64 size = backend->GetSize();
159 LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", 152 cmd_buff[2] = (u32)size;
160 GetTypeName().c_str(), GetName().c_str(), size); 153 cmd_buff[3] = size >> 32;
161 backend->SetSize(size); 154 break;
162 break; 155 }
163 }
164 156
165 case FileCommand::Close: 157 case FileCommand::SetSize: {
166 { 158 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
167 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); 159 LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", GetTypeName().c_str(), GetName().c_str(),
168 backend->Close(); 160 size);
169 break; 161 backend->SetSize(size);
170 } 162 break;
163 }
171 164
172 case FileCommand::Flush: 165 case FileCommand::Close: {
173 { 166 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
174 LOG_TRACE(Service_FS, "Flush"); 167 backend->Close();
175 backend->Flush(); 168 break;
176 break; 169 }
177 }
178 170
179 case FileCommand::OpenLinkFile: 171 case FileCommand::Flush: {
180 { 172 LOG_TRACE(Service_FS, "Flush");
181 LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); 173 backend->Flush();
182 cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE); 174 break;
183 break; 175 }
184 }
185 176
186 case FileCommand::SetPriority: 177 case FileCommand::OpenLinkFile: {
187 { 178 LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str());
188 priority = cmd_buff[1]; 179 cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE);
189 LOG_TRACE(Service_FS, "SetPriority %u", priority); 180 break;
190 break; 181 }
191 }
192 182
193 case FileCommand::GetPriority: 183 case FileCommand::SetPriority: {
194 { 184 priority = cmd_buff[1];
195 cmd_buff[2] = priority; 185 LOG_TRACE(Service_FS, "SetPriority %u", priority);
196 LOG_TRACE(Service_FS, "GetPriority"); 186 break;
197 break; 187 }
198 }
199 188
200 // Unknown command... 189 case FileCommand::GetPriority: {
201 default: 190 cmd_buff[2] = priority;
202 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); 191 LOG_TRACE(Service_FS, "GetPriority");
203 ResultCode error = UnimplementedFunction(ErrorModule::FS); 192 break;
204 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. 193 }
205 return error; 194
195 // Unknown command...
196 default:
197 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
198 ResultCode error = UnimplementedFunction(ErrorModule::FS);
199 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
200 return error;
206 } 201 }
207 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 202 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
208 return MakeResult<bool>(false); 203 return MakeResult<bool>(false);
209} 204}
210 205
211Directory::Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path & path) 206Directory::Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend,
212 : path(path), backend(std::move(backend)) {} 207 const FileSys::Path& path)
208 : path(path), backend(std::move(backend)) {
209}
213 210
214Directory::~Directory() {} 211Directory::~Directory() {
212}
215 213
216ResultVal<bool> Directory::SyncRequest() { 214ResultVal<bool> Directory::SyncRequest() {
217 u32* cmd_buff = Kernel::GetCommandBuffer(); 215 u32* cmd_buff = Kernel::GetCommandBuffer();
218 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); 216 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
219 switch (cmd) { 217 switch (cmd) {
220 218
221 // Read from directory... 219 // Read from directory...
222 case DirectoryCommand::Read: 220 case DirectoryCommand::Read: {
223 { 221 u32 count = cmd_buff[1];
224 u32 count = cmd_buff[1]; 222 u32 address = cmd_buff[3];
225 u32 address = cmd_buff[3]; 223 std::vector<FileSys::Entry> entries(count);
226 std::vector<FileSys::Entry> entries(count); 224 LOG_TRACE(Service_FS, "Read %s %s: count=%d", GetTypeName().c_str(), GetName().c_str(),
227 LOG_TRACE(Service_FS, "Read %s %s: count=%d", 225 count);
228 GetTypeName().c_str(), GetName().c_str(), count); 226
229 227 // Number of entries actually read
230 // Number of entries actually read 228 u32 read = backend->Read(entries.size(), entries.data());
231 u32 read = backend->Read(entries.size(), entries.data()); 229 cmd_buff[2] = read;
232 cmd_buff[2] = read; 230 Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry));
233 Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry)); 231 break;
234 break; 232 }
235 }
236 233
237 case DirectoryCommand::Close: 234 case DirectoryCommand::Close: {
238 { 235 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
239 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); 236 backend->Close();
240 backend->Close(); 237 break;
241 break; 238 }
242 }
243 239
244 // Unknown command... 240 // Unknown command...
245 default: 241 default:
246 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); 242 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
247 ResultCode error = UnimplementedFunction(ErrorModule::FS); 243 ResultCode error = UnimplementedFunction(ErrorModule::FS);
248 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. 244 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
249 return MakeResult<bool>(false); 245 return MakeResult<bool>(false);
250 } 246 }
251 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 247 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
252 return MakeResult<bool>(false); 248 return MakeResult<bool>(false);
@@ -280,8 +276,8 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
280 auto itr = id_code_map.find(id_code); 276 auto itr = id_code_map.find(id_code);
281 if (itr == id_code_map.end()) { 277 if (itr == id_code_map.end()) {
282 // TODO: Verify error against hardware 278 // TODO: Verify error against hardware
283 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, 279 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, ErrorSummary::NotFound,
284 ErrorSummary::NotFound, ErrorLevel::Permanent); 280 ErrorLevel::Permanent);
285 } 281 }
286 282
287 CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); 283 CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path));
@@ -303,19 +299,22 @@ ResultCode CloseArchive(ArchiveHandle handle) {
303 299
304// TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in 300// TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in
305// http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 301// http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22
306ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code) { 302ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory,
303 ArchiveIdCode id_code) {
307 auto result = id_code_map.emplace(id_code, std::move(factory)); 304 auto result = id_code_map.emplace(id_code, std::move(factory));
308 305
309 bool inserted = result.second; 306 bool inserted = result.second;
310 ASSERT_MSG(inserted, "Tried to register more than one archive with same id code"); 307 ASSERT_MSG(inserted, "Tried to register more than one archive with same id code");
311 308
312 auto& archive = result.first->second; 309 auto& archive = result.first->second;
313 LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); 310 LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(),
311 id_code);
314 return RESULT_SUCCESS; 312 return RESULT_SUCCESS;
315} 313}
316 314
317ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, 315ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle,
318 const FileSys::Path& path, const FileSys::Mode mode) { 316 const FileSys::Path& path,
317 const FileSys::Mode mode) {
319 ArchiveBackend* archive = GetArchive(archive_handle); 318 ArchiveBackend* archive = GetArchive(archive_handle);
320 if (archive == nullptr) 319 if (archive == nullptr)
321 return ERR_INVALID_ARCHIVE_HANDLE; 320 return ERR_INVALID_ARCHIVE_HANDLE;
@@ -336,8 +335,10 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa
336 return archive->DeleteFile(path); 335 return archive->DeleteFile(path);
337} 336}
338 337
339ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 338ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle,
340 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { 339 const FileSys::Path& src_path,
340 ArchiveHandle dest_archive_handle,
341 const FileSys::Path& dest_path) {
341 ArchiveBackend* src_archive = GetArchive(src_archive_handle); 342 ArchiveBackend* src_archive = GetArchive(src_archive_handle);
342 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); 343 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle);
343 if (src_archive == nullptr || dest_archive == nullptr) 344 if (src_archive == nullptr || dest_archive == nullptr)
@@ -368,7 +369,8 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
368 ErrorSummary::Canceled, ErrorLevel::Status); 369 ErrorSummary::Canceled, ErrorLevel::Status);
369} 370}
370 371
371ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u64 file_size) { 372ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path,
373 u64 file_size) {
372 ArchiveBackend* archive = GetArchive(archive_handle); 374 ArchiveBackend* archive = GetArchive(archive_handle);
373 if (archive == nullptr) 375 if (archive == nullptr)
374 return ERR_INVALID_ARCHIVE_HANDLE; 376 return ERR_INVALID_ARCHIVE_HANDLE;
@@ -387,8 +389,10 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
387 ErrorSummary::Canceled, ErrorLevel::Status); 389 ErrorSummary::Canceled, ErrorLevel::Status);
388} 390}
389 391
390ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 392ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle,
391 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { 393 const FileSys::Path& src_path,
394 ArchiveHandle dest_archive_handle,
395 const FileSys::Path& dest_path) {
392 ArchiveBackend* src_archive = GetArchive(src_archive_handle); 396 ArchiveBackend* src_archive = GetArchive(src_archive_handle);
393 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); 397 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle);
394 if (src_archive == nullptr || dest_archive == nullptr) 398 if (src_archive == nullptr || dest_archive == nullptr)
@@ -409,15 +413,15 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
409} 413}
410 414
411ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, 415ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
412 const FileSys::Path& path) { 416 const FileSys::Path& path) {
413 ArchiveBackend* archive = GetArchive(archive_handle); 417 ArchiveBackend* archive = GetArchive(archive_handle);
414 if (archive == nullptr) 418 if (archive == nullptr)
415 return ERR_INVALID_ARCHIVE_HANDLE; 419 return ERR_INVALID_ARCHIVE_HANDLE;
416 420
417 std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path); 421 std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path);
418 if (backend == nullptr) { 422 if (backend == nullptr) {
419 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, 423 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
420 ErrorSummary::NotFound, ErrorLevel::Permanent); 424 ErrorLevel::Permanent);
421 } 425 }
422 426
423 auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path)); 427 auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path));
@@ -431,7 +435,8 @@ ResultVal<u64> GetFreeBytesInArchive(ArchiveHandle archive_handle) {
431 return MakeResult<u64>(archive->GetFreeBytes()); 435 return MakeResult<u64>(archive->GetFreeBytes());
432} 436}
433 437
434ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, const FileSys::Path& path) { 438ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info,
439 const FileSys::Path& path) {
435 auto archive_itr = id_code_map.find(id_code); 440 auto archive_itr = id_code_map.find(id_code);
436 if (archive_itr == id_code_map.end()) { 441 if (archive_itr == id_code_map.end()) {
437 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error 442 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
@@ -440,7 +445,8 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo
440 return archive_itr->second->Format(path, format_info); 445 return archive_itr->second->Format(path, format_info);
441} 446}
442 447
443ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, FileSys::Path& archive_path) { 448ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code,
449 FileSys::Path& archive_path) {
444 auto archive = id_code_map.find(id_code); 450 auto archive = id_code_map.find(id_code);
445 if (archive == id_code_map.end()) { 451 if (archive == id_code_map.end()) {
446 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error 452 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
@@ -449,11 +455,14 @@ ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code
449 return archive->second->GetFormatInfo(archive_path); 455 return archive->second->GetFormatInfo(archive_path);
450} 456}
451 457
452ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size, const FileSys::ArchiveFormatInfo& format_info) { 458ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer,
459 u32 icon_size, const FileSys::ArchiveFormatInfo& format_info) {
453 // Construct the binary path to the archive first 460 // Construct the binary path to the archive first
454 FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); 461 FileSys::Path path =
462 FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low);
455 463
456 auto archive = id_code_map.find(media_type == MediaType::NAND ? ArchiveIdCode::SharedExtSaveData : ArchiveIdCode::ExtSaveData); 464 auto archive = id_code_map.find(media_type == MediaType::NAND ? ArchiveIdCode::SharedExtSaveData
465 : ArchiveIdCode::ExtSaveData);
457 466
458 if (archive == id_code_map.end()) { 467 if (archive == id_code_map.end()) {
459 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error 468 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
@@ -476,7 +485,8 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon
476 485
477ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) { 486ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) {
478 // Construct the binary path to the archive first 487 // Construct the binary path to the archive first
479 FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); 488 FileSys::Path path =
489 FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low);
480 490
481 std::string media_type_directory; 491 std::string media_type_directory;
482 if (media_type == MediaType::NAND) { 492 if (media_type == MediaType::NAND) {
@@ -489,7 +499,8 @@ ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) {
489 } 499 }
490 500
491 // Delete all directories (/user, /boss) and the icon file. 501 // Delete all directories (/user, /boss) and the icon file.
492 std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND); 502 std::string base_path =
503 FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND);
493 std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path); 504 std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path);
494 if (FileUtil::Exists(extsavedata_path) && !FileUtil::DeleteDirRecursively(extsavedata_path)) 505 if (FileUtil::Exists(extsavedata_path) && !FileUtil::DeleteDirRecursively(extsavedata_path))
495 return ResultCode(-1); // TODO(Subv): Find the right error code 506 return ResultCode(-1); // TODO(Subv): Find the right error code
@@ -530,30 +541,36 @@ void RegisterArchiveTypes() {
530 if (sdmc_factory->Initialize()) 541 if (sdmc_factory->Initialize())
531 RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC); 542 RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC);
532 else 543 else
533 LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); 544 LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s",
545 sdmc_directory.c_str());
534 546
535 // Create the SaveData archive 547 // Create the SaveData archive
536 auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); 548 auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory);
537 RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); 549 RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData);
538 550
539 auto extsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); 551 auto extsavedata_factory =
552 std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false);
540 if (extsavedata_factory->Initialize()) 553 if (extsavedata_factory->Initialize())
541 RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData); 554 RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData);
542 else 555 else
543 LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_factory->GetMountPoint().c_str()); 556 LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s",
557 extsavedata_factory->GetMountPoint().c_str());
544 558
545 auto sharedextsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true); 559 auto sharedextsavedata_factory =
560 std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true);
546 if (sharedextsavedata_factory->Initialize()) 561 if (sharedextsavedata_factory->Initialize())
547 RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); 562 RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData);
548 else 563 else
549 LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", 564 LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s",
550 sharedextsavedata_factory->GetMountPoint().c_str()); 565 sharedextsavedata_factory->GetMountPoint().c_str());
551 566
552 // Create the SaveDataCheck archive, basically a small variation of the RomFS archive 567 // Create the SaveDataCheck archive, basically a small variation of the RomFS archive
553 auto savedatacheck_factory = std::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); 568 auto savedatacheck_factory =
569 std::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory);
554 RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); 570 RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck);
555 571
556 auto systemsavedata_factory = std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory); 572 auto systemsavedata_factory =
573 std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
557 RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData); 574 RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData);
558} 575}
559 576
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index f7a50a3a7..aad540ff9 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -28,21 +28,18 @@ namespace FS {
28 28
29/// Supported archive types 29/// Supported archive types
30enum class ArchiveIdCode : u32 { 30enum class ArchiveIdCode : u32 {
31 RomFS = 0x00000003, 31 RomFS = 0x00000003,
32 SaveData = 0x00000004, 32 SaveData = 0x00000004,
33 ExtSaveData = 0x00000006, 33 ExtSaveData = 0x00000006,
34 SharedExtSaveData = 0x00000007, 34 SharedExtSaveData = 0x00000007,
35 SystemSaveData = 0x00000008, 35 SystemSaveData = 0x00000008,
36 SDMC = 0x00000009, 36 SDMC = 0x00000009,
37 SDMCWriteOnly = 0x0000000A, 37 SDMCWriteOnly = 0x0000000A,
38 SaveDataCheck = 0x2345678A, 38 SaveDataCheck = 0x2345678A,
39}; 39};
40 40
41/// Media types for the archives 41/// Media types for the archives
42enum class MediaType : u32 { 42enum class MediaType : u32 { NAND = 0, SDMC = 1 };
43 NAND = 0,
44 SDMC = 1
45};
46 43
47typedef u64 ArchiveHandle; 44typedef u64 ArchiveHandle;
48 45
@@ -51,11 +48,13 @@ public:
51 File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path); 48 File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path);
52 ~File(); 49 ~File();
53 50
54 std::string GetName() const override { return "Path: " + path.DebugStr(); } 51 std::string GetName() const override {
52 return "Path: " + path.DebugStr();
53 }
55 ResultVal<bool> SyncRequest() override; 54 ResultVal<bool> SyncRequest() override;
56 55
57 FileSys::Path path; ///< Path of the file 56 FileSys::Path path; ///< Path of the file
58 u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means 57 u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means
59 std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface 58 std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface
60}; 59};
61 60
@@ -64,10 +63,12 @@ public:
64 Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path); 63 Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path);
65 ~Directory(); 64 ~Directory();
66 65
67 std::string GetName() const override { return "Directory: " + path.DebugStr(); } 66 std::string GetName() const override {
67 return "Directory: " + path.DebugStr();
68 }
68 ResultVal<bool> SyncRequest() override; 69 ResultVal<bool> SyncRequest() override;
69 70
70 FileSys::Path path; ///< Path of the directory 71 FileSys::Path path; ///< Path of the directory
71 std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface 72 std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface
72}; 73};
73 74
@@ -90,7 +91,8 @@ ResultCode CloseArchive(ArchiveHandle handle);
90 * @param factory File system backend interface to the archive 91 * @param factory File system backend interface to the archive
91 * @param id_code Id code used to access this type of archive 92 * @param id_code Id code used to access this type of archive
92 */ 93 */
93ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code); 94ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory,
95 ArchiveIdCode id_code);
94 96
95/** 97/**
96 * Open a File from an Archive 98 * Open a File from an Archive
@@ -100,7 +102,8 @@ ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factor
100 * @return The opened File object as a Session 102 * @return The opened File object as a Session
101 */ 103 */
102ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, 104ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle,
103 const FileSys::Path& path, const FileSys::Mode mode); 105 const FileSys::Path& path,
106 const FileSys::Mode mode);
104 107
105/** 108/**
106 * Delete a File from an Archive 109 * Delete a File from an Archive
@@ -118,8 +121,10 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa
118 * @param dest_path Path to the File inside of the destination Archive 121 * @param dest_path Path to the File inside of the destination Archive
119 * @return Whether rename succeeded 122 * @return Whether rename succeeded
120 */ 123 */
121ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 124ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle,
122 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); 125 const FileSys::Path& src_path,
126 ArchiveHandle dest_archive_handle,
127 const FileSys::Path& dest_path);
123 128
124/** 129/**
125 * Delete a Directory from an Archive 130 * Delete a Directory from an Archive
@@ -136,7 +141,8 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
136 * @param file_size The size of the new file, filled with zeroes 141 * @param file_size The size of the new file, filled with zeroes
137 * @return File creation result code 142 * @return File creation result code
138 */ 143 */
139ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u64 file_size); 144ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path,
145 u64 file_size);
140 146
141/** 147/**
142 * Create a Directory from an Archive 148 * Create a Directory from an Archive
@@ -154,8 +160,10 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
154 * @param dest_path Path to the Directory inside of the destination Archive 160 * @param dest_path Path to the Directory inside of the destination Archive
155 * @return Whether rename succeeded 161 * @return Whether rename succeeded
156 */ 162 */
157ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 163ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle,
158 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); 164 const FileSys::Path& src_path,
165 ArchiveHandle dest_archive_handle,
166 const FileSys::Path& dest_path);
159 167
160/** 168/**
161 * Open a Directory from an Archive 169 * Open a Directory from an Archive
@@ -164,7 +172,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
164 * @return The opened Directory object as a Session 172 * @return The opened Directory object as a Session
165 */ 173 */
166ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, 174ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
167 const FileSys::Path& path); 175 const FileSys::Path& path);
168 176
169/** 177/**
170 * Get the free space in an Archive 178 * Get the free space in an Archive
@@ -181,7 +189,8 @@ ResultVal<u64> GetFreeBytesInArchive(ArchiveHandle archive_handle);
181 * @param path The path to the archive, if relevant. 189 * @param path The path to the archive, if relevant.
182 * @return ResultCode 0 on success or the corresponding code on error 190 * @return ResultCode 0 on success or the corresponding code on error
183 */ 191 */
184ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, const FileSys::Path& path = FileSys::Path()); 192ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info,
193 const FileSys::Path& path = FileSys::Path());
185 194
186/** 195/**
187 * Retrieves the format info about the archive of the specified type and path. 196 * Retrieves the format info about the archive of the specified type and path.
@@ -190,7 +199,8 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo
190 * @param archive_path The path of the archive, if relevant 199 * @param archive_path The path of the archive, if relevant
191 * @return The format info of the archive, or the corresponding error code if failed. 200 * @return The format info of the archive, or the corresponding error code if failed.
192 */ 201 */
193ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, FileSys::Path& archive_path); 202ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code,
203 FileSys::Path& archive_path);
194 204
195/** 205/**
196 * Creates a blank SharedExtSaveData archive for the specified extdata ID 206 * Creates a blank SharedExtSaveData archive for the specified extdata ID
@@ -202,7 +212,8 @@ ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code
202 * @param format_info Format information about the new archive 212 * @param format_info Format information about the new archive
203 * @return ResultCode 0 on success or the corresponding code on error 213 * @return ResultCode 0 on success or the corresponding code on error
204 */ 214 */
205ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size, const FileSys::ArchiveFormatInfo& format_info); 215ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer,
216 u32 icon_size, const FileSys::ArchiveFormatInfo& format_info);
206 217
207/** 218/**
208 * Deletes the SharedExtSaveData archive for the specified extdata ID 219 * Deletes the SharedExtSaveData archive for the specified extdata ID
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 937868747..a0adad634 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -57,14 +57,16 @@ static void OpenFile(Service::Interface* self) {
57 u32* cmd_buff = Kernel::GetCommandBuffer(); 57 u32* cmd_buff = Kernel::GetCommandBuffer();
58 58
59 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 59 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
60 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 60 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
61 u32 filename_size = cmd_buff[5]; 61 u32 filename_size = cmd_buff[5];
62 FileSys::Mode mode; mode.hex = cmd_buff[6]; 62 FileSys::Mode mode;
63 u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes. 63 mode.hex = cmd_buff[6];
64 u32 filename_ptr = cmd_buff[9]; 64 u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes.
65 u32 filename_ptr = cmd_buff[9];
65 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 66 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
66 67
67 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); 68 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex,
69 attributes);
68 70
69 ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); 71 ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode);
70 cmd_buff[1] = file_res.Code().raw; 72 cmd_buff[1] = file_res.Code().raw;
@@ -98,24 +100,27 @@ static void OpenFile(Service::Interface* self) {
98static void OpenFileDirectly(Service::Interface* self) { 100static void OpenFileDirectly(Service::Interface* self) {
99 u32* cmd_buff = Kernel::GetCommandBuffer(); 101 u32* cmd_buff = Kernel::GetCommandBuffer();
100 102
101 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[2]); 103 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[2]);
102 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); 104 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]);
103 u32 archivename_size = cmd_buff[4]; 105 u32 archivename_size = cmd_buff[4];
104 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]); 106 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]);
105 u32 filename_size = cmd_buff[6]; 107 u32 filename_size = cmd_buff[6];
106 FileSys::Mode mode; mode.hex = cmd_buff[7]; 108 FileSys::Mode mode;
107 u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes. 109 mode.hex = cmd_buff[7];
108 u32 archivename_ptr = cmd_buff[10]; 110 u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes.
109 u32 filename_ptr = cmd_buff[12]; 111 u32 archivename_ptr = cmd_buff[10];
112 u32 filename_ptr = cmd_buff[12];
110 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); 113 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
111 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 114 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
112 115
113 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s file_path=%s, mode=%u attributes=%d", 116 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s file_path=%s, mode=%u attributes=%d",
114 archive_id, archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes); 117 archive_id, archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex,
118 attributes);
115 119
116 ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path); 120 ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path);
117 if (archive_handle.Failed()) { 121 if (archive_handle.Failed()) {
118 LOG_ERROR(Service_FS, "failed to get a handle for archive archive_id=0x%08X archive_path=%s", 122 LOG_ERROR(Service_FS,
123 "failed to get a handle for archive archive_id=0x%08X archive_path=%s",
119 archive_id, archive_path.DebugStr().c_str()); 124 archive_id, archive_path.DebugStr().c_str());
120 cmd_buff[1] = archive_handle.Code().raw; 125 cmd_buff[1] = archive_handle.Code().raw;
121 cmd_buff[3] = 0; 126 cmd_buff[3] = 0;
@@ -149,14 +154,14 @@ static void DeleteFile(Service::Interface* self) {
149 u32* cmd_buff = Kernel::GetCommandBuffer(); 154 u32* cmd_buff = Kernel::GetCommandBuffer();
150 155
151 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 156 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
152 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 157 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
153 u32 filename_size = cmd_buff[5]; 158 u32 filename_size = cmd_buff[5];
154 u32 filename_ptr = cmd_buff[7]; 159 u32 filename_ptr = cmd_buff[7];
155 160
156 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 161 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
157 162
158 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", 163 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", filename_type, filename_size,
159 filename_type, filename_size, file_path.DebugStr().c_str()); 164 file_path.DebugStr().c_str());
160 165
161 cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw; 166 cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw;
162} 167}
@@ -181,22 +186,26 @@ static void RenameFile(Service::Interface* self) {
181 u32* cmd_buff = Kernel::GetCommandBuffer(); 186 u32* cmd_buff = Kernel::GetCommandBuffer();
182 187
183 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 188 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
184 auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 189 auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
185 u32 src_filename_size = cmd_buff[5]; 190 u32 src_filename_size = cmd_buff[5];
186 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);; 191 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);
187 auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); 192 ;
188 u32 dest_filename_size = cmd_buff[9]; 193 auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
189 u32 src_filename_ptr = cmd_buff[11]; 194 u32 dest_filename_size = cmd_buff[9];
190 u32 dest_filename_ptr = cmd_buff[13]; 195 u32 src_filename_ptr = cmd_buff[11];
196 u32 dest_filename_ptr = cmd_buff[13];
191 197
192 FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr); 198 FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr);
193 FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr); 199 FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr);
194 200
195 LOG_DEBUG(Service_FS, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s", 201 LOG_DEBUG(Service_FS,
202 "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
196 src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(), 203 src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(),
197 dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str()); 204 dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str());
198 205
199 cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw; 206 cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle,
207 dest_file_path)
208 .raw;
200} 209}
201 210
202/* 211/*
@@ -214,14 +223,14 @@ static void DeleteDirectory(Service::Interface* self) {
214 u32* cmd_buff = Kernel::GetCommandBuffer(); 223 u32* cmd_buff = Kernel::GetCommandBuffer();
215 224
216 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 225 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
217 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 226 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
218 u32 dirname_size = cmd_buff[5]; 227 u32 dirname_size = cmd_buff[5];
219 u32 dirname_ptr = cmd_buff[7]; 228 u32 dirname_ptr = cmd_buff[7];
220 229
221 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); 230 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
222 231
223 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", 232 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size,
224 dirname_type, dirname_size, dir_path.DebugStr().c_str()); 233 dir_path.DebugStr().c_str());
225 234
226 cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw; 235 cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw;
227} 236}
@@ -243,14 +252,15 @@ static void CreateFile(Service::Interface* self) {
243 u32* cmd_buff = Kernel::GetCommandBuffer(); 252 u32* cmd_buff = Kernel::GetCommandBuffer();
244 253
245 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 254 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
246 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 255 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
247 u32 filename_size = cmd_buff[5]; 256 u32 filename_size = cmd_buff[5];
248 u64 file_size = ((u64)cmd_buff[8] << 32) | cmd_buff[7]; 257 u64 file_size = ((u64)cmd_buff[8] << 32) | cmd_buff[7];
249 u32 filename_ptr = cmd_buff[10]; 258 u32 filename_ptr = cmd_buff[10];
250 259
251 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 260 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
252 261
253 LOG_DEBUG(Service_FS, "type=%d size=%llu data=%s", filename_type, file_size, file_path.DebugStr().c_str()); 262 LOG_DEBUG(Service_FS, "type=%d size=%llu data=%s", filename_type, file_size,
263 file_path.DebugStr().c_str());
254 264
255 cmd_buff[1] = CreateFileInArchive(archive_handle, file_path, file_size).raw; 265 cmd_buff[1] = CreateFileInArchive(archive_handle, file_path, file_size).raw;
256} 266}
@@ -276,7 +286,8 @@ static void CreateDirectory(Service::Interface* self) {
276 286
277 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); 287 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
278 288
279 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); 289 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size,
290 dir_path.DebugStr().c_str());
280 291
281 cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw; 292 cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw;
282} 293}
@@ -301,22 +312,25 @@ static void RenameDirectory(Service::Interface* self) {
301 u32* cmd_buff = Kernel::GetCommandBuffer(); 312 u32* cmd_buff = Kernel::GetCommandBuffer();
302 313
303 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 314 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
304 auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 315 auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
305 u32 src_dirname_size = cmd_buff[5]; 316 u32 src_dirname_size = cmd_buff[5];
306 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]); 317 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);
307 auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); 318 auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
308 u32 dest_dirname_size = cmd_buff[9]; 319 u32 dest_dirname_size = cmd_buff[9];
309 u32 src_dirname_ptr = cmd_buff[11]; 320 u32 src_dirname_ptr = cmd_buff[11];
310 u32 dest_dirname_ptr = cmd_buff[13]; 321 u32 dest_dirname_ptr = cmd_buff[13];
311 322
312 FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr); 323 FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr);
313 FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr); 324 FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr);
314 325
315 LOG_DEBUG(Service_FS, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s", 326 LOG_DEBUG(Service_FS,
327 "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
316 src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(), 328 src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(),
317 dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str()); 329 dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str());
318 330
319 cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw; 331 cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path,
332 dest_archive_handle, dest_dir_path)
333 .raw;
320} 334}
321 335
322/** 336/**
@@ -342,7 +356,8 @@ static void OpenDirectory(Service::Interface* self) {
342 356
343 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); 357 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
344 358
345 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); 359 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size,
360 dir_path.DebugStr().c_str());
346 361
347 ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); 362 ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path);
348 cmd_buff[1] = dir_res.Code().raw; 363 cmd_buff[1] = dir_res.Code().raw;
@@ -370,13 +385,14 @@ static void OpenDirectory(Service::Interface* self) {
370static void OpenArchive(Service::Interface* self) { 385static void OpenArchive(Service::Interface* self) {
371 u32* cmd_buff = Kernel::GetCommandBuffer(); 386 u32* cmd_buff = Kernel::GetCommandBuffer();
372 387
373 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]); 388 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]);
374 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); 389 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]);
375 u32 archivename_size = cmd_buff[3]; 390 u32 archivename_size = cmd_buff[3];
376 u32 archivename_ptr = cmd_buff[5]; 391 u32 archivename_ptr = cmd_buff[5];
377 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); 392 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
378 393
379 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s", archive_id, archive_path.DebugStr().c_str()); 394 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s", archive_id,
395 archive_path.DebugStr().c_str());
380 396
381 ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path); 397 ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path);
382 cmd_buff[1] = handle.Code().raw; 398 cmd_buff[1] = handle.Code().raw;
@@ -385,7 +401,8 @@ static void OpenArchive(Service::Interface* self) {
385 cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF; 401 cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF;
386 } else { 402 } else {
387 cmd_buff[2] = cmd_buff[3] = 0; 403 cmd_buff[2] = cmd_buff[3] = 0;
388 LOG_ERROR(Service_FS, "failed to get a handle for archive archive_id=0x%08X archive_path=%s", 404 LOG_ERROR(Service_FS,
405 "failed to get a handle for archive archive_id=0x%08X archive_path=%s",
389 archive_id, archive_path.DebugStr().c_str()); 406 archive_id, archive_path.DebugStr().c_str());
390 } 407 }
391} 408}
@@ -471,7 +488,8 @@ static void FormatSaveData(Service::Interface* self) {
471 if (archive_id != FS::ArchiveIdCode::SaveData) { 488 if (archive_id != FS::ArchiveIdCode::SaveData) {
472 LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", archive_id); 489 LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", archive_id);
473 cmd_buff[1] = ResultCode(ErrorDescription::FS_InvalidPath, ErrorModule::FS, 490 cmd_buff[1] = ResultCode(ErrorDescription::FS_InvalidPath, ErrorModule::FS,
474 ErrorSummary::InvalidArgument, ErrorLevel::Usage).raw; 491 ErrorSummary::InvalidArgument, ErrorLevel::Usage)
492 .raw;
475 return; 493 return;
476 } 494 }
477 495
@@ -571,18 +589,21 @@ static void CreateExtSaveData(Service::Interface* self) {
571 u32 icon_size = cmd_buff[9]; 589 u32 icon_size = cmd_buff[9];
572 VAddr icon_buffer = cmd_buff[11]; 590 VAddr icon_buffer = cmd_buff[11];
573 591
574 LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " 592 LOG_WARNING(
575 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " 593 Service_FS,
576 "icon_size=%08X icon_descriptor=%08X icon_buffer=%08X", save_high, save_low, 594 "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X "
577 cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], icon_size, 595 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X "
578 cmd_buff[10], icon_buffer); 596 "icon_size=%08X icon_descriptor=%08X icon_buffer=%08X",
597 save_high, save_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7],
598 cmd_buff[8], icon_size, cmd_buff[10], icon_buffer);
579 599
580 FileSys::ArchiveFormatInfo format_info; 600 FileSys::ArchiveFormatInfo format_info;
581 format_info.number_directories = cmd_buff[5]; 601 format_info.number_directories = cmd_buff[5];
582 format_info.number_files = cmd_buff[6]; 602 format_info.number_files = cmd_buff[6];
583 format_info.duplicate_data = false; 603 format_info.duplicate_data = false;
584 format_info.total_size = 0; 604 format_info.total_size = 0;
585 cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size, format_info).raw; 605 cmd_buff[1] =
606 CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size, format_info).raw;
586} 607}
587 608
588/** 609/**
@@ -604,7 +625,7 @@ static void DeleteExtSaveData(Service::Interface* self) {
604 u32 unknown = cmd_buff[4]; // TODO(Subv): Figure out what this is 625 u32 unknown = cmd_buff[4]; // TODO(Subv): Figure out what this is
605 626
606 LOG_WARNING(Service_FS, "(STUBBED) save_low=%08X save_high=%08X media_type=%08X unknown=%08X", 627 LOG_WARNING(Service_FS, "(STUBBED) save_low=%08X save_high=%08X media_type=%08X unknown=%08X",
607 save_low, save_high, cmd_buff[1] & 0xFF, unknown); 628 save_low, save_high, cmd_buff[1] & 0xFF, unknown);
608 629
609 cmd_buff[1] = DeleteExtSaveData(media_type, save_high, save_low).raw; 630 cmd_buff[1] = DeleteExtSaveData(media_type, save_high, save_low).raw;
610} 631}
@@ -662,10 +683,13 @@ static void CreateSystemSaveData(Service::Interface* self) {
662 u32 savedata_high = cmd_buff[1]; 683 u32 savedata_high = cmd_buff[1];
663 u32 savedata_low = cmd_buff[2]; 684 u32 savedata_low = cmd_buff[2];
664 685
665 LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " 686 LOG_WARNING(
666 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " 687 Service_FS,
667 "cmd_buff[9]=%08X", savedata_high, savedata_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], 688 "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X "
668 cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9]); 689 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X "
690 "cmd_buff[9]=%08X",
691 savedata_high, savedata_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6],
692 cmd_buff[7], cmd_buff[8], cmd_buff[9]);
669 693
670 cmd_buff[1] = CreateSystemSaveData(savedata_high, savedata_low).raw; 694 cmd_buff[1] = CreateSystemSaveData(savedata_high, savedata_low).raw;
671} 695}
@@ -692,10 +716,13 @@ static void CreateLegacySystemSaveData(Service::Interface* self) {
692 u32* cmd_buff = Kernel::GetCommandBuffer(); 716 u32* cmd_buff = Kernel::GetCommandBuffer();
693 u32 savedata_id = cmd_buff[1]; 717 u32 savedata_id = cmd_buff[1];
694 718
695 LOG_WARNING(Service_FS, "(STUBBED) savedata_id=%08X cmd_buff[3]=%08X " 719 LOG_WARNING(
696 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " 720 Service_FS,
697 "cmd_buff[9]=%08X", savedata_id, cmd_buff[3], cmd_buff[4], cmd_buff[5], 721 "(STUBBED) savedata_id=%08X cmd_buff[3]=%08X "
698 cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9]); 722 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X "
723 "cmd_buff[9]=%08X",
724 savedata_id, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8],
725 cmd_buff[9]);
699 726
700 cmd_buff[0] = IPC::MakeHeader(0x810, 0x1, 0); 727 cmd_buff[0] = IPC::MakeHeader(0x810, 0x1, 0);
701 // With this command, the SystemSaveData always has save_high = 0 (Always created in the NAND) 728 // With this command, the SystemSaveData always has save_high = 0 (Always created in the NAND)
@@ -721,8 +748,8 @@ static void InitializeWithSdkVersion(Service::Interface* self) {
721 748
722 cmd_buff[1] = RESULT_SUCCESS.raw; 749 cmd_buff[1] = RESULT_SUCCESS.raw;
723 750
724 LOG_WARNING(Service_FS, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, unk3=0x%08X", 751 LOG_WARNING(Service_FS, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, unk3=0x%08X", unk1, unk2,
725 unk1, unk2, unk3); 752 unk3);
726} 753}
727 754
728/** 755/**
@@ -834,115 +861,114 @@ static void GetFormatInfo(Service::Interface* self) {
834} 861}
835 862
836const Interface::FunctionInfo FunctionTable[] = { 863const Interface::FunctionInfo FunctionTable[] = {
837 {0x000100C6, nullptr, "Dummy1"}, 864 {0x000100C6, nullptr, "Dummy1"},
838 {0x040100C4, nullptr, "Control"}, 865 {0x040100C4, nullptr, "Control"},
839 {0x08010002, Initialize, "Initialize"}, 866 {0x08010002, Initialize, "Initialize"},
840 {0x080201C2, OpenFile, "OpenFile"}, 867 {0x080201C2, OpenFile, "OpenFile"},
841 {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, 868 {0x08030204, OpenFileDirectly, "OpenFileDirectly"},
842 {0x08040142, DeleteFile, "DeleteFile"}, 869 {0x08040142, DeleteFile, "DeleteFile"},
843 {0x08050244, RenameFile, "RenameFile"}, 870 {0x08050244, RenameFile, "RenameFile"},
844 {0x08060142, DeleteDirectory, "DeleteDirectory"}, 871 {0x08060142, DeleteDirectory, "DeleteDirectory"},
845 {0x08070142, nullptr, "DeleteDirectoryRecursively"}, 872 {0x08070142, nullptr, "DeleteDirectoryRecursively"},
846 {0x08080202, CreateFile, "CreateFile"}, 873 {0x08080202, CreateFile, "CreateFile"},
847 {0x08090182, CreateDirectory, "CreateDirectory"}, 874 {0x08090182, CreateDirectory, "CreateDirectory"},
848 {0x080A0244, RenameDirectory, "RenameDirectory"}, 875 {0x080A0244, RenameDirectory, "RenameDirectory"},
849 {0x080B0102, OpenDirectory, "OpenDirectory"}, 876 {0x080B0102, OpenDirectory, "OpenDirectory"},
850 {0x080C00C2, OpenArchive, "OpenArchive"}, 877 {0x080C00C2, OpenArchive, "OpenArchive"},
851 {0x080D0144, nullptr, "ControlArchive"}, 878 {0x080D0144, nullptr, "ControlArchive"},
852 {0x080E0080, CloseArchive, "CloseArchive"}, 879 {0x080E0080, CloseArchive, "CloseArchive"},
853 {0x080F0180, FormatThisUserSaveData, "FormatThisUserSaveData"}, 880 {0x080F0180, FormatThisUserSaveData, "FormatThisUserSaveData"},
854 {0x08100200, CreateLegacySystemSaveData, "CreateLegacySystemSaveData"}, 881 {0x08100200, CreateLegacySystemSaveData, "CreateLegacySystemSaveData"},
855 {0x08110040, nullptr, "DeleteSystemSaveData"}, 882 {0x08110040, nullptr, "DeleteSystemSaveData"},
856 {0x08120080, GetFreeBytes, "GetFreeBytes"}, 883 {0x08120080, GetFreeBytes, "GetFreeBytes"},
857 {0x08130000, nullptr, "GetCardType"}, 884 {0x08130000, nullptr, "GetCardType"},
858 {0x08140000, nullptr, "GetSdmcArchiveResource"}, 885 {0x08140000, nullptr, "GetSdmcArchiveResource"},
859 {0x08150000, nullptr, "GetNandArchiveResource"}, 886 {0x08150000, nullptr, "GetNandArchiveResource"},
860 {0x08160000, nullptr, "GetSdmcFatfsError"}, 887 {0x08160000, nullptr, "GetSdmcFatfsError"},
861 {0x08170000, IsSdmcDetected, "IsSdmcDetected"}, 888 {0x08170000, IsSdmcDetected, "IsSdmcDetected"},
862 {0x08180000, IsSdmcWriteable, "IsSdmcWritable"}, 889 {0x08180000, IsSdmcWriteable, "IsSdmcWritable"},
863 {0x08190042, nullptr, "GetSdmcCid"}, 890 {0x08190042, nullptr, "GetSdmcCid"},
864 {0x081A0042, nullptr, "GetNandCid"}, 891 {0x081A0042, nullptr, "GetNandCid"},
865 {0x081B0000, nullptr, "GetSdmcSpeedInfo"}, 892 {0x081B0000, nullptr, "GetSdmcSpeedInfo"},
866 {0x081C0000, nullptr, "GetNandSpeedInfo"}, 893 {0x081C0000, nullptr, "GetNandSpeedInfo"},
867 {0x081D0042, nullptr, "GetSdmcLog"}, 894 {0x081D0042, nullptr, "GetSdmcLog"},
868 {0x081E0042, nullptr, "GetNandLog"}, 895 {0x081E0042, nullptr, "GetNandLog"},
869 {0x081F0000, nullptr, "ClearSdmcLog"}, 896 {0x081F0000, nullptr, "ClearSdmcLog"},
870 {0x08200000, nullptr, "ClearNandLog"}, 897 {0x08200000, nullptr, "ClearNandLog"},
871 {0x08210000, CardSlotIsInserted, "CardSlotIsInserted"}, 898 {0x08210000, CardSlotIsInserted, "CardSlotIsInserted"},
872 {0x08220000, nullptr, "CardSlotPowerOn"}, 899 {0x08220000, nullptr, "CardSlotPowerOn"},
873 {0x08230000, nullptr, "CardSlotPowerOff"}, 900 {0x08230000, nullptr, "CardSlotPowerOff"},
874 {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"}, 901 {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"},
875 {0x08250040, nullptr, "CardNorDirectCommand"}, 902 {0x08250040, nullptr, "CardNorDirectCommand"},
876 {0x08260080, nullptr, "CardNorDirectCommandWithAddress"}, 903 {0x08260080, nullptr, "CardNorDirectCommandWithAddress"},
877 {0x08270082, nullptr, "CardNorDirectRead"}, 904 {0x08270082, nullptr, "CardNorDirectRead"},
878 {0x082800C2, nullptr, "CardNorDirectReadWithAddress"}, 905 {0x082800C2, nullptr, "CardNorDirectReadWithAddress"},
879 {0x08290082, nullptr, "CardNorDirectWrite"}, 906 {0x08290082, nullptr, "CardNorDirectWrite"},
880 {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"}, 907 {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"},
881 {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"}, 908 {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"},
882 {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"}, 909 {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"},
883 {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"}, 910 {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"},
884 {0x082E0040, nullptr, "GetProductInfo"}, 911 {0x082E0040, nullptr, "GetProductInfo"},
885 {0x082F0040, nullptr, "GetProgramLaunchInfo"}, 912 {0x082F0040, nullptr, "GetProgramLaunchInfo"},
886 {0x08300182, nullptr, "CreateExtSaveData"}, 913 {0x08300182, nullptr, "CreateExtSaveData"},
887 {0x08310180, nullptr, "CreateSharedExtSaveData"}, 914 {0x08310180, nullptr, "CreateSharedExtSaveData"},
888 {0x08320102, nullptr, "ReadExtSaveDataIcon"}, 915 {0x08320102, nullptr, "ReadExtSaveDataIcon"},
889 {0x08330082, nullptr, "EnumerateExtSaveData"}, 916 {0x08330082, nullptr, "EnumerateExtSaveData"},
890 {0x08340082, nullptr, "EnumerateSharedExtSaveData"}, 917 {0x08340082, nullptr, "EnumerateSharedExtSaveData"},
891 {0x08350080, nullptr, "DeleteExtSaveData"}, 918 {0x08350080, nullptr, "DeleteExtSaveData"},
892 {0x08360080, nullptr, "DeleteSharedExtSaveData"}, 919 {0x08360080, nullptr, "DeleteSharedExtSaveData"},
893 {0x08370040, nullptr, "SetCardSpiBaudRate"}, 920 {0x08370040, nullptr, "SetCardSpiBaudRate"},
894 {0x08380040, nullptr, "SetCardSpiBusMode"}, 921 {0x08380040, nullptr, "SetCardSpiBusMode"},
895 {0x08390000, nullptr, "SendInitializeInfoTo9"}, 922 {0x08390000, nullptr, "SendInitializeInfoTo9"},
896 {0x083A0100, nullptr, "GetSpecialContentIndex"}, 923 {0x083A0100, nullptr, "GetSpecialContentIndex"},
897 {0x083B00C2, nullptr, "GetLegacyRomHeader"}, 924 {0x083B00C2, nullptr, "GetLegacyRomHeader"},
898 {0x083C00C2, nullptr, "GetLegacyBannerData"}, 925 {0x083C00C2, nullptr, "GetLegacyBannerData"},
899 {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"}, 926 {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"},
900 {0x083E00C2, nullptr, "QueryTotalQuotaSize"}, 927 {0x083E00C2, nullptr, "QueryTotalQuotaSize"},
901 {0x083F00C0, nullptr, "GetExtDataBlockSize"}, 928 {0x083F00C0, nullptr, "GetExtDataBlockSize"},
902 {0x08400040, nullptr, "AbnegateAccessRight"}, 929 {0x08400040, nullptr, "AbnegateAccessRight"},
903 {0x08410000, nullptr, "DeleteSdmcRoot"}, 930 {0x08410000, nullptr, "DeleteSdmcRoot"},
904 {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"}, 931 {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"},
905 {0x08430000, nullptr, "InitializeCtrFileSystem"}, 932 {0x08430000, nullptr, "InitializeCtrFileSystem"},
906 {0x08440000, nullptr, "CreateSeed"}, 933 {0x08440000, nullptr, "CreateSeed"},
907 {0x084500C2, GetFormatInfo, "GetFormatInfo"}, 934 {0x084500C2, GetFormatInfo, "GetFormatInfo"},
908 {0x08460102, nullptr, "GetLegacyRomHeader2"}, 935 {0x08460102, nullptr, "GetLegacyRomHeader2"},
909 {0x08470180, nullptr, "FormatCtrCardUserSaveData"}, 936 {0x08470180, nullptr, "FormatCtrCardUserSaveData"},
910 {0x08480042, nullptr, "GetSdmcCtrRootPath"}, 937 {0x08480042, nullptr, "GetSdmcCtrRootPath"},
911 {0x08490040, GetArchiveResource, "GetArchiveResource"}, 938 {0x08490040, GetArchiveResource, "GetArchiveResource"},
912 {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"}, 939 {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"},
913 {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"}, 940 {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"},
914 {0x084C0242, FormatSaveData, "FormatSaveData"}, 941 {0x084C0242, FormatSaveData, "FormatSaveData"},
915 {0x084D0102, nullptr, "GetLegacySubBannerData"}, 942 {0x084D0102, nullptr, "GetLegacySubBannerData"},
916 {0x084E0342, nullptr, "UpdateSha256Context"}, 943 {0x084E0342, nullptr, "UpdateSha256Context"},
917 {0x084F0102, nullptr, "ReadSpecialFile"}, 944 {0x084F0102, nullptr, "ReadSpecialFile"},
918 {0x08500040, nullptr, "GetSpecialFileSize"}, 945 {0x08500040, nullptr, "GetSpecialFileSize"},
919 {0x08510242, CreateExtSaveData, "CreateExtSaveData"}, 946 {0x08510242, CreateExtSaveData, "CreateExtSaveData"},
920 {0x08520100, DeleteExtSaveData, "DeleteExtSaveData"}, 947 {0x08520100, DeleteExtSaveData, "DeleteExtSaveData"},
921 {0x08530142, nullptr, "ReadExtSaveDataIcon"}, 948 {0x08530142, nullptr, "ReadExtSaveDataIcon"},
922 {0x085400C0, nullptr, "GetExtDataBlockSize"}, 949 {0x085400C0, nullptr, "GetExtDataBlockSize"},
923 {0x08550102, nullptr, "EnumerateExtSaveData"}, 950 {0x08550102, nullptr, "EnumerateExtSaveData"},
924 {0x08560240, CreateSystemSaveData, "CreateSystemSaveData"}, 951 {0x08560240, CreateSystemSaveData, "CreateSystemSaveData"},
925 {0x08570080, DeleteSystemSaveData, "DeleteSystemSaveData"}, 952 {0x08570080, DeleteSystemSaveData, "DeleteSystemSaveData"},
926 {0x08580000, nullptr, "StartDeviceMoveAsSource"}, 953 {0x08580000, nullptr, "StartDeviceMoveAsSource"},
927 {0x08590200, nullptr, "StartDeviceMoveAsDestination"}, 954 {0x08590200, nullptr, "StartDeviceMoveAsDestination"},
928 {0x085A00C0, nullptr, "SetArchivePriority"}, 955 {0x085A00C0, nullptr, "SetArchivePriority"},
929 {0x085B0080, nullptr, "GetArchivePriority"}, 956 {0x085B0080, nullptr, "GetArchivePriority"},
930 {0x085C00C0, nullptr, "SetCtrCardLatencyParameter"}, 957 {0x085C00C0, nullptr, "SetCtrCardLatencyParameter"},
931 {0x085D01C0, nullptr, "SetFsCompatibilityInfo"}, 958 {0x085D01C0, nullptr, "SetFsCompatibilityInfo"},
932 {0x085E0040, nullptr, "ResetCardCompatibilityParameter"}, 959 {0x085E0040, nullptr, "ResetCardCompatibilityParameter"},
933 {0x085F0040, nullptr, "SwitchCleanupInvalidSaveData"}, 960 {0x085F0040, nullptr, "SwitchCleanupInvalidSaveData"},
934 {0x08600042, nullptr, "EnumerateSystemSaveData"}, 961 {0x08600042, nullptr, "EnumerateSystemSaveData"},
935 {0x08610042, InitializeWithSdkVersion, "InitializeWithSdkVersion"}, 962 {0x08610042, InitializeWithSdkVersion, "InitializeWithSdkVersion"},
936 {0x08620040, SetPriority, "SetPriority"}, 963 {0x08620040, SetPriority, "SetPriority"},
937 {0x08630000, GetPriority, "GetPriority"}, 964 {0x08630000, GetPriority, "GetPriority"},
938 {0x08640000, nullptr, "GetNandInfo"}, 965 {0x08640000, nullptr, "GetNandInfo"},
939 {0x08650140, nullptr, "SetSaveDataSecureValue"}, 966 {0x08650140, nullptr, "SetSaveDataSecureValue"},
940 {0x086600C0, nullptr, "GetSaveDataSecureValue"}, 967 {0x086600C0, nullptr, "GetSaveDataSecureValue"},
941 {0x086700C4, nullptr, "ControlSecureSave"}, 968 {0x086700C4, nullptr, "ControlSecureSave"},
942 {0x08680000, nullptr, "GetMediaType"}, 969 {0x08680000, nullptr, "GetMediaType"},
943 {0x08690000, nullptr, "GetNandEraseCount"}, 970 {0x08690000, nullptr, "GetNandEraseCount"},
944 {0x086A0082, nullptr, "ReadNandReport"} 971 {0x086A0082, nullptr, "ReadNandReport"}};
945};
946 972
947//////////////////////////////////////////////////////////////////////////////////////////////////// 973////////////////////////////////////////////////////////////////////////////////////////////////////
948// Interface class 974// Interface class
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index ec565f46d..b273aac47 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -5,16 +5,16 @@
5#include "common/bit_field.h" 5#include "common/bit_field.h"
6#include "common/microprofile.h" 6#include "common/microprofile.h"
7 7
8#include "core/memory.h"
9#include "core/hle/kernel/event.h" 8#include "core/hle/kernel/event.h"
10#include "core/hle/kernel/shared_memory.h" 9#include "core/hle/kernel/shared_memory.h"
11#include "core/hle/result.h" 10#include "core/hle/result.h"
12#include "core/hw/hw.h"
13#include "core/hw/gpu.h" 11#include "core/hw/gpu.h"
12#include "core/hw/hw.h"
14#include "core/hw/lcd.h" 13#include "core/hw/lcd.h"
14#include "core/memory.h"
15 15
16#include "video_core/gpu_debugger.h"
17#include "video_core/debug_utils/debug_utils.h" 16#include "video_core/debug_utils/debug_utils.h"
17#include "video_core/gpu_debugger.h"
18 18
19#include "gsp_gpu.h" 19#include "gsp_gpu.h"
20 20
@@ -29,12 +29,16 @@ const static u32 REGS_BEGIN = 0x1EB00000;
29 29
30namespace GSP_GPU { 30namespace GSP_GPU {
31 31
32const ResultCode ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED(ErrorDescription::OutofRangeOrMisalignedAddress, ErrorModule::GX, 32const ResultCode
33 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02A01 33 ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED(ErrorDescription::OutofRangeOrMisalignedAddress,
34 ErrorModule::GX, ErrorSummary::InvalidArgument,
35 ErrorLevel::Usage); // 0xE0E02A01
34const ResultCode ERR_GSP_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX, 36const ResultCode ERR_GSP_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX,
35 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BF2 37 ErrorSummary::InvalidArgument,
38 ErrorLevel::Usage); // 0xE0E02BF2
36const ResultCode ERR_GSP_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX, 39const ResultCode ERR_GSP_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX,
37 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BEC 40 ErrorSummary::InvalidArgument,
41 ErrorLevel::Usage); // 0xE0E02BEC
38 42
39/// Event triggered when GSP interrupt has been signalled 43/// Event triggered when GSP interrupt has been signalled
40Kernel::SharedPtr<Kernel::Event> g_interrupt_event; 44Kernel::SharedPtr<Kernel::Event> g_interrupt_event;
@@ -73,7 +77,8 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) {
73 * @param data Data to be written 77 * @param data Data to be written
74 */ 78 */
75static void WriteSingleHWReg(u32 base_address, u32 data) { 79static void WriteSingleHWReg(u32 base_address, u32 data) {
76 DEBUG_ASSERT_MSG((base_address & 3) == 0 && base_address < 0x420000, "Write address out of range or misaligned"); 80 DEBUG_ASSERT_MSG((base_address & 3) == 0 && base_address < 0x420000,
81 "Write address out of range or misaligned");
77 HW::Write<u32>(base_address + REGS_BEGIN, data); 82 HW::Write<u32>(base_address + REGS_BEGIN, data);
78} 83}
79 84
@@ -90,7 +95,8 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_va
90 const u32 max_size_in_bytes = 0x80; 95 const u32 max_size_in_bytes = 0x80;
91 96
92 if (base_address & 3 || base_address >= 0x420000) { 97 if (base_address & 3 || base_address >= 0x420000) {
93 LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", 98 LOG_ERROR(Service_GSP,
99 "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)",
94 base_address, size_in_bytes); 100 base_address, size_in_bytes);
95 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; 101 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED;
96 } else if (size_in_bytes <= max_size_in_bytes) { 102 } else if (size_in_bytes <= max_size_in_bytes) {
@@ -124,12 +130,14 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_va
124 * @param masks A pointer to the masks 130 * @param masks A pointer to the masks
125 * @return RESULT_SUCCESS if the parameters are valid, error code otherwise 131 * @return RESULT_SUCCESS if the parameters are valid, error code otherwise
126 */ 132 */
127static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr, VAddr masks_vaddr) { 133static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr,
134 VAddr masks_vaddr) {
128 // This magic number is verified to be done by the gsp module 135 // This magic number is verified to be done by the gsp module
129 const u32 max_size_in_bytes = 0x80; 136 const u32 max_size_in_bytes = 0x80;
130 137
131 if (base_address & 3 || base_address >= 0x420000) { 138 if (base_address & 3 || base_address >= 0x420000) {
132 LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", 139 LOG_ERROR(Service_GSP,
140 "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)",
133 base_address, size_in_bytes); 141 base_address, size_in_bytes);
134 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; 142 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED;
135 } else if (size_in_bytes <= max_size_in_bytes) { 143 } else if (size_in_bytes <= max_size_in_bytes) {
@@ -214,7 +222,8 @@ static void ReadHWRegs(Service::Interface* self) {
214 222
215 // TODO: Return proper error codes 223 // TODO: Return proper error codes
216 if (reg_addr + size >= 0x420000) { 224 if (reg_addr + size >= 0x420000) {
217 LOG_ERROR(Service_GSP, "Read address out of range! (address=0x%08x, size=0x%08x)", reg_addr, size); 225 LOG_ERROR(Service_GSP, "Read address out of range! (address=0x%08x, size=0x%08x)", reg_addr,
226 size);
218 return; 227 return;
219 } 228 }
220 229
@@ -243,22 +252,34 @@ ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
243 PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); 252 PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left);
244 PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); 253 PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right);
245 if (info.active_fb == 0) { 254 if (info.active_fb == 0) {
246 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), 255 WriteSingleHWReg(
247 phys_address_left); 256 base_address +
248 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), 257 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)),
249 phys_address_right); 258 phys_address_left);
259 WriteSingleHWReg(
260 base_address +
261 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)),
262 phys_address_right);
250 } else { 263 } else {
251 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), 264 WriteSingleHWReg(
252 phys_address_left); 265 base_address +
253 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), 266 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)),
254 phys_address_right); 267 phys_address_left);
268 WriteSingleHWReg(
269 base_address +
270 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)),
271 phys_address_right);
255 } 272 }
256 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), 273 WriteSingleHWReg(base_address +
274 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)),
257 info.stride); 275 info.stride);
258 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), 276 WriteSingleHWReg(
259 info.format); 277 base_address +
260 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 278 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)),
261 info.shown_fb); 279 info.format);
280 WriteSingleHWReg(
281 base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)),
282 info.shown_fb);
262 283
263 if (Pica::g_debug_context) 284 if (Pica::g_debug_context)
264 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); 285 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr);
@@ -305,15 +326,15 @@ static void SetBufferSwap(Service::Interface* self) {
305static void FlushDataCache(Service::Interface* self) { 326static void FlushDataCache(Service::Interface* self) {
306 u32* cmd_buff = Kernel::GetCommandBuffer(); 327 u32* cmd_buff = Kernel::GetCommandBuffer();
307 u32 address = cmd_buff[1]; 328 u32 address = cmd_buff[1];
308 u32 size = cmd_buff[2]; 329 u32 size = cmd_buff[2];
309 u32 process = cmd_buff[4]; 330 u32 process = cmd_buff[4];
310 331
311 // TODO(purpasmart96): Verify return header on HW 332 // TODO(purpasmart96): Verify return header on HW
312 333
313 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 334 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
314 335
315 LOG_DEBUG(Service_GSP, "(STUBBED) called address=0x%08X, size=0x%08X, process=0x%08X", 336 LOG_DEBUG(Service_GSP, "(STUBBED) called address=0x%08X, size=0x%08X, process=0x%08X", address,
316 address, size, process); 337 size, process);
317} 338}
318 339
319/** 340/**
@@ -356,11 +377,12 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) {
356 // This specific code is required for a successful initialization, rather than 0 377 // This specific code is required for a successful initialization, rather than 0
357 first_initialization = false; 378 first_initialization = false;
358 cmd_buff[1] = ResultCode(ErrorDescription::GPU_FirstInitialization, ErrorModule::GX, 379 cmd_buff[1] = ResultCode(ErrorDescription::GPU_FirstInitialization, ErrorModule::GX,
359 ErrorSummary::Success, ErrorLevel::Success).raw; 380 ErrorSummary::Success, ErrorLevel::Success)
381 .raw;
360 } else { 382 } else {
361 cmd_buff[1] = RESULT_SUCCESS.raw; 383 cmd_buff[1] = RESULT_SUCCESS.raw;
362 } 384 }
363 cmd_buff[2] = g_thread_id++; // Thread ID 385 cmd_buff[2] = g_thread_id++; // Thread ID
364 cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // GSP shared memory 386 cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // GSP shared memory
365 387
366 g_interrupt_event->Signal(); // TODO(bunnei): Is this correct? 388 g_interrupt_event->Signal(); // TODO(bunnei): Is this correct?
@@ -416,7 +438,8 @@ void SignalInterrupt(InterruptId interrupt_id) {
416 // Update framebuffer information if requested 438 // Update framebuffer information if requested
417 // TODO(yuriks): Confirm where this code should be called. It is definitely updated without 439 // TODO(yuriks): Confirm where this code should be called. It is definitely updated without
418 // executing any GSP commands, only waiting on the event. 440 // executing any GSP commands, only waiting on the event.
419 int screen_id = (interrupt_id == InterruptId::PDC0) ? 0 : (interrupt_id == InterruptId::PDC1) ? 1 : -1; 441 int screen_id =
442 (interrupt_id == InterruptId::PDC0) ? 0 : (interrupt_id == InterruptId::PDC1) ? 1 : -1;
420 if (screen_id != -1) { 443 if (screen_id != -1) {
421 FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id); 444 FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id);
422 if (info->is_dirty) { 445 if (info->is_dirty) {
@@ -440,25 +463,27 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
440 switch (command.id) { 463 switch (command.id) {
441 464
442 // GX request DMA - typically used for copying memory from GSP heap to VRAM 465 // GX request DMA - typically used for copying memory from GSP heap to VRAM
443 case CommandId::REQUEST_DMA: 466 case CommandId::REQUEST_DMA: {
444 {
445 MICROPROFILE_SCOPE(GPU_GSP_DMA); 467 MICROPROFILE_SCOPE(GPU_GSP_DMA);
446 468
447 // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever possible/likely 469 // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever
448 Memory::RasterizerFlushRegion(Memory::VirtualToPhysicalAddress(command.dma_request.source_address), 470 // possible/likely
449 command.dma_request.size); 471 Memory::RasterizerFlushRegion(
450 Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), 472 Memory::VirtualToPhysicalAddress(command.dma_request.source_address),
451 command.dma_request.size); 473 command.dma_request.size);
474 Memory::RasterizerFlushAndInvalidateRegion(
475 Memory::VirtualToPhysicalAddress(command.dma_request.dest_address),
476 command.dma_request.size);
452 477
453 // TODO(Subv): These memory accesses should not go through the application's memory mapping. 478 // TODO(Subv): These memory accesses should not go through the application's memory mapping.
454 // They should go through the GSP module's memory mapping. 479 // They should go through the GSP module's memory mapping.
455 Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address, command.dma_request.size); 480 Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address,
481 command.dma_request.size);
456 SignalInterrupt(InterruptId::DMA); 482 SignalInterrupt(InterruptId::DMA);
457 break; 483 break;
458 } 484 }
459 // TODO: This will need some rework in the future. (why?) 485 // TODO: This will need some rework in the future. (why?)
460 case CommandId::SUBMIT_GPU_CMDLIST: 486 case CommandId::SUBMIT_GPU_CMDLIST: {
461 {
462 auto& params = command.submit_gpu_cmdlist; 487 auto& params = command.submit_gpu_cmdlist;
463 488
464 if (params.do_flush) { 489 if (params.do_flush) {
@@ -468,10 +493,12 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
468 } 493 }
469 494
470 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)), 495 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)),
471 Memory::VirtualToPhysicalAddress(params.address) >> 3); 496 Memory::VirtualToPhysicalAddress(params.address) >> 3);
472 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.size)), params.size); 497 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.size)),
498 params.size);
473 499
474 // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though 500 // TODO: Not sure if we are supposed to always write this .. seems to trigger processing
501 // though
475 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.trigger)), 1); 502 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.trigger)), 1);
476 503
477 // TODO(yuriks): Figure out the meaning of the `flags` field. 504 // TODO(yuriks): Figure out the meaning of the `flags` field.
@@ -481,67 +508,70 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
481 508
482 // It's assumed that the two "blocks" behave equivalently. 509 // It's assumed that the two "blocks" behave equivalently.
483 // Presumably this is done simply to allow two memory fills to run in parallel. 510 // Presumably this is done simply to allow two memory fills to run in parallel.
484 case CommandId::SET_MEMORY_FILL: 511 case CommandId::SET_MEMORY_FILL: {
485 {
486 auto& params = command.memory_fill; 512 auto& params = command.memory_fill;
487 513
488 if (params.start1 != 0) { 514 if (params.start1 != 0) {
489 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)), 515 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)),
490 Memory::VirtualToPhysicalAddress(params.start1) >> 3); 516 Memory::VirtualToPhysicalAddress(params.start1) >> 3);
491 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)), 517 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)),
492 Memory::VirtualToPhysicalAddress(params.end1) >> 3); 518 Memory::VirtualToPhysicalAddress(params.end1) >> 3);
493 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)), params.value1); 519 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)),
494 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)), params.control1); 520 params.value1);
521 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)),
522 params.control1);
495 } 523 }
496 524
497 if (params.start2 != 0) { 525 if (params.start2 != 0) {
498 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)), 526 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)),
499 Memory::VirtualToPhysicalAddress(params.start2) >> 3); 527 Memory::VirtualToPhysicalAddress(params.start2) >> 3);
500 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)), 528 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)),
501 Memory::VirtualToPhysicalAddress(params.end2) >> 3); 529 Memory::VirtualToPhysicalAddress(params.end2) >> 3);
502 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)), params.value2); 530 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)),
503 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)), params.control2); 531 params.value2);
532 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)),
533 params.control2);
504 } 534 }
505 break; 535 break;
506 } 536 }
507 537
508 case CommandId::SET_DISPLAY_TRANSFER: 538 case CommandId::SET_DISPLAY_TRANSFER: {
509 {
510 auto& params = command.display_transfer; 539 auto& params = command.display_transfer;
511 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)), 540 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)),
512 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); 541 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3);
513 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)), 542 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)),
514 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); 543 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3);
515 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_size)), params.in_buffer_size); 544 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_size)),
516 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_size)), params.out_buffer_size); 545 params.in_buffer_size);
517 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.flags)), params.flags); 546 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_size)),
547 params.out_buffer_size);
548 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.flags)),
549 params.flags);
518 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.trigger)), 1); 550 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.trigger)), 1);
519 break; 551 break;
520 } 552 }
521 553
522 case CommandId::SET_TEXTURE_COPY: 554 case CommandId::SET_TEXTURE_COPY: {
523 {
524 auto& params = command.texture_copy; 555 auto& params = command.texture_copy;
525 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.input_address), 556 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.input_address),
526 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); 557 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3);
527 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.output_address), 558 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.output_address),
528 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); 559 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3);
529 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.size), 560 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.size),
530 params.size); 561 params.size);
531 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.input_size), 562 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.input_size),
532 params.in_width_gap); 563 params.in_width_gap);
533 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.output_size), 564 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.output_size),
534 params.out_width_gap); 565 params.out_width_gap);
535 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.flags), 566 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.flags), params.flags);
536 params.flags);
537 567
538 // NOTE: Actual GSP ORs 1 with current register instead of overwriting. Doesn't seem to matter. 568 // NOTE: Actual GSP ORs 1 with current register instead of overwriting. Doesn't seem to
569 // matter.
539 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.trigger), 1); 570 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.trigger), 1);
540 break; 571 break;
541 } 572 }
542 573
543 case CommandId::CACHE_FLUSH: 574 case CommandId::CACHE_FLUSH: {
544 {
545 // NOTE: Rasterizer flushing handled elsewhere in CPU read/write and other GPU handlers 575 // NOTE: Rasterizer flushing handled elsewhere in CPU read/write and other GPU handlers
546 // Use command.cache_flush.regions to implement this handler 576 // Use command.cache_flush.regions to implement this handler
547 break; 577 break;
@@ -552,7 +582,8 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
552 } 582 }
553 583
554 if (Pica::g_debug_context) 584 if (Pica::g_debug_context)
555 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::GSPCommandProcessed, (void*)&command); 585 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::GSPCommandProcessed,
586 (void*)&command);
556} 587}
557 588
558/** 589/**
@@ -575,7 +606,7 @@ static void SetLcdForceBlack(Service::Interface* self) {
575 // the color to black (all zero). 606 // the color to black (all zero).
576 data.is_enabled.Assign(enable_black); 607 data.is_enabled.Assign(enable_black);
577 608
578 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_top), data.raw); // Top LCD 609 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_top), data.raw); // Top LCD
579 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_bottom), data.raw); // Bottom LCD 610 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_bottom), data.raw); // Bottom LCD
580 611
581 cmd_buff[1] = RESULT_SUCCESS.raw; 612 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -679,37 +710,37 @@ static void ReleaseRight(Service::Interface* self) {
679} 710}
680 711
681const Interface::FunctionInfo FunctionTable[] = { 712const Interface::FunctionInfo FunctionTable[] = {
682 {0x00010082, WriteHWRegs, "WriteHWRegs"}, 713 {0x00010082, WriteHWRegs, "WriteHWRegs"},
683 {0x00020084, WriteHWRegsWithMask, "WriteHWRegsWithMask"}, 714 {0x00020084, WriteHWRegsWithMask, "WriteHWRegsWithMask"},
684 {0x00030082, nullptr, "WriteHWRegRepeat"}, 715 {0x00030082, nullptr, "WriteHWRegRepeat"},
685 {0x00040080, ReadHWRegs, "ReadHWRegs"}, 716 {0x00040080, ReadHWRegs, "ReadHWRegs"},
686 {0x00050200, SetBufferSwap, "SetBufferSwap"}, 717 {0x00050200, SetBufferSwap, "SetBufferSwap"},
687 {0x00060082, nullptr, "SetCommandList"}, 718 {0x00060082, nullptr, "SetCommandList"},
688 {0x000700C2, nullptr, "RequestDma"}, 719 {0x000700C2, nullptr, "RequestDma"},
689 {0x00080082, FlushDataCache, "FlushDataCache"}, 720 {0x00080082, FlushDataCache, "FlushDataCache"},
690 {0x00090082, nullptr, "InvalidateDataCache"}, 721 {0x00090082, nullptr, "InvalidateDataCache"},
691 {0x000A0044, nullptr, "RegisterInterruptEvents"}, 722 {0x000A0044, nullptr, "RegisterInterruptEvents"},
692 {0x000B0040, SetLcdForceBlack, "SetLcdForceBlack"}, 723 {0x000B0040, SetLcdForceBlack, "SetLcdForceBlack"},
693 {0x000C0000, TriggerCmdReqQueue, "TriggerCmdReqQueue"}, 724 {0x000C0000, TriggerCmdReqQueue, "TriggerCmdReqQueue"},
694 {0x000D0140, nullptr, "SetDisplayTransfer"}, 725 {0x000D0140, nullptr, "SetDisplayTransfer"},
695 {0x000E0180, nullptr, "SetTextureCopy"}, 726 {0x000E0180, nullptr, "SetTextureCopy"},
696 {0x000F0200, nullptr, "SetMemoryFill"}, 727 {0x000F0200, nullptr, "SetMemoryFill"},
697 {0x00100040, SetAxiConfigQoSMode, "SetAxiConfigQoSMode"}, 728 {0x00100040, SetAxiConfigQoSMode, "SetAxiConfigQoSMode"},
698 {0x00110040, nullptr, "SetPerfLogMode"}, 729 {0x00110040, nullptr, "SetPerfLogMode"},
699 {0x00120000, nullptr, "GetPerfLog"}, 730 {0x00120000, nullptr, "GetPerfLog"},
700 {0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"}, 731 {0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"},
701 {0x00140000, UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"}, 732 {0x00140000, UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"},
702 {0x00150002, nullptr, "TryAcquireRight"}, 733 {0x00150002, nullptr, "TryAcquireRight"},
703 {0x00160042, AcquireRight, "AcquireRight"}, 734 {0x00160042, AcquireRight, "AcquireRight"},
704 {0x00170000, ReleaseRight, "ReleaseRight"}, 735 {0x00170000, ReleaseRight, "ReleaseRight"},
705 {0x00180000, ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"}, 736 {0x00180000, ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"},
706 {0x00190000, nullptr, "SaveVramSysArea"}, 737 {0x00190000, nullptr, "SaveVramSysArea"},
707 {0x001A0000, nullptr, "RestoreVramSysArea"}, 738 {0x001A0000, nullptr, "RestoreVramSysArea"},
708 {0x001B0000, nullptr, "ResetGpuCore"}, 739 {0x001B0000, nullptr, "ResetGpuCore"},
709 {0x001C0040, nullptr, "SetLedForceOff"}, 740 {0x001C0040, nullptr, "SetLedForceOff"},
710 {0x001D0040, nullptr, "SetTestCommand"}, 741 {0x001D0040, nullptr, "SetTestCommand"},
711 {0x001E0080, nullptr, "SetInternalPriorities"}, 742 {0x001E0080, nullptr, "SetInternalPriorities"},
712 {0x001F0082, nullptr, "StoreDataCache"}, 743 {0x001F0082, nullptr, "StoreDataCache"},
713}; 744};
714 745
715//////////////////////////////////////////////////////////////////////////////////////////////////// 746////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -721,9 +752,9 @@ Interface::Interface() {
721 g_interrupt_event = nullptr; 752 g_interrupt_event = nullptr;
722 753
723 using Kernel::MemoryPermission; 754 using Kernel::MemoryPermission;
724 g_shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000, 755 g_shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite,
725 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 756 MemoryPermission::ReadWrite, 0,
726 0, Kernel::MemoryRegion::BASE, "GSP:SharedMemory"); 757 Kernel::MemoryRegion::BASE, "GSP:SharedMemory");
727 758
728 g_thread_id = 0; 759 g_thread_id = 0;
729 gpu_right_acquired = false; 760 gpu_right_acquired = false;
diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h
index 3b4b678a3..e028123f3 100644
--- a/src/core/hle/service/gsp_gpu.h
+++ b/src/core/hle/service/gsp_gpu.h
@@ -20,30 +20,30 @@ namespace GSP_GPU {
20 20
21/// GSP interrupt ID 21/// GSP interrupt ID
22enum class InterruptId : u8 { 22enum class InterruptId : u8 {
23 PSC0 = 0x00, 23 PSC0 = 0x00,
24 PSC1 = 0x01, 24 PSC1 = 0x01,
25 PDC0 = 0x02, // Seems called every vertical screen line 25 PDC0 = 0x02, // Seems called every vertical screen line
26 PDC1 = 0x03, // Seems called every frame 26 PDC1 = 0x03, // Seems called every frame
27 PPF = 0x04, 27 PPF = 0x04,
28 P3D = 0x05, 28 P3D = 0x05,
29 DMA = 0x06, 29 DMA = 0x06,
30}; 30};
31 31
32/// GSP command ID 32/// GSP command ID
33enum class CommandId : u32 { 33enum class CommandId : u32 {
34 REQUEST_DMA = 0x00, 34 REQUEST_DMA = 0x00,
35 /// Submits a commandlist for execution by the GPU. 35 /// Submits a commandlist for execution by the GPU.
36 SUBMIT_GPU_CMDLIST = 0x01, 36 SUBMIT_GPU_CMDLIST = 0x01,
37 37
38 // Fills a given memory range with a particular value 38 // Fills a given memory range with a particular value
39 SET_MEMORY_FILL = 0x02, 39 SET_MEMORY_FILL = 0x02,
40 40
41 // Copies an image and optionally performs color-conversion or scaling. 41 // Copies an image and optionally performs color-conversion or scaling.
42 // This is highly similar to the GameCube's EFB copy feature 42 // This is highly similar to the GameCube's EFB copy feature
43 SET_DISPLAY_TRANSFER = 0x03, 43 SET_DISPLAY_TRANSFER = 0x03,
44 44
45 // Conceptionally similar to SET_DISPLAY_TRANSFER and presumable uses the same hardware path 45 // Conceptionally similar to SET_DISPLAY_TRANSFER and presumable uses the same hardware path
46 SET_TEXTURE_COPY = 0x04, 46 SET_TEXTURE_COPY = 0x04,
47 /// Flushes up to 3 cache regions in a single command. 47 /// Flushes up to 3 cache regions in a single command.
48 CACHE_FLUSH = 0x05, 48 CACHE_FLUSH = 0x05,
49}; 49};
@@ -61,19 +61,18 @@ struct InterruptRelayQueue {
61 u32 missed_PDC0; 61 u32 missed_PDC0;
62 u32 missed_PDC1; 62 u32 missed_PDC1;
63 63
64 InterruptId slot[0x34]; ///< Interrupt ID slots 64 InterruptId slot[0x34]; ///< Interrupt ID slots
65}; 65};
66static_assert(sizeof(InterruptRelayQueue) == 0x40, 66static_assert(sizeof(InterruptRelayQueue) == 0x40, "InterruptRelayQueue struct has incorrect size");
67 "InterruptRelayQueue struct has incorrect size");
68 67
69struct FrameBufferInfo { 68struct FrameBufferInfo {
70 BitField<0, 1, u32> active_fb; // 0 = first, 1 = second 69 BitField<0, 1, u32> active_fb; // 0 = first, 1 = second
71 70
72 u32 address_left; 71 u32 address_left;
73 u32 address_right; 72 u32 address_right;
74 u32 stride; // maps to 0x1EF00X90 ? 73 u32 stride; // maps to 0x1EF00X90 ?
75 u32 format; // maps to 0x1EF00X70 ? 74 u32 format; // maps to 0x1EF00X70 ?
76 u32 shown_fb; // maps to 0x1EF00X78 ? 75 u32 shown_fb; // maps to 0x1EF00X78 ?
77 u32 unknown; 76 u32 unknown;
78}; 77};
79static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size"); 78static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size");
@@ -91,7 +90,8 @@ static_assert(sizeof(FrameBufferUpdate) == 0x40, "Struct has incorrect size");
91// TODO: Not sure if this padding is correct. 90// TODO: Not sure if this padding is correct.
92// Chances are the second block is stored at offset 0x24 rather than 0x20. 91// Chances are the second block is stored at offset 0x24 rather than 0x20.
93#ifndef _MSC_VER 92#ifndef _MSC_VER
94static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20, "FrameBufferInfo element has incorrect alignment"); 93static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20,
94 "FrameBufferInfo element has incorrect alignment");
95#endif 95#endif
96 96
97/// GSP command 97/// GSP command
@@ -163,13 +163,13 @@ struct CommandBuffer {
163 // Current command index. This index is updated by GSP module after loading the command 163 // Current command index. This index is updated by GSP module after loading the command
164 // data, right before the command is processed. When this index is updated by GSP module, 164 // data, right before the command is processed. When this index is updated by GSP module,
165 // the total commands field is decreased by one as well. 165 // the total commands field is decreased by one as well.
166 BitField<0,8,u32> index; 166 BitField<0, 8, u32> index;
167 167
168 // Total commands to process, must not be value 0 when GSP module handles commands. This 168 // Total commands to process, must not be value 0 when GSP module handles commands. This
169 // must be <=15 when writing a command to shared memory. This is incremented by the 169 // must be <=15 when writing a command to shared memory. This is incremented by the
170 // application when writing a command to shared memory, after increasing this value 170 // application when writing a command to shared memory, after increasing this value
171 // TriggerCmdReqQueue is only used if this field is value 1. 171 // TriggerCmdReqQueue is only used if this field is value 1.
172 BitField<8,8,u32> number_commands; 172 BitField<8, 8, u32> number_commands;
173 }; 173 };
174 174
175 u32 unk[7]; 175 u32 unk[7];
diff --git a/src/core/hle/service/gsp_lcd.cpp b/src/core/hle/service/gsp_lcd.cpp
index c700c21c5..3922cd197 100644
--- a/src/core/hle/service/gsp_lcd.cpp
+++ b/src/core/hle/service/gsp_lcd.cpp
@@ -9,13 +9,11 @@
9 9
10namespace GSP_LCD { 10namespace GSP_LCD {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {{0x000F0000, nullptr, "PowerOnAllBacklights"},
13 {0x000F0000, nullptr, "PowerOnAllBacklights"}, 13 {0x00100000, nullptr, "PowerOffAllBacklights"},
14 {0x00100000, nullptr, "PowerOffAllBacklights"}, 14 {0x00110040, nullptr, "PowerOnBacklight"},
15 {0x00110040, nullptr, "PowerOnBacklight"}, 15 {0x00120040, nullptr, "PowerOffBacklight"},
16 {0x00120040, nullptr, "PowerOffBacklight"}, 16 {0x00130040, nullptr, "SetLedForceOff"}};
17 {0x00130040, nullptr, "SetLedForceOff"}
18};
19 17
20//////////////////////////////////////////////////////////////////////////////////////////////////// 18////////////////////////////////////////////////////////////////////////////////////////////////////
21// Interface class 19// Interface class
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index cdec11388..d915a3105 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -4,13 +4,13 @@
4 4
5#include <cmath> 5#include <cmath>
6 6
7#include "common/logging/log.h"
8#include "common/emu_window.h" 7#include "common/emu_window.h"
8#include "common/logging/log.h"
9 9
10#include "core/hle/service/service.h"
11#include "core/hle/service/hid/hid.h" 10#include "core/hle/service/hid/hid.h"
12#include "core/hle/service/hid/hid_spvr.h" 11#include "core/hle/service/hid/hid_spvr.h"
13#include "core/hle/service/hid/hid_user.h" 12#include "core/hle/service/hid/hid_user.h"
13#include "core/hle/service/service.h"
14 14
15#include "core/core_timing.h" 15#include "core/core_timing.h"
16#include "core/hle/kernel/event.h" 16#include "core/hle/kernel/event.h"
@@ -37,11 +37,14 @@ static u32 next_accelerometer_index;
37static u32 next_gyroscope_index; 37static u32 next_gyroscope_index;
38 38
39static int enable_accelerometer_count = 0; // positive means enabled 39static int enable_accelerometer_count = 0; // positive means enabled
40static int enable_gyroscope_count = 0; // positive means enabled 40static int enable_gyroscope_count = 0; // positive means enabled
41 41
42static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) { 42static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) {
43 constexpr float TAN30 = 0.577350269, TAN60 = 1 / TAN30; // 30 degree and 60 degree are angular thresholds for directions 43 constexpr float TAN30 = 0.577350269,
44 constexpr int CIRCLE_PAD_THRESHOLD_SQUARE = 40 * 40; // a circle pad radius greater than 40 will trigger circle pad direction 44 TAN60 =
45 1 / TAN30; // 30 degree and 60 degree are angular thresholds for directions
46 constexpr int CIRCLE_PAD_THRESHOLD_SQUARE =
47 40 * 40; // a circle pad radius greater than 40 will trigger circle pad direction
45 PadState state; 48 PadState state;
46 state.hex = 0; 49 state.hex = 0;
47 50
@@ -90,7 +93,7 @@ void Update() {
90 PadState old_state = mem->pad.entries[last_entry_index].current_state; 93 PadState old_state = mem->pad.entries[last_entry_index].current_state;
91 94
92 // Compute bitmask with 1s for bits different from the old state 95 // Compute bitmask with 1s for bits different from the old state
93 PadState changed = { { (state.hex ^ old_state.hex) } }; 96 PadState changed = {{(state.hex ^ old_state.hex)}};
94 97
95 // Get the current Pad entry 98 // Get the current Pad entry
96 PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index]; 99 PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index];
@@ -135,11 +138,13 @@ void Update() {
135 // Update accelerometer 138 // Update accelerometer
136 if (enable_accelerometer_count > 0) { 139 if (enable_accelerometer_count > 0) {
137 mem->accelerometer.index = next_accelerometer_index; 140 mem->accelerometer.index = next_accelerometer_index;
138 next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size(); 141 next_accelerometer_index =
142 (next_accelerometer_index + 1) % mem->accelerometer.entries.size();
139 143
140 AccelerometerDataEntry& accelerometer_entry = mem->accelerometer.entries[mem->accelerometer.index]; 144 AccelerometerDataEntry& accelerometer_entry =
141 std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) 145 mem->accelerometer.entries[mem->accelerometer.index];
142 = VideoCore::g_emu_window->GetAccelerometerState(); 146 std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) =
147 VideoCore::g_emu_window->GetAccelerometerState();
143 148
144 // Make up "raw" entry 149 // Make up "raw" entry
145 // TODO(wwylele): 150 // TODO(wwylele):
@@ -167,8 +172,8 @@ void Update() {
167 next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size(); 172 next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size();
168 173
169 GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index]; 174 GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];
170 std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) 175 std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) =
171 = VideoCore::g_emu_window->GetGyroscopeState(); 176 VideoCore::g_emu_window->GetGyroscopeState();
172 177
173 // Make up "raw" entry 178 // Make up "raw" entry
174 mem->gyroscope.raw_entry.x = gyroscope_entry.x; 179 mem->gyroscope.raw_entry.x = gyroscope_entry.x;
@@ -188,7 +193,7 @@ void Update() {
188void GetIPCHandles(Service::Interface* self) { 193void GetIPCHandles(Service::Interface* self) {
189 u32* cmd_buff = Kernel::GetCommandBuffer(); 194 u32* cmd_buff = Kernel::GetCommandBuffer();
190 195
191 cmd_buff[1] = 0; // No error 196 cmd_buff[1] = 0; // No error
192 cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header 197 cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header
193 // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling) 198 // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling)
194 cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).MoveFrom(); 199 cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).MoveFrom();
@@ -259,9 +264,7 @@ void GetGyroscopeLowCalibrateParam(Service::Interface* self) {
259 264
260 const s16 param_unit = 6700; // an approximate value taken from hw 265 const s16 param_unit = 6700; // an approximate value taken from hw
261 GyroscopeCalibrateParam param = { 266 GyroscopeCalibrateParam param = {
262 { 0, param_unit, -param_unit }, 267 {0, param_unit, -param_unit}, {0, param_unit, -param_unit}, {0, param_unit, -param_unit},
263 { 0, param_unit, -param_unit },
264 { 0, param_unit, -param_unit },
265 }; 268 };
266 memcpy(&cmd_buff[2], &param, sizeof(param)); 269 memcpy(&cmd_buff[2], &param, sizeof(param));
267 270
@@ -286,9 +289,9 @@ void Init() {
286 AddService(new HID_SPVR_Interface); 289 AddService(new HID_SPVR_Interface);
287 290
288 using Kernel::MemoryPermission; 291 using Kernel::MemoryPermission;
289 shared_mem = SharedMemory::Create(nullptr, 0x1000, 292 shared_mem =
290 MemoryPermission::ReadWrite, MemoryPermission::Read, 293 SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read,
291 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); 294 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");
292 295
293 next_pad_index = 0; 296 next_pad_index = 0;
294 next_touch_index = 0; 297 next_touch_index = 0;
@@ -296,9 +299,9 @@ void Init() {
296 // Create event handles 299 // Create event handles
297 event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1"); 300 event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1");
298 event_pad_or_touch_2 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch2"); 301 event_pad_or_touch_2 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch2");
299 event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer"); 302 event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer");
300 event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope"); 303 event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope");
301 event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad"); 304 event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad");
302} 305}
303 306
304void Shutdown() { 307void Shutdown() {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 669b1f723..f54ffd8be 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -9,10 +9,10 @@
9#ifndef _MSC_VER 9#ifndef _MSC_VER
10#include <cstddef> 10#include <cstddef>
11#endif 11#endif
12#include "core/settings.h"
13#include "common/bit_field.h" 12#include "common/bit_field.h"
14#include "common/common_funcs.h" 13#include "common/common_funcs.h"
15#include "common/common_types.h" 14#include "common/common_types.h"
15#include "core/settings.h"
16 16
17namespace Service { 17namespace Service {
18 18
@@ -103,7 +103,7 @@ struct SharedMem {
103 struct { 103 struct {
104 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 104 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0
105 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` 105 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
106 u32 index; ///< Index of the last updated pad state entry 106 u32 index; ///< Index of the last updated pad state entry
107 107
108 INSERT_PADDING_WORDS(0x2); 108 INSERT_PADDING_WORDS(0x2);
109 109
@@ -121,7 +121,7 @@ struct SharedMem {
121 struct { 121 struct {
122 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 122 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0
123 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` 123 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
124 u32 index; ///< Index of the last updated touch entry 124 u32 index; ///< Index of the last updated touch entry
125 125
126 INSERT_PADDING_WORDS(0x1); 126 INSERT_PADDING_WORDS(0x1);
127 127
@@ -135,7 +135,7 @@ struct SharedMem {
135 struct { 135 struct {
136 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 136 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0
137 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` 137 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
138 u32 index; ///< Index of the last updated accelerometer entry 138 u32 index; ///< Index of the last updated accelerometer entry
139 139
140 INSERT_PADDING_WORDS(0x1); 140 INSERT_PADDING_WORDS(0x1);
141 141
@@ -149,7 +149,7 @@ struct SharedMem {
149 struct { 149 struct {
150 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 150 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0
151 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` 151 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
152 u32 index; ///< Index of the last updated accelerometer entry 152 u32 index; ///< Index of the last updated accelerometer entry
153 153
154 INSERT_PADDING_WORDS(0x1); 154 INSERT_PADDING_WORDS(0x1);
155 155
@@ -176,9 +176,9 @@ struct GyroscopeCalibrateParam {
176// is technically allowed since C++11. This macro should be enabled once MSVC adds 176// is technically allowed since C++11. This macro should be enabled once MSVC adds
177// support for that. 177// support for that.
178#ifndef _MSC_VER 178#ifndef _MSC_VER
179#define ASSERT_REG_POSITION(field_name, position) \ 179#define ASSERT_REG_POSITION(field_name, position) \
180 static_assert(offsetof(SharedMem, field_name) == position * 4, \ 180 static_assert(offsetof(SharedMem, field_name) == position * 4, \
181 "Field "#field_name" has invalid position") 181 "Field " #field_name " has invalid position")
182 182
183ASSERT_REG_POSITION(pad.index_reset_ticks, 0x0); 183ASSERT_REG_POSITION(pad.index_reset_ticks, 0x0);
184ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A); 184ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A);
@@ -187,33 +187,33 @@ ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A);
187#endif // !defined(_MSC_VER) 187#endif // !defined(_MSC_VER)
188 188
189// Pre-defined PadStates for single button presses 189// Pre-defined PadStates for single button presses
190const PadState PAD_NONE = {{0}}; 190const PadState PAD_NONE = {{0}};
191const PadState PAD_A = {{1u << 0}}; 191const PadState PAD_A = {{1u << 0}};
192const PadState PAD_B = {{1u << 1}}; 192const PadState PAD_B = {{1u << 1}};
193const PadState PAD_SELECT = {{1u << 2}}; 193const PadState PAD_SELECT = {{1u << 2}};
194const PadState PAD_START = {{1u << 3}}; 194const PadState PAD_START = {{1u << 3}};
195const PadState PAD_RIGHT = {{1u << 4}}; 195const PadState PAD_RIGHT = {{1u << 4}};
196const PadState PAD_LEFT = {{1u << 5}}; 196const PadState PAD_LEFT = {{1u << 5}};
197const PadState PAD_UP = {{1u << 6}}; 197const PadState PAD_UP = {{1u << 6}};
198const PadState PAD_DOWN = {{1u << 7}}; 198const PadState PAD_DOWN = {{1u << 7}};
199const PadState PAD_R = {{1u << 8}}; 199const PadState PAD_R = {{1u << 8}};
200const PadState PAD_L = {{1u << 9}}; 200const PadState PAD_L = {{1u << 9}};
201const PadState PAD_X = {{1u << 10}}; 201const PadState PAD_X = {{1u << 10}};
202const PadState PAD_Y = {{1u << 11}}; 202const PadState PAD_Y = {{1u << 11}};
203 203
204const PadState PAD_ZL = {{1u << 14}}; 204const PadState PAD_ZL = {{1u << 14}};
205const PadState PAD_ZR = {{1u << 15}}; 205const PadState PAD_ZR = {{1u << 15}};
206 206
207const PadState PAD_TOUCH = {{1u << 20}}; 207const PadState PAD_TOUCH = {{1u << 20}};
208 208
209const PadState PAD_C_RIGHT = {{1u << 24}}; 209const PadState PAD_C_RIGHT = {{1u << 24}};
210const PadState PAD_C_LEFT = {{1u << 25}}; 210const PadState PAD_C_LEFT = {{1u << 25}};
211const PadState PAD_C_UP = {{1u << 26}}; 211const PadState PAD_C_UP = {{1u << 26}};
212const PadState PAD_C_DOWN = {{1u << 27}}; 212const PadState PAD_C_DOWN = {{1u << 27}};
213const PadState PAD_CIRCLE_RIGHT = {{1u << 28}}; 213const PadState PAD_CIRCLE_RIGHT = {{1u << 28}};
214const PadState PAD_CIRCLE_LEFT = {{1u << 29}}; 214const PadState PAD_CIRCLE_LEFT = {{1u << 29}};
215const PadState PAD_CIRCLE_UP = {{1u << 30}}; 215const PadState PAD_CIRCLE_UP = {{1u << 30}};
216const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; 216const PadState PAD_CIRCLE_DOWN = {{1u << 31}};
217 217
218/** 218/**
219 * HID::GetIPCHandles service function 219 * HID::GetIPCHandles service function
@@ -305,6 +305,5 @@ void Init();
305 305
306/// Shutdown HID service 306/// Shutdown HID service
307void Shutdown(); 307void Shutdown();
308
309} 308}
310} 309}
diff --git a/src/core/hle/service/hid/hid_spvr.cpp b/src/core/hle/service/hid/hid_spvr.cpp
index 046e65b11..09007e304 100644
--- a/src/core/hle/service/hid/hid_spvr.cpp
+++ b/src/core/hle/service/hid/hid_spvr.cpp
@@ -9,16 +9,16 @@ namespace Service {
9namespace HID { 9namespace HID {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x000A0000, GetIPCHandles, "GetIPCHandles"}, 12 {0x000A0000, GetIPCHandles, "GetIPCHandles"},
13 {0x000B0000, nullptr, "StartAnalogStickCalibration"}, 13 {0x000B0000, nullptr, "StartAnalogStickCalibration"},
14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, 14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"},
15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, 15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"},
16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, 16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"},
17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, 17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"},
18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, 18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"},
19 {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, 19 {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"},
20 {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, 20 {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"},
21 {0x00170000, GetSoundVolume, "GetSoundVolume"}, 21 {0x00170000, GetSoundVolume, "GetSoundVolume"},
22}; 22};
23 23
24HID_SPVR_Interface::HID_SPVR_Interface() { 24HID_SPVR_Interface::HID_SPVR_Interface() {
diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp
index bb157b83d..42591543c 100644
--- a/src/core/hle/service/hid/hid_user.cpp
+++ b/src/core/hle/service/hid/hid_user.cpp
@@ -9,16 +9,16 @@ namespace Service {
9namespace HID { 9namespace HID {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x000A0000, GetIPCHandles, "GetIPCHandles"}, 12 {0x000A0000, GetIPCHandles, "GetIPCHandles"},
13 {0x000B0000, nullptr, "StartAnalogStickCalibration"}, 13 {0x000B0000, nullptr, "StartAnalogStickCalibration"},
14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, 14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"},
15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, 15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"},
16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, 16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"},
17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, 17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"},
18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, 18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"},
19 {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, 19 {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"},
20 {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, 20 {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"},
21 {0x00170000, GetSoundVolume, "GetSoundVolume"}, 21 {0x00170000, GetSoundVolume, "GetSoundVolume"},
22}; 22};
23 23
24HID_U_Interface::HID_U_Interface() { 24HID_U_Interface::HID_U_Interface() {
diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp
index 0855ab227..3cf62a4b8 100644
--- a/src/core/hle/service/http_c.cpp
+++ b/src/core/hle/service/http_c.cpp
@@ -10,56 +10,56 @@
10namespace HTTP_C { 10namespace HTTP_C {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {
13 {0x00010044, nullptr, "Initialize"}, 13 {0x00010044, nullptr, "Initialize"},
14 {0x00020082, nullptr, "CreateContext"}, 14 {0x00020082, nullptr, "CreateContext"},
15 {0x00030040, nullptr, "CloseContext"}, 15 {0x00030040, nullptr, "CloseContext"},
16 {0x00040040, nullptr, "CancelConnection"}, 16 {0x00040040, nullptr, "CancelConnection"},
17 {0x00050040, nullptr, "GetRequestState"}, 17 {0x00050040, nullptr, "GetRequestState"},
18 {0x00060040, nullptr, "GetDownloadSizeState"}, 18 {0x00060040, nullptr, "GetDownloadSizeState"},
19 {0x00070040, nullptr, "GetRequestError"}, 19 {0x00070040, nullptr, "GetRequestError"},
20 {0x00080042, nullptr, "InitializeConnectionSession"}, 20 {0x00080042, nullptr, "InitializeConnectionSession"},
21 {0x00090040, nullptr, "BeginRequest"}, 21 {0x00090040, nullptr, "BeginRequest"},
22 {0x000A0040, nullptr, "BeginRequestAsync"}, 22 {0x000A0040, nullptr, "BeginRequestAsync"},
23 {0x000B0082, nullptr, "ReceiveData"}, 23 {0x000B0082, nullptr, "ReceiveData"},
24 {0x000C0102, nullptr, "ReceiveDataTimeout"}, 24 {0x000C0102, nullptr, "ReceiveDataTimeout"},
25 {0x000D0146, nullptr, "SetProxy"}, 25 {0x000D0146, nullptr, "SetProxy"},
26 {0x000E0040, nullptr, "SetProxyDefault"}, 26 {0x000E0040, nullptr, "SetProxyDefault"},
27 {0x000F00C4, nullptr, "SetBasicAuthorization"}, 27 {0x000F00C4, nullptr, "SetBasicAuthorization"},
28 {0x00100080, nullptr, "SetSocketBufferSize"}, 28 {0x00100080, nullptr, "SetSocketBufferSize"},
29 {0x001100C4, nullptr, "AddRequestHeader"}, 29 {0x001100C4, nullptr, "AddRequestHeader"},
30 {0x001200C4, nullptr, "AddPostDataAscii"}, 30 {0x001200C4, nullptr, "AddPostDataAscii"},
31 {0x001300C4, nullptr, "AddPostDataBinary"}, 31 {0x001300C4, nullptr, "AddPostDataBinary"},
32 {0x00140082, nullptr, "AddPostDataRaw"}, 32 {0x00140082, nullptr, "AddPostDataRaw"},
33 {0x00150080, nullptr, "SetPostDataType"}, 33 {0x00150080, nullptr, "SetPostDataType"},
34 {0x001600C4, nullptr, "SendPostDataAscii"}, 34 {0x001600C4, nullptr, "SendPostDataAscii"},
35 {0x00170144, nullptr, "SendPostDataAsciiTimeout"}, 35 {0x00170144, nullptr, "SendPostDataAsciiTimeout"},
36 {0x001800C4, nullptr, "SendPostDataBinary"}, 36 {0x001800C4, nullptr, "SendPostDataBinary"},
37 {0x00190144, nullptr, "SendPostDataBinaryTimeout"}, 37 {0x00190144, nullptr, "SendPostDataBinaryTimeout"},
38 {0x001A0082, nullptr, "SendPostDataRaw"}, 38 {0x001A0082, nullptr, "SendPostDataRaw"},
39 {0x001B0102, nullptr, "SendPOSTDataRawTimeout"}, 39 {0x001B0102, nullptr, "SendPOSTDataRawTimeout"},
40 {0x001C0080, nullptr, "SetPostDataEncoding"}, 40 {0x001C0080, nullptr, "SetPostDataEncoding"},
41 {0x001D0040, nullptr, "NotifyFinishSendPostData"}, 41 {0x001D0040, nullptr, "NotifyFinishSendPostData"},
42 {0x001E00C4, nullptr, "GetResponseHeader"}, 42 {0x001E00C4, nullptr, "GetResponseHeader"},
43 {0x001F0144, nullptr, "GetResponseHeaderTimeout"}, 43 {0x001F0144, nullptr, "GetResponseHeaderTimeout"},
44 {0x00200082, nullptr, "GetResponseData"}, 44 {0x00200082, nullptr, "GetResponseData"},
45 {0x00210102, nullptr, "GetResponseDataTimeout"}, 45 {0x00210102, nullptr, "GetResponseDataTimeout"},
46 {0x00220040, nullptr, "GetResponseStatusCode"}, 46 {0x00220040, nullptr, "GetResponseStatusCode"},
47 {0x002300C0, nullptr, "GetResponseStatusCodeTimeout"}, 47 {0x002300C0, nullptr, "GetResponseStatusCodeTimeout"},
48 {0x00240082, nullptr, "AddTrustedRootCA"}, 48 {0x00240082, nullptr, "AddTrustedRootCA"},
49 {0x00250080, nullptr, "AddDefaultCert"}, 49 {0x00250080, nullptr, "AddDefaultCert"},
50 {0x00260080, nullptr, "SelectRootCertChain"}, 50 {0x00260080, nullptr, "SelectRootCertChain"},
51 {0x002700C4, nullptr, "SetClientCert"}, 51 {0x002700C4, nullptr, "SetClientCert"},
52 {0x002B0080, nullptr, "SetSSLOpt"}, 52 {0x002B0080, nullptr, "SetSSLOpt"},
53 {0x002C0080, nullptr, "SetSSLClearOpt"}, 53 {0x002C0080, nullptr, "SetSSLClearOpt"},
54 {0x002D0000, nullptr, "CreateRootCertChain"}, 54 {0x002D0000, nullptr, "CreateRootCertChain"},
55 {0x002E0040, nullptr, "DestroyRootCertChain"}, 55 {0x002E0040, nullptr, "DestroyRootCertChain"},
56 {0x002F0082, nullptr, "RootCertChainAddCert"}, 56 {0x002F0082, nullptr, "RootCertChainAddCert"},
57 {0x00300080, nullptr, "RootCertChainAddDefaultCert"}, 57 {0x00300080, nullptr, "RootCertChainAddDefaultCert"},
58 {0x00350186, nullptr, "SetDefaultProxy"}, 58 {0x00350186, nullptr, "SetDefaultProxy"},
59 {0x00360000, nullptr, "ClearDNSCache"}, 59 {0x00360000, nullptr, "ClearDNSCache"},
60 {0x00370080, nullptr, "SetKeepAlive"}, 60 {0x00370080, nullptr, "SetKeepAlive"},
61 {0x003800C0, nullptr, "SetPostDataTypeSize"}, 61 {0x003800C0, nullptr, "SetPostDataTypeSize"},
62 {0x00390000, nullptr, "Finalize"}, 62 {0x00390000, nullptr, "Finalize"},
63}; 63};
64 64
65//////////////////////////////////////////////////////////////////////////////////////////////////// 65////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ir/ir.cpp b/src/core/hle/service/ir/ir.cpp
index 079a87e48..fc048ae88 100644
--- a/src/core/hle/service/ir/ir.cpp
+++ b/src/core/hle/service/ir/ir.cpp
@@ -5,11 +5,11 @@
5#include "core/hle/kernel/event.h" 5#include "core/hle/kernel/event.h"
6#include "core/hle/kernel/shared_memory.h" 6#include "core/hle/kernel/shared_memory.h"
7 7
8#include "core/hle/service/service.h"
9#include "core/hle/service/ir/ir.h" 8#include "core/hle/service/ir/ir.h"
10#include "core/hle/service/ir/ir_rst.h" 9#include "core/hle/service/ir/ir_rst.h"
11#include "core/hle/service/ir/ir_u.h" 10#include "core/hle/service/ir/ir_u.h"
12#include "core/hle/service/ir/ir_user.h" 11#include "core/hle/service/ir/ir_user.h"
12#include "core/hle/service/service.h"
13 13
14namespace Service { 14namespace Service {
15namespace IR { 15namespace IR {
@@ -32,14 +32,14 @@ void InitializeIrNopShared(Interface* self) {
32 u32* cmd_buff = Kernel::GetCommandBuffer(); 32 u32* cmd_buff = Kernel::GetCommandBuffer();
33 33
34 u32 transfer_buff_size = cmd_buff[1]; 34 u32 transfer_buff_size = cmd_buff[1];
35 u32 recv_buff_size = cmd_buff[2]; 35 u32 recv_buff_size = cmd_buff[2];
36 u32 unk1 = cmd_buff[3]; 36 u32 unk1 = cmd_buff[3];
37 u32 send_buff_size = cmd_buff[4]; 37 u32 send_buff_size = cmd_buff[4];
38 u32 unk2 = cmd_buff[5]; 38 u32 unk2 = cmd_buff[5];
39 u8 baud_rate = cmd_buff[6] & 0xFF; 39 u8 baud_rate = cmd_buff[6] & 0xFF;
40 Handle handle = cmd_buff[8]; 40 Handle handle = cmd_buff[8];
41 41
42 if(Kernel::g_handle_table.IsValid(handle)) { 42 if (Kernel::g_handle_table.IsValid(handle)) {
43 transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle); 43 transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle);
44 transfer_shared_memory->name = "IR:TransferSharedMemory"; 44 transfer_shared_memory->name = "IR:TransferSharedMemory";
45 } 45 }
@@ -47,7 +47,7 @@ void InitializeIrNopShared(Interface* self) {
47 cmd_buff[1] = RESULT_SUCCESS.raw; 47 cmd_buff[1] = RESULT_SUCCESS.raw;
48 48
49 LOG_WARNING(Service_IR, "(STUBBED) called, transfer_buff_size=%d, recv_buff_size=%d, " 49 LOG_WARNING(Service_IR, "(STUBBED) called, transfer_buff_size=%d, recv_buff_size=%d, "
50 "unk1=%d, send_buff_size=%d, unk2=%d, baud_rate=%u, handle=0x%08X", 50 "unk1=%d, send_buff_size=%d, unk2=%d, baud_rate=%u, handle=0x%08X",
51 transfer_buff_size, recv_buff_size, unk1, send_buff_size, unk2, baud_rate, handle); 51 transfer_buff_size, recv_buff_size, unk1, send_buff_size, unk2, baud_rate, handle);
52} 52}
53 53
@@ -94,13 +94,13 @@ void Init() {
94 AddService(new IR_User_Interface); 94 AddService(new IR_User_Interface);
95 95
96 using Kernel::MemoryPermission; 96 using Kernel::MemoryPermission;
97 shared_memory = SharedMemory::Create(nullptr, 0x1000, 97 shared_memory = SharedMemory::Create(nullptr, 0x1000, Kernel::MemoryPermission::ReadWrite,
98 Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::ReadWrite, 98 Kernel::MemoryPermission::ReadWrite, 0,
99 0, Kernel::MemoryRegion::BASE, "IR:SharedMemory"); 99 Kernel::MemoryRegion::BASE, "IR:SharedMemory");
100 transfer_shared_memory = nullptr; 100 transfer_shared_memory = nullptr;
101 101
102 // Create event handle(s) 102 // Create event handle(s)
103 handle_event = Event::Create(ResetType::OneShot, "IR:HandleEvent"); 103 handle_event = Event::Create(ResetType::OneShot, "IR:HandleEvent");
104 conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent"); 104 conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent");
105} 105}
106 106
diff --git a/src/core/hle/service/ir/ir_rst.cpp b/src/core/hle/service/ir/ir_rst.cpp
index c0300f109..1f10ebd3d 100644
--- a/src/core/hle/service/ir/ir_rst.cpp
+++ b/src/core/hle/service/ir/ir_rst.cpp
@@ -9,10 +9,10 @@ namespace Service {
9namespace IR { 9namespace IR {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010000, GetHandles, "GetHandles"}, 12 {0x00010000, GetHandles, "GetHandles"},
13 {0x00020080, nullptr, "Initialize"}, 13 {0x00020080, nullptr, "Initialize"},
14 {0x00030000, nullptr, "Shutdown"}, 14 {0x00030000, nullptr, "Shutdown"},
15 {0x00090000, nullptr, "WriteToTwoFields"}, 15 {0x00090000, nullptr, "WriteToTwoFields"},
16}; 16};
17 17
18IR_RST_Interface::IR_RST_Interface() { 18IR_RST_Interface::IR_RST_Interface() {
diff --git a/src/core/hle/service/ir/ir_u.cpp b/src/core/hle/service/ir/ir_u.cpp
index 96f76cb83..be4049da9 100644
--- a/src/core/hle/service/ir/ir_u.cpp
+++ b/src/core/hle/service/ir/ir_u.cpp
@@ -8,24 +8,15 @@ namespace Service {
8namespace IR { 8namespace IR {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x00010000, nullptr, "Initialize"}, 11 {0x00010000, nullptr, "Initialize"}, {0x00020000, nullptr, "Shutdown"},
12 {0x00020000, nullptr, "Shutdown"}, 12 {0x00030042, nullptr, "StartSendTransfer"}, {0x00040000, nullptr, "WaitSendTransfer"},
13 {0x00030042, nullptr, "StartSendTransfer"}, 13 {0x000500C2, nullptr, "StartRecvTransfer"}, {0x00060000, nullptr, "WaitRecvTransfer"},
14 {0x00040000, nullptr, "WaitSendTransfer"}, 14 {0x00070080, nullptr, "GetRecvTransferCount"}, {0x00080000, nullptr, "GetSendState"},
15 {0x000500C2, nullptr, "StartRecvTransfer"}, 15 {0x00090040, nullptr, "SetBitRate"}, {0x000A0000, nullptr, "GetBitRate"},
16 {0x00060000, nullptr, "WaitRecvTransfer"}, 16 {0x000B0040, nullptr, "SetIRLEDState"}, {0x000C0000, nullptr, "GetIRLEDRecvState"},
17 {0x00070080, nullptr, "GetRecvTransferCount"}, 17 {0x000D0000, nullptr, "GetSendFinishedEvent"}, {0x000E0000, nullptr, "GetRecvFinishedEvent"},
18 {0x00080000, nullptr, "GetSendState"}, 18 {0x000F0000, nullptr, "GetTransferState"}, {0x00100000, nullptr, "GetErrorStatus"},
19 {0x00090040, nullptr, "SetBitRate"}, 19 {0x00110040, nullptr, "SetSleepModeActive"}, {0x00120040, nullptr, "SetSleepModeState"},
20 {0x000A0000, nullptr, "GetBitRate"},
21 {0x000B0040, nullptr, "SetIRLEDState"},
22 {0x000C0000, nullptr, "GetIRLEDRecvState"},
23 {0x000D0000, nullptr, "GetSendFinishedEvent"},
24 {0x000E0000, nullptr, "GetRecvFinishedEvent"},
25 {0x000F0000, nullptr, "GetTransferState"},
26 {0x00100000, nullptr, "GetErrorStatus"},
27 {0x00110040, nullptr, "SetSleepModeActive"},
28 {0x00120040, nullptr, "SetSleepModeState"},
29}; 20};
30 21
31IR_U_Interface::IR_U_Interface() { 22IR_U_Interface::IR_U_Interface() {
diff --git a/src/core/hle/service/ir/ir_user.cpp b/src/core/hle/service/ir/ir_user.cpp
index 06a601029..6cff1d544 100644
--- a/src/core/hle/service/ir/ir_user.cpp
+++ b/src/core/hle/service/ir/ir_user.cpp
@@ -9,32 +9,32 @@ namespace Service {
9namespace IR { 9namespace IR {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010182, nullptr, "InitializeIrNop"}, 12 {0x00010182, nullptr, "InitializeIrNop"},
13 {0x00020000, FinalizeIrNop, "FinalizeIrNop"}, 13 {0x00020000, FinalizeIrNop, "FinalizeIrNop"},
14 {0x00030000, nullptr, "ClearReceiveBuffer"}, 14 {0x00030000, nullptr, "ClearReceiveBuffer"},
15 {0x00040000, nullptr, "ClearSendBuffer"}, 15 {0x00040000, nullptr, "ClearSendBuffer"},
16 {0x000500C0, nullptr, "WaitConnection"}, 16 {0x000500C0, nullptr, "WaitConnection"},
17 {0x00060040, RequireConnection, "RequireConnection"}, 17 {0x00060040, RequireConnection, "RequireConnection"},
18 {0x000702C0, nullptr, "AutoConnection"}, 18 {0x000702C0, nullptr, "AutoConnection"},
19 {0x00080000, nullptr, "AnyConnection"}, 19 {0x00080000, nullptr, "AnyConnection"},
20 {0x00090000, Disconnect, "Disconnect"}, 20 {0x00090000, Disconnect, "Disconnect"},
21 {0x000A0000, nullptr, "GetReceiveEvent"}, 21 {0x000A0000, nullptr, "GetReceiveEvent"},
22 {0x000B0000, nullptr, "GetSendEvent"}, 22 {0x000B0000, nullptr, "GetSendEvent"},
23 {0x000C0000, GetConnectionStatusEvent, "GetConnectionStatusEvent"}, 23 {0x000C0000, GetConnectionStatusEvent, "GetConnectionStatusEvent"},
24 {0x000D0042, nullptr, "SendIrNop"}, 24 {0x000D0042, nullptr, "SendIrNop"},
25 {0x000E0042, nullptr, "SendIrNopLarge"}, 25 {0x000E0042, nullptr, "SendIrNopLarge"},
26 {0x000F0040, nullptr, "ReceiveIrnop"}, 26 {0x000F0040, nullptr, "ReceiveIrnop"},
27 {0x00100042, nullptr, "ReceiveIrnopLarge"}, 27 {0x00100042, nullptr, "ReceiveIrnopLarge"},
28 {0x00110040, nullptr, "GetLatestReceiveErrorResult"}, 28 {0x00110040, nullptr, "GetLatestReceiveErrorResult"},
29 {0x00120040, nullptr, "GetLatestSendErrorResult"}, 29 {0x00120040, nullptr, "GetLatestSendErrorResult"},
30 {0x00130000, nullptr, "GetConnectionStatus"}, 30 {0x00130000, nullptr, "GetConnectionStatus"},
31 {0x00140000, nullptr, "GetTryingToConnectStatus"}, 31 {0x00140000, nullptr, "GetTryingToConnectStatus"},
32 {0x00150000, nullptr, "GetReceiveSizeFreeAndUsed"}, 32 {0x00150000, nullptr, "GetReceiveSizeFreeAndUsed"},
33 {0x00160000, nullptr, "GetSendSizeFreeAndUsed"}, 33 {0x00160000, nullptr, "GetSendSizeFreeAndUsed"},
34 {0x00170000, nullptr, "GetConnectionRole"}, 34 {0x00170000, nullptr, "GetConnectionRole"},
35 {0x00180182, InitializeIrNopShared, "InitializeIrNopShared"}, 35 {0x00180182, InitializeIrNopShared, "InitializeIrNopShared"},
36 {0x00190040, nullptr, "ReleaseReceivedData"}, 36 {0x00190040, nullptr, "ReleaseReceivedData"},
37 {0x001A0040, nullptr, "SetOwnMachineId"}, 37 {0x001A0040, nullptr, "SetOwnMachineId"},
38}; 38};
39 39
40IR_User_Interface::IR_User_Interface() { 40IR_User_Interface::IR_User_Interface() {
diff --git a/src/core/hle/service/ldr_ro/cro_helper.cpp b/src/core/hle/service/ldr_ro/cro_helper.cpp
index 3d2a613ee..5757a4e64 100644
--- a/src/core/hle/service/ldr_ro/cro_helper.cpp
+++ b/src/core/hle/service/ldr_ro/cro_helper.cpp
@@ -14,38 +14,29 @@
14namespace LDR_RO { 14namespace LDR_RO {
15 15
16static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F 16static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F
17 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 17 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument,
18 ErrorLevel::Usage);
18 19
19static ResultCode CROFormatError(u32 description) { 20static ResultCode CROFormatError(u32 description) {
20 return ResultCode(static_cast<ErrorDescription>(description), ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 21 return ResultCode(static_cast<ErrorDescription>(description), ErrorModule::RO,
22 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
21} 23}
22 24
23const std::array<int, 17> CROHelper::ENTRY_SIZE {{ 25const std::array<int, 17> CROHelper::ENTRY_SIZE{
24 1, // code 26 {1, // code
25 1, // data 27 1, // data
26 1, // module name 28 1, // module name
27 sizeof(SegmentEntry), 29 sizeof(SegmentEntry), sizeof(ExportNamedSymbolEntry), sizeof(ExportIndexedSymbolEntry),
28 sizeof(ExportNamedSymbolEntry), 30 1, // export strings
29 sizeof(ExportIndexedSymbolEntry), 31 sizeof(ExportTreeEntry), sizeof(ImportModuleEntry), sizeof(ExternalRelocationEntry),
30 1, // export strings 32 sizeof(ImportNamedSymbolEntry), sizeof(ImportIndexedSymbolEntry),
31 sizeof(ExportTreeEntry), 33 sizeof(ImportAnonymousSymbolEntry),
32 sizeof(ImportModuleEntry), 34 1, // import strings
33 sizeof(ExternalRelocationEntry), 35 sizeof(StaticAnonymousSymbolEntry), sizeof(InternalRelocationEntry),
34 sizeof(ImportNamedSymbolEntry), 36 sizeof(StaticRelocationEntry)}};
35 sizeof(ImportIndexedSymbolEntry), 37
36 sizeof(ImportAnonymousSymbolEntry), 38const std::array<CROHelper::HeaderField, 4> CROHelper::FIX_BARRIERS{
37 1, // import strings 39 {Fix0Barrier, Fix1Barrier, Fix2Barrier, Fix3Barrier}};
38 sizeof(StaticAnonymousSymbolEntry),
39 sizeof(InternalRelocationEntry),
40 sizeof(StaticRelocationEntry)
41}};
42
43const std::array<CROHelper::HeaderField, 4> CROHelper::FIX_BARRIERS {{
44 Fix0Barrier,
45 Fix1Barrier,
46 Fix2Barrier,
47 Fix3Barrier
48}};
49 40
50VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const { 41VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const {
51 u32 segment_num = GetField(SegmentNum); 42 u32 segment_num = GetField(SegmentNum);
@@ -63,7 +54,7 @@ VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const {
63} 54}
64 55
65ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType relocation_type, 56ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType relocation_type,
66 u32 addend, u32 symbol_address, u32 target_future_address) { 57 u32 addend, u32 symbol_address, u32 target_future_address) {
67 58
68 switch (relocation_type) { 59 switch (relocation_type) {
69 case RelocationType::Nothing: 60 case RelocationType::Nothing:
@@ -124,7 +115,8 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool
124 return CROFormatError(0x12); 115 return CROFormatError(0x12);
125 } 116 }
126 117
127 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, symbol_address, relocation_target); 118 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend,
119 symbol_address, relocation_target);
128 if (result.IsError()) { 120 if (result.IsError()) {
129 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); 121 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
130 return result; 122 return result;
@@ -167,7 +159,7 @@ VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const {
167 159
168 if (test_byte >= len) { 160 if (test_byte >= len) {
169 next.raw = entry.left.raw; 161 next.raw = entry.left.raw;
170 } else if((name[test_byte] >> test_bit_in_byte) & 1) { 162 } else if ((name[test_byte] >> test_bit_in_byte) & 1) {
171 next.raw = entry.right.raw; 163 next.raw = entry.right.raw;
172 } else { 164 } else {
173 next.raw = entry.left.raw; 165 next.raw = entry.left.raw;
@@ -212,26 +204,13 @@ ResultCode CROHelper::RebaseHeader(u32 cro_size) {
212 return error; 204 return error;
213 205
214 // verifies that all offsets are in the correct order 206 // verifies that all offsets are in the correct order
215 constexpr std::array<HeaderField, 18> OFFSET_ORDER = {{ 207 constexpr std::array<HeaderField, 18> OFFSET_ORDER = {
216 CodeOffset, 208 {CodeOffset, ModuleNameOffset, SegmentTableOffset, ExportNamedSymbolTableOffset,
217 ModuleNameOffset, 209 ExportTreeTableOffset, ExportIndexedSymbolTableOffset, ExportStringsOffset,
218 SegmentTableOffset, 210 ImportModuleTableOffset, ExternalRelocationTableOffset, ImportNamedSymbolTableOffset,
219 ExportNamedSymbolTableOffset, 211 ImportIndexedSymbolTableOffset, ImportAnonymousSymbolTableOffset, ImportStringsOffset,
220 ExportTreeTableOffset, 212 StaticAnonymousSymbolTableOffset, InternalRelocationTableOffset,
221 ExportIndexedSymbolTableOffset, 213 StaticRelocationTableOffset, DataOffset, FileSize}};
222 ExportStringsOffset,
223 ImportModuleTableOffset,
224 ExternalRelocationTableOffset,
225 ImportNamedSymbolTableOffset,
226 ImportIndexedSymbolTableOffset,
227 ImportAnonymousSymbolTableOffset,
228 ImportStringsOffset,
229 StaticAnonymousSymbolTableOffset,
230 InternalRelocationTableOffset,
231 StaticRelocationTableOffset,
232 DataOffset,
233 FileSize
234 }};
235 214
236 u32 prev_offset = GetField(OFFSET_ORDER[0]); 215 u32 prev_offset = GetField(OFFSET_ORDER[0]);
237 u32 cur_offset; 216 u32 cur_offset;
@@ -266,9 +245,9 @@ ResultCode CROHelper::RebaseHeader(u32 cro_size) {
266 return RESULT_SUCCESS; 245 return RESULT_SUCCESS;
267} 246}
268 247
269ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, 248ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, VAddr data_segment_address,
270 VAddr data_segment_address, u32 data_segment_size, 249 u32 data_segment_size, VAddr bss_segment_address,
271 VAddr bss_segment_address, u32 bss_segment_size) { 250 u32 bss_segment_size) {
272 251
273 u32 prev_data_segment = 0; 252 u32 prev_data_segment = 0;
274 u32 segment_num = GetField(SegmentNum); 253 u32 segment_num = GetField(SegmentNum);
@@ -309,8 +288,8 @@ ResultCode CROHelper::RebaseExportNamedSymbolTable() {
309 288
310 if (entry.name_offset != 0) { 289 if (entry.name_offset != 0) {
311 entry.name_offset += module_address; 290 entry.name_offset += module_address;
312 if (entry.name_offset < export_strings_offset 291 if (entry.name_offset < export_strings_offset ||
313 || entry.name_offset >= export_strings_end) { 292 entry.name_offset >= export_strings_end) {
314 return CROFormatError(0x11); 293 return CROFormatError(0x11);
315 } 294 }
316 } 295 }
@@ -337,9 +316,13 @@ ResultCode CROHelper::RebaseImportModuleTable() {
337 VAddr import_strings_offset = GetField(ImportStringsOffset); 316 VAddr import_strings_offset = GetField(ImportStringsOffset);
338 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); 317 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize);
339 VAddr import_indexed_symbol_table_offset = GetField(ImportIndexedSymbolTableOffset); 318 VAddr import_indexed_symbol_table_offset = GetField(ImportIndexedSymbolTableOffset);
340 VAddr index_import_table_end = import_indexed_symbol_table_offset + GetField(ImportIndexedSymbolNum) * sizeof(ImportIndexedSymbolEntry); 319 VAddr index_import_table_end =
320 import_indexed_symbol_table_offset +
321 GetField(ImportIndexedSymbolNum) * sizeof(ImportIndexedSymbolEntry);
341 VAddr import_anonymous_symbol_table_offset = GetField(ImportAnonymousSymbolTableOffset); 322 VAddr import_anonymous_symbol_table_offset = GetField(ImportAnonymousSymbolTableOffset);
342 VAddr offset_import_table_end = import_anonymous_symbol_table_offset + GetField(ImportAnonymousSymbolNum) * sizeof(ImportAnonymousSymbolEntry); 323 VAddr offset_import_table_end =
324 import_anonymous_symbol_table_offset +
325 GetField(ImportAnonymousSymbolNum) * sizeof(ImportAnonymousSymbolEntry);
343 326
344 u32 module_num = GetField(ImportModuleNum); 327 u32 module_num = GetField(ImportModuleNum);
345 for (u32 i = 0; i < module_num; ++i) { 328 for (u32 i = 0; i < module_num; ++i) {
@@ -348,24 +331,24 @@ ResultCode CROHelper::RebaseImportModuleTable() {
348 331
349 if (entry.name_offset != 0) { 332 if (entry.name_offset != 0) {
350 entry.name_offset += module_address; 333 entry.name_offset += module_address;
351 if (entry.name_offset < import_strings_offset 334 if (entry.name_offset < import_strings_offset ||
352 || entry.name_offset >= import_strings_end) { 335 entry.name_offset >= import_strings_end) {
353 return CROFormatError(0x18); 336 return CROFormatError(0x18);
354 } 337 }
355 } 338 }
356 339
357 if (entry.import_indexed_symbol_table_offset != 0) { 340 if (entry.import_indexed_symbol_table_offset != 0) {
358 entry.import_indexed_symbol_table_offset += module_address; 341 entry.import_indexed_symbol_table_offset += module_address;
359 if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset 342 if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset ||
360 || entry.import_indexed_symbol_table_offset > index_import_table_end) { 343 entry.import_indexed_symbol_table_offset > index_import_table_end) {
361 return CROFormatError(0x18); 344 return CROFormatError(0x18);
362 } 345 }
363 } 346 }
364 347
365 if (entry.import_anonymous_symbol_table_offset != 0) { 348 if (entry.import_anonymous_symbol_table_offset != 0) {
366 entry.import_anonymous_symbol_table_offset += module_address; 349 entry.import_anonymous_symbol_table_offset += module_address;
367 if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset 350 if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset ||
368 || entry.import_anonymous_symbol_table_offset > offset_import_table_end) { 351 entry.import_anonymous_symbol_table_offset > offset_import_table_end) {
369 return CROFormatError(0x18); 352 return CROFormatError(0x18);
370 } 353 }
371 } 354 }
@@ -379,25 +362,27 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() {
379 VAddr import_strings_offset = GetField(ImportStringsOffset); 362 VAddr import_strings_offset = GetField(ImportStringsOffset);
380 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); 363 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize);
381 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); 364 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset);
382 VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); 365 VAddr external_relocation_table_end =
366 external_relocation_table_offset +
367 GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
383 368
384 u32 num = GetField(ImportNamedSymbolNum); 369 u32 num = GetField(ImportNamedSymbolNum);
385 for (u32 i = 0; i < num ; ++i) { 370 for (u32 i = 0; i < num; ++i) {
386 ImportNamedSymbolEntry entry; 371 ImportNamedSymbolEntry entry;
387 GetEntry(i, entry); 372 GetEntry(i, entry);
388 373
389 if (entry.name_offset != 0) { 374 if (entry.name_offset != 0) {
390 entry.name_offset += module_address; 375 entry.name_offset += module_address;
391 if (entry.name_offset < import_strings_offset 376 if (entry.name_offset < import_strings_offset ||
392 || entry.name_offset >= import_strings_end) { 377 entry.name_offset >= import_strings_end) {
393 return CROFormatError(0x1B); 378 return CROFormatError(0x1B);
394 } 379 }
395 } 380 }
396 381
397 if (entry.relocation_batch_offset != 0) { 382 if (entry.relocation_batch_offset != 0) {
398 entry.relocation_batch_offset += module_address; 383 entry.relocation_batch_offset += module_address;
399 if (entry.relocation_batch_offset < external_relocation_table_offset 384 if (entry.relocation_batch_offset < external_relocation_table_offset ||
400 || entry.relocation_batch_offset > external_relocation_table_end) { 385 entry.relocation_batch_offset > external_relocation_table_end) {
401 return CROFormatError(0x1B); 386 return CROFormatError(0x1B);
402 } 387 }
403 } 388 }
@@ -409,17 +394,19 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() {
409 394
410ResultCode CROHelper::RebaseImportIndexedSymbolTable() { 395ResultCode CROHelper::RebaseImportIndexedSymbolTable() {
411 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); 396 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset);
412 VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); 397 VAddr external_relocation_table_end =
398 external_relocation_table_offset +
399 GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
413 400
414 u32 num = GetField(ImportIndexedSymbolNum); 401 u32 num = GetField(ImportIndexedSymbolNum);
415 for (u32 i = 0; i < num ; ++i) { 402 for (u32 i = 0; i < num; ++i) {
416 ImportIndexedSymbolEntry entry; 403 ImportIndexedSymbolEntry entry;
417 GetEntry(i, entry); 404 GetEntry(i, entry);
418 405
419 if (entry.relocation_batch_offset != 0) { 406 if (entry.relocation_batch_offset != 0) {
420 entry.relocation_batch_offset += module_address; 407 entry.relocation_batch_offset += module_address;
421 if (entry.relocation_batch_offset < external_relocation_table_offset 408 if (entry.relocation_batch_offset < external_relocation_table_offset ||
422 || entry.relocation_batch_offset > external_relocation_table_end) { 409 entry.relocation_batch_offset > external_relocation_table_end) {
423 return CROFormatError(0x14); 410 return CROFormatError(0x14);
424 } 411 }
425 } 412 }
@@ -431,17 +418,19 @@ ResultCode CROHelper::RebaseImportIndexedSymbolTable() {
431 418
432ResultCode CROHelper::RebaseImportAnonymousSymbolTable() { 419ResultCode CROHelper::RebaseImportAnonymousSymbolTable() {
433 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); 420 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset);
434 VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); 421 VAddr external_relocation_table_end =
422 external_relocation_table_offset +
423 GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
435 424
436 u32 num = GetField(ImportAnonymousSymbolNum); 425 u32 num = GetField(ImportAnonymousSymbolNum);
437 for (u32 i = 0; i < num ; ++i) { 426 for (u32 i = 0; i < num; ++i) {
438 ImportAnonymousSymbolEntry entry; 427 ImportAnonymousSymbolEntry entry;
439 GetEntry(i, entry); 428 GetEntry(i, entry);
440 429
441 if (entry.relocation_batch_offset != 0) { 430 if (entry.relocation_batch_offset != 0) {
442 entry.relocation_batch_offset += module_address; 431 entry.relocation_batch_offset += module_address;
443 if (entry.relocation_batch_offset < external_relocation_table_offset 432 if (entry.relocation_batch_offset < external_relocation_table_offset ||
444 || entry.relocation_batch_offset > external_relocation_table_end) { 433 entry.relocation_batch_offset > external_relocation_table_end) {
445 return CROFormatError(0x17); 434 return CROFormatError(0x17);
446 } 435 }
447 } 436 }
@@ -475,7 +464,8 @@ ResultCode CROHelper::ResetExternalRelocations() {
475 return CROFormatError(0x12); 464 return CROFormatError(0x12);
476 } 465 }
477 466
478 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, unresolved_symbol, relocation_target); 467 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend,
468 unresolved_symbol, relocation_target);
479 if (result.IsError()) { 469 if (result.IsError()) {
480 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); 470 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
481 return result; 471 return result;
@@ -528,23 +518,27 @@ ResultCode CROHelper::ClearExternalRelocations() {
528 518
529ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) { 519ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) {
530 VAddr static_relocation_table_offset = GetField(StaticRelocationTableOffset); 520 VAddr static_relocation_table_offset = GetField(StaticRelocationTableOffset);
531 VAddr static_relocation_table_end = static_relocation_table_offset + GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); 521 VAddr static_relocation_table_end =
522 static_relocation_table_offset +
523 GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry);
532 524
533 CROHelper crs(crs_address); 525 CROHelper crs(crs_address);
534 u32 offset_export_num = GetField(StaticAnonymousSymbolNum); 526 u32 offset_export_num = GetField(StaticAnonymousSymbolNum);
535 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d static anonymous symbols", ModuleName().data(), offset_export_num); 527 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d static anonymous symbols", ModuleName().data(),
528 offset_export_num);
536 for (u32 i = 0; i < offset_export_num; ++i) { 529 for (u32 i = 0; i < offset_export_num; ++i) {
537 StaticAnonymousSymbolEntry entry; 530 StaticAnonymousSymbolEntry entry;
538 GetEntry(i, entry); 531 GetEntry(i, entry);
539 u32 batch_address = entry.relocation_batch_offset + module_address; 532 u32 batch_address = entry.relocation_batch_offset + module_address;
540 533
541 if (batch_address < static_relocation_table_offset 534 if (batch_address < static_relocation_table_offset ||
542 || batch_address > static_relocation_table_end) { 535 batch_address > static_relocation_table_end) {
543 return CROFormatError(0x16); 536 return CROFormatError(0x16);
544 } 537 }
545 538
546 u32 symbol_address = SegmentTagToAddress(entry.symbol_position); 539 u32 symbol_address = SegmentTagToAddress(entry.symbol_position);
547 LOG_TRACE(Service_LDR, "CRO \"%s\" exports 0x%08X to the static module", ModuleName().data(), symbol_address); 540 LOG_TRACE(Service_LDR, "CRO \"%s\" exports 0x%08X to the static module",
541 ModuleName().data(), symbol_address);
548 ResultCode result = crs.ApplyRelocationBatch(batch_address, symbol_address); 542 ResultCode result = crs.ApplyRelocationBatch(batch_address, symbol_address);
549 if (result.IsError()) { 543 if (result.IsError()) {
550 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 544 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
@@ -571,7 +565,8 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) {
571 565
572 if (target_segment.type == SegmentType::Data) { 566 if (target_segment.type == SegmentType::Data) {
573 // If the relocation is to the .data segment, we need to relocate it in the old buffer 567 // If the relocation is to the .data segment, we need to relocate it in the old buffer
574 target_address = old_data_segment_address + relocation.target_position.offset_into_segment; 568 target_address =
569 old_data_segment_address + relocation.target_position.offset_into_segment;
575 } else { 570 } else {
576 target_address = target_addressB; 571 target_address = target_addressB;
577 } 572 }
@@ -582,8 +577,10 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) {
582 577
583 SegmentEntry symbol_segment; 578 SegmentEntry symbol_segment;
584 GetEntry(relocation.symbol_segment, symbol_segment); 579 GetEntry(relocation.symbol_segment, symbol_segment);
585 LOG_TRACE(Service_LDR, "Internally relocates 0x%08X with 0x%08X", target_address, symbol_segment.offset); 580 LOG_TRACE(Service_LDR, "Internally relocates 0x%08X with 0x%08X", target_address,
586 ResultCode result = ApplyRelocation(target_address, relocation.type, relocation.addend, symbol_segment.offset, target_addressB); 581 symbol_segment.offset);
582 ResultCode result = ApplyRelocation(target_address, relocation.type, relocation.addend,
583 symbol_segment.offset, target_addressB);
587 if (result.IsError()) { 584 if (result.IsError()) {
588 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); 585 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
589 return result; 586 return result;
@@ -734,25 +731,29 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) {
734 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 731 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
735 732
736 if (!relocation_entry.is_batch_resolved) { 733 if (!relocation_entry.is_batch_resolved) {
737 ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { 734 ResultCode result =
738 std::string symbol_name = Memory::ReadCString(entry.name_offset, import_strings_size); 735 ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> {
739 u32 symbol_address = source.FindExportNamedSymbol(symbol_name); 736 std::string symbol_name =
740 737 Memory::ReadCString(entry.name_offset, import_strings_size);
741 if (symbol_address != 0) { 738 u32 symbol_address = source.FindExportNamedSymbol(symbol_name);
742 LOG_TRACE(Service_LDR, "CRO \"%s\" imports \"%s\" from \"%s\"", 739
743 ModuleName().data(), symbol_name.data(), source.ModuleName().data()); 740 if (symbol_address != 0) {
744 741 LOG_TRACE(Service_LDR, "CRO \"%s\" imports \"%s\" from \"%s\"",
745 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); 742 ModuleName().data(), symbol_name.data(),
746 if (result.IsError()) { 743 source.ModuleName().data());
747 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 744
748 return result; 745 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address);
746 if (result.IsError()) {
747 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
748 result.raw);
749 return result;
750 }
751
752 return MakeResult<bool>(false);
749 } 753 }
750 754
751 return MakeResult<bool>(false); 755 return MakeResult<bool>(true);
752 } 756 });
753
754 return MakeResult<bool>(true);
755 });
756 if (result.IsError()) { 757 if (result.IsError()) {
757 return result; 758 return result;
758 } 759 }
@@ -777,7 +778,6 @@ ResultCode CROHelper::ResetImportNamedSymbol() {
777 LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw); 778 LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw);
778 return result; 779 return result;
779 } 780 }
780
781 } 781 }
782 return RESULT_SUCCESS; 782 return RESULT_SUCCESS;
783} 783}
@@ -831,40 +831,47 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
831 GetEntry(i, entry); 831 GetEntry(i, entry);
832 std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size); 832 std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size);
833 833
834 ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { 834 ResultCode result =
835 if (want_cro_name == source.ModuleName()) { 835 ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> {
836 LOG_INFO(Service_LDR, "CRO \"%s\" imports %d indexed symbols from \"%s\"", 836 if (want_cro_name == source.ModuleName()) {
837 ModuleName().data(), entry.import_indexed_symbol_num, source.ModuleName().data()); 837 LOG_INFO(Service_LDR, "CRO \"%s\" imports %d indexed symbols from \"%s\"",
838 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { 838 ModuleName().data(), entry.import_indexed_symbol_num,
839 ImportIndexedSymbolEntry im; 839 source.ModuleName().data());
840 entry.GetImportIndexedSymbolEntry(j, im); 840 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
841 ExportIndexedSymbolEntry ex; 841 ImportIndexedSymbolEntry im;
842 source.GetEntry(im.index, ex); 842 entry.GetImportIndexedSymbolEntry(j, im);
843 u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position); 843 ExportIndexedSymbolEntry ex;
844 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); 844 source.GetEntry(im.index, ex);
845 ResultCode result = ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 845 u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position);
846 if (result.IsError()) { 846 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address);
847 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 847 ResultCode result =
848 return result; 848 ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
849 if (result.IsError()) {
850 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
851 result.raw);
852 return result;
853 }
849 } 854 }
850 } 855 LOG_INFO(Service_LDR, "CRO \"%s\" imports %d anonymous symbols from \"%s\"",
851 LOG_INFO(Service_LDR, "CRO \"%s\" imports %d anonymous symbols from \"%s\"", 856 ModuleName().data(), entry.import_anonymous_symbol_num,
852 ModuleName().data(), entry.import_anonymous_symbol_num, source.ModuleName().data()); 857 source.ModuleName().data());
853 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { 858 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
854 ImportAnonymousSymbolEntry im; 859 ImportAnonymousSymbolEntry im;
855 entry.GetImportAnonymousSymbolEntry(j, im); 860 entry.GetImportAnonymousSymbolEntry(j, im);
856 u32 symbol_address = source.SegmentTagToAddress(im.symbol_position); 861 u32 symbol_address = source.SegmentTagToAddress(im.symbol_position);
857 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); 862 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address);
858 ResultCode result = ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 863 ResultCode result =
859 if (result.IsError()) { 864 ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
860 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 865 if (result.IsError()) {
861 return result; 866 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
867 result.raw);
868 return result;
869 }
862 } 870 }
871 return MakeResult<bool>(false);
863 } 872 }
864 return MakeResult<bool>(false); 873 return MakeResult<bool>(true);
865 } 874 });
866 return MakeResult<bool>(true);
867 });
868 if (result.IsError()) { 875 if (result.IsError()) {
869 return result; 876 return result;
870 } 877 }
@@ -873,8 +880,8 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
873} 880}
874 881
875ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { 882ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
876 LOG_DEBUG(Service_LDR, "CRO \"%s\" exports named symbols to \"%s\"", 883 LOG_DEBUG(Service_LDR, "CRO \"%s\" exports named symbols to \"%s\"", ModuleName().data(),
877 ModuleName().data(), target.ModuleName().data()); 884 target.ModuleName().data());
878 u32 target_import_strings_size = target.GetField(ImportStringsSize); 885 u32 target_import_strings_size = target.GetField(ImportStringsSize);
879 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); 886 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum);
880 for (u32 i = 0; i < target_symbol_import_num; ++i) { 887 for (u32 i = 0; i < target_symbol_import_num; ++i) {
@@ -885,7 +892,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
885 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 892 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
886 893
887 if (!relocation_entry.is_batch_resolved) { 894 if (!relocation_entry.is_batch_resolved) {
888 std::string symbol_name = Memory::ReadCString(entry.name_offset, target_import_strings_size); 895 std::string symbol_name =
896 Memory::ReadCString(entry.name_offset, target_import_strings_size);
889 u32 symbol_address = FindExportNamedSymbol(symbol_name); 897 u32 symbol_address = FindExportNamedSymbol(symbol_name);
890 if (symbol_address != 0) { 898 if (symbol_address != 0) {
891 LOG_TRACE(Service_LDR, " exports symbol \"%s\"", symbol_name.data()); 899 LOG_TRACE(Service_LDR, " exports symbol \"%s\"", symbol_name.data());
@@ -901,8 +909,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
901} 909}
902 910
903ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) { 911ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) {
904 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"", 912 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"", ModuleName().data(),
905 ModuleName().data(), target.ModuleName().data()); 913 target.ModuleName().data());
906 u32 unresolved_symbol = target.GetOnUnresolvedAddress(); 914 u32 unresolved_symbol = target.GetOnUnresolvedAddress();
907 u32 target_import_strings_size = target.GetField(ImportStringsSize); 915 u32 target_import_strings_size = target.GetField(ImportStringsSize);
908 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); 916 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum);
@@ -914,11 +922,13 @@ ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) {
914 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 922 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
915 923
916 if (relocation_entry.is_batch_resolved) { 924 if (relocation_entry.is_batch_resolved) {
917 std::string symbol_name = Memory::ReadCString(entry.name_offset, target_import_strings_size); 925 std::string symbol_name =
926 Memory::ReadCString(entry.name_offset, target_import_strings_size);
918 u32 symbol_address = FindExportNamedSymbol(symbol_name); 927 u32 symbol_address = FindExportNamedSymbol(symbol_name);
919 if (symbol_address != 0) { 928 if (symbol_address != 0) {
920 LOG_TRACE(Service_LDR, " unexports symbol \"%s\"", symbol_name.data()); 929 LOG_TRACE(Service_LDR, " unexports symbol \"%s\"", symbol_name.data());
921 ResultCode result = target.ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); 930 ResultCode result =
931 target.ApplyRelocationBatch(relocation_addr, unresolved_symbol, true);
922 if (result.IsError()) { 932 if (result.IsError()) {
923 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 933 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
924 return result; 934 return result;
@@ -940,8 +950,8 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
940 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) 950 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name)
941 continue; 951 continue;
942 952
943 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d indexed symbols to \"%s\"", 953 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d indexed symbols to \"%s\"", module_name.data(),
944 module_name.data(), entry.import_indexed_symbol_num, target.ModuleName().data()); 954 entry.import_indexed_symbol_num, target.ModuleName().data());
945 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { 955 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
946 ImportIndexedSymbolEntry im; 956 ImportIndexedSymbolEntry im;
947 entry.GetImportIndexedSymbolEntry(j, im); 957 entry.GetImportIndexedSymbolEntry(j, im);
@@ -949,7 +959,8 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
949 GetEntry(im.index, ex); 959 GetEntry(im.index, ex);
950 u32 symbol_address = SegmentTagToAddress(ex.symbol_position); 960 u32 symbol_address = SegmentTagToAddress(ex.symbol_position);
951 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); 961 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address);
952 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 962 ResultCode result =
963 target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
953 if (result.IsError()) { 964 if (result.IsError()) {
954 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 965 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
955 return result; 966 return result;
@@ -957,13 +968,14 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
957 } 968 }
958 969
959 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d anonymous symbols to \"%s\"", 970 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d anonymous symbols to \"%s\"",
960 module_name.data(), entry.import_anonymous_symbol_num, target.ModuleName().data()); 971 module_name.data(), entry.import_anonymous_symbol_num, target.ModuleName().data());
961 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { 972 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
962 ImportAnonymousSymbolEntry im; 973 ImportAnonymousSymbolEntry im;
963 entry.GetImportAnonymousSymbolEntry(j, im); 974 entry.GetImportAnonymousSymbolEntry(j, im);
964 u32 symbol_address = SegmentTagToAddress(im.symbol_position); 975 u32 symbol_address = SegmentTagToAddress(im.symbol_position);
965 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); 976 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address);
966 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 977 ResultCode result =
978 target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
967 if (result.IsError()) { 979 if (result.IsError()) {
968 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 980 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
969 return result; 981 return result;
@@ -987,12 +999,13 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
987 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) 999 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name)
988 continue; 1000 continue;
989 1001
990 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports indexed symbols to \"%s\"", 1002 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports indexed symbols to \"%s\"", module_name.data(),
991 module_name.data(), target.ModuleName().data()); 1003 target.ModuleName().data());
992 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { 1004 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
993 ImportIndexedSymbolEntry im; 1005 ImportIndexedSymbolEntry im;
994 entry.GetImportIndexedSymbolEntry(j, im); 1006 entry.GetImportIndexedSymbolEntry(j, im);
995 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); 1007 ResultCode result =
1008 target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true);
996 if (result.IsError()) { 1009 if (result.IsError()) {
997 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 1010 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
998 return result; 1011 return result;
@@ -1000,11 +1013,12 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
1000 } 1013 }
1001 1014
1002 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"", 1015 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"",
1003 module_name.data(), target.ModuleName().data()); 1016 module_name.data(), target.ModuleName().data());
1004 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { 1017 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
1005 ImportAnonymousSymbolEntry im; 1018 ImportAnonymousSymbolEntry im;
1006 entry.GetImportAnonymousSymbolEntry(j, im); 1019 entry.GetImportAnonymousSymbolEntry(j, im);
1007 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); 1020 ResultCode result =
1021 target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true);
1008 if (result.IsError()) { 1022 if (result.IsError()) {
1009 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 1023 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
1010 return result; 1024 return result;
@@ -1025,25 +1039,27 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) {
1025 ExternalRelocationEntry relocation_entry; 1039 ExternalRelocationEntry relocation_entry;
1026 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 1040 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
1027 1041
1028 if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit"){ 1042 if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") {
1029 ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { 1043 ResultCode result =
1030 u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); 1044 ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> {
1045 u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_");
1031 1046
1032 if (symbol_address != 0) { 1047 if (symbol_address != 0) {
1033 LOG_DEBUG(Service_LDR, "CRO \"%s\" import exit function from \"%s\"", 1048 LOG_DEBUG(Service_LDR, "CRO \"%s\" import exit function from \"%s\"",
1034 ModuleName().data(), source.ModuleName().data()); 1049 ModuleName().data(), source.ModuleName().data());
1035 1050
1036 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); 1051 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address);
1037 if (result.IsError()) { 1052 if (result.IsError()) {
1038 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 1053 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
1039 return result; 1054 result.raw);
1040 } 1055 return result;
1056 }
1041 1057
1042 return MakeResult<bool>(false); 1058 return MakeResult<bool>(false);
1043 } 1059 }
1044 1060
1045 return MakeResult<bool>(true); 1061 return MakeResult<bool>(true);
1046 }); 1062 });
1047 if (result.IsError()) { 1063 if (result.IsError()) {
1048 LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw); 1064 LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw);
1049 return result; 1065 return result;
@@ -1070,9 +1086,9 @@ static ResultCode VerifyStringTableLength(VAddr address, u32 size) {
1070 return RESULT_SUCCESS; 1086 return RESULT_SUCCESS;
1071} 1087}
1072 1088
1073ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, 1089ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment_addresss,
1074 VAddr data_segment_addresss, u32 data_segment_size, 1090 u32 data_segment_size, VAddr bss_segment_address, u32 bss_segment_size,
1075 VAddr bss_segment_address, u32 bss_segment_size, bool is_crs) { 1091 bool is_crs) {
1076 1092
1077 ResultCode result = RebaseHeader(cro_size); 1093 ResultCode result = RebaseHeader(cro_size);
1078 if (result.IsError()) { 1094 if (result.IsError()) {
@@ -1088,9 +1104,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size,
1088 1104
1089 u32 prev_data_segment_address = 0; 1105 u32 prev_data_segment_address = 0;
1090 if (!is_crs) { 1106 if (!is_crs) {
1091 auto result_val = RebaseSegmentTable(cro_size, 1107 auto result_val = RebaseSegmentTable(cro_size, data_segment_addresss, data_segment_size,
1092 data_segment_addresss, data_segment_size, 1108 bss_segment_address, bss_segment_size);
1093 bss_segment_address, bss_segment_size);
1094 if (result_val.Failed()) { 1109 if (result_val.Failed()) {
1095 LOG_ERROR(Service_LDR, "Error rebasing segment table %08X", result_val.Code().raw); 1110 LOG_ERROR(Service_LDR, "Error rebasing segment table %08X", result_val.Code().raw);
1096 return result_val.Code(); 1111 return result_val.Code();
@@ -1374,7 +1389,8 @@ void CROHelper::Unregister(VAddr crs_address) {
1374 CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule()); 1389 CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule());
1375 CROHelper next(NextModule()), previous(PreviousModule()); 1390 CROHelper next(NextModule()), previous(PreviousModule());
1376 1391
1377 if (module_address == next_head.module_address || module_address == previous_head.module_address) { 1392 if (module_address == next_head.module_address ||
1393 module_address == previous_head.module_address) {
1378 // removing head 1394 // removing head
1379 if (next.module_address) { 1395 if (next.module_address) {
1380 // the next is new head 1396 // the next is new head
@@ -1400,7 +1416,8 @@ void CROHelper::Unregister(VAddr crs_address) {
1400 // let head's previous point to the new tail 1416 // let head's previous point to the new tail
1401 if (next_head.module_address && next_head.PreviousModule() == module_address) { 1417 if (next_head.module_address && next_head.PreviousModule() == module_address) {
1402 next_head.SetPreviousModule(previous.module_address); 1418 next_head.SetPreviousModule(previous.module_address);
1403 } else if (previous_head.module_address && previous_head.PreviousModule() == module_address) { 1419 } else if (previous_head.module_address &&
1420 previous_head.PreviousModule() == module_address) {
1404 previous_head.SetPreviousModule(previous.module_address); 1421 previous_head.SetPreviousModule(previous.module_address);
1405 } else { 1422 } else {
1406 UNREACHABLE(); 1423 UNREACHABLE();
@@ -1419,9 +1436,9 @@ u32 CROHelper::GetFixEnd(u32 fix_level) const {
1419 u32 entry_size_i = 2; 1436 u32 entry_size_i = 2;
1420 int field = ModuleNameOffset; 1437 int field = ModuleNameOffset;
1421 while (true) { 1438 while (true) {
1422 end = std::max<u32>(end, 1439 end = std::max<u32>(end, GetField(static_cast<HeaderField>(field)) +
1423 GetField(static_cast<HeaderField>(field)) + 1440 GetField(static_cast<HeaderField>(field + 1)) *
1424 GetField(static_cast<HeaderField>(field + 1)) * ENTRY_SIZE[entry_size_i]); 1441 ENTRY_SIZE[entry_size_i]);
1425 1442
1426 ++entry_size_i; 1443 ++entry_size_i;
1427 field += 2; 1444 field += 2;
diff --git a/src/core/hle/service/ldr_ro/cro_helper.h b/src/core/hle/service/ldr_ro/cro_helper.h
index 34e357afd..e4457d4be 100644
--- a/src/core/hle/service/ldr_ro/cro_helper.h
+++ b/src/core/hle/service/ldr_ro/cro_helper.h
@@ -10,8 +10,8 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/swap.h" 11#include "common/swap.h"
12 12
13#include "core/memory.h"
14#include "core/hle/result.h" 13#include "core/hle/result.h"
14#include "core/memory.h"
15 15
16//////////////////////////////////////////////////////////////////////////////////////////////////// 16////////////////////////////////////////////////////////////////////////////////////////////////////
17// Namespace LDR_RO 17// Namespace LDR_RO
@@ -21,14 +21,17 @@ namespace LDR_RO {
21// GCC versions < 5.0 do not implement std::is_trivially_copyable. 21// GCC versions < 5.0 do not implement std::is_trivially_copyable.
22// Excluding MSVC because it has weird behaviour for std::is_trivially_copyable. 22// Excluding MSVC because it has weird behaviour for std::is_trivially_copyable.
23#if (__GNUC__ >= 5) || defined(__clang__) 23#if (__GNUC__ >= 5) || defined(__clang__)
24 #define ASSERT_CRO_STRUCT(name, size) \ 24#define ASSERT_CRO_STRUCT(name, size) \
25 static_assert(std::is_standard_layout<name>::value, "CRO structure " #name " doesn't use standard layout"); \ 25 static_assert(std::is_standard_layout<name>::value, \
26 static_assert(std::is_trivially_copyable<name>::value, "CRO structure " #name " isn't trivially copyable"); \ 26 "CRO structure " #name " doesn't use standard layout"); \
27 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) 27 static_assert(std::is_trivially_copyable<name>::value, \
28 "CRO structure " #name " isn't trivially copyable"); \
29 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name)
28#else 30#else
29 #define ASSERT_CRO_STRUCT(name, size) \ 31#define ASSERT_CRO_STRUCT(name, size) \
30 static_assert(std::is_standard_layout<name>::value, "CRO structure " #name " doesn't use standard layout"); \ 32 static_assert(std::is_standard_layout<name>::value, \
31 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) 33 "CRO structure " #name " doesn't use standard layout"); \
34 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name)
32#endif 35#endif
33 36
34static constexpr u32 CRO_HEADER_SIZE = 0x138; 37static constexpr u32 CRO_HEADER_SIZE = 0x138;
@@ -59,9 +62,9 @@ public:
59 * @param is_crs true if the module itself is the static module 62 * @param is_crs true if the module itself is the static module
60 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 63 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
61 */ 64 */
62 ResultCode Rebase(VAddr crs_address, u32 cro_size, 65 ResultCode Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment_addresss,
63 VAddr data_segment_addresss, u32 data_segment_size, 66 u32 data_segment_size, VAddr bss_segment_address, u32 bss_segment_size,
64 VAddr bss_segment_address, u32 bss_segment_size, bool is_crs); 67 bool is_crs);
65 68
66 /** 69 /**
67 * Unrebases the module. 70 * Unrebases the module.
@@ -148,8 +151,10 @@ private:
148 const VAddr module_address; ///< the virtual address of this module 151 const VAddr module_address; ///< the virtual address of this module
149 152
150 /** 153 /**
151 * Each item in this enum represents a u32 field in the header begin from address+0x80, successively. 154 * Each item in this enum represents a u32 field in the header begin from address+0x80,
152 * We don't directly use a struct here, to avoid GetPointer, reinterpret_cast, or Read/WriteBlock repeatedly. 155 * successively.
156 * We don't directly use a struct here, to avoid GetPointer, reinterpret_cast, or
157 * Read/WriteBlock repeatedly.
153 */ 158 */
154 enum HeaderField { 159 enum HeaderField {
155 Magic = 0, 160 Magic = 0,
@@ -208,18 +213,20 @@ private:
208 Fix2Barrier = ImportModuleTableOffset, 213 Fix2Barrier = ImportModuleTableOffset,
209 Fix1Barrier = StaticAnonymousSymbolTableOffset, 214 Fix1Barrier = StaticAnonymousSymbolTableOffset,
210 }; 215 };
211 static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4, "CRO Header fields are wrong!"); 216 static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4,
217 "CRO Header fields are wrong!");
212 218
213 enum class SegmentType : u32 { 219 enum class SegmentType : u32 {
214 Code = 0, 220 Code = 0,
215 ROData = 1, 221 ROData = 1,
216 Data = 2, 222 Data = 2,
217 BSS = 3, 223 BSS = 3,
218 }; 224 };
219 225
220 /** 226 /**
221 * Identifies a program location inside of a segment. 227 * Identifies a program location inside of a segment.
222 * Required to refer to program locations because individual segments may be relocated independently of each other. 228 * Required to refer to program locations because individual segments may be relocated
229 * independently of each other.
223 */ 230 */
224 union SegmentTag { 231 union SegmentTag {
225 u32_le raw; 232 u32_le raw;
@@ -227,7 +234,8 @@ private:
227 BitField<4, 28, u32_le> offset_into_segment; 234 BitField<4, 28, u32_le> offset_into_segment;
228 235
229 SegmentTag() = default; 236 SegmentTag() = default;
230 explicit SegmentTag(u32 raw_) : raw(raw_) {} 237 explicit SegmentTag(u32 raw_) : raw(raw_) {
238 }
231 }; 239 };
232 240
233 /// Information of a segment in this module. 241 /// Information of a segment in this module.
@@ -282,7 +290,7 @@ private:
282 290
283 /// Identifies an indexed symbol imported from another module. 291 /// Identifies an indexed symbol imported from another module.
284 struct ImportIndexedSymbolEntry { 292 struct ImportIndexedSymbolEntry {
285 u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module 293 u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module
286 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable 294 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable
287 295
288 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportIndexedSymbolTableOffset; 296 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportIndexedSymbolTableOffset;
@@ -291,8 +299,8 @@ private:
291 299
292 /// Identifies an anonymous symbol imported from another module. 300 /// Identifies an anonymous symbol imported from another module.
293 struct ImportAnonymousSymbolEntry { 301 struct ImportAnonymousSymbolEntry {
294 SegmentTag symbol_position; // in the exporting segment 302 SegmentTag symbol_position; // in the exporting segment
295 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable 303 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable
296 304
297 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportAnonymousSymbolTableOffset; 305 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportAnonymousSymbolTableOffset;
298 }; 306 };
@@ -300,42 +308,47 @@ private:
300 308
301 /// Information of a imported module and symbols imported from it. 309 /// Information of a imported module and symbols imported from it.
302 struct ImportModuleEntry { 310 struct ImportModuleEntry {
303 u32_le name_offset; // pointing to a substring in ImportStrings 311 u32_le name_offset; // pointing to a substring in ImportStrings
304 u32_le import_indexed_symbol_table_offset; // pointing to a subtable in ImportIndexedSymbolTable 312 u32_le import_indexed_symbol_table_offset; // pointing to a subtable in
313 // ImportIndexedSymbolTable
305 u32_le import_indexed_symbol_num; 314 u32_le import_indexed_symbol_num;
306 u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in ImportAnonymousSymbolTable 315 u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in
316 // ImportAnonymousSymbolTable
307 u32_le import_anonymous_symbol_num; 317 u32_le import_anonymous_symbol_num;
308 318
309 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset; 319 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset;
310 320
311 void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) { 321 void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) {
312 Memory::ReadBlock(import_indexed_symbol_table_offset + index * sizeof(ImportIndexedSymbolEntry), 322 Memory::ReadBlock(import_indexed_symbol_table_offset +
313 &entry, sizeof(ImportIndexedSymbolEntry)); 323 index * sizeof(ImportIndexedSymbolEntry),
324 &entry, sizeof(ImportIndexedSymbolEntry));
314 } 325 }
315 326
316 void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) { 327 void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) {
317 Memory::ReadBlock(import_anonymous_symbol_table_offset + index * sizeof(ImportAnonymousSymbolEntry), 328 Memory::ReadBlock(import_anonymous_symbol_table_offset +
318 &entry, sizeof(ImportAnonymousSymbolEntry)); 329 index * sizeof(ImportAnonymousSymbolEntry),
330 &entry, sizeof(ImportAnonymousSymbolEntry));
319 } 331 }
320 }; 332 };
321 ASSERT_CRO_STRUCT(ImportModuleEntry, 20); 333 ASSERT_CRO_STRUCT(ImportModuleEntry, 20);
322 334
323 enum class RelocationType : u8 { 335 enum class RelocationType : u8 {
324 Nothing = 0, 336 Nothing = 0,
325 AbsoluteAddress = 2, 337 AbsoluteAddress = 2,
326 RelativeAddress = 3, 338 RelativeAddress = 3,
327 ThumbBranch = 10, 339 ThumbBranch = 10,
328 ArmBranch = 28, 340 ArmBranch = 28,
329 ModifyArmBranch = 29, 341 ModifyArmBranch = 29,
330 AbsoluteAddress2 = 38, 342 AbsoluteAddress2 = 38,
331 AlignedRelativeAddress = 42, 343 AlignedRelativeAddress = 42,
332 }; 344 };
333 345
334 struct RelocationEntry { 346 struct RelocationEntry {
335 SegmentTag target_position; // to self's segment as an ExternalRelocationEntry; to static module segment as a StaticRelocationEntry 347 SegmentTag target_position; // to self's segment as an ExternalRelocationEntry; to static
348 // module segment as a StaticRelocationEntry
336 RelocationType type; 349 RelocationType type;
337 u8 is_batch_end; 350 u8 is_batch_end;
338 u8 is_batch_resolved; // set at a batch beginning if the batch is resolved 351 u8 is_batch_resolved; // set at a batch beginning if the batch is resolved
339 INSERT_PADDING_BYTES(1); 352 INSERT_PADDING_BYTES(1);
340 u32_le addend; 353 u32_le addend;
341 }; 354 };
@@ -366,8 +379,8 @@ private:
366 379
367 /// Identifies a special static anonymous symbol (no game is known using this). 380 /// Identifies a special static anonymous symbol (no game is known using this).
368 struct StaticAnonymousSymbolEntry { 381 struct StaticAnonymousSymbolEntry {
369 SegmentTag symbol_position; // to self's segment 382 SegmentTag symbol_position; // to self's segment
370 u32_le relocation_batch_offset; // pointing to a relocation batch in StaticRelocationTable 383 u32_le relocation_batch_offset; // pointing to a relocation batch in StaticRelocationTable
371 384
372 static constexpr HeaderField TABLE_OFFSET_FIELD = StaticAnonymousSymbolTableOffset; 385 static constexpr HeaderField TABLE_OFFSET_FIELD = StaticAnonymousSymbolTableOffset;
373 }; 386 };
@@ -446,12 +459,15 @@ private:
446 } 459 }
447 460
448 /** 461 /**
449 * A helper function iterating over all registered auto-link modules, including the static module. 462 * A helper function iterating over all registered auto-link modules, including the static
463 * module.
450 * @param crs_address the virtual address of the static module 464 * @param crs_address the virtual address of the static module
451 * @param func a function object to operate on a module. It accepts one parameter 465 * @param func a function object to operate on a module. It accepts one parameter
452 * CROHelper and returns ResultVal<bool>. It should return true to continue the iteration, 466 * CROHelper and returns ResultVal<bool>. It should return true to continue the
467 * iteration,
453 * false to stop the iteration, or an error code (which will also stop the iteration). 468 * false to stop the iteration, or an error code (which will also stop the iteration).
454 * @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration success, 469 * @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration
470 * success,
455 * otherwise error code of the last iteration. 471 * otherwise error code of the last iteration.
456 */ 472 */
457 template <typename FunctionObject> 473 template <typename FunctionObject>
@@ -477,8 +493,8 @@ private:
477 * Usually equals to target_address, but will be different for a target in .data segment 493 * Usually equals to target_address, but will be different for a target in .data segment
478 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 494 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
479 */ 495 */
480 ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type, 496 ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type, u32 addend,
481 u32 addend, u32 symbol_address, u32 target_future_address); 497 u32 symbol_address, u32 target_future_address);
482 498
483 /** 499 /**
484 * Clears a relocation to zero 500 * Clears a relocation to zero
@@ -492,7 +508,8 @@ private:
492 * Applies or resets a batch of relocations 508 * Applies or resets a batch of relocations
493 * @param batch the virtual address of the first relocation in the batch 509 * @param batch the virtual address of the first relocation in the batch
494 * @param symbol_address the symbol address to be relocated with 510 * @param symbol_address the symbol address to be relocated with
495 * @param reset false to set the batch to resolved state, true to reset the batch to unresolved state 511 * @param reset false to set the batch to resolved state, true to reset the batch to unresolved
512 * state
496 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 513 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
497 */ 514 */
498 ResultCode ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset = false); 515 ResultCode ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset = false);
@@ -507,7 +524,8 @@ private:
507 /** 524 /**
508 * Rebases offsets in module header according to module address. 525 * Rebases offsets in module header according to module address.
509 * @param cro_size the size of the CRO file 526 * @param cro_size the size of the CRO file
510 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 527 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
528 * code.
511 */ 529 */
512 ResultCode RebaseHeader(u32 cro_size); 530 ResultCode RebaseHeader(u32 cro_size);
513 531
@@ -520,43 +538,49 @@ private:
520 * @param bss_segment_size the buffer size for .bss segment 538 * @param bss_segment_size the buffer size for .bss segment
521 * @returns ResultVal<VAddr> with the virtual address of .data segment in CRO. 539 * @returns ResultVal<VAddr> with the virtual address of .data segment in CRO.
522 */ 540 */
523 ResultVal<VAddr> RebaseSegmentTable(u32 cro_size, 541 ResultVal<VAddr> RebaseSegmentTable(u32 cro_size, VAddr data_segment_address,
524 VAddr data_segment_address, u32 data_segment_size, 542 u32 data_segment_size, VAddr bss_segment_address,
525 VAddr bss_segment_address, u32 bss_segment_size); 543 u32 bss_segment_size);
526 544
527 /** 545 /**
528 * Rebases offsets in exported named symbol table according to module address. 546 * Rebases offsets in exported named symbol table according to module address.
529 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 547 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
548 * code.
530 */ 549 */
531 ResultCode RebaseExportNamedSymbolTable(); 550 ResultCode RebaseExportNamedSymbolTable();
532 551
533 /** 552 /**
534 * Verifies indices in export tree table. 553 * Verifies indices in export tree table.
535 * @returns ResultCode RESULT_SUCCESS if all indices are verified as valid, otherwise error code. 554 * @returns ResultCode RESULT_SUCCESS if all indices are verified as valid, otherwise error
555 * code.
536 */ 556 */
537 ResultCode VerifyExportTreeTable() const; 557 ResultCode VerifyExportTreeTable() const;
538 558
539 /** 559 /**
540 * Rebases offsets in exported module table according to module address. 560 * Rebases offsets in exported module table according to module address.
541 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 561 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
562 * code.
542 */ 563 */
543 ResultCode RebaseImportModuleTable(); 564 ResultCode RebaseImportModuleTable();
544 565
545 /** 566 /**
546 * Rebases offsets in imported named symbol table according to module address. 567 * Rebases offsets in imported named symbol table according to module address.
547 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 568 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
569 * code.
548 */ 570 */
549 ResultCode RebaseImportNamedSymbolTable(); 571 ResultCode RebaseImportNamedSymbolTable();
550 572
551 /** 573 /**
552 * Rebases offsets in imported indexed symbol table according to module address. 574 * Rebases offsets in imported indexed symbol table according to module address.
553 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 575 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
576 * code.
554 */ 577 */
555 ResultCode RebaseImportIndexedSymbolTable(); 578 ResultCode RebaseImportIndexedSymbolTable();
556 579
557 /** 580 /**
558 * Rebases offsets in imported anonymous symbol table according to module address. 581 * Rebases offsets in imported anonymous symbol table according to module address.
559 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 582 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
583 * code.
560 */ 584 */
561 ResultCode RebaseImportAnonymousSymbolTable(); 585 ResultCode RebaseImportAnonymousSymbolTable();
562 586
@@ -621,7 +645,8 @@ private:
621 void UnrebaseHeader(); 645 void UnrebaseHeader();
622 646
623 /** 647 /**
624 * Looks up all imported named symbols of this module in all registered auto-link modules, and resolves them if found. 648 * Looks up all imported named symbols of this module in all registered auto-link modules, and
649 * resolves them if found.
625 * @param crs_address the virtual address of the static module 650 * @param crs_address the virtual address of the static module
626 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 651 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
627 */ 652 */
@@ -646,7 +671,8 @@ private:
646 ResultCode ResetImportAnonymousSymbol(); 671 ResultCode ResetImportAnonymousSymbol();
647 672
648 /** 673 /**
649 * Finds registered auto-link modules that this module imports, and resolves indexed and anonymous symbols exported by them. 674 * Finds registered auto-link modules that this module imports, and resolves indexed and
675 * anonymous symbols exported by them.
650 * @param crs_address the virtual address of the static module 676 * @param crs_address the virtual address of the static module
651 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 677 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
652 */ 678 */
@@ -667,7 +693,8 @@ private:
667 ResultCode ResetExportNamedSymbol(CROHelper target); 693 ResultCode ResetExportNamedSymbol(CROHelper target);
668 694
669 /** 695 /**
670 * Resolves imported indexed and anonymous symbols in the target module which imports this module. 696 * Resolves imported indexed and anonymous symbols in the target module which imports this
697 * module.
671 * @param target the module to resolve. 698 * @param target the module to resolve.
672 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 699 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
673 */ 700 */
diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp
index 8ba73ea8d..ae5d3921f 100644
--- a/src/core/hle/service/ldr_ro/ldr_ro.cpp
+++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp
@@ -18,24 +18,33 @@
18 18
19namespace LDR_RO { 19namespace LDR_RO {
20 20
21static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9 21static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9
22 ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent); 22 ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal,
23static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8 23 ErrorLevel::Permanent);
24 ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent); 24static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8
25static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F 25 ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal,
26 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 26 ErrorLevel::Permanent);
27static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1 27static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F
28 ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 28 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument,
29static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2 29 ErrorLevel::Usage);
30 ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 30static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1
31static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F 31 ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument,
32 ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Usage); 32 ErrorLevel::Permanent);
33static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08 33static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2
34 ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent); 34 ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument,
35static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D 35 ErrorLevel::Permanent);
36 ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent); 36static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F
37static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830 37 ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal,
38 ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 38 ErrorLevel::Usage);
39static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08
40 ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState,
41 ErrorLevel::Permanent);
42static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D
43 ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState,
44 ErrorLevel::Permanent);
45static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830
46 ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
47 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
39 48
40static MemorySynchronizer memory_synchronizer; 49static MemorySynchronizer memory_synchronizer;
41 50
@@ -44,10 +53,10 @@ static VAddr loaded_crs; ///< the virtual address of the static module
44 53
45static bool VerifyBufferState(VAddr buffer_ptr, u32 size) { 54static bool VerifyBufferState(VAddr buffer_ptr, u32 size) {
46 auto vma = Kernel::g_current_process->vm_manager.FindVMA(buffer_ptr); 55 auto vma = Kernel::g_current_process->vm_manager.FindVMA(buffer_ptr);
47 return vma != Kernel::g_current_process->vm_manager.vma_map.end() 56 return vma != Kernel::g_current_process->vm_manager.vma_map.end() &&
48 && vma->second.base + vma->second.size >= buffer_ptr + size 57 vma->second.base + vma->second.size >= buffer_ptr + size &&
49 && vma->second.permissions == Kernel::VMAPermission::ReadWrite 58 vma->second.permissions == Kernel::VMAPermission::ReadWrite &&
50 && vma->second.meminfo_state == Kernel::MemoryState::Private; 59 vma->second.meminfo_state == Kernel::MemoryState::Private;
51} 60}
52 61
53/** 62/**
@@ -66,13 +75,14 @@ static bool VerifyBufferState(VAddr buffer_ptr, u32 size) {
66static void Initialize(Service::Interface* self) { 75static void Initialize(Service::Interface* self) {
67 u32* cmd_buff = Kernel::GetCommandBuffer(); 76 u32* cmd_buff = Kernel::GetCommandBuffer();
68 VAddr crs_buffer_ptr = cmd_buff[1]; 77 VAddr crs_buffer_ptr = cmd_buff[1];
69 u32 crs_size = cmd_buff[2]; 78 u32 crs_size = cmd_buff[2];
70 VAddr crs_address = cmd_buff[3]; 79 VAddr crs_address = cmd_buff[3];
71 u32 descriptor = cmd_buff[4]; 80 u32 descriptor = cmd_buff[4];
72 u32 process = cmd_buff[5]; 81 u32 process = cmd_buff[5];
73 82
74 LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, crs_address=0x%08X, crs_size=0x%X, descriptor=0x%08X, process=0x%08X", 83 LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, crs_address=0x%08X, crs_size=0x%X, "
75 crs_buffer_ptr, crs_address, crs_size, descriptor, process); 84 "descriptor=0x%08X, process=0x%08X",
85 crs_buffer_ptr, crs_address, crs_size, descriptor, process);
76 86
77 if (descriptor != 0) { 87 if (descriptor != 0) {
78 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 88 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -119,7 +129,8 @@ static void Initialize(Service::Interface* self) {
119 return; 129 return;
120 } 130 }
121 131
122 if (crs_address < Memory::PROCESS_IMAGE_VADDR || crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) { 132 if (crs_address < Memory::PROCESS_IMAGE_VADDR ||
133 crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) {
123 LOG_ERROR(Service_LDR, "CRS mapping address is not in the process image region"); 134 LOG_ERROR(Service_LDR, "CRS mapping address is not in the process image region");
124 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; 135 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw;
125 return; 136 return;
@@ -131,14 +142,17 @@ static void Initialize(Service::Interface* self) {
131 // TODO(wwylele): should be memory aliasing 142 // TODO(wwylele): should be memory aliasing
132 std::shared_ptr<std::vector<u8>> crs_mem = std::make_shared<std::vector<u8>>(crs_size); 143 std::shared_ptr<std::vector<u8>> crs_mem = std::make_shared<std::vector<u8>>(crs_size);
133 Memory::ReadBlock(crs_buffer_ptr, crs_mem->data(), crs_size); 144 Memory::ReadBlock(crs_buffer_ptr, crs_mem->data(), crs_size);
134 result = Kernel::g_current_process->vm_manager.MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code).Code(); 145 result = Kernel::g_current_process->vm_manager
146 .MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code)
147 .Code();
135 if (result.IsError()) { 148 if (result.IsError()) {
136 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); 149 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw);
137 cmd_buff[1] = result.raw; 150 cmd_buff[1] = result.raw;
138 return; 151 return;
139 } 152 }
140 153
141 result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size, Kernel::VMAPermission::Read); 154 result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size,
155 Kernel::VMAPermission::Read);
142 if (result.IsError()) { 156 if (result.IsError()) {
143 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); 157 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
144 cmd_buff[1] = result.raw; 158 cmd_buff[1] = result.raw;
@@ -186,9 +200,9 @@ static void Initialize(Service::Interface* self) {
186static void LoadCRR(Service::Interface* self) { 200static void LoadCRR(Service::Interface* self) {
187 u32* cmd_buff = Kernel::GetCommandBuffer(); 201 u32* cmd_buff = Kernel::GetCommandBuffer();
188 u32 crr_buffer_ptr = cmd_buff[1]; 202 u32 crr_buffer_ptr = cmd_buff[1];
189 u32 crr_size = cmd_buff[2]; 203 u32 crr_size = cmd_buff[2];
190 u32 descriptor = cmd_buff[3]; 204 u32 descriptor = cmd_buff[3];
191 u32 process = cmd_buff[4]; 205 u32 process = cmd_buff[4];
192 206
193 if (descriptor != 0) { 207 if (descriptor != 0) {
194 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 208 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -200,7 +214,8 @@ static void LoadCRR(Service::Interface* self) {
200 cmd_buff[0] = IPC::MakeHeader(2, 1, 0); 214 cmd_buff[0] = IPC::MakeHeader(2, 1, 0);
201 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 215 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
202 216
203 LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, descriptor=0x%08X, process=0x%08X", 217 LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, "
218 "descriptor=0x%08X, process=0x%08X",
204 crr_buffer_ptr, crr_size, descriptor, process); 219 crr_buffer_ptr, crr_size, descriptor, process);
205} 220}
206 221
@@ -218,8 +233,8 @@ static void LoadCRR(Service::Interface* self) {
218static void UnloadCRR(Service::Interface* self) { 233static void UnloadCRR(Service::Interface* self) {
219 u32* cmd_buff = Kernel::GetCommandBuffer(); 234 u32* cmd_buff = Kernel::GetCommandBuffer();
220 u32 crr_buffer_ptr = cmd_buff[1]; 235 u32 crr_buffer_ptr = cmd_buff[1];
221 u32 descriptor = cmd_buff[2]; 236 u32 descriptor = cmd_buff[2];
222 u32 process = cmd_buff[3]; 237 u32 process = cmd_buff[3];
223 238
224 if (descriptor != 0) { 239 if (descriptor != 0) {
225 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 240 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -231,7 +246,8 @@ static void UnloadCRR(Service::Interface* self) {
231 cmd_buff[0] = IPC::MakeHeader(3, 1, 0); 246 cmd_buff[0] = IPC::MakeHeader(3, 1, 0);
232 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 247 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
233 248
234 LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", 249 LOG_WARNING(Service_LDR,
250 "(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X",
235 crr_buffer_ptr, descriptor, process); 251 crr_buffer_ptr, descriptor, process);
236} 252}
237 253
@@ -263,27 +279,28 @@ static void UnloadCRR(Service::Interface* self) {
263 */ 279 */
264static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { 280static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
265 u32* cmd_buff = Kernel::GetCommandBuffer(); 281 u32* cmd_buff = Kernel::GetCommandBuffer();
266 VAddr cro_buffer_ptr = cmd_buff[1]; 282 VAddr cro_buffer_ptr = cmd_buff[1];
267 VAddr cro_address = cmd_buff[2]; 283 VAddr cro_address = cmd_buff[2];
268 u32 cro_size = cmd_buff[3]; 284 u32 cro_size = cmd_buff[3];
269 VAddr data_segment_address = cmd_buff[4]; 285 VAddr data_segment_address = cmd_buff[4];
270 u32 zero = cmd_buff[5]; 286 u32 zero = cmd_buff[5];
271 u32 data_segment_size = cmd_buff[6]; 287 u32 data_segment_size = cmd_buff[6];
272 u32 bss_segment_address = cmd_buff[7]; 288 u32 bss_segment_address = cmd_buff[7];
273 u32 bss_segment_size = cmd_buff[8]; 289 u32 bss_segment_size = cmd_buff[8];
274 bool auto_link = (cmd_buff[9] & 0xFF) != 0; 290 bool auto_link = (cmd_buff[9] & 0xFF) != 0;
275 u32 fix_level = cmd_buff[10]; 291 u32 fix_level = cmd_buff[10];
276 VAddr crr_address = cmd_buff[11]; 292 VAddr crr_address = cmd_buff[11];
277 u32 descriptor = cmd_buff[12]; 293 u32 descriptor = cmd_buff[12];
278 u32 process = cmd_buff[13]; 294 u32 process = cmd_buff[13];
279 295
280 LOG_DEBUG(Service_LDR, "called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, " 296 LOG_DEBUG(Service_LDR,
281 "data_segment_address=0x%08X, zero=%d, data_segment_size=0x%X, bss_segment_address=0x%08X, bss_segment_size=0x%X, " 297 "called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, "
282 "auto_link=%s, fix_level=%d, crr_address=0x%08X, descriptor=0x%08X, process=0x%08X", 298 "data_segment_address=0x%08X, zero=%d, data_segment_size=0x%X, "
283 link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size, 299 "bss_segment_address=0x%08X, bss_segment_size=0x%X, "
284 data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size, 300 "auto_link=%s, fix_level=%d, crr_address=0x%08X, descriptor=0x%08X, process=0x%08X",
285 auto_link ? "true" : "false", fix_level, crr_address, descriptor, process 301 link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size,
286 ); 302 data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size,
303 auto_link ? "true" : "false", fix_level, crr_address, descriptor, process);
287 304
288 if (descriptor != 0) { 305 if (descriptor != 0) {
289 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 306 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -330,8 +347,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
330 return; 347 return;
331 } 348 }
332 349
333 if (cro_address < Memory::PROCESS_IMAGE_VADDR 350 if (cro_address < Memory::PROCESS_IMAGE_VADDR ||
334 || cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) { 351 cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) {
335 LOG_ERROR(Service_LDR, "CRO mapping address is not in the process image region"); 352 LOG_ERROR(Service_LDR, "CRO mapping address is not in the process image region");
336 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; 353 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw;
337 return; 354 return;
@@ -339,7 +356,9 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
339 356
340 if (zero) { 357 if (zero) {
341 LOG_ERROR(Service_LDR, "Zero is not zero %d", zero); 358 LOG_ERROR(Service_LDR, "Zero is not zero %d", zero);
342 cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Usage).raw; 359 cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO,
360 ErrorSummary::Internal, ErrorLevel::Usage)
361 .raw;
343 return; 362 return;
344 } 363 }
345 364
@@ -349,14 +368,17 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
349 // TODO(wwylele): should be memory aliasing 368 // TODO(wwylele): should be memory aliasing
350 std::shared_ptr<std::vector<u8>> cro_mem = std::make_shared<std::vector<u8>>(cro_size); 369 std::shared_ptr<std::vector<u8>> cro_mem = std::make_shared<std::vector<u8>>(cro_size);
351 Memory::ReadBlock(cro_buffer_ptr, cro_mem->data(), cro_size); 370 Memory::ReadBlock(cro_buffer_ptr, cro_mem->data(), cro_size);
352 result = Kernel::g_current_process->vm_manager.MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code).Code(); 371 result = Kernel::g_current_process->vm_manager
372 .MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code)
373 .Code();
353 if (result.IsError()) { 374 if (result.IsError()) {
354 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); 375 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw);
355 cmd_buff[1] = result.raw; 376 cmd_buff[1] = result.raw;
356 return; 377 return;
357 } 378 }
358 379
359 result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size, Kernel::VMAPermission::Read); 380 result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size,
381 Kernel::VMAPermission::Read);
360 if (result.IsError()) { 382 if (result.IsError()) {
361 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); 383 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
362 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); 384 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
@@ -384,7 +406,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
384 return; 406 return;
385 } 407 }
386 408
387 result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size, bss_segment_address, bss_segment_size, false); 409 result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size,
410 bss_segment_address, bss_segment_size, false);
388 if (result.IsError()) { 411 if (result.IsError()) {
389 LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw); 412 LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw);
390 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); 413 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
@@ -409,7 +432,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
409 // TODO(wwylele): verify the behaviour when buffer_ptr == address 432 // TODO(wwylele): verify the behaviour when buffer_ptr == address
410 if (cro_buffer_ptr != cro_address) { 433 if (cro_buffer_ptr != cro_address) {
411 if (fix_size != cro_size) { 434 if (fix_size != cro_size) {
412 result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size, cro_size - fix_size); 435 result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size,
436 cro_size - fix_size);
413 if (result.IsError()) { 437 if (result.IsError()) {
414 LOG_ERROR(Service_LDR, "Error unmapping memory block %08X", result.raw); 438 LOG_ERROR(Service_LDR, "Error unmapping memory block %08X", result.raw);
415 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); 439 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
@@ -426,7 +450,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
426 u32 exe_size; 450 u32 exe_size;
427 std::tie(exe_begin, exe_size) = cro.GetExecutablePages(); 451 std::tie(exe_begin, exe_size) = cro.GetExecutablePages();
428 if (exe_begin) { 452 if (exe_begin) {
429 result = Kernel::g_current_process->vm_manager.ReprotectRange(exe_begin, exe_size, Kernel::VMAPermission::ReadExecute); 453 result = Kernel::g_current_process->vm_manager.ReprotectRange(
454 exe_begin, exe_size, Kernel::VMAPermission::ReadExecute);
430 if (result.IsError()) { 455 if (result.IsError()) {
431 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); 456 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
432 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fix_size); 457 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fix_size);
@@ -437,8 +462,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
437 462
438 Core::g_app_core->ClearInstructionCache(); 463 Core::g_app_core->ClearInstructionCache();
439 464
440 LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", 465 LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(),
441 cro.ModuleName().data(), cro_address, cro_address+fix_size); 466 cro_address, cro_address + fix_size);
442 467
443 cmd_buff[1] = RESULT_SUCCESS.raw; 468 cmd_buff[1] = RESULT_SUCCESS.raw;
444 cmd_buff[2] = fix_size; 469 cmd_buff[2] = fix_size;
@@ -464,14 +489,15 @@ static void LoadCRO(Service::Interface* self) {
464 */ 489 */
465static void UnloadCRO(Service::Interface* self) { 490static void UnloadCRO(Service::Interface* self) {
466 u32* cmd_buff = Kernel::GetCommandBuffer(); 491 u32* cmd_buff = Kernel::GetCommandBuffer();
467 VAddr cro_address = cmd_buff[1]; 492 VAddr cro_address = cmd_buff[1];
468 u32 zero = cmd_buff[2]; 493 u32 zero = cmd_buff[2];
469 VAddr cro_buffer_ptr = cmd_buff[3]; 494 VAddr cro_buffer_ptr = cmd_buff[3];
470 u32 descriptor = cmd_buff[4]; 495 u32 descriptor = cmd_buff[4];
471 u32 process = cmd_buff[5]; 496 u32 process = cmd_buff[5];
472 497
473 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", 498 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, "
474 cro_address, zero, cro_buffer_ptr, descriptor, process); 499 "descriptor=0x%08X, process=0x%08X",
500 cro_address, zero, cro_buffer_ptr, descriptor, process);
475 501
476 if (descriptor != 0) { 502 if (descriptor != 0) {
477 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 503 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -558,11 +584,11 @@ static void UnloadCRO(Service::Interface* self) {
558static void LinkCRO(Service::Interface* self) { 584static void LinkCRO(Service::Interface* self) {
559 u32* cmd_buff = Kernel::GetCommandBuffer(); 585 u32* cmd_buff = Kernel::GetCommandBuffer();
560 VAddr cro_address = cmd_buff[1]; 586 VAddr cro_address = cmd_buff[1];
561 u32 descriptor = cmd_buff[2]; 587 u32 descriptor = cmd_buff[2];
562 u32 process = cmd_buff[3]; 588 u32 process = cmd_buff[3];
563 589
564 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", 590 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X",
565 cro_address, descriptor, process); 591 cro_address, descriptor, process);
566 592
567 if (descriptor != 0) { 593 if (descriptor != 0) {
568 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 594 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -620,11 +646,11 @@ static void LinkCRO(Service::Interface* self) {
620static void UnlinkCRO(Service::Interface* self) { 646static void UnlinkCRO(Service::Interface* self) {
621 u32* cmd_buff = Kernel::GetCommandBuffer(); 647 u32* cmd_buff = Kernel::GetCommandBuffer();
622 VAddr cro_address = cmd_buff[1]; 648 VAddr cro_address = cmd_buff[1];
623 u32 descriptor = cmd_buff[2]; 649 u32 descriptor = cmd_buff[2];
624 u32 process = cmd_buff[3]; 650 u32 process = cmd_buff[3];
625 651
626 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", 652 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X",
627 cro_address, descriptor, process); 653 cro_address, descriptor, process);
628 654
629 if (descriptor != 0) { 655 if (descriptor != 0) {
630 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 656 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -682,11 +708,11 @@ static void UnlinkCRO(Service::Interface* self) {
682static void Shutdown(Service::Interface* self) { 708static void Shutdown(Service::Interface* self) {
683 u32* cmd_buff = Kernel::GetCommandBuffer(); 709 u32* cmd_buff = Kernel::GetCommandBuffer();
684 VAddr crs_buffer_ptr = cmd_buff[1]; 710 VAddr crs_buffer_ptr = cmd_buff[1];
685 u32 descriptor = cmd_buff[2]; 711 u32 descriptor = cmd_buff[2];
686 u32 process = cmd_buff[3]; 712 u32 process = cmd_buff[3];
687 713
688 LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", 714 LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X",
689 crs_buffer_ptr, descriptor, process); 715 crs_buffer_ptr, descriptor, process);
690 716
691 if (descriptor != 0) { 717 if (descriptor != 0) {
692 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 718 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -724,15 +750,11 @@ static void Shutdown(Service::Interface* self) {
724} 750}
725 751
726const Interface::FunctionInfo FunctionTable[] = { 752const Interface::FunctionInfo FunctionTable[] = {
727 {0x000100C2, Initialize, "Initialize"}, 753 {0x000100C2, Initialize, "Initialize"}, {0x00020082, LoadCRR, "LoadCRR"},
728 {0x00020082, LoadCRR, "LoadCRR"}, 754 {0x00030042, UnloadCRR, "UnloadCRR"}, {0x000402C2, LoadCRO<false>, "LoadCRO"},
729 {0x00030042, UnloadCRR, "UnloadCRR"}, 755 {0x000500C2, UnloadCRO, "UnloadCRO"}, {0x00060042, LinkCRO, "LinkCRO"},
730 {0x000402C2, LoadCRO<false>, "LoadCRO"}, 756 {0x00070042, UnlinkCRO, "UnlinkCRO"}, {0x00080042, Shutdown, "Shutdown"},
731 {0x000500C2, UnloadCRO, "UnloadCRO"}, 757 {0x000902C2, LoadCRO<true>, "LoadCRO_New"},
732 {0x00060042, LinkCRO, "LinkCRO"},
733 {0x00070042, UnlinkCRO, "UnlinkCRO"},
734 {0x00080042, Shutdown, "Shutdown"},
735 {0x000902C2, LoadCRO<true>, "LoadCRO_New"},
736}; 758};
737 759
738//////////////////////////////////////////////////////////////////////////////////////////////////// 760////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ldr_ro/memory_synchronizer.cpp b/src/core/hle/service/ldr_ro/memory_synchronizer.cpp
index 4402876e6..aed6d3365 100644
--- a/src/core/hle/service/ldr_ro/memory_synchronizer.cpp
+++ b/src/core/hle/service/ldr_ro/memory_synchronizer.cpp
@@ -14,9 +14,8 @@
14namespace LDR_RO { 14namespace LDR_RO {
15 15
16auto MemorySynchronizer::FindMemoryBlock(VAddr mapping, VAddr original) { 16auto MemorySynchronizer::FindMemoryBlock(VAddr mapping, VAddr original) {
17 auto block = std::find_if(memory_blocks.begin(), memory_blocks.end(), [=](MemoryBlock& b){ 17 auto block = std::find_if(memory_blocks.begin(), memory_blocks.end(),
18 return b.original == original; 18 [=](MemoryBlock& b) { return b.original == original; });
19 });
20 ASSERT(block->mapping == mapping); 19 ASSERT(block->mapping == mapping);
21 return block; 20 return block;
22} 21}
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index f792bc9cd..edd1ea97b 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -10,22 +10,22 @@
10namespace MIC_U { 10namespace MIC_U {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {
13 {0x00010042, nullptr, "MapSharedMem"}, 13 {0x00010042, nullptr, "MapSharedMem"},
14 {0x00020000, nullptr, "UnmapSharedMem"}, 14 {0x00020000, nullptr, "UnmapSharedMem"},
15 {0x00030140, nullptr, "Initialize"}, 15 {0x00030140, nullptr, "Initialize"},
16 {0x00040040, nullptr, "AdjustSampling"}, 16 {0x00040040, nullptr, "AdjustSampling"},
17 {0x00050000, nullptr, "StopSampling"}, 17 {0x00050000, nullptr, "StopSampling"},
18 {0x00060000, nullptr, "IsSampling"}, 18 {0x00060000, nullptr, "IsSampling"},
19 {0x00070000, nullptr, "GetEventHandle"}, 19 {0x00070000, nullptr, "GetEventHandle"},
20 {0x00080040, nullptr, "SetGain"}, 20 {0x00080040, nullptr, "SetGain"},
21 {0x00090000, nullptr, "GetGain"}, 21 {0x00090000, nullptr, "GetGain"},
22 {0x000A0040, nullptr, "SetPower"}, 22 {0x000A0040, nullptr, "SetPower"},
23 {0x000B0000, nullptr, "GetPower"}, 23 {0x000B0000, nullptr, "GetPower"},
24 {0x000C0042, nullptr, "size"}, 24 {0x000C0042, nullptr, "size"},
25 {0x000D0040, nullptr, "SetClamp"}, 25 {0x000D0040, nullptr, "SetClamp"},
26 {0x000E0000, nullptr, "GetClamp"}, 26 {0x000E0000, nullptr, "GetClamp"},
27 {0x000F0040, nullptr, "SetAllowShellClosed"}, 27 {0x000F0040, nullptr, "SetAllowShellClosed"},
28 {0x00100040, nullptr, "unknown_input2"}, 28 {0x00100040, nullptr, "unknown_input2"},
29}; 29};
30 30
31//////////////////////////////////////////////////////////////////////////////////////////////////// 31////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ndm/ndm.cpp b/src/core/hle/service/ndm/ndm.cpp
index bc9c3413d..9f1536aef 100644
--- a/src/core/hle/service/ndm/ndm.cpp
+++ b/src/core/hle/service/ndm/ndm.cpp
@@ -2,23 +2,21 @@
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 "core/hle/service/ndm/ndm.h"
5#include "common/common_types.h" 6#include "common/common_types.h"
6#include "common/logging/log.h" 7#include "common/logging/log.h"
7#include "core/hle/service/service.h"
8#include "core/hle/service/ndm/ndm.h"
9#include "core/hle/service/ndm/ndm_u.h" 8#include "core/hle/service/ndm/ndm_u.h"
9#include "core/hle/service/service.h"
10 10
11namespace Service { 11namespace Service {
12namespace NDM { 12namespace NDM {
13 13
14enum : u32 { 14enum : u32 { DEFAULT_RETRY_INTERVAL = 10, DEFAULT_SCAN_INTERVAL = 30 };
15 DEFAULT_RETRY_INTERVAL = 10,
16 DEFAULT_SCAN_INTERVAL = 30
17};
18 15
19static DaemonMask daemon_bit_mask = DaemonMask::Default; 16static DaemonMask daemon_bit_mask = DaemonMask::Default;
20static DaemonMask default_daemon_bit_mask = DaemonMask::Default; 17static DaemonMask default_daemon_bit_mask = DaemonMask::Default;
21static std::array<DaemonStatus, 4> daemon_status = { DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle }; 18static std::array<DaemonStatus, 4> daemon_status = {DaemonStatus::Idle, DaemonStatus::Idle,
19 DaemonStatus::Idle, DaemonStatus::Idle};
22static ExclusiveState exclusive_state = ExclusiveState::None; 20static ExclusiveState exclusive_state = ExclusiveState::None;
23static u32 scan_interval = DEFAULT_SCAN_INTERVAL; 21static u32 scan_interval = DEFAULT_SCAN_INTERVAL;
24static u32 retry_interval = DEFAULT_RETRY_INTERVAL; 22static u32 retry_interval = DEFAULT_RETRY_INTERVAL;
@@ -72,7 +70,8 @@ void UnlockState(Service::Interface* self) {
72void SuspendDaemons(Service::Interface* self) { 70void SuspendDaemons(Service::Interface* self) {
73 u32* cmd_buff = Kernel::GetCommandBuffer(); 71 u32* cmd_buff = Kernel::GetCommandBuffer();
74 u32 bit_mask = cmd_buff[1] & 0xF; 72 u32 bit_mask = cmd_buff[1] & 0xF;
75 daemon_bit_mask = static_cast<DaemonMask>(static_cast<u32>(default_daemon_bit_mask) & ~bit_mask); 73 daemon_bit_mask =
74 static_cast<DaemonMask>(static_cast<u32>(default_daemon_bit_mask) & ~bit_mask);
76 for (size_t index = 0; index < daemon_status.size(); ++index) { 75 for (size_t index = 0; index < daemon_status.size(); ++index) {
77 if (bit_mask & (1 << index)) { 76 if (bit_mask & (1 << index)) {
78 daemon_status[index] = DaemonStatus::Suspended; 77 daemon_status[index] = DaemonStatus::Suspended;
@@ -229,8 +228,7 @@ void Init() {
229} 228}
230 229
231void Shutdown() { 230void Shutdown() {
232
233} 231}
234 232
235}// namespace NDM 233} // namespace NDM
236}// namespace Service 234} // namespace Service
diff --git a/src/core/hle/service/ndm/ndm.h b/src/core/hle/service/ndm/ndm.h
index 5c2b968dc..fb574541d 100644
--- a/src/core/hle/service/ndm/ndm.h
+++ b/src/core/hle/service/ndm/ndm.h
@@ -12,36 +12,26 @@ class Interface;
12 12
13namespace NDM { 13namespace NDM {
14 14
15enum class Daemon : u32 { 15enum class Daemon : u32 { Cec = 0, Boss = 1, Nim = 2, Friend = 3 };
16 Cec = 0,
17 Boss = 1,
18 Nim = 2,
19 Friend = 3
20};
21 16
22enum class DaemonMask : u32 { 17enum class DaemonMask : u32 {
23 None = 0, 18 None = 0,
24 Cec = (1 << static_cast<u32>(Daemon::Cec)), 19 Cec = (1 << static_cast<u32>(Daemon::Cec)),
25 Boss = (1 << static_cast<u32>(Daemon::Boss)), 20 Boss = (1 << static_cast<u32>(Daemon::Boss)),
26 Nim = (1 << static_cast<u32>(Daemon::Nim)), 21 Nim = (1 << static_cast<u32>(Daemon::Nim)),
27 Friend = (1 << static_cast<u32>(Daemon::Friend)), 22 Friend = (1 << static_cast<u32>(Daemon::Friend)),
28 Default = Cec | Friend, 23 Default = Cec | Friend,
29 All = Cec | Boss | Nim | Friend 24 All = Cec | Boss | Nim | Friend
30}; 25};
31 26
32enum class DaemonStatus : u32 { 27enum class DaemonStatus : u32 { Busy = 0, Idle = 1, Suspending = 2, Suspended = 3 };
33 Busy = 0,
34 Idle = 1,
35 Suspending = 2,
36 Suspended = 3
37};
38 28
39enum class ExclusiveState : u32 { 29enum class ExclusiveState : u32 {
40 None = 0, 30 None = 0,
41 Infrastructure = 1, 31 Infrastructure = 1,
42 LocalCommunications = 2, 32 LocalCommunications = 2,
43 Streetpass = 3, 33 Streetpass = 3,
44 StreetpassData = 4, 34 StreetpassData = 4,
45}; 35};
46 36
47/** 37/**
@@ -205,7 +195,6 @@ void SetRetryInterval(Service::Interface* self);
205 */ 195 */
206void GetRetryInterval(Service::Interface* self); 196void GetRetryInterval(Service::Interface* self);
207 197
208
209/** 198/**
210 * NDM::OverrideDefaultDaemons service function 199 * NDM::OverrideDefaultDaemons service function
211 * Inputs: 200 * Inputs:
@@ -233,7 +222,8 @@ void ResetDefaultDaemons(Service::Interface* self);
233 * 1 : Result, 0 on success, otherwise error code 222 * 1 : Result, 0 on success, otherwise error code
234 * 2 : Daemon bit mask 223 * 2 : Daemon bit mask
235 * Note: 224 * Note:
236 * Gets the current default daemon bit mask. The default value is (DAEMONMASK_CEC | DAEMONMASK_FRIENDS) 225 * Gets the current default daemon bit mask. The default value is (DAEMONMASK_CEC |
226 * DAEMONMASK_FRIENDS)
237 */ 227 */
238void GetDefaultDaemons(Service::Interface* self); 228void GetDefaultDaemons(Service::Interface* self);
239 229
@@ -252,5 +242,5 @@ void Init();
252/// Shutdown NDM service 242/// Shutdown NDM service
253void Shutdown(); 243void Shutdown();
254 244
255}// namespace NDM 245} // namespace NDM
256}// namespace Service 246} // namespace Service
diff --git a/src/core/hle/service/ndm/ndm_u.cpp b/src/core/hle/service/ndm/ndm_u.cpp
index 3ff0744ee..f5c7a341a 100644
--- a/src/core/hle/service/ndm/ndm_u.cpp
+++ b/src/core/hle/service/ndm/ndm_u.cpp
@@ -9,28 +9,28 @@ namespace Service {
9namespace NDM { 9namespace NDM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010042, EnterExclusiveState, "EnterExclusiveState"}, 12 {0x00010042, EnterExclusiveState, "EnterExclusiveState"},
13 {0x00020002, LeaveExclusiveState, "LeaveExclusiveState"}, 13 {0x00020002, LeaveExclusiveState, "LeaveExclusiveState"},
14 {0x00030000, QueryExclusiveMode, "QueryExclusiveMode"}, 14 {0x00030000, QueryExclusiveMode, "QueryExclusiveMode"},
15 {0x00040002, LockState, "LockState"}, 15 {0x00040002, LockState, "LockState"},
16 {0x00050002, UnlockState, "UnlockState"}, 16 {0x00050002, UnlockState, "UnlockState"},
17 {0x00060040, SuspendDaemons, "SuspendDaemons"}, 17 {0x00060040, SuspendDaemons, "SuspendDaemons"},
18 {0x00070040, ResumeDaemons, "ResumeDaemons"}, 18 {0x00070040, ResumeDaemons, "ResumeDaemons"},
19 {0x00080040, SuspendScheduler, "SuspendScheduler"}, 19 {0x00080040, SuspendScheduler, "SuspendScheduler"},
20 {0x00090000, ResumeScheduler, "ResumeScheduler"}, 20 {0x00090000, ResumeScheduler, "ResumeScheduler"},
21 {0x000A0000, nullptr, "GetCurrentState"}, 21 {0x000A0000, nullptr, "GetCurrentState"},
22 {0x000B0000, nullptr, "GetTargetState"}, 22 {0x000B0000, nullptr, "GetTargetState"},
23 {0x000C0000, nullptr, "<Stubbed>"}, 23 {0x000C0000, nullptr, "<Stubbed>"},
24 {0x000D0040, QueryStatus, "QueryStatus"}, 24 {0x000D0040, QueryStatus, "QueryStatus"},
25 {0x000E0040, GetDaemonDisableCount, "GetDaemonDisableCount"}, 25 {0x000E0040, GetDaemonDisableCount, "GetDaemonDisableCount"},
26 {0x000F0000, GetSchedulerDisableCount,"GetSchedulerDisableCount"}, 26 {0x000F0000, GetSchedulerDisableCount, "GetSchedulerDisableCount"},
27 {0x00100040, SetScanInterval, "SetScanInterval"}, 27 {0x00100040, SetScanInterval, "SetScanInterval"},
28 {0x00110000, GetScanInterval, "GetScanInterval"}, 28 {0x00110000, GetScanInterval, "GetScanInterval"},
29 {0x00120040, SetRetryInterval, "SetRetryInterval"}, 29 {0x00120040, SetRetryInterval, "SetRetryInterval"},
30 {0x00130000, GetRetryInterval, "GetRetryInterval"}, 30 {0x00130000, GetRetryInterval, "GetRetryInterval"},
31 {0x00140040, OverrideDefaultDaemons, "OverrideDefaultDaemons"}, 31 {0x00140040, OverrideDefaultDaemons, "OverrideDefaultDaemons"},
32 {0x00150000, ResetDefaultDaemons, "ResetDefaultDaemons"}, 32 {0x00150000, ResetDefaultDaemons, "ResetDefaultDaemons"},
33 {0x00160000, GetDefaultDaemons, "GetDefaultDaemons"}, 33 {0x00160000, GetDefaultDaemons, "GetDefaultDaemons"},
34 {0x00170000, ClearHalfAwakeMacFilter, "ClearHalfAwakeMacFilter"}, 34 {0x00170000, ClearHalfAwakeMacFilter, "ClearHalfAwakeMacFilter"},
35}; 35};
36 36
diff --git a/src/core/hle/service/news/news.cpp b/src/core/hle/service/news/news.cpp
index b3f500694..983e0777c 100644
--- a/src/core/hle/service/news/news.cpp
+++ b/src/core/hle/service/news/news.cpp
@@ -4,10 +4,10 @@
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6 6
7#include "core/hle/service/service.h"
8#include "core/hle/service/news/news.h" 7#include "core/hle/service/news/news.h"
9#include "core/hle/service/news/news_s.h" 8#include "core/hle/service/news/news_s.h"
10#include "core/hle/service/news/news_u.h" 9#include "core/hle/service/news/news_u.h"
10#include "core/hle/service/service.h"
11 11
12namespace Service { 12namespace Service {
13namespace NEWS { 13namespace NEWS {
diff --git a/src/core/hle/service/news/news_s.cpp b/src/core/hle/service/news/news_s.cpp
index 39b5a50f8..dda3d0f6a 100644
--- a/src/core/hle/service/news/news_s.cpp
+++ b/src/core/hle/service/news/news_s.cpp
@@ -9,19 +9,19 @@ namespace Service {
9namespace NEWS { 9namespace NEWS {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x000100C6, nullptr, "AddNotification"}, 12 {0x000100C6, nullptr, "AddNotification"},
13 {0x00050000, nullptr, "GetTotalNotifications"}, 13 {0x00050000, nullptr, "GetTotalNotifications"},
14 {0x00060042, nullptr, "SetNewsDBHeader"}, 14 {0x00060042, nullptr, "SetNewsDBHeader"},
15 {0x00070082, nullptr, "SetNotificationHeader"}, 15 {0x00070082, nullptr, "SetNotificationHeader"},
16 {0x00080082, nullptr, "SetNotificationMessage"}, 16 {0x00080082, nullptr, "SetNotificationMessage"},
17 {0x00090082, nullptr, "SetNotificationImage"}, 17 {0x00090082, nullptr, "SetNotificationImage"},
18 {0x000A0042, nullptr, "GetNewsDBHeader"}, 18 {0x000A0042, nullptr, "GetNewsDBHeader"},
19 {0x000B0082, nullptr, "GetNotificationHeader"}, 19 {0x000B0082, nullptr, "GetNotificationHeader"},
20 {0x000C0082, nullptr, "GetNotificationMessage"}, 20 {0x000C0082, nullptr, "GetNotificationMessage"},
21 {0x000D0082, nullptr, "GetNotificationImage"}, 21 {0x000D0082, nullptr, "GetNotificationImage"},
22 {0x000E0040, nullptr, "SetInfoLEDPattern"}, 22 {0x000E0040, nullptr, "SetInfoLEDPattern"},
23 {0x00120082, nullptr, "GetNotificationHeaderOther"}, 23 {0x00120082, nullptr, "GetNotificationHeaderOther"},
24 {0x00130000, nullptr, "WriteNewsDBSavedata"}, 24 {0x00130000, nullptr, "WriteNewsDBSavedata"},
25}; 25};
26 26
27NEWS_S_Interface::NEWS_S_Interface() { 27NEWS_S_Interface::NEWS_S_Interface() {
diff --git a/src/core/hle/service/news/news_u.cpp b/src/core/hle/service/news/news_u.cpp
index 6b75cc24e..a07e466de 100644
--- a/src/core/hle/service/news/news_u.cpp
+++ b/src/core/hle/service/news/news_u.cpp
@@ -8,7 +8,7 @@ namespace Service {
8namespace NEWS { 8namespace NEWS {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x000100C6, nullptr, "AddNotification"}, 11 {0x000100C6, nullptr, "AddNotification"},
12}; 12};
13 13
14NEWS_U_Interface::NEWS_U_Interface() { 14NEWS_U_Interface::NEWS_U_Interface() {
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index ed42464ce..f3c01d6e6 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -5,11 +5,11 @@
5#include "common/common_types.h" 5#include "common/common_types.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7 7
8#include "core/hle/service/service.h"
9#include "core/hle/service/nim/nim.h" 8#include "core/hle/service/nim/nim.h"
10#include "core/hle/service/nim/nim_aoc.h" 9#include "core/hle/service/nim/nim_aoc.h"
11#include "core/hle/service/nim/nim_s.h" 10#include "core/hle/service/nim/nim_s.h"
12#include "core/hle/service/nim/nim_u.h" 11#include "core/hle/service/nim/nim_u.h"
12#include "core/hle/service/service.h"
13 13
14namespace Service { 14namespace Service {
15namespace NIM { 15namespace NIM {
diff --git a/src/core/hle/service/nim/nim_aoc.cpp b/src/core/hle/service/nim/nim_aoc.cpp
index 4a4818d57..2d0fb6fc4 100644
--- a/src/core/hle/service/nim/nim_aoc.cpp
+++ b/src/core/hle/service/nim/nim_aoc.cpp
@@ -8,14 +8,14 @@ namespace Service {
8namespace NIM { 8namespace NIM {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x00030042, nullptr, "SetApplicationId"}, 11 {0x00030042, nullptr, "SetApplicationId"},
12 {0x00040042, nullptr, "SetTin"}, 12 {0x00040042, nullptr, "SetTin"},
13 {0x000902D0, nullptr, "ListContentSetsEx"}, 13 {0x000902D0, nullptr, "ListContentSetsEx"},
14 {0x00180000, nullptr, "GetBalance"}, 14 {0x00180000, nullptr, "GetBalance"},
15 {0x001D0000, nullptr, "GetCustomerSupportCode"}, 15 {0x001D0000, nullptr, "GetCustomerSupportCode"},
16 {0x00210000, nullptr, "Initialize"}, 16 {0x00210000, nullptr, "Initialize"},
17 {0x00240282, nullptr, "CalculateContentsRequiredSize"}, 17 {0x00240282, nullptr, "CalculateContentsRequiredSize"},
18 {0x00250000, nullptr, "RefreshServerTime"}, 18 {0x00250000, nullptr, "RefreshServerTime"},
19}; 19};
20 20
21NIM_AOC_Interface::NIM_AOC_Interface() { 21NIM_AOC_Interface::NIM_AOC_Interface() {
diff --git a/src/core/hle/service/nim/nim_s.cpp b/src/core/hle/service/nim/nim_s.cpp
index dcaa0255a..e2ba693c9 100644
--- a/src/core/hle/service/nim/nim_s.cpp
+++ b/src/core/hle/service/nim/nim_s.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace NIM { 8namespace NIM {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x000A0000, nullptr, "CheckSysupdateAvailableSOAP"}, 11 {0x000A0000, nullptr, "CheckSysupdateAvailableSOAP"},
12 {0x0016020A, nullptr, "ListTitles"}, 12 {0x0016020A, nullptr, "ListTitles"},
13 {0x002D0042, nullptr, "DownloadTickets"}, 13 {0x002D0042, nullptr, "DownloadTickets"},
14 {0x00420240, nullptr, "StartDownload"}, 14 {0x00420240, nullptr, "StartDownload"},
15}; 15};
16 16
17NIM_S_Interface::NIM_S_Interface() { 17NIM_S_Interface::NIM_S_Interface() {
@@ -20,4 +20,3 @@ NIM_S_Interface::NIM_S_Interface() {
20 20
21} // namespace NIM 21} // namespace NIM
22} // namespace Service 22} // namespace Service
23
diff --git a/src/core/hle/service/nim/nim_u.cpp b/src/core/hle/service/nim/nim_u.cpp
index eae45ebc0..7e07d02e8 100644
--- a/src/core/hle/service/nim/nim_u.cpp
+++ b/src/core/hle/service/nim/nim_u.cpp
@@ -9,12 +9,12 @@ namespace Service {
9namespace NIM { 9namespace NIM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010000, nullptr, "StartSysUpdate"}, 12 {0x00010000, nullptr, "StartSysUpdate"},
13 {0x00020000, nullptr, "GetUpdateDownloadProgress"}, 13 {0x00020000, nullptr, "GetUpdateDownloadProgress"},
14 {0x00040000, nullptr, "FinishTitlesInstall"}, 14 {0x00040000, nullptr, "FinishTitlesInstall"},
15 {0x00050000, nullptr, "CheckForSysUpdateEvent"}, 15 {0x00050000, nullptr, "CheckForSysUpdateEvent"},
16 {0x00090000, CheckSysUpdateAvailable, "CheckSysUpdateAvailable"}, 16 {0x00090000, CheckSysUpdateAvailable, "CheckSysUpdateAvailable"},
17 {0x000A0000, nullptr, "GetState"}, 17 {0x000A0000, nullptr, "GetState"},
18}; 18};
19 19
20NIM_U_Interface::NIM_U_Interface() { 20NIM_U_Interface::NIM_U_Interface() {
@@ -23,4 +23,3 @@ NIM_U_Interface::NIM_U_Interface() {
23 23
24} // namespace NIM 24} // namespace NIM
25} // namespace Service 25} // namespace Service
26
diff --git a/src/core/hle/service/ns_s.cpp b/src/core/hle/service/ns_s.cpp
index 072918d62..6693f7c08 100644
--- a/src/core/hle/service/ns_s.cpp
+++ b/src/core/hle/service/ns_s.cpp
@@ -10,21 +10,21 @@
10namespace NS_S { 10namespace NS_S {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {
13 {0x000100C0, nullptr, "LaunchFIRM"}, 13 {0x000100C0, nullptr, "LaunchFIRM"},
14 {0x000200C0, nullptr, "LaunchTitle"}, 14 {0x000200C0, nullptr, "LaunchTitle"},
15 {0x00030000, nullptr, "TerminateApplication"}, 15 {0x00030000, nullptr, "TerminateApplication"},
16 {0x00040040, nullptr, "TerminateProcess"}, 16 {0x00040040, nullptr, "TerminateProcess"},
17 {0x000500C0, nullptr, "LaunchApplicationFIRM"}, 17 {0x000500C0, nullptr, "LaunchApplicationFIRM"},
18 {0x00060042, nullptr, "SetFIRMParams4A0"}, 18 {0x00060042, nullptr, "SetFIRMParams4A0"},
19 {0x00070042, nullptr, "CardUpdateInitialize"}, 19 {0x00070042, nullptr, "CardUpdateInitialize"},
20 {0x00080000, nullptr, "CardUpdateShutdown"}, 20 {0x00080000, nullptr, "CardUpdateShutdown"},
21 {0x000D0140, nullptr, "SetTWLBannerHMAC"}, 21 {0x000D0140, nullptr, "SetTWLBannerHMAC"},
22 {0x000E0000, nullptr, "ShutdownAsync"}, 22 {0x000E0000, nullptr, "ShutdownAsync"},
23 {0x00100180, nullptr, "RebootSystem"}, 23 {0x00100180, nullptr, "RebootSystem"},
24 {0x00110100, nullptr, "TerminateTitle"}, 24 {0x00110100, nullptr, "TerminateTitle"},
25 {0x001200C0, nullptr, "SetApplicationCpuTimeLimit"}, 25 {0x001200C0, nullptr, "SetApplicationCpuTimeLimit"},
26 {0x00150140, nullptr, "LaunchApplication"}, 26 {0x00150140, nullptr, "LaunchApplication"},
27 {0x00160000, nullptr, "RebootSystemClean"}, 27 {0x00160000, nullptr, "RebootSystemClean"},
28}; 28};
29 29
30//////////////////////////////////////////////////////////////////////////////////////////////////// 30////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp
index ae4640409..ed417fa9a 100644
--- a/src/core/hle/service/nwm_uds.cpp
+++ b/src/core/hle/service/nwm_uds.cpp
@@ -54,22 +54,23 @@ static void Shutdown(Service::Interface* self) {
54static void RecvBeaconBroadcastData(Service::Interface* self) { 54static void RecvBeaconBroadcastData(Service::Interface* self) {
55 u32* cmd_buff = Kernel::GetCommandBuffer(); 55 u32* cmd_buff = Kernel::GetCommandBuffer();
56 u32 out_buffer_size = cmd_buff[1]; 56 u32 out_buffer_size = cmd_buff[1];
57 u32 unk1 = cmd_buff[2]; 57 u32 unk1 = cmd_buff[2];
58 u32 unk2 = cmd_buff[3]; 58 u32 unk2 = cmd_buff[3];
59 u32 mac_address = cmd_buff[4]; 59 u32 mac_address = cmd_buff[4];
60 60
61 u32 unk3 = cmd_buff[6]; 61 u32 unk3 = cmd_buff[6];
62 62
63 u32 wlan_comm_id = cmd_buff[15]; 63 u32 wlan_comm_id = cmd_buff[15];
64 u32 ctr_gen_id = cmd_buff[16]; 64 u32 ctr_gen_id = cmd_buff[16];
65 u32 value = cmd_buff[17]; 65 u32 value = cmd_buff[17];
66 u32 input_handle = cmd_buff[18]; 66 u32 input_handle = cmd_buff[18];
67 u32 new_buffer_size = cmd_buff[19]; 67 u32 new_buffer_size = cmd_buff[19];
68 u32 out_buffer_ptr = cmd_buff[20]; 68 u32 out_buffer_ptr = cmd_buff[20];
69 69
70 cmd_buff[1] = RESULT_SUCCESS.raw; 70 cmd_buff[1] = RESULT_SUCCESS.raw;
71 71
72 LOG_WARNING(Service_NWM, "(STUBBED) called out_buffer_size=0x%08X, unk1=0x%08X, unk2=0x%08X," 72 LOG_WARNING(Service_NWM,
73 "(STUBBED) called out_buffer_size=0x%08X, unk1=0x%08X, unk2=0x%08X,"
73 "mac_address=0x%08X, unk3=0x%08X, wlan_comm_id=0x%08X, ctr_gen_id=0x%08X," 74 "mac_address=0x%08X, unk3=0x%08X, wlan_comm_id=0x%08X, ctr_gen_id=0x%08X,"
74 "value=%u, input_handle=0x%08X, new_buffer_size=0x%08X, out_buffer_ptr=0x%08X", 75 "value=%u, input_handle=0x%08X, new_buffer_size=0x%08X, out_buffer_ptr=0x%08X",
75 out_buffer_size, unk1, unk2, mac_address, unk3, wlan_comm_id, ctr_gen_id, value, 76 out_buffer_size, unk1, unk2, mac_address, unk3, wlan_comm_id, ctr_gen_id, value,
@@ -92,46 +93,47 @@ static void RecvBeaconBroadcastData(Service::Interface* self) {
92 */ 93 */
93static void Initialize(Service::Interface* self) { 94static void Initialize(Service::Interface* self) {
94 u32* cmd_buff = Kernel::GetCommandBuffer(); 95 u32* cmd_buff = Kernel::GetCommandBuffer();
95 u32 unk1 = cmd_buff[1]; 96 u32 unk1 = cmd_buff[1];
96 u32 unk2 = cmd_buff[12]; 97 u32 unk2 = cmd_buff[12];
97 u32 value = cmd_buff[13]; 98 u32 value = cmd_buff[13];
98 u32 handle = cmd_buff[14]; 99 u32 handle = cmd_buff[14];
99 100
100 cmd_buff[1] = RESULT_SUCCESS.raw; 101 cmd_buff[1] = RESULT_SUCCESS.raw;
101 cmd_buff[2] = 0; 102 cmd_buff[2] = 0;
102 cmd_buff[3] = Kernel::g_handle_table.Create(handle_event).MoveFrom(); //TODO(purpasmart): Verify if this is a event handle 103 cmd_buff[3] = Kernel::g_handle_table.Create(handle_event)
104 .MoveFrom(); // TODO(purpasmart): Verify if this is a event handle
103 105
104 LOG_WARNING(Service_NWM, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, value=%u, handle=0x%08X", 106 LOG_WARNING(Service_NWM, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, value=%u, handle=0x%08X",
105 unk1, unk2, value, handle); 107 unk1, unk2, value, handle);
106} 108}
107 109
108const Interface::FunctionInfo FunctionTable[] = { 110const Interface::FunctionInfo FunctionTable[] = {
109 {0x00020000, nullptr, "Scrap"}, 111 {0x00020000, nullptr, "Scrap"},
110 {0x00030000, Shutdown, "Shutdown"}, 112 {0x00030000, Shutdown, "Shutdown"},
111 {0x00040402, nullptr, "CreateNetwork"}, 113 {0x00040402, nullptr, "CreateNetwork"},
112 {0x00050040, nullptr, "EjectClient"}, 114 {0x00050040, nullptr, "EjectClient"},
113 {0x00060000, nullptr, "EjectSpectator"}, 115 {0x00060000, nullptr, "EjectSpectator"},
114 {0x00070080, nullptr, "UpdateNetworkAttribute"}, 116 {0x00070080, nullptr, "UpdateNetworkAttribute"},
115 {0x00080000, nullptr, "DestroyNetwork"}, 117 {0x00080000, nullptr, "DestroyNetwork"},
116 {0x000A0000, nullptr, "DisconnectNetwork"}, 118 {0x000A0000, nullptr, "DisconnectNetwork"},
117 {0x000B0000, nullptr, "GetConnectionStatus"}, 119 {0x000B0000, nullptr, "GetConnectionStatus"},
118 {0x000D0040, nullptr, "GetNodeInformation"}, 120 {0x000D0040, nullptr, "GetNodeInformation"},
119 {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"}, 121 {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"},
120 {0x00100042, nullptr, "SetBeaconAdditionalData"}, 122 {0x00100042, nullptr, "SetBeaconAdditionalData"},
121 {0x00110040, nullptr, "GetApplicationData"}, 123 {0x00110040, nullptr, "GetApplicationData"},
122 {0x00120100, nullptr, "Bind"}, 124 {0x00120100, nullptr, "Bind"},
123 {0x00130040, nullptr, "Unbind"}, 125 {0x00130040, nullptr, "Unbind"},
124 {0x001400C0, nullptr, "RecvBroadcastDataFrame"}, 126 {0x001400C0, nullptr, "RecvBroadcastDataFrame"},
125 {0x00150080, nullptr, "SetMaxSendDelay"}, 127 {0x00150080, nullptr, "SetMaxSendDelay"},
126 {0x00170182, nullptr, "SendTo"}, 128 {0x00170182, nullptr, "SendTo"},
127 {0x001A0000, nullptr, "GetChannel"}, 129 {0x001A0000, nullptr, "GetChannel"},
128 {0x001B0302, Initialize, "Initialize"}, 130 {0x001B0302, Initialize, "Initialize"},
129 {0x001D0044, nullptr, "BeginHostingNetwork"}, 131 {0x001D0044, nullptr, "BeginHostingNetwork"},
130 {0x001E0084, nullptr, "ConnectToNetwork"}, 132 {0x001E0084, nullptr, "ConnectToNetwork"},
131 {0x001F0006, nullptr, "DecryptBeaconData"}, 133 {0x001F0006, nullptr, "DecryptBeaconData"},
132 {0x00200040, nullptr, "Flush"}, 134 {0x00200040, nullptr, "Flush"},
133 {0x00210080, nullptr, "SetProbeResponseParam"}, 135 {0x00210080, nullptr, "SetProbeResponseParam"},
134 {0x00220402, nullptr, "ScanOnConnection"}, 136 {0x00220402, nullptr, "ScanOnConnection"},
135}; 137};
136 138
137//////////////////////////////////////////////////////////////////////////////////////////////////// 139////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp
index 05d01bc48..7d91694f6 100644
--- a/src/core/hle/service/pm_app.cpp
+++ b/src/core/hle/service/pm_app.cpp
@@ -10,18 +10,18 @@
10namespace PM_APP { 10namespace PM_APP {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {
13 {0x00010140, nullptr, "LaunchTitle"}, 13 {0x00010140, nullptr, "LaunchTitle"},
14 {0x00020082, nullptr, "LaunchFIRMSetParams"}, 14 {0x00020082, nullptr, "LaunchFIRMSetParams"},
15 {0x00030080, nullptr, "TerminateProcesse"}, 15 {0x00030080, nullptr, "TerminateProcesse"},
16 {0x00040100, nullptr, "TerminateProcessTID"}, 16 {0x00040100, nullptr, "TerminateProcessTID"},
17 {0x000500C0, nullptr, "TerminateProcessTID_unknown"}, 17 {0x000500C0, nullptr, "TerminateProcessTID_unknown"},
18 {0x00070042, nullptr, "GetFIRMLaunchParams"}, 18 {0x00070042, nullptr, "GetFIRMLaunchParams"},
19 {0x00080100, nullptr, "GetTitleExheaderFlags"}, 19 {0x00080100, nullptr, "GetTitleExheaderFlags"},
20 {0x00090042, nullptr, "SetFIRMLaunchParams"}, 20 {0x00090042, nullptr, "SetFIRMLaunchParams"},
21 {0x000A0140, nullptr, "SetResourceLimit"}, 21 {0x000A0140, nullptr, "SetResourceLimit"},
22 {0x000B0140, nullptr, "GetResourceLimitMax"}, 22 {0x000B0140, nullptr, "GetResourceLimitMax"},
23 {0x000C0080, nullptr, "UnregisterProcess"}, 23 {0x000C0080, nullptr, "UnregisterProcess"},
24 {0x000D0240, nullptr, "LaunchTitleUpdate"}, 24 {0x000D0240, nullptr, "LaunchTitleUpdate"},
25}; 25};
26 26
27//////////////////////////////////////////////////////////////////////////////////////////////////// 27////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp
index e2c17d93b..80fa09f5f 100644
--- a/src/core/hle/service/ptm/ptm.cpp
+++ b/src/core/hle/service/ptm/ptm.cpp
@@ -2,21 +2,21 @@
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 "core/hle/service/ptm/ptm.h"
5#include "common/logging/log.h" 6#include "common/logging/log.h"
6#include "core/settings.h"
7#include "core/file_sys/file_backend.h" 7#include "core/file_sys/file_backend.h"
8#include "core/hle/service/fs/archive.h" 8#include "core/hle/service/fs/archive.h"
9#include "core/hle/service/ptm/ptm.h"
10#include "core/hle/service/ptm/ptm_play.h" 9#include "core/hle/service/ptm/ptm_play.h"
11#include "core/hle/service/ptm/ptm_sysm.h" 10#include "core/hle/service/ptm/ptm_sysm.h"
12#include "core/hle/service/ptm/ptm_u.h" 11#include "core/hle/service/ptm/ptm_u.h"
13#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
13#include "core/settings.h"
14 14
15namespace Service { 15namespace Service {
16namespace PTM { 16namespace PTM {
17 17
18/// Values for the default gamecoin.dat file 18/// Values for the default gamecoin.dat file
19static const GameCoin default_game_coin = { 0x4F00, 42, 0, 0, 0, 2014, 12, 29 }; 19static const GameCoin default_game_coin = {0x4F00, 42, 0, 0, 0, 2014, 12, 29};
20 20
21/// Id of the SharedExtData archive used by the PTM process 21/// Id of the SharedExtData archive used by the PTM process
22static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; 22static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0};
@@ -51,7 +51,8 @@ void GetBatteryLevel(Service::Interface* self) {
51 // it returns a valid result without implementing full functionality. 51 // it returns a valid result without implementing full functionality.
52 52
53 cmd_buff[1] = RESULT_SUCCESS.raw; 53 cmd_buff[1] = RESULT_SUCCESS.raw;
54 cmd_buff[2] = static_cast<u32>(ChargeLevels::CompletelyFull); // Set to a completely full battery 54 cmd_buff[2] =
55 static_cast<u32>(ChargeLevels::CompletelyFull); // Set to a completely full battery
55 56
56 LOG_WARNING(Service_PTM, "(STUBBED) called"); 57 LOG_WARNING(Service_PTM, "(STUBBED) called");
57} 58}
@@ -94,7 +95,8 @@ void CheckNew3DS(Service::Interface* self) {
94 const bool is_new_3ds = Settings::values.is_new_3ds; 95 const bool is_new_3ds = Settings::values.is_new_3ds;
95 96
96 if (is_new_3ds) { 97 if (is_new_3ds) {
97 LOG_CRITICAL(Service_PTM, "The option 'is_new_3ds' is enabled as part of the 'System' settings. Citra does not fully support New 3DS emulation yet!"); 98 LOG_CRITICAL(Service_PTM, "The option 'is_new_3ds' is enabled as part of the 'System' "
99 "settings. Citra does not fully support New 3DS emulation yet!");
98 } 100 }
99 101
100 cmd_buff[1] = RESULT_SUCCESS.raw; 102 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -111,15 +113,19 @@ void Init() {
111 shell_open = true; 113 shell_open = true;
112 battery_is_charging = true; 114 battery_is_charging = true;
113 115
114 // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't exist 116 // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't
117 // exist
115 FileSys::Path archive_path(ptm_shared_extdata_id); 118 FileSys::Path archive_path(ptm_shared_extdata_id);
116 auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); 119 auto archive_result =
120 Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
117 // If the archive didn't exist, create the files inside 121 // If the archive didn't exist, create the files inside
118 if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { 122 if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) {
119 // Format the archive to create the directories 123 // Format the archive to create the directories
120 Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, FileSys::ArchiveFormatInfo(), archive_path); 124 Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData,
125 FileSys::ArchiveFormatInfo(), archive_path);
121 // Open it again to get a valid archive now that the folder exists 126 // Open it again to get a valid archive now that the folder exists
122 archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); 127 archive_result =
128 Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
123 ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!"); 129 ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!");
124 130
125 FileSys::Path gamecoin_path("gamecoin.dat"); 131 FileSys::Path gamecoin_path("gamecoin.dat");
@@ -127,17 +133,18 @@ void Init() {
127 open_mode.write_flag.Assign(1); 133 open_mode.write_flag.Assign(1);
128 open_mode.create_flag.Assign(1); 134 open_mode.create_flag.Assign(1);
129 // Open the file and write the default gamecoin information 135 // Open the file and write the default gamecoin information
130 auto gamecoin_result = Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode); 136 auto gamecoin_result =
137 Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode);
131 if (gamecoin_result.Succeeded()) { 138 if (gamecoin_result.Succeeded()) {
132 auto gamecoin = gamecoin_result.MoveFrom(); 139 auto gamecoin = gamecoin_result.MoveFrom();
133 gamecoin->backend->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin)); 140 gamecoin->backend->Write(0, sizeof(GameCoin), 1,
141 reinterpret_cast<const u8*>(&default_game_coin));
134 gamecoin->backend->Close(); 142 gamecoin->backend->Close();
135 } 143 }
136 } 144 }
137} 145}
138 146
139void Shutdown() { 147void Shutdown() {
140
141} 148}
142 149
143} // namespace PTM 150} // namespace PTM
diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h
index 7ef8877c7..6e163a6f9 100644
--- a/src/core/hle/service/ptm/ptm.h
+++ b/src/core/hle/service/ptm/ptm.h
@@ -14,23 +14,24 @@ namespace PTM {
14 14
15/// Charge levels used by PTM functions 15/// Charge levels used by PTM functions
16enum class ChargeLevels : u32 { 16enum class ChargeLevels : u32 {
17 CriticalBattery = 1, 17 CriticalBattery = 1,
18 LowBattery = 2, 18 LowBattery = 2,
19 HalfFull = 3, 19 HalfFull = 3,
20 MostlyFull = 4, 20 MostlyFull = 4,
21 CompletelyFull = 5, 21 CompletelyFull = 5,
22}; 22};
23 23
24/** 24/**
25 * Represents the gamecoin file structure in the SharedExtData archive 25 * Represents the gamecoin file structure in the SharedExtData archive
26 * More information in 3dbrew (http://www.3dbrew.org/wiki/Extdata#Shared_Extdata_0xf000000b_gamecoin.dat) 26 * More information in 3dbrew
27 * (http://www.3dbrew.org/wiki/Extdata#Shared_Extdata_0xf000000b_gamecoin.dat)
27 */ 28 */
28struct GameCoin { 29struct GameCoin {
29 u32 magic; ///< Magic number: 0x4F00 30 u32 magic; ///< Magic number: 0x4F00
30 u16 total_coins; ///< Total Play Coins 31 u16 total_coins; ///< Total Play Coins
31 u16 total_coins_on_date; ///< Total Play Coins obtained on the date stored below. 32 u16 total_coins_on_date; ///< Total Play Coins obtained on the date stored below.
32 u32 step_count; ///< Total step count at the time a new Play Coin was obtained. 33 u32 step_count; ///< Total step count at the time a new Play Coin was obtained.
33 u32 last_step_count; ///< Step count for the day the last Play Coin was obtained 34 u32 last_step_count; ///< Step count for the day the last Play Coin was obtained
34 u16 year; 35 u16 year;
35 u8 month; 36 u8 month;
36 u8 day; 37 u8 day;
diff --git a/src/core/hle/service/ptm/ptm_play.cpp b/src/core/hle/service/ptm/ptm_play.cpp
index ca5dd0403..2e0c6e1a3 100644
--- a/src/core/hle/service/ptm/ptm_play.cpp
+++ b/src/core/hle/service/ptm/ptm_play.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace PTM { 8namespace PTM {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x08070082, nullptr, "GetPlayHistory"}, 11 {0x08070082, nullptr, "GetPlayHistory"},
12 {0x08080000, nullptr, "GetPlayHistoryStart"}, 12 {0x08080000, nullptr, "GetPlayHistoryStart"},
13 {0x08090000, nullptr, "GetPlayHistoryLength"}, 13 {0x08090000, nullptr, "GetPlayHistoryLength"},
14 {0x080B0080, nullptr, "CalcPlayHistoryStart"}, 14 {0x080B0080, nullptr, "CalcPlayHistoryStart"},
15}; 15};
16 16
17PTM_Play_Interface::PTM_Play_Interface() { 17PTM_Play_Interface::PTM_Play_Interface() {
diff --git a/src/core/hle/service/ptm/ptm_play.h b/src/core/hle/service/ptm/ptm_play.h
index e5c3e04df..47f229581 100644
--- a/src/core/hle/service/ptm/ptm_play.h
+++ b/src/core/hle/service/ptm/ptm_play.h
@@ -13,9 +13,9 @@ class PTM_Play_Interface : public Service::Interface {
13public: 13public:
14 PTM_Play_Interface(); 14 PTM_Play_Interface();
15 15
16std::string GetPortName() const override { 16 std::string GetPortName() const override {
17 return "ptm:play"; 17 return "ptm:play";
18} 18 }
19}; 19};
20 20
21} // namespace PTM 21} // namespace PTM
diff --git a/src/core/hle/service/ptm/ptm_sysm.cpp b/src/core/hle/service/ptm/ptm_sysm.cpp
index cc4ef1101..693158dbf 100644
--- a/src/core/hle/service/ptm/ptm_sysm.cpp
+++ b/src/core/hle/service/ptm/ptm_sysm.cpp
@@ -9,37 +9,37 @@ namespace Service {
9namespace PTM { 9namespace PTM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x040100C0, nullptr, "SetRtcAlarmEx"}, 12 {0x040100C0, nullptr, "SetRtcAlarmEx"},
13 {0x04020042, nullptr, "ReplySleepQuery"}, 13 {0x04020042, nullptr, "ReplySleepQuery"},
14 {0x04030042, nullptr, "NotifySleepPreparationComplete"}, 14 {0x04030042, nullptr, "NotifySleepPreparationComplete"},
15 {0x04040102, nullptr, "SetWakeupTrigger"}, 15 {0x04040102, nullptr, "SetWakeupTrigger"},
16 {0x04050000, nullptr, "GetAwakeReason"}, 16 {0x04050000, nullptr, "GetAwakeReason"},
17 {0x04060000, nullptr, "RequestSleep"}, 17 {0x04060000, nullptr, "RequestSleep"},
18 {0x040700C0, nullptr, "ShutdownAsync"}, 18 {0x040700C0, nullptr, "ShutdownAsync"},
19 {0x04080000, nullptr, "Awake"}, 19 {0x04080000, nullptr, "Awake"},
20 {0x04090080, nullptr, "RebootAsync"}, 20 {0x04090080, nullptr, "RebootAsync"},
21 {0x040A0000, CheckNew3DS, "CheckNew3DS"}, 21 {0x040A0000, CheckNew3DS, "CheckNew3DS"},
22 {0x08010640, nullptr, "SetInfoLEDPattern"}, 22 {0x08010640, nullptr, "SetInfoLEDPattern"},
23 {0x08020040, nullptr, "SetInfoLEDPatternHeader"}, 23 {0x08020040, nullptr, "SetInfoLEDPatternHeader"},
24 {0x08030000, nullptr, "GetInfoLEDStatus"}, 24 {0x08030000, nullptr, "GetInfoLEDStatus"},
25 {0x08040040, nullptr, "SetBatteryEmptyLEDPattern"}, 25 {0x08040040, nullptr, "SetBatteryEmptyLEDPattern"},
26 {0x08050000, nullptr, "ClearStepHistory"}, 26 {0x08050000, nullptr, "ClearStepHistory"},
27 {0x080600C2, nullptr, "SetStepHistory"}, 27 {0x080600C2, nullptr, "SetStepHistory"},
28 {0x08070082, nullptr, "GetPlayHistory"}, 28 {0x08070082, nullptr, "GetPlayHistory"},
29 {0x08080000, nullptr, "GetPlayHistoryStart"}, 29 {0x08080000, nullptr, "GetPlayHistoryStart"},
30 {0x08090000, nullptr, "GetPlayHistoryLength"}, 30 {0x08090000, nullptr, "GetPlayHistoryLength"},
31 {0x080A0000, nullptr, "ClearPlayHistory"}, 31 {0x080A0000, nullptr, "ClearPlayHistory"},
32 {0x080B0080, nullptr, "CalcPlayHistoryStart"}, 32 {0x080B0080, nullptr, "CalcPlayHistoryStart"},
33 {0x080C0080, nullptr, "SetUserTime"}, 33 {0x080C0080, nullptr, "SetUserTime"},
34 {0x080D0000, nullptr, "InvalidateSystemTime"}, 34 {0x080D0000, nullptr, "InvalidateSystemTime"},
35 {0x080E0140, nullptr, "NotifyPlayEvent"}, 35 {0x080E0140, nullptr, "NotifyPlayEvent"},
36 {0x080F0000, IsLegacyPowerOff, "IsLegacyPowerOff"}, 36 {0x080F0000, IsLegacyPowerOff, "IsLegacyPowerOff"},
37 {0x08100000, nullptr, "ClearLegacyPowerOff"}, 37 {0x08100000, nullptr, "ClearLegacyPowerOff"},
38 {0x08110000, GetShellState, "GetShellState"}, 38 {0x08110000, GetShellState, "GetShellState"},
39 {0x08120000, nullptr, "IsShutdownByBatteryEmpty"}, 39 {0x08120000, nullptr, "IsShutdownByBatteryEmpty"},
40 {0x08130000, nullptr, "FormatSavedata"}, 40 {0x08130000, nullptr, "FormatSavedata"},
41 {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"}, 41 {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"},
42 {0x08180040, nullptr, "ConfigureNew3DSCPU"}, 42 {0x08180040, nullptr, "ConfigureNew3DSCPU"},
43}; 43};
44 44
45PTM_Sysm_Interface::PTM_Sysm_Interface() { 45PTM_Sysm_Interface::PTM_Sysm_Interface() {
diff --git a/src/core/hle/service/ptm/ptm_u.cpp b/src/core/hle/service/ptm/ptm_u.cpp
index 17e764866..65e868393 100644
--- a/src/core/hle/service/ptm/ptm_u.cpp
+++ b/src/core/hle/service/ptm/ptm_u.cpp
@@ -9,21 +9,21 @@ namespace Service {
9namespace PTM { 9namespace PTM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010002, nullptr, "RegisterAlarmClient"}, 12 {0x00010002, nullptr, "RegisterAlarmClient"},
13 {0x00020080, nullptr, "SetRtcAlarm"}, 13 {0x00020080, nullptr, "SetRtcAlarm"},
14 {0x00030000, nullptr, "GetRtcAlarm"}, 14 {0x00030000, nullptr, "GetRtcAlarm"},
15 {0x00040000, nullptr, "CancelRtcAlarm"}, 15 {0x00040000, nullptr, "CancelRtcAlarm"},
16 {0x00050000, GetAdapterState, "GetAdapterState"}, 16 {0x00050000, GetAdapterState, "GetAdapterState"},
17 {0x00060000, GetShellState, "GetShellState"}, 17 {0x00060000, GetShellState, "GetShellState"},
18 {0x00070000, GetBatteryLevel, "GetBatteryLevel"}, 18 {0x00070000, GetBatteryLevel, "GetBatteryLevel"},
19 {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"}, 19 {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"},
20 {0x00090000, nullptr, "GetPedometerState"}, 20 {0x00090000, nullptr, "GetPedometerState"},
21 {0x000A0042, nullptr, "GetStepHistoryEntry"}, 21 {0x000A0042, nullptr, "GetStepHistoryEntry"},
22 {0x000B00C2, nullptr, "GetStepHistory"}, 22 {0x000B00C2, nullptr, "GetStepHistory"},
23 {0x000C0000, GetTotalStepCount, "GetTotalStepCount"}, 23 {0x000C0000, GetTotalStepCount, "GetTotalStepCount"},
24 {0x000D0040, nullptr, "SetPedometerRecordingMode"}, 24 {0x000D0040, nullptr, "SetPedometerRecordingMode"},
25 {0x000E0000, nullptr, "GetPedometerRecordingMode"}, 25 {0x000E0000, nullptr, "GetPedometerRecordingMode"},
26 {0x000F0084, nullptr, "GetStepHistoryAll"}, 26 {0x000F0084, nullptr, "GetStepHistoryAll"},
27}; 27};
28 28
29PTM_U_Interface::PTM_U_Interface() { 29PTM_U_Interface::PTM_U_Interface() {
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 5b8440b77..a531aad87 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -5,7 +5,6 @@
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "common/string_util.h" 6#include "common/string_util.h"
7 7
8#include "core/hle/service/service.h"
9#include "core/hle/service/ac_u.h" 8#include "core/hle/service/ac_u.h"
10#include "core/hle/service/act_a.h" 9#include "core/hle/service/act_a.h"
11#include "core/hle/service/act_u.h" 10#include "core/hle/service/act_u.h"
@@ -19,6 +18,7 @@
19#include "core/hle/service/ns_s.h" 18#include "core/hle/service/ns_s.h"
20#include "core/hle/service/nwm_uds.h" 19#include "core/hle/service/nwm_uds.h"
21#include "core/hle/service/pm_app.h" 20#include "core/hle/service/pm_app.h"
21#include "core/hle/service/service.h"
22#include "core/hle/service/soc_u.h" 22#include "core/hle/service/soc_u.h"
23#include "core/hle/service/srv.h" 23#include "core/hle/service/srv.h"
24#include "core/hle/service/ssl_c.h" 24#include "core/hle/service/ssl_c.h"
@@ -29,10 +29,10 @@
29#include "core/hle/service/boss/boss.h" 29#include "core/hle/service/boss/boss.h"
30#include "core/hle/service/cam/cam.h" 30#include "core/hle/service/cam/cam.h"
31#include "core/hle/service/cecd/cecd.h" 31#include "core/hle/service/cecd/cecd.h"
32#include "core/hle/service/cfg/cfg.h"
32#include "core/hle/service/dlp/dlp.h" 33#include "core/hle/service/dlp/dlp.h"
33#include "core/hle/service/frd/frd.h" 34#include "core/hle/service/frd/frd.h"
34#include "core/hle/service/fs/archive.h" 35#include "core/hle/service/fs/archive.h"
35#include "core/hle/service/cfg/cfg.h"
36#include "core/hle/service/hid/hid.h" 36#include "core/hle/service/hid/hid.h"
37#include "core/hle/service/ir/ir.h" 37#include "core/hle/service/ir/ir.h"
38#include "core/hle/service/ldr_ro/ldr_ro.h" 38#include "core/hle/service/ldr_ro/ldr_ro.h"
@@ -50,11 +50,13 @@ std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
50 * Creates a function string for logging, complete with the name (or header code, depending 50 * Creates a function string for logging, complete with the name (or header code, depending
51 * on what's passed in) the port name, and all the cmd_buff arguments. 51 * on what's passed in) the port name, and all the cmd_buff arguments.
52 */ 52 */
53static std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) { 53static std::string MakeFunctionString(const char* name, const char* port_name,
54 const u32* cmd_buff) {
54 // Number of params == bits 0-5 + bits 6-11 55 // Number of params == bits 0-5 + bits 6-11
55 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); 56 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
56 57
57 std::string function_string = Common::StringFromFormat("function '%s': port=%s", name, port_name); 58 std::string function_string =
59 Common::StringFromFormat("function '%s': port=%s", name, port_name);
58 for (int i = 1; i <= num_params; ++i) { 60 for (int i = 1; i <= num_params; ++i) {
59 function_string += Common::StringFromFormat(", cmd_buff[%i]=0x%X", i, cmd_buff[i]); 61 function_string += Common::StringFromFormat(", cmd_buff[%i]=0x%X", i, cmd_buff[i]);
60 } 62 }
@@ -66,14 +68,19 @@ ResultVal<bool> Interface::SyncRequest() {
66 auto itr = m_functions.find(cmd_buff[0]); 68 auto itr = m_functions.find(cmd_buff[0]);
67 69
68 if (itr == m_functions.end() || itr->second.func == nullptr) { 70 if (itr == m_functions.end() || itr->second.func == nullptr) {
69 std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name; 71 std::string function_name = (itr == m_functions.end())
70 LOG_ERROR(Service, "unknown / unimplemented %s", MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str()); 72 ? Common::StringFromFormat("0x%08X", cmd_buff[0])
73 : itr->second.name;
74 LOG_ERROR(
75 Service, "unknown / unimplemented %s",
76 MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str());
71 77
72 // TODO(bunnei): Hack - ignore error 78 // TODO(bunnei): Hack - ignore error
73 cmd_buff[1] = 0; 79 cmd_buff[1] = 0;
74 return MakeResult<bool>(false); 80 return MakeResult<bool>(false);
75 } 81 }
76 LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str()); 82 LOG_TRACE(Service, "%s",
83 MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
77 84
78 itr->second.func(this); 85 itr->second.func(this);
79 86
@@ -163,6 +170,4 @@ void Shutdown() {
163 g_kernel_named_ports.clear(); 170 g_kernel_named_ports.clear();
164 LOG_DEBUG(Service, "shutdown OK"); 171 LOG_DEBUG(Service, "shutdown OK");
165} 172}
166
167
168} 173}
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index f31135212..cd216f27e 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -28,13 +28,15 @@ class Interface : public Kernel::Session {
28 // just something that encapsulates a session and acts as a helper to implement service 28 // just something that encapsulates a session and acts as a helper to implement service
29 // processes. 29 // processes.
30public: 30public:
31 std::string GetName() const override { return GetPortName(); } 31 std::string GetName() const override {
32 return GetPortName();
33 }
32 34
33 typedef void (*Function)(Interface*); 35 typedef void (*Function)(Interface*);
34 36
35 struct FunctionInfo { 37 struct FunctionInfo {
36 u32 id; 38 u32 id;
37 Function func; 39 Function func;
38 const char* name; 40 const char* name;
39 }; 41 };
40 42
@@ -49,7 +51,6 @@ public:
49 ResultVal<bool> SyncRequest() override; 51 ResultVal<bool> SyncRequest() override;
50 52
51protected: 53protected:
52
53 /** 54 /**
54 * Registers the functions in the service 55 * Registers the functions in the service
55 */ 56 */
@@ -62,7 +63,6 @@ protected:
62 63
63private: 64private:
64 boost::container::flat_map<u32, FunctionInfo> m_functions; 65 boost::container::flat_map<u32, FunctionInfo> m_functions;
65
66}; 66};
67 67
68/// Initialize ServiceManager 68/// Initialize ServiceManager
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index 9b285567b..695b286c0 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -19,40 +19,40 @@
19#include "core/memory.h" 19#include "core/memory.h"
20 20
21#ifdef _WIN32 21#ifdef _WIN32
22 #include <winsock2.h> 22#include <winsock2.h>
23 #include <ws2tcpip.h> 23#include <ws2tcpip.h>
24 24
25 // MinGW does not define several errno constants 25// MinGW does not define several errno constants
26 #ifndef _MSC_VER 26#ifndef _MSC_VER
27 #define EBADMSG 104 27#define EBADMSG 104
28 #define ENODATA 120 28#define ENODATA 120
29 #define ENOMSG 122 29#define ENOMSG 122
30 #define ENOSR 124 30#define ENOSR 124
31 #define ENOSTR 125 31#define ENOSTR 125
32 #define ETIME 137 32#define ETIME 137
33 #define EIDRM 2001 33#define EIDRM 2001
34 #define ENOLINK 2002 34#define ENOLINK 2002
35 #endif // _MSC_VER 35#endif // _MSC_VER
36#else 36#else
37 #include <cerrno> 37#include <cerrno>
38 #include <fcntl.h> 38#include <fcntl.h>
39 #include <netinet/in.h> 39#include <netdb.h>
40 #include <netdb.h> 40#include <netinet/in.h>
41 #include <poll.h> 41#include <poll.h>
42 #include <sys/socket.h> 42#include <sys/socket.h>
43 #include <unistd.h> 43#include <unistd.h>
44#endif 44#endif
45 45
46#ifdef _WIN32 46#ifdef _WIN32
47# define WSAEAGAIN WSAEWOULDBLOCK 47#define WSAEAGAIN WSAEWOULDBLOCK
48# define WSAEMULTIHOP -1 // Invalid dummy value 48#define WSAEMULTIHOP -1 // Invalid dummy value
49# define ERRNO(x) WSA##x 49#define ERRNO(x) WSA##x
50# define GET_ERRNO WSAGetLastError() 50#define GET_ERRNO WSAGetLastError()
51# define poll(x, y, z) WSAPoll(x, y, z); 51#define poll(x, y, z) WSAPoll(x, y, z);
52#else 52#else
53# define ERRNO(x) x 53#define ERRNO(x) x
54# define GET_ERRNO errno 54#define GET_ERRNO errno
55# define closesocket(x) close(x) 55#define closesocket(x) close(x)
56#endif 56#endif
57 57
58static const s32 SOCKET_ERROR_VALUE = -1; 58static const s32 SOCKET_ERROR_VALUE = -1;
@@ -63,84 +63,82 @@ static const s32 SOCKET_ERROR_VALUE = -1;
63namespace SOC_U { 63namespace SOC_U {
64 64
65/// Holds the translation from system network errors to 3DS network errors 65/// Holds the translation from system network errors to 3DS network errors
66static const std::unordered_map<int, int> error_map = { { 66static const std::unordered_map<int, int> error_map = {{{E2BIG, 1},
67 { E2BIG, 1 }, 67 {ERRNO(EACCES), 2},
68 { ERRNO(EACCES), 2 }, 68 {ERRNO(EADDRINUSE), 3},
69 { ERRNO(EADDRINUSE), 3 }, 69 {ERRNO(EADDRNOTAVAIL), 4},
70 { ERRNO(EADDRNOTAVAIL), 4 }, 70 {ERRNO(EAFNOSUPPORT), 5},
71 { ERRNO(EAFNOSUPPORT), 5 }, 71 {ERRNO(EAGAIN), 6},
72 { ERRNO(EAGAIN), 6 }, 72 {ERRNO(EALREADY), 7},
73 { ERRNO(EALREADY), 7 }, 73 {ERRNO(EBADF), 8},
74 { ERRNO(EBADF), 8 }, 74 {EBADMSG, 9},
75 { EBADMSG, 9 }, 75 {EBUSY, 10},
76 { EBUSY, 10 }, 76 {ECANCELED, 11},
77 { ECANCELED, 11 }, 77 {ECHILD, 12},
78 { ECHILD, 12 }, 78 {ERRNO(ECONNABORTED), 13},
79 { ERRNO(ECONNABORTED), 13 }, 79 {ERRNO(ECONNREFUSED), 14},
80 { ERRNO(ECONNREFUSED), 14 }, 80 {ERRNO(ECONNRESET), 15},
81 { ERRNO(ECONNRESET), 15 }, 81 {EDEADLK, 16},
82 { EDEADLK, 16 }, 82 {ERRNO(EDESTADDRREQ), 17},
83 { ERRNO(EDESTADDRREQ), 17 }, 83 {EDOM, 18},
84 { EDOM, 18 }, 84 {ERRNO(EDQUOT), 19},
85 { ERRNO(EDQUOT), 19 }, 85 {EEXIST, 20},
86 { EEXIST, 20 }, 86 {ERRNO(EFAULT), 21},
87 { ERRNO(EFAULT), 21 }, 87 {EFBIG, 22},
88 { EFBIG, 22 }, 88 {ERRNO(EHOSTUNREACH), 23},
89 { ERRNO(EHOSTUNREACH), 23 }, 89 {EIDRM, 24},
90 { EIDRM, 24 }, 90 {EILSEQ, 25},
91 { EILSEQ, 25 }, 91 {ERRNO(EINPROGRESS), 26},
92 { ERRNO(EINPROGRESS), 26 }, 92 {ERRNO(EINTR), 27},
93 { ERRNO(EINTR), 27 }, 93 {ERRNO(EINVAL), 28},
94 { ERRNO(EINVAL), 28 }, 94 {EIO, 29},
95 { EIO, 29 }, 95 {ERRNO(EISCONN), 30},
96 { ERRNO(EISCONN), 30 }, 96 {EISDIR, 31},
97 { EISDIR, 31 }, 97 {ERRNO(ELOOP), 32},
98 { ERRNO(ELOOP), 32 }, 98 {ERRNO(EMFILE), 33},
99 { ERRNO(EMFILE), 33 }, 99 {EMLINK, 34},
100 { EMLINK, 34 }, 100 {ERRNO(EMSGSIZE), 35},
101 { ERRNO(EMSGSIZE), 35 }, 101 {ERRNO(EMULTIHOP), 36},
102 { ERRNO(EMULTIHOP), 36 }, 102 {ERRNO(ENAMETOOLONG), 37},
103 { ERRNO(ENAMETOOLONG), 37 }, 103 {ERRNO(ENETDOWN), 38},
104 { ERRNO(ENETDOWN), 38 }, 104 {ERRNO(ENETRESET), 39},
105 { ERRNO(ENETRESET), 39 }, 105 {ERRNO(ENETUNREACH), 40},
106 { ERRNO(ENETUNREACH), 40 }, 106 {ENFILE, 41},
107 { ENFILE, 41 }, 107 {ERRNO(ENOBUFS), 42},
108 { ERRNO(ENOBUFS), 42 }, 108 {ENODATA, 43},
109 { ENODATA, 43 }, 109 {ENODEV, 44},
110 { ENODEV, 44 }, 110 {ENOENT, 45},
111 { ENOENT, 45 }, 111 {ENOEXEC, 46},
112 { ENOEXEC, 46 }, 112 {ENOLCK, 47},
113 { ENOLCK, 47 }, 113 {ENOLINK, 48},
114 { ENOLINK, 48 }, 114 {ENOMEM, 49},
115 { ENOMEM, 49 }, 115 {ENOMSG, 50},
116 { ENOMSG, 50 }, 116 {ERRNO(ENOPROTOOPT), 51},
117 { ERRNO(ENOPROTOOPT), 51 }, 117 {ENOSPC, 52},
118 { ENOSPC, 52 }, 118 {ENOSR, 53},
119 { ENOSR, 53 }, 119 {ENOSTR, 54},
120 { ENOSTR, 54 }, 120 {ENOSYS, 55},
121 { ENOSYS, 55 }, 121 {ERRNO(ENOTCONN), 56},
122 { ERRNO(ENOTCONN), 56 }, 122 {ENOTDIR, 57},
123 { ENOTDIR, 57 }, 123 {ERRNO(ENOTEMPTY), 58},
124 { ERRNO(ENOTEMPTY), 58 }, 124 {ERRNO(ENOTSOCK), 59},
125 { ERRNO(ENOTSOCK), 59 }, 125 {ENOTSUP, 60},
126 { ENOTSUP, 60 }, 126 {ENOTTY, 61},
127 { ENOTTY, 61 }, 127 {ENXIO, 62},
128 { ENXIO, 62 }, 128 {ERRNO(EOPNOTSUPP), 63},
129 { ERRNO(EOPNOTSUPP), 63 }, 129 {EOVERFLOW, 64},
130 { EOVERFLOW, 64 }, 130 {EPERM, 65},
131 { EPERM, 65 }, 131 {EPIPE, 66},
132 { EPIPE, 66 }, 132 {EPROTO, 67},
133 { EPROTO, 67 }, 133 {ERRNO(EPROTONOSUPPORT), 68},
134 { ERRNO(EPROTONOSUPPORT), 68 }, 134 {ERRNO(EPROTOTYPE), 69},
135 { ERRNO(EPROTOTYPE), 69 }, 135 {ERANGE, 70},
136 { ERANGE, 70 }, 136 {EROFS, 71},
137 { EROFS, 71 }, 137 {ESPIPE, 72},
138 { ESPIPE, 72 }, 138 {ESRCH, 73},
139 { ESRCH, 73 }, 139 {ERRNO(ESTALE), 74},
140 { ERRNO(ESTALE), 74 }, 140 {ETIME, 75},
141 { ETIME, 75 }, 141 {ERRNO(ETIMEDOUT), 76}}};
142 { ERRNO(ETIMEDOUT), 76 }
143}};
144 142
145/// Converts a network error from platform-specific to 3ds-specific 143/// Converts a network error from platform-specific to 3ds-specific
146static int TranslateError(int error) { 144static int TranslateError(int error) {
@@ -153,21 +151,21 @@ static int TranslateError(int error) {
153 151
154/// Holds the translation from system network socket options to 3DS network socket options 152/// Holds the translation from system network socket options to 3DS network socket options
155/// Note: -1 = No effect/unavailable 153/// Note: -1 = No effect/unavailable
156static const std::unordered_map<int, int> sockopt_map = { { 154static const std::unordered_map<int, int> sockopt_map = {{
157 { 0x0004, SO_REUSEADDR }, 155 {0x0004, SO_REUSEADDR},
158 { 0x0080, -1 }, 156 {0x0080, -1},
159 { 0x0100, -1 }, 157 {0x0100, -1},
160 { 0x1001, SO_SNDBUF }, 158 {0x1001, SO_SNDBUF},
161 { 0x1002, SO_RCVBUF }, 159 {0x1002, SO_RCVBUF},
162 { 0x1003, -1 }, 160 {0x1003, -1},
163#ifdef _WIN32 161#ifdef _WIN32
164 /// Unsupported in WinSock2 162 /// Unsupported in WinSock2
165 { 0x1004, -1 }, 163 {0x1004, -1},
166#else 164#else
167 { 0x1004, SO_RCVLOWAT }, 165 {0x1004, SO_RCVLOWAT},
168#endif 166#endif
169 { 0x1008, SO_TYPE }, 167 {0x1008, SO_TYPE},
170 { 0x1009, SO_ERROR }, 168 {0x1009, SO_ERROR},
171}}; 169}};
172 170
173/// Converts a socket option from 3ds-specific to platform-specific 171/// Converts a socket option from 3ds-specific to platform-specific
@@ -203,7 +201,8 @@ struct CTRPollFD {
203 return *this; 201 return *this;
204 } 202 }
205 203
206 /// Translates the resulting events of a Poll operation from platform-specific to 3ds specific 204 /// Translates the resulting events of a Poll operation from platform-specific to 3ds
205 /// specific
207 static Events TranslateTo3DS(u32 input_event) { 206 static Events TranslateTo3DS(u32 input_event) {
208 Events ev = {}; 207 Events ev = {};
209 if (input_event & POLLIN) 208 if (input_event & POLLIN)
@@ -221,7 +220,8 @@ struct CTRPollFD {
221 return ev; 220 return ev;
222 } 221 }
223 222
224 /// Translates the resulting events of a Poll operation from 3ds specific to platform specific 223 /// Translates the resulting events of a Poll operation from 3ds specific to platform
224 /// specific
225 static u32 TranslateToPlatform(Events input_event) { 225 static u32 TranslateToPlatform(Events input_event) {
226 u32 ret = 0; 226 u32 ret = 0;
227 if (input_event.pollin) 227 if (input_event.pollin)
@@ -239,7 +239,7 @@ struct CTRPollFD {
239 return ret; 239 return ret;
240 } 240 }
241 }; 241 };
242 Events events; ///< Events to poll for (input) 242 Events events; ///< Events to poll for (input)
243 Events revents; ///< Events received (output) 243 Events revents; ///< Events received (output)
244 244
245 /// Converts a platform-specific pollfd to a 3ds specific structure 245 /// Converts a platform-specific pollfd to a 3ds specific structure
@@ -265,17 +265,17 @@ struct CTRPollFD {
265union CTRSockAddr { 265union CTRSockAddr {
266 /// Structure to represent a raw sockaddr 266 /// Structure to represent a raw sockaddr
267 struct { 267 struct {
268 u8 len; ///< The length of the entire structure, only the set fields count 268 u8 len; ///< The length of the entire structure, only the set fields count
269 u8 sa_family; ///< The address family of the sockaddr 269 u8 sa_family; ///< The address family of the sockaddr
270 u8 sa_data[0x1A]; ///< The extra data, this varies, depending on the address family 270 u8 sa_data[0x1A]; ///< The extra data, this varies, depending on the address family
271 } raw; 271 } raw;
272 272
273 /// Structure to represent the 3ds' sockaddr_in structure 273 /// Structure to represent the 3ds' sockaddr_in structure
274 struct CTRSockAddrIn { 274 struct CTRSockAddrIn {
275 u8 len; ///< The length of the entire structure 275 u8 len; ///< The length of the entire structure
276 u8 sin_family; ///< The address family of the sockaddr_in 276 u8 sin_family; ///< The address family of the sockaddr_in
277 u16 sin_port; ///< The port associated with this sockaddr_in 277 u16 sin_port; ///< The port associated with this sockaddr_in
278 u32 sin_addr; ///< The actual address of the sockaddr_in 278 u32 sin_addr; ///< The actual address of the sockaddr_in
279 } in; 279 } in;
280 280
281 /// Convert a 3DS CTRSockAddr to a platform-specific sockaddr 281 /// Convert a 3DS CTRSockAddr to a platform-specific sockaddr
@@ -286,8 +286,7 @@ union CTRSockAddr {
286 286
287 // We can not guarantee ABI compatibility between platforms so we copy the fields manually 287 // We can not guarantee ABI compatibility between platforms so we copy the fields manually
288 switch (result.sa_family) { 288 switch (result.sa_family) {
289 case AF_INET: 289 case AF_INET: {
290 {
291 sockaddr_in* result_in = reinterpret_cast<sockaddr_in*>(&result); 290 sockaddr_in* result_in = reinterpret_cast<sockaddr_in*>(&result);
292 result_in->sin_port = ctr_addr.in.sin_port; 291 result_in->sin_port = ctr_addr.in.sin_port;
293 result_in->sin_addr.s_addr = ctr_addr.in.sin_addr; 292 result_in->sin_addr.s_addr = ctr_addr.in.sin_addr;
@@ -307,8 +306,7 @@ union CTRSockAddr {
307 result.raw.sa_family = static_cast<u8>(addr.sa_family); 306 result.raw.sa_family = static_cast<u8>(addr.sa_family);
308 // We can not guarantee ABI compatibility between platforms so we copy the fields manually 307 // We can not guarantee ABI compatibility between platforms so we copy the fields manually
309 switch (result.raw.sa_family) { 308 switch (result.raw.sa_family) {
310 case AF_INET: 309 case AF_INET: {
311 {
312 sockaddr_in const* addr_in = reinterpret_cast<sockaddr_in const*>(&addr); 310 sockaddr_in const* addr_in = reinterpret_cast<sockaddr_in const*>(&addr);
313 result.raw.len = sizeof(CTRSockAddrIn); 311 result.raw.len = sizeof(CTRSockAddrIn);
314 result.in.sin_port = addr_in->sin_port; 312 result.in.sin_port = addr_in->sin_port;
@@ -341,24 +339,27 @@ static void Socket(Service::Interface* self) {
341 339
342 // Only 0 is allowed according to 3dbrew, using 0 will let the OS decide which protocol to use 340 // Only 0 is allowed according to 3dbrew, using 0 will let the OS decide which protocol to use
343 if (protocol != 0) { 341 if (protocol != 0) {
344 cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code 342 cmd_buffer[1] =
343 UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code
345 return; 344 return;
346 } 345 }
347 346
348 if (domain != AF_INET) { 347 if (domain != AF_INET) {
349 cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code 348 cmd_buffer[1] =
349 UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code
350 return; 350 return;
351 } 351 }
352 352
353 if (type != SOCK_DGRAM && type != SOCK_STREAM) { 353 if (type != SOCK_DGRAM && type != SOCK_STREAM) {
354 cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code 354 cmd_buffer[1] =
355 UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code
355 return; 356 return;
356 } 357 }
357 358
358 u32 socket_handle = static_cast<u32>(::socket(domain, type, protocol)); 359 u32 socket_handle = static_cast<u32>(::socket(domain, type, protocol));
359 360
360 if ((s32)socket_handle != SOCKET_ERROR_VALUE) 361 if ((s32)socket_handle != SOCKET_ERROR_VALUE)
361 open_sockets[socket_handle] = { socket_handle, true }; 362 open_sockets[socket_handle] = {socket_handle, true};
362 363
363 int result = 0; 364 int result = 0;
364 if ((s32)socket_handle == SOCKET_ERROR_VALUE) 365 if ((s32)socket_handle == SOCKET_ERROR_VALUE)
@@ -406,8 +407,8 @@ static void Fcntl(Service::Interface* self) {
406 int result = 0; 407 int result = 0;
407 u32 posix_ret = 0; // TODO: Check what hardware returns for F_SETFL (unspecified by POSIX) 408 u32 posix_ret = 0; // TODO: Check what hardware returns for F_SETFL (unspecified by POSIX)
408 SCOPE_EXIT({ 409 SCOPE_EXIT({
409 cmd_buffer[1] = result; 410 cmd_buffer[1] = result;
410 cmd_buffer[2] = posix_ret; 411 cmd_buffer[2] = posix_ret;
411 }); 412 });
412 413
413 if (ctr_cmd == 3) { // F_GETFL 414 if (ctr_cmd == 3) { // F_GETFL
@@ -493,7 +494,7 @@ static void Accept(Service::Interface* self) {
493 u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len)); 494 u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len));
494 495
495 if ((s32)ret != SOCKET_ERROR_VALUE) 496 if ((s32)ret != SOCKET_ERROR_VALUE)
496 open_sockets[ret] = { ret, true }; 497 open_sockets[ret] = {ret, true};
497 498
498 int result = 0; 499 int result = 0;
499 if ((s32)ret == SOCKET_ERROR_VALUE) { 500 if ((s32)ret == SOCKET_ERROR_VALUE) {
@@ -573,9 +574,11 @@ static void SendTo(Service::Interface* self) {
573 int ret = -1; 574 int ret = -1;
574 if (addr_len > 0) { 575 if (addr_len > 0) {
575 sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr); 576 sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr);
576 ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, &dest_addr, sizeof(dest_addr)); 577 ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags,
578 &dest_addr, sizeof(dest_addr));
577 } else { 579 } else {
578 ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, nullptr, 0); 580 ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags,
581 nullptr, 0);
579 } 582 }
580 583
581 int result = 0; 584 int result = 0;
@@ -596,8 +599,7 @@ static void RecvFrom(Service::Interface* self) {
596 u32 flags = cmd_buffer[3]; 599 u32 flags = cmd_buffer[3];
597 socklen_t addr_len = static_cast<socklen_t>(cmd_buffer[4]); 600 socklen_t addr_len = static_cast<socklen_t>(cmd_buffer[4]);
598 601
599 struct 602 struct {
600 {
601 u32 output_buffer_descriptor; 603 u32 output_buffer_descriptor;
602 u32 output_buffer_addr; 604 u32 output_buffer_addr;
603 u32 address_buffer_descriptor; 605 u32 address_buffer_descriptor;
@@ -619,11 +621,13 @@ static void RecvFrom(Service::Interface* self) {
619 std::vector<u8> output_buff(len); 621 std::vector<u8> output_buff(len);
620 sockaddr src_addr; 622 sockaddr src_addr;
621 socklen_t src_addr_len = sizeof(src_addr); 623 socklen_t src_addr_len = sizeof(src_addr);
622 int ret = ::recvfrom(socket_handle, reinterpret_cast<char*>(output_buff.data()), len, flags, &src_addr, &src_addr_len); 624 int ret = ::recvfrom(socket_handle, reinterpret_cast<char*>(output_buff.data()), len, flags,
625 &src_addr, &src_addr_len);
623 626
624 if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { 627 if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) {
625 CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); 628 CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr);
626 Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr, sizeof(ctr_src_addr)); 629 Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr,
630 sizeof(ctr_src_addr));
627 } 631 }
628 632
629 int result = 0; 633 int result = 0;
@@ -633,7 +637,8 @@ static void RecvFrom(Service::Interface* self) {
633 total_received = 0; 637 total_received = 0;
634 } else { 638 } else {
635 // Write only the data we received to avoid overwriting parts of the buffer with zeros 639 // Write only the data we received to avoid overwriting parts of the buffer with zeros
636 Memory::WriteBlock(buffer_parameters.output_buffer_addr, output_buff.data(), total_received); 640 Memory::WriteBlock(buffer_parameters.output_buffer_addr, output_buff.data(),
641 total_received);
637 } 642 }
638 643
639 cmd_buffer[1] = result; 644 cmd_buffer[1] = result;
@@ -648,7 +653,8 @@ static void Poll(Service::Interface* self) {
648 653
649 VAddr input_fds_addr = cmd_buffer[6]; 654 VAddr input_fds_addr = cmd_buffer[6];
650 VAddr output_fds_addr = cmd_buffer[0x104 >> 2]; 655 VAddr output_fds_addr = cmd_buffer[0x104 >> 2];
651 if (!Memory::IsValidVirtualAddress(input_fds_addr) || !Memory::IsValidVirtualAddress(output_fds_addr)) { 656 if (!Memory::IsValidVirtualAddress(input_fds_addr) ||
657 !Memory::IsValidVirtualAddress(output_fds_addr)) {
652 cmd_buffer[1] = -1; // TODO(Subv): Find correct error code. 658 cmd_buffer[1] = -1; // TODO(Subv): Find correct error code.
653 return; 659 return;
654 } 660 }
@@ -656,7 +662,8 @@ static void Poll(Service::Interface* self) {
656 std::vector<CTRPollFD> ctr_fds(nfds); 662 std::vector<CTRPollFD> ctr_fds(nfds);
657 Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); 663 Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD));
658 664
659 // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes) 665 // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different
666 // sizes)
660 // so we have to copy the data 667 // so we have to copy the data
661 std::vector<pollfd> platform_pollfd(nfds); 668 std::vector<pollfd> platform_pollfd(nfds);
662 std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform); 669 std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform);
@@ -664,7 +671,8 @@ static void Poll(Service::Interface* self) {
664 const int ret = ::poll(platform_pollfd.data(), nfds, timeout); 671 const int ret = ::poll(platform_pollfd.data(), nfds, timeout);
665 672
666 // Now update the output pollfd structure 673 // Now update the output pollfd structure
667 std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), CTRPollFD::FromPlatform); 674 std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(),
675 CTRPollFD::FromPlatform);
668 676
669 Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); 677 Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD));
670 678
@@ -775,7 +783,7 @@ static void Connect(Service::Interface* self) {
775} 783}
776 784
777static void InitializeSockets(Service::Interface* self) { 785static void InitializeSockets(Service::Interface* self) {
778 // TODO(Subv): Implement 786// TODO(Subv): Implement
779#ifdef _WIN32 787#ifdef _WIN32
780 WSADATA data; 788 WSADATA data;
781 WSAStartup(MAKEWORD(2, 2), &data); 789 WSAStartup(MAKEWORD(2, 2), &data);
@@ -808,7 +816,7 @@ static void GetSockOpt(Service::Interface* self) {
808 int ret = -1; 816 int ret = -1;
809 int err = 0; 817 int err = 0;
810 818
811 if(optname < 0) { 819 if (optname < 0) {
812#ifdef _WIN32 820#ifdef _WIN32
813 err = WSAEINVAL; 821 err = WSAEINVAL;
814#else 822#else
@@ -818,7 +826,7 @@ static void GetSockOpt(Service::Interface* self) {
818 // 0x100 = static buffer offset (bytes) 826 // 0x100 = static buffer offset (bytes)
819 // + 0x4 = 2nd pointer (u32) position 827 // + 0x4 = 2nd pointer (u32) position
820 // >> 2 = convert to u32 offset instead of byte offset (cmd_buffer = u32*) 828 // >> 2 = convert to u32 offset instead of byte offset (cmd_buffer = u32*)
821 char* optval = reinterpret_cast<char *>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); 829 char* optval = reinterpret_cast<char*>(Memory::GetPointer(cmd_buffer[0x104 >> 2]));
822 830
823 ret = ::getsockopt(socket_handle, level, optname, optval, &optlen); 831 ret = ::getsockopt(socket_handle, level, optname, optval, &optlen);
824 err = 0; 832 err = 0;
@@ -842,7 +850,7 @@ static void SetSockOpt(Service::Interface* self) {
842 int ret = -1; 850 int ret = -1;
843 int err = 0; 851 int err = 0;
844 852
845 if(optname < 0) { 853 if (optname < 0) {
846#ifdef _WIN32 854#ifdef _WIN32
847 err = WSAEINVAL; 855 err = WSAEINVAL;
848#else 856#else
@@ -850,7 +858,7 @@ static void SetSockOpt(Service::Interface* self) {
850#endif 858#endif
851 } else { 859 } else {
852 socklen_t optlen = static_cast<socklen_t>(cmd_buffer[4]); 860 socklen_t optlen = static_cast<socklen_t>(cmd_buffer[4]);
853 const char* optval = reinterpret_cast<const char *>(Memory::GetPointer(cmd_buffer[8])); 861 const char* optval = reinterpret_cast<const char*>(Memory::GetPointer(cmd_buffer[8]));
854 862
855 ret = static_cast<u32>(::setsockopt(socket_handle, level, optname, optval, optlen)); 863 ret = static_cast<u32>(::setsockopt(socket_handle, level, optname, optval, optlen));
856 err = 0; 864 err = 0;
@@ -865,39 +873,39 @@ static void SetSockOpt(Service::Interface* self) {
865} 873}
866 874
867const Interface::FunctionInfo FunctionTable[] = { 875const Interface::FunctionInfo FunctionTable[] = {
868 {0x00010044, InitializeSockets, "InitializeSockets"}, 876 {0x00010044, InitializeSockets, "InitializeSockets"},
869 {0x000200C2, Socket, "Socket"}, 877 {0x000200C2, Socket, "Socket"},
870 {0x00030082, Listen, "Listen"}, 878 {0x00030082, Listen, "Listen"},
871 {0x00040082, Accept, "Accept"}, 879 {0x00040082, Accept, "Accept"},
872 {0x00050084, Bind, "Bind"}, 880 {0x00050084, Bind, "Bind"},
873 {0x00060084, Connect, "Connect"}, 881 {0x00060084, Connect, "Connect"},
874 {0x00070104, nullptr, "recvfrom_other"}, 882 {0x00070104, nullptr, "recvfrom_other"},
875 {0x00080102, RecvFrom, "RecvFrom"}, 883 {0x00080102, RecvFrom, "RecvFrom"},
876 {0x00090106, nullptr, "sendto_other"}, 884 {0x00090106, nullptr, "sendto_other"},
877 {0x000A0106, SendTo, "SendTo"}, 885 {0x000A0106, SendTo, "SendTo"},
878 {0x000B0042, Close, "Close"}, 886 {0x000B0042, Close, "Close"},
879 {0x000C0082, Shutdown, "Shutdown"}, 887 {0x000C0082, Shutdown, "Shutdown"},
880 {0x000D0082, nullptr, "GetHostByName"}, 888 {0x000D0082, nullptr, "GetHostByName"},
881 {0x000E00C2, nullptr, "GetHostByAddr"}, 889 {0x000E00C2, nullptr, "GetHostByAddr"},
882 {0x000F0106, nullptr, "GetAddrInfo"}, 890 {0x000F0106, nullptr, "GetAddrInfo"},
883 {0x00100102, nullptr, "GetNameInfo"}, 891 {0x00100102, nullptr, "GetNameInfo"},
884 {0x00110102, GetSockOpt, "GetSockOpt"}, 892 {0x00110102, GetSockOpt, "GetSockOpt"},
885 {0x00120104, SetSockOpt, "SetSockOpt"}, 893 {0x00120104, SetSockOpt, "SetSockOpt"},
886 {0x001300C2, Fcntl, "Fcntl"}, 894 {0x001300C2, Fcntl, "Fcntl"},
887 {0x00140084, Poll, "Poll"}, 895 {0x00140084, Poll, "Poll"},
888 {0x00150042, nullptr, "SockAtMark"}, 896 {0x00150042, nullptr, "SockAtMark"},
889 {0x00160000, GetHostId, "GetHostId"}, 897 {0x00160000, GetHostId, "GetHostId"},
890 {0x00170082, GetSockName, "GetSockName"}, 898 {0x00170082, GetSockName, "GetSockName"},
891 {0x00180082, GetPeerName, "GetPeerName"}, 899 {0x00180082, GetPeerName, "GetPeerName"},
892 {0x00190000, ShutdownSockets, "ShutdownSockets"}, 900 {0x00190000, ShutdownSockets, "ShutdownSockets"},
893 {0x001A00C0, nullptr, "GetNetworkOpt"}, 901 {0x001A00C0, nullptr, "GetNetworkOpt"},
894 {0x001B0040, nullptr, "ICMPSocket"}, 902 {0x001B0040, nullptr, "ICMPSocket"},
895 {0x001C0104, nullptr, "ICMPPing"}, 903 {0x001C0104, nullptr, "ICMPPing"},
896 {0x001D0040, nullptr, "ICMPCancel"}, 904 {0x001D0040, nullptr, "ICMPCancel"},
897 {0x001E0040, nullptr, "ICMPClose"}, 905 {0x001E0040, nullptr, "ICMPClose"},
898 {0x001F0040, nullptr, "GetResolverInfo"}, 906 {0x001F0040, nullptr, "GetResolverInfo"},
899 {0x00210002, nullptr, "CloseSockets"}, 907 {0x00210002, nullptr, "CloseSockets"},
900 {0x00230040, nullptr, "AddGlobalSocket"}, 908 {0x00230040, nullptr, "AddGlobalSocket"},
901}; 909};
902 910
903//////////////////////////////////////////////////////////////////////////////////////////////////// 911////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index 3c05f836b..fda9d8acf 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -5,8 +5,8 @@
5#include "common/common_types.h" 5#include "common/common_types.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7 7
8#include "core/hle/service/srv.h"
9#include "core/hle/kernel/event.h" 8#include "core/hle/kernel/event.h"
9#include "core/hle/service/srv.h"
10 10
11//////////////////////////////////////////////////////////////////////////////////////////////////// 11////////////////////////////////////////////////////////////////////////////////////////////////////
12// Namespace SRV 12// Namespace SRV
@@ -28,13 +28,14 @@ static void RegisterClient(Service::Interface* self) {
28 u32* cmd_buff = Kernel::GetCommandBuffer(); 28 u32* cmd_buff = Kernel::GetCommandBuffer();
29 29
30 if (cmd_buff[1] != IPC::CallingPidDesc()) { 30 if (cmd_buff[1] != IPC::CallingPidDesc()) {
31 cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); //0x40 31 cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); // 0x40
32 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, 32 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
33 ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; 33 ErrorSummary::WrongArgument, ErrorLevel::Permanent)
34 .raw;
34 return; 35 return;
35 } 36 }
36 cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); //0x10040 37 cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); // 0x10040
37 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 38 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
38 LOG_WARNING(Service_SRV, "(STUBBED) called"); 39 LOG_WARNING(Service_SRV, "(STUBBED) called");
39} 40}
40 41
@@ -56,7 +57,7 @@ static void EnableNotification(Service::Interface* self) {
56 event_handle->Clear(); 57 event_handle->Clear();
57 58
58 cmd_buff[0] = IPC::MakeHeader(0x2, 0x1, 0x2); // 0x20042 59 cmd_buff[0] = IPC::MakeHeader(0x2, 0x1, 0x2); // 0x20042
59 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 60 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
60 cmd_buff[2] = IPC::CopyHandleDesc(1); 61 cmd_buff[2] = IPC::CopyHandleDesc(1);
61 cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom(); 62 cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom();
62 LOG_WARNING(Service_SRV, "(STUBBED) called"); 63 LOG_WARNING(Service_SRV, "(STUBBED) called");
@@ -105,7 +106,7 @@ static void Subscribe(Service::Interface* self) {
105 u32 notification_id = cmd_buff[1]; 106 u32 notification_id = cmd_buff[1];
106 107
107 cmd_buff[0] = IPC::MakeHeader(0x9, 0x1, 0); // 0x90040 108 cmd_buff[0] = IPC::MakeHeader(0x9, 0x1, 0); // 0x90040
108 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 109 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
109 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); 110 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id);
110} 111}
111 112
@@ -124,7 +125,7 @@ static void Unsubscribe(Service::Interface* self) {
124 u32 notification_id = cmd_buff[1]; 125 u32 notification_id = cmd_buff[1];
125 126
126 cmd_buff[0] = IPC::MakeHeader(0xA, 0x1, 0); // 0xA0040 127 cmd_buff[0] = IPC::MakeHeader(0xA, 0x1, 0); // 0xA0040
127 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 128 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
128 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); 129 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id);
129} 130}
130 131
@@ -145,25 +146,26 @@ static void PublishToSubscriber(Service::Interface* self) {
145 u8 flags = cmd_buff[2] & 0xFF; 146 u8 flags = cmd_buff[2] & 0xFF;
146 147
147 cmd_buff[0] = IPC::MakeHeader(0xC, 0x1, 0); // 0xC0040 148 cmd_buff[0] = IPC::MakeHeader(0xC, 0x1, 0); // 0xC0040
148 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 149 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
149 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X, flags=%u", notification_id, flags); 150 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X, flags=%u", notification_id,
151 flags);
150} 152}
151 153
152const Interface::FunctionInfo FunctionTable[] = { 154const Interface::FunctionInfo FunctionTable[] = {
153 {0x00010002, RegisterClient, "RegisterClient"}, 155 {0x00010002, RegisterClient, "RegisterClient"},
154 {0x00020000, EnableNotification, "EnableNotification"}, 156 {0x00020000, EnableNotification, "EnableNotification"},
155 {0x00030100, nullptr, "RegisterService"}, 157 {0x00030100, nullptr, "RegisterService"},
156 {0x000400C0, nullptr, "UnregisterService"}, 158 {0x000400C0, nullptr, "UnregisterService"},
157 {0x00050100, GetServiceHandle, "GetServiceHandle"}, 159 {0x00050100, GetServiceHandle, "GetServiceHandle"},
158 {0x000600C2, nullptr, "RegisterPort"}, 160 {0x000600C2, nullptr, "RegisterPort"},
159 {0x000700C0, nullptr, "UnregisterPort"}, 161 {0x000700C0, nullptr, "UnregisterPort"},
160 {0x00080100, nullptr, "GetPort"}, 162 {0x00080100, nullptr, "GetPort"},
161 {0x00090040, Subscribe, "Subscribe"}, 163 {0x00090040, Subscribe, "Subscribe"},
162 {0x000A0040, Unsubscribe, "Unsubscribe"}, 164 {0x000A0040, Unsubscribe, "Unsubscribe"},
163 {0x000B0000, nullptr, "ReceiveNotification"}, 165 {0x000B0000, nullptr, "ReceiveNotification"},
164 {0x000C0080, PublishToSubscriber, "PublishToSubscriber"}, 166 {0x000C0080, PublishToSubscriber, "PublishToSubscriber"},
165 {0x000D0040, nullptr, "PublishAndGetSubscriber"}, 167 {0x000D0040, nullptr, "PublishAndGetSubscriber"},
166 {0x000E00C0, nullptr, "IsServiceRegistered"}, 168 {0x000E00C0, nullptr, "IsServiceRegistered"},
167}; 169};
168 170
169//////////////////////////////////////////////////////////////////////////////////////////////////// 171////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp
index a8aff1abf..47c4a8cb0 100644
--- a/src/core/hle/service/ssl_c.cpp
+++ b/src/core/hle/service/ssl_c.cpp
@@ -37,7 +37,8 @@ static void GenerateRandomData(Service::Interface* self) {
37 u32 i = 0; 37 u32 i = 0;
38 while (i < size) { 38 while (i < size) {
39 if ((i % 4) == 0) { 39 if ((i % 4) == 0) {
40 // The random number generator returns 4 bytes worth of data, so generate new random data when i == 0 and when i is divisible by 4 40 // The random number generator returns 4 bytes worth of data, so generate new random
41 // data when i == 0 and when i is divisible by 4
41 data = rand_gen(); 42 data = rand_gen();
42 } 43 }
43 44
@@ -59,27 +60,26 @@ static void GenerateRandomData(Service::Interface* self) {
59} 60}
60 61
61const Interface::FunctionInfo FunctionTable[] = { 62const Interface::FunctionInfo FunctionTable[] = {
62 {0x00010002, Initialize, "Initialize"}, 63 {0x00010002, Initialize, "Initialize"},
63 {0x000200C2, nullptr, "CreateContext"}, 64 {0x000200C2, nullptr, "CreateContext"},
64 {0x00030000, nullptr, "CreateRootCertChain"}, 65 {0x00030000, nullptr, "CreateRootCertChain"},
65 {0x00040040, nullptr, "DestroyRootCertChain"}, 66 {0x00040040, nullptr, "DestroyRootCertChain"},
66 {0x00050082, nullptr, "AddTrustedRootCA"}, 67 {0x00050082, nullptr, "AddTrustedRootCA"},
67 {0x00060080, nullptr, "RootCertChainAddDefaultCert"}, 68 {0x00060080, nullptr, "RootCertChainAddDefaultCert"},
68 {0x00070080, nullptr, "RootCertChainRemoveCert"}, 69 {0x00070080, nullptr, "RootCertChainRemoveCert"},
69 {0x000E0040, nullptr, "OpenDefaultClientCertContext"}, 70 {0x000E0040, nullptr, "OpenDefaultClientCertContext"},
70 {0x000F0040, nullptr, "CloseClientCertContext"}, 71 {0x000F0040, nullptr, "CloseClientCertContext"},
71 {0x00110042, GenerateRandomData, "GenerateRandomData"}, 72 {0x00110042, GenerateRandomData, "GenerateRandomData"},
72 {0x00120042, nullptr, "InitializeConnectionSession"}, 73 {0x00120042, nullptr, "InitializeConnectionSession"},
73 {0x00130040, nullptr, "StartConnection"}, 74 {0x00130040, nullptr, "StartConnection"},
74 {0x00140040, nullptr, "StartConnectionGetOut"}, 75 {0x00140040, nullptr, "StartConnectionGetOut"},
75 {0x00150082, nullptr, "Read"}, 76 {0x00150082, nullptr, "Read"},
76 {0x00170082, nullptr, "Write"}, 77 {0x00170082, nullptr, "Write"},
77 {0x00180080, nullptr, "ContextSetRootCertChain"}, 78 {0x00180080, nullptr, "ContextSetRootCertChain"},
78 {0x00190080, nullptr, "ContextSetClientCert"}, 79 {0x00190080, nullptr, "ContextSetClientCert"},
79 {0x001B0080, nullptr, "ContextClearOpt"}, 80 {0x001B0080, nullptr, "ContextClearOpt"},
80 {0x001E0040, nullptr, "DestroyContext"}, 81 {0x001E0040, nullptr, "DestroyContext"},
81 {0x001F0082, nullptr, "ContextInitSharedmem"} 82 {0x001F0082, nullptr, "ContextInitSharedmem"}};
82};
83 83
84//////////////////////////////////////////////////////////////////////////////////////////////////// 84////////////////////////////////////////////////////////////////////////////////////////////////////
85// Interface class 85// Interface class
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index d16578f87..278548e0e 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -39,16 +39,16 @@ static u32 transfer_end_interrupt_enabled = 0;
39static u32 spacial_dithering_enabled = 0; 39static u32 spacial_dithering_enabled = 0;
40 40
41static const CoefficientSet standard_coefficients[4] = { 41static const CoefficientSet standard_coefficients[4] = {
42 {{ 0x100, 0x166, 0xB6, 0x58, 0x1C5, -0x166F, 0x10EE, -0x1C5B }}, // ITU_Rec601 42 {{0x100, 0x166, 0xB6, 0x58, 0x1C5, -0x166F, 0x10EE, -0x1C5B}}, // ITU_Rec601
43 {{ 0x100, 0x193, 0x77, 0x2F, 0x1DB, -0x1933, 0xA7C, -0x1D51 }}, // ITU_Rec709 43 {{0x100, 0x193, 0x77, 0x2F, 0x1DB, -0x1933, 0xA7C, -0x1D51}}, // ITU_Rec709
44 {{ 0x12A, 0x198, 0xD0, 0x64, 0x204, -0x1BDE, 0x10F2, -0x229B }}, // ITU_Rec601_Scaling 44 {{0x12A, 0x198, 0xD0, 0x64, 0x204, -0x1BDE, 0x10F2, -0x229B}}, // ITU_Rec601_Scaling
45 {{ 0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421 }}, // ITU_Rec709_Scaling 45 {{0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421}}, // ITU_Rec709_Scaling
46}; 46};
47 47
48ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) { 48ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) {
49 if (width == 0 || width > 1024 || width % 8 != 0) { 49 if (width == 0 || width > 1024 || width % 8 != 0) {
50 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, 50 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM,
51 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD 51 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD
52 } 52 }
53 53
54 // Note: The hardware uses the register value 0 to represent a width of 1024, so for a width of 54 // Note: The hardware uses the register value 0 to represent a width of 1024, so for a width of
@@ -61,7 +61,7 @@ ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) {
61ResultCode ConversionConfiguration::SetInputLines(u16 lines) { 61ResultCode ConversionConfiguration::SetInputLines(u16 lines) {
62 if (lines == 0 || lines > 1024) { 62 if (lines == 0 || lines > 1024) {
63 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, 63 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM,
64 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD 64 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD
65 } 65 }
66 66
67 // Note: In what appears to be a bug, the `camera` module does not set the hardware register at 67 // Note: In what appears to be a bug, the `camera` module does not set the hardware register at
@@ -73,11 +73,12 @@ ResultCode ConversionConfiguration::SetInputLines(u16 lines) {
73 return RESULT_SUCCESS; 73 return RESULT_SUCCESS;
74} 74}
75 75
76ResultCode ConversionConfiguration::SetStandardCoefficient(StandardCoefficient standard_coefficient) { 76ResultCode
77ConversionConfiguration::SetStandardCoefficient(StandardCoefficient standard_coefficient) {
77 size_t index = static_cast<size_t>(standard_coefficient); 78 size_t index = static_cast<size_t>(standard_coefficient);
78 if (index >= ARRAY_SIZE(standard_coefficients)) { 79 if (index >= ARRAY_SIZE(standard_coefficients)) {
79 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM, 80 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM,
80 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053ED 81 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053ED
81 } 82 }
82 83
83 std::memcpy(coefficients.data(), standard_coefficients[index].data(), sizeof(coefficients)); 84 std::memcpy(coefficients.data(), standard_coefficients[index].data(), sizeof(coefficients));
@@ -294,8 +295,10 @@ static void SetSendingY(Service::Interface* self) {
294 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0); 295 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0);
295 cmd_buff[1] = RESULT_SUCCESS.raw; 296 cmd_buff[1] = RESULT_SUCCESS.raw;
296 297
297 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 298 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
298 conversion.src_Y.image_size, conversion.src_Y.transfer_unit, conversion.src_Y.gap, cmd_buff[6]); 299 "src_process_handle=0x%08X",
300 conversion.src_Y.image_size, conversion.src_Y.transfer_unit, conversion.src_Y.gap,
301 cmd_buff[6]);
299} 302}
300 303
301static void SetSendingU(Service::Interface* self) { 304static void SetSendingU(Service::Interface* self) {
@@ -309,8 +312,10 @@ static void SetSendingU(Service::Interface* self) {
309 cmd_buff[0] = IPC::MakeHeader(0x11, 1, 0); 312 cmd_buff[0] = IPC::MakeHeader(0x11, 1, 0);
310 cmd_buff[1] = RESULT_SUCCESS.raw; 313 cmd_buff[1] = RESULT_SUCCESS.raw;
311 314
312 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 315 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
313 conversion.src_U.image_size, conversion.src_U.transfer_unit, conversion.src_U.gap, cmd_buff[6]); 316 "src_process_handle=0x%08X",
317 conversion.src_U.image_size, conversion.src_U.transfer_unit, conversion.src_U.gap,
318 cmd_buff[6]);
314} 319}
315 320
316static void SetSendingV(Service::Interface* self) { 321static void SetSendingV(Service::Interface* self) {
@@ -324,8 +329,10 @@ static void SetSendingV(Service::Interface* self) {
324 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); 329 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0);
325 cmd_buff[1] = RESULT_SUCCESS.raw; 330 cmd_buff[1] = RESULT_SUCCESS.raw;
326 331
327 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 332 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
328 conversion.src_V.image_size, conversion.src_V.transfer_unit, conversion.src_V.gap, cmd_buff[6]); 333 "src_process_handle=0x%08X",
334 conversion.src_V.image_size, conversion.src_V.transfer_unit, conversion.src_V.gap,
335 cmd_buff[6]);
329} 336}
330 337
331static void SetSendingYUYV(Service::Interface* self) { 338static void SetSendingYUYV(Service::Interface* self) {
@@ -339,8 +346,10 @@ static void SetSendingYUYV(Service::Interface* self) {
339 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); 346 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0);
340 cmd_buff[1] = RESULT_SUCCESS.raw; 347 cmd_buff[1] = RESULT_SUCCESS.raw;
341 348
342 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 349 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
343 conversion.src_YUYV.image_size, conversion.src_YUYV.transfer_unit, conversion.src_YUYV.gap, cmd_buff[6]); 350 "src_process_handle=0x%08X",
351 conversion.src_YUYV.image_size, conversion.src_YUYV.transfer_unit,
352 conversion.src_YUYV.gap, cmd_buff[6]);
344} 353}
345 354
346/** 355/**
@@ -418,8 +427,10 @@ static void SetReceiving(Service::Interface* self) {
418 cmd_buff[0] = IPC::MakeHeader(0x18, 1, 0); 427 cmd_buff[0] = IPC::MakeHeader(0x18, 1, 0);
419 cmd_buff[1] = RESULT_SUCCESS.raw; 428 cmd_buff[1] = RESULT_SUCCESS.raw;
420 429
421 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, dst_process_handle=0x%08X", 430 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
422 conversion.dst.image_size, conversion.dst.transfer_unit, conversion.dst.gap, cmd_buff[6]); 431 "dst_process_handle=0x%08X",
432 conversion.dst.image_size, conversion.dst.transfer_unit, conversion.dst.gap,
433 cmd_buff[6]);
423} 434}
424 435
425/** 436/**
@@ -486,8 +497,8 @@ static void SetCoefficient(Service::Interface* self) {
486 cmd_buff[1] = RESULT_SUCCESS.raw; 497 cmd_buff[1] = RESULT_SUCCESS.raw;
487 498
488 LOG_DEBUG(Service_Y2R, "called coefficients=[%hX, %hX, %hX, %hX, %hX, %hX, %hX, %hX]", 499 LOG_DEBUG(Service_Y2R, "called coefficients=[%hX, %hX, %hX, %hX, %hX, %hX, %hX, %hX]",
489 coefficients[0], coefficients[1], coefficients[2], coefficients[3], 500 coefficients[0], coefficients[1], coefficients[2], coefficients[3], coefficients[4],
490 coefficients[4], coefficients[5], coefficients[6], coefficients[7]); 501 coefficients[5], coefficients[6], coefficients[7]);
491} 502}
492 503
493static void GetCoefficient(Service::Interface* self) { 504static void GetCoefficient(Service::Interface* self) {
@@ -575,8 +586,10 @@ static void StartConversion(Service::Interface* self) {
575 u32* cmd_buff = Kernel::GetCommandBuffer(); 586 u32* cmd_buff = Kernel::GetCommandBuffer();
576 587
577 // dst_image_size would seem to be perfect for this, but it doesn't include the gap :( 588 // dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
578 u32 total_output_size = conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); 589 u32 total_output_size =
579 Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size); 590 conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap);
591 Memory::RasterizerFlushAndInvalidateRegion(
592 Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size);
580 593
581 HW::Y2R::PerformConversion(conversion); 594 HW::Y2R::PerformConversion(conversion);
582 595
@@ -648,10 +661,13 @@ cleanup:
648 cmd_buff[0] = IPC::MakeHeader(0x29, 1, 0); 661 cmd_buff[0] = IPC::MakeHeader(0x29, 1, 0);
649 cmd_buff[1] = result.raw; 662 cmd_buff[1] = result.raw;
650 663
651 LOG_DEBUG(Service_Y2R, "called input_format=%hhu output_format=%hhu rotation=%hhu block_alignment=%hhu " 664 LOG_DEBUG(
652 "input_line_width=%hu input_lines=%hu standard_coefficient=%hhu reserved=%hhu alpha=%hX", 665 Service_Y2R,
653 params->input_format, params->output_format, params->rotation, params->block_alignment, 666 "called input_format=%hhu output_format=%hhu rotation=%hhu block_alignment=%hhu "
654 params->input_line_width, params->input_lines, params->standard_coefficient, params->padding, params->alpha); 667 "input_line_width=%hu input_lines=%hu standard_coefficient=%hhu reserved=%hhu alpha=%hX",
668 params->input_format, params->output_format, params->rotation, params->block_alignment,
669 params->input_line_width, params->input_lines, params->standard_coefficient,
670 params->padding, params->alpha);
655} 671}
656 672
657static void PingProcess(Service::Interface* self) { 673static void PingProcess(Service::Interface* self) {
@@ -699,7 +715,6 @@ static void DriverFinalize(Service::Interface* self) {
699 LOG_DEBUG(Service_Y2R, "called"); 715 LOG_DEBUG(Service_Y2R, "called");
700} 716}
701 717
702
703static void GetPackageParameter(Service::Interface* self) { 718static void GetPackageParameter(Service::Interface* self) {
704 u32* cmd_buff = Kernel::GetCommandBuffer(); 719 u32* cmd_buff = Kernel::GetCommandBuffer();
705 720
@@ -711,51 +726,51 @@ static void GetPackageParameter(Service::Interface* self) {
711} 726}
712 727
713const Interface::FunctionInfo FunctionTable[] = { 728const Interface::FunctionInfo FunctionTable[] = {
714 {0x00010040, SetInputFormat, "SetInputFormat"}, 729 {0x00010040, SetInputFormat, "SetInputFormat"},
715 {0x00020000, GetInputFormat, "GetInputFormat"}, 730 {0x00020000, GetInputFormat, "GetInputFormat"},
716 {0x00030040, SetOutputFormat, "SetOutputFormat"}, 731 {0x00030040, SetOutputFormat, "SetOutputFormat"},
717 {0x00040000, GetOutputFormat, "GetOutputFormat"}, 732 {0x00040000, GetOutputFormat, "GetOutputFormat"},
718 {0x00050040, SetRotation, "SetRotation"}, 733 {0x00050040, SetRotation, "SetRotation"},
719 {0x00060000, GetRotation, "GetRotation"}, 734 {0x00060000, GetRotation, "GetRotation"},
720 {0x00070040, SetBlockAlignment, "SetBlockAlignment"}, 735 {0x00070040, SetBlockAlignment, "SetBlockAlignment"},
721 {0x00080000, GetBlockAlignment, "GetBlockAlignment"}, 736 {0x00080000, GetBlockAlignment, "GetBlockAlignment"},
722 {0x00090040, SetSpacialDithering, "SetSpacialDithering"}, 737 {0x00090040, SetSpacialDithering, "SetSpacialDithering"},
723 {0x000A0000, GetSpacialDithering, "GetSpacialDithering"}, 738 {0x000A0000, GetSpacialDithering, "GetSpacialDithering"},
724 {0x000B0040, SetTemporalDithering, "SetTemporalDithering"}, 739 {0x000B0040, SetTemporalDithering, "SetTemporalDithering"},
725 {0x000C0000, GetTemporalDithering, "GetTemporalDithering"}, 740 {0x000C0000, GetTemporalDithering, "GetTemporalDithering"},
726 {0x000D0040, SetTransferEndInterrupt, "SetTransferEndInterrupt"}, 741 {0x000D0040, SetTransferEndInterrupt, "SetTransferEndInterrupt"},
727 {0x000E0000, GetTransferEndInterrupt, "GetTransferEndInterrupt"}, 742 {0x000E0000, GetTransferEndInterrupt, "GetTransferEndInterrupt"},
728 {0x000F0000, GetTransferEndEvent, "GetTransferEndEvent"}, 743 {0x000F0000, GetTransferEndEvent, "GetTransferEndEvent"},
729 {0x00100102, SetSendingY, "SetSendingY"}, 744 {0x00100102, SetSendingY, "SetSendingY"},
730 {0x00110102, SetSendingU, "SetSendingU"}, 745 {0x00110102, SetSendingU, "SetSendingU"},
731 {0x00120102, SetSendingV, "SetSendingV"}, 746 {0x00120102, SetSendingV, "SetSendingV"},
732 {0x00130102, SetSendingYUYV, "SetSendingYUYV"}, 747 {0x00130102, SetSendingYUYV, "SetSendingYUYV"},
733 {0x00140000, IsFinishedSendingYuv, "IsFinishedSendingYuv"}, 748 {0x00140000, IsFinishedSendingYuv, "IsFinishedSendingYuv"},
734 {0x00150000, IsFinishedSendingY, "IsFinishedSendingY"}, 749 {0x00150000, IsFinishedSendingY, "IsFinishedSendingY"},
735 {0x00160000, IsFinishedSendingU, "IsFinishedSendingU"}, 750 {0x00160000, IsFinishedSendingU, "IsFinishedSendingU"},
736 {0x00170000, IsFinishedSendingV, "IsFinishedSendingV"}, 751 {0x00170000, IsFinishedSendingV, "IsFinishedSendingV"},
737 {0x00180102, SetReceiving, "SetReceiving"}, 752 {0x00180102, SetReceiving, "SetReceiving"},
738 {0x00190000, IsFinishedReceiving, "IsFinishedReceiving"}, 753 {0x00190000, IsFinishedReceiving, "IsFinishedReceiving"},
739 {0x001A0040, SetInputLineWidth, "SetInputLineWidth"}, 754 {0x001A0040, SetInputLineWidth, "SetInputLineWidth"},
740 {0x001B0000, GetInputLineWidth, "GetInputLineWidth"}, 755 {0x001B0000, GetInputLineWidth, "GetInputLineWidth"},
741 {0x001C0040, SetInputLines, "SetInputLines"}, 756 {0x001C0040, SetInputLines, "SetInputLines"},
742 {0x001D0000, GetInputLines, "GetInputLines"}, 757 {0x001D0000, GetInputLines, "GetInputLines"},
743 {0x001E0100, SetCoefficient, "SetCoefficient"}, 758 {0x001E0100, SetCoefficient, "SetCoefficient"},
744 {0x001F0000, GetCoefficient, "GetCoefficient"}, 759 {0x001F0000, GetCoefficient, "GetCoefficient"},
745 {0x00200040, SetStandardCoefficient, "SetStandardCoefficient"}, 760 {0x00200040, SetStandardCoefficient, "SetStandardCoefficient"},
746 {0x00210040, GetStandardCoefficient, "GetStandardCoefficient"}, 761 {0x00210040, GetStandardCoefficient, "GetStandardCoefficient"},
747 {0x00220040, SetAlpha, "SetAlpha"}, 762 {0x00220040, SetAlpha, "SetAlpha"},
748 {0x00230000, GetAlpha, "GetAlpha"}, 763 {0x00230000, GetAlpha, "GetAlpha"},
749 {0x00240200, SetDitheringWeightParams,"SetDitheringWeightParams"}, 764 {0x00240200, SetDitheringWeightParams, "SetDitheringWeightParams"},
750 {0x00250000, GetDitheringWeightParams,"GetDitheringWeightParams"}, 765 {0x00250000, GetDitheringWeightParams, "GetDitheringWeightParams"},
751 {0x00260000, StartConversion, "StartConversion"}, 766 {0x00260000, StartConversion, "StartConversion"},
752 {0x00270000, StopConversion, "StopConversion"}, 767 {0x00270000, StopConversion, "StopConversion"},
753 {0x00280000, IsBusyConversion, "IsBusyConversion"}, 768 {0x00280000, IsBusyConversion, "IsBusyConversion"},
754 {0x002901C0, SetPackageParameter, "SetPackageParameter"}, 769 {0x002901C0, SetPackageParameter, "SetPackageParameter"},
755 {0x002A0000, PingProcess, "PingProcess"}, 770 {0x002A0000, PingProcess, "PingProcess"},
756 {0x002B0000, DriverInitialize, "DriverInitialize"}, 771 {0x002B0000, DriverInitialize, "DriverInitialize"},
757 {0x002C0000, DriverFinalize, "DriverFinalize"}, 772 {0x002C0000, DriverFinalize, "DriverFinalize"},
758 {0x002D0000, GetPackageParameter, "GetPackageParameter"}, 773 {0x002D0000, GetPackageParameter, "GetPackageParameter"},
759}; 774};
760 775
761//////////////////////////////////////////////////////////////////////////////////////////////////// 776////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/shared_page.cpp b/src/core/hle/shared_page.cpp
index 4d9272923..453fcf7ec 100644
--- a/src/core/hle/shared_page.cpp
+++ b/src/core/hle/shared_page.cpp
@@ -52,8 +52,8 @@ static u64 GetSystemTime() {
52} 52}
53 53
54static void UpdateTimeCallback(u64 userdata, int cycles_late) { 54static void UpdateTimeCallback(u64 userdata, int cycles_late) {
55 DateTime& date_time = shared_page.date_time_counter % 2 ? 55 DateTime& date_time =
56 shared_page.date_time_0 : shared_page.date_time_1; 56 shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1;
57 57
58 date_time.date_time = GetSystemTime(); 58 date_time.date_time = GetSystemTime();
59 date_time.update_tick = CoreTiming::GetTicks(); 59 date_time.update_tick = CoreTiming::GetTicks();
@@ -74,7 +74,8 @@ void Init() {
74 // Some games wait until this value becomes 0x1, before asking running_hw 74 // Some games wait until this value becomes 0x1, before asking running_hw
75 shared_page.unknown_value = 0x1; 75 shared_page.unknown_value = 0x1;
76 76
77 update_time_event = CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback); 77 update_time_event =
78 CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback);
78 CoreTiming::ScheduleEvent(0, update_time_event); 79 CoreTiming::ScheduleEvent(0, update_time_event);
79} 80}
80 81
diff --git a/src/core/hle/shared_page.h b/src/core/hle/shared_page.h
index cd9246726..b3b10be31 100644
--- a/src/core/hle/shared_page.h
+++ b/src/core/hle/shared_page.h
@@ -32,27 +32,28 @@ static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong");
32 32
33struct SharedPageDef { 33struct SharedPageDef {
34 // Most of these names are taken from the 3dbrew page linked above. 34 // Most of these names are taken from the 3dbrew page linked above.
35 u32_le date_time_counter; // 0 35 u32_le date_time_counter; // 0
36 u8 running_hw; // 4 36 u8 running_hw; // 4
37 /// "Microcontroller hardware info" 37 /// "Microcontroller hardware info"
38 u8 mcu_hw_info; // 5 38 u8 mcu_hw_info; // 5
39 INSERT_PADDING_BYTES(0x20 - 0x6); // 6 39 INSERT_PADDING_BYTES(0x20 - 0x6); // 6
40 DateTime date_time_0; // 20 40 DateTime date_time_0; // 20
41 DateTime date_time_1; // 40 41 DateTime date_time_1; // 40
42 u8 wifi_macaddr[6]; // 60 42 u8 wifi_macaddr[6]; // 60
43 u8 wifi_link_level; // 66 43 u8 wifi_link_level; // 66
44 u8 wifi_unknown2; // 67 44 u8 wifi_unknown2; // 67
45 INSERT_PADDING_BYTES(0x80 - 0x68); // 68 45 INSERT_PADDING_BYTES(0x80 - 0x68); // 68
46 float_le sliderstate_3d; // 80 46 float_le sliderstate_3d; // 80
47 u8 ledstate_3d; // 84 47 u8 ledstate_3d; // 84
48 INSERT_PADDING_BYTES(1); // 85 48 INSERT_PADDING_BYTES(1); // 85
49 u8 unknown_value; // 86 49 u8 unknown_value; // 86
50 INSERT_PADDING_BYTES(0xA0 - 0x87); // 87 50 INSERT_PADDING_BYTES(0xA0 - 0x87); // 87
51 u64_le menu_title_id; // A0 51 u64_le menu_title_id; // A0
52 u64_le active_menu_title_id; // A8 52 u64_le active_menu_title_id; // A8
53 INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0 53 INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0
54}; 54};
55static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong"); 55static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE,
56 "Shared page structure size is wrong");
56 57
57extern SharedPageDef shared_page; 58extern SharedPageDef shared_page;
58 59
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 5d71d5619..9d0a9c54c 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -10,8 +10,8 @@
10#include "common/string_util.h" 10#include "common/string_util.h"
11#include "common/symbols.h" 11#include "common/symbols.h"
12 12
13#include "core/core_timing.h"
14#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
14#include "core/core_timing.h"
15 15
16#include "core/hle/kernel/address_arbiter.h" 16#include "core/hle/kernel/address_arbiter.h"
17#include "core/hle/kernel/client_port.h" 17#include "core/hle/kernel/client_port.h"
@@ -40,43 +40,46 @@ using Kernel::ERR_INVALID_HANDLE;
40namespace SVC { 40namespace SVC {
41 41
42const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, 42const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel,
43 ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA 43 ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA
44const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, 44const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS,
45 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E 45 ErrorSummary::InvalidArgument,
46 46 ErrorLevel::Usage); // 0xE0E0181E
47const ResultCode ERR_MISALIGNED_ADDRESS{ // 0xE0E01BF1 47
48 ErrorDescription::MisalignedAddress, ErrorModule::OS, 48const ResultCode ERR_MISALIGNED_ADDRESS{// 0xE0E01BF1
49 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 49 ErrorDescription::MisalignedAddress, ErrorModule::OS,
50const ResultCode ERR_MISALIGNED_SIZE{ // 0xE0E01BF2 50 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
51 ErrorDescription::MisalignedSize, ErrorModule::OS, 51const ResultCode ERR_MISALIGNED_SIZE{// 0xE0E01BF2
52 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 52 ErrorDescription::MisalignedSize, ErrorModule::OS,
53const ResultCode ERR_INVALID_COMBINATION{ // 0xE0E01BEE 53 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
54 ErrorDescription::InvalidCombination, ErrorModule::OS, 54const ResultCode ERR_INVALID_COMBINATION{// 0xE0E01BEE
55 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 55 ErrorDescription::InvalidCombination, ErrorModule::OS,
56 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
56 57
57enum ControlMemoryOperation { 58enum ControlMemoryOperation {
58 MEMOP_FREE = 1, 59 MEMOP_FREE = 1,
59 MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel 60 MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel
60 MEMOP_COMMIT = 3, 61 MEMOP_COMMIT = 3,
61 MEMOP_MAP = 4, 62 MEMOP_MAP = 4,
62 MEMOP_UNMAP = 5, 63 MEMOP_UNMAP = 5,
63 MEMOP_PROTECT = 6, 64 MEMOP_PROTECT = 6,
64 MEMOP_OPERATION_MASK = 0xFF, 65 MEMOP_OPERATION_MASK = 0xFF,
65 66
66 MEMOP_REGION_APP = 0x100, 67 MEMOP_REGION_APP = 0x100,
67 MEMOP_REGION_SYSTEM = 0x200, 68 MEMOP_REGION_SYSTEM = 0x200,
68 MEMOP_REGION_BASE = 0x300, 69 MEMOP_REGION_BASE = 0x300,
69 MEMOP_REGION_MASK = 0xF00, 70 MEMOP_REGION_MASK = 0xF00,
70 71
71 MEMOP_LINEAR = 0x10000, 72 MEMOP_LINEAR = 0x10000,
72}; 73};
73 74
74/// Map application or GSP heap memory 75/// Map application or GSP heap memory
75static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { 76static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size,
77 u32 permissions) {
76 using namespace Kernel; 78 using namespace Kernel;
77 79
78 LOG_DEBUG(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=0x%X, permissions=0x%08X", 80 LOG_DEBUG(Kernel_SVC,
79 operation, addr0, addr1, size, permissions); 81 "called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=0x%X, permissions=0x%08X",
82 operation, addr0, addr1, size, permissions);
80 83
81 if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) { 84 if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) {
82 return ERR_MISALIGNED_ADDRESS; 85 return ERR_MISALIGNED_ADDRESS;
@@ -89,7 +92,8 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
89 operation &= ~MEMOP_REGION_MASK; 92 operation &= ~MEMOP_REGION_MASK;
90 93
91 if (region != 0) { 94 if (region != 0) {
92 LOG_WARNING(Kernel_SVC, "ControlMemory with specified region not supported, region=%X", region); 95 LOG_WARNING(Kernel_SVC, "ControlMemory with specified region not supported, region=%X",
96 region);
93 } 97 }
94 98
95 if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) { 99 if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) {
@@ -100,15 +104,17 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
100 auto& process = *g_current_process; 104 auto& process = *g_current_process;
101 105
102 switch (operation & MEMOP_OPERATION_MASK) { 106 switch (operation & MEMOP_OPERATION_MASK) {
103 case MEMOP_FREE: 107 case MEMOP_FREE: {
104 { 108 // TODO(Subv): What happens if an application tries to FREE a block of memory that has a
105 // TODO(Subv): What happens if an application tries to FREE a block of memory that has a SharedMemory pointing to it? 109 // SharedMemory pointing to it?
106 if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) { 110 if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) {
107 ResultCode result = process.HeapFree(addr0, size); 111 ResultCode result = process.HeapFree(addr0, size);
108 if (result.IsError()) return result; 112 if (result.IsError())
113 return result;
109 } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) { 114 } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) {
110 ResultCode result = process.LinearFree(addr0, size); 115 ResultCode result = process.LinearFree(addr0, size);
111 if (result.IsError()) return result; 116 if (result.IsError())
117 return result;
112 } else { 118 } else {
113 return ERR_INVALID_ADDRESS; 119 return ERR_INVALID_ADDRESS;
114 } 120 }
@@ -116,8 +122,7 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
116 break; 122 break;
117 } 123 }
118 124
119 case MEMOP_COMMIT: 125 case MEMOP_COMMIT: {
120 {
121 if (operation & MEMOP_LINEAR) { 126 if (operation & MEMOP_LINEAR) {
122 CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions)); 127 CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions));
123 } else { 128 } else {
@@ -126,23 +131,26 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
126 break; 131 break;
127 } 132 }
128 133
129 case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented 134 case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is
130 { 135 // implemented
131 CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions)); 136 {
132 break; 137 CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions));
133 } 138 break;
139 }
134 140
135 case MEMOP_UNMAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented 141 case MEMOP_UNMAP: // TODO: This is just a hack to avoid regressions until memory aliasing is
136 { 142 // implemented
137 ResultCode result = process.HeapFree(addr0, size); 143 {
138 if (result.IsError()) return result; 144 ResultCode result = process.HeapFree(addr0, size);
139 break; 145 if (result.IsError())
140 } 146 return result;
147 break;
148 }
141 149
142 case MEMOP_PROTECT: 150 case MEMOP_PROTECT: {
143 {
144 ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions); 151 ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions);
145 if (result.IsError()) return result; 152 if (result.IsError())
153 return result;
146 break; 154 break;
147 } 155 }
148 156
@@ -161,8 +169,9 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
161 using Kernel::SharedMemory; 169 using Kernel::SharedMemory;
162 using Kernel::MemoryPermission; 170 using Kernel::MemoryPermission;
163 171
164 LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", 172 LOG_TRACE(Kernel_SVC,
165 handle, addr, permissions, other_permissions); 173 "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
174 handle, addr, permissions, other_permissions);
166 175
167 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); 176 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
168 if (shared_memory == nullptr) 177 if (shared_memory == nullptr)
@@ -179,12 +188,13 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
179 case MemoryPermission::ReadWriteExecute: 188 case MemoryPermission::ReadWriteExecute:
180 case MemoryPermission::DontCare: 189 case MemoryPermission::DontCare:
181 return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type, 190 return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type,
182 static_cast<MemoryPermission>(other_permissions)); 191 static_cast<MemoryPermission>(other_permissions));
183 default: 192 default:
184 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); 193 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
185 } 194 }
186 195
187 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 196 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
197 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
188} 198}
189 199
190static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) { 200static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) {
@@ -249,7 +259,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
249 return ERR_INVALID_HANDLE; 259 return ERR_INVALID_HANDLE;
250 260
251 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, 261 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle,
252 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); 262 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds);
253 263
254 HLE::Reschedule(__func__); 264 HLE::Reschedule(__func__);
255 265
@@ -257,7 +267,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
257 if (object->ShouldWait()) { 267 if (object->ShouldWait()) {
258 268
259 object->AddWaitingThread(thread); 269 object->AddWaitingThread(thread);
260 Kernel::WaitCurrentThread_WaitSynchronization({ object }, false, false); 270 Kernel::WaitCurrentThread_WaitSynchronization({object}, false, false);
261 271
262 // Create an event to wake the thread up after the specified nanosecond delay has passed 272 // Create an event to wake the thread up after the specified nanosecond delay has passed
263 thread->WakeAfterDelay(nano_seconds); 273 thread->WakeAfterDelay(nano_seconds);
@@ -272,7 +282,8 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
272} 282}
273 283
274/// Wait for the given handles to synchronize, timeout after the specified nanoseconds 284/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
275static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { 285static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all,
286 s64 nano_seconds) {
276 bool wait_thread = !wait_all; 287 bool wait_thread = !wait_all;
277 int handle_index = 0; 288 int handle_index = 0;
278 Kernel::Thread* thread = Kernel::GetCurrentThread(); 289 Kernel::Thread* thread = Kernel::GetCurrentThread();
@@ -281,7 +292,8 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
281 292
282 // Check if 'handles' is invalid 293 // Check if 'handles' is invalid
283 if (handles == nullptr) 294 if (handles == nullptr)
284 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 295 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel,
296 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
285 297
286 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If 298 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
287 // this happens, the running application will crash. 299 // this happens, the running application will crash.
@@ -289,7 +301,8 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
289 301
290 // Check if 'handle_count' is invalid 302 // Check if 'handle_count' is invalid
291 if (handle_count < 0) 303 if (handle_count < 0)
292 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 304 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS,
305 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
293 306
294 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if 307 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if
295 // necessary 308 // necessary
@@ -329,7 +342,9 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
329 } 342 }
330 } 343 }
331 344
332 SCOPE_EXIT({HLE::Reschedule("WaitSynchronizationN");}); // Reschedule after putting the threads to sleep. 345 SCOPE_EXIT({
346 HLE::Reschedule("WaitSynchronizationN");
347 }); // Reschedule after putting the threads to sleep.
333 348
334 // If thread should wait, then set its state to waiting 349 // If thread should wait, then set its state to waiting
335 if (wait_thread) { 350 if (wait_thread) {
@@ -386,18 +401,19 @@ static ResultCode CreateAddressArbiter(Handle* out_handle) {
386} 401}
387 402
388/// Arbitrate address 403/// Arbitrate address
389static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds) { 404static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value,
405 s64 nanoseconds) {
390 using Kernel::AddressArbiter; 406 using Kernel::AddressArbiter;
391 407
392 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle, 408 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle,
393 address, type, value); 409 address, type, value);
394 410
395 SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle); 411 SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle);
396 if (arbiter == nullptr) 412 if (arbiter == nullptr)
397 return ERR_INVALID_HANDLE; 413 return ERR_INVALID_HANDLE;
398 414
399 auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), 415 auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), address, value,
400 address, value, nanoseconds); 416 nanoseconds);
401 417
402 return res; 418 return res;
403} 419}
@@ -406,10 +422,18 @@ static void Break(u8 break_reason) {
406 LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); 422 LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
407 std::string reason_str; 423 std::string reason_str;
408 switch (break_reason) { 424 switch (break_reason) {
409 case 0: reason_str = "PANIC"; break; 425 case 0:
410 case 1: reason_str = "ASSERT"; break; 426 reason_str = "PANIC";
411 case 2: reason_str = "USER"; break; 427 break;
412 default: reason_str = "UNKNOWN"; break; 428 case 1:
429 reason_str = "ASSERT";
430 break;
431 case 2:
432 reason_str = "USER";
433 break;
434 default:
435 reason_str = "UNKNOWN";
436 break;
413 } 437 }
414 LOG_CRITICAL(Debug_Emulated, "Break reason: %s", reason_str.c_str()); 438 LOG_CRITICAL(Debug_Emulated, "Break reason: %s", reason_str.c_str());
415} 439}
@@ -423,7 +447,8 @@ static void OutputDebugString(const char* string) {
423static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) { 447static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) {
424 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); 448 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
425 449
426 SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); 450 SharedPtr<Kernel::Process> process =
451 Kernel::g_handle_table.Get<Kernel::Process>(process_handle);
427 if (process == nullptr) 452 if (process == nullptr)
428 return ERR_INVALID_HANDLE; 453 return ERR_INVALID_HANDLE;
429 454
@@ -433,12 +458,13 @@ static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle
433} 458}
434 459
435/// Get resource limit current values 460/// Get resource limit current values
436static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names, 461static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle,
437 u32 name_count) { 462 u32* names, u32 name_count) {
438 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", 463 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
439 resource_limit_handle, names, name_count); 464 resource_limit_handle, names, name_count);
440 465
441 SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); 466 SharedPtr<Kernel::ResourceLimit> resource_limit =
467 Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
442 if (resource_limit == nullptr) 468 if (resource_limit == nullptr)
443 return ERR_INVALID_HANDLE; 469 return ERR_INVALID_HANDLE;
444 470
@@ -450,11 +476,12 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_lim
450 476
451/// Get resource limit max values 477/// Get resource limit max values
452static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, 478static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names,
453 u32 name_count) { 479 u32 name_count) {
454 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", 480 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
455 resource_limit_handle, names, name_count); 481 resource_limit_handle, names, name_count);
456 482
457 SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); 483 SharedPtr<Kernel::ResourceLimit> resource_limit =
484 Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
458 if (resource_limit == nullptr) 485 if (resource_limit == nullptr)
459 return ERR_INVALID_HANDLE; 486 return ERR_INVALID_HANDLE;
460 487
@@ -465,7 +492,8 @@ static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit
465} 492}
466 493
467/// Creates a new thread 494/// Creates a new thread
468static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { 495static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg,
496 u32 stack_top, s32 processor_id) {
469 using Kernel::Thread; 497 using Kernel::Thread;
470 498
471 std::string name; 499 std::string name;
@@ -499,20 +527,23 @@ static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point
499 } 527 }
500 528
501 if (processor_id == THREADPROCESSORID_1 || processor_id == THREADPROCESSORID_ALL || 529 if (processor_id == THREADPROCESSORID_1 || processor_id == THREADPROCESSORID_ALL ||
502 (processor_id == THREADPROCESSORID_DEFAULT && Kernel::g_current_process->ideal_processor == THREADPROCESSORID_1)) { 530 (processor_id == THREADPROCESSORID_DEFAULT &&
503 LOG_WARNING(Kernel_SVC, "Newly created thread is allowed to be run in the SysCore, unimplemented."); 531 Kernel::g_current_process->ideal_processor == THREADPROCESSORID_1)) {
532 LOG_WARNING(Kernel_SVC,
533 "Newly created thread is allowed to be run in the SysCore, unimplemented.");
504 } 534 }
505 535
506 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create( 536 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create(name, entry_point, priority,
507 name, entry_point, priority, arg, processor_id, stack_top)); 537 arg, processor_id, stack_top));
508 538
509 thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000 539 thread->context.fpscr =
540 FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000
510 541
511 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); 542 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread)));
512 543
513 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " 544 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
514 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, 545 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X",
515 name.c_str(), arg, stack_top, priority, processor_id, *out_handle); 546 entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle);
516 547
517 return RESULT_SUCCESS; 548 return RESULT_SUCCESS;
518} 549}
@@ -552,7 +583,7 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
552 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); 583 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
553 584
554 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", 585 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
555 initial_locked ? "true" : "false", *out_handle); 586 initial_locked ? "true" : "false", *out_handle);
556 587
557 return RESULT_SUCCESS; 588 return RESULT_SUCCESS;
558} 589}
@@ -576,7 +607,8 @@ static ResultCode ReleaseMutex(Handle handle) {
576static ResultCode GetProcessId(u32* process_id, Handle process_handle) { 607static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
577 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); 608 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
578 609
579 const SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); 610 const SharedPtr<Kernel::Process> process =
611 Kernel::g_handle_table.Get<Kernel::Process>(process_handle);
580 if (process == nullptr) 612 if (process == nullptr)
581 return ERR_INVALID_HANDLE; 613 return ERR_INVALID_HANDLE;
582 614
@@ -588,7 +620,8 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
588static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { 620static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
589 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); 621 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
590 622
591 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle); 623 const SharedPtr<Kernel::Thread> thread =
624 Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle);
592 if (thread == nullptr) 625 if (thread == nullptr)
593 return ERR_INVALID_HANDLE; 626 return ERR_INVALID_HANDLE;
594 627
@@ -620,7 +653,7 @@ static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max
620 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore))); 653 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore)));
621 654
622 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", 655 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
623 initial_count, max_count, *out_handle); 656 initial_count, max_count, *out_handle);
624 return RESULT_SUCCESS; 657 return RESULT_SUCCESS;
625} 658}
626 659
@@ -640,7 +673,8 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count)
640} 673}
641 674
642/// Query process memory 675/// Query process memory
643static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info, Handle process_handle, u32 addr) { 676static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info,
677 Handle process_handle, u32 addr) {
644 using Kernel::Process; 678 using Kernel::Process;
645 Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle); 679 Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle);
646 if (process == nullptr) 680 if (process == nullptr)
@@ -649,7 +683,8 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_inf
649 auto vma = process->vm_manager.FindVMA(addr); 683 auto vma = process->vm_manager.FindVMA(addr);
650 684
651 if (vma == Kernel::g_current_process->vm_manager.vma_map.end()) 685 if (vma == Kernel::g_current_process->vm_manager.vma_map.end())
652 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 686 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
687 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
653 688
654 memory_info->base_address = vma->second.base; 689 memory_info->base_address = vma->second.base;
655 memory_info->permission = static_cast<u32>(vma->second.permissions); 690 memory_info->permission = static_cast<u32>(vma->second.permissions);
@@ -673,8 +708,8 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
673 SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type)); 708 SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type));
674 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); 709 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
675 710
676 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 711 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
677 reset_type, *out_handle); 712 *out_handle);
678 return RESULT_SUCCESS; 713 return RESULT_SUCCESS;
679} 714}
680 715
@@ -719,8 +754,8 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
719 SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type)); 754 SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type));
720 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); 755 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
721 756
722 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 757 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
723 reset_type, *out_handle); 758 *out_handle);
724 return RESULT_SUCCESS; 759 return RESULT_SUCCESS;
725} 760}
726 761
@@ -783,17 +818,19 @@ static void SleepThread(s64 nanoseconds) {
783static s64 GetSystemTick() { 818static s64 GetSystemTick() {
784 s64 result = CoreTiming::GetTicks(); 819 s64 result = CoreTiming::GetTicks();
785 // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end. 820 // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end.
786 Core::g_app_core->AddTicks(150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b 821 Core::g_app_core->AddTicks(
822 150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b
787 return result; 823 return result;
788} 824}
789 825
790/// Creates a memory block at the specified address with the specified permissions and size 826/// Creates a memory block at the specified address with the specified permissions and size
791static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, 827static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission,
792 u32 other_permission) { 828 u32 other_permission) {
793 using Kernel::SharedMemory; 829 using Kernel::SharedMemory;
794 830
795 if (size % Memory::PAGE_SIZE != 0) 831 if (size % Memory::PAGE_SIZE != 0)
796 return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 832 return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS,
833 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
797 834
798 SharedPtr<SharedMemory> shared_memory = nullptr; 835 SharedPtr<SharedMemory> shared_memory = nullptr;
799 836
@@ -818,25 +855,29 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
818 ErrorSummary::InvalidArgument, ErrorLevel::Usage); 855 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
819 856
820 if (addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) { 857 if (addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) {
821 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 858 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
859 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
822 } 860 }
823 861
824 // When trying to create a memory block with address = 0, 862 // When trying to create a memory block with address = 0,
825 // if the process has the Shared Device Memory flag in the exheader, 863 // if the process has the Shared Device Memory flag in the exheader,
826 // then we have to allocate from the same region as the caller process instead of the BASE region. 864 // then we have to allocate from the same region as the caller process instead of the BASE
865 // region.
827 Kernel::MemoryRegion region = Kernel::MemoryRegion::BASE; 866 Kernel::MemoryRegion region = Kernel::MemoryRegion::BASE;
828 if (addr == 0 && Kernel::g_current_process->flags.shared_device_mem) 867 if (addr == 0 && Kernel::g_current_process->flags.shared_device_mem)
829 region = Kernel::g_current_process->flags.memory_region; 868 region = Kernel::g_current_process->flags.memory_region;
830 869
831 shared_memory = SharedMemory::Create(Kernel::g_current_process, size, 870 shared_memory = SharedMemory::Create(
832 static_cast<MemoryPermission>(my_permission), static_cast<MemoryPermission>(other_permission), addr, region); 871 Kernel::g_current_process, size, static_cast<MemoryPermission>(my_permission),
872 static_cast<MemoryPermission>(other_permission), addr, region);
833 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); 873 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
834 874
835 LOG_WARNING(Kernel_SVC, "called addr=0x%08X", addr); 875 LOG_WARNING(Kernel_SVC, "called addr=0x%08X", addr);
836 return RESULT_SUCCESS; 876 return RESULT_SUCCESS;
837} 877}
838 878
839static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name, u32 max_sessions) { 879static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name,
880 u32 max_sessions) {
840 // TODO(Subv): Implement named ports. 881 // TODO(Subv): Implement named ports.
841 ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented"); 882 ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented");
842 883
@@ -845,9 +886,12 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, const cha
845 using Kernel::SharedPtr; 886 using Kernel::SharedPtr;
846 887
847 auto ports = ServerPort::CreatePortPair(max_sessions); 888 auto ports = ServerPort::CreatePortPair(max_sessions);
848 CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports)))); 889 CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create(
849 // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be created. 890 std::move(std::get<SharedPtr<ClientPort>>(ports))));
850 CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ServerPort>>(ports)))); 891 // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
892 // created.
893 CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create(
894 std::move(std::get<SharedPtr<ServerPort>>(ports))));
851 895
852 LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions); 896 LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions);
853 return RESULT_SUCCESS; 897 return RESULT_SUCCESS;
@@ -862,9 +906,9 @@ static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
862 case SystemInfoType::REGION_MEMORY_USAGE: 906 case SystemInfoType::REGION_MEMORY_USAGE:
863 switch ((SystemInfoMemUsageRegion)param) { 907 switch ((SystemInfoMemUsageRegion)param) {
864 case SystemInfoMemUsageRegion::ALL: 908 case SystemInfoMemUsageRegion::ALL:
865 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used 909 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used +
866 + Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used 910 Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used +
867 + Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used; 911 Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used;
868 break; 912 break;
869 case SystemInfoMemUsageRegion::APPLICATION: 913 case SystemInfoMemUsageRegion::APPLICATION:
870 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used; 914 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used;
@@ -912,7 +956,7 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
912 // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure 956 // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure
913 // what's the difference between them. 957 // what's the difference between them.
914 *out = process->heap_used + process->linear_heap_used + process->misc_memory_used; 958 *out = process->heap_used + process->linear_heap_used + process->misc_memory_used;
915 if(*out % Memory::PAGE_SIZE != 0) { 959 if (*out % Memory::PAGE_SIZE != 0) {
916 LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned"); 960 LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned");
917 return ERR_MISALIGNED_SIZE; 961 return ERR_MISALIGNED_SIZE;
918 } 962 }
@@ -935,12 +979,12 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
935 979
936 if (type >= 21 && type <= 23) { 980 if (type >= 21 && type <= 23) {
937 return ResultCode( // 0xE0E01BF4 981 return ResultCode( // 0xE0E01BF4
938 ErrorDescription::NotImplemented, ErrorModule::OS, 982 ErrorDescription::NotImplemented, ErrorModule::OS, ErrorSummary::InvalidArgument,
939 ErrorSummary::InvalidArgument, ErrorLevel::Usage); 983 ErrorLevel::Usage);
940 } else { 984 } else {
941 return ResultCode( // 0xD8E007ED 985 return ResultCode( // 0xD8E007ED
942 ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, 986 ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
943 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 987 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
944 } 988 }
945 break; 989 break;
946 } 990 }
@@ -949,142 +993,142 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
949} 993}
950 994
951namespace { 995namespace {
952 struct FunctionDef { 996struct FunctionDef {
953 using Func = void(); 997 using Func = void();
954 998
955 u32 id; 999 u32 id;
956 Func* func; 1000 Func* func;
957 const char* name; 1001 const char* name;
958 }; 1002};
959} 1003}
960 1004
961static const FunctionDef SVC_Table[] = { 1005static const FunctionDef SVC_Table[] = {
962 {0x00, nullptr, "Unknown"}, 1006 {0x00, nullptr, "Unknown"},
963 {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"}, 1007 {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"},
964 {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"}, 1008 {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"},
965 {0x03, nullptr, "ExitProcess"}, 1009 {0x03, nullptr, "ExitProcess"},
966 {0x04, nullptr, "GetProcessAffinityMask"}, 1010 {0x04, nullptr, "GetProcessAffinityMask"},
967 {0x05, nullptr, "SetProcessAffinityMask"}, 1011 {0x05, nullptr, "SetProcessAffinityMask"},
968 {0x06, nullptr, "GetProcessIdealProcessor"}, 1012 {0x06, nullptr, "GetProcessIdealProcessor"},
969 {0x07, nullptr, "SetProcessIdealProcessor"}, 1013 {0x07, nullptr, "SetProcessIdealProcessor"},
970 {0x08, HLE::Wrap<CreateThread>, "CreateThread"}, 1014 {0x08, HLE::Wrap<CreateThread>, "CreateThread"},
971 {0x09, ExitThread, "ExitThread"}, 1015 {0x09, ExitThread, "ExitThread"},
972 {0x0A, HLE::Wrap<SleepThread>, "SleepThread"}, 1016 {0x0A, HLE::Wrap<SleepThread>, "SleepThread"},
973 {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"}, 1017 {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"},
974 {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"}, 1018 {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"},
975 {0x0D, nullptr, "GetThreadAffinityMask"}, 1019 {0x0D, nullptr, "GetThreadAffinityMask"},
976 {0x0E, nullptr, "SetThreadAffinityMask"}, 1020 {0x0E, nullptr, "SetThreadAffinityMask"},
977 {0x0F, nullptr, "GetThreadIdealProcessor"}, 1021 {0x0F, nullptr, "GetThreadIdealProcessor"},
978 {0x10, nullptr, "SetThreadIdealProcessor"}, 1022 {0x10, nullptr, "SetThreadIdealProcessor"},
979 {0x11, nullptr, "GetCurrentProcessorNumber"}, 1023 {0x11, nullptr, "GetCurrentProcessorNumber"},
980 {0x12, nullptr, "Run"}, 1024 {0x12, nullptr, "Run"},
981 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, 1025 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"},
982 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, 1026 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"},
983 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"}, 1027 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"},
984 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"}, 1028 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"},
985 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, 1029 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"},
986 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, 1030 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"},
987 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, 1031 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"},
988 {0x1A, HLE::Wrap<CreateTimer>, "CreateTimer"}, 1032 {0x1A, HLE::Wrap<CreateTimer>, "CreateTimer"},
989 {0x1B, HLE::Wrap<SetTimer>, "SetTimer"}, 1033 {0x1B, HLE::Wrap<SetTimer>, "SetTimer"},
990 {0x1C, HLE::Wrap<CancelTimer>, "CancelTimer"}, 1034 {0x1C, HLE::Wrap<CancelTimer>, "CancelTimer"},
991 {0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"}, 1035 {0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"},
992 {0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"}, 1036 {0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"},
993 {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"}, 1037 {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"},
994 {0x20, HLE::Wrap<UnmapMemoryBlock>, "UnmapMemoryBlock"}, 1038 {0x20, HLE::Wrap<UnmapMemoryBlock>, "UnmapMemoryBlock"},
995 {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"}, 1039 {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"},
996 {0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"}, 1040 {0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"},
997 {0x23, HLE::Wrap<CloseHandle>, "CloseHandle"}, 1041 {0x23, HLE::Wrap<CloseHandle>, "CloseHandle"},
998 {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"}, 1042 {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"},
999 {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"}, 1043 {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"},
1000 {0x26, nullptr, "SignalAndWait"}, 1044 {0x26, nullptr, "SignalAndWait"},
1001 {0x27, HLE::Wrap<DuplicateHandle>, "DuplicateHandle"}, 1045 {0x27, HLE::Wrap<DuplicateHandle>, "DuplicateHandle"},
1002 {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"}, 1046 {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"},
1003 {0x29, nullptr, "GetHandleInfo"}, 1047 {0x29, nullptr, "GetHandleInfo"},
1004 {0x2A, HLE::Wrap<GetSystemInfo>, "GetSystemInfo"}, 1048 {0x2A, HLE::Wrap<GetSystemInfo>, "GetSystemInfo"},
1005 {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"}, 1049 {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"},
1006 {0x2C, nullptr, "GetThreadInfo"}, 1050 {0x2C, nullptr, "GetThreadInfo"},
1007 {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"}, 1051 {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"},
1008 {0x2E, nullptr, "SendSyncRequest1"}, 1052 {0x2E, nullptr, "SendSyncRequest1"},
1009 {0x2F, nullptr, "SendSyncRequest2"}, 1053 {0x2F, nullptr, "SendSyncRequest2"},
1010 {0x30, nullptr, "SendSyncRequest3"}, 1054 {0x30, nullptr, "SendSyncRequest3"},
1011 {0x31, nullptr, "SendSyncRequest4"}, 1055 {0x31, nullptr, "SendSyncRequest4"},
1012 {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"}, 1056 {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"},
1013 {0x33, nullptr, "OpenProcess"}, 1057 {0x33, nullptr, "OpenProcess"},
1014 {0x34, nullptr, "OpenThread"}, 1058 {0x34, nullptr, "OpenThread"},
1015 {0x35, HLE::Wrap<GetProcessId>, "GetProcessId"}, 1059 {0x35, HLE::Wrap<GetProcessId>, "GetProcessId"},
1016 {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"}, 1060 {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"},
1017 {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"}, 1061 {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"},
1018 {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"}, 1062 {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"},
1019 {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"}, 1063 {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"},
1020 {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"}, 1064 {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"},
1021 {0x3B, nullptr, "GetThreadContext"}, 1065 {0x3B, nullptr, "GetThreadContext"},
1022 {0x3C, HLE::Wrap<Break>, "Break"}, 1066 {0x3C, HLE::Wrap<Break>, "Break"},
1023 {0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"}, 1067 {0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"},
1024 {0x3E, nullptr, "ControlPerformanceCounter"}, 1068 {0x3E, nullptr, "ControlPerformanceCounter"},
1025 {0x3F, nullptr, "Unknown"}, 1069 {0x3F, nullptr, "Unknown"},
1026 {0x40, nullptr, "Unknown"}, 1070 {0x40, nullptr, "Unknown"},
1027 {0x41, nullptr, "Unknown"}, 1071 {0x41, nullptr, "Unknown"},
1028 {0x42, nullptr, "Unknown"}, 1072 {0x42, nullptr, "Unknown"},
1029 {0x43, nullptr, "Unknown"}, 1073 {0x43, nullptr, "Unknown"},
1030 {0x44, nullptr, "Unknown"}, 1074 {0x44, nullptr, "Unknown"},
1031 {0x45, nullptr, "Unknown"}, 1075 {0x45, nullptr, "Unknown"},
1032 {0x46, nullptr, "Unknown"}, 1076 {0x46, nullptr, "Unknown"},
1033 {0x47, HLE::Wrap<CreatePort>, "CreatePort"}, 1077 {0x47, HLE::Wrap<CreatePort>, "CreatePort"},
1034 {0x48, nullptr, "CreateSessionToPort"}, 1078 {0x48, nullptr, "CreateSessionToPort"},
1035 {0x49, nullptr, "CreateSession"}, 1079 {0x49, nullptr, "CreateSession"},
1036 {0x4A, nullptr, "AcceptSession"}, 1080 {0x4A, nullptr, "AcceptSession"},
1037 {0x4B, nullptr, "ReplyAndReceive1"}, 1081 {0x4B, nullptr, "ReplyAndReceive1"},
1038 {0x4C, nullptr, "ReplyAndReceive2"}, 1082 {0x4C, nullptr, "ReplyAndReceive2"},
1039 {0x4D, nullptr, "ReplyAndReceive3"}, 1083 {0x4D, nullptr, "ReplyAndReceive3"},
1040 {0x4E, nullptr, "ReplyAndReceive4"}, 1084 {0x4E, nullptr, "ReplyAndReceive4"},
1041 {0x4F, nullptr, "ReplyAndReceive"}, 1085 {0x4F, nullptr, "ReplyAndReceive"},
1042 {0x50, nullptr, "BindInterrupt"}, 1086 {0x50, nullptr, "BindInterrupt"},
1043 {0x51, nullptr, "UnbindInterrupt"}, 1087 {0x51, nullptr, "UnbindInterrupt"},
1044 {0x52, nullptr, "InvalidateProcessDataCache"}, 1088 {0x52, nullptr, "InvalidateProcessDataCache"},
1045 {0x53, nullptr, "StoreProcessDataCache"}, 1089 {0x53, nullptr, "StoreProcessDataCache"},
1046 {0x54, nullptr, "FlushProcessDataCache"}, 1090 {0x54, nullptr, "FlushProcessDataCache"},
1047 {0x55, nullptr, "StartInterProcessDma"}, 1091 {0x55, nullptr, "StartInterProcessDma"},
1048 {0x56, nullptr, "StopDma"}, 1092 {0x56, nullptr, "StopDma"},
1049 {0x57, nullptr, "GetDmaState"}, 1093 {0x57, nullptr, "GetDmaState"},
1050 {0x58, nullptr, "RestartDma"}, 1094 {0x58, nullptr, "RestartDma"},
1051 {0x59, nullptr, "Unknown"}, 1095 {0x59, nullptr, "Unknown"},
1052 {0x5A, nullptr, "Unknown"}, 1096 {0x5A, nullptr, "Unknown"},
1053 {0x5B, nullptr, "Unknown"}, 1097 {0x5B, nullptr, "Unknown"},
1054 {0x5C, nullptr, "Unknown"}, 1098 {0x5C, nullptr, "Unknown"},
1055 {0x5D, nullptr, "Unknown"}, 1099 {0x5D, nullptr, "Unknown"},
1056 {0x5E, nullptr, "Unknown"}, 1100 {0x5E, nullptr, "Unknown"},
1057 {0x5F, nullptr, "Unknown"}, 1101 {0x5F, nullptr, "Unknown"},
1058 {0x60, nullptr, "DebugActiveProcess"}, 1102 {0x60, nullptr, "DebugActiveProcess"},
1059 {0x61, nullptr, "BreakDebugProcess"}, 1103 {0x61, nullptr, "BreakDebugProcess"},
1060 {0x62, nullptr, "TerminateDebugProcess"}, 1104 {0x62, nullptr, "TerminateDebugProcess"},
1061 {0x63, nullptr, "GetProcessDebugEvent"}, 1105 {0x63, nullptr, "GetProcessDebugEvent"},
1062 {0x64, nullptr, "ContinueDebugEvent"}, 1106 {0x64, nullptr, "ContinueDebugEvent"},
1063 {0x65, nullptr, "GetProcessList"}, 1107 {0x65, nullptr, "GetProcessList"},
1064 {0x66, nullptr, "GetThreadList"}, 1108 {0x66, nullptr, "GetThreadList"},
1065 {0x67, nullptr, "GetDebugThreadContext"}, 1109 {0x67, nullptr, "GetDebugThreadContext"},
1066 {0x68, nullptr, "SetDebugThreadContext"}, 1110 {0x68, nullptr, "SetDebugThreadContext"},
1067 {0x69, nullptr, "QueryDebugProcessMemory"}, 1111 {0x69, nullptr, "QueryDebugProcessMemory"},
1068 {0x6A, nullptr, "ReadProcessMemory"}, 1112 {0x6A, nullptr, "ReadProcessMemory"},
1069 {0x6B, nullptr, "WriteProcessMemory"}, 1113 {0x6B, nullptr, "WriteProcessMemory"},
1070 {0x6C, nullptr, "SetHardwareBreakPoint"}, 1114 {0x6C, nullptr, "SetHardwareBreakPoint"},
1071 {0x6D, nullptr, "GetDebugThreadParam"}, 1115 {0x6D, nullptr, "GetDebugThreadParam"},
1072 {0x6E, nullptr, "Unknown"}, 1116 {0x6E, nullptr, "Unknown"},
1073 {0x6F, nullptr, "Unknown"}, 1117 {0x6F, nullptr, "Unknown"},
1074 {0x70, nullptr, "ControlProcessMemory"}, 1118 {0x70, nullptr, "ControlProcessMemory"},
1075 {0x71, nullptr, "MapProcessMemory"}, 1119 {0x71, nullptr, "MapProcessMemory"},
1076 {0x72, nullptr, "UnmapProcessMemory"}, 1120 {0x72, nullptr, "UnmapProcessMemory"},
1077 {0x73, nullptr, "CreateCodeSet"}, 1121 {0x73, nullptr, "CreateCodeSet"},
1078 {0x74, nullptr, "RandomStub"}, 1122 {0x74, nullptr, "RandomStub"},
1079 {0x75, nullptr, "CreateProcess"}, 1123 {0x75, nullptr, "CreateProcess"},
1080 {0x76, nullptr, "TerminateProcess"}, 1124 {0x76, nullptr, "TerminateProcess"},
1081 {0x77, nullptr, "SetProcessResourceLimits"}, 1125 {0x77, nullptr, "SetProcessResourceLimits"},
1082 {0x78, nullptr, "CreateResourceLimit"}, 1126 {0x78, nullptr, "CreateResourceLimit"},
1083 {0x79, nullptr, "SetResourceLimitValues"}, 1127 {0x79, nullptr, "SetResourceLimitValues"},
1084 {0x7A, nullptr, "AddCodeSegment"}, 1128 {0x7A, nullptr, "AddCodeSegment"},
1085 {0x7B, nullptr, "Backdoor"}, 1129 {0x7B, nullptr, "Backdoor"},
1086 {0x7C, nullptr, "KernelSetState"}, 1130 {0x7C, nullptr, "KernelSetState"},
1087 {0x7D, HLE::Wrap<QueryProcessMemory>, "QueryProcessMemory"}, 1131 {0x7D, HLE::Wrap<QueryProcessMemory>, "QueryProcessMemory"},
1088}; 1132};
1089 1133
1090static const FunctionDef* GetSVCInfo(u32 func_num) { 1134static const FunctionDef* GetSVCInfo(u32 func_num) {
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index a4dfb7e43..bf2c066f4 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -12,15 +12,15 @@
12#include "common/microprofile.h" 12#include "common/microprofile.h"
13#include "common/vector_math.h" 13#include "common/vector_math.h"
14 14
15#include "core/settings.h"
16#include "core/memory.h"
17#include "core/core_timing.h" 15#include "core/core_timing.h"
16#include "core/memory.h"
17#include "core/settings.h"
18 18
19#include "core/hle/service/gsp_gpu.h" 19#include "core/hle/service/gsp_gpu.h"
20#include "core/hle/service/hid/hid.h" 20#include "core/hle/service/hid/hid.h"
21 21
22#include "core/hw/hw.h"
23#include "core/hw/gpu.h" 22#include "core/hw/gpu.h"
23#include "core/hw/hw.h"
24 24
25#include "core/tracer/recorder.h" 25#include "core/tracer/recorder.h"
26 26
@@ -32,7 +32,6 @@
32 32
33#include "video_core/debug_utils/debug_utils.h" 33#include "video_core/debug_utils/debug_utils.h"
34 34
35
36namespace GPU { 35namespace GPU {
37 36
38Regs g_regs; 37Regs g_regs;
@@ -49,7 +48,7 @@ static u64 frame_count;
49static bool last_skip_frame; 48static bool last_skip_frame;
50 49
51template <typename T> 50template <typename T>
52inline void Read(T &var, const u32 raw_addr) { 51inline void Read(T& var, const u32 raw_addr) {
53 u32 addr = raw_addr - HW::VADDR_GPU; 52 u32 addr = raw_addr - HW::VADDR_GPU;
54 u32 index = addr / 4; 53 u32 index = addr / 4;
55 54
@@ -105,8 +104,7 @@ inline void Write(u32 addr, const T data) {
105 104
106 // Memory fills are triggered once the fill value is written. 105 // Memory fills are triggered once the fill value is written.
107 case GPU_REG_INDEX_WORKAROUND(memory_fill_config[0].trigger, 0x00004 + 0x3): 106 case GPU_REG_INDEX_WORKAROUND(memory_fill_config[0].trigger, 0x00004 + 0x3):
108 case GPU_REG_INDEX_WORKAROUND(memory_fill_config[1].trigger, 0x00008 + 0x3): 107 case GPU_REG_INDEX_WORKAROUND(memory_fill_config[1].trigger, 0x00008 + 0x3): {
109 {
110 const bool is_second_filler = (index != GPU_REG_INDEX(memory_fill_config[0].trigger)); 108 const bool is_second_filler = (index != GPU_REG_INDEX(memory_fill_config[0].trigger));
111 auto& config = g_regs.memory_fill_config[is_second_filler]; 109 auto& config = g_regs.memory_fill_config[is_second_filler];
112 110
@@ -125,7 +123,9 @@ inline void Write(u32 addr, const T data) {
125 // regions that were between surfaces or within the touching 123 // regions that were between surfaces or within the touching
126 // ones for cpu to manually fill here. 124 // ones for cpu to manually fill here.
127 if (!VideoCore::g_renderer->Rasterizer()->AccelerateFill(config)) { 125 if (!VideoCore::g_renderer->Rasterizer()->AccelerateFill(config)) {
128 Memory::RasterizerFlushAndInvalidateRegion(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress()); 126 Memory::RasterizerFlushAndInvalidateRegion(config.GetStartAddress(),
127 config.GetEndAddress() -
128 config.GetStartAddress());
129 129
130 if (config.fill_24bit) { 130 if (config.fill_24bit) {
131 // fill with 24-bit values 131 // fill with 24-bit values
@@ -150,7 +150,8 @@ inline void Write(u32 addr, const T data) {
150 } 150 }
151 } 151 }
152 152
153 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress()); 153 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(),
154 config.GetEndAddress());
154 155
155 if (!is_second_filler) { 156 if (!is_second_filler) {
156 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0); 157 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0);
@@ -167,15 +168,15 @@ inline void Write(u32 addr, const T data) {
167 break; 168 break;
168 } 169 }
169 170
170 case GPU_REG_INDEX(display_transfer_config.trigger): 171 case GPU_REG_INDEX(display_transfer_config.trigger): {
171 {
172 MICROPROFILE_SCOPE(GPU_DisplayTransfer); 172 MICROPROFILE_SCOPE(GPU_DisplayTransfer);
173 173
174 const auto& config = g_regs.display_transfer_config; 174 const auto& config = g_regs.display_transfer_config;
175 if (config.trigger & 1) { 175 if (config.trigger & 1) {
176 176
177 if (Pica::g_debug_context) 177 if (Pica::g_debug_context)
178 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::IncomingDisplayTransfer, nullptr); 178 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::IncomingDisplayTransfer,
179 nullptr);
179 180
180 if (!VideoCore::g_renderer->Rasterizer()->AccelerateDisplayTransfer(config)) { 181 if (!VideoCore::g_renderer->Rasterizer()->AccelerateDisplayTransfer(config)) {
181 u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress()); 182 u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress());
@@ -187,17 +188,23 @@ inline void Write(u32 addr, const T data) {
187 u32 output_width = config.texture_copy.output_width * 16; 188 u32 output_width = config.texture_copy.output_width * 16;
188 u32 output_gap = config.texture_copy.output_gap * 16; 189 u32 output_gap = config.texture_copy.output_gap * 16;
189 190
190 size_t contiguous_input_size = config.texture_copy.size / input_width * (input_width + input_gap); 191 size_t contiguous_input_size =
191 Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), static_cast<u32>(contiguous_input_size)); 192 config.texture_copy.size / input_width * (input_width + input_gap);
193 Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(),
194 static_cast<u32>(contiguous_input_size));
192 195
193 size_t contiguous_output_size = config.texture_copy.size / output_width * (output_width + output_gap); 196 size_t contiguous_output_size =
194 Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), static_cast<u32>(contiguous_output_size)); 197 config.texture_copy.size / output_width * (output_width + output_gap);
198 Memory::RasterizerFlushAndInvalidateRegion(
199 config.GetPhysicalOutputAddress(),
200 static_cast<u32>(contiguous_output_size));
195 201
196 u32 remaining_size = config.texture_copy.size; 202 u32 remaining_size = config.texture_copy.size;
197 u32 remaining_input = input_width; 203 u32 remaining_input = input_width;
198 u32 remaining_output = output_width; 204 u32 remaining_output = output_width;
199 while (remaining_size > 0) { 205 while (remaining_size > 0) {
200 u32 copy_size = std::min({ remaining_input, remaining_output, remaining_size }); 206 u32 copy_size =
207 std::min({remaining_input, remaining_output, remaining_size});
201 208
202 std::memcpy(dst_pointer, src_pointer, copy_size); 209 std::memcpy(dst_pointer, src_pointer, copy_size);
203 src_pointer += copy_size; 210 src_pointer += copy_size;
@@ -217,10 +224,11 @@ inline void Write(u32 addr, const T data) {
217 } 224 }
218 } 225 }
219 226
220 LOG_TRACE(HW_GPU, "TextureCopy: 0x%X bytes from 0x%08X(%u+%u)-> 0x%08X(%u+%u), flags 0x%08X", 227 LOG_TRACE(
221 config.texture_copy.size, 228 HW_GPU,
222 config.GetPhysicalInputAddress(), input_width, input_gap, 229 "TextureCopy: 0x%X bytes from 0x%08X(%u+%u)-> 0x%08X(%u+%u), flags 0x%08X",
223 config.GetPhysicalOutputAddress(), output_width, output_gap, 230 config.texture_copy.size, config.GetPhysicalInputAddress(), input_width,
231 input_gap, config.GetPhysicalOutputAddress(), output_width, output_gap,
224 config.flags); 232 config.flags);
225 233
226 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); 234 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF);
@@ -228,7 +236,8 @@ inline void Write(u32 addr, const T data) {
228 } 236 }
229 237
230 if (config.scaling > config.ScaleXY) { 238 if (config.scaling > config.ScaleXY) {
231 LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode %u", config.scaling.Value()); 239 LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode %u",
240 config.scaling.Value());
232 UNIMPLEMENTED(); 241 UNIMPLEMENTED();
233 break; 242 break;
234 } 243 }
@@ -245,11 +254,14 @@ inline void Write(u32 addr, const T data) {
245 u32 output_width = config.output_width >> horizontal_scale; 254 u32 output_width = config.output_width >> horizontal_scale;
246 u32 output_height = config.output_height >> vertical_scale; 255 u32 output_height = config.output_height >> vertical_scale;
247 256
248 u32 input_size = config.input_width * config.input_height * GPU::Regs::BytesPerPixel(config.input_format); 257 u32 input_size = config.input_width * config.input_height *
249 u32 output_size = output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format); 258 GPU::Regs::BytesPerPixel(config.input_format);
259 u32 output_size =
260 output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format);
250 261
251 Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), input_size); 262 Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), input_size);
252 Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), output_size); 263 Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(),
264 output_size);
253 265
254 for (u32 y = 0; y < output_height; ++y) { 266 for (u32 y = 0; y < output_height; ++y) {
255 for (u32 x = 0; x < output_width; ++x) { 267 for (u32 x = 0; x < output_width; ++x) {
@@ -278,11 +290,14 @@ inline void Write(u32 addr, const T data) {
278 u32 coarse_y = y & ~7; 290 u32 coarse_y = y & ~7;
279 u32 stride = output_width * dst_bytes_per_pixel; 291 u32 stride = output_width * dst_bytes_per_pixel;
280 292
281 src_offset = (input_x + input_y * config.input_width) * src_bytes_per_pixel; 293 src_offset =
282 dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + coarse_y * stride; 294 (input_x + input_y * config.input_width) * src_bytes_per_pixel;
295 dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) +
296 coarse_y * stride;
283 } else { 297 } else {
284 // Both input and output are linear 298 // Both input and output are linear
285 src_offset = (input_x + input_y * config.input_width) * src_bytes_per_pixel; 299 src_offset =
300 (input_x + input_y * config.input_width) * src_bytes_per_pixel;
286 dst_offset = (x + y * output_width) * dst_bytes_per_pixel; 301 dst_offset = (x + y * output_width) * dst_bytes_per_pixel;
287 } 302 }
288 } else { 303 } else {
@@ -291,7 +306,9 @@ inline void Write(u32 addr, const T data) {
291 u32 coarse_y = input_y & ~7; 306 u32 coarse_y = input_y & ~7;
292 u32 stride = config.input_width * src_bytes_per_pixel; 307 u32 stride = config.input_width * src_bytes_per_pixel;
293 308
294 src_offset = VideoCore::GetMortonOffset(input_x, input_y, src_bytes_per_pixel) + coarse_y * stride; 309 src_offset = VideoCore::GetMortonOffset(input_x, input_y,
310 src_bytes_per_pixel) +
311 coarse_y * stride;
295 dst_offset = (x + y * output_width) * dst_bytes_per_pixel; 312 dst_offset = (x + y * output_width) * dst_bytes_per_pixel;
296 } else { 313 } else {
297 // Both input and output are tiled 314 // Both input and output are tiled
@@ -301,20 +318,27 @@ inline void Write(u32 addr, const T data) {
301 u32 in_coarse_y = input_y & ~7; 318 u32 in_coarse_y = input_y & ~7;
302 u32 in_stride = config.input_width * src_bytes_per_pixel; 319 u32 in_stride = config.input_width * src_bytes_per_pixel;
303 320
304 src_offset = VideoCore::GetMortonOffset(input_x, input_y, src_bytes_per_pixel) + in_coarse_y * in_stride; 321 src_offset = VideoCore::GetMortonOffset(input_x, input_y,
305 dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + out_coarse_y * out_stride; 322 src_bytes_per_pixel) +
323 in_coarse_y * in_stride;
324 dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) +
325 out_coarse_y * out_stride;
306 } 326 }
307 } 327 }
308 328
309 const u8* src_pixel = src_pointer + src_offset; 329 const u8* src_pixel = src_pointer + src_offset;
310 src_color = DecodePixel(config.input_format, src_pixel); 330 src_color = DecodePixel(config.input_format, src_pixel);
311 if (config.scaling == config.ScaleX) { 331 if (config.scaling == config.ScaleX) {
312 Math::Vec4<u8> pixel = DecodePixel(config.input_format, src_pixel + src_bytes_per_pixel); 332 Math::Vec4<u8> pixel =
333 DecodePixel(config.input_format, src_pixel + src_bytes_per_pixel);
313 src_color = ((src_color + pixel) / 2).Cast<u8>(); 334 src_color = ((src_color + pixel) / 2).Cast<u8>();
314 } else if (config.scaling == config.ScaleXY) { 335 } else if (config.scaling == config.ScaleXY) {
315 Math::Vec4<u8> pixel1 = DecodePixel(config.input_format, src_pixel + 1 * src_bytes_per_pixel); 336 Math::Vec4<u8> pixel1 = DecodePixel(
316 Math::Vec4<u8> pixel2 = DecodePixel(config.input_format, src_pixel + 2 * src_bytes_per_pixel); 337 config.input_format, src_pixel + 1 * src_bytes_per_pixel);
317 Math::Vec4<u8> pixel3 = DecodePixel(config.input_format, src_pixel + 3 * src_bytes_per_pixel); 338 Math::Vec4<u8> pixel2 = DecodePixel(
339 config.input_format, src_pixel + 2 * src_bytes_per_pixel);
340 Math::Vec4<u8> pixel3 = DecodePixel(
341 config.input_format, src_pixel + 3 * src_bytes_per_pixel);
318 src_color = (((src_color + pixel1) + (pixel2 + pixel3)) / 4).Cast<u8>(); 342 src_color = (((src_color + pixel1) + (pixel2 + pixel3)) / 4).Cast<u8>();
319 } 343 }
320 344
@@ -341,17 +365,20 @@ inline void Write(u32 addr, const T data) {
341 break; 365 break;
342 366
343 default: 367 default:
344 LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x", config.output_format.Value()); 368 LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x",
369 config.output_format.Value());
345 break; 370 break;
346 } 371 }
347 } 372 }
348 } 373 }
349 374
350 LOG_TRACE(HW_GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), dst format %x, flags 0x%08X", 375 LOG_TRACE(HW_GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> "
351 config.output_height * output_width * GPU::Regs::BytesPerPixel(config.output_format), 376 "0x%08x(%ux%u), dst format %x, flags 0x%08X",
352 config.GetPhysicalInputAddress(), config.input_width.Value(), config.input_height.Value(), 377 config.output_height * output_width *
353 config.GetPhysicalOutputAddress(), output_width, output_height, 378 GPU::Regs::BytesPerPixel(config.output_format),
354 config.output_format.Value(), config.flags); 379 config.GetPhysicalInputAddress(), config.input_width.Value(),
380 config.input_height.Value(), config.GetPhysicalOutputAddress(),
381 output_width, output_height, config.output_format.Value(), config.flags);
355 } 382 }
356 383
357 g_regs.display_transfer_config.trigger = 0; 384 g_regs.display_transfer_config.trigger = 0;
@@ -361,17 +388,16 @@ inline void Write(u32 addr, const T data) {
361 } 388 }
362 389
363 // Seems like writing to this register triggers processing 390 // Seems like writing to this register triggers processing
364 case GPU_REG_INDEX(command_processor_config.trigger): 391 case GPU_REG_INDEX(command_processor_config.trigger): {
365 {
366 const auto& config = g_regs.command_processor_config; 392 const auto& config = g_regs.command_processor_config;
367 if (config.trigger & 1) 393 if (config.trigger & 1) {
368 {
369 MICROPROFILE_SCOPE(GPU_CmdlistProcessing); 394 MICROPROFILE_SCOPE(GPU_CmdlistProcessing);
370 395
371 u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress()); 396 u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress());
372 397
373 if (Pica::g_debug_context && Pica::g_debug_context->recorder) { 398 if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
374 Pica::g_debug_context->recorder->MemoryAccessed((u8*)buffer, config.size * sizeof(u32), config.GetPhysicalAddress()); 399 Pica::g_debug_context->recorder->MemoryAccessed(
400 (u8*)buffer, config.size * sizeof(u32), config.GetPhysicalAddress());
375 } 401 }
376 402
377 Pica::CommandProcessor::ProcessCommandList(buffer, config.size); 403 Pica::CommandProcessor::ProcessCommandList(buffer, config.size);
@@ -389,16 +415,17 @@ inline void Write(u32 addr, const T data) {
389 // This is happening *after* handling the write to make sure we properly catch all memory reads. 415 // This is happening *after* handling the write to make sure we properly catch all memory reads.
390 if (Pica::g_debug_context && Pica::g_debug_context->recorder) { 416 if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
391 // addr + GPU VBase - IO VBase + IO PBase 417 // addr + GPU VBase - IO VBase + IO PBase
392 Pica::g_debug_context->recorder->RegisterWritten<T>(addr + 0x1EF00000 - 0x1EC00000 + 0x10100000, data); 418 Pica::g_debug_context->recorder->RegisterWritten<T>(
419 addr + 0x1EF00000 - 0x1EC00000 + 0x10100000, data);
393 } 420 }
394} 421}
395 422
396// Explicitly instantiate template functions because we aren't defining this in the header: 423// Explicitly instantiate template functions because we aren't defining this in the header:
397 424
398template void Read<u64>(u64 &var, const u32 addr); 425template void Read<u64>(u64& var, const u32 addr);
399template void Read<u32>(u32 &var, const u32 addr); 426template void Read<u32>(u32& var, const u32 addr);
400template void Read<u16>(u16 &var, const u32 addr); 427template void Read<u16>(u16& var, const u32 addr);
401template void Read<u8>(u8 &var, const u32 addr); 428template void Read<u8>(u8& var, const u32 addr);
402 429
403template void Write<u64>(u32 addr, const u64 data); 430template void Write<u64>(u32 addr, const u64 data);
404template void Write<u32>(u32 addr, const u32 data); 431template void Write<u32>(u32 addr, const u32 data);
@@ -417,8 +444,9 @@ static void VBlankCallback(u64 userdata, int cycles_late) {
417 // - If frameskip == 0 (disabled), always swap buffers 444 // - If frameskip == 0 (disabled), always swap buffers
418 // - If frameskip == 1, swap buffers every other frame (starting from the first frame) 445 // - If frameskip == 1, swap buffers every other frame (starting from the first frame)
419 // - If frameskip > 1, swap buffers every frameskip^n frames (starting from the second frame) 446 // - If frameskip > 1, swap buffers every frameskip^n frames (starting from the second frame)
420 if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && last_skip_frame != g_skip_frame) || 447 if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) &&
421 Settings::values.frame_skip == 0) { 448 last_skip_frame != g_skip_frame) ||
449 Settings::values.frame_skip == 0) {
422 VideoCore::g_renderer->SwapBuffers(); 450 VideoCore::g_renderer->SwapBuffers();
423 } 451 }
424 452
@@ -448,12 +476,12 @@ void Init() {
448 // .. or at least these are the ones used by system applets. 476 // .. or at least these are the ones used by system applets.
449 // There's probably a smarter way to come up with addresses 477 // There's probably a smarter way to come up with addresses
450 // like this which does not require hardcoding. 478 // like this which does not require hardcoding.
451 framebuffer_top.address_left1 = 0x181E6000; 479 framebuffer_top.address_left1 = 0x181E6000;
452 framebuffer_top.address_left2 = 0x1822C800; 480 framebuffer_top.address_left2 = 0x1822C800;
453 framebuffer_top.address_right1 = 0x18273000; 481 framebuffer_top.address_right1 = 0x18273000;
454 framebuffer_top.address_right2 = 0x182B9800; 482 framebuffer_top.address_right2 = 0x182B9800;
455 framebuffer_sub.address_left1 = 0x1848F000; 483 framebuffer_sub.address_left1 = 0x1848F000;
456 framebuffer_sub.address_left2 = 0x184C7800; 484 framebuffer_sub.address_left2 = 0x184C7800;
457 485
458 framebuffer_top.width.Assign(240); 486 framebuffer_top.width.Assign(240);
459 framebuffer_top.height.Assign(400); 487 framebuffer_top.height.Assign(400);
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index da4c345b4..077b6255f 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -17,7 +17,8 @@ namespace GPU {
17// Returns index corresponding to the Regs member labeled by field_name 17// Returns index corresponding to the Regs member labeled by field_name
18// TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions 18// TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions
19// when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])). 19// when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])).
20// For details cf. https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members 20// For details cf.
21// https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members
21// Hopefully, this will be fixed sometime in the future. 22// Hopefully, this will be fixed sometime in the future.
22// For lack of better alternatives, we currently hardcode the offsets when constant 23// For lack of better alternatives, we currently hardcode the offsets when constant
23// expressions are needed via GPU_REG_INDEX_WORKAROUND (on sane compilers, static_asserts 24// expressions are needed via GPU_REG_INDEX_WORKAROUND (on sane compilers, static_asserts
@@ -30,8 +31,9 @@ namespace GPU {
30// really is this annoying. This macro just forwards its first argument to GPU_REG_INDEX 31// really is this annoying. This macro just forwards its first argument to GPU_REG_INDEX
31// and then performs a (no-op) cast to size_t iff the second argument matches the expected 32// and then performs a (no-op) cast to size_t iff the second argument matches the expected
32// field offset. Otherwise, the compiler will fail to compile this code. 33// field offset. Otherwise, the compiler will fail to compile this code.
33#define GPU_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ 34#define GPU_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \
34 ((typename std::enable_if<backup_workaround_index == GPU_REG_INDEX(field_name), size_t>::type)GPU_REG_INDEX(field_name)) 35 ((typename std::enable_if<backup_workaround_index == GPU_REG_INDEX(field_name), size_t>::type) \
36 GPU_REG_INDEX(field_name))
35#endif 37#endif
36 38
37// MMIO region 0x1EFxxxxx 39// MMIO region 0x1EFxxxxx
@@ -44,18 +46,18 @@ struct Regs {
44// support for that. 46// support for that.
45#define ASSERT_MEMBER_SIZE(name, size_in_bytes) 47#define ASSERT_MEMBER_SIZE(name, size_in_bytes)
46#else 48#else
47#define ASSERT_MEMBER_SIZE(name, size_in_bytes) \ 49#define ASSERT_MEMBER_SIZE(name, size_in_bytes) \
48 static_assert(sizeof(name) == size_in_bytes, \ 50 static_assert(sizeof(name) == size_in_bytes, \
49 "Structure size and register block length don't match") 51 "Structure size and register block length don't match")
50#endif 52#endif
51 53
52 // Components are laid out in reverse byte order, most significant bits first. 54 // Components are laid out in reverse byte order, most significant bits first.
53 enum class PixelFormat : u32 { 55 enum class PixelFormat : u32 {
54 RGBA8 = 0, 56 RGBA8 = 0,
55 RGB8 = 1, 57 RGB8 = 1,
56 RGB565 = 2, 58 RGB565 = 2,
57 RGB5A1 = 3, 59 RGB5A1 = 3,
58 RGBA4 = 4, 60 RGBA4 = 4,
59 }; 61 };
60 62
61 /** 63 /**
@@ -88,8 +90,8 @@ struct Regs {
88 BitField<0, 16, u32> value_16bit; 90 BitField<0, 16, u32> value_16bit;
89 91
90 // TODO: Verify component order 92 // TODO: Verify component order
91 BitField< 0, 8, u32> value_24bit_r; 93 BitField<0, 8, u32> value_24bit_r;
92 BitField< 8, 8, u32> value_24bit_g; 94 BitField<8, 8, u32> value_24bit_g;
93 BitField<16, 8, u32> value_24bit_b; 95 BitField<16, 8, u32> value_24bit_b;
94 }; 96 };
95 97
@@ -126,7 +128,7 @@ struct Regs {
126 union { 128 union {
127 u32 size; 129 u32 size;
128 130
129 BitField< 0, 16, u32> width; 131 BitField<0, 16, u32> width;
130 BitField<16, 16, u32> height; 132 BitField<16, 16, u32> height;
131 }; 133 };
132 134
@@ -138,7 +140,7 @@ struct Regs {
138 union { 140 union {
139 u32 format; 141 u32 format;
140 142
141 BitField< 0, 3, PixelFormat> color_format; 143 BitField<0, 3, PixelFormat> color_format;
142 }; 144 };
143 145
144 INSERT_PADDING_WORDS(0x1); 146 INSERT_PADDING_WORDS(0x1);
@@ -180,35 +182,37 @@ struct Regs {
180 union { 182 union {
181 u32 output_size; 183 u32 output_size;
182 184
183 BitField< 0, 16, u32> output_width; 185 BitField<0, 16, u32> output_width;
184 BitField<16, 16, u32> output_height; 186 BitField<16, 16, u32> output_height;
185 }; 187 };
186 188
187 union { 189 union {
188 u32 input_size; 190 u32 input_size;
189 191
190 BitField< 0, 16, u32> input_width; 192 BitField<0, 16, u32> input_width;
191 BitField<16, 16, u32> input_height; 193 BitField<16, 16, u32> input_height;
192 }; 194 };
193 195
194 enum ScalingMode : u32 { 196 enum ScalingMode : u32 {
195 NoScale = 0, // Doesn't scale the image 197 NoScale = 0, // Doesn't scale the image
196 ScaleX = 1, // Downscales the image in half in the X axis and applies a box filter 198 ScaleX = 1, // Downscales the image in half in the X axis and applies a box filter
197 ScaleXY = 2, // Downscales the image in half in both the X and Y axes and applies a box filter 199 ScaleXY =
200 2, // Downscales the image in half in both the X and Y axes and applies a box filter
198 }; 201 };
199 202
200 union { 203 union {
201 u32 flags; 204 u32 flags;
202 205
203 BitField< 0, 1, u32> flip_vertically; // flips input data vertically 206 BitField<0, 1, u32> flip_vertically; // flips input data vertically
204 BitField< 1, 1, u32> input_linear; // Converts from linear to tiled format 207 BitField<1, 1, u32> input_linear; // Converts from linear to tiled format
205 BitField< 2, 1, u32> crop_input_lines; 208 BitField<2, 1, u32> crop_input_lines;
206 BitField< 3, 1, u32> is_texture_copy; // Copies the data without performing any processing and respecting texture copy fields 209 BitField<3, 1, u32> is_texture_copy; // Copies the data without performing any
207 BitField< 5, 1, u32> dont_swizzle; 210 // processing and respecting texture copy fields
208 BitField< 8, 3, PixelFormat> input_format; 211 BitField<5, 1, u32> dont_swizzle;
212 BitField<8, 3, PixelFormat> input_format;
209 BitField<12, 3, PixelFormat> output_format; 213 BitField<12, 3, PixelFormat> output_format;
210 /// Uses some kind of 32x32 block swizzling mode, instead of the usual 8x8 one. 214 /// Uses some kind of 32x32 block swizzling mode, instead of the usual 8x8 one.
211 BitField<16, 1, u32> block_32; // TODO(yuriks): unimplemented 215 BitField<16, 1, u32> block_32; // TODO(yuriks): unimplemented
212 BitField<24, 2, ScalingMode> scaling; // Determines the scaling mode of the transfer 216 BitField<24, 2, ScalingMode> scaling; // Determines the scaling mode of the transfer
213 }; 217 };
214 218
@@ -225,14 +229,14 @@ struct Regs {
225 union { 229 union {
226 u32 input_size; 230 u32 input_size;
227 231
228 BitField< 0, 16, u32> input_width; 232 BitField<0, 16, u32> input_width;
229 BitField<16, 16, u32> input_gap; 233 BitField<16, 16, u32> input_gap;
230 }; 234 };
231 235
232 union { 236 union {
233 u32 output_size; 237 u32 output_size;
234 238
235 BitField< 0, 16, u32> output_width; 239 BitField<0, 16, u32> output_width;
236 BitField<16, 16, u32> output_gap; 240 BitField<16, 16, u32> output_gap;
237 }; 241 };
238 } texture_copy; 242 } texture_copy;
@@ -267,12 +271,12 @@ struct Regs {
267 return sizeof(Regs) / sizeof(u32); 271 return sizeof(Regs) / sizeof(u32);
268 } 272 }
269 273
270 const u32& operator [] (int index) const { 274 const u32& operator[](int index) const {
271 const u32* content = reinterpret_cast<const u32*>(this); 275 const u32* content = reinterpret_cast<const u32*>(this);
272 return content[index]; 276 return content[index];
273 } 277 }
274 278
275 u32& operator [] (int index) { 279 u32& operator[](int index) {
276 u32* content = reinterpret_cast<u32*>(this); 280 u32* content = reinterpret_cast<u32*>(this);
277 return content[index]; 281 return content[index];
278 } 282 }
@@ -294,28 +298,29 @@ static_assert(std::is_standard_layout<Regs>::value, "Structure does not use stan
294// is technically allowed since C++11. This macro should be enabled once MSVC adds 298// is technically allowed since C++11. This macro should be enabled once MSVC adds
295// support for that. 299// support for that.
296#ifndef _MSC_VER 300#ifndef _MSC_VER
297#define ASSERT_REG_POSITION(field_name, position) \ 301#define ASSERT_REG_POSITION(field_name, position) \
298 static_assert(offsetof(Regs, field_name) == position * 4, \ 302 static_assert(offsetof(Regs, field_name) == position * 4, \
299 "Field "#field_name" has invalid position") 303 "Field " #field_name " has invalid position")
300 304
301ASSERT_REG_POSITION(memory_fill_config[0], 0x00004); 305ASSERT_REG_POSITION(memory_fill_config[0], 0x00004);
302ASSERT_REG_POSITION(memory_fill_config[1], 0x00008); 306ASSERT_REG_POSITION(memory_fill_config[1], 0x00008);
303ASSERT_REG_POSITION(framebuffer_config[0], 0x00117); 307ASSERT_REG_POSITION(framebuffer_config[0], 0x00117);
304ASSERT_REG_POSITION(framebuffer_config[1], 0x00157); 308ASSERT_REG_POSITION(framebuffer_config[1], 0x00157);
305ASSERT_REG_POSITION(display_transfer_config, 0x00300); 309ASSERT_REG_POSITION(display_transfer_config, 0x00300);
306ASSERT_REG_POSITION(command_processor_config, 0x00638); 310ASSERT_REG_POSITION(command_processor_config, 0x00638);
307 311
308#undef ASSERT_REG_POSITION 312#undef ASSERT_REG_POSITION
309#endif // !defined(_MSC_VER) 313#endif // !defined(_MSC_VER)
310 314
311// The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value anyway. 315// The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value
316// anyway.
312static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of register set"); 317static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of register set");
313 318
314extern Regs g_regs; 319extern Regs g_regs;
315extern bool g_skip_frame; 320extern bool g_skip_frame;
316 321
317template <typename T> 322template <typename T>
318void Read(T &var, const u32 addr); 323void Read(T& var, const u32 addr);
319 324
320template <typename T> 325template <typename T>
321void Write(u32 addr, const T data); 326void Write(u32 addr, const T data);
@@ -326,5 +331,4 @@ void Init();
326/// Shutdown hardware 331/// Shutdown hardware
327void Shutdown(); 332void Shutdown();
328 333
329
330} // namespace 334} // namespace
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp
index b5fdbf9c1..db224c9aa 100644
--- a/src/core/hw/hw.cpp
+++ b/src/core/hw/hw.cpp
@@ -5,14 +5,14 @@
5#include "common/common_types.h" 5#include "common/common_types.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7 7
8#include "core/hw/hw.h"
9#include "core/hw/gpu.h" 8#include "core/hw/gpu.h"
9#include "core/hw/hw.h"
10#include "core/hw/lcd.h" 10#include "core/hw/lcd.h"
11 11
12namespace HW { 12namespace HW {
13 13
14template <typename T> 14template <typename T>
15inline void Read(T &var, const u32 addr) { 15inline void Read(T& var, const u32 addr) {
16 switch (addr & 0xFFFFF000) { 16 switch (addr & 0xFFFFF000) {
17 case VADDR_GPU: 17 case VADDR_GPU:
18 case VADDR_GPU + 0x1000: 18 case VADDR_GPU + 0x1000:
@@ -71,10 +71,10 @@ inline void Write(u32 addr, const T data) {
71 71
72// Explicitly instantiate template functions because we aren't defining this in the header: 72// Explicitly instantiate template functions because we aren't defining this in the header:
73 73
74template void Read<u64>(u64 &var, const u32 addr); 74template void Read<u64>(u64& var, const u32 addr);
75template void Read<u32>(u32 &var, const u32 addr); 75template void Read<u32>(u32& var, const u32 addr);
76template void Read<u16>(u16 &var, const u32 addr); 76template void Read<u16>(u16& var, const u32 addr);
77template void Read<u8>(u8 &var, const u32 addr); 77template void Read<u8>(u8& var, const u32 addr);
78 78
79template void Write<u64>(u32 addr, const u64 data); 79template void Write<u64>(u32 addr, const u64 data);
80template void Write<u32>(u32 addr, const u32 data); 80template void Write<u32>(u32 addr, const u32 data);
@@ -98,5 +98,4 @@ void Shutdown() {
98 LCD::Shutdown(); 98 LCD::Shutdown();
99 LOG_DEBUG(HW, "shutdown OK"); 99 LOG_DEBUG(HW, "shutdown OK");
100} 100}
101
102} 101}
diff --git a/src/core/hw/hw.h b/src/core/hw/hw.h
index d65608910..a3c5d2ea3 100644
--- a/src/core/hw/hw.h
+++ b/src/core/hw/hw.h
@@ -10,30 +10,30 @@ namespace HW {
10 10
11/// Beginnings of IO register regions, in the user VA space. 11/// Beginnings of IO register regions, in the user VA space.
12enum : u32 { 12enum : u32 {
13 VADDR_HASH = 0x1EC01000, 13 VADDR_HASH = 0x1EC01000,
14 VADDR_CSND = 0x1EC03000, 14 VADDR_CSND = 0x1EC03000,
15 VADDR_DSP = 0x1EC40000, 15 VADDR_DSP = 0x1EC40000,
16 VADDR_PDN = 0x1EC41000, 16 VADDR_PDN = 0x1EC41000,
17 VADDR_CODEC = 0x1EC41000, 17 VADDR_CODEC = 0x1EC41000,
18 VADDR_SPI = 0x1EC42000, 18 VADDR_SPI = 0x1EC42000,
19 VADDR_SPI_2 = 0x1EC43000, // Only used under TWL_FIRM? 19 VADDR_SPI_2 = 0x1EC43000, // Only used under TWL_FIRM?
20 VADDR_I2C = 0x1EC44000, 20 VADDR_I2C = 0x1EC44000,
21 VADDR_CODEC_2 = 0x1EC45000, 21 VADDR_CODEC_2 = 0x1EC45000,
22 VADDR_HID = 0x1EC46000, 22 VADDR_HID = 0x1EC46000,
23 VADDR_GPIO = 0x1EC47000, 23 VADDR_GPIO = 0x1EC47000,
24 VADDR_I2C_2 = 0x1EC48000, 24 VADDR_I2C_2 = 0x1EC48000,
25 VADDR_SPI_3 = 0x1EC60000, 25 VADDR_SPI_3 = 0x1EC60000,
26 VADDR_I2C_3 = 0x1EC61000, 26 VADDR_I2C_3 = 0x1EC61000,
27 VADDR_MIC = 0x1EC62000, 27 VADDR_MIC = 0x1EC62000,
28 VADDR_PXI = 0x1EC63000, 28 VADDR_PXI = 0x1EC63000,
29 VADDR_LCD = 0x1ED02000, 29 VADDR_LCD = 0x1ED02000,
30 VADDR_DSP_2 = 0x1ED03000, 30 VADDR_DSP_2 = 0x1ED03000,
31 VADDR_HASH_2 = 0x1EE01000, 31 VADDR_HASH_2 = 0x1EE01000,
32 VADDR_GPU = 0x1EF00000, 32 VADDR_GPU = 0x1EF00000,
33}; 33};
34 34
35template <typename T> 35template <typename T>
36void Read(T &var, const u32 addr); 36void Read(T& var, const u32 addr);
37 37
38template <typename T> 38template <typename T>
39void Write(u32 addr, const T data); 39void Write(u32 addr, const T data);
diff --git a/src/core/hw/lcd.cpp b/src/core/hw/lcd.cpp
index 6f93709e3..0e3aa7cfd 100644
--- a/src/core/hw/lcd.cpp
+++ b/src/core/hw/lcd.cpp
@@ -18,7 +18,7 @@ namespace LCD {
18Regs g_regs; 18Regs g_regs;
19 19
20template <typename T> 20template <typename T>
21inline void Read(T &var, const u32 raw_addr) { 21inline void Read(T& var, const u32 raw_addr) {
22 u32 addr = raw_addr - HW::VADDR_LCD; 22 u32 addr = raw_addr - HW::VADDR_LCD;
23 u32 index = addr / 4; 23 u32 index = addr / 4;
24 24
@@ -48,16 +48,17 @@ inline void Write(u32 addr, const T data) {
48 // This is happening *after* handling the write to make sure we properly catch all memory reads. 48 // This is happening *after* handling the write to make sure we properly catch all memory reads.
49 if (Pica::g_debug_context && Pica::g_debug_context->recorder) { 49 if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
50 // addr + GPU VBase - IO VBase + IO PBase 50 // addr + GPU VBase - IO VBase + IO PBase
51 Pica::g_debug_context->recorder->RegisterWritten<T>(addr + HW::VADDR_LCD - 0x1EC00000 + 0x10100000, data); 51 Pica::g_debug_context->recorder->RegisterWritten<T>(
52 addr + HW::VADDR_LCD - 0x1EC00000 + 0x10100000, data);
52 } 53 }
53} 54}
54 55
55// Explicitly instantiate template functions because we aren't defining this in the header: 56// Explicitly instantiate template functions because we aren't defining this in the header:
56 57
57template void Read<u64>(u64 &var, const u32 addr); 58template void Read<u64>(u64& var, const u32 addr);
58template void Read<u32>(u32 &var, const u32 addr); 59template void Read<u32>(u32& var, const u32 addr);
59template void Read<u16>(u16 &var, const u32 addr); 60template void Read<u16>(u16& var, const u32 addr);
60template void Read<u8>(u8 &var, const u32 addr); 61template void Read<u8>(u8& var, const u32 addr);
61 62
62template void Write<u64>(u32 addr, const u64 data); 63template void Write<u64>(u32 addr, const u64 data);
63template void Write<u32>(u32 addr, const u32 data); 64template void Write<u32>(u32 addr, const u32 data);
diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h
index 57029c5e8..404833165 100644
--- a/src/core/hw/lcd.h
+++ b/src/core/hw/lcd.h
@@ -42,16 +42,15 @@ struct Regs {
42 return sizeof(Regs) / sizeof(u32); 42 return sizeof(Regs) / sizeof(u32);
43 } 43 }
44 44
45 const u32& operator [] (int index) const { 45 const u32& operator[](int index) const {
46 const u32* content = reinterpret_cast<const u32*>(this); 46 const u32* content = reinterpret_cast<const u32*>(this);
47 return content[index]; 47 return content[index];
48 } 48 }
49 49
50 u32& operator [] (int index) { 50 u32& operator[](int index) {
51 u32* content = reinterpret_cast<u32*>(this); 51 u32* content = reinterpret_cast<u32*>(this);
52 return content[index]; 52 return content[index];
53 } 53 }
54
55}; 54};
56static_assert(std::is_standard_layout<Regs>::value, "Structure does not use standard layout"); 55static_assert(std::is_standard_layout<Regs>::value, "Structure does not use standard layout");
57 56
@@ -59,14 +58,14 @@ static_assert(std::is_standard_layout<Regs>::value, "Structure does not use stan
59// is technically allowed since C++11. This macro should be enabled once MSVC adds 58// is technically allowed since C++11. This macro should be enabled once MSVC adds
60// support for that. 59// support for that.
61#ifndef _MSC_VER 60#ifndef _MSC_VER
62#define ASSERT_REG_POSITION(field_name, position) \ 61#define ASSERT_REG_POSITION(field_name, position) \
63 static_assert(offsetof(Regs, field_name) == position * 4, \ 62 static_assert(offsetof(Regs, field_name) == position * 4, \
64 "Field "#field_name" has invalid position") 63 "Field " #field_name " has invalid position")
65 64
66ASSERT_REG_POSITION(color_fill_top, 0x81); 65ASSERT_REG_POSITION(color_fill_top, 0x81);
67ASSERT_REG_POSITION(backlight_top, 0x90); 66ASSERT_REG_POSITION(backlight_top, 0x90);
68ASSERT_REG_POSITION(color_fill_bottom, 0x281); 67ASSERT_REG_POSITION(color_fill_bottom, 0x281);
69ASSERT_REG_POSITION(backlight_bottom, 0x290); 68ASSERT_REG_POSITION(backlight_bottom, 0x290);
70 69
71#undef ASSERT_REG_POSITION 70#undef ASSERT_REG_POSITION
72#endif // !defined(_MSC_VER) 71#endif // !defined(_MSC_VER)
@@ -74,7 +73,7 @@ ASSERT_REG_POSITION(backlight_bottom, 0x290);
74extern Regs g_regs; 73extern Regs g_regs;
75 74
76template <typename T> 75template <typename T>
77void Read(T &var, const u32 addr); 76void Read(T& var, const u32 addr);
78 77
79template <typename T> 78template <typename T>
80void Write(u32 addr, const T data); 79void Write(u32 addr, const T data);
diff --git a/src/core/hw/y2r.cpp b/src/core/hw/y2r.cpp
index 083391e83..5a68d7e65 100644
--- a/src/core/hw/y2r.cpp
+++ b/src/core/hw/y2r.cpp
@@ -27,9 +27,9 @@ static const size_t TILE_SIZE = 8 * 8;
27using ImageTile = std::array<u32, TILE_SIZE>; 27using ImageTile = std::array<u32, TILE_SIZE>;
28 28
29/// Converts a image strip from the source YUV format into individual 8x8 RGB32 tiles. 29/// Converts a image strip from the source YUV format into individual 8x8 RGB32 tiles.
30static void ConvertYUVToRGB(InputFormat input_format, 30static void ConvertYUVToRGB(InputFormat input_format, const u8* input_Y, const u8* input_U,
31 const u8* input_Y, const u8* input_U, const u8* input_V, ImageTile output[], 31 const u8* input_V, ImageTile output[], unsigned int width,
32 unsigned int width, unsigned int height, const CoefficientSet& coefficients) { 32 unsigned int height, const CoefficientSet& coefficients) {
33 33
34 for (unsigned int y = 0; y < height; ++y) { 34 for (unsigned int y = 0; y < height; ++y) {
35 for (unsigned int x = 0; x < width; ++x) { 35 for (unsigned int x = 0; x < width; ++x) {
@@ -58,11 +58,11 @@ static void ConvertYUVToRGB(InputFormat input_format,
58 58
59 // This conversion process is bit-exact with hardware, as far as could be tested. 59 // This conversion process is bit-exact with hardware, as far as could be tested.
60 auto& c = coefficients; 60 auto& c = coefficients;
61 s32 cY = c[0]*Y; 61 s32 cY = c[0] * Y;
62 62
63 s32 r = cY + c[1]*V; 63 s32 r = cY + c[1] * V;
64 s32 g = cY - c[3]*U - c[2]*V; 64 s32 g = cY - c[3] * U - c[2] * V;
65 s32 b = cY + c[4]*U; 65 s32 b = cY + c[4] * U;
66 66
67 const s32 rounding_offset = 0x18; 67 const s32 rounding_offset = 0x18;
68 r = (r >> 3) + c[5] + rounding_offset; 68 r = (r >> 3) + c[5] + rounding_offset;
@@ -74,14 +74,14 @@ static void ConvertYUVToRGB(InputFormat input_format,
74 u32* out = &output[tile][y * 8 + tile_x]; 74 u32* out = &output[tile][y * 8 + tile_x];
75 75
76 using MathUtil::Clamp; 76 using MathUtil::Clamp;
77 *out = ((u32)Clamp(r >> 5, 0, 0xFF) << 24) | 77 *out = ((u32)Clamp(r >> 5, 0, 0xFF) << 24) | ((u32)Clamp(g >> 5, 0, 0xFF) << 16) |
78 ((u32)Clamp(g >> 5, 0, 0xFF) << 16) |
79 ((u32)Clamp(b >> 5, 0, 0xFF) << 8); 78 ((u32)Clamp(b >> 5, 0, 0xFF) << 8);
80 } 79 }
81 } 80 }
82} 81}
83 82
84/// Simulates an incoming CDMA transfer. The N parameter is used to automatically convert 16-bit formats to 8-bit. 83/// Simulates an incoming CDMA transfer. The N parameter is used to automatically convert 16-bit
84/// formats to 8-bit.
85template <size_t N> 85template <size_t N>
86static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data) { 86static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data) {
87 const u8* input = Memory::GetPointer(buf.address); 87 const u8* input = Memory::GetPointer(buf.address);
@@ -103,9 +103,10 @@ static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data
103 } 103 }
104} 104}
105 105
106/// Convert intermediate RGB32 format to the final output format while simulating an outgoing CDMA transfer. 106/// Convert intermediate RGB32 format to the final output format while simulating an outgoing CDMA
107/// transfer.
107static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data, 108static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data,
108 OutputFormat output_format, u8 alpha) { 109 OutputFormat output_format, u8 alpha) {
109 110
110 u8* output = Memory::GetPointer(buf.address); 111 u8* output = Memory::GetPointer(buf.address);
111 112
@@ -113,9 +114,7 @@ static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data
113 u8* unit_end = output + buf.transfer_unit; 114 u8* unit_end = output + buf.transfer_unit;
114 while (output < unit_end) { 115 while (output < unit_end) {
115 u32 color = *input++; 116 u32 color = *input++;
116 Math::Vec4<u8> col_vec{ 117 Math::Vec4<u8> col_vec{(u8)(color >> 24), (u8)(color >> 16), (u8)(color >> 8), alpha};
117 (u8)(color >> 24), (u8)(color >> 16), (u8)(color >> 8), alpha
118 };
119 118
120 switch (output_format) { 119 switch (output_format) {
121 case OutputFormat::RGBA8: 120 case OutputFormat::RGBA8:
@@ -146,34 +145,26 @@ static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data
146} 145}
147 146
148static const u8 linear_lut[64] = { 147static const u8 linear_lut[64] = {
149 0, 1, 2, 3, 4, 5, 6, 7, 148 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
150 8, 9, 10, 11, 12, 13, 14, 15, 149 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
151 16, 17, 18, 19, 20, 21, 22, 23, 150 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
152 24, 25, 26, 27, 28, 29, 30, 31,
153 32, 33, 34, 35, 36, 37, 38, 39,
154 40, 41, 42, 43, 44, 45, 46, 47,
155 48, 49, 50, 51, 52, 53, 54, 55,
156 56, 57, 58, 59, 60, 61, 62, 63,
157}; 151};
158 152
159static const u8 morton_lut[64] = { 153static const u8 morton_lut[64] = {
160 0, 1, 4, 5, 16, 17, 20, 21, 154 0, 1, 4, 5, 16, 17, 20, 21, 2, 3, 6, 7, 18, 19, 22, 23, 8, 9, 12, 13, 24, 25,
161 2, 3, 6, 7, 18, 19, 22, 23, 155 28, 29, 10, 11, 14, 15, 26, 27, 30, 31, 32, 33, 36, 37, 48, 49, 52, 53, 34, 35, 38, 39,
162 8, 9, 12, 13, 24, 25, 28, 29, 156 50, 51, 54, 55, 40, 41, 44, 45, 56, 57, 60, 61, 42, 43, 46, 47, 58, 59, 62, 63,
163 10, 11, 14, 15, 26, 27, 30, 31,
164 32, 33, 36, 37, 48, 49, 52, 53,
165 34, 35, 38, 39, 50, 51, 54, 55,
166 40, 41, 44, 45, 56, 57, 60, 61,
167 42, 43, 46, 47, 58, 59, 62, 63,
168}; 157};
169 158
170static void RotateTile0(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { 159static void RotateTile0(const ImageTile& input, ImageTile& output, int height,
160 const u8 out_map[64]) {
171 for (int i = 0; i < height * 8; ++i) { 161 for (int i = 0; i < height * 8; ++i) {
172 output[out_map[i]] = input[i]; 162 output[out_map[i]] = input[i];
173 } 163 }
174} 164}
175 165
176static void RotateTile90(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { 166static void RotateTile90(const ImageTile& input, ImageTile& output, int height,
167 const u8 out_map[64]) {
177 int out_i = 0; 168 int out_i = 0;
178 for (int x = 0; x < 8; ++x) { 169 for (int x = 0; x < 8; ++x) {
179 for (int y = height - 1; y >= 0; --y) { 170 for (int y = height - 1; y >= 0; --y) {
@@ -182,16 +173,18 @@ static void RotateTile90(const ImageTile& input, ImageTile& output, int height,
182 } 173 }
183} 174}
184 175
185static void RotateTile180(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { 176static void RotateTile180(const ImageTile& input, ImageTile& output, int height,
177 const u8 out_map[64]) {
186 int out_i = 0; 178 int out_i = 0;
187 for (int i = height * 8 - 1; i >= 0; --i) { 179 for (int i = height * 8 - 1; i >= 0; --i) {
188 output[out_map[out_i++]] = input[i]; 180 output[out_map[out_i++]] = input[i];
189 } 181 }
190} 182}
191 183
192static void RotateTile270(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { 184static void RotateTile270(const ImageTile& input, ImageTile& output, int height,
185 const u8 out_map[64]) {
193 int out_i = 0; 186 int out_i = 0;
194 for (int x = 8-1; x >= 0; --x) { 187 for (int x = 8 - 1; x >= 0; --x) {
195 for (int y = 0; y < height; ++y) { 188 for (int y = 0; y < height; ++y) {
196 output[out_map[out_i++]] = input[y * 8 + x]; 189 output[out_map[out_i++]] = input[y * 8 + x];
197 } 190 }
@@ -274,9 +267,11 @@ void PerformConversion(ConversionConfiguration& cvt) {
274 const u8* tile_remap = nullptr; 267 const u8* tile_remap = nullptr;
275 switch (cvt.block_alignment) { 268 switch (cvt.block_alignment) {
276 case BlockAlignment::Linear: 269 case BlockAlignment::Linear:
277 tile_remap = linear_lut; break; 270 tile_remap = linear_lut;
271 break;
278 case BlockAlignment::Block8x8: 272 case BlockAlignment::Block8x8:
279 tile_remap = morton_lut; break; 273 tile_remap = morton_lut;
274 break;
280 } 275 }
281 276
282 for (unsigned int y = 0; y < cvt.input_lines; y += 8) { 277 for (unsigned int y = 0; y < cvt.input_lines; y += 8) {
@@ -320,7 +315,7 @@ void PerformConversion(ConversionConfiguration& cvt) {
320 // Note(yuriks): If additional optimization is required, input_format can be moved to a 315 // Note(yuriks): If additional optimization is required, input_format can be moved to a
321 // template parameter, so that its dispatch can be moved to outside the inner loop. 316 // template parameter, so that its dispatch can be moved to outside the inner loop.
322 ConvertYUVToRGB(cvt.input_format, input_Y, input_U, input_V, tiles.get(), 317 ConvertYUVToRGB(cvt.input_format, input_Y, input_U, input_V, tiles.get(),
323 cvt.input_line_width, row_height, cvt.coefficients); 318 cvt.input_line_width, row_height, cvt.coefficients);
324 319
325 u32* output_buffer = reinterpret_cast<u32*>(data_buffer.get()); 320 u32* output_buffer = reinterpret_cast<u32*>(data_buffer.get());
326 321
@@ -367,9 +362,9 @@ void PerformConversion(ConversionConfiguration& cvt) {
367 362
368 // Note(yuriks): If additional optimization is required, output_format can be moved to a 363 // Note(yuriks): If additional optimization is required, output_format can be moved to a
369 // template parameter, so that its dispatch can be moved to outside the inner loop. 364 // template parameter, so that its dispatch can be moved to outside the inner loop.
370 SendData(reinterpret_cast<u32*>(data_buffer.get()), cvt.dst, (int)row_data_size, cvt.output_format, (u8)cvt.alpha); 365 SendData(reinterpret_cast<u32*>(data_buffer.get()), cvt.dst, (int)row_data_size,
366 cvt.output_format, (u8)cvt.alpha);
371 } 367 }
372} 368}
373
374} 369}
375} 370}
diff --git a/src/core/hw/y2r.h b/src/core/hw/y2r.h
index 729e1eee3..6b6e71bec 100644
--- a/src/core/hw/y2r.h
+++ b/src/core/hw/y2r.h
@@ -3,13 +3,12 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5namespace Y2R_U { 5namespace Y2R_U {
6 struct ConversionConfiguration; 6struct ConversionConfiguration;
7} 7}
8 8
9namespace HW { 9namespace HW {
10namespace Y2R { 10namespace Y2R {
11 11
12void PerformConversion(Y2R_U::ConversionConfiguration& cvt); 12void PerformConversion(Y2R_U::ConversionConfiguration& cvt);
13
14} 13}
15} 14}
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index a16411e14..c2e87f592 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -37,20 +37,14 @@ namespace Loader {
37 * The BSS section must be cleared manually by the application. 37 * The BSS section must be cleared manually by the application.
38 */ 38 */
39 39
40enum THREEDSX_Error { 40enum THREEDSX_Error { ERROR_NONE = 0, ERROR_READ = 1, ERROR_FILE = 2, ERROR_ALLOC = 3 };
41 ERROR_NONE = 0,
42 ERROR_READ = 1,
43 ERROR_FILE = 2,
44 ERROR_ALLOC = 3
45};
46 41
47static const u32 RELOCBUFSIZE = 512; 42static const u32 RELOCBUFSIZE = 512;
48static const unsigned int NUM_SEGMENTS = 3; 43static const unsigned int NUM_SEGMENTS = 3;
49 44
50// File header 45// File header
51#pragma pack(1) 46#pragma pack(1)
52struct THREEDSX_Header 47struct THREEDSX_Header {
53{
54 u32 magic; 48 u32 magic;
55 u16 header_size, reloc_hdr_size; 49 u16 header_size, reloc_hdr_size;
56 u32 format_ver; 50 u32 format_ver;
@@ -66,11 +60,11 @@ struct THREEDSX_Header
66}; 60};
67 61
68// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts. 62// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts.
69struct THREEDSX_RelocHdr 63struct THREEDSX_RelocHdr {
70{
71 // # of absolute relocations (that is, fix address to post-relocation memory layout) 64 // # of absolute relocations (that is, fix address to post-relocation memory layout)
72 u32 cross_segment_absolute; 65 u32 cross_segment_absolute;
73 // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be patched) 66 // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be
67 // patched)
74 u32 cross_segment_relative; 68 u32 cross_segment_relative;
75 // more? 69 // more?
76 70
@@ -80,21 +74,18 @@ struct THREEDSX_RelocHdr
80}; 74};
81 75
82// Relocation entry: from the current pointer, skip X words and patch Y words 76// Relocation entry: from the current pointer, skip X words and patch Y words
83struct THREEDSX_Reloc 77struct THREEDSX_Reloc {
84{
85 u16 skip, patch; 78 u16 skip, patch;
86}; 79};
87#pragma pack() 80#pragma pack()
88 81
89struct THREEloadinfo 82struct THREEloadinfo {
90{
91 u8* seg_ptrs[3]; // code, rodata & data 83 u8* seg_ptrs[3]; // code, rodata & data
92 u32 seg_addrs[3]; 84 u32 seg_addrs[3];
93 u32 seg_sizes[3]; 85 u32 seg_sizes[3];
94}; 86};
95 87
96static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets) 88static u32 TranslateAddr(u32 addr, const THREEloadinfo* loadinfo, u32* offsets) {
97{
98 if (addr < offsets[0]) 89 if (addr < offsets[0])
99 return loadinfo->seg_addrs[0] + addr; 90 return loadinfo->seg_addrs[0] + addr;
100 if (addr < offsets[1]) 91 if (addr < offsets[1])
@@ -105,8 +96,8 @@ static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets)
105using Kernel::SharedPtr; 96using Kernel::SharedPtr;
106using Kernel::CodeSet; 97using Kernel::CodeSet;
107 98
108static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, SharedPtr<CodeSet>* out_codeset) 99static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
109{ 100 SharedPtr<CodeSet>* out_codeset) {
110 if (!file.IsOpen()) 101 if (!file.IsOpen())
111 return ERROR_FILE; 102 return ERROR_FILE;
112 103
@@ -118,13 +109,14 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
118 return ERROR_READ; 109 return ERROR_READ;
119 110
120 THREEloadinfo loadinfo; 111 THREEloadinfo loadinfo;
121 //loadinfo segments must be a multiple of 0x1000 112 // loadinfo segments must be a multiple of 0x1000
122 loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) &~0xFFF; 113 loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) & ~0xFFF;
123 loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF; 114 loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) & ~0xFFF;
124 loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF; 115 loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) & ~0xFFF;
125 u32 offsets[2] = { loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] }; 116 u32 offsets[2] = {loadinfo.seg_sizes[0], loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1]};
126 u32 n_reloc_tables = hdr.reloc_hdr_size / sizeof(u32); 117 u32 n_reloc_tables = hdr.reloc_hdr_size / sizeof(u32);
127 std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] + loadinfo.seg_sizes[2]); 118 std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] +
119 loadinfo.seg_sizes[2]);
128 120
129 loadinfo.seg_addrs[0] = base_addr; 121 loadinfo.seg_addrs[0] = base_addr;
130 loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0]; 122 loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0];
@@ -149,7 +141,8 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
149 return ERROR_READ; 141 return ERROR_READ;
150 if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size) 142 if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size)
151 return ERROR_READ; 143 return ERROR_READ;
152 if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) != hdr.data_seg_size - hdr.bss_size) 144 if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) !=
145 hdr.data_seg_size - hdr.bss_size)
153 return ERROR_READ; 146 return ERROR_READ;
154 147
155 // BSS clear 148 // BSS clear
@@ -157,11 +150,12 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
157 150
158 // Relocate the segments 151 // Relocate the segments
159 for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) { 152 for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) {
160 for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables; current_segment_reloc_table++) { 153 for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables;
154 current_segment_reloc_table++) {
161 u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; 155 u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table];
162 if (current_segment_reloc_table >= 2) { 156 if (current_segment_reloc_table >= 2) {
163 // We are not using this table - ignore it because we don't know what it dose 157 // We are not using this table - ignore it because we don't know what it dose
164 file.Seek(n_relocs*sizeof(THREEDSX_Reloc), SEEK_CUR); 158 file.Seek(n_relocs * sizeof(THREEDSX_Reloc), SEEK_CUR);
165 continue; 159 continue;
166 } 160 }
167 THREEDSX_Reloc reloc_table[RELOCBUFSIZE]; 161 THREEDSX_Reloc reloc_table[RELOCBUFSIZE];
@@ -173,17 +167,20 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
173 u32 remaining = std::min(RELOCBUFSIZE, n_relocs); 167 u32 remaining = std::min(RELOCBUFSIZE, n_relocs);
174 n_relocs -= remaining; 168 n_relocs -= remaining;
175 169
176 if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) != remaining * sizeof(THREEDSX_Reloc)) 170 if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) !=
171 remaining * sizeof(THREEDSX_Reloc))
177 return ERROR_READ; 172 return ERROR_READ;
178 173
179 for (unsigned current_inprogress = 0; current_inprogress < remaining && pos < end_pos; current_inprogress++) { 174 for (unsigned current_inprogress = 0;
175 current_inprogress < remaining && pos < end_pos; current_inprogress++) {
180 const auto& table = reloc_table[current_inprogress]; 176 const auto& table = reloc_table[current_inprogress];
181 LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)", current_segment_reloc_table, 177 LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)", current_segment_reloc_table,
182 static_cast<u32>(table.skip), static_cast<u32>(table.patch)); 178 static_cast<u32>(table.skip), static_cast<u32>(table.patch));
183 pos += table.skip; 179 pos += table.skip;
184 s32 num_patches = table.patch; 180 s32 num_patches = table.patch;
185 while (0 < num_patches && pos < end_pos) { 181 while (0 < num_patches && pos < end_pos) {
186 u32 in_addr = static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data()); 182 u32 in_addr =
183 static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data());
187 u32 addr = TranslateAddr(*pos, &loadinfo, offsets); 184 u32 addr = TranslateAddr(*pos, &loadinfo, offsets);
188 LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)", 185 LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)",
189 base_addr + in_addr, addr, current_segment_reloc_table, *pos); 186 base_addr + in_addr, addr, current_segment_reloc_table, *pos);
@@ -195,7 +192,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
195 *pos = static_cast<u32>(addr - in_addr); 192 *pos = static_cast<u32>(addr - in_addr);
196 break; 193 break;
197 default: 194 default:
198 break; //this should never happen 195 break; // this should never happen
199 } 196 }
200 pos++; 197 pos++;
201 num_patches--; 198 num_patches--;
@@ -209,23 +206,24 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
209 SharedPtr<CodeSet> code_set = CodeSet::Create("", 0); 206 SharedPtr<CodeSet> code_set = CodeSet::Create("", 0);
210 207
211 code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data(); 208 code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data();
212 code_set->code.addr = loadinfo.seg_addrs[0]; 209 code_set->code.addr = loadinfo.seg_addrs[0];
213 code_set->code.size = loadinfo.seg_sizes[0]; 210 code_set->code.size = loadinfo.seg_sizes[0];
214 211
215 code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data(); 212 code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data();
216 code_set->rodata.addr = loadinfo.seg_addrs[1]; 213 code_set->rodata.addr = loadinfo.seg_addrs[1];
217 code_set->rodata.size = loadinfo.seg_sizes[1]; 214 code_set->rodata.size = loadinfo.seg_sizes[1];
218 215
219 code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data(); 216 code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data();
220 code_set->data.addr = loadinfo.seg_addrs[2]; 217 code_set->data.addr = loadinfo.seg_addrs[2];
221 code_set->data.size = loadinfo.seg_sizes[2]; 218 code_set->data.size = loadinfo.seg_sizes[2];
222 219
223 code_set->entrypoint = code_set->code.addr; 220 code_set->entrypoint = code_set->code.addr;
224 code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); 221 code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
225 222
226 LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]); 223 LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]);
227 LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]); 224 LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]);
228 LOG_DEBUG(Loader, "data size: 0x%X (including 0x%X of bss)", loadinfo.seg_sizes[2], hdr.bss_size); 225 LOG_DEBUG(Loader, "data size: 0x%X (including 0x%X of bss)", loadinfo.seg_sizes[2],
226 hdr.bss_size);
229 227
230 *out_codeset = code_set; 228 *out_codeset = code_set;
231 return ERROR_NONE; 229 return ERROR_NONE;
@@ -260,17 +258,20 @@ ResultStatus AppLoader_THREEDSX::Load() {
260 Kernel::g_current_process->address_mappings = default_address_mappings; 258 Kernel::g_current_process->address_mappings = default_address_mappings;
261 259
262 // Attach the default resource limit (APPLICATION) to the process 260 // Attach the default resource limit (APPLICATION) to the process
263 Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); 261 Kernel::g_current_process->resource_limit =
262 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
264 263
265 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); 264 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
266 265
267 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), Service::FS::ArchiveIdCode::RomFS); 266 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this),
267 Service::FS::ArchiveIdCode::RomFS);
268 268
269 is_loaded = true; 269 is_loaded = true;
270 return ResultStatus::Success; 270 return ResultStatus::Success;
271} 271}
272 272
273ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { 273ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file,
274 u64& offset, u64& size) {
274 if (!file.IsOpen()) 275 if (!file.IsOpen())
275 return ResultStatus::Error; 276 return ResultStatus::Error;
276 277
diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h
index 90b20c61c..09a788a1c 100644
--- a/src/core/loader/3dsx.h
+++ b/src/core/loader/3dsx.h
@@ -17,8 +17,10 @@ namespace Loader {
17/// Loads an 3DSX file 17/// Loads an 3DSX file
18class AppLoader_THREEDSX final : public AppLoader { 18class AppLoader_THREEDSX final : public AppLoader {
19public: 19public:
20 AppLoader_THREEDSX(FileUtil::IOFile&& file, const std::string& filename, const std::string& filepath) 20 AppLoader_THREEDSX(FileUtil::IOFile&& file, const std::string& filename,
21 : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {} 21 const std::string& filepath)
22 : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {
23 }
22 24
23 /** 25 /**
24 * Returns the type of the file 26 * Returns the type of the file
@@ -55,7 +57,8 @@ public:
55 * @param size Size of the RomFS in bytes 57 * @param size Size of the RomFS in bytes
56 * @return ResultStatus result of function 58 * @return ResultStatus result of function
57 */ 59 */
58 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) override; 60 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
61 u64& size) override;
59 62
60private: 63private:
61 std::string filename; 64 std::string filename;
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 69df94324..53c10a456 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -3,8 +3,8 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring> 5#include <cstring>
6#include <string>
7#include <memory> 6#include <memory>
7#include <string>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/file_util.h" 10#include "common/file_util.h"
@@ -24,112 +24,111 @@ using Kernel::CodeSet;
24 24
25// File type 25// File type
26enum ElfType { 26enum ElfType {
27 ET_NONE = 0, 27 ET_NONE = 0,
28 ET_REL = 1, 28 ET_REL = 1,
29 ET_EXEC = 2, 29 ET_EXEC = 2,
30 ET_DYN = 3, 30 ET_DYN = 3,
31 ET_CORE = 4, 31 ET_CORE = 4,
32 ET_LOPROC = 0xFF00, 32 ET_LOPROC = 0xFF00,
33 ET_HIPROC = 0xFFFF, 33 ET_HIPROC = 0xFFFF,
34}; 34};
35 35
36// Machine/Architecture 36// Machine/Architecture
37enum ElfMachine { 37enum ElfMachine {
38 EM_NONE = 0, 38 EM_NONE = 0,
39 EM_M32 = 1, 39 EM_M32 = 1,
40 EM_SPARC = 2, 40 EM_SPARC = 2,
41 EM_386 = 3, 41 EM_386 = 3,
42 EM_68K = 4, 42 EM_68K = 4,
43 EM_88K = 5, 43 EM_88K = 5,
44 EM_860 = 7, 44 EM_860 = 7,
45 EM_MIPS = 8 45 EM_MIPS = 8
46}; 46};
47 47
48// File version 48// File version
49#define EV_NONE 0 49#define EV_NONE 0
50#define EV_CURRENT 1 50#define EV_CURRENT 1
51 51
52// Identification index 52// Identification index
53#define EI_MAG0 0 53#define EI_MAG0 0
54#define EI_MAG1 1 54#define EI_MAG1 1
55#define EI_MAG2 2 55#define EI_MAG2 2
56#define EI_MAG3 3 56#define EI_MAG3 3
57#define EI_CLASS 4 57#define EI_CLASS 4
58#define EI_DATA 5 58#define EI_DATA 5
59#define EI_VERSION 6 59#define EI_VERSION 6
60#define EI_PAD 7 60#define EI_PAD 7
61#define EI_NIDENT 16 61#define EI_NIDENT 16
62 62
63// Sections constants 63// Sections constants
64 64
65// Section types 65// Section types
66#define SHT_NULL 0 66#define SHT_NULL 0
67#define SHT_PROGBITS 1 67#define SHT_PROGBITS 1
68#define SHT_SYMTAB 2 68#define SHT_SYMTAB 2
69#define SHT_STRTAB 3 69#define SHT_STRTAB 3
70#define SHT_RELA 4 70#define SHT_RELA 4
71#define SHT_HASH 5 71#define SHT_HASH 5
72#define SHT_DYNAMIC 6 72#define SHT_DYNAMIC 6
73#define SHT_NOTE 7 73#define SHT_NOTE 7
74#define SHT_NOBITS 8 74#define SHT_NOBITS 8
75#define SHT_REL 9 75#define SHT_REL 9
76#define SHT_SHLIB 10 76#define SHT_SHLIB 10
77#define SHT_DYNSYM 11 77#define SHT_DYNSYM 11
78#define SHT_LOPROC 0x70000000 78#define SHT_LOPROC 0x70000000
79#define SHT_HIPROC 0x7FFFFFFF 79#define SHT_HIPROC 0x7FFFFFFF
80#define SHT_LOUSER 0x80000000 80#define SHT_LOUSER 0x80000000
81#define SHT_HIUSER 0xFFFFFFFF 81#define SHT_HIUSER 0xFFFFFFFF
82 82
83// Section flags 83// Section flags
84enum ElfSectionFlags 84enum ElfSectionFlags {
85{ 85 SHF_WRITE = 0x1,
86 SHF_WRITE = 0x1, 86 SHF_ALLOC = 0x2,
87 SHF_ALLOC = 0x2,
88 SHF_EXECINSTR = 0x4, 87 SHF_EXECINSTR = 0x4,
89 SHF_MASKPROC = 0xF0000000, 88 SHF_MASKPROC = 0xF0000000,
90}; 89};
91 90
92// Segment types 91// Segment types
93#define PT_NULL 0 92#define PT_NULL 0
94#define PT_LOAD 1 93#define PT_LOAD 1
95#define PT_DYNAMIC 2 94#define PT_DYNAMIC 2
96#define PT_INTERP 3 95#define PT_INTERP 3
97#define PT_NOTE 4 96#define PT_NOTE 4
98#define PT_SHLIB 5 97#define PT_SHLIB 5
99#define PT_PHDR 6 98#define PT_PHDR 6
100#define PT_LOPROC 0x70000000 99#define PT_LOPROC 0x70000000
101#define PT_HIPROC 0x7FFFFFFF 100#define PT_HIPROC 0x7FFFFFFF
102 101
103// Segment flags 102// Segment flags
104#define PF_X 0x1 103#define PF_X 0x1
105#define PF_W 0x2 104#define PF_W 0x2
106#define PF_R 0x4 105#define PF_R 0x4
107#define PF_MASKPROC 0xF0000000 106#define PF_MASKPROC 0xF0000000
108 107
109typedef unsigned int Elf32_Addr; 108typedef unsigned int Elf32_Addr;
110typedef unsigned short Elf32_Half; 109typedef unsigned short Elf32_Half;
111typedef unsigned int Elf32_Off; 110typedef unsigned int Elf32_Off;
112typedef signed int Elf32_Sword; 111typedef signed int Elf32_Sword;
113typedef unsigned int Elf32_Word; 112typedef unsigned int Elf32_Word;
114 113
115//////////////////////////////////////////////////////////////////////////////////////////////////// 114////////////////////////////////////////////////////////////////////////////////////////////////////
116// ELF file header 115// ELF file header
117 116
118struct Elf32_Ehdr { 117struct Elf32_Ehdr {
119 unsigned char e_ident[EI_NIDENT]; 118 unsigned char e_ident[EI_NIDENT];
120 Elf32_Half e_type; 119 Elf32_Half e_type;
121 Elf32_Half e_machine; 120 Elf32_Half e_machine;
122 Elf32_Word e_version; 121 Elf32_Word e_version;
123 Elf32_Addr e_entry; 122 Elf32_Addr e_entry;
124 Elf32_Off e_phoff; 123 Elf32_Off e_phoff;
125 Elf32_Off e_shoff; 124 Elf32_Off e_shoff;
126 Elf32_Word e_flags; 125 Elf32_Word e_flags;
127 Elf32_Half e_ehsize; 126 Elf32_Half e_ehsize;
128 Elf32_Half e_phentsize; 127 Elf32_Half e_phentsize;
129 Elf32_Half e_phnum; 128 Elf32_Half e_phnum;
130 Elf32_Half e_shentsize; 129 Elf32_Half e_shentsize;
131 Elf32_Half e_shnum; 130 Elf32_Half e_shnum;
132 Elf32_Half e_shstrndx; 131 Elf32_Half e_shstrndx;
133}; 132};
134 133
135// Section header 134// Section header
@@ -138,7 +137,7 @@ struct Elf32_Shdr {
138 Elf32_Word sh_type; 137 Elf32_Word sh_type;
139 Elf32_Word sh_flags; 138 Elf32_Word sh_flags;
140 Elf32_Addr sh_addr; 139 Elf32_Addr sh_addr;
141 Elf32_Off sh_offset; 140 Elf32_Off sh_offset;
142 Elf32_Word sh_size; 141 Elf32_Word sh_size;
143 Elf32_Word sh_link; 142 Elf32_Word sh_link;
144 Elf32_Word sh_info; 143 Elf32_Word sh_info;
@@ -149,7 +148,7 @@ struct Elf32_Shdr {
149// Segment header 148// Segment header
150struct Elf32_Phdr { 149struct Elf32_Phdr {
151 Elf32_Word p_type; 150 Elf32_Word p_type;
152 Elf32_Off p_offset; 151 Elf32_Off p_offset;
153 Elf32_Addr p_vaddr; 152 Elf32_Addr p_vaddr;
154 Elf32_Addr p_paddr; 153 Elf32_Addr p_paddr;
155 Elf32_Word p_filesz; 154 Elf32_Word p_filesz;
@@ -160,12 +159,12 @@ struct Elf32_Phdr {
160 159
161// Symbol table entry 160// Symbol table entry
162struct Elf32_Sym { 161struct Elf32_Sym {
163 Elf32_Word st_name; 162 Elf32_Word st_name;
164 Elf32_Addr st_value; 163 Elf32_Addr st_value;
165 Elf32_Word st_size; 164 Elf32_Word st_size;
166 unsigned char st_info; 165 unsigned char st_info;
167 unsigned char st_other; 166 unsigned char st_other;
168 Elf32_Half st_shndx; 167 Elf32_Half st_shndx;
169}; 168};
170 169
171// Relocation entries 170// Relocation entries
@@ -181,35 +180,51 @@ typedef int SectionID;
181 180
182class ElfReader { 181class ElfReader {
183private: 182private:
184 char *base; 183 char* base;
185 u32 *base32; 184 u32* base32;
186 185
187 Elf32_Ehdr *header; 186 Elf32_Ehdr* header;
188 Elf32_Phdr *segments; 187 Elf32_Phdr* segments;
189 Elf32_Shdr *sections; 188 Elf32_Shdr* sections;
190 189
191 u32 *sectionAddrs; 190 u32* sectionAddrs;
192 bool relocate; 191 bool relocate;
193 u32 entryPoint; 192 u32 entryPoint;
194 193
195public: 194public:
196 ElfReader(void *ptr); 195 ElfReader(void* ptr);
197 196
198 u32 Read32(int off) const { return base32[off >> 2]; } 197 u32 Read32(int off) const {
198 return base32[off >> 2];
199 }
199 200
200 // Quick accessors 201 // Quick accessors
201 ElfType GetType() const { return (ElfType)(header->e_type); } 202 ElfType GetType() const {
202 ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); } 203 return (ElfType)(header->e_type);
203 u32 GetEntryPoint() const { return entryPoint; } 204 }
204 u32 GetFlags() const { return (u32)(header->e_flags); } 205 ElfMachine GetMachine() const {
206 return (ElfMachine)(header->e_machine);
207 }
208 u32 GetEntryPoint() const {
209 return entryPoint;
210 }
211 u32 GetFlags() const {
212 return (u32)(header->e_flags);
213 }
205 SharedPtr<CodeSet> LoadInto(u32 vaddr); 214 SharedPtr<CodeSet> LoadInto(u32 vaddr);
206 bool LoadSymbols(); 215 bool LoadSymbols();
207 216
208 int GetNumSegments() const { return (int)(header->e_phnum); } 217 int GetNumSegments() const {
209 int GetNumSections() const { return (int)(header->e_shnum); } 218 return (int)(header->e_phnum);
210 const u8 *GetPtr(int offset) const { return (u8*)base + offset; } 219 }
211 const char *GetSectionName(int section) const; 220 int GetNumSections() const {
212 const u8 *GetSectionDataPtr(int section) const { 221 return (int)(header->e_shnum);
222 }
223 const u8* GetPtr(int offset) const {
224 return (u8*)base + offset;
225 }
226 const char* GetSectionName(int section) const;
227 const u8* GetSectionDataPtr(int section) const {
213 if (section < 0 || section >= header->e_shnum) 228 if (section < 0 || section >= header->e_shnum)
214 return nullptr; 229 return nullptr;
215 if (sections[section].sh_type != SHT_NOBITS) 230 if (sections[section].sh_type != SHT_NOBITS)
@@ -220,19 +235,23 @@ public:
220 bool IsCodeSection(int section) const { 235 bool IsCodeSection(int section) const {
221 return sections[section].sh_type == SHT_PROGBITS; 236 return sections[section].sh_type == SHT_PROGBITS;
222 } 237 }
223 const u8 *GetSegmentPtr(int segment) { 238 const u8* GetSegmentPtr(int segment) {
224 return GetPtr(segments[segment].p_offset); 239 return GetPtr(segments[segment].p_offset);
225 } 240 }
226 u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; } 241 u32 GetSectionAddr(SectionID section) const {
227 unsigned int GetSectionSize(SectionID section) const { return sections[section].sh_size; } 242 return sectionAddrs[section];
228 SectionID GetSectionByName(const char *name, int firstSection = 0) const; //-1 for not found 243 }
244 unsigned int GetSectionSize(SectionID section) const {
245 return sections[section].sh_size;
246 }
247 SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found
229 248
230 bool DidRelocate() const { 249 bool DidRelocate() const {
231 return relocate; 250 return relocate;
232 } 251 }
233}; 252};
234 253
235ElfReader::ElfReader(void *ptr) { 254ElfReader::ElfReader(void* ptr) {
236 base = (char*)ptr; 255 base = (char*)ptr;
237 base32 = (u32*)ptr; 256 base32 = (u32*)ptr;
238 header = (Elf32_Ehdr*)ptr; 257 header = (Elf32_Ehdr*)ptr;
@@ -245,7 +264,7 @@ ElfReader::ElfReader(void *ptr) {
245 LoadSymbols(); 264 LoadSymbols();
246} 265}
247 266
248const char *ElfReader::GetSectionName(int section) const { 267const char* ElfReader::GetSectionName(int section) const {
249 if (sections[section].sh_type == SHT_NULL) 268 if (sections[section].sh_type == SHT_NULL)
250 return nullptr; 269 return nullptr;
251 270
@@ -303,12 +322,15 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
303 } else if (permission_flags == (PF_R | PF_W)) { 322 } else if (permission_flags == (PF_R | PF_W)) {
304 codeset_segment = &codeset->data; 323 codeset_segment = &codeset->data;
305 } else { 324 } else {
306 LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i, p->p_flags); 325 LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i,
326 p->p_flags);
307 continue; 327 continue;
308 } 328 }
309 329
310 if (codeset_segment->size != 0) { 330 if (codeset_segment->size != 0) {
311 LOG_ERROR(Loader, "ELF has more than one segment of the same type. Skipping extra segment (id %i)", i); 331 LOG_ERROR(Loader, "ELF has more than one segment of the same type. Skipping extra "
332 "segment (id %i)",
333 i);
312 continue; 334 continue;
313 } 335 }
314 336
@@ -332,9 +354,9 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
332 return codeset; 354 return codeset;
333} 355}
334 356
335SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const { 357SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const {
336 for (int i = firstSection; i < header->e_shnum; i++) { 358 for (int i = firstSection; i < header->e_shnum; i++) {
337 const char *secname = GetSectionName(i); 359 const char* secname = GetSectionName(i);
338 360
339 if (secname != nullptr && strcmp(name, secname) == 0) 361 if (secname != nullptr && strcmp(name, secname) == 0)
340 return i; 362 return i;
@@ -347,9 +369,9 @@ bool ElfReader::LoadSymbols() {
347 SectionID sec = GetSectionByName(".symtab"); 369 SectionID sec = GetSectionByName(".symtab");
348 if (sec != -1) { 370 if (sec != -1) {
349 int stringSection = sections[sec].sh_link; 371 int stringSection = sections[sec].sh_link;
350 const char *stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection)); 372 const char* stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection));
351 373
352 //We have a symbol table! 374 // We have a symbol table!
353 const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec)); 375 const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec));
354 unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); 376 unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
355 for (unsigned sym = 0; sym < numSymbols; sym++) { 377 for (unsigned sym = 0; sym < numSymbols; sym++) {
@@ -359,7 +381,7 @@ bool ElfReader::LoadSymbols() {
359 381
360 int type = symtab[sym].st_info & 0xF; 382 int type = symtab[sym].st_info & 0xF;
361 383
362 const char *name = stringBase + symtab[sym].st_name; 384 const char* name = stringBase + symtab[sym].st_name;
363 385
364 Symbols::Add(symtab[sym].st_value, name, size, type); 386 Symbols::Add(symtab[sym].st_value, name, size, type);
365 387
@@ -411,7 +433,8 @@ ResultStatus AppLoader_ELF::Load() {
411 Kernel::g_current_process->address_mappings = default_address_mappings; 433 Kernel::g_current_process->address_mappings = default_address_mappings;
412 434
413 // Attach the default resource limit (APPLICATION) to the process 435 // Attach the default resource limit (APPLICATION) to the process
414 Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); 436 Kernel::g_current_process->resource_limit =
437 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
415 438
416 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); 439 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
417 440
diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h
index cb3724f9d..0b1456c64 100644
--- a/src/core/loader/elf.h
+++ b/src/core/loader/elf.h
@@ -18,7 +18,8 @@ namespace Loader {
18class AppLoader_ELF final : public AppLoader { 18class AppLoader_ELF final : public AppLoader {
19public: 19public:
20 AppLoader_ELF(FileUtil::IOFile&& file, std::string filename) 20 AppLoader_ELF(FileUtil::IOFile&& file, std::string filename)
21 : AppLoader(std::move(file)), filename(std::move(filename)) { } 21 : AppLoader(std::move(file)), filename(std::move(filename)) {
22 }
22 23
23 /** 24 /**
24 * Returns the type of the file 25 * Returns the type of the file
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 9719d30d5..b392bf544 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -18,17 +18,17 @@
18namespace Loader { 18namespace Loader {
19 19
20const std::initializer_list<Kernel::AddressMapping> default_address_mappings = { 20const std::initializer_list<Kernel::AddressMapping> default_address_mappings = {
21 { 0x1FF50000, 0x8000, true }, // part of DSP RAM 21 {0x1FF50000, 0x8000, true}, // part of DSP RAM
22 { 0x1FF70000, 0x8000, true }, // part of DSP RAM 22 {0x1FF70000, 0x8000, true}, // part of DSP RAM
23 { 0x1F000000, 0x600000, false }, // entire VRAM 23 {0x1F000000, 0x600000, false}, // entire VRAM
24}; 24};
25 25
26FileType IdentifyFile(FileUtil::IOFile& file) { 26FileType IdentifyFile(FileUtil::IOFile& file) {
27 FileType type; 27 FileType type;
28 28
29#define CHECK_TYPE(loader) \ 29#define CHECK_TYPE(loader) \
30 type = AppLoader_##loader::IdentifyType(file); \ 30 type = AppLoader_##loader::IdentifyType(file); \
31 if (FileType::Error != type) \ 31 if (FileType::Error != type) \
32 return type; 32 return type;
33 33
34 CHECK_TYPE(THREEDSX) 34 CHECK_TYPE(THREEDSX)
@@ -100,7 +100,8 @@ const char* GetFileTypeString(FileType type) {
100 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type 100 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type
101 */ 101 */
102static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileType type, 102static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileType type,
103 const std::string& filename, const std::string& filepath) { 103 const std::string& filename,
104 const std::string& filepath) {
104 switch (type) { 105 switch (type) {
105 106
106 // 3DSX file format. 107 // 3DSX file format.
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 77d87afe1..5f48d2ffe 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -30,7 +30,7 @@ enum class FileType {
30 CXI, 30 CXI,
31 CIA, 31 CIA,
32 ELF, 32 ELF,
33 THREEDSX, //3DSX 33 THREEDSX, // 3DSX
34}; 34};
35 35
36/** 36/**
@@ -81,8 +81,10 @@ constexpr u32 MakeMagic(char a, char b, char c, char d) {
81/// Interface for loading an application 81/// Interface for loading an application
82class AppLoader : NonCopyable { 82class AppLoader : NonCopyable {
83public: 83public:
84 AppLoader(FileUtil::IOFile&& file) : file(std::move(file)) { } 84 AppLoader(FileUtil::IOFile&& file) : file(std::move(file)) {
85 virtual ~AppLoader() { } 85 }
86 virtual ~AppLoader() {
87 }
86 88
87 /** 89 /**
88 * Returns the type of this file 90 * Returns the type of this file
@@ -140,7 +142,8 @@ public:
140 * @param size The size of the romfs 142 * @param size The size of the romfs
141 * @return ResultStatus result of function 143 * @return ResultStatus result of function
142 */ 144 */
143 virtual ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { 145 virtual ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
146 u64& size) {
144 return ResultStatus::ErrorNotImplemented; 147 return ResultStatus::ErrorNotImplemented;
145 } 148 }
146 149
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index fca091ff9..5b996d671 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -22,8 +22,8 @@
22 22
23namespace Loader { 23namespace Loader {
24 24
25static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs 25static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs
26static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes) 26static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes)
27 27
28/** 28/**
29 * Get the decompressed size of an LZSS compressed ExeFS file 29 * Get the decompressed size of an LZSS compressed ExeFS file
@@ -44,7 +44,8 @@ static u32 LZSS_GetDecompressedSize(const u8* buffer, u32 size) {
44 * @param decompressed_size Size of decompressed buffer 44 * @param decompressed_size Size of decompressed buffer
45 * @return True on success, otherwise false 45 * @return True on success, otherwise false
46 */ 46 */
47static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decompressed, u32 decompressed_size) { 47static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decompressed,
48 u32 decompressed_size) {
48 const u8* footer = compressed + compressed_size - 8; 49 const u8* footer = compressed + compressed_size - 8;
49 u32 buffer_top_and_bottom = *reinterpret_cast<const u32*>(footer); 50 u32 buffer_top_and_bottom = *reinterpret_cast<const u32*>(footer);
50 u32 out = decompressed_size; 51 u32 out = decompressed_size;
@@ -55,7 +56,7 @@ static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decom
55 memcpy(decompressed, compressed, compressed_size); 56 memcpy(decompressed, compressed, compressed_size);
56 57
57 while (index > stop_index) { 58 while (index > stop_index) {
58 u8 control = compressed[--index]; 59 u8 control = compressed[--index];
59 60
60 for (unsigned i = 0; i < 8; i++) { 61 for (unsigned i = 0; i < 8; i++) {
61 if (index <= stop_index) 62 if (index <= stop_index)
@@ -128,7 +129,7 @@ ResultStatus AppLoader_NCCH::LoadExec() {
128 std::vector<u8> code; 129 std::vector<u8> code;
129 if (ResultStatus::Success == ReadCode(code)) { 130 if (ResultStatus::Success == ReadCode(code)) {
130 std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( 131 std::string process_name = Common::StringFromFixedZeroTerminatedBuffer(
131 (const char*)exheader_header.codeset_info.name, 8); 132 (const char*)exheader_header.codeset_info.name, 8);
132 133
133 SharedPtr<CodeSet> codeset = CodeSet::Create(process_name, ncch_header.program_id); 134 SharedPtr<CodeSet> codeset = CodeSet::Create(process_name, ncch_header.program_id);
134 135
@@ -147,7 +148,8 @@ ResultStatus AppLoader_NCCH::LoadExec() {
147 148
148 codeset->data.offset = codeset->rodata.offset + codeset->rodata.size; 149 codeset->data.offset = codeset->rodata.offset + codeset->rodata.size;
149 codeset->data.addr = exheader_header.codeset_info.data.address; 150 codeset->data.addr = exheader_header.codeset_info.data.address;
150 codeset->data.size = exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE + bss_page_size; 151 codeset->data.size =
152 exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE + bss_page_size;
151 153
152 codeset->entrypoint = codeset->code.addr; 154 codeset->entrypoint = codeset->code.addr;
153 codeset->memory = std::make_shared<std::vector<u8>>(std::move(code)); 155 codeset->memory = std::make_shared<std::vector<u8>>(std::move(code));
@@ -155,15 +157,18 @@ ResultStatus AppLoader_NCCH::LoadExec() {
155 Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); 157 Kernel::g_current_process = Kernel::Process::Create(std::move(codeset));
156 158
157 // Attach a resource limit to the process based on the resource limit category 159 // Attach a resource limit to the process based on the resource limit category
158 Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory( 160 Kernel::g_current_process->resource_limit =
159 static_cast<Kernel::ResourceLimitCategory>(exheader_header.arm11_system_local_caps.resource_limit_category)); 161 Kernel::ResourceLimit::GetForCategory(static_cast<Kernel::ResourceLimitCategory>(
162 exheader_header.arm11_system_local_caps.resource_limit_category));
160 163
161 // Set the default CPU core for this process 164 // Set the default CPU core for this process
162 Kernel::g_current_process->ideal_processor = exheader_header.arm11_system_local_caps.ideal_processor; 165 Kernel::g_current_process->ideal_processor =
166 exheader_header.arm11_system_local_caps.ideal_processor;
163 167
164 // Copy data while converting endianess 168 // Copy data while converting endianess
165 std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps; 169 std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps;
166 std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), begin(kernel_caps)); 170 std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(),
171 begin(kernel_caps));
167 Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); 172 Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size());
168 173
169 s32 priority = exheader_header.arm11_system_local_caps.priority; 174 s32 priority = exheader_header.arm11_system_local_caps.priority;
@@ -192,7 +197,8 @@ ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>&
192 LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", section_number, 197 LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", section_number,
193 section.offset, section.size, section.name); 198 section.offset, section.size, section.name);
194 199
195 s64 section_offset = (section.offset + exefs_offset + sizeof(ExeFs_Header) + ncch_offset); 200 s64 section_offset =
201 (section.offset + exefs_offset + sizeof(ExeFs_Header) + ncch_offset);
196 file.Seek(section_offset, SEEK_SET); 202 file.Seek(section_offset, SEEK_SET);
197 203
198 if (strcmp(section.name, ".code") == 0 && is_compressed) { 204 if (strcmp(section.name, ".code") == 0 && is_compressed) {
@@ -254,25 +260,25 @@ ResultStatus AppLoader_NCCH::LoadExeFS() {
254 if (file.ReadBytes(&exheader_header, sizeof(ExHeader_Header)) != sizeof(ExHeader_Header)) 260 if (file.ReadBytes(&exheader_header, sizeof(ExHeader_Header)) != sizeof(ExHeader_Header))
255 return ResultStatus::Error; 261 return ResultStatus::Error;
256 262
257 is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1; 263 is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1;
258 entry_point = exheader_header.codeset_info.text.address; 264 entry_point = exheader_header.codeset_info.text.address;
259 code_size = exheader_header.codeset_info.text.code_size; 265 code_size = exheader_header.codeset_info.text.code_size;
260 stack_size = exheader_header.codeset_info.stack_size; 266 stack_size = exheader_header.codeset_info.stack_size;
261 bss_size = exheader_header.codeset_info.bss_size; 267 bss_size = exheader_header.codeset_info.bss_size;
262 core_version = exheader_header.arm11_system_local_caps.core_version; 268 core_version = exheader_header.arm11_system_local_caps.core_version;
263 priority = exheader_header.arm11_system_local_caps.priority; 269 priority = exheader_header.arm11_system_local_caps.priority;
264 resource_limit_category = exheader_header.arm11_system_local_caps.resource_limit_category; 270 resource_limit_category = exheader_header.arm11_system_local_caps.resource_limit_category;
265 271
266 LOG_INFO(Loader, "Name: %s" , exheader_header.codeset_info.name); 272 LOG_INFO(Loader, "Name: %s", exheader_header.codeset_info.name);
267 LOG_INFO(Loader, "Program ID: %016llX" , ncch_header.program_id); 273 LOG_INFO(Loader, "Program ID: %016llX", ncch_header.program_id);
268 LOG_DEBUG(Loader, "Code compressed: %s" , is_compressed ? "yes" : "no"); 274 LOG_DEBUG(Loader, "Code compressed: %s", is_compressed ? "yes" : "no");
269 LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point); 275 LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point);
270 LOG_DEBUG(Loader, "Code size: 0x%08X", code_size); 276 LOG_DEBUG(Loader, "Code size: 0x%08X", code_size);
271 LOG_DEBUG(Loader, "Stack size: 0x%08X", stack_size); 277 LOG_DEBUG(Loader, "Stack size: 0x%08X", stack_size);
272 LOG_DEBUG(Loader, "Bss size: 0x%08X", bss_size); 278 LOG_DEBUG(Loader, "Bss size: 0x%08X", bss_size);
273 LOG_DEBUG(Loader, "Core version: %d" , core_version); 279 LOG_DEBUG(Loader, "Core version: %d", core_version);
274 LOG_DEBUG(Loader, "Thread priority: 0x%X" , priority); 280 LOG_DEBUG(Loader, "Thread priority: 0x%X", priority);
275 LOG_DEBUG(Loader, "Resource limit category: %d" , resource_limit_category); 281 LOG_DEBUG(Loader, "Resource limit category: %d", resource_limit_category);
276 282
277 if (exheader_header.arm11_system_local_caps.program_id != ncch_header.program_id) { 283 if (exheader_header.arm11_system_local_caps.program_id != ncch_header.program_id) {
278 LOG_ERROR(Loader, "ExHeader Program ID mismatch: the ROM is probably encrypted."); 284 LOG_ERROR(Loader, "ExHeader Program ID mismatch: the ROM is probably encrypted.");
@@ -309,7 +315,8 @@ ResultStatus AppLoader_NCCH::Load() {
309 if (ResultStatus::Success != result) 315 if (ResultStatus::Success != result)
310 return result; 316 return result;
311 317
312 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), Service::FS::ArchiveIdCode::RomFS); 318 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this),
319 Service::FS::ArchiveIdCode::RomFS);
313 return ResultStatus::Success; 320 return ResultStatus::Success;
314} 321}
315 322
@@ -329,7 +336,8 @@ ResultStatus AppLoader_NCCH::ReadLogo(std::vector<u8>& buffer) {
329 return LoadSectionExeFS("logo", buffer); 336 return LoadSectionExeFS("logo", buffer);
330} 337}
331 338
332ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { 339ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
340 u64& size) {
333 if (!file.IsOpen()) 341 if (!file.IsOpen())
334 return ResultStatus::Error; 342 return ResultStatus::Error;
335 343
@@ -341,7 +349,7 @@ ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_
341 LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset); 349 LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset);
342 LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size); 350 LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size);
343 351
344 if (file.GetSize () < romfs_offset + romfs_size) 352 if (file.GetSize() < romfs_offset + romfs_size)
345 return ResultStatus::Error; 353 return ResultStatus::Error;
346 354
347 // We reopen the file, to allow its position to be independent from file's 355 // We reopen the file, to allow its position to be independent from file's
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index 75609ee57..0cd70f70c 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -164,7 +164,8 @@ namespace Loader {
164class AppLoader_NCCH final : public AppLoader { 164class AppLoader_NCCH final : public AppLoader {
165public: 165public:
166 AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath) 166 AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath)
167 : AppLoader(std::move(file)), filepath(filepath) { } 167 : AppLoader(std::move(file)), filepath(filepath) {
168 }
168 169
169 /** 170 /**
170 * Returns the type of the file 171 * Returns the type of the file
@@ -222,10 +223,10 @@ public:
222 * @param size Size of the RomFS in bytes 223 * @param size Size of the RomFS in bytes
223 * @return ResultStatus result of function 224 * @return ResultStatus result of function
224 */ 225 */
225 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) override; 226 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
227 u64& size) override;
226 228
227private: 229private:
228
229 /** 230 /**
230 * Reads an application ExeFS section of an NCCH file into AppLoader (e.g. .code, .logo, etc.) 231 * Reads an application ExeFS section of an NCCH file into AppLoader (e.g. .code, .logo, etc.)
231 * @param name Name of section to read out of NCCH file 232 * @param name Name of section to read out of NCCH file
@@ -246,24 +247,24 @@ private:
246 */ 247 */
247 ResultStatus LoadExeFS(); 248 ResultStatus LoadExeFS();
248 249
249 bool is_exefs_loaded = false; 250 bool is_exefs_loaded = false;
250 bool is_compressed = false; 251 bool is_compressed = false;
251 252
252 u32 entry_point = 0; 253 u32 entry_point = 0;
253 u32 code_size = 0; 254 u32 code_size = 0;
254 u32 stack_size = 0; 255 u32 stack_size = 0;
255 u32 bss_size = 0; 256 u32 bss_size = 0;
256 u32 core_version = 0; 257 u32 core_version = 0;
257 u8 priority = 0; 258 u8 priority = 0;
258 u8 resource_limit_category = 0; 259 u8 resource_limit_category = 0;
259 u32 ncch_offset = 0; // Offset to NCCH header, can be 0 or after NCSD header 260 u32 ncch_offset = 0; // Offset to NCCH header, can be 0 or after NCSD header
260 u32 exefs_offset = 0; 261 u32 exefs_offset = 0;
261 262
262 NCCH_Header ncch_header; 263 NCCH_Header ncch_header;
263 ExeFs_Header exefs_header; 264 ExeFs_Header exefs_header;
264 ExHeader_Header exheader_header; 265 ExHeader_Header exheader_header;
265 266
266 std::string filepath; 267 std::string filepath;
267}; 268};
268 269
269} // namespace Loader 270} // namespace Loader
diff --git a/src/core/loader/smdh.h b/src/core/loader/smdh.h
index 2011abda2..ab665ea82 100644
--- a/src/core/loader/smdh.h
+++ b/src/core/loader/smdh.h
@@ -56,7 +56,7 @@ struct SMDH {
56 Italian = 4, 56 Italian = 4,
57 Spanish = 5, 57 Spanish = 5,
58 SimplifiedChinese = 6, 58 SimplifiedChinese = 6,
59 Korean= 7, 59 Korean = 7,
60 Dutch = 8, 60 Dutch = 8,
61 Portuguese = 9, 61 Portuguese = 9,
62 Russian = 10, 62 Russian = 10,
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 9aa8c4e5a..4de510fe5 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -25,11 +25,13 @@ enum class PageType {
25 Unmapped, 25 Unmapped,
26 /// Page is mapped to regular memory. This is the only type you can get pointers to. 26 /// Page is mapped to regular memory. This is the only type you can get pointers to.
27 Memory, 27 Memory,
28 /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and invalidation 28 /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and
29 /// invalidation
29 RasterizerCachedMemory, 30 RasterizerCachedMemory,
30 /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions. 31 /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions.
31 Special, 32 Special,
32 /// Page is mapped to a I/O region, but also needs to check for rasterizer cache flushing and invalidation 33 /// Page is mapped to a I/O region, but also needs to check for rasterizer cache flushing and
34 /// invalidation
33 RasterizerCachedSpecial, 35 RasterizerCachedSpecial,
34}; 36};
35 37
@@ -55,7 +57,8 @@ struct PageTable {
55 std::array<u8*, NUM_ENTRIES> pointers; 57 std::array<u8*, NUM_ENTRIES> pointers;
56 58
57 /** 59 /**
58 * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of type `Special`. 60 * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of
61 * type `Special`.
59 */ 62 */
60 std::vector<SpecialRegion> special_regions; 63 std::vector<SpecialRegion> special_regions;
61 64
@@ -78,17 +81,20 @@ static PageTable main_page_table;
78static PageTable* current_page_table = &main_page_table; 81static PageTable* current_page_table = &main_page_table;
79 82
80static void MapPages(u32 base, u32 size, u8* memory, PageType type) { 83static void MapPages(u32 base, u32 size, u8* memory, PageType type) {
81 LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE, (base + size) * PAGE_SIZE); 84 LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE,
85 (base + size) * PAGE_SIZE);
82 86
83 u32 end = base + size; 87 u32 end = base + size;
84 88
85 while (base != end) { 89 while (base != end) {
86 ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base); 90 ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base);
87 91
88 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be null here 92 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
93 // null here
89 if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory || 94 if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory ||
90 current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) { 95 current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) {
91 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS), PAGE_SIZE); 96 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS),
97 PAGE_SIZE);
92 } 98 }
93 99
94 current_page_table->attributes[base] = type; 100 current_page_table->attributes[base] = type;
@@ -162,7 +168,7 @@ static MMIORegionPointer GetMMIOHandler(VAddr vaddr) {
162 return nullptr; // Should never happen 168 return nullptr; // Should never happen
163} 169}
164 170
165template<typename T> 171template <typename T>
166T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); 172T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr);
167 173
168template <typename T> 174template <typename T>
@@ -183,8 +189,7 @@ T Read(const VAddr vaddr) {
183 case PageType::Memory: 189 case PageType::Memory:
184 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 190 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
185 break; 191 break;
186 case PageType::RasterizerCachedMemory: 192 case PageType::RasterizerCachedMemory: {
187 {
188 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 193 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
189 194
190 T value; 195 T value;
@@ -193,8 +198,7 @@ T Read(const VAddr vaddr) {
193 } 198 }
194 case PageType::Special: 199 case PageType::Special:
195 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 200 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
196 case PageType::RasterizerCachedSpecial: 201 case PageType::RasterizerCachedSpecial: {
197 {
198 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 202 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
199 203
200 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 204 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
@@ -204,7 +208,7 @@ T Read(const VAddr vaddr) {
204 } 208 }
205} 209}
206 210
207template<typename T> 211template <typename T>
208void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data); 212void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data);
209 213
210template <typename T> 214template <typename T>
@@ -219,13 +223,13 @@ void Write(const VAddr vaddr, const T data) {
219 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; 223 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
220 switch (type) { 224 switch (type) {
221 case PageType::Unmapped: 225 case PageType::Unmapped:
222 LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32) data, vaddr); 226 LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data,
227 vaddr);
223 return; 228 return;
224 case PageType::Memory: 229 case PageType::Memory:
225 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 230 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
226 break; 231 break;
227 case PageType::RasterizerCachedMemory: 232 case PageType::RasterizerCachedMemory: {
228 {
229 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 233 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
230 234
231 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); 235 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T));
@@ -234,8 +238,7 @@ void Write(const VAddr vaddr, const T data) {
234 case PageType::Special: 238 case PageType::Special:
235 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 239 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
236 break; 240 break;
237 case PageType::RasterizerCachedSpecial: 241 case PageType::RasterizerCachedSpecial: {
238 {
239 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 242 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
240 243
241 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 244 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
@@ -310,7 +313,8 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
310 for (unsigned i = 0; i < num_pages; ++i) { 313 for (unsigned i = 0; i < num_pages; ++i) {
311 VAddr vaddr = PhysicalToVirtualAddress(paddr); 314 VAddr vaddr = PhysicalToVirtualAddress(paddr);
312 u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS]; 315 u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS];
313 ASSERT_MSG(count_delta <= UINT8_MAX - res_count, "Rasterizer resource cache counter overflow!"); 316 ASSERT_MSG(count_delta <= UINT8_MAX - res_count,
317 "Rasterizer resource cache counter overflow!");
314 ASSERT_MSG(count_delta >= -res_count, "Rasterizer resource cache counter underflow!"); 318 ASSERT_MSG(count_delta >= -res_count, "Rasterizer resource cache counter underflow!");
315 319
316 // Switch page type to cached if now cached 320 // Switch page type to cached if now cached
@@ -337,7 +341,8 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
337 switch (page_type) { 341 switch (page_type) {
338 case PageType::RasterizerCachedMemory: 342 case PageType::RasterizerCachedMemory:
339 page_type = PageType::Memory; 343 page_type = PageType::Memory;
340 current_page_table->pointers[vaddr >> PAGE_BITS] = GetPointerFromVMA(vaddr & ~PAGE_MASK); 344 current_page_table->pointers[vaddr >> PAGE_BITS] =
345 GetPointerFromVMA(vaddr & ~PAGE_MASK);
341 break; 346 break;
342 case PageType::RasterizerCachedSpecial: 347 case PageType::RasterizerCachedSpecial:
343 page_type = PageType::Special; 348 page_type = PageType::Special;
@@ -389,7 +394,8 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) {
389 394
390 switch (current_page_table->attributes[page_index]) { 395 switch (current_page_table->attributes[page_index]) {
391 case PageType::Unmapped: { 396 case PageType::Unmapped: {
392 LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); 397 LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
398 current_vaddr, src_addr, size);
393 std::memset(dest_buffer, 0, copy_amount); 399 std::memset(dest_buffer, 0, copy_amount);
394 break; 400 break;
395 } 401 }
@@ -458,7 +464,9 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
458 464
459 switch (current_page_table->attributes[page_index]) { 465 switch (current_page_table->attributes[page_index]) {
460 case PageType::Unmapped: { 466 case PageType::Unmapped: {
461 LOG_ERROR(HW_Memory, "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); 467 LOG_ERROR(HW_Memory,
468 "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
469 current_vaddr, dest_addr, size);
462 break; 470 break;
463 } 471 }
464 case PageType::Memory: { 472 case PageType::Memory: {
@@ -475,7 +483,8 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
475 break; 483 break;
476 } 484 }
477 case PageType::RasterizerCachedMemory: { 485 case PageType::RasterizerCachedMemory: {
478 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 486 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
487 copy_amount);
479 488
480 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); 489 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount);
481 break; 490 break;
@@ -483,7 +492,8 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
483 case PageType::RasterizerCachedSpecial: { 492 case PageType::RasterizerCachedSpecial: {
484 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 493 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
485 494
486 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 495 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
496 copy_amount);
487 497
488 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); 498 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount);
489 break; 499 break;
@@ -512,7 +522,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
512 522
513 switch (current_page_table->attributes[page_index]) { 523 switch (current_page_table->attributes[page_index]) {
514 case PageType::Unmapped: { 524 case PageType::Unmapped: {
515 LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); 525 LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
526 current_vaddr, dest_addr, size);
516 break; 527 break;
517 } 528 }
518 case PageType::Memory: { 529 case PageType::Memory: {
@@ -529,7 +540,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
529 break; 540 break;
530 } 541 }
531 case PageType::RasterizerCachedMemory: { 542 case PageType::RasterizerCachedMemory: {
532 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 543 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
544 copy_amount);
533 545
534 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); 546 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount);
535 break; 547 break;
@@ -537,7 +549,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
537 case PageType::RasterizerCachedSpecial: { 549 case PageType::RasterizerCachedSpecial: {
538 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 550 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
539 551
540 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 552 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
553 copy_amount);
541 554
542 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); 555 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount);
543 break; 556 break;
@@ -563,7 +576,8 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
563 576
564 switch (current_page_table->attributes[page_index]) { 577 switch (current_page_table->attributes[page_index]) {
565 case PageType::Unmapped: { 578 case PageType::Unmapped: {
566 LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); 579 LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
580 current_vaddr, src_addr, size);
567 ZeroBlock(dest_addr, copy_amount); 581 ZeroBlock(dest_addr, copy_amount);
568 break; 582 break;
569 } 583 }
@@ -609,42 +623,42 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
609 } 623 }
610} 624}
611 625
612template<> 626template <>
613u8 ReadMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr) { 627u8 ReadMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr) {
614 return mmio_handler->Read8(addr); 628 return mmio_handler->Read8(addr);
615} 629}
616 630
617template<> 631template <>
618u16 ReadMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr) { 632u16 ReadMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr) {
619 return mmio_handler->Read16(addr); 633 return mmio_handler->Read16(addr);
620} 634}
621 635
622template<> 636template <>
623u32 ReadMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr) { 637u32 ReadMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr) {
624 return mmio_handler->Read32(addr); 638 return mmio_handler->Read32(addr);
625} 639}
626 640
627template<> 641template <>
628u64 ReadMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr) { 642u64 ReadMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr) {
629 return mmio_handler->Read64(addr); 643 return mmio_handler->Read64(addr);
630} 644}
631 645
632template<> 646template <>
633void WriteMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr, const u8 data) { 647void WriteMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr, const u8 data) {
634 mmio_handler->Write8(addr, data); 648 mmio_handler->Write8(addr, data);
635} 649}
636 650
637template<> 651template <>
638void WriteMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr, const u16 data) { 652void WriteMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr, const u16 data) {
639 mmio_handler->Write16(addr, data); 653 mmio_handler->Write16(addr, data);
640} 654}
641 655
642template<> 656template <>
643void WriteMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr, const u32 data) { 657void WriteMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr, const u32 data) {
644 mmio_handler->Write32(addr, data); 658 mmio_handler->Write32(addr, data);
645} 659}
646 660
647template<> 661template <>
648void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) { 662void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) {
649 mmio_handler->Write64(addr, data); 663 mmio_handler->Write64(addr, data);
650} 664}
diff --git a/src/core/memory.h b/src/core/memory.h
index cad845385..7d60ccdf1 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -22,92 +22,93 @@ const int PAGE_BITS = 12;
22/// Physical memory regions as seen from the ARM11 22/// Physical memory regions as seen from the ARM11
23enum : PAddr { 23enum : PAddr {
24 /// IO register area 24 /// IO register area
25 IO_AREA_PADDR = 0x10100000, 25 IO_AREA_PADDR = 0x10100000,
26 IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB) 26 IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB)
27 IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE, 27 IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE,
28 28
29 /// MPCore internal memory region 29 /// MPCore internal memory region
30 MPCORE_RAM_PADDR = 0x17E00000, 30 MPCORE_RAM_PADDR = 0x17E00000,
31 MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB) 31 MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB)
32 MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE, 32 MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE,
33 33
34 /// Video memory 34 /// Video memory
35 VRAM_PADDR = 0x18000000, 35 VRAM_PADDR = 0x18000000,
36 VRAM_SIZE = 0x00600000, ///< VRAM size (6MB) 36 VRAM_SIZE = 0x00600000, ///< VRAM size (6MB)
37 VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, 37 VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE,
38 38
39 /// DSP memory 39 /// DSP memory
40 DSP_RAM_PADDR = 0x1FF00000, 40 DSP_RAM_PADDR = 0x1FF00000,
41 DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB) 41 DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB)
42 DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE, 42 DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE,
43 43
44 /// AXI WRAM 44 /// AXI WRAM
45 AXI_WRAM_PADDR = 0x1FF80000, 45 AXI_WRAM_PADDR = 0x1FF80000,
46 AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB) 46 AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB)
47 AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE, 47 AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE,
48 48
49 /// Main FCRAM 49 /// Main FCRAM
50 FCRAM_PADDR = 0x20000000, 50 FCRAM_PADDR = 0x20000000,
51 FCRAM_SIZE = 0x08000000, ///< FCRAM size (128MB) 51 FCRAM_SIZE = 0x08000000, ///< FCRAM size (128MB)
52 FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE, 52 FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE,
53}; 53};
54 54
55/// Virtual user-space memory regions 55/// Virtual user-space memory regions
56enum : VAddr { 56enum : VAddr {
57 /// Where the application text, data and bss reside. 57 /// Where the application text, data and bss reside.
58 PROCESS_IMAGE_VADDR = 0x00100000, 58 PROCESS_IMAGE_VADDR = 0x00100000,
59 PROCESS_IMAGE_MAX_SIZE = 0x03F00000, 59 PROCESS_IMAGE_MAX_SIZE = 0x03F00000,
60 PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE, 60 PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE,
61 61
62 /// Area where IPC buffers are mapped onto. 62 /// Area where IPC buffers are mapped onto.
63 IPC_MAPPING_VADDR = 0x04000000, 63 IPC_MAPPING_VADDR = 0x04000000,
64 IPC_MAPPING_SIZE = 0x04000000, 64 IPC_MAPPING_SIZE = 0x04000000,
65 IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE, 65 IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE,
66 66
67 /// Application heap (includes stack). 67 /// Application heap (includes stack).
68 HEAP_VADDR = 0x08000000, 68 HEAP_VADDR = 0x08000000,
69 HEAP_SIZE = 0x08000000, 69 HEAP_SIZE = 0x08000000,
70 HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, 70 HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE,
71 71
72 /// Area where shared memory buffers are mapped onto. 72 /// Area where shared memory buffers are mapped onto.
73 SHARED_MEMORY_VADDR = 0x10000000, 73 SHARED_MEMORY_VADDR = 0x10000000,
74 SHARED_MEMORY_SIZE = 0x04000000, 74 SHARED_MEMORY_SIZE = 0x04000000,
75 SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE, 75 SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE,
76 76
77 /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical memory. 77 /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical
78 LINEAR_HEAP_VADDR = 0x14000000, 78 /// memory.
79 LINEAR_HEAP_SIZE = 0x08000000, 79 LINEAR_HEAP_VADDR = 0x14000000,
80 LINEAR_HEAP_SIZE = 0x08000000,
80 LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, 81 LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE,
81 82
82 /// Maps 1:1 to the IO register area. 83 /// Maps 1:1 to the IO register area.
83 IO_AREA_VADDR = 0x1EC00000, 84 IO_AREA_VADDR = 0x1EC00000,
84 IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, 85 IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE,
85 86
86 /// Maps 1:1 to VRAM. 87 /// Maps 1:1 to VRAM.
87 VRAM_VADDR = 0x1F000000, 88 VRAM_VADDR = 0x1F000000,
88 VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE, 89 VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE,
89 90
90 /// Maps 1:1 to DSP memory. 91 /// Maps 1:1 to DSP memory.
91 DSP_RAM_VADDR = 0x1FF00000, 92 DSP_RAM_VADDR = 0x1FF00000,
92 DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE, 93 DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE,
93 94
94 /// Read-only page containing kernel and system configuration values. 95 /// Read-only page containing kernel and system configuration values.
95 CONFIG_MEMORY_VADDR = 0x1FF80000, 96 CONFIG_MEMORY_VADDR = 0x1FF80000,
96 CONFIG_MEMORY_SIZE = 0x00001000, 97 CONFIG_MEMORY_SIZE = 0x00001000,
97 CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE, 98 CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE,
98 99
99 /// Usually read-only page containing mostly values read from hardware. 100 /// Usually read-only page containing mostly values read from hardware.
100 SHARED_PAGE_VADDR = 0x1FF81000, 101 SHARED_PAGE_VADDR = 0x1FF81000,
101 SHARED_PAGE_SIZE = 0x00001000, 102 SHARED_PAGE_SIZE = 0x00001000,
102 SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, 103 SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE,
103 104
104 /// Area where TLS (Thread-Local Storage) buffers are allocated. 105 /// Area where TLS (Thread-Local Storage) buffers are allocated.
105 TLS_AREA_VADDR = 0x1FF82000, 106 TLS_AREA_VADDR = 0x1FF82000,
106 TLS_ENTRY_SIZE = 0x200, 107 TLS_ENTRY_SIZE = 0x200,
107 108
108 /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. 109 /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS.
109 NEW_LINEAR_HEAP_VADDR = 0x30000000, 110 NEW_LINEAR_HEAP_VADDR = 0x30000000,
110 NEW_LINEAR_HEAP_SIZE = 0x10000000, 111 NEW_LINEAR_HEAP_SIZE = 0x10000000,
111 NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, 112 NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE,
112}; 113};
113 114
@@ -166,5 +167,4 @@ void RasterizerFlushRegion(PAddr start, u32 size);
166 * Flushes and invalidates any externally cached rasterizer resources touching the given region. 167 * Flushes and invalidates any externally cached rasterizer resources touching the given region.
167 */ 168 */
168void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size); 169void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size);
169
170} 170}
diff --git a/src/core/memory_setup.h b/src/core/memory_setup.h
index ee8ea7857..23c36d019 100644
--- a/src/core/memory_setup.h
+++ b/src/core/memory_setup.h
@@ -30,5 +30,4 @@ void MapMemoryRegion(VAddr base, u32 size, u8* target);
30void MapIoRegion(VAddr base, u32 size, MMIORegionPointer mmio_handler); 30void MapIoRegion(VAddr base, u32 size, MMIORegionPointer mmio_handler);
31 31
32void UnmapRegion(VAddr base, u32 size); 32void UnmapRegion(VAddr base, u32 size);
33
34} 33}
diff --git a/src/core/mmio.h b/src/core/mmio.h
index d76f005d8..9aa59212b 100644
--- a/src/core/mmio.h
+++ b/src/core/mmio.h
@@ -36,5 +36,4 @@ public:
36}; 36};
37 37
38using MMIORegionPointer = std::shared_ptr<MMIORegion>; 38using MMIORegionPointer = std::shared_ptr<MMIORegion>;
39
40}; 39};
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 1b6733a79..09194fe1f 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -25,7 +25,6 @@ void Apply() {
25 25
26 AudioCore::SelectSink(values.sink_id); 26 AudioCore::SelectSink(values.sink_id);
27 AudioCore::EnableStretching(values.enable_audio_stretching); 27 AudioCore::EnableStretching(values.enable_audio_stretching);
28
29} 28}
30 29
31} // namespace 30} // namespace
diff --git a/src/core/settings.h b/src/core/settings.h
index fcd14c6f3..adb2fd538 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -4,8 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <string>
8#include <array> 7#include <array>
8#include <string>
9 9
10#include "common/common_types.h" 10#include "common/common_types.h"
11 11
@@ -14,14 +14,31 @@ namespace Settings {
14namespace NativeInput { 14namespace NativeInput {
15enum Values { 15enum Values {
16 // directly mapped keys 16 // directly mapped keys
17 A, B, X, Y, 17 A,
18 L, R, ZL, ZR, 18 B,
19 START, SELECT, HOME, 19 X,
20 DUP, DDOWN, DLEFT, DRIGHT, 20 Y,
21 CUP, CDOWN, CLEFT, CRIGHT, 21 L,
22 R,
23 ZL,
24 ZR,
25 START,
26 SELECT,
27 HOME,
28 DUP,
29 DDOWN,
30 DLEFT,
31 DRIGHT,
32 CUP,
33 CDOWN,
34 CLEFT,
35 CRIGHT,
22 36
23 // indirectly mapped keys 37 // indirectly mapped keys
24 CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, 38 CIRCLE_UP,
39 CIRCLE_DOWN,
40 CIRCLE_LEFT,
41 CIRCLE_RIGHT,
25 CIRCLE_MODIFIER, 42 CIRCLE_MODIFIER,
26 43
27 NUM_INPUTS 44 NUM_INPUTS
@@ -29,28 +46,21 @@ enum Values {
29 46
30static const std::array<const char*, NUM_INPUTS> Mapping = {{ 47static const std::array<const char*, NUM_INPUTS> Mapping = {{
31 // directly mapped keys 48 // directly mapped keys
32 "pad_a", "pad_b", "pad_x", "pad_y", 49 "pad_a", "pad_b", "pad_x", "pad_y", "pad_l", "pad_r", "pad_zl", "pad_zr", "pad_start",
33 "pad_l", "pad_r", "pad_zl", "pad_zr", 50 "pad_select", "pad_home", "pad_dup", "pad_ddown", "pad_dleft", "pad_dright", "pad_cup",
34 "pad_start", "pad_select", "pad_home", 51 "pad_cdown", "pad_cleft", "pad_cright",
35 "pad_dup", "pad_ddown", "pad_dleft", "pad_dright",
36 "pad_cup", "pad_cdown", "pad_cleft", "pad_cright",
37 52
38 // indirectly mapped keys 53 // indirectly mapped keys
39 "pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right", 54 "pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right",
40 "pad_circle_modifier", 55 "pad_circle_modifier",
41}}; 56}};
42static const std::array<Values, NUM_INPUTS> All = {{ 57static const std::array<Values, NUM_INPUTS> All = {{
43 A, B, X, Y, 58 A, B, X, Y, L, R, ZL, ZR,
44 L, R, ZL, ZR, 59 START, SELECT, HOME, DUP, DDOWN, DLEFT, DRIGHT, CUP,
45 START, SELECT, HOME, 60 CDOWN, CLEFT, CRIGHT, CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, CIRCLE_MODIFIER,
46 DUP, DDOWN, DLEFT, DRIGHT,
47 CUP, CDOWN, CLEFT, CRIGHT,
48 CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT,
49 CIRCLE_MODIFIER,
50}}; 61}};
51} 62}
52 63
53
54struct Values { 64struct Values {
55 // CheckNew3DS 65 // CheckNew3DS
56 bool is_new_3ds; 66 bool is_new_3ds;
@@ -91,5 +101,4 @@ struct Values {
91} extern values; 101} extern values;
92 102
93void Apply(); 103void Apply();
94
95} 104}
diff --git a/src/core/system.cpp b/src/core/system.cpp
index 4fc266cb0..f2bf648bd 100644
--- a/src/core/system.cpp
+++ b/src/core/system.cpp
@@ -6,18 +6,18 @@
6 6
7#include "core/core.h" 7#include "core/core.h"
8#include "core/core_timing.h" 8#include "core/core_timing.h"
9#include "core/system.h"
10#include "core/gdbstub/gdbstub.h" 9#include "core/gdbstub/gdbstub.h"
11#include "core/hw/hw.h"
12#include "core/hle/hle.h" 10#include "core/hle/hle.h"
13#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/memory.h" 12#include "core/hle/kernel/memory.h"
13#include "core/hw/hw.h"
14#include "core/system.h"
15 15
16#include "video_core/video_core.h" 16#include "video_core/video_core.h"
17 17
18namespace System { 18namespace System {
19 19
20static bool is_powered_on{ false }; 20static bool is_powered_on{false};
21 21
22Result Init(EmuWindow* emu_window) { 22Result Init(EmuWindow* emu_window) {
23 Core::Init(); 23 Core::Init();
diff --git a/src/core/system.h b/src/core/system.h
index fb0ca4e1b..6d672b1b5 100644
--- a/src/core/system.h
+++ b/src/core/system.h
@@ -9,14 +9,13 @@ class EmuWindow;
9namespace System { 9namespace System {
10 10
11enum class Result { 11enum class Result {
12 Success, ///< Everything is fine 12 Success, ///< Everything is fine
13 Error, ///< Something went wrong (no module specified) 13 Error, ///< Something went wrong (no module specified)
14 ErrorInitCore, ///< Something went wrong during core init 14 ErrorInitCore, ///< Something went wrong during core init
15 ErrorInitVideoCore, ///< Something went wrong during video core init 15 ErrorInitVideoCore, ///< Something went wrong during video core init
16}; 16};
17 17
18Result Init(EmuWindow* emu_window); 18Result Init(EmuWindow* emu_window);
19bool IsPoweredOn(); 19bool IsPoweredOn();
20void Shutdown(); 20void Shutdown();
21
22} 21}
diff --git a/src/core/tracer/citrace.h b/src/core/tracer/citrace.h
index 709abdfb3..ac26e872b 100644
--- a/src/core/tracer/citrace.h
+++ b/src/core/tracer/citrace.h
@@ -61,8 +61,8 @@ struct CTHeader {
61}; 61};
62 62
63enum CTStreamElementType : u32 { 63enum CTStreamElementType : u32 {
64 FrameMarker = 0xE1, 64 FrameMarker = 0xE1,
65 MemoryLoad = 0xE2, 65 MemoryLoad = 0xE2,
66 RegisterWrite = 0xE3, 66 RegisterWrite = 0xE3,
67}; 67};
68 68
@@ -76,12 +76,7 @@ struct CTMemoryLoad {
76struct CTRegisterWrite { 76struct CTRegisterWrite {
77 u32 physical_address; 77 u32 physical_address;
78 78
79 enum : u32 { 79 enum : u32 { SIZE_8 = 0xD1, SIZE_16 = 0xD2, SIZE_32 = 0xD3, SIZE_64 = 0xD4 } size;
80 SIZE_8 = 0xD1,
81 SIZE_16 = 0xD2,
82 SIZE_32 = 0xD3,
83 SIZE_64 = 0xD4
84 } size;
85 80
86 // TODO: Make it clearer which bits of this member are used for sizes other than 32 bits 81 // TODO: Make it clearer which bits of this member are used for sizes other than 32 bits
87 u64 value; 82 u64 value;
@@ -97,5 +92,4 @@ struct CTStreamElement {
97}; 92};
98 93
99#pragma pack() 94#pragma pack()
100
101} 95}
diff --git a/src/core/tracer/recorder.cpp b/src/core/tracer/recorder.cpp
index 7abaacf70..8fd0018c4 100644
--- a/src/core/tracer/recorder.cpp
+++ b/src/core/tracer/recorder.cpp
@@ -13,7 +13,6 @@
13namespace CiTrace { 13namespace CiTrace {
14 14
15Recorder::Recorder(const InitialState& initial_state) : initial_state(initial_state) { 15Recorder::Recorder(const InitialState& initial_state) : initial_state(initial_state) {
16
17} 16}
18 17
19void Recorder::Finish(const std::string& filename) { 18void Recorder::Finish(const std::string& filename) {
@@ -26,35 +25,41 @@ void Recorder::Finish(const std::string& filename) {
26 // Calculate file offsets 25 // Calculate file offsets
27 auto& initial = header.initial_state_offsets; 26 auto& initial = header.initial_state_offsets;
28 27
29 initial.gpu_registers_size = static_cast<u32>(initial_state.gpu_registers.size()); 28 initial.gpu_registers_size = static_cast<u32>(initial_state.gpu_registers.size());
30 initial.lcd_registers_size = static_cast<u32>(initial_state.lcd_registers.size()); 29 initial.lcd_registers_size = static_cast<u32>(initial_state.lcd_registers.size());
31 initial.pica_registers_size = static_cast<u32>(initial_state.pica_registers.size()); 30 initial.pica_registers_size = static_cast<u32>(initial_state.pica_registers.size());
32 initial.default_attributes_size = static_cast<u32>(initial_state.default_attributes.size()); 31 initial.default_attributes_size = static_cast<u32>(initial_state.default_attributes.size());
33 initial.vs_program_binary_size = static_cast<u32>(initial_state.vs_program_binary.size()); 32 initial.vs_program_binary_size = static_cast<u32>(initial_state.vs_program_binary.size());
34 initial.vs_swizzle_data_size = static_cast<u32>(initial_state.vs_swizzle_data.size()); 33 initial.vs_swizzle_data_size = static_cast<u32>(initial_state.vs_swizzle_data.size());
35 initial.vs_float_uniforms_size = static_cast<u32>(initial_state.vs_float_uniforms.size()); 34 initial.vs_float_uniforms_size = static_cast<u32>(initial_state.vs_float_uniforms.size());
36 initial.gs_program_binary_size = static_cast<u32>(initial_state.gs_program_binary.size()); 35 initial.gs_program_binary_size = static_cast<u32>(initial_state.gs_program_binary.size());
37 initial.gs_swizzle_data_size = static_cast<u32>(initial_state.gs_swizzle_data.size()); 36 initial.gs_swizzle_data_size = static_cast<u32>(initial_state.gs_swizzle_data.size());
38 initial.gs_float_uniforms_size = static_cast<u32>(initial_state.gs_float_uniforms.size()); 37 initial.gs_float_uniforms_size = static_cast<u32>(initial_state.gs_float_uniforms.size());
39 header.stream_size = static_cast<u32>(stream.size()); 38 header.stream_size = static_cast<u32>(stream.size());
40 39
41 initial.gpu_registers = sizeof(header); 40 initial.gpu_registers = sizeof(header);
42 initial.lcd_registers = initial.gpu_registers + initial.gpu_registers_size * sizeof(u32); 41 initial.lcd_registers = initial.gpu_registers + initial.gpu_registers_size * sizeof(u32);
43 initial.pica_registers = initial.lcd_registers + initial.lcd_registers_size * sizeof(u32);; 42 initial.pica_registers = initial.lcd_registers + initial.lcd_registers_size * sizeof(u32);
44 initial.default_attributes = initial.pica_registers + initial.pica_registers_size * sizeof(u32); 43 ;
45 initial.vs_program_binary = initial.default_attributes + initial.default_attributes_size * sizeof(u32); 44 initial.default_attributes = initial.pica_registers + initial.pica_registers_size * sizeof(u32);
46 initial.vs_swizzle_data = initial.vs_program_binary + initial.vs_program_binary_size * sizeof(u32); 45 initial.vs_program_binary =
47 initial.vs_float_uniforms = initial.vs_swizzle_data + initial.vs_swizzle_data_size * sizeof(u32); 46 initial.default_attributes + initial.default_attributes_size * sizeof(u32);
48 initial.gs_program_binary = initial.vs_float_uniforms + initial.vs_float_uniforms_size * sizeof(u32); 47 initial.vs_swizzle_data =
49 initial.gs_swizzle_data = initial.gs_program_binary + initial.gs_program_binary_size * sizeof(u32); 48 initial.vs_program_binary + initial.vs_program_binary_size * sizeof(u32);
50 initial.gs_float_uniforms = initial.gs_swizzle_data + initial.gs_swizzle_data_size * sizeof(u32); 49 initial.vs_float_uniforms =
51 header.stream_offset = initial.gs_float_uniforms + initial.gs_float_uniforms_size * sizeof(u32); 50 initial.vs_swizzle_data + initial.vs_swizzle_data_size * sizeof(u32);
51 initial.gs_program_binary =
52 initial.vs_float_uniforms + initial.vs_float_uniforms_size * sizeof(u32);
53 initial.gs_swizzle_data =
54 initial.gs_program_binary + initial.gs_program_binary_size * sizeof(u32);
55 initial.gs_float_uniforms =
56 initial.gs_swizzle_data + initial.gs_swizzle_data_size * sizeof(u32);
57 header.stream_offset = initial.gs_float_uniforms + initial.gs_float_uniforms_size * sizeof(u32);
52 58
53 // Iterate through stream elements, update relevant stream element data 59 // Iterate through stream elements, update relevant stream element data
54 for (auto& stream_element : stream) { 60 for (auto& stream_element : stream) {
55 switch (stream_element.data.type) { 61 switch (stream_element.data.type) {
56 case MemoryLoad: 62 case MemoryLoad: {
57 {
58 auto& file_offset = memory_regions[stream_element.hash]; 63 auto& file_offset = memory_regions[stream_element.hash];
59 if (!stream_element.uses_existing_data) { 64 if (!stream_element.uses_existing_data) {
60 file_offset = header.stream_offset; 65 file_offset = header.stream_offset;
@@ -79,44 +84,62 @@ void Recorder::Finish(const std::string& filename) {
79 throw "Failed to write header"; 84 throw "Failed to write header";
80 85
81 // Write initial state 86 // Write initial state
82 written = file.WriteArray(initial_state.gpu_registers.data(), initial_state.gpu_registers.size()); 87 written =
88 file.WriteArray(initial_state.gpu_registers.data(), initial_state.gpu_registers.size());
83 if (written != initial_state.gpu_registers.size() || file.Tell() != initial.lcd_registers) 89 if (written != initial_state.gpu_registers.size() || file.Tell() != initial.lcd_registers)
84 throw "Failed to write GPU registers"; 90 throw "Failed to write GPU registers";
85 91
86 written = file.WriteArray(initial_state.lcd_registers.data(), initial_state.lcd_registers.size()); 92 written =
93 file.WriteArray(initial_state.lcd_registers.data(), initial_state.lcd_registers.size());
87 if (written != initial_state.lcd_registers.size() || file.Tell() != initial.pica_registers) 94 if (written != initial_state.lcd_registers.size() || file.Tell() != initial.pica_registers)
88 throw "Failed to write LCD registers"; 95 throw "Failed to write LCD registers";
89 96
90 written = file.WriteArray(initial_state.pica_registers.data(), initial_state.pica_registers.size()); 97 written = file.WriteArray(initial_state.pica_registers.data(),
91 if (written != initial_state.pica_registers.size() || file.Tell() != initial.default_attributes) 98 initial_state.pica_registers.size());
99 if (written != initial_state.pica_registers.size() ||
100 file.Tell() != initial.default_attributes)
92 throw "Failed to write Pica registers"; 101 throw "Failed to write Pica registers";
93 102
94 written = file.WriteArray(initial_state.default_attributes.data(), initial_state.default_attributes.size()); 103 written = file.WriteArray(initial_state.default_attributes.data(),
95 if (written != initial_state.default_attributes.size() || file.Tell() != initial.vs_program_binary) 104 initial_state.default_attributes.size());
105 if (written != initial_state.default_attributes.size() ||
106 file.Tell() != initial.vs_program_binary)
96 throw "Failed to write default vertex attributes"; 107 throw "Failed to write default vertex attributes";
97 108
98 written = file.WriteArray(initial_state.vs_program_binary.data(), initial_state.vs_program_binary.size()); 109 written = file.WriteArray(initial_state.vs_program_binary.data(),
99 if (written != initial_state.vs_program_binary.size() || file.Tell() != initial.vs_swizzle_data) 110 initial_state.vs_program_binary.size());
111 if (written != initial_state.vs_program_binary.size() ||
112 file.Tell() != initial.vs_swizzle_data)
100 throw "Failed to write vertex shader program binary"; 113 throw "Failed to write vertex shader program binary";
101 114
102 written = file.WriteArray(initial_state.vs_swizzle_data.data(), initial_state.vs_swizzle_data.size()); 115 written = file.WriteArray(initial_state.vs_swizzle_data.data(),
103 if (written != initial_state.vs_swizzle_data.size() || file.Tell() != initial.vs_float_uniforms) 116 initial_state.vs_swizzle_data.size());
117 if (written != initial_state.vs_swizzle_data.size() ||
118 file.Tell() != initial.vs_float_uniforms)
104 throw "Failed to write vertex shader swizzle data"; 119 throw "Failed to write vertex shader swizzle data";
105 120
106 written = file.WriteArray(initial_state.vs_float_uniforms.data(), initial_state.vs_float_uniforms.size()); 121 written = file.WriteArray(initial_state.vs_float_uniforms.data(),
107 if (written != initial_state.vs_float_uniforms.size() || file.Tell() != initial.gs_program_binary) 122 initial_state.vs_float_uniforms.size());
123 if (written != initial_state.vs_float_uniforms.size() ||
124 file.Tell() != initial.gs_program_binary)
108 throw "Failed to write vertex shader float uniforms"; 125 throw "Failed to write vertex shader float uniforms";
109 126
110 written = file.WriteArray(initial_state.gs_program_binary.data(), initial_state.gs_program_binary.size()); 127 written = file.WriteArray(initial_state.gs_program_binary.data(),
111 if (written != initial_state.gs_program_binary.size() || file.Tell() != initial.gs_swizzle_data) 128 initial_state.gs_program_binary.size());
129 if (written != initial_state.gs_program_binary.size() ||
130 file.Tell() != initial.gs_swizzle_data)
112 throw "Failed to write geomtry shader program binary"; 131 throw "Failed to write geomtry shader program binary";
113 132
114 written = file.WriteArray(initial_state.gs_swizzle_data.data(), initial_state.gs_swizzle_data.size()); 133 written = file.WriteArray(initial_state.gs_swizzle_data.data(),
115 if (written != initial_state.gs_swizzle_data.size() || file.Tell() != initial.gs_float_uniforms) 134 initial_state.gs_swizzle_data.size());
135 if (written != initial_state.gs_swizzle_data.size() ||
136 file.Tell() != initial.gs_float_uniforms)
116 throw "Failed to write geometry shader swizzle data"; 137 throw "Failed to write geometry shader swizzle data";
117 138
118 written = file.WriteArray(initial_state.gs_float_uniforms.data(), initial_state.gs_float_uniforms.size()); 139 written = file.WriteArray(initial_state.gs_float_uniforms.data(),
119 if (written != initial_state.gs_float_uniforms.size() || file.Tell() != initial.gs_float_uniforms + sizeof(u32) * initial.gs_float_uniforms_size) 140 initial_state.gs_float_uniforms.size());
141 if (written != initial_state.gs_float_uniforms.size() ||
142 file.Tell() != initial.gs_float_uniforms + sizeof(u32) * initial.gs_float_uniforms_size)
120 throw "Failed to write geometry shader float uniforms"; 143 throw "Failed to write geometry shader float uniforms";
121 144
122 // Iterate through stream elements, write "extra data" 145 // Iterate through stream elements, write "extra data"
@@ -124,7 +147,8 @@ void Recorder::Finish(const std::string& filename) {
124 if (stream_element.extra_data.size() == 0) 147 if (stream_element.extra_data.size() == 0)
125 continue; 148 continue;
126 149
127 written = file.WriteBytes(stream_element.extra_data.data(), stream_element.extra_data.size()); 150 written =
151 file.WriteBytes(stream_element.extra_data.data(), stream_element.extra_data.size());
128 if (written != stream_element.extra_data.size()) 152 if (written != stream_element.extra_data.size())
129 throw "Failed to write extra data"; 153 throw "Failed to write extra data";
130 } 154 }
@@ -137,17 +161,17 @@ void Recorder::Finish(const std::string& filename) {
137 if (1 != file.WriteObject(stream_element.data)) 161 if (1 != file.WriteObject(stream_element.data))
138 throw "Failed to write stream element"; 162 throw "Failed to write stream element";
139 } 163 }
140 } catch(const char* str) { 164 } catch (const char* str) {
141 LOG_ERROR(HW_GPU, "Writing CiTrace file failed: %s", str); 165 LOG_ERROR(HW_GPU, "Writing CiTrace file failed: %s", str);
142 } 166 }
143} 167}
144 168
145void Recorder::FrameFinished() { 169void Recorder::FrameFinished() {
146 stream.push_back( { { FrameMarker } } ); 170 stream.push_back({{FrameMarker}});
147} 171}
148 172
149void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) { 173void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) {
150 StreamElement element = { { MemoryLoad } }; 174 StreamElement element = {{MemoryLoad}};
151 element.data.memory_load.size = size; 175 element.data.memory_load.size = size;
152 element.data.memory_load.physical_address = physical_address; 176 element.data.memory_load.physical_address = physical_address;
153 177
@@ -166,22 +190,22 @@ void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) {
166 stream.push_back(element); 190 stream.push_back(element);
167} 191}
168 192
169template<typename T> 193template <typename T>
170void Recorder::RegisterWritten(u32 physical_address, T value) { 194void Recorder::RegisterWritten(u32 physical_address, T value) {
171 StreamElement element = { { RegisterWrite } }; 195 StreamElement element = {{RegisterWrite}};
172 element.data.register_write.size = (sizeof(T) == 1) ? CTRegisterWrite::SIZE_8 196 element.data.register_write.size =
173 : (sizeof(T) == 2) ? CTRegisterWrite::SIZE_16 197 (sizeof(T) == 1) ? CTRegisterWrite::SIZE_8
174 : (sizeof(T) == 4) ? CTRegisterWrite::SIZE_32 198 : (sizeof(T) == 2) ? CTRegisterWrite::SIZE_16
175 : CTRegisterWrite::SIZE_64; 199 : (sizeof(T) == 4) ? CTRegisterWrite::SIZE_32
200 : CTRegisterWrite::SIZE_64;
176 element.data.register_write.physical_address = physical_address; 201 element.data.register_write.physical_address = physical_address;
177 element.data.register_write.value = value; 202 element.data.register_write.value = value;
178 203
179 stream.push_back(element); 204 stream.push_back(element);
180} 205}
181 206
182template void Recorder::RegisterWritten(u32,u8); 207template void Recorder::RegisterWritten(u32, u8);
183template void Recorder::RegisterWritten(u32,u16); 208template void Recorder::RegisterWritten(u32, u16);
184template void Recorder::RegisterWritten(u32,u32); 209template void Recorder::RegisterWritten(u32, u32);
185template void Recorder::RegisterWritten(u32,u64); 210template void Recorder::RegisterWritten(u32, u64);
186
187} 211}
diff --git a/src/core/tracer/recorder.h b/src/core/tracer/recorder.h
index febf883c8..6f5354f84 100644
--- a/src/core/tracer/recorder.h
+++ b/src/core/tracer/recorder.h
@@ -54,7 +54,7 @@ public:
54 * Record a register write. 54 * Record a register write.
55 * @note Use this whenever a GPU-related MMIO register has been written to. 55 * @note Use this whenever a GPU-related MMIO register has been written to.
56 */ 56 */
57 template<typename T> 57 template <typename T>
58 void RegisterWritten(u32 physical_address, T value); 58 void RegisterWritten(u32 physical_address, T value);
59 59
60private: 60private: