summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/arm_interface.h10
-rw-r--r--src/core/arm/disassembler/arm_disasm.cpp1292
-rw-r--r--src/core/arm/disassembler/arm_disasm.h89
-rw-r--r--src/core/arm/disassembler/load_symbol_map.cpp4
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp4
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h3
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp12
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h2
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp14
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.h7
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp6292
-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.cpp1813
-rw-r--r--src/core/arm/dyncom/arm_dyncom_trans.h33
-rw-r--r--src/core/arm/skyeye_common/arm_regformat.h2
-rw-r--r--src/core/arm/skyeye_common/armstate.cpp231
-rw-r--r--src/core/arm/skyeye_common/armstate.h104
-rw-r--r--src/core/arm/skyeye_common/armsupp.cpp56
-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.cpp112
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h185
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp262
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp757
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp270
-rw-r--r--src/core/core.cpp8
-rw-r--r--src/core/core.h4
-rw-r--r--src/core/core_timing.cpp33
-rw-r--r--src/core/core_timing.h15
-rw-r--r--src/core/file_sys/archive_backend.cpp35
-rw-r--r--src/core/file_sys/archive_backend.h33
-rw-r--r--src/core/file_sys/archive_extsavedata.cpp23
-rw-r--r--src/core/file_sys/archive_extsavedata.h16
-rw-r--r--src/core/file_sys/archive_romfs.cpp9
-rw-r--r--src/core/file_sys/archive_romfs.h6
-rw-r--r--src/core/file_sys/archive_savedata.cpp40
-rw-r--r--src/core/file_sys/archive_savedata.h5
-rw-r--r--src/core/file_sys/archive_savedatacheck.cpp18
-rw-r--r--src/core/file_sys/archive_savedatacheck.h5
-rw-r--r--src/core/file_sys/archive_sdmc.cpp8
-rw-r--r--src/core/file_sys/archive_sdmc.h5
-rw-r--r--src/core/file_sys/archive_systemsavedata.cpp12
-rw-r--r--src/core/file_sys/archive_systemsavedata.h9
-rw-r--r--src/core/file_sys/directory_backend.h20
-rw-r--r--src/core/file_sys/disk_archive.cpp51
-rw-r--r--src/core/file_sys/disk_archive.h9
-rw-r--r--src/core/file_sys/file_backend.h8
-rw-r--r--src/core/file_sys/ivfc_archive.cpp36
-rw-r--r--src/core/file_sys/ivfc_archive.h27
-rw-r--r--src/core/gdbstub/gdbstub.cpp103
-rw-r--r--src/core/gdbstub/gdbstub.h15
-rw-r--r--src/core/hle/applets/applet.cpp34
-rw-r--r--src/core/hle/applets/applet.h8
-rw-r--r--src/core/hle/applets/erreula.cpp16
-rw-r--r--src/core/hle/applets/erreula.h10
-rw-r--r--src/core/hle/applets/mii_selector.cpp22
-rw-r--r--src/core/hle/applets/mii_selector.h39
-rw-r--r--src/core/hle/applets/swkbd.cpp23
-rw-r--r--src/core/hle/applets/swkbd.h13
-rw-r--r--src/core/hle/config_mem.h26
-rw-r--r--src/core/hle/function_wrappers.h105
-rw-r--r--src/core/hle/hle.cpp7
-rw-r--r--src/core/hle/hle.h2
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp24
-rw-r--r--src/core/hle/kernel/address_arbiter.h15
-rw-r--r--src/core/hle/kernel/client_port.cpp1
-rw-r--r--src/core/hle/kernel/client_port.h24
-rw-r--r--src/core/hle/kernel/event.cpp6
-rw-r--r--src/core/hle/kernel/event.h20
-rw-r--r--src/core/hle/kernel/kernel.cpp5
-rw-r--r--src/core/hle/kernel/kernel.h68
-rw-r--r--src/core/hle/kernel/memory.cpp25
-rw-r--r--src/core/hle/kernel/memory.h3
-rw-r--r--src/core/hle/kernel/mutex.cpp3
-rw-r--r--src/core/hle/kernel/mutex.h20
-rw-r--r--src/core/hle/kernel/process.cpp55
-rw-r--r--src/core/hle/kernel/process.h53
-rw-r--r--src/core/hle/kernel/resource_limit.cpp113
-rw-r--r--src/core/hle/kernel/resource_limit.h47
-rw-r--r--src/core/hle/kernel/semaphore.cpp3
-rw-r--r--src/core/hle/kernel/semaphore.h22
-rw-r--r--src/core/hle/kernel/server_port.cpp6
-rw-r--r--src/core/hle/kernel/server_port.h22
-rw-r--r--src/core/hle/kernel/session.cpp1
-rw-r--r--src/core/hle/kernel/session.h63
-rw-r--r--src/core/hle/kernel/shared_memory.cpp71
-rw-r--r--src/core/hle/kernel/shared_memory.h61
-rw-r--r--src/core/hle/kernel/thread.cpp110
-rw-r--r--src/core/hle/kernel/thread.h82
-rw-r--r--src/core/hle/kernel/timer.cpp18
-rw-r--r--src/core/hle/kernel/timer.h23
-rw-r--r--src/core/hle/kernel/vm_manager.cpp38
-rw-r--r--src/core/hle/kernel/vm_manager.h23
-rw-r--r--src/core/hle/result.h98
-rw-r--r--src/core/hle/service/ac_u.cpp39
-rw-r--r--src/core/hle/service/am/am.cpp58
-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.cpp42
-rw-r--r--src/core/hle/service/am/am_u.cpp68
-rw-r--r--src/core/hle/service/apt/apt.cpp158
-rw-r--r--src/core/hle/service/apt/apt.h96
-rw-r--r--src/core/hle/service/apt/apt_a.cpp56
-rw-r--r--src/core/hle/service/apt/apt_s.cpp170
-rw-r--r--src/core/hle/service/apt/apt_u.cpp176
-rw-r--r--src/core/hle/service/apt/bcfnt/bcfnt.h1
-rw-r--r--src/core/hle/service/boss/boss.cpp5
-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.cpp76
-rw-r--r--src/core/hle/service/cam/cam.h52
-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.cpp10
-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.cpp196
-rw-r--r--src/core/hle/service/cfg/cfg.h26
-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.cpp32
-rw-r--r--src/core/hle/service/csnd_snd.h2
-rw-r--r--src/core/hle/service/dlp/dlp.cpp5
-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.cpp8
-rw-r--r--src/core/hle/service/dsp_dsp.cpp156
-rw-r--r--src/core/hle/service/dsp_dsp.h1
-rw-r--r--src/core/hle/service/err_f.cpp128
-rw-r--r--src/core/hle/service/frd/frd.cpp24
-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.cpp380
-rw-r--r--src/core/hle/service/fs/archive.h67
-rw-r--r--src/core/hle/service/fs/fs_user.cpp386
-rw-r--r--src/core/hle/service/gsp_gpu.cpp251
-rw-r--r--src/core/hle/service/gsp_gpu.h42
-rw-r--r--src/core/hle/service/gsp_lcd.cpp4
-rw-r--r--src/core/hle/service/hid/hid.cpp56
-rw-r--r--src/core/hle/service/hid/hid.h70
-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.cpp29
-rw-r--r--src/core/hle/service/ir/ir_rst.cpp8
-rw-r--r--src/core/hle/service/ir/ir_u.cpp38
-rw-r--r--src/core/hle/service/ir/ir_user.cpp50
-rw-r--r--src/core/hle/service/ldr_ro/cro_helper.cpp357
-rw-r--r--src/core/hle/service/ldr_ro/cro_helper.h146
-rw-r--r--src/core/hle/service/ldr_ro/ldr_ro.cpp215
-rw-r--r--src/core/hle/service/ldr_ro/memory_synchronizer.cpp7
-rw-r--r--src/core/hle/service/ldr_ro/memory_synchronizer.h1
-rw-r--r--src/core/hle/service/mic_u.cpp32
-rw-r--r--src/core/hle/service/ndm/ndm.cpp19
-rw-r--r--src/core/hle/service/ndm/ndm.h43
-rw-r--r--src/core/hle/service/ndm/ndm_u.cpp44
-rw-r--r--src/core/hle/service/news/news.cpp6
-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.cpp6
-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/nim/nim_u.h2
-rw-r--r--src/core/hle/service/ns_s.cpp30
-rw-r--r--src/core/hle/service/nwm_uds.cpp83
-rw-r--r--src/core/hle/service/pm_app.cpp24
-rw-r--r--src/core/hle/service/ptm/ptm.cpp32
-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.cpp53
-rw-r--r--src/core/hle/service/service.h13
-rw-r--r--src/core/hle/service/soc_u.cpp380
-rw-r--r--src/core/hle/service/soc_u.h1
-rw-r--r--src/core/hle/service/srv.cpp51
-rw-r--r--src/core/hle/service/ssl_c.cpp44
-rw-r--r--src/core/hle/service/y2r_u.cpp157
-rw-r--r--src/core/hle/service/y2r_u.h2
-rw-r--r--src/core/hle/shared_page.cpp8
-rw-r--r--src/core/hle/shared_page.h24
-rw-r--r--src/core/hle/svc.cpp518
-rw-r--r--src/core/hw/gpu.cpp151
-rw-r--r--src/core/hw/gpu.h85
-rw-r--r--src/core/hw/hw.cpp17
-rw-r--r--src/core/hw/hw.h42
-rw-r--r--src/core/hw/lcd.cpp16
-rw-r--r--src/core/hw/lcd.h20
-rw-r--r--src/core/hw/y2r.cpp65
-rw-r--r--src/core/hw/y2r.h3
-rw-r--r--src/core/loader/3dsx.cpp87
-rw-r--r--src/core/loader/3dsx.h7
-rw-r--r--src/core/loader/elf.cpp233
-rw-r--r--src/core/loader/elf.h3
-rw-r--r--src/core/loader/loader.cpp17
-rw-r--r--src/core/loader/loader.h10
-rw-r--r--src/core/loader/ncch.cpp64
-rw-r--r--src/core/loader/ncch.h40
-rw-r--r--src/core/loader/smdh.cpp3
-rw-r--r--src/core/loader/smdh.h3
-rw-r--r--src/core/memory.cpp87
-rw-r--r--src/core/memory.h71
-rw-r--r--src/core/memory_setup.h2
-rw-r--r--src/core/mmio.h2
-rw-r--r--src/core/settings.cpp6
-rw-r--r--src/core/settings.h52
-rw-r--r--src/core/system.cpp8
-rw-r--r--src/core/system.h9
-rw-r--r--src/core/tracer/citrace.h9
-rw-r--r--src/core/tracer/recorder.cpp145
-rw-r--r--src/core/tracer/recorder.h7
218 files changed, 10685 insertions, 10727 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 480c90e66..e466b21b2 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -9,14 +9,13 @@
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
16class ARM_Interface : NonCopyable { 16class ARM_Interface : NonCopyable {
17public: 17public:
18 virtual ~ARM_Interface() { 18 virtual ~ARM_Interface() {}
19 }
20 19
21 /** 20 /**
22 * Runs the CPU for the given number of instructions 21 * Runs the CPU for the given number of instructions
@@ -141,10 +140,10 @@ public:
141 return num_instructions; 140 return num_instructions;
142 } 141 }
143 142
144 s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event, decreased by the cpu run loop 143 s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event,
144 /// decreased by the cpu run loop
145 145
146protected: 146protected:
147
148 /** 147 /**
149 * Executes the given number of instructions 148 * Executes the given number of instructions
150 * @param num_instructions Number of instructions to executes 149 * @param num_instructions Number of instructions to executes
@@ -152,6 +151,5 @@ protected:
152 virtual void ExecuteInstructions(int num_instructions) = 0; 151 virtual void ExecuteInstructions(int num_instructions) = 0;
153 152
154private: 153private:
155
156 u64 num_instructions = 0; ///< Number of instructions executed 154 u64 num_instructions = 0; ///< Number of instructions executed
157}; 155};
diff --git a/src/core/arm/disassembler/arm_disasm.cpp b/src/core/arm/disassembler/arm_disasm.cpp
index 5ad1f1c29..05d6ed1fb 100644
--- a/src/core/arm/disassembler/arm_disasm.cpp
+++ b/src/core/arm/disassembler/arm_disasm.cpp
@@ -2,408 +2,230 @@
2 2
3#include <string> 3#include <string>
4#include <unordered_set> 4#include <unordered_set>
5
6#include "common/common_types.h" 5#include "common/common_types.h"
7#include "common/string_util.h" 6#include "common/string_util.h"
8
9#include "core/arm/disassembler/arm_disasm.h" 7#include "core/arm/disassembler/arm_disasm.h"
10#include "core/arm/skyeye_common/armsupp.h" 8#include "core/arm/skyeye_common/armsupp.h"
11 9
12static const char *cond_names[] = { 10static const char* cond_names[] = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
13 "eq", 11 "hi", "ls", "ge", "lt", "gt", "le", "", "RESERVED"};
14 "ne", 12
15 "cs", 13static const char* opcode_names[] = {
16 "cc", 14 "invalid", "undefined", "adc", "add", "and", "b", "bl", "bic",
17 "mi", 15 "bkpt", "blx", "bx", "cdp", "clrex", "clz", "cmn", "cmp",
18 "pl", 16 "eor", "ldc", "ldm", "ldr", "ldrb", "ldrbt", "ldrex", "ldrexb",
19 "vs", 17 "ldrexd", "ldrexh", "ldrh", "ldrsb", "ldrsh", "ldrt", "mcr", "mla",
20 "vc", 18 "mov", "mrc", "mrs", "msr", "mul", "mvn", "nop", "orr",
21 "hi", 19 "pkh", "pld", "qadd16", "qadd8", "qasx", "qsax", "qsub16", "qsub8",
22 "ls", 20 "rev", "rev16", "revsh", "rsb", "rsc", "sadd16", "sadd8", "sasx",
23 "ge", 21 "sbc", "sel", "sev", "shadd16", "shadd8", "shasx", "shsax", "shsub16",
24 "lt", 22 "shsub8", "smlad", "smlal", "smlald", "smlsd", "smlsld", "smmla", "smmls",
25 "gt", 23 "smmul", "smuad", "smull", "smusd", "ssat", "ssat16", "ssax", "ssub16",
26 "le", 24 "ssub8", "stc", "stm", "str", "strb", "strbt", "strex", "strexb",
27 "", 25 "strexd", "strexh", "strh", "strt", "sub", "swi", "swp", "swpb",
28 "RESERVED" 26 "sxtab", "sxtab16", "sxtah", "sxtb", "sxtb16", "sxth", "teq", "tst",
29}; 27 "uadd16", "uadd8", "uasx", "uhadd16", "uhadd8", "uhasx", "uhsax", "uhsub16",
30 28 "uhsub8", "umlal", "umull", "uqadd16", "uqadd8", "uqasx", "uqsax", "uqsub16",
31static const char *opcode_names[] = { 29 "uqsub8", "usad8", "usada8", "usat", "usat16", "usax", "usub16", "usub8",
32 "invalid", 30 "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", 31 "yield",
169 32
170 "undefined", 33 "undefined", "adc", "add", "and", "asr", "b", "bic", "bkpt",
171 "adc", 34 "bl", "blx", "bx", "cmn", "cmp", "eor", "ldmia", "ldr",
172 "add", 35 "ldrb", "ldrh", "ldrsb", "ldrsh", "lsl", "lsr", "mov", "mul",
173 "and", 36 "mvn", "neg", "orr", "pop", "push", "ror", "sbc", "stmia",
174 "asr", 37 "str", "strb", "strh", "sub", "swi", "tst",
175 "b", 38
176 "bic", 39 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 40
212// Indexed by the shift type (bits 6-5) 41// Indexed by the shift type (bits 6-5)
213static const char *shift_names[] = { 42static const char* shift_names[] = {"LSL", "LSR", "ASR", "ROR"};
214 "LSL",
215 "LSR",
216 "ASR",
217 "ROR"
218};
219 43
220static const char* cond_to_str(u32 cond) { 44static const char* cond_to_str(u32 cond) {
221 return cond_names[cond]; 45 return cond_names[cond];
222} 46}
223 47
224std::string ARM_Disasm::Disassemble(u32 addr, u32 insn) 48std::string ARM_Disasm::Disassemble(u32 addr, u32 insn) {
225{
226 Opcode opcode = Decode(insn); 49 Opcode opcode = Decode(insn);
227 switch (opcode) { 50 switch (opcode) {
228 case OP_INVALID: 51 case OP_INVALID:
229 return "Invalid"; 52 return "Invalid";
230 case OP_UNDEFINED: 53 case OP_UNDEFINED:
231 return "Undefined"; 54 return "Undefined";
232 case OP_ADC: 55 case OP_ADC:
233 case OP_ADD: 56 case OP_ADD:
234 case OP_AND: 57 case OP_AND:
235 case OP_BIC: 58 case OP_BIC:
236 case OP_CMN: 59 case OP_CMN:
237 case OP_CMP: 60 case OP_CMP:
238 case OP_EOR: 61 case OP_EOR:
239 case OP_MOV: 62 case OP_MOV:
240 case OP_MVN: 63 case OP_MVN:
241 case OP_ORR: 64 case OP_ORR:
242 case OP_RSB: 65 case OP_RSB:
243 case OP_RSC: 66 case OP_RSC:
244 case OP_SBC: 67 case OP_SBC:
245 case OP_SUB: 68 case OP_SUB:
246 case OP_TEQ: 69 case OP_TEQ:
247 case OP_TST: 70 case OP_TST:
248 return DisassembleALU(opcode, insn); 71 return DisassembleALU(opcode, insn);
249 case OP_B: 72 case OP_B:
250 case OP_BL: 73 case OP_BL:
251 return DisassembleBranch(addr, opcode, insn); 74 return DisassembleBranch(addr, opcode, insn);
252 case OP_BKPT: 75 case OP_BKPT:
253 return DisassembleBKPT(insn); 76 return DisassembleBKPT(insn);
254 case OP_BLX: 77 case OP_BLX:
255 // not supported yet 78 // not supported yet
256 break; 79 break;
257 case OP_BX: 80 case OP_BX:
258 return DisassembleBX(insn); 81 return DisassembleBX(insn);
259 case OP_CDP: 82 case OP_CDP:
260 return "cdp"; 83 return "cdp";
261 case OP_CLREX: 84 case OP_CLREX:
262 return "clrex"; 85 return "clrex";
263 case OP_CLZ: 86 case OP_CLZ:
264 return DisassembleCLZ(insn); 87 return DisassembleCLZ(insn);
265 case OP_LDC: 88 case OP_LDC:
266 return "ldc"; 89 return "ldc";
267 case OP_LDM: 90 case OP_LDM:
268 case OP_STM: 91 case OP_STM:
269 return DisassembleMemblock(opcode, insn); 92 return DisassembleMemblock(opcode, insn);
270 case OP_LDR: 93 case OP_LDR:
271 case OP_LDRB: 94 case OP_LDRB:
272 case OP_LDRBT: 95 case OP_LDRBT:
273 case OP_LDRT: 96 case OP_LDRT:
274 case OP_STR: 97 case OP_STR:
275 case OP_STRB: 98 case OP_STRB:
276 case OP_STRBT: 99 case OP_STRBT:
277 case OP_STRT: 100 case OP_STRT:
278 return DisassembleMem(insn); 101 return DisassembleMem(insn);
279 case OP_LDREX: 102 case OP_LDREX:
280 case OP_LDREXB: 103 case OP_LDREXB:
281 case OP_LDREXD: 104 case OP_LDREXD:
282 case OP_LDREXH: 105 case OP_LDREXH:
283 case OP_STREX: 106 case OP_STREX:
284 case OP_STREXB: 107 case OP_STREXB:
285 case OP_STREXD: 108 case OP_STREXD:
286 case OP_STREXH: 109 case OP_STREXH:
287 return DisassembleREX(opcode, insn); 110 return DisassembleREX(opcode, insn);
288 case OP_LDRH: 111 case OP_LDRH:
289 case OP_LDRSB: 112 case OP_LDRSB:
290 case OP_LDRSH: 113 case OP_LDRSH:
291 case OP_STRH: 114 case OP_STRH:
292 return DisassembleMemHalf(insn); 115 return DisassembleMemHalf(insn);
293 case OP_MCR: 116 case OP_MCR:
294 case OP_MRC: 117 case OP_MRC:
295 return DisassembleMCR(opcode, insn); 118 return DisassembleMCR(opcode, insn);
296 case OP_MLA: 119 case OP_MLA:
297 return DisassembleMLA(opcode, insn); 120 return DisassembleMLA(opcode, insn);
298 case OP_MRS: 121 case OP_MRS:
299 return DisassembleMRS(insn); 122 return DisassembleMRS(insn);
300 case OP_MSR: 123 case OP_MSR:
301 return DisassembleMSR(insn); 124 return DisassembleMSR(insn);
302 case OP_MUL: 125 case OP_MUL:
303 return DisassembleMUL(opcode, insn); 126 return DisassembleMUL(opcode, insn);
304 case OP_NOP: 127 case OP_NOP:
305 case OP_SEV: 128 case OP_SEV:
306 case OP_WFE: 129 case OP_WFE:
307 case OP_WFI: 130 case OP_WFI:
308 case OP_YIELD: 131 case OP_YIELD:
309 return DisassembleNoOperands(opcode, insn); 132 return DisassembleNoOperands(opcode, insn);
310 case OP_PKH: 133 case OP_PKH:
311 return DisassemblePKH(insn); 134 return DisassemblePKH(insn);
312 case OP_PLD: 135 case OP_PLD:
313 return DisassemblePLD(insn); 136 return DisassemblePLD(insn);
314 case OP_QADD16: 137 case OP_QADD16:
315 case OP_QADD8: 138 case OP_QADD8:
316 case OP_QASX: 139 case OP_QASX:
317 case OP_QSAX: 140 case OP_QSAX:
318 case OP_QSUB16: 141 case OP_QSUB16:
319 case OP_QSUB8: 142 case OP_QSUB8:
320 case OP_SADD16: 143 case OP_SADD16:
321 case OP_SADD8: 144 case OP_SADD8:
322 case OP_SASX: 145 case OP_SASX:
323 case OP_SHADD16: 146 case OP_SHADD16:
324 case OP_SHADD8: 147 case OP_SHADD8:
325 case OP_SHASX: 148 case OP_SHASX:
326 case OP_SHSAX: 149 case OP_SHSAX:
327 case OP_SHSUB16: 150 case OP_SHSUB16:
328 case OP_SHSUB8: 151 case OP_SHSUB8:
329 case OP_SSAX: 152 case OP_SSAX:
330 case OP_SSUB16: 153 case OP_SSUB16:
331 case OP_SSUB8: 154 case OP_SSUB8:
332 case OP_UADD16: 155 case OP_UADD16:
333 case OP_UADD8: 156 case OP_UADD8:
334 case OP_UASX: 157 case OP_UASX:
335 case OP_UHADD16: 158 case OP_UHADD16:
336 case OP_UHADD8: 159 case OP_UHADD8:
337 case OP_UHASX: 160 case OP_UHASX:
338 case OP_UHSAX: 161 case OP_UHSAX:
339 case OP_UHSUB16: 162 case OP_UHSUB16:
340 case OP_UHSUB8: 163 case OP_UHSUB8:
341 case OP_UQADD16: 164 case OP_UQADD16:
342 case OP_UQADD8: 165 case OP_UQADD8:
343 case OP_UQASX: 166 case OP_UQASX:
344 case OP_UQSAX: 167 case OP_UQSAX:
345 case OP_UQSUB16: 168 case OP_UQSUB16:
346 case OP_UQSUB8: 169 case OP_UQSUB8:
347 case OP_USAX: 170 case OP_USAX:
348 case OP_USUB16: 171 case OP_USUB16:
349 case OP_USUB8: 172 case OP_USUB8:
350 return DisassembleParallelAddSub(opcode, insn); 173 return DisassembleParallelAddSub(opcode, insn);
351 case OP_REV: 174 case OP_REV:
352 case OP_REV16: 175 case OP_REV16:
353 case OP_REVSH: 176 case OP_REVSH:
354 return DisassembleREV(opcode, insn); 177 return DisassembleREV(opcode, insn);
355 case OP_SEL: 178 case OP_SEL:
356 return DisassembleSEL(insn); 179 return DisassembleSEL(insn);
357 case OP_SMLAD: 180 case OP_SMLAD:
358 case OP_SMLALD: 181 case OP_SMLALD:
359 case OP_SMLSD: 182 case OP_SMLSD:
360 case OP_SMLSLD: 183 case OP_SMLSLD:
361 case OP_SMMLA: 184 case OP_SMMLA:
362 case OP_SMMLS: 185 case OP_SMMLS:
363 case OP_SMMUL: 186 case OP_SMMUL:
364 case OP_SMUAD: 187 case OP_SMUAD:
365 case OP_SMUSD: 188 case OP_SMUSD:
366 case OP_USAD8: 189 case OP_USAD8:
367 case OP_USADA8: 190 case OP_USADA8:
368 return DisassembleMediaMulDiv(opcode, insn); 191 return DisassembleMediaMulDiv(opcode, insn);
369 case OP_SSAT: 192 case OP_SSAT:
370 case OP_SSAT16: 193 case OP_SSAT16:
371 case OP_USAT: 194 case OP_USAT:
372 case OP_USAT16: 195 case OP_USAT16:
373 return DisassembleSAT(opcode, insn); 196 return DisassembleSAT(opcode, insn);
374 case OP_STC: 197 case OP_STC:
375 return "stc"; 198 return "stc";
376 case OP_SWI: 199 case OP_SWI:
377 return DisassembleSWI(insn); 200 return DisassembleSWI(insn);
378 case OP_SWP: 201 case OP_SWP:
379 case OP_SWPB: 202 case OP_SWPB:
380 return DisassembleSWP(opcode, insn); 203 return DisassembleSWP(opcode, insn);
381 case OP_SXTAB: 204 case OP_SXTAB:
382 case OP_SXTAB16: 205 case OP_SXTAB16:
383 case OP_SXTAH: 206 case OP_SXTAH:
384 case OP_SXTB: 207 case OP_SXTB:
385 case OP_SXTB16: 208 case OP_SXTB16:
386 case OP_SXTH: 209 case OP_SXTH:
387 case OP_UXTAB: 210 case OP_UXTAB:
388 case OP_UXTAB16: 211 case OP_UXTAB16:
389 case OP_UXTAH: 212 case OP_UXTAH:
390 case OP_UXTB: 213 case OP_UXTB:
391 case OP_UXTB16: 214 case OP_UXTB16:
392 case OP_UXTH: 215 case OP_UXTH:
393 return DisassembleXT(opcode, insn); 216 return DisassembleXT(opcode, insn);
394 case OP_UMLAL: 217 case OP_UMLAL:
395 case OP_UMULL: 218 case OP_UMULL:
396 case OP_SMLAL: 219 case OP_SMLAL:
397 case OP_SMULL: 220 case OP_SMULL:
398 return DisassembleUMLAL(opcode, insn); 221 return DisassembleUMLAL(opcode, insn);
399 default: 222 default:
400 return "Error"; 223 return "Error";
401 } 224 }
402 return nullptr; 225 return nullptr;
403} 226}
404 227
405std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn) 228std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn) {
406{
407 static const u8 kNoOperand1 = 1; 229 static const u8 kNoOperand1 = 1;
408 static const u8 kNoDest = 2; 230 static const u8 kNoDest = 2;
409 static const u8 kNoSbit = 4; 231 static const u8 kNoSbit = 4;
@@ -421,18 +243,18 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn)
421 243
422 const char* opname = opcode_names[opcode]; 244 const char* opname = opcode_names[opcode];
423 switch (opcode) { 245 switch (opcode) {
424 case OP_CMN: 246 case OP_CMN:
425 case OP_CMP: 247 case OP_CMP:
426 case OP_TEQ: 248 case OP_TEQ:
427 case OP_TST: 249 case OP_TST:
428 flags = kNoDest | kNoSbit; 250 flags = kNoDest | kNoSbit;
429 break; 251 break;
430 case OP_MOV: 252 case OP_MOV:
431 case OP_MVN: 253 case OP_MVN:
432 flags = kNoOperand1; 254 flags = kNoOperand1;
433 break; 255 break;
434 default: 256 default:
435 break; 257 break;
436 } 258 }
437 259
438 // The "mov" instruction ignores the first operand (rn). 260 // The "mov" instruction ignores the first operand (rn).
@@ -448,13 +270,13 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn)
448 rd_str = Common::StringFromFormat("r%d, ", rd); 270 rd_str = Common::StringFromFormat("r%d, ", rd);
449 } 271 }
450 272
451 const char *sbit_str = ""; 273 const char* sbit_str = "";
452 if (bit_s && !(flags & kNoSbit)) 274 if (bit_s && !(flags & kNoSbit))
453 sbit_str = "s"; 275 sbit_str = "s";
454 276
455 if (is_immed) { 277 if (is_immed) {
456 return Common::StringFromFormat("%s%s%s\t%s%s#%u ; 0x%x", 278 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); 279 sbit_str, rd_str.c_str(), rn_str.c_str(), immed, immed);
458 } 280 }
459 281
460 u8 shift_is_reg = (insn >> 4) & 1; 282 u8 shift_is_reg = (insn >> 4) & 1;
@@ -468,30 +290,28 @@ std::string ARM_Disasm::DisassembleALU(Opcode opcode, u32 insn)
468 rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2)); 290 rotated_val = (rotated_val >> rotate2) | (rotated_val << (32 - rotate2));
469 291
470 if (!shift_is_reg && shift_type == 0 && shift_amount == 0) { 292 if (!shift_is_reg && shift_type == 0 && shift_amount == 0) {
471 return Common::StringFromFormat("%s%s%s\t%s%sr%d", 293 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); 294 rd_str.c_str(), rn_str.c_str(), rm);
473 } 295 }
474 296
475 const char *shift_name = shift_names[shift_type]; 297 const char* shift_name = shift_names[shift_type];
476 if (shift_is_reg) { 298 if (shift_is_reg) {
477 return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s r%d", 299 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, 300 sbit_str, rd_str.c_str(), rn_str.c_str(), rm, shift_name,
479 shift_name, rs); 301 rs);
480 } 302 }
481 if (shift_amount == 0) { 303 if (shift_amount == 0) {
482 if (shift_type == 3) { 304 if (shift_type == 3) {
483 return Common::StringFromFormat("%s%s%s\t%s%sr%d, RRX", 305 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); 306 sbit_str, rd_str.c_str(), rn_str.c_str(), rm);
485 } 307 }
486 shift_amount = 32; 308 shift_amount = 32;
487 } 309 }
488 return Common::StringFromFormat("%s%s%s\t%s%sr%d, %s #%u", 310 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, 311 rd_str.c_str(), rn_str.c_str(), rm, shift_name, shift_amount);
490 shift_name, shift_amount);
491} 312}
492 313
493std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn) 314std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn) {
494{
495 u8 cond = (insn >> 28) & 0xf; 315 u8 cond = (insn >> 28) & 0xf;
496 u32 offset = insn & 0xffffff; 316 u32 offset = insn & 0xffffff;
497 // Sign-extend the 24-bit offset 317 // Sign-extend the 24-bit offset
@@ -502,26 +322,23 @@ std::string ARM_Disasm::DisassembleBranch(u32 addr, Opcode opcode, u32 insn)
502 offset <<= 2; 322 offset <<= 2;
503 offset += 8; 323 offset += 8;
504 addr += offset; 324 addr += offset;
505 const char *opname = opcode_names[opcode]; 325 const char* opname = opcode_names[opcode];
506 return Common::StringFromFormat("%s%s\t0x%x", opname, cond_to_str(cond), addr); 326 return Common::StringFromFormat("%s%s\t0x%x", opname, cond_to_str(cond), addr);
507} 327}
508 328
509std::string ARM_Disasm::DisassembleBX(u32 insn) 329std::string ARM_Disasm::DisassembleBX(u32 insn) {
510{
511 u8 cond = (insn >> 28) & 0xf; 330 u8 cond = (insn >> 28) & 0xf;
512 u8 rn = insn & 0xf; 331 u8 rn = insn & 0xf;
513 return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn); 332 return Common::StringFromFormat("bx%s\tr%d", cond_to_str(cond), rn);
514} 333}
515 334
516std::string ARM_Disasm::DisassembleBKPT(u32 insn) 335std::string ARM_Disasm::DisassembleBKPT(u32 insn) {
517{
518 u8 cond = (insn >> 28) & 0xf; 336 u8 cond = (insn >> 28) & 0xf;
519 u32 immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf); 337 u32 immed = (((insn >> 8) & 0xfff) << 4) | (insn & 0xf);
520 return Common::StringFromFormat("bkpt%s\t#%d", cond_to_str(cond), immed); 338 return Common::StringFromFormat("bkpt%s\t#%d", cond_to_str(cond), immed);
521} 339}
522 340
523std::string ARM_Disasm::DisassembleCLZ(u32 insn) 341std::string ARM_Disasm::DisassembleCLZ(u32 insn) {
524{
525 u8 cond = (insn >> 28) & 0xf; 342 u8 cond = (insn >> 28) & 0xf;
526 u8 rd = (insn >> 12) & 0xf; 343 u8 rd = (insn >> 12) & 0xf;
527 u8 rm = insn & 0xf; 344 u8 rm = insn & 0xf;
@@ -545,9 +362,8 @@ std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, u32 insn) {
545 } 362 }
546 363
547 std::string ext_reg = ""; 364 std::string ext_reg = "";
548 std::unordered_set<Opcode, std::hash<int>> with_ext_reg = { 365 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 366 OP_SMMLS, OP_USADA8};
550 };
551 if (with_ext_reg.find(opcode) != with_ext_reg.end()) 367 if (with_ext_reg.find(opcode) != with_ext_reg.end())
552 ext_reg = Common::StringFromFormat(", r%u", ra); 368 ext_reg = Common::StringFromFormat(", r%u", ra);
553 369
@@ -560,8 +376,7 @@ std::string ARM_Disasm::DisassembleMediaMulDiv(Opcode opcode, u32 insn) {
560 ext_reg.c_str()); 376 ext_reg.c_str());
561} 377}
562 378
563std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn) 379std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn) {
564{
565 std::string tmp_list; 380 std::string tmp_list;
566 381
567 u8 cond = (insn >> 28) & 0xf; 382 u8 cond = (insn >> 28) & 0xf;
@@ -572,17 +387,17 @@ std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn)
572 u8 rn = (insn >> 16) & 0xf; 387 u8 rn = (insn >> 16) & 0xf;
573 u16 reg_list = insn & 0xffff; 388 u16 reg_list = insn & 0xffff;
574 389
575 const char *opname = opcode_names[opcode]; 390 const char* opname = opcode_names[opcode];
576 391
577 const char *bang = ""; 392 const char* bang = "";
578 if (write_back) 393 if (write_back)
579 bang = "!"; 394 bang = "!";
580 395
581 const char *carret = ""; 396 const char* carret = "";
582 if (bit_s) 397 if (bit_s)
583 carret = "^"; 398 carret = "^";
584 399
585 const char *comma = ""; 400 const char* comma = "";
586 tmp_list[0] = 0; 401 tmp_list[0] = 0;
587 for (int ii = 0; ii < 16; ++ii) { 402 for (int ii = 0; ii < 16; ++ii) {
588 if (reg_list & (1 << ii)) { 403 if (reg_list & (1 << ii)) {
@@ -591,7 +406,7 @@ std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn)
591 } 406 }
592 } 407 }
593 408
594 const char *addr_mode = ""; 409 const char* addr_mode = "";
595 if (is_pre) { 410 if (is_pre) {
596 if (is_up) { 411 if (is_up) {
597 addr_mode = "ib"; 412 addr_mode = "ib";
@@ -606,12 +421,11 @@ std::string ARM_Disasm::DisassembleMemblock(Opcode opcode, u32 insn)
606 } 421 }
607 } 422 }
608 423
609 return Common::StringFromFormat("%s%s%s\tr%d%s, {%s}%s", 424 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); 425 rn, bang, tmp_list.c_str(), carret);
611} 426}
612 427
613std::string ARM_Disasm::DisassembleMem(u32 insn) 428std::string ARM_Disasm::DisassembleMem(u32 insn) {
614{
615 u8 cond = (insn >> 28) & 0xf; 429 u8 cond = (insn >> 28) & 0xf;
616 u8 is_reg = (insn >> 25) & 0x1; 430 u8 is_reg = (insn >> 25) & 0x1;
617 u8 is_load = (insn >> 20) & 0x1; 431 u8 is_load = (insn >> 20) & 0x1;
@@ -623,38 +437,40 @@ std::string ARM_Disasm::DisassembleMem(u32 insn)
623 u8 rd = (insn >> 12) & 0xf; 437 u8 rd = (insn >> 12) & 0xf;
624 u16 offset = insn & 0xfff; 438 u16 offset = insn & 0xfff;
625 439
626 const char *opname = "ldr"; 440 const char* opname = "ldr";
627 if (!is_load) 441 if (!is_load)
628 opname = "str"; 442 opname = "str";
629 443
630 const char *bang = ""; 444 const char* bang = "";
631 if (write_back) 445 if (write_back)
632 bang = "!"; 446 bang = "!";
633 447
634 const char *minus = ""; 448 const char* minus = "";
635 if (is_up == 0) 449 if (is_up == 0)
636 minus = "-"; 450 minus = "-";
637 451
638 const char *byte = ""; 452 const char* byte = "";
639 if (is_byte) 453 if (is_byte)
640 byte = "b"; 454 byte = "b";
641 455
642 if (is_reg == 0) { 456 if (is_reg == 0) {
643 if (is_pre) { 457 if (is_pre) {
644 if (offset == 0) { 458 if (offset == 0) {
645 return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", 459 return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond),
646 opname, cond_to_str(cond), byte, rd, rn); 460 byte, rd, rn);
647 } else { 461 } else {
648 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", 462 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); 463 cond_to_str(cond), byte, rd, rn, minus, offset,
464 bang);
650 } 465 }
651 } else { 466 } else {
652 const char *transfer = ""; 467 const char* transfer = "";
653 if (write_back) 468 if (write_back)
654 transfer = "t"; 469 transfer = "t";
655 470
656 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], #%s%u", 471 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); 472 cond_to_str(cond), byte, transfer, rd, rn, minus,
473 offset);
658 } 474 }
659 } 475 }
660 476
@@ -662,48 +478,47 @@ std::string ARM_Disasm::DisassembleMem(u32 insn)
662 u8 shift_type = (insn >> 5) & 0x3; 478 u8 shift_type = (insn >> 5) & 0x3;
663 u8 shift_amount = (insn >> 7) & 0x1f; 479 u8 shift_amount = (insn >> 7) & 0x1f;
664 480
665 const char *shift_name = shift_names[shift_type]; 481 const char* shift_name = shift_names[shift_type];
666 482
667 if (is_pre) { 483 if (is_pre) {
668 if (shift_amount == 0) { 484 if (shift_amount == 0) {
669 if (shift_type == 0) { 485 if (shift_type == 0) {
670 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", 486 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); 487 cond_to_str(cond), byte, rd, rn, minus, rm, bang);
672 } 488 }
673 if (shift_type == 3) { 489 if (shift_type == 3) {
674 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, RRX]%s", 490 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); 491 cond_to_str(cond), byte, rd, rn, minus, rm, bang);
676 } 492 }
677 shift_amount = 32; 493 shift_amount = 32;
678 } 494 }
679 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d, %s #%u]%s", 495 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, 496 cond_to_str(cond), byte, rd, rn, minus, rm, shift_name,
681 shift_name, shift_amount, bang); 497 shift_amount, bang);
682 } 498 }
683 499
684 const char *transfer = ""; 500 const char* transfer = "";
685 if (write_back) 501 if (write_back)
686 transfer = "t"; 502 transfer = "t";
687 503
688 if (shift_amount == 0) { 504 if (shift_amount == 0) {
689 if (shift_type == 0) { 505 if (shift_type == 0) {
690 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d", 506 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); 507 cond_to_str(cond), byte, transfer, rd, rn, minus, rm);
692 } 508 }
693 if (shift_type == 3) { 509 if (shift_type == 3) {
694 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, RRX", 510 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); 511 cond_to_str(cond), byte, transfer, rd, rn, minus, rm);
696 } 512 }
697 shift_amount = 32; 513 shift_amount = 32;
698 } 514 }
699 515
700 return Common::StringFromFormat("%s%s%s%s\tr%d, [r%d], %sr%d, %s #%u", 516 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, 517 cond_to_str(cond), byte, transfer, rd, rn, minus, rm,
702 shift_name, shift_amount); 518 shift_name, shift_amount);
703} 519}
704 520
705std::string ARM_Disasm::DisassembleMemHalf(u32 insn) 521std::string ARM_Disasm::DisassembleMemHalf(u32 insn) {
706{
707 u8 cond = (insn >> 28) & 0xf; 522 u8 cond = (insn >> 28) & 0xf;
708 u8 is_load = (insn >> 20) & 0x1; 523 u8 is_load = (insn >> 20) & 0x1;
709 u8 write_back = (insn >> 21) & 0x1; 524 u8 write_back = (insn >> 21) & 0x1;
@@ -716,11 +531,11 @@ std::string ARM_Disasm::DisassembleMemHalf(u32 insn)
716 u8 rm = insn & 0xf; 531 u8 rm = insn & 0xf;
717 u8 offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf); 532 u8 offset = (((insn >> 8) & 0xf) << 4) | (insn & 0xf);
718 533
719 const char *opname = "ldr"; 534 const char* opname = "ldr";
720 if (is_load == 0) 535 if (is_load == 0)
721 opname = "str"; 536 opname = "str";
722 537
723 const char *width = ""; 538 const char* width = "";
724 if (bits_65 == 1) 539 if (bits_65 == 1)
725 width = "h"; 540 width = "h";
726 else if (bits_65 == 2) 541 else if (bits_65 == 2)
@@ -728,38 +543,39 @@ std::string ARM_Disasm::DisassembleMemHalf(u32 insn)
728 else 543 else
729 width = "sh"; 544 width = "sh";
730 545
731 const char *bang = ""; 546 const char* bang = "";
732 if (write_back) 547 if (write_back)
733 bang = "!"; 548 bang = "!";
734 const char *minus = ""; 549 const char* minus = "";
735 if (is_up == 0) 550 if (is_up == 0)
736 minus = "-"; 551 minus = "-";
737 552
738 if (is_immed) { 553 if (is_immed) {
739 if (is_pre) { 554 if (is_pre) {
740 if (offset == 0) { 555 if (offset == 0) {
741 return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond), width, rd, rn); 556 return Common::StringFromFormat("%s%s%s\tr%d, [r%d]", opname, cond_to_str(cond),
557 width, rd, rn);
742 } else { 558 } else {
743 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, #%s%u]%s", 559 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); 560 cond_to_str(cond), width, rd, rn, minus, offset,
561 bang);
745 } 562 }
746 } else { 563 } else {
747 return Common::StringFromFormat("%s%s%s\tr%d, [r%d], #%s%u", 564 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); 565 width, rd, rn, minus, offset);
749 } 566 }
750 } 567 }
751 568
752 if (is_pre) { 569 if (is_pre) {
753 return Common::StringFromFormat("%s%s%s\tr%d, [r%d, %sr%d]%s", 570 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); 571 width, rd, rn, minus, rm, bang);
755 } else { 572 } else {
756 return Common::StringFromFormat("%s%s%s\tr%d, [r%d], %sr%d", 573 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); 574 width, rd, rn, minus, rm);
758 } 575 }
759} 576}
760 577
761std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn) 578std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn) {
762{
763 u8 cond = (insn >> 28) & 0xf; 579 u8 cond = (insn >> 28) & 0xf;
764 u8 crn = (insn >> 16) & 0xf; 580 u8 crn = (insn >> 16) & 0xf;
765 u8 crd = (insn >> 12) & 0xf; 581 u8 crd = (insn >> 12) & 0xf;
@@ -767,13 +583,12 @@ std::string ARM_Disasm::DisassembleMCR(Opcode opcode, u32 insn)
767 u8 opcode2 = (insn >> 5) & 0x7; 583 u8 opcode2 = (insn >> 5) & 0x7;
768 u8 crm = insn & 0xf; 584 u8 crm = insn & 0xf;
769 585
770 const char *opname = opcode_names[opcode]; 586 const char* opname = opcode_names[opcode];
771 return Common::StringFromFormat("%s%s\t%d, 0, r%d, cr%d, cr%d, {%d}", 587 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); 588 cpnum, crd, crn, crm, opcode2);
773} 589}
774 590
775std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn) 591std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn) {
776{
777 u8 cond = (insn >> 28) & 0xf; 592 u8 cond = (insn >> 28) & 0xf;
778 u8 rd = (insn >> 16) & 0xf; 593 u8 rd = (insn >> 16) & 0xf;
779 u8 rn = (insn >> 12) & 0xf; 594 u8 rn = (insn >> 12) & 0xf;
@@ -781,13 +596,12 @@ std::string ARM_Disasm::DisassembleMLA(Opcode opcode, u32 insn)
781 u8 rm = insn & 0xf; 596 u8 rm = insn & 0xf;
782 u8 bit_s = (insn >> 20) & 1; 597 u8 bit_s = (insn >> 20) & 1;
783 598
784 const char *opname = opcode_names[opcode]; 599 const char* opname = opcode_names[opcode];
785 return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", 600 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); 601 bit_s ? "s" : "", rd, rm, rs, rn);
787} 602}
788 603
789std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn) 604std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn) {
790{
791 u8 cond = (insn >> 28) & 0xf; 605 u8 cond = (insn >> 28) & 0xf;
792 u8 rdhi = (insn >> 16) & 0xf; 606 u8 rdhi = (insn >> 16) & 0xf;
793 u8 rdlo = (insn >> 12) & 0xf; 607 u8 rdlo = (insn >> 12) & 0xf;
@@ -795,26 +609,24 @@ std::string ARM_Disasm::DisassembleUMLAL(Opcode opcode, u32 insn)
795 u8 rm = insn & 0xf; 609 u8 rm = insn & 0xf;
796 u8 bit_s = (insn >> 20) & 1; 610 u8 bit_s = (insn >> 20) & 1;
797 611
798 const char *opname = opcode_names[opcode]; 612 const char* opname = opcode_names[opcode];
799 return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d, r%d", 613 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); 614 bit_s ? "s" : "", rdlo, rdhi, rm, rs);
801} 615}
802 616
803std::string ARM_Disasm::DisassembleMUL(Opcode opcode, u32 insn) 617std::string ARM_Disasm::DisassembleMUL(Opcode opcode, u32 insn) {
804{
805 u8 cond = (insn >> 28) & 0xf; 618 u8 cond = (insn >> 28) & 0xf;
806 u8 rd = (insn >> 16) & 0xf; 619 u8 rd = (insn >> 16) & 0xf;
807 u8 rs = (insn >> 8) & 0xf; 620 u8 rs = (insn >> 8) & 0xf;
808 u8 rm = insn & 0xf; 621 u8 rm = insn & 0xf;
809 u8 bit_s = (insn >> 20) & 1; 622 u8 bit_s = (insn >> 20) & 1;
810 623
811 const char *opname = opcode_names[opcode]; 624 const char* opname = opcode_names[opcode];
812 return Common::StringFromFormat("%s%s%s\tr%d, r%d, r%d", 625 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); 626 bit_s ? "s" : "", rd, rm, rs);
814} 627}
815 628
816std::string ARM_Disasm::DisassembleMRS(u32 insn) 629std::string ARM_Disasm::DisassembleMRS(u32 insn) {
817{
818 u8 cond = (insn >> 28) & 0xf; 630 u8 cond = (insn >> 28) & 0xf;
819 u8 rd = (insn >> 12) & 0xf; 631 u8 rd = (insn >> 12) & 0xf;
820 u8 ps = (insn >> 22) & 1; 632 u8 ps = (insn >> 22) & 1;
@@ -822,8 +634,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"); 634 return Common::StringFromFormat("mrs%s\tr%d, %s", cond_to_str(cond), rd, ps ? "spsr" : "cpsr");
823} 635}
824 636
825std::string ARM_Disasm::DisassembleMSR(u32 insn) 637std::string ARM_Disasm::DisassembleMSR(u32 insn) {
826{
827 char flags[8]; 638 char flags[8];
828 int flag_index = 0; 639 int flag_index = 0;
829 u8 cond = (insn >> 28) & 0xf; 640 u8 cond = (insn >> 28) & 0xf;
@@ -846,18 +657,17 @@ std::string ARM_Disasm::DisassembleMSR(u32 insn)
846 u8 rotate = (insn >> 8) & 0xf; 657 u8 rotate = (insn >> 8) & 0xf;
847 u8 rotate2 = rotate << 1; 658 u8 rotate2 = rotate << 1;
848 u32 rotated_val = (immed >> rotate2) | (immed << (32 - rotate2)); 659 u32 rotated_val = (immed >> rotate2) | (immed << (32 - rotate2));
849 return Common::StringFromFormat("msr%s\t%s_%s, #0x%x", 660 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); 661 pd ? "spsr" : "cpsr", flags, rotated_val);
851 } 662 }
852 663
853 u8 rm = insn & 0xf; 664 u8 rm = insn & 0xf;
854 665
855 return Common::StringFromFormat("msr%s\t%s_%s, r%d", 666 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); 667 flags, rm);
857} 668}
858 669
859std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, u32 insn) 670std::string ARM_Disasm::DisassembleNoOperands(Opcode opcode, u32 insn) {
860{
861 u32 cond = BITS(insn, 28, 31); 671 u32 cond = BITS(insn, 28, 31);
862 return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond)); 672 return Common::StringFromFormat("%s%s", opcode_names[opcode], cond_to_str(cond));
863} 673}
@@ -872,8 +682,7 @@ std::string ARM_Disasm::DisassembleParallelAddSub(Opcode opcode, u32 insn) {
872 rd, rn, rm); 682 rd, rn, rm);
873} 683}
874 684
875std::string ARM_Disasm::DisassemblePKH(u32 insn) 685std::string ARM_Disasm::DisassemblePKH(u32 insn) {
876{
877 u32 cond = BITS(insn, 28, 31); 686 u32 cond = BITS(insn, 28, 31);
878 u32 rn = BITS(insn, 16, 19); 687 u32 rn = BITS(insn, 16, 19);
879 u32 rd = BITS(insn, 12, 15); 688 u32 rd = BITS(insn, 12, 15);
@@ -896,13 +705,12 @@ std::string ARM_Disasm::DisassemblePKH(u32 insn)
896 rd, rn, rm, shift.c_str()); 705 rd, rn, rm, shift.c_str());
897} 706}
898 707
899std::string ARM_Disasm::DisassemblePLD(u32 insn) 708std::string ARM_Disasm::DisassemblePLD(u32 insn) {
900{
901 u8 is_reg = (insn >> 25) & 0x1; 709 u8 is_reg = (insn >> 25) & 0x1;
902 u8 is_up = (insn >> 23) & 0x1; 710 u8 is_up = (insn >> 23) & 0x1;
903 u8 rn = (insn >> 16) & 0xf; 711 u8 rn = (insn >> 16) & 0xf;
904 712
905 const char *minus = ""; 713 const char* minus = "";
906 if (is_up == 0) 714 if (is_up == 0)
907 minus = "-"; 715 minus = "-";
908 716
@@ -924,8 +732,8 @@ std::string ARM_Disasm::DisassembleREV(Opcode opcode, u32 insn) {
924 u32 rd = BITS(insn, 12, 15); 732 u32 rd = BITS(insn, 12, 15);
925 u32 rm = BITS(insn, 0, 3); 733 u32 rm = BITS(insn, 0, 3);
926 734
927 return Common::StringFromFormat("%s%s\tr%u, r%u", opcode_names[opcode], cond_to_str(cond), 735 return Common::StringFromFormat("%s%s\tr%u, r%u", opcode_names[opcode], cond_to_str(cond), rd,
928 rd, rm); 736 rm);
929} 737}
930 738
931std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) { 739std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) {
@@ -935,26 +743,26 @@ std::string ARM_Disasm::DisassembleREX(Opcode opcode, u32 insn) {
935 u32 cond = BITS(insn, 28, 31); 743 u32 cond = BITS(insn, 28, 31);
936 744
937 switch (opcode) { 745 switch (opcode) {
938 case OP_STREX: 746 case OP_STREX:
939 case OP_STREXB: 747 case OP_STREXB:
940 case OP_STREXH: 748 case OP_STREXH:
941 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], 749 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode],
942 cond_to_str(cond), rd, rt, rn); 750 cond_to_str(cond), rd, rt, rn);
943 case OP_STREXD: 751 case OP_STREXD:
944 return Common::StringFromFormat("%s%s\tr%d, r%d, r%d, [r%d]", opcode_names[opcode], 752 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); 753 cond_to_str(cond), rd, rt, rt + 1, rn);
946 754
947 // for LDREX instructions, rd corresponds to Rt from reference manual 755 // for LDREX instructions, rd corresponds to Rt from reference manual
948 case OP_LDREX: 756 case OP_LDREX:
949 case OP_LDREXB: 757 case OP_LDREXB:
950 case OP_LDREXH: 758 case OP_LDREXH:
951 return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode], 759 return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode], cond_to_str(cond),
952 cond_to_str(cond), rd, rn); 760 rd, rn);
953 case OP_LDREXD: 761 case OP_LDREXD:
954 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode], 762 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode],
955 cond_to_str(cond), rd, rd + 1, rn); 763 cond_to_str(cond), rd, rd + 1, rn);
956 default: 764 default:
957 return opcode_names[OP_UNDEFINED]; 765 return opcode_names[OP_UNDEFINED];
958 } 766 }
959} 767}
960 768
@@ -982,8 +790,8 @@ std::string ARM_Disasm::DisassembleSAT(Opcode opcode, u32 insn) {
982 if (opcode == OP_SSAT || opcode == OP_SSAT16) 790 if (opcode == OP_SSAT || opcode == OP_SSAT16)
983 sat_imm++; 791 sat_imm++;
984 792
985 return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode], cond_to_str(cond), rd, 793 return Common::StringFromFormat("%s%s\tr%u, #%u, r%u%s", opcode_names[opcode],
986 sat_imm, rn, shift_part.c_str()); 794 cond_to_str(cond), rd, sat_imm, rn, shift_part.c_str());
987} 795}
988 796
989std::string ARM_Disasm::DisassembleSEL(u32 insn) { 797std::string ARM_Disasm::DisassembleSEL(u32 insn) {
@@ -996,27 +804,24 @@ std::string ARM_Disasm::DisassembleSEL(u32 insn) {
996 rd, rn, rm); 804 rd, rn, rm);
997} 805}
998 806
999std::string ARM_Disasm::DisassembleSWI(u32 insn) 807std::string ARM_Disasm::DisassembleSWI(u32 insn) {
1000{
1001 u8 cond = (insn >> 28) & 0xf; 808 u8 cond = (insn >> 28) & 0xf;
1002 u32 sysnum = insn & 0x00ffffff; 809 u32 sysnum = insn & 0x00ffffff;
1003 810
1004 return Common::StringFromFormat("swi%s 0x%x", cond_to_str(cond), sysnum); 811 return Common::StringFromFormat("swi%s 0x%x", cond_to_str(cond), sysnum);
1005} 812}
1006 813
1007std::string ARM_Disasm::DisassembleSWP(Opcode opcode, u32 insn) 814std::string ARM_Disasm::DisassembleSWP(Opcode opcode, u32 insn) {
1008{
1009 u8 cond = (insn >> 28) & 0xf; 815 u8 cond = (insn >> 28) & 0xf;
1010 u8 rn = (insn >> 16) & 0xf; 816 u8 rn = (insn >> 16) & 0xf;
1011 u8 rd = (insn >> 12) & 0xf; 817 u8 rd = (insn >> 12) & 0xf;
1012 u8 rm = insn & 0xf; 818 u8 rm = insn & 0xf;
1013 819
1014 const char *opname = opcode_names[opcode]; 820 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); 821 return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opname, cond_to_str(cond), rd, rm, rn);
1016} 822}
1017 823
1018std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn) 824std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn) {
1019{
1020 u32 cond = BITS(insn, 28, 31); 825 u32 cond = BITS(insn, 28, 31);
1021 u32 rn = BITS(insn, 16, 19); 826 u32 rn = BITS(insn, 16, 19);
1022 u32 rd = BITS(insn, 12, 15); 827 u32 rd = BITS(insn, 12, 15);
@@ -1025,9 +830,7 @@ std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn)
1025 830
1026 std::string rn_part = ""; 831 std::string rn_part = "";
1027 static std::unordered_set<Opcode, std::hash<int>> extend_with_add = { 832 static std::unordered_set<Opcode, std::hash<int>> extend_with_add = {
1028 OP_SXTAB, OP_SXTAB16, OP_SXTAH, 833 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()) 834 if (extend_with_add.find(opcode) != extend_with_add.end())
1032 rn_part = ", r" + std::to_string(rn); 835 rn_part = ", r" + std::to_string(rn);
1033 836
@@ -1042,14 +845,14 @@ std::string ARM_Disasm::DisassembleXT(Opcode opcode, u32 insn)
1042Opcode ARM_Disasm::Decode(u32 insn) { 845Opcode ARM_Disasm::Decode(u32 insn) {
1043 u32 bits27_26 = (insn >> 26) & 0x3; 846 u32 bits27_26 = (insn >> 26) & 0x3;
1044 switch (bits27_26) { 847 switch (bits27_26) {
1045 case 0x0: 848 case 0x0:
1046 return Decode00(insn); 849 return Decode00(insn);
1047 case 0x1: 850 case 0x1:
1048 return Decode01(insn); 851 return Decode01(insn);
1049 case 0x2: 852 case 0x2:
1050 return Decode10(insn); 853 return Decode10(insn);
1051 case 0x3: 854 case 0x3:
1052 return Decode11(insn); 855 return Decode11(insn);
1053 } 856 }
1054 return OP_INVALID; 857 return OP_INVALID;
1055} 858}
@@ -1198,28 +1001,28 @@ Opcode ARM_Disasm::DecodeSyncPrimitive(u32 insn) {
1198 u32 op = BITS(insn, 20, 23); 1001 u32 op = BITS(insn, 20, 23);
1199 u32 bit22 = BIT(insn, 22); 1002 u32 bit22 = BIT(insn, 22);
1200 switch (op) { 1003 switch (op) {
1201 case 0x0: 1004 case 0x0:
1202 if (bit22) 1005 if (bit22)
1203 return OP_SWPB; 1006 return OP_SWPB;
1204 return OP_SWP; 1007 return OP_SWP;
1205 case 0x8: 1008 case 0x8:
1206 return OP_STREX; 1009 return OP_STREX;
1207 case 0x9: 1010 case 0x9:
1208 return OP_LDREX; 1011 return OP_LDREX;
1209 case 0xA: 1012 case 0xA:
1210 return OP_STREXD; 1013 return OP_STREXD;
1211 case 0xB: 1014 case 0xB:
1212 return OP_LDREXD; 1015 return OP_LDREXD;
1213 case 0xC: 1016 case 0xC:
1214 return OP_STREXB; 1017 return OP_STREXB;
1215 case 0xD: 1018 case 0xD:
1216 return OP_LDREXB; 1019 return OP_LDREXB;
1217 case 0xE: 1020 case 0xE:
1218 return OP_STREXH; 1021 return OP_STREXH;
1219 case 0xF: 1022 case 0xF:
1220 return OP_LDREXH; 1023 return OP_LDREXH;
1221 default: 1024 default:
1222 return OP_UNDEFINED; 1025 return OP_UNDEFINED;
1223 } 1026 }
1224} 1027}
1225 1028
@@ -1240,27 +1043,14 @@ Opcode ARM_Disasm::DecodeParallelAddSub(u32 insn) {
1240 1043
1241 static std::vector<Opcode> opcodes = { 1044 static std::vector<Opcode> opcodes = {
1242 // op1 = 0 1045 // op1 = 0
1243 OP_SADD16, OP_UADD16, 1046 OP_SADD16, OP_UADD16, OP_SASX, OP_UASX, OP_SSAX, OP_USAX, OP_SSUB16, OP_USUB16, OP_SADD8,
1244 OP_SASX, OP_UASX, 1047 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 1048 // op1 = 1
1250 OP_QADD16, OP_UQADD16, 1049 OP_QADD16, OP_UQADD16, OP_QASX, OP_UQASX, OP_QSAX, OP_UQSAX, OP_QSUB16, OP_UQSUB16,
1251 OP_QASX, OP_UQASX, 1050 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 1051 // op1 = 2
1257 OP_SHADD16, OP_UHADD16, 1052 OP_SHADD16, OP_UHADD16, OP_SHASX, OP_UHASX, OP_SHSAX, OP_UHSAX, OP_SHSUB16, OP_UHSUB16,
1258 OP_SHASX, OP_UHASX, 1053 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 1054
1265 u32 opcode_index = op1 * 12 + op2 * 2 + is_unsigned; 1055 u32 opcode_index = op1 * 12 + op2 * 2 + is_unsigned;
1266 return opcodes[opcode_index]; 1056 return opcodes[opcode_index];
@@ -1272,66 +1062,66 @@ Opcode ARM_Disasm::DecodePackingSaturationReversal(u32 insn) {
1272 u32 op2 = BITS(insn, 5, 7); 1062 u32 op2 = BITS(insn, 5, 7);
1273 1063
1274 switch (op1) { 1064 switch (op1) {
1275 case 0x0: 1065 case 0x0:
1276 if (BIT(op2, 0) == 0) 1066 if (BIT(op2, 0) == 0)
1277 return OP_PKH; 1067 return OP_PKH;
1278 if (op2 == 0x3 && a != 0xf) 1068 if (op2 == 0x3 && a != 0xf)
1279 return OP_SXTAB16; 1069 return OP_SXTAB16;
1280 if (op2 == 0x3 && a == 0xf) 1070 if (op2 == 0x3 && a == 0xf)
1281 return OP_SXTB16; 1071 return OP_SXTB16;
1282 if (op2 == 0x5) 1072 if (op2 == 0x5)
1283 return OP_SEL; 1073 return OP_SEL;
1284 break; 1074 break;
1285 case 0x2: 1075 case 0x2:
1286 if (BIT(op2, 0) == 0) 1076 if (BIT(op2, 0) == 0)
1287 return OP_SSAT; 1077 return OP_SSAT;
1288 if (op2 == 0x1) 1078 if (op2 == 0x1)
1289 return OP_SSAT16; 1079 return OP_SSAT16;
1290 if (op2 == 0x3 && a != 0xf) 1080 if (op2 == 0x3 && a != 0xf)
1291 return OP_SXTAB; 1081 return OP_SXTAB;
1292 if (op2 == 0x3 && a == 0xf) 1082 if (op2 == 0x3 && a == 0xf)
1293 return OP_SXTB; 1083 return OP_SXTB;
1294 break; 1084 break;
1295 case 0x3: 1085 case 0x3:
1296 if (op2 == 0x1) 1086 if (op2 == 0x1)
1297 return OP_REV; 1087 return OP_REV;
1298 if (BIT(op2, 0) == 0) 1088 if (BIT(op2, 0) == 0)
1299 return OP_SSAT; 1089 return OP_SSAT;
1300 if (op2 == 0x3 && a != 0xf) 1090 if (op2 == 0x3 && a != 0xf)
1301 return OP_SXTAH; 1091 return OP_SXTAH;
1302 if (op2 == 0x3 && a == 0xf) 1092 if (op2 == 0x3 && a == 0xf)
1303 return OP_SXTH; 1093 return OP_SXTH;
1304 if (op2 == 0x5) 1094 if (op2 == 0x5)
1305 return OP_REV16; 1095 return OP_REV16;
1306 break; 1096 break;
1307 case 0x4: 1097 case 0x4:
1308 if (op2 == 0x3 && a != 0xf) 1098 if (op2 == 0x3 && a != 0xf)
1309 return OP_UXTAB16; 1099 return OP_UXTAB16;
1310 if (op2 == 0x3 && a == 0xf) 1100 if (op2 == 0x3 && a == 0xf)
1311 return OP_UXTB16; 1101 return OP_UXTB16;
1312 break; 1102 break;
1313 case 0x6: 1103 case 0x6:
1314 if (BIT(op2, 0) == 0) 1104 if (BIT(op2, 0) == 0)
1315 return OP_USAT; 1105 return OP_USAT;
1316 if (op2 == 0x1) 1106 if (op2 == 0x1)
1317 return OP_USAT16; 1107 return OP_USAT16;
1318 if (op2 == 0x3 && a != 0xf) 1108 if (op2 == 0x3 && a != 0xf)
1319 return OP_UXTAB; 1109 return OP_UXTAB;
1320 if (op2 == 0x3 && a == 0xf) 1110 if (op2 == 0x3 && a == 0xf)
1321 return OP_UXTB; 1111 return OP_UXTB;
1322 break; 1112 break;
1323 case 0x7: 1113 case 0x7:
1324 if (BIT(op2, 0) == 0) 1114 if (BIT(op2, 0) == 0)
1325 return OP_USAT; 1115 return OP_USAT;
1326 if (op2 == 0x3 && a != 0xf) 1116 if (op2 == 0x3 && a != 0xf)
1327 return OP_UXTAH; 1117 return OP_UXTAH;
1328 if (op2 == 0x3 && a == 0xf) 1118 if (op2 == 0x3 && a == 0xf)
1329 return OP_UXTH; 1119 return OP_UXTH;
1330 if (op2 == 0x5) 1120 if (op2 == 0x5)
1331 return OP_REVSH; 1121 return OP_REVSH;
1332 break; 1122 break;
1333 default: 1123 default:
1334 break; 1124 break;
1335 } 1125 }
1336 1126
1337 return OP_UNDEFINED; 1127 return OP_UNDEFINED;
@@ -1378,18 +1168,18 @@ Opcode ARM_Disasm::DecodeMSRImmAndHints(u32 insn) {
1378 1168
1379 if (op == 0 && op1 == 0) { 1169 if (op == 0 && op1 == 0) {
1380 switch (op2) { 1170 switch (op2) {
1381 case 0x0: 1171 case 0x0:
1382 return OP_NOP; 1172 return OP_NOP;
1383 case 0x1: 1173 case 0x1:
1384 return OP_YIELD; 1174 return OP_YIELD;
1385 case 0x2: 1175 case 0x2:
1386 return OP_WFE; 1176 return OP_WFE;
1387 case 0x3: 1177 case 0x3:
1388 return OP_WFI; 1178 return OP_WFI;
1389 case 0x4: 1179 case 0x4:
1390 return OP_SEV; 1180 return OP_SEV;
1391 default: 1181 default:
1392 return OP_UNDEFINED; 1182 return OP_UNDEFINED;
1393 } 1183 }
1394 } 1184 }
1395 1185
@@ -1402,37 +1192,37 @@ Opcode ARM_Disasm::DecodeMediaMulDiv(u32 insn) {
1402 u32 a = BITS(insn, 12, 15); 1192 u32 a = BITS(insn, 12, 15);
1403 1193
1404 switch (op1) { 1194 switch (op1) {
1405 case 0x0: 1195 case 0x0:
1406 if (op2_h == 0x0) { 1196 if (op2_h == 0x0) {
1407 if (a != 0xf) 1197 if (a != 0xf)
1408 return OP_SMLAD; 1198 return OP_SMLAD;
1409 else 1199 else
1410 return OP_SMUAD; 1200 return OP_SMUAD;
1411 } else if (op2_h == 0x1) { 1201 } else if (op2_h == 0x1) {
1412 if (a != 0xf) 1202 if (a != 0xf)
1413 return OP_SMLSD; 1203 return OP_SMLSD;
1414 else 1204 else
1415 return OP_SMUSD; 1205 return OP_SMUSD;
1416 } 1206 }
1417 break; 1207 break;
1418 case 0x4: 1208 case 0x4:
1419 if (op2_h == 0x0) 1209 if (op2_h == 0x0)
1420 return OP_SMLALD; 1210 return OP_SMLALD;
1421 else if (op2_h == 0x1) 1211 else if (op2_h == 0x1)
1422 return OP_SMLSLD; 1212 return OP_SMLSLD;
1423 break; 1213 break;
1424 case 0x5: 1214 case 0x5:
1425 if (op2_h == 0x0) { 1215 if (op2_h == 0x0) {
1426 if (a != 0xf) 1216 if (a != 0xf)
1427 return OP_SMMLA; 1217 return OP_SMMLA;
1428 else 1218 else
1429 return OP_SMMUL; 1219 return OP_SMMUL;
1430 } else if (op2_h == 0x3) { 1220 } else if (op2_h == 0x3) {
1431 return OP_SMMLS; 1221 return OP_SMMLS;
1432 } 1222 }
1433 break; 1223 break;
1434 default: 1224 default:
1435 break; 1225 break;
1436 } 1226 }
1437 1227
1438 return OP_UNDEFINED; 1228 return OP_UNDEFINED;
@@ -1444,23 +1234,23 @@ Opcode ARM_Disasm::DecodeMedia(u32 insn) {
1444 u32 op2 = BITS(insn, 5, 7); 1234 u32 op2 = BITS(insn, 5, 7);
1445 1235
1446 switch (BITS(op1, 3, 4)) { 1236 switch (BITS(op1, 3, 4)) {
1447 case 0x0: 1237 case 0x0:
1448 // unsigned and signed parallel addition and subtraction 1238 // unsigned and signed parallel addition and subtraction
1449 return DecodeParallelAddSub(insn); 1239 return DecodeParallelAddSub(insn);
1450 case 0x1: 1240 case 0x1:
1451 // Packing, unpacking, saturation, and reversal 1241 // Packing, unpacking, saturation, and reversal
1452 return DecodePackingSaturationReversal(insn); 1242 return DecodePackingSaturationReversal(insn);
1453 case 0x2: 1243 case 0x2:
1454 // Signed multiply, signed and unsigned divide 1244 // Signed multiply, signed and unsigned divide
1455 return DecodeMediaMulDiv(insn); 1245 return DecodeMediaMulDiv(insn);
1456 case 0x3: 1246 case 0x3:
1457 if (op2 == 0 && rd == 0xf) 1247 if (op2 == 0 && rd == 0xf)
1458 return OP_USAD8; 1248 return OP_USAD8;
1459 if (op2 == 0 && rd != 0xf) 1249 if (op2 == 0 && rd != 0xf)
1460 return OP_USADA8; 1250 return OP_USADA8;
1461 break; 1251 break;
1462 default: 1252 default:
1463 break; 1253 break;
1464 } 1254 }
1465 1255
1466 return OP_UNDEFINED; 1256 return OP_UNDEFINED;
@@ -1508,46 +1298,46 @@ Opcode ARM_Disasm::DecodeALU(u32 insn) {
1508 return OP_UNDEFINED; 1298 return OP_UNDEFINED;
1509 } 1299 }
1510 switch (opcode) { 1300 switch (opcode) {
1511 case 0x0: 1301 case 0x0:
1512 return OP_AND; 1302 return OP_AND;
1513 case 0x1: 1303 case 0x1:
1514 return OP_EOR; 1304 return OP_EOR;
1515 case 0x2: 1305 case 0x2:
1516 return OP_SUB; 1306 return OP_SUB;
1517 case 0x3: 1307 case 0x3:
1518 return OP_RSB; 1308 return OP_RSB;
1519 case 0x4: 1309 case 0x4:
1520 return OP_ADD; 1310 return OP_ADD;
1521 case 0x5: 1311 case 0x5:
1522 return OP_ADC; 1312 return OP_ADC;
1523 case 0x6: 1313 case 0x6:
1524 return OP_SBC; 1314 return OP_SBC;
1525 case 0x7: 1315 case 0x7:
1526 return OP_RSC; 1316 return OP_RSC;
1527 case 0x8: 1317 case 0x8:
1528 if (bit_s) 1318 if (bit_s)
1529 return OP_TST; 1319 return OP_TST;
1530 return OP_MRS; 1320 return OP_MRS;
1531 case 0x9: 1321 case 0x9:
1532 if (bit_s) 1322 if (bit_s)
1533 return OP_TEQ; 1323 return OP_TEQ;
1534 return OP_MSR; 1324 return OP_MSR;
1535 case 0xa: 1325 case 0xa:
1536 if (bit_s) 1326 if (bit_s)
1537 return OP_CMP; 1327 return OP_CMP;
1538 return OP_MRS; 1328 return OP_MRS;
1539 case 0xb: 1329 case 0xb:
1540 if (bit_s) 1330 if (bit_s)
1541 return OP_CMN; 1331 return OP_CMN;
1542 return OP_MSR; 1332 return OP_MSR;
1543 case 0xc: 1333 case 0xc:
1544 return OP_ORR; 1334 return OP_ORR;
1545 case 0xd: 1335 case 0xd:
1546 return OP_MOV; 1336 return OP_MOV;
1547 case 0xe: 1337 case 0xe:
1548 return OP_BIC; 1338 return OP_BIC;
1549 case 0xf: 1339 case 0xf:
1550 return OP_MVN; 1340 return OP_MVN;
1551 } 1341 }
1552 // Unreachable 1342 // Unreachable
1553 return OP_INVALID; 1343 return OP_INVALID;
diff --git a/src/core/arm/disassembler/arm_disasm.h b/src/core/arm/disassembler/arm_disasm.h
index 53d9c6a74..300e228ed 100644
--- a/src/core/arm/disassembler/arm_disasm.h
+++ b/src/core/arm/disassembler/arm_disasm.h
@@ -3,7 +3,6 @@
3#pragma once 3#pragma once
4 4
5#include <string> 5#include <string>
6
7#include "common/common_types.h" 6#include "common/common_types.h"
8 7
9// Note: this list of opcodes must match the list used to initialize 8// Note: this list of opcodes must match the list used to initialize
@@ -187,53 +186,53 @@ enum Opcode {
187 OP_THUMB_SWI, 186 OP_THUMB_SWI,
188 OP_THUMB_TST, 187 OP_THUMB_TST,
189 188
190 OP_END // must be last 189 OP_END // must be last
191}; 190};
192 191
193class ARM_Disasm { 192class ARM_Disasm {
194 public: 193public:
195 static std::string Disassemble(u32 addr, u32 insn); 194 static std::string Disassemble(u32 addr, u32 insn);
196 static Opcode Decode(u32 insn); 195 static Opcode Decode(u32 insn);
197 196
198 private: 197private:
199 static Opcode Decode00(u32 insn); 198 static Opcode Decode00(u32 insn);
200 static Opcode Decode01(u32 insn); 199 static Opcode Decode01(u32 insn);
201 static Opcode Decode10(u32 insn); 200 static Opcode Decode10(u32 insn);
202 static Opcode Decode11(u32 insn); 201 static Opcode Decode11(u32 insn);
203 static Opcode DecodeSyncPrimitive(u32 insn); 202 static Opcode DecodeSyncPrimitive(u32 insn);
204 static Opcode DecodeParallelAddSub(u32 insn); 203 static Opcode DecodeParallelAddSub(u32 insn);
205 static Opcode DecodePackingSaturationReversal(u32 insn); 204 static Opcode DecodePackingSaturationReversal(u32 insn);
206 static Opcode DecodeMUL(u32 insn); 205 static Opcode DecodeMUL(u32 insn);
207 static Opcode DecodeMSRImmAndHints(u32 insn); 206 static Opcode DecodeMSRImmAndHints(u32 insn);
208 static Opcode DecodeMediaMulDiv(u32 insn); 207 static Opcode DecodeMediaMulDiv(u32 insn);
209 static Opcode DecodeMedia(u32 insn); 208 static Opcode DecodeMedia(u32 insn);
210 static Opcode DecodeLDRH(u32 insn); 209 static Opcode DecodeLDRH(u32 insn);
211 static Opcode DecodeALU(u32 insn); 210 static Opcode DecodeALU(u32 insn);
212 211
213 static std::string DisassembleALU(Opcode opcode, u32 insn); 212 static std::string DisassembleALU(Opcode opcode, u32 insn);
214 static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn); 213 static std::string DisassembleBranch(u32 addr, Opcode opcode, u32 insn);
215 static std::string DisassembleBX(u32 insn); 214 static std::string DisassembleBX(u32 insn);
216 static std::string DisassembleBKPT(u32 insn); 215 static std::string DisassembleBKPT(u32 insn);
217 static std::string DisassembleCLZ(u32 insn); 216 static std::string DisassembleCLZ(u32 insn);
218 static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn); 217 static std::string DisassembleMediaMulDiv(Opcode opcode, u32 insn);
219 static std::string DisassembleMemblock(Opcode opcode, u32 insn); 218 static std::string DisassembleMemblock(Opcode opcode, u32 insn);
220 static std::string DisassembleMem(u32 insn); 219 static std::string DisassembleMem(u32 insn);
221 static std::string DisassembleMemHalf(u32 insn); 220 static std::string DisassembleMemHalf(u32 insn);
222 static std::string DisassembleMCR(Opcode opcode, u32 insn); 221 static std::string DisassembleMCR(Opcode opcode, u32 insn);
223 static std::string DisassembleMLA(Opcode opcode, u32 insn); 222 static std::string DisassembleMLA(Opcode opcode, u32 insn);
224 static std::string DisassembleUMLAL(Opcode opcode, u32 insn); 223 static std::string DisassembleUMLAL(Opcode opcode, u32 insn);
225 static std::string DisassembleMUL(Opcode opcode, u32 insn); 224 static std::string DisassembleMUL(Opcode opcode, u32 insn);
226 static std::string DisassembleMRS(u32 insn); 225 static std::string DisassembleMRS(u32 insn);
227 static std::string DisassembleMSR(u32 insn); 226 static std::string DisassembleMSR(u32 insn);
228 static std::string DisassembleNoOperands(Opcode opcode, u32 insn); 227 static std::string DisassembleNoOperands(Opcode opcode, u32 insn);
229 static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn); 228 static std::string DisassembleParallelAddSub(Opcode opcode, u32 insn);
230 static std::string DisassemblePKH(u32 insn); 229 static std::string DisassemblePKH(u32 insn);
231 static std::string DisassemblePLD(u32 insn); 230 static std::string DisassemblePLD(u32 insn);
232 static std::string DisassembleREV(Opcode opcode, u32 insn); 231 static std::string DisassembleREV(Opcode opcode, u32 insn);
233 static std::string DisassembleREX(Opcode opcode, u32 insn); 232 static std::string DisassembleREX(Opcode opcode, u32 insn);
234 static std::string DisassembleSAT(Opcode opcode, u32 insn); 233 static std::string DisassembleSAT(Opcode opcode, u32 insn);
235 static std::string DisassembleSEL(u32 insn); 234 static std::string DisassembleSEL(u32 insn);
236 static std::string DisassembleSWI(u32 insn); 235 static std::string DisassembleSWI(u32 insn);
237 static std::string DisassembleSWP(Opcode opcode, u32 insn); 236 static std::string DisassembleSWP(Opcode opcode, u32 insn);
238 static std::string DisassembleXT(Opcode opcode, u32 insn); 237 static std::string DisassembleXT(Opcode opcode, u32 insn);
239}; 238};
diff --git a/src/core/arm/disassembler/load_symbol_map.cpp b/src/core/arm/disassembler/load_symbol_map.cpp
index eb20bf6f7..6863c103a 100644
--- a/src/core/arm/disassembler/load_symbol_map.cpp
+++ b/src/core/arm/disassembler/load_symbol_map.cpp
@@ -5,10 +5,8 @@
5#include <sstream> 5#include <sstream>
6#include <string> 6#include <string>
7#include <vector> 7#include <vector>
8
9#include "common/symbols.h"
10#include "common/file_util.h" 8#include "common/file_util.h"
11 9#include "common/symbols.h"
12#include "core/arm/disassembler/load_symbol_map.h" 10#include "core/arm/disassembler/load_symbol_map.h"
13 11
14/* 12/*
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index a521aec7c..b4444c869 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -2,11 +2,9 @@
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 <dynarmic/dynarmic.h>
5#include "common/assert.h" 6#include "common/assert.h"
6#include "common/microprofile.h" 7#include "common/microprofile.h"
7
8#include <dynarmic/dynarmic.h>
9
10#include "core/arm/dynarmic/arm_dynarmic.h" 8#include "core/arm/dynarmic/arm_dynarmic.h"
11#include "core/arm/dyncom/arm_dyncom_interpreter.h" 9#include "core/arm/dyncom/arm_dyncom_interpreter.h"
12#include "core/core.h" 10#include "core/core.h"
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h
index d493cabd5..ced86d29b 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.h
+++ b/src/core/arm/dynarmic/arm_dynarmic.h
@@ -5,11 +5,8 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8
9#include <dynarmic/dynarmic.h> 8#include <dynarmic/dynarmic.h>
10
11#include "common/common_types.h" 9#include "common/common_types.h"
12
13#include "core/arm/arm_interface.h" 10#include "core/arm/arm_interface.h"
14#include "core/arm/skyeye_common/armstate.h" 11#include "core/arm/skyeye_common/armstate.h"
15 12
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index d84917529..34c7f945e 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -4,16 +4,13 @@
4 4
5#include <cstring> 5#include <cstring>
6#include <memory> 6#include <memory>
7
8#include "core/arm/skyeye_common/armstate.h"
9#include "core/arm/skyeye_common/armsupp.h"
10#include "core/arm/skyeye_common/vfp/vfp.h"
11
12#include "core/arm/dyncom/arm_dyncom.h" 7#include "core/arm/dyncom/arm_dyncom.h"
13#include "core/arm/dyncom/arm_dyncom_interpreter.h" 8#include "core/arm/dyncom/arm_dyncom_interpreter.h"
14#include "core/arm/dyncom/arm_dyncom_run.h" 9#include "core/arm/dyncom/arm_dyncom_run.h"
15#include "core/arm/dyncom/arm_dyncom_trans.h" 10#include "core/arm/dyncom/arm_dyncom_trans.h"
16 11#include "core/arm/skyeye_common/armstate.h"
12#include "core/arm/skyeye_common/armsupp.h"
13#include "core/arm/skyeye_common/vfp/vfp.h"
17#include "core/core.h" 14#include "core/core.h"
18#include "core/core_timing.h" 15#include "core/core_timing.h"
19 16
@@ -21,8 +18,7 @@ ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) {
21 state = std::make_unique<ARMul_State>(initial_mode); 18 state = std::make_unique<ARMul_State>(initial_mode);
22} 19}
23 20
24ARM_DynCom::~ARM_DynCom() { 21ARM_DynCom::~ARM_DynCom() {}
25}
26 22
27void ARM_DynCom::ClearInstructionCache() { 23void ARM_DynCom::ClearInstructionCache() {
28 state->instruction_cache.clear(); 24 state->instruction_cache.clear();
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index 70f71a828..65db1f0f9 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -5,9 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10
11#include "core/arm/arm_interface.h" 9#include "core/arm/arm_interface.h"
12#include "core/arm/skyeye_common/arm_regformat.h" 10#include "core/arm/skyeye_common/arm_regformat.h"
13#include "core/arm/skyeye_common/armstate.h" 11#include "core/arm/skyeye_common/armstate.h"
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp
index 247d379e3..64dcaae08 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp
@@ -5,6 +5,7 @@
5#include "core/arm/dyncom/arm_dyncom_dec.h" 5#include "core/arm/dyncom/arm_dyncom_dec.h"
6#include "core/arm/skyeye_common/armsupp.h" 6#include "core/arm/skyeye_common/armsupp.h"
7 7
8// clang-format off
8const InstructionSetEncodingItem arm_instruction[] = { 9const InstructionSetEncodingItem arm_instruction[] = {
9 { "vmla", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }}, 10 { "vmla", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 }},
10 { "vmls", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }}, 11 { "vmls", 5, ARMVFP2, { 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 }},
@@ -206,6 +207,7 @@ const InstructionSetEncodingItem arm_instruction[] = {
206 { "bbl", 1, 0, { 25, 27, 0x00000005 }}, 207 { "bbl", 1, 0, { 25, 27, 0x00000005 }},
207}; 208};
208 209
210
209const InstructionSetEncodingItem arm_exclusion_code[] = { 211const InstructionSetEncodingItem arm_exclusion_code[] = {
210 { "vmla", 0, ARMVFP2, { 0 }}, 212 { "vmla", 0, ARMVFP2, { 0 }},
211 { "vmls", 0, ARMVFP2, { 0 }}, 213 { "vmls", 0, ARMVFP2, { 0 }},
@@ -411,6 +413,7 @@ const InstructionSetEncodingItem arm_exclusion_code[] = {
411 { "blx_1_thumb", 0, INVALID, { 0 }}, // Should be located at table[-2] 413 { "blx_1_thumb", 0, INVALID, { 0 }}, // Should be located at table[-2]
412 { "invalid", 0, INVALID, { 0 }} 414 { "invalid", 0, INVALID, { 0 }}
413}; 415};
416// clang-format on
414 417
415ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { 418ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) {
416 int n = 0; 419 int n = 0;
@@ -427,12 +430,15 @@ ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) {
427 continue; 430 continue;
428 431
429 while (n) { 432 while (n) {
430 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) {
431 // clrex 435 // clrex
432 if (instr != arm_instruction[i].content[base + 2]) { 436 if (instr != arm_instruction[i].content[base + 2]) {
433 break; 437 break;
434 } 438 }
435 } 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]) {
436 break; 442 break;
437 } 443 }
438 base += 3; 444 base += 3;
@@ -448,7 +454,9 @@ ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) {
448 if (n != 0) { 454 if (n != 0) {
449 base = 0; 455 base = 0;
450 while (n) { 456 while (n) {
451 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]) {
452 break; 460 break;
453 } 461 }
454 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..7b8616702 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -6,34 +6,31 @@
6 6
7#include <algorithm> 7#include <algorithm>
8#include <cstdio> 8#include <cstdio>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12#include "common/microprofile.h" 11#include "common/microprofile.h"
13
14#include "core/memory.h"
15#include "core/hle/svc.h"
16#include "core/arm/disassembler/arm_disasm.h" 12#include "core/arm/disassembler/arm_disasm.h"
17#include "core/arm/dyncom/arm_dyncom_dec.h" 13#include "core/arm/dyncom/arm_dyncom_dec.h"
18#include "core/arm/dyncom/arm_dyncom_interpreter.h" 14#include "core/arm/dyncom/arm_dyncom_interpreter.h"
15#include "core/arm/dyncom/arm_dyncom_run.h"
19#include "core/arm/dyncom/arm_dyncom_thumb.h" 16#include "core/arm/dyncom/arm_dyncom_thumb.h"
20#include "core/arm/dyncom/arm_dyncom_trans.h" 17#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" 18#include "core/arm/skyeye_common/armstate.h"
23#include "core/arm/skyeye_common/armsupp.h" 19#include "core/arm/skyeye_common/armsupp.h"
24#include "core/arm/skyeye_common/vfp/vfp.h" 20#include "core/arm/skyeye_common/vfp/vfp.h"
25
26#include "core/gdbstub/gdbstub.h" 21#include "core/gdbstub/gdbstub.h"
22#include "core/hle/svc.h"
23#include "core/memory.h"
27 24
28#define RM BITS(sht_oper, 0, 3) 25#define RM BITS(sht_oper, 0, 3)
29#define RS BITS(sht_oper, 8, 11) 26#define RS BITS(sht_oper, 8, 11)
30 27
31#define glue(x, y) x ## y 28#define glue(x, y) x##y
32#define DPO(s) glue(DataProcessingOperands, s) 29#define DPO(s) glue(DataProcessingOperands, s)
33#define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i)) 30#define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i))
34#define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i)) 31#define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i))
35#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32) 32#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32)
36#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32) 33#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32)
37 34
38static bool CondPassed(const ARMul_State* cpu, unsigned int cond) { 35static bool CondPassed(const ARMul_State* cpu, unsigned int cond) {
39 const bool n_flag = cpu->NFlag != 0; 36 const bool n_flag = cpu->NFlag != 0;
@@ -232,17 +229,19 @@ static unsigned int DPO(RotateRightByRegister)(ARMul_State* cpu, unsigned int sh
232 return shifter_operand; 229 return shifter_operand;
233} 230}
234 231
235#define DEBUG_MSG LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0) 232#define DEBUG_MSG \
233 LOG_DEBUG(Core_ARM11, "inst is %x", inst); \
234 CITRA_IGNORE_EXIT(0)
236 235
237#define LnSWoUB(s) glue(LnSWoUB, s) 236#define LnSWoUB(s) glue(LnSWoUB, s)
238#define MLnS(s) glue(MLnS, s) 237#define MLnS(s) glue(MLnS, s)
239#define LdnStM(s) glue(LdnStM, s) 238#define LdnStM(s) glue(LdnStM, s)
240 239
241#define W_BIT BIT(inst, 21) 240#define W_BIT BIT(inst, 21)
242#define U_BIT BIT(inst, 23) 241#define U_BIT BIT(inst, 23)
243#define I_BIT BIT(inst, 25) 242#define I_BIT BIT(inst, 25)
244#define P_BIT BIT(inst, 24) 243#define P_BIT BIT(inst, 24)
245#define OFFSET_12 BITS(inst, 0, 11) 244#define OFFSET_12 BITS(inst, 0, 11)
246 245
247static void LnSWoUB(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 246static void LnSWoUB(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
248 unsigned int Rn = BITS(inst, 16, 19); 247 unsigned int Rn = BITS(inst, 16, 19);
@@ -271,7 +270,8 @@ static void LnSWoUB(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigne
271 virt_addr = addr; 270 virt_addr = addr;
272} 271}
273 272
274static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 273static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst,
274 unsigned int& virt_addr) {
275 unsigned int Rn = BITS(inst, 16, 19); 275 unsigned int Rn = BITS(inst, 16, 19);
276 unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn); 276 unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn);
277 277
@@ -283,7 +283,8 @@ static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, u
283 virt_addr = addr; 283 virt_addr = addr;
284} 284}
285 285
286static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 286static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst,
287 unsigned int& virt_addr) {
287 unsigned int Rn = BITS(inst, 16, 19); 288 unsigned int Rn = BITS(inst, 16, 19);
288 unsigned int addr; 289 unsigned int addr;
289 290
@@ -301,7 +302,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) { 302static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
302 unsigned int addr; 303 unsigned int addr;
303 unsigned int Rn = BITS(inst, 16, 19); 304 unsigned int Rn = BITS(inst, 16, 19);
304 unsigned int Rm = BITS(inst, 0, 3); 305 unsigned int Rm = BITS(inst, 0, 3);
305 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 306 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
306 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 307 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
307 308
@@ -316,7 +317,8 @@ static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsign
316 cpu->Reg[Rn] = addr; 317 cpu->Reg[Rn] = addr;
317} 318}
318 319
319static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 320static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst,
321 unsigned int& virt_addr) {
320 unsigned int Rn = BITS(inst, 16, 19); 322 unsigned int Rn = BITS(inst, 16, 19);
321 unsigned int Rm = BITS(inst, 0, 3); 323 unsigned int Rm = BITS(inst, 0, 3);
322 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 324 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
@@ -335,7 +337,8 @@ static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, uns
335 } 337 }
336} 338}
337 339
338static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 340static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int inst,
341 unsigned int& virt_addr) {
339 unsigned int shift = BITS(inst, 5, 6); 342 unsigned int shift = BITS(inst, 5, 6);
340 unsigned int shift_imm = BITS(inst, 7, 11); 343 unsigned int shift_imm = BITS(inst, 7, 11);
341 unsigned int Rn = BITS(inst, 16, 19); 344 unsigned int Rn = BITS(inst, 16, 19);
@@ -386,7 +389,8 @@ static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int ins
386 cpu->Reg[Rn] = addr; 389 cpu->Reg[Rn] = addr;
387} 390}
388 391
389static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 392static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
393 unsigned int& virt_addr) {
390 unsigned int shift = BITS(inst, 5, 6); 394 unsigned int shift = BITS(inst, 5, 6);
391 unsigned int shift_imm = BITS(inst, 7, 11); 395 unsigned int shift_imm = BITS(inst, 7, 11);
392 unsigned int Rn = BITS(inst, 16, 19); 396 unsigned int Rn = BITS(inst, 16, 19);
@@ -435,9 +439,10 @@ static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int in
435 } 439 }
436} 440}
437 441
438static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 442static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
443 unsigned int& virt_addr) {
439 unsigned int Rn = BITS(inst, 16, 19); 444 unsigned int Rn = BITS(inst, 16, 19);
440 unsigned int Rm = BITS(inst, 0, 3); 445 unsigned int Rm = BITS(inst, 0, 3);
441 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 446 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
442 447
443 virt_addr = CHECK_READ_REG15_WA(cpu, Rn); 448 virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
@@ -454,7 +459,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) { 459static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
455 unsigned int immedL = BITS(inst, 0, 3); 460 unsigned int immedL = BITS(inst, 0, 3);
456 unsigned int immedH = BITS(inst, 8, 11); 461 unsigned int immedH = BITS(inst, 8, 11);
457 unsigned int Rn = BITS(inst, 16, 19); 462 unsigned int Rn = BITS(inst, 16, 19);
458 unsigned int addr; 463 unsigned int addr;
459 464
460 unsigned int offset_8 = (immedH << 4) | immedL; 465 unsigned int offset_8 = (immedH << 4) | immedL;
@@ -470,7 +475,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) { 475static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
471 unsigned int addr; 476 unsigned int addr;
472 unsigned int Rn = BITS(inst, 16, 19); 477 unsigned int Rn = BITS(inst, 16, 19);
473 unsigned int Rm = BITS(inst, 0, 3); 478 unsigned int Rm = BITS(inst, 0, 3);
474 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 479 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
475 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 480 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
476 481
@@ -482,10 +487,11 @@ static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned i
482 virt_addr = addr; 487 virt_addr = addr;
483} 488}
484 489
485static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 490static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst,
486 unsigned int Rn = BITS(inst, 16, 19); 491 unsigned int& virt_addr) {
487 unsigned int immedH = BITS(inst, 8, 11); 492 unsigned int Rn = BITS(inst, 16, 19);
488 unsigned int immedL = BITS(inst, 0, 3); 493 unsigned int immedH = BITS(inst, 8, 11);
494 unsigned int immedL = BITS(inst, 0, 3);
489 unsigned int addr; 495 unsigned int addr;
490 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 496 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
491 unsigned int offset_8 = (immedH << 4) | immedL; 497 unsigned int offset_8 = (immedH << 4) | immedL;
@@ -501,10 +507,11 @@ static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst, unsig
501 cpu->Reg[Rn] = addr; 507 cpu->Reg[Rn] = addr;
502} 508}
503 509
504static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 510static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst,
505 unsigned int Rn = BITS(inst, 16, 19); 511 unsigned int& virt_addr) {
506 unsigned int immedH = BITS(inst, 8, 11); 512 unsigned int Rn = BITS(inst, 16, 19);
507 unsigned int immedL = BITS(inst, 0, 3); 513 unsigned int immedH = BITS(inst, 8, 11);
514 unsigned int immedL = BITS(inst, 0, 3);
508 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 515 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
509 516
510 virt_addr = rn; 517 virt_addr = rn;
@@ -520,9 +527,10 @@ static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst, unsi
520 } 527 }
521} 528}
522 529
523static void MLnS(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 530static void MLnS(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
531 unsigned int& virt_addr) {
524 unsigned int Rn = BITS(inst, 16, 19); 532 unsigned int Rn = BITS(inst, 16, 19);
525 unsigned int Rm = BITS(inst, 0, 3); 533 unsigned int Rm = BITS(inst, 0, 3);
526 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 534 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
527 535
528 virt_addr = CHECK_READ_REG15_WA(cpu, Rn); 536 virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
@@ -541,7 +549,8 @@ static void LdnStM(DecrementBefore)(ARMul_State* cpu, unsigned int inst, unsigne
541 int count = 0; 549 int count = 0;
542 550
543 while (i) { 551 while (i) {
544 if (i & 1) count++; 552 if (i & 1)
553 count++;
545 i = i >> 1; 554 i = i >> 1;
546 } 555 }
547 556
@@ -557,7 +566,8 @@ static void LdnStM(IncrementBefore)(ARMul_State* cpu, unsigned int inst, unsigne
557 int count = 0; 566 int count = 0;
558 567
559 while (i) { 568 while (i) {
560 if (i & 1) count++; 569 if (i & 1)
570 count++;
561 i = i >> 1; 571 i = i >> 1;
562 } 572 }
563 573
@@ -572,8 +582,9 @@ static void LdnStM(IncrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned
572 unsigned int i = BITS(inst, 0, 15); 582 unsigned int i = BITS(inst, 0, 15);
573 int count = 0; 583 int count = 0;
574 584
575 while(i) { 585 while (i) {
576 if (i & 1) count++; 586 if (i & 1)
587 count++;
577 i = i >> 1; 588 i = i >> 1;
578 } 589 }
579 590
@@ -587,8 +598,9 @@ static void LdnStM(DecrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned
587 unsigned int Rn = BITS(inst, 16, 19); 598 unsigned int Rn = BITS(inst, 16, 19);
588 unsigned int i = BITS(inst, 0, 15); 599 unsigned int i = BITS(inst, 0, 15);
589 int count = 0; 600 int count = 0;
590 while(i) { 601 while (i) {
591 if(i & 1) count++; 602 if (i & 1)
603 count++;
592 i = i >> 1; 604 i = i >> 1;
593 } 605 }
594 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 606 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
@@ -601,7 +613,8 @@ static void LdnStM(DecrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned
601 } 613 }
602} 614}
603 615
604static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) { 616static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst,
617 unsigned int& virt_addr) {
605 unsigned int shift = BITS(inst, 5, 6); 618 unsigned int shift = BITS(inst, 5, 6);
606 unsigned int shift_imm = BITS(inst, 7, 11); 619 unsigned int shift_imm = BITS(inst, 7, 11);
607 unsigned int Rn = BITS(inst, 16, 19); 620 unsigned int Rn = BITS(inst, 16, 19);
@@ -693,17 +706,23 @@ get_addr_fp_t GetAddressingOp(unsigned int inst) {
693 return LnSWoUB(RegisterPostIndexed); 706 return LnSWoUB(RegisterPostIndexed);
694 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) { 707 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
695 return LnSWoUB(ScaledRegisterPostIndexed); 708 return LnSWoUB(ScaledRegisterPostIndexed);
696 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 709 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 &&
710 BIT(inst, 4) == 1) {
697 return MLnS(ImmediateOffset); 711 return MLnS(ImmediateOffset);
698 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 712 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 &&
713 BIT(inst, 4) == 1) {
699 return MLnS(RegisterOffset); 714 return MLnS(RegisterOffset);
700 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 715 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 &&
716 BIT(inst, 4) == 1) {
701 return MLnS(ImmediatePreIndexed); 717 return MLnS(ImmediatePreIndexed);
702 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 718 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 &&
719 BIT(inst, 4) == 1) {
703 return MLnS(RegisterPreIndexed); 720 return MLnS(RegisterPreIndexed);
704 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 721 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 &&
722 BIT(inst, 4) == 1) {
705 return MLnS(ImmediatePostIndexed); 723 return MLnS(ImmediatePostIndexed);
706 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 724 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 &&
725 BIT(inst, 4) == 1) {
707 return MLnS(RegisterPostIndexed); 726 return MLnS(RegisterPostIndexed);
708 } else if (BITS(inst, 23, 27) == 0x11) { 727 } else if (BITS(inst, 23, 27) == 0x11) {
709 return LdnStM(IncrementAfter); 728 return LdnStM(IncrementAfter);
@@ -732,14 +751,12 @@ get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst) {
732 return nullptr; 751 return nullptr;
733} 752}
734 753
735enum { 754enum { FETCH_SUCCESS, FETCH_FAILURE };
736 FETCH_SUCCESS,
737 FETCH_FAILURE
738};
739 755
740static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size, ARM_INST_PTR* ptr_inst_base) { 756static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size,
757 ARM_INST_PTR* ptr_inst_base) {
741 // Check if in Thumb mode 758 // Check if in Thumb mode
742 ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size); 759 ThumbDecodeStatus ret = TranslateThumbInstruction(addr, inst, arm_inst, inst_size);
743 if (ret == ThumbDecodeStatus::BRANCH) { 760 if (ret == ThumbDecodeStatus::BRANCH) {
744 int inst_index; 761 int inst_index;
745 int table_length = arm_instruction_trans_len; 762 int table_length = arm_instruction_trans_len;
@@ -748,7 +765,7 @@ static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_ins
748 switch ((tinstr & 0xF800) >> 11) { 765 switch ((tinstr & 0xF800) >> 11) {
749 case 26: 766 case 26:
750 case 27: 767 case 27:
751 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ 768 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)) {
752 inst_index = table_length - 4; 769 inst_index = table_length - 4;
753 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); 770 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
754 } else { 771 } else {
@@ -785,21 +802,21 @@ static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_ins
785 return ret; 802 return ret;
786} 803}
787 804
788enum { 805enum { KEEP_GOING, FETCH_EXCEPTION };
789 KEEP_GOING,
790 FETCH_EXCEPTION
791};
792 806
793MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64)); 807MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64));
794 808
795static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, ARM_INST_PTR& inst_base) { 809static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr,
810 ARM_INST_PTR& inst_base) {
796 unsigned int inst_size = 4; 811 unsigned int inst_size = 4;
797 unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC); 812 unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
798 813
799 // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction 814 // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM
815 // instruction
800 if (cpu->TFlag) { 816 if (cpu->TFlag) {
801 u32 arm_inst; 817 u32 arm_inst;
802 ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base); 818 ThumbDecodeStatus state =
819 DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
803 820
804 // We have translated the Thumb branch instruction in the Thumb decoder 821 // We have translated the Thumb branch instruction in the Thumb decoder
805 if (state == ThumbDecodeStatus::BRANCH) { 822 if (state == ThumbDecodeStatus::BRANCH) {
@@ -811,8 +828,10 @@ static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, cons
811 int idx; 828 int idx;
812 if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) { 829 if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
813 std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst); 830 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); 831 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]); 832 disasm.c_str(), inst);
833 LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag,
834 cpu->Reg[15]);
816 CITRA_IGNORE_EXIT(-1); 835 CITRA_IGNORE_EXIT(-1);
817 } 836 }
818 inst_base = arm_instruction_trans[idx](inst, idx); 837 inst_base = arm_instruction_trans[idx](inst, idx);
@@ -875,12 +894,25 @@ static int InterpreterTranslateSingle(ARMul_State* cpu, int& bb_start, u32 addr)
875 894
876static int clz(unsigned int x) { 895static int clz(unsigned int x) {
877 int n; 896 int n;
878 if (x == 0) return (32); 897 if (x == 0)
898 return (32);
879 n = 1; 899 n = 1;
880 if ((x >> 16) == 0) { n = n + 16; x = x << 16;} 900 if ((x >> 16) == 0) {
881 if ((x >> 24) == 0) { n = n + 8; x = x << 8;} 901 n = n + 16;
882 if ((x >> 28) == 0) { n = n + 4; x = x << 4;} 902 x = x << 16;
883 if ((x >> 30) == 0) { n = n + 2; x = x << 2;} 903 }
904 if ((x >> 24) == 0) {
905 n = n + 8;
906 x = x << 8;
907 }
908 if ((x >> 28) == 0) {
909 n = n + 4;
910 x = x << 4;
911 }
912 if ((x >> 30) == 0) {
913 n = n + 2;
914 x = x << 2;
915 }
884 n = n - (x >> 31); 916 n = n - (x >> 31);
885 return n; 917 return n;
886} 918}
@@ -892,310 +924,698 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
892 924
893 GDBStub::BreakpointAddress breakpoint_data; 925 GDBStub::BreakpointAddress breakpoint_data;
894 926
895 #undef RM 927#undef RM
896 #undef RS 928#undef RS
897 929
898 #define CRn inst_cream->crn 930#define CRn inst_cream->crn
899 #define OPCODE_1 inst_cream->opcode_1 931#define OPCODE_1 inst_cream->opcode_1
900 #define OPCODE_2 inst_cream->opcode_2 932#define OPCODE_2 inst_cream->opcode_2
901 #define CRm inst_cream->crm 933#define CRm inst_cream->crm
902 #define RD cpu->Reg[inst_cream->Rd] 934#define RD cpu->Reg[inst_cream->Rd]
903 #define RD2 cpu->Reg[inst_cream->Rd + 1] 935#define RD2 cpu->Reg[inst_cream->Rd + 1]
904 #define RN cpu->Reg[inst_cream->Rn] 936#define RN cpu->Reg[inst_cream->Rn]
905 #define RM cpu->Reg[inst_cream->Rm] 937#define RM cpu->Reg[inst_cream->Rm]
906 #define RS cpu->Reg[inst_cream->Rs] 938#define RS cpu->Reg[inst_cream->Rs]
907 #define RDHI cpu->Reg[inst_cream->RdHi] 939#define RDHI cpu->Reg[inst_cream->RdHi]
908 #define RDLO cpu->Reg[inst_cream->RdLo] 940#define RDLO cpu->Reg[inst_cream->RdLo]
909 #define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4) 941#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) 942#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) 943#define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand)
912 944
913 #define FETCH_INST if (inst_base->br != TransExtData::NON_BRANCH) goto DISPATCH; \ 945#define FETCH_INST \
914 inst_base = (arm_inst *)&trans_cache_buf[ptr] 946 if (inst_base->br != TransExtData::NON_BRANCH) \
915 947 goto DISPATCH; \
916 #define INC_PC(l) ptr += sizeof(arm_inst) + l 948 inst_base = (arm_inst*)&trans_cache_buf[ptr]
917 #define INC_PC_STUB ptr += sizeof(arm_inst) 949
918 950#define INC_PC(l) ptr += sizeof(arm_inst) + l
919#define GDB_BP_CHECK \ 951#define INC_PC_STUB ptr += sizeof(arm_inst)
920 cpu->Cpsr &= ~(1 << 5); \ 952
921 cpu->Cpsr |= cpu->TFlag << 5; \ 953#define GDB_BP_CHECK \
922 if (GDBStub::g_server_enabled) { \ 954 cpu->Cpsr &= ~(1 << 5); \
923 if (GDBStub::IsMemoryBreak() || (breakpoint_data.type != GDBStub::BreakpointType::None && PC == breakpoint_data.address)) { \ 955 cpu->Cpsr |= cpu->TFlag << 5; \
924 GDBStub::Break(); \ 956 if (GDBStub::g_server_enabled) { \
925 goto END; \ 957 if (GDBStub::IsMemoryBreak() || (breakpoint_data.type != GDBStub::BreakpointType::None && \
926 } \ 958 PC == breakpoint_data.address)) { \
959 GDBStub::Break(); \
960 goto END; \
961 } \
927 } 962 }
928 963
929// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a 964// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a
930// clunky switch statement. 965// clunky switch statement.
931#if defined __GNUC__ || defined __clang__ 966#if defined __GNUC__ || defined __clang__
932#define GOTO_NEXT_INST \ 967#define GOTO_NEXT_INST \
933 GDB_BP_CHECK; \ 968 GDB_BP_CHECK; \
934 if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ 969 if (num_instrs >= cpu->NumInstrsToExecute) \
935 num_instrs++; \ 970 goto END; \
936 goto *InstLabel[inst_base->idx] 971 num_instrs++; \
972 goto* InstLabel[inst_base->idx]
937#else 973#else
938#define GOTO_NEXT_INST \ 974#define GOTO_NEXT_INST \
939 GDB_BP_CHECK; \ 975 GDB_BP_CHECK; \
940 if (num_instrs >= cpu->NumInstrsToExecute) goto END; \ 976 if (num_instrs >= cpu->NumInstrsToExecute) \
941 num_instrs++; \ 977 goto END; \
942 switch(inst_base->idx) { \ 978 num_instrs++; \
943 case 0: goto VMLA_INST; \ 979 switch (inst_base->idx) { \
944 case 1: goto VMLS_INST; \ 980 case 0: \
945 case 2: goto VNMLA_INST; \ 981 goto VMLA_INST; \
946 case 3: goto VNMLS_INST; \ 982 case 1: \
947 case 4: goto VNMUL_INST; \ 983 goto VMLS_INST; \
948 case 5: goto VMUL_INST; \ 984 case 2: \
949 case 6: goto VADD_INST; \ 985 goto VNMLA_INST; \
950 case 7: goto VSUB_INST; \ 986 case 3: \
951 case 8: goto VDIV_INST; \ 987 goto VNMLS_INST; \
952 case 9: goto VMOVI_INST; \ 988 case 4: \
953 case 10: goto VMOVR_INST; \ 989 goto VNMUL_INST; \
954 case 11: goto VABS_INST; \ 990 case 5: \
955 case 12: goto VNEG_INST; \ 991 goto VMUL_INST; \
956 case 13: goto VSQRT_INST; \ 992 case 6: \
957 case 14: goto VCMP_INST; \ 993 goto VADD_INST; \
958 case 15: goto VCMP2_INST; \ 994 case 7: \
959 case 16: goto VCVTBDS_INST; \ 995 goto VSUB_INST; \
960 case 17: goto VCVTBFF_INST; \ 996 case 8: \
961 case 18: goto VCVTBFI_INST; \ 997 goto VDIV_INST; \
962 case 19: goto VMOVBRS_INST; \ 998 case 9: \
963 case 20: goto VMSR_INST; \ 999 goto VMOVI_INST; \
964 case 21: goto VMOVBRC_INST; \ 1000 case 10: \
965 case 22: goto VMRS_INST; \ 1001 goto VMOVR_INST; \
966 case 23: goto VMOVBCR_INST; \ 1002 case 11: \
967 case 24: goto VMOVBRRSS_INST; \ 1003 goto VABS_INST; \
968 case 25: goto VMOVBRRD_INST; \ 1004 case 12: \
969 case 26: goto VSTR_INST; \ 1005 goto VNEG_INST; \
970 case 27: goto VPUSH_INST; \ 1006 case 13: \
971 case 28: goto VSTM_INST; \ 1007 goto VSQRT_INST; \
972 case 29: goto VPOP_INST; \ 1008 case 14: \
973 case 30: goto VLDR_INST; \ 1009 goto VCMP_INST; \
974 case 31: goto VLDM_INST ; \ 1010 case 15: \
975 case 32: goto SRS_INST; \ 1011 goto VCMP2_INST; \
976 case 33: goto RFE_INST; \ 1012 case 16: \
977 case 34: goto BKPT_INST; \ 1013 goto VCVTBDS_INST; \
978 case 35: goto BLX_INST; \ 1014 case 17: \
979 case 36: goto CPS_INST; \ 1015 goto VCVTBFF_INST; \
980 case 37: goto PLD_INST; \ 1016 case 18: \
981 case 38: goto SETEND_INST; \ 1017 goto VCVTBFI_INST; \
982 case 39: goto CLREX_INST; \ 1018 case 19: \
983 case 40: goto REV16_INST; \ 1019 goto VMOVBRS_INST; \
984 case 41: goto USAD8_INST; \ 1020 case 20: \
985 case 42: goto SXTB_INST; \ 1021 goto VMSR_INST; \
986 case 43: goto UXTB_INST; \ 1022 case 21: \
987 case 44: goto SXTH_INST; \ 1023 goto VMOVBRC_INST; \
988 case 45: goto SXTB16_INST; \ 1024 case 22: \
989 case 46: goto UXTH_INST; \ 1025 goto VMRS_INST; \
990 case 47: goto UXTB16_INST; \ 1026 case 23: \
991 case 48: goto CPY_INST; \ 1027 goto VMOVBCR_INST; \
992 case 49: goto UXTAB_INST; \ 1028 case 24: \
993 case 50: goto SSUB8_INST; \ 1029 goto VMOVBRRSS_INST; \
994 case 51: goto SHSUB8_INST; \ 1030 case 25: \
995 case 52: goto SSUBADDX_INST; \ 1031 goto VMOVBRRD_INST; \
996 case 53: goto STREX_INST; \ 1032 case 26: \
997 case 54: goto STREXB_INST; \ 1033 goto VSTR_INST; \
998 case 55: goto SWP_INST; \ 1034 case 27: \
999 case 56: goto SWPB_INST; \ 1035 goto VPUSH_INST; \
1000 case 57: goto SSUB16_INST; \ 1036 case 28: \
1001 case 58: goto SSAT16_INST; \ 1037 goto VSTM_INST; \
1002 case 59: goto SHSUBADDX_INST; \ 1038 case 29: \
1003 case 60: goto QSUBADDX_INST; \ 1039 goto VPOP_INST; \
1004 case 61: goto SHADDSUBX_INST; \ 1040 case 30: \
1005 case 62: goto SHADD8_INST; \ 1041 goto VLDR_INST; \
1006 case 63: goto SHADD16_INST; \ 1042 case 31: \
1007 case 64: goto SEL_INST; \ 1043 goto VLDM_INST; \
1008 case 65: goto SADDSUBX_INST; \ 1044 case 32: \
1009 case 66: goto SADD8_INST; \ 1045 goto SRS_INST; \
1010 case 67: goto SADD16_INST; \ 1046 case 33: \
1011 case 68: goto SHSUB16_INST; \ 1047 goto RFE_INST; \
1012 case 69: goto UMAAL_INST; \ 1048 case 34: \
1013 case 70: goto UXTAB16_INST; \ 1049 goto BKPT_INST; \
1014 case 71: goto USUBADDX_INST; \ 1050 case 35: \
1015 case 72: goto USUB8_INST; \ 1051 goto BLX_INST; \
1016 case 73: goto USUB16_INST; \ 1052 case 36: \
1017 case 74: goto USAT16_INST; \ 1053 goto CPS_INST; \
1018 case 75: goto USADA8_INST; \ 1054 case 37: \
1019 case 76: goto UQSUBADDX_INST; \ 1055 goto PLD_INST; \
1020 case 77: goto UQSUB8_INST; \ 1056 case 38: \
1021 case 78: goto UQSUB16_INST; \ 1057 goto SETEND_INST; \
1022 case 79: goto UQADDSUBX_INST; \ 1058 case 39: \
1023 case 80: goto UQADD8_INST; \ 1059 goto CLREX_INST; \
1024 case 81: goto UQADD16_INST; \ 1060 case 40: \
1025 case 82: goto SXTAB_INST; \ 1061 goto REV16_INST; \
1026 case 83: goto UHSUBADDX_INST; \ 1062 case 41: \
1027 case 84: goto UHSUB8_INST; \ 1063 goto USAD8_INST; \
1028 case 85: goto UHSUB16_INST; \ 1064 case 42: \
1029 case 86: goto UHADDSUBX_INST; \ 1065 goto SXTB_INST; \
1030 case 87: goto UHADD8_INST; \ 1066 case 43: \
1031 case 88: goto UHADD16_INST; \ 1067 goto UXTB_INST; \
1032 case 89: goto UADDSUBX_INST; \ 1068 case 44: \
1033 case 90: goto UADD8_INST; \ 1069 goto SXTH_INST; \
1034 case 91: goto UADD16_INST; \ 1070 case 45: \
1035 case 92: goto SXTAH_INST; \ 1071 goto SXTB16_INST; \
1036 case 93: goto SXTAB16_INST; \ 1072 case 46: \
1037 case 94: goto QADD8_INST; \ 1073 goto UXTH_INST; \
1038 case 95: goto BXJ_INST; \ 1074 case 47: \
1039 case 96: goto CLZ_INST; \ 1075 goto UXTB16_INST; \
1040 case 97: goto UXTAH_INST; \ 1076 case 48: \
1041 case 98: goto BX_INST; \ 1077 goto CPY_INST; \
1042 case 99: goto REV_INST; \ 1078 case 49: \
1043 case 100: goto BLX_INST; \ 1079 goto UXTAB_INST; \
1044 case 101: goto REVSH_INST; \ 1080 case 50: \
1045 case 102: goto QADD_INST; \ 1081 goto SSUB8_INST; \
1046 case 103: goto QADD16_INST; \ 1082 case 51: \
1047 case 104: goto QADDSUBX_INST; \ 1083 goto SHSUB8_INST; \
1048 case 105: goto LDREX_INST; \ 1084 case 52: \
1049 case 106: goto QDADD_INST; \ 1085 goto SSUBADDX_INST; \
1050 case 107: goto QDSUB_INST; \ 1086 case 53: \
1051 case 108: goto QSUB_INST; \ 1087 goto STREX_INST; \
1052 case 109: goto LDREXB_INST; \ 1088 case 54: \
1053 case 110: goto QSUB8_INST; \ 1089 goto STREXB_INST; \
1054 case 111: goto QSUB16_INST; \ 1090 case 55: \
1055 case 112: goto SMUAD_INST; \ 1091 goto SWP_INST; \
1056 case 113: goto SMMUL_INST; \ 1092 case 56: \
1057 case 114: goto SMUSD_INST; \ 1093 goto SWPB_INST; \
1058 case 115: goto SMLSD_INST; \ 1094 case 57: \
1059 case 116: goto SMLSLD_INST; \ 1095 goto SSUB16_INST; \
1060 case 117: goto SMMLA_INST; \ 1096 case 58: \
1061 case 118: goto SMMLS_INST; \ 1097 goto SSAT16_INST; \
1062 case 119: goto SMLALD_INST; \ 1098 case 59: \
1063 case 120: goto SMLAD_INST; \ 1099 goto SHSUBADDX_INST; \
1064 case 121: goto SMLAW_INST; \ 1100 case 60: \
1065 case 122: goto SMULW_INST; \ 1101 goto QSUBADDX_INST; \
1066 case 123: goto PKHTB_INST; \ 1102 case 61: \
1067 case 124: goto PKHBT_INST; \ 1103 goto SHADDSUBX_INST; \
1068 case 125: goto SMUL_INST; \ 1104 case 62: \
1069 case 126: goto SMLALXY_INST; \ 1105 goto SHADD8_INST; \
1070 case 127: goto SMLA_INST; \ 1106 case 63: \
1071 case 128: goto MCRR_INST; \ 1107 goto SHADD16_INST; \
1072 case 129: goto MRRC_INST; \ 1108 case 64: \
1073 case 130: goto CMP_INST; \ 1109 goto SEL_INST; \
1074 case 131: goto TST_INST; \ 1110 case 65: \
1075 case 132: goto TEQ_INST; \ 1111 goto SADDSUBX_INST; \
1076 case 133: goto CMN_INST; \ 1112 case 66: \
1077 case 134: goto SMULL_INST; \ 1113 goto SADD8_INST; \
1078 case 135: goto UMULL_INST; \ 1114 case 67: \
1079 case 136: goto UMLAL_INST; \ 1115 goto SADD16_INST; \
1080 case 137: goto SMLAL_INST; \ 1116 case 68: \
1081 case 138: goto MUL_INST; \ 1117 goto SHSUB16_INST; \
1082 case 139: goto MLA_INST; \ 1118 case 69: \
1083 case 140: goto SSAT_INST; \ 1119 goto UMAAL_INST; \
1084 case 141: goto USAT_INST; \ 1120 case 70: \
1085 case 142: goto MRS_INST; \ 1121 goto UXTAB16_INST; \
1086 case 143: goto MSR_INST; \ 1122 case 71: \
1087 case 144: goto AND_INST; \ 1123 goto USUBADDX_INST; \
1088 case 145: goto BIC_INST; \ 1124 case 72: \
1089 case 146: goto LDM_INST; \ 1125 goto USUB8_INST; \
1090 case 147: goto EOR_INST; \ 1126 case 73: \
1091 case 148: goto ADD_INST; \ 1127 goto USUB16_INST; \
1092 case 149: goto RSB_INST; \ 1128 case 74: \
1093 case 150: goto RSC_INST; \ 1129 goto USAT16_INST; \
1094 case 151: goto SBC_INST; \ 1130 case 75: \
1095 case 152: goto ADC_INST; \ 1131 goto USADA8_INST; \
1096 case 153: goto SUB_INST; \ 1132 case 76: \
1097 case 154: goto ORR_INST; \ 1133 goto UQSUBADDX_INST; \
1098 case 155: goto MVN_INST; \ 1134 case 77: \
1099 case 156: goto MOV_INST; \ 1135 goto UQSUB8_INST; \
1100 case 157: goto STM_INST; \ 1136 case 78: \
1101 case 158: goto LDM_INST; \ 1137 goto UQSUB16_INST; \
1102 case 159: goto LDRSH_INST; \ 1138 case 79: \
1103 case 160: goto STM_INST; \ 1139 goto UQADDSUBX_INST; \
1104 case 161: goto LDM_INST; \ 1140 case 80: \
1105 case 162: goto LDRSB_INST; \ 1141 goto UQADD8_INST; \
1106 case 163: goto STRD_INST; \ 1142 case 81: \
1107 case 164: goto LDRH_INST; \ 1143 goto UQADD16_INST; \
1108 case 165: goto STRH_INST; \ 1144 case 82: \
1109 case 166: goto LDRD_INST; \ 1145 goto SXTAB_INST; \
1110 case 167: goto STRT_INST; \ 1146 case 83: \
1111 case 168: goto STRBT_INST; \ 1147 goto UHSUBADDX_INST; \
1112 case 169: goto LDRBT_INST; \ 1148 case 84: \
1113 case 170: goto LDRT_INST; \ 1149 goto UHSUB8_INST; \
1114 case 171: goto MRC_INST; \ 1150 case 85: \
1115 case 172: goto MCR_INST; \ 1151 goto UHSUB16_INST; \
1116 case 173: goto MSR_INST; \ 1152 case 86: \
1117 case 174: goto MSR_INST; \ 1153 goto UHADDSUBX_INST; \
1118 case 175: goto MSR_INST; \ 1154 case 87: \
1119 case 176: goto MSR_INST; \ 1155 goto UHADD8_INST; \
1120 case 177: goto MSR_INST; \ 1156 case 88: \
1121 case 178: goto LDRB_INST; \ 1157 goto UHADD16_INST; \
1122 case 179: goto STRB_INST; \ 1158 case 89: \
1123 case 180: goto LDR_INST; \ 1159 goto UADDSUBX_INST; \
1124 case 181: goto LDRCOND_INST ; \ 1160 case 90: \
1125 case 182: goto STR_INST; \ 1161 goto UADD8_INST; \
1126 case 183: goto CDP_INST; \ 1162 case 91: \
1127 case 184: goto STC_INST; \ 1163 goto UADD16_INST; \
1128 case 185: goto LDC_INST; \ 1164 case 92: \
1129 case 186: goto LDREXD_INST; \ 1165 goto SXTAH_INST; \
1130 case 187: goto STREXD_INST; \ 1166 case 93: \
1131 case 188: goto LDREXH_INST; \ 1167 goto SXTAB16_INST; \
1132 case 189: goto STREXH_INST; \ 1168 case 94: \
1133 case 190: goto NOP_INST; \ 1169 goto QADD8_INST; \
1134 case 191: goto YIELD_INST; \ 1170 case 95: \
1135 case 192: goto WFE_INST; \ 1171 goto BXJ_INST; \
1136 case 193: goto WFI_INST; \ 1172 case 96: \
1137 case 194: goto SEV_INST; \ 1173 goto CLZ_INST; \
1138 case 195: goto SWI_INST; \ 1174 case 97: \
1139 case 196: goto BBL_INST; \ 1175 goto UXTAH_INST; \
1140 case 197: goto B_2_THUMB ; \ 1176 case 98: \
1141 case 198: goto B_COND_THUMB ; \ 1177 goto BX_INST; \
1142 case 199: goto BL_1_THUMB ; \ 1178 case 99: \
1143 case 200: goto BL_2_THUMB ; \ 1179 goto REV_INST; \
1144 case 201: goto BLX_1_THUMB ; \ 1180 case 100: \
1145 case 202: goto DISPATCH; \ 1181 goto BLX_INST; \
1146 case 203: goto INIT_INST_LENGTH; \ 1182 case 101: \
1147 case 204: goto END; \ 1183 goto REVSH_INST; \
1184 case 102: \
1185 goto QADD_INST; \
1186 case 103: \
1187 goto QADD16_INST; \
1188 case 104: \
1189 goto QADDSUBX_INST; \
1190 case 105: \
1191 goto LDREX_INST; \
1192 case 106: \
1193 goto QDADD_INST; \
1194 case 107: \
1195 goto QDSUB_INST; \
1196 case 108: \
1197 goto QSUB_INST; \
1198 case 109: \
1199 goto LDREXB_INST; \
1200 case 110: \
1201 goto QSUB8_INST; \
1202 case 111: \
1203 goto QSUB16_INST; \
1204 case 112: \
1205 goto SMUAD_INST; \
1206 case 113: \
1207 goto SMMUL_INST; \
1208 case 114: \
1209 goto SMUSD_INST; \
1210 case 115: \
1211 goto SMLSD_INST; \
1212 case 116: \
1213 goto SMLSLD_INST; \
1214 case 117: \
1215 goto SMMLA_INST; \
1216 case 118: \
1217 goto SMMLS_INST; \
1218 case 119: \
1219 goto SMLALD_INST; \
1220 case 120: \
1221 goto SMLAD_INST; \
1222 case 121: \
1223 goto SMLAW_INST; \
1224 case 122: \
1225 goto SMULW_INST; \
1226 case 123: \
1227 goto PKHTB_INST; \
1228 case 124: \
1229 goto PKHBT_INST; \
1230 case 125: \
1231 goto SMUL_INST; \
1232 case 126: \
1233 goto SMLALXY_INST; \
1234 case 127: \
1235 goto SMLA_INST; \
1236 case 128: \
1237 goto MCRR_INST; \
1238 case 129: \
1239 goto MRRC_INST; \
1240 case 130: \
1241 goto CMP_INST; \
1242 case 131: \
1243 goto TST_INST; \
1244 case 132: \
1245 goto TEQ_INST; \
1246 case 133: \
1247 goto CMN_INST; \
1248 case 134: \
1249 goto SMULL_INST; \
1250 case 135: \
1251 goto UMULL_INST; \
1252 case 136: \
1253 goto UMLAL_INST; \
1254 case 137: \
1255 goto SMLAL_INST; \
1256 case 138: \
1257 goto MUL_INST; \
1258 case 139: \
1259 goto MLA_INST; \
1260 case 140: \
1261 goto SSAT_INST; \
1262 case 141: \
1263 goto USAT_INST; \
1264 case 142: \
1265 goto MRS_INST; \
1266 case 143: \
1267 goto MSR_INST; \
1268 case 144: \
1269 goto AND_INST; \
1270 case 145: \
1271 goto BIC_INST; \
1272 case 146: \
1273 goto LDM_INST; \
1274 case 147: \
1275 goto EOR_INST; \
1276 case 148: \
1277 goto ADD_INST; \
1278 case 149: \
1279 goto RSB_INST; \
1280 case 150: \
1281 goto RSC_INST; \
1282 case 151: \
1283 goto SBC_INST; \
1284 case 152: \
1285 goto ADC_INST; \
1286 case 153: \
1287 goto SUB_INST; \
1288 case 154: \
1289 goto ORR_INST; \
1290 case 155: \
1291 goto MVN_INST; \
1292 case 156: \
1293 goto MOV_INST; \
1294 case 157: \
1295 goto STM_INST; \
1296 case 158: \
1297 goto LDM_INST; \
1298 case 159: \
1299 goto LDRSH_INST; \
1300 case 160: \
1301 goto STM_INST; \
1302 case 161: \
1303 goto LDM_INST; \
1304 case 162: \
1305 goto LDRSB_INST; \
1306 case 163: \
1307 goto STRD_INST; \
1308 case 164: \
1309 goto LDRH_INST; \
1310 case 165: \
1311 goto STRH_INST; \
1312 case 166: \
1313 goto LDRD_INST; \
1314 case 167: \
1315 goto STRT_INST; \
1316 case 168: \
1317 goto STRBT_INST; \
1318 case 169: \
1319 goto LDRBT_INST; \
1320 case 170: \
1321 goto LDRT_INST; \
1322 case 171: \
1323 goto MRC_INST; \
1324 case 172: \
1325 goto MCR_INST; \
1326 case 173: \
1327 goto MSR_INST; \
1328 case 174: \
1329 goto MSR_INST; \
1330 case 175: \
1331 goto MSR_INST; \
1332 case 176: \
1333 goto MSR_INST; \
1334 case 177: \
1335 goto MSR_INST; \
1336 case 178: \
1337 goto LDRB_INST; \
1338 case 179: \
1339 goto STRB_INST; \
1340 case 180: \
1341 goto LDR_INST; \
1342 case 181: \
1343 goto LDRCOND_INST; \
1344 case 182: \
1345 goto STR_INST; \
1346 case 183: \
1347 goto CDP_INST; \
1348 case 184: \
1349 goto STC_INST; \
1350 case 185: \
1351 goto LDC_INST; \
1352 case 186: \
1353 goto LDREXD_INST; \
1354 case 187: \
1355 goto STREXD_INST; \
1356 case 188: \
1357 goto LDREXH_INST; \
1358 case 189: \
1359 goto STREXH_INST; \
1360 case 190: \
1361 goto NOP_INST; \
1362 case 191: \
1363 goto YIELD_INST; \
1364 case 192: \
1365 goto WFE_INST; \
1366 case 193: \
1367 goto WFI_INST; \
1368 case 194: \
1369 goto SEV_INST; \
1370 case 195: \
1371 goto SWI_INST; \
1372 case 196: \
1373 goto BBL_INST; \
1374 case 197: \
1375 goto B_2_THUMB; \
1376 case 198: \
1377 goto B_COND_THUMB; \
1378 case 199: \
1379 goto BL_1_THUMB; \
1380 case 200: \
1381 goto BL_2_THUMB; \
1382 case 201: \
1383 goto BLX_1_THUMB; \
1384 case 202: \
1385 goto DISPATCH; \
1386 case 203: \
1387 goto INIT_INST_LENGTH; \
1388 case 204: \
1389 goto END; \
1148 } 1390 }
1149#endif 1391#endif
1150 1392
1151 #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0) 1393#define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0)
1152 #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1) 1394#define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1)
1153 #define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out) 1395#define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out)
1154 1396
1155 #define SAVE_NZCVT cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | \ 1397#define SAVE_NZCVT \
1156 (cpu->NFlag << 31) | \ 1398 cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | (cpu->NFlag << 31) | (cpu->ZFlag << 30) | \
1157 (cpu->ZFlag << 30) | \ 1399 (cpu->CFlag << 29) | (cpu->VFlag << 28) | (cpu->TFlag << 5)
1158 (cpu->CFlag << 29) | \ 1400#define LOAD_NZCVT \
1159 (cpu->VFlag << 28) | \ 1401 cpu->NFlag = (cpu->Cpsr >> 31); \
1160 (cpu->TFlag << 5) 1402 cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \
1161 #define LOAD_NZCVT cpu->NFlag = (cpu->Cpsr >> 31); \ 1403 cpu->CFlag = (cpu->Cpsr >> 29) & 1; \
1162 cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \ 1404 cpu->VFlag = (cpu->Cpsr >> 28) & 1; \
1163 cpu->CFlag = (cpu->Cpsr >> 29) & 1; \ 1405 cpu->TFlag = (cpu->Cpsr >> 5) & 1;
1164 cpu->VFlag = (cpu->Cpsr >> 28) & 1; \ 1406
1165 cpu->TFlag = (cpu->Cpsr >> 5) & 1; 1407#define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE)
1166 1408#define PC (cpu->Reg[15])
1167 #define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE) 1409
1168 #define PC (cpu->Reg[15]) 1410// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback
1169 1411// 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__ 1412#if defined __GNUC__ || defined __clang__
1173 void *InstLabel[] = { 1413 void* InstLabel[] = {&&VMLA_INST,
1174 &&VMLA_INST, &&VMLS_INST, &&VNMLA_INST, &&VNMLS_INST, &&VNMUL_INST, &&VMUL_INST, &&VADD_INST, &&VSUB_INST, 1414 &&VMLS_INST,
1175 &&VDIV_INST, &&VMOVI_INST, &&VMOVR_INST, &&VABS_INST, &&VNEG_INST, &&VSQRT_INST, &&VCMP_INST, &&VCMP2_INST, &&VCVTBDS_INST, 1415 &&VNMLA_INST,
1176 &&VCVTBFF_INST, &&VCVTBFI_INST, &&VMOVBRS_INST, &&VMSR_INST, &&VMOVBRC_INST, &&VMRS_INST, &&VMOVBCR_INST, &&VMOVBRRSS_INST, 1416 &&VNMLS_INST,
1177 &&VMOVBRRD_INST, &&VSTR_INST, &&VPUSH_INST, &&VSTM_INST, &&VPOP_INST, &&VLDR_INST, &&VLDM_INST, 1417 &&VNMUL_INST,
1178 1418 &&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, 1419 &&VADD_INST,
1180 &&UXTB_INST,&&SXTH_INST,&&SXTB16_INST,&&UXTH_INST,&&UXTB16_INST,&&CPY_INST,&&UXTAB_INST,&&SSUB8_INST,&&SHSUB8_INST,&&SSUBADDX_INST, 1420 &&VSUB_INST,
1181 &&STREX_INST,&&STREXB_INST,&&SWP_INST,&&SWPB_INST,&&SSUB16_INST,&&SSAT16_INST,&&SHSUBADDX_INST,&&QSUBADDX_INST,&&SHADDSUBX_INST, 1421 &&VDIV_INST,
1182 &&SHADD8_INST,&&SHADD16_INST,&&SEL_INST,&&SADDSUBX_INST,&&SADD8_INST,&&SADD16_INST,&&SHSUB16_INST,&&UMAAL_INST,&&UXTAB16_INST, 1422 &&VMOVI_INST,
1183 &&USUBADDX_INST,&&USUB8_INST,&&USUB16_INST,&&USAT16_INST,&&USADA8_INST,&&UQSUBADDX_INST,&&UQSUB8_INST,&&UQSUB16_INST, 1423 &&VMOVR_INST,
1184 &&UQADDSUBX_INST,&&UQADD8_INST,&&UQADD16_INST,&&SXTAB_INST,&&UHSUBADDX_INST,&&UHSUB8_INST,&&UHSUB16_INST,&&UHADDSUBX_INST,&&UHADD8_INST, 1424 &&VABS_INST,
1185 &&UHADD16_INST,&&UADDSUBX_INST,&&UADD8_INST,&&UADD16_INST,&&SXTAH_INST,&&SXTAB16_INST,&&QADD8_INST,&&BXJ_INST,&&CLZ_INST,&&UXTAH_INST, 1425 &&VNEG_INST,
1186 &&BX_INST,&&REV_INST,&&BLX_INST,&&REVSH_INST,&&QADD_INST,&&QADD16_INST,&&QADDSUBX_INST,&&LDREX_INST,&&QDADD_INST,&&QDSUB_INST, 1426 &&VSQRT_INST,
1187 &&QSUB_INST,&&LDREXB_INST,&&QSUB8_INST,&&QSUB16_INST,&&SMUAD_INST,&&SMMUL_INST,&&SMUSD_INST,&&SMLSD_INST,&&SMLSLD_INST,&&SMMLA_INST, 1427 &&VCMP_INST,
1188 &&SMMLS_INST,&&SMLALD_INST,&&SMLAD_INST,&&SMLAW_INST,&&SMULW_INST,&&PKHTB_INST,&&PKHBT_INST,&&SMUL_INST,&&SMLALXY_INST,&&SMLA_INST, 1428 &&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, 1429 &&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, 1430 &&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, 1431 &&VCVTBFI_INST,
1192 &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST, 1432 &&VMOVBRS_INST,
1193 &&MSR_INST, &&MSR_INST, &&MSR_INST, &&MSR_INST, &&MSR_INST, 1433 &&VMSR_INST,
1194 &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST, &&LDREXD_INST, 1434 &&VMOVBRC_INST,
1195 &&STREXD_INST,&&LDREXH_INST,&&STREXH_INST, &&NOP_INST, &&YIELD_INST, &&WFE_INST, &&WFI_INST, &&SEV_INST, &&SWI_INST,&&BBL_INST, 1435 &&VMRS_INST,
1196 &&B_2_THUMB, &&B_COND_THUMB,&&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH, 1436 &&VMOVBCR_INST,
1197 &&INIT_INST_LENGTH,&&END 1437 &&VMOVBRRSS_INST,
1198 }; 1438 &&VMOVBRRD_INST,
1439 &&VSTR_INST,
1440 &&VPUSH_INST,
1441 &&VSTM_INST,
1442 &&VPOP_INST,
1443 &&VLDR_INST,
1444 &&VLDM_INST,
1445
1446 &&SRS_INST,
1447 &&RFE_INST,
1448 &&BKPT_INST,
1449 &&BLX_INST,
1450 &&CPS_INST,
1451 &&PLD_INST,
1452 &&SETEND_INST,
1453 &&CLREX_INST,
1454 &&REV16_INST,
1455 &&USAD8_INST,
1456 &&SXTB_INST,
1457 &&UXTB_INST,
1458 &&SXTH_INST,
1459 &&SXTB16_INST,
1460 &&UXTH_INST,
1461 &&UXTB16_INST,
1462 &&CPY_INST,
1463 &&UXTAB_INST,
1464 &&SSUB8_INST,
1465 &&SHSUB8_INST,
1466 &&SSUBADDX_INST,
1467 &&STREX_INST,
1468 &&STREXB_INST,
1469 &&SWP_INST,
1470 &&SWPB_INST,
1471 &&SSUB16_INST,
1472 &&SSAT16_INST,
1473 &&SHSUBADDX_INST,
1474 &&QSUBADDX_INST,
1475 &&SHADDSUBX_INST,
1476 &&SHADD8_INST,
1477 &&SHADD16_INST,
1478 &&SEL_INST,
1479 &&SADDSUBX_INST,
1480 &&SADD8_INST,
1481 &&SADD16_INST,
1482 &&SHSUB16_INST,
1483 &&UMAAL_INST,
1484 &&UXTAB16_INST,
1485 &&USUBADDX_INST,
1486 &&USUB8_INST,
1487 &&USUB16_INST,
1488 &&USAT16_INST,
1489 &&USADA8_INST,
1490 &&UQSUBADDX_INST,
1491 &&UQSUB8_INST,
1492 &&UQSUB16_INST,
1493 &&UQADDSUBX_INST,
1494 &&UQADD8_INST,
1495 &&UQADD16_INST,
1496 &&SXTAB_INST,
1497 &&UHSUBADDX_INST,
1498 &&UHSUB8_INST,
1499 &&UHSUB16_INST,
1500 &&UHADDSUBX_INST,
1501 &&UHADD8_INST,
1502 &&UHADD16_INST,
1503 &&UADDSUBX_INST,
1504 &&UADD8_INST,
1505 &&UADD16_INST,
1506 &&SXTAH_INST,
1507 &&SXTAB16_INST,
1508 &&QADD8_INST,
1509 &&BXJ_INST,
1510 &&CLZ_INST,
1511 &&UXTAH_INST,
1512 &&BX_INST,
1513 &&REV_INST,
1514 &&BLX_INST,
1515 &&REVSH_INST,
1516 &&QADD_INST,
1517 &&QADD16_INST,
1518 &&QADDSUBX_INST,
1519 &&LDREX_INST,
1520 &&QDADD_INST,
1521 &&QDSUB_INST,
1522 &&QSUB_INST,
1523 &&LDREXB_INST,
1524 &&QSUB8_INST,
1525 &&QSUB16_INST,
1526 &&SMUAD_INST,
1527 &&SMMUL_INST,
1528 &&SMUSD_INST,
1529 &&SMLSD_INST,
1530 &&SMLSLD_INST,
1531 &&SMMLA_INST,
1532 &&SMMLS_INST,
1533 &&SMLALD_INST,
1534 &&SMLAD_INST,
1535 &&SMLAW_INST,
1536 &&SMULW_INST,
1537 &&PKHTB_INST,
1538 &&PKHBT_INST,
1539 &&SMUL_INST,
1540 &&SMLALXY_INST,
1541 &&SMLA_INST,
1542 &&MCRR_INST,
1543 &&MRRC_INST,
1544 &&CMP_INST,
1545 &&TST_INST,
1546 &&TEQ_INST,
1547 &&CMN_INST,
1548 &&SMULL_INST,
1549 &&UMULL_INST,
1550 &&UMLAL_INST,
1551 &&SMLAL_INST,
1552 &&MUL_INST,
1553 &&MLA_INST,
1554 &&SSAT_INST,
1555 &&USAT_INST,
1556 &&MRS_INST,
1557 &&MSR_INST,
1558 &&AND_INST,
1559 &&BIC_INST,
1560 &&LDM_INST,
1561 &&EOR_INST,
1562 &&ADD_INST,
1563 &&RSB_INST,
1564 &&RSC_INST,
1565 &&SBC_INST,
1566 &&ADC_INST,
1567 &&SUB_INST,
1568 &&ORR_INST,
1569 &&MVN_INST,
1570 &&MOV_INST,
1571 &&STM_INST,
1572 &&LDM_INST,
1573 &&LDRSH_INST,
1574 &&STM_INST,
1575 &&LDM_INST,
1576 &&LDRSB_INST,
1577 &&STRD_INST,
1578 &&LDRH_INST,
1579 &&STRH_INST,
1580 &&LDRD_INST,
1581 &&STRT_INST,
1582 &&STRBT_INST,
1583 &&LDRBT_INST,
1584 &&LDRT_INST,
1585 &&MRC_INST,
1586 &&MCR_INST,
1587 &&MSR_INST,
1588 &&MSR_INST,
1589 &&MSR_INST,
1590 &&MSR_INST,
1591 &&MSR_INST,
1592 &&LDRB_INST,
1593 &&STRB_INST,
1594 &&LDR_INST,
1595 &&LDRCOND_INST,
1596 &&STR_INST,
1597 &&CDP_INST,
1598 &&STC_INST,
1599 &&LDC_INST,
1600 &&LDREXD_INST,
1601 &&STREXD_INST,
1602 &&LDREXH_INST,
1603 &&STREXH_INST,
1604 &&NOP_INST,
1605 &&YIELD_INST,
1606 &&WFE_INST,
1607 &&WFI_INST,
1608 &&SEV_INST,
1609 &&SWI_INST,
1610 &&BBL_INST,
1611 &&B_2_THUMB,
1612 &&B_COND_THUMB,
1613 &&BL_1_THUMB,
1614 &&BL_2_THUMB,
1615 &&BLX_1_THUMB,
1616 &&DISPATCH,
1617 &&INIT_INST_LENGTH,
1618 &&END};
1199#endif 1619#endif
1200 arm_inst* inst_base; 1620 arm_inst* inst_base;
1201 unsigned int addr; 1621 unsigned int addr;
@@ -1204,516 +1624,517 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
1204 int ptr; 1624 int ptr;
1205 1625
1206 LOAD_NZCVT; 1626 LOAD_NZCVT;
1207 DISPATCH: 1627DISPATCH : {
1208 { 1628 if (!cpu->NirqSig) {
1209 if (!cpu->NirqSig) { 1629 if (!(cpu->Cpsr & 0x80)) {
1210 if (!(cpu->Cpsr & 0x80)) { 1630 goto END;
1211 goto END;
1212 }
1213 } 1631 }
1632 }
1214 1633
1215 if (cpu->TFlag) 1634 if (cpu->TFlag)
1216 cpu->Reg[15] &= 0xfffffffe; 1635 cpu->Reg[15] &= 0xfffffffe;
1217 else 1636 else
1218 cpu->Reg[15] &= 0xfffffffc; 1637 cpu->Reg[15] &= 0xfffffffc;
1219 1638
1220 // Find the cached instruction cream, otherwise translate it... 1639 // Find the cached instruction cream, otherwise translate it...
1221 auto itr = cpu->instruction_cache.find(cpu->Reg[15]); 1640 auto itr = cpu->instruction_cache.find(cpu->Reg[15]);
1222 if (itr != cpu->instruction_cache.end()) { 1641 if (itr != cpu->instruction_cache.end()) {
1223 ptr = itr->second; 1642 ptr = itr->second;
1224 } else if (cpu->NumInstrsToExecute != 1) { 1643 } else if (cpu->NumInstrsToExecute != 1) {
1225 if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) 1644 if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
1226 goto END; 1645 goto END;
1227 } else { 1646 } else {
1228 if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) 1647 if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
1229 goto END; 1648 goto END;
1230 } 1649 }
1231 1650
1232 // Find breakpoint if one exists within the block 1651 // Find breakpoint if one exists within the block
1233 if (GDBStub::g_server_enabled && GDBStub::IsConnected()) { 1652 if (GDBStub::g_server_enabled && GDBStub::IsConnected()) {
1234 breakpoint_data = GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute); 1653 breakpoint_data =
1235 } 1654 GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute);
1655 }
1236 1656
1237 inst_base = (arm_inst *)&trans_cache_buf[ptr]; 1657 inst_base = (arm_inst*)&trans_cache_buf[ptr];
1238 GOTO_NEXT_INST; 1658 GOTO_NEXT_INST;
1659}
1660ADC_INST : {
1661 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1662 adc_inst* const inst_cream = (adc_inst*)inst_base->component;
1663
1664 u32 rn_val = RN;
1665 if (inst_cream->Rn == 15)
1666 rn_val += 2 * cpu->GetInstructionSize();
1667
1668 bool carry;
1669 bool overflow;
1670 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
1671
1672 if (inst_cream->S && (inst_cream->Rd == 15)) {
1673 if (CurrentModeHasSPSR) {
1674 cpu->Cpsr = cpu->Spsr_copy;
1675 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1676 LOAD_NZCVT;
1677 }
1678 } else if (inst_cream->S) {
1679 UPDATE_NFLAG(RD);
1680 UPDATE_ZFLAG(RD);
1681 cpu->CFlag = carry;
1682 cpu->VFlag = overflow;
1683 }
1684 if (inst_cream->Rd == 15) {
1685 INC_PC(sizeof(adc_inst));
1686 goto DISPATCH;
1687 }
1239 } 1688 }
1240 ADC_INST: 1689 cpu->Reg[15] += cpu->GetInstructionSize();
1241 { 1690 INC_PC(sizeof(adc_inst));
1242 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1691 FETCH_INST;
1243 adc_inst* const inst_cream = (adc_inst*)inst_base->component; 1692 GOTO_NEXT_INST;
1693}
1694ADD_INST : {
1695 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1696 add_inst* const inst_cream = (add_inst*)inst_base->component;
1244 1697
1245 u32 rn_val = RN; 1698 u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
1246 if (inst_cream->Rn == 15)
1247 rn_val += 2 * cpu->GetInstructionSize();
1248 1699
1249 bool carry; 1700 bool carry;
1250 bool overflow; 1701 bool overflow;
1251 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); 1702 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
1252 1703
1253 if (inst_cream->S && (inst_cream->Rd == 15)) { 1704 if (inst_cream->S && (inst_cream->Rd == 15)) {
1254 if (CurrentModeHasSPSR) { 1705 if (CurrentModeHasSPSR) {
1255 cpu->Cpsr = cpu->Spsr_copy; 1706 cpu->Cpsr = cpu->Spsr_copy;
1256 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 1707 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
1257 LOAD_NZCVT; 1708 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 } 1709 }
1710 } else if (inst_cream->S) {
1711 UPDATE_NFLAG(RD);
1712 UPDATE_ZFLAG(RD);
1713 cpu->CFlag = carry;
1714 cpu->VFlag = overflow;
1269 } 1715 }
1270 cpu->Reg[15] += cpu->GetInstructionSize(); 1716 if (inst_cream->Rd == 15) {
1271 INC_PC(sizeof(adc_inst)); 1717 INC_PC(sizeof(add_inst));
1272 FETCH_INST; 1718 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 } 1719 }
1303 cpu->Reg[15] += cpu->GetInstructionSize();
1304 INC_PC(sizeof(add_inst));
1305 FETCH_INST;
1306 GOTO_NEXT_INST;
1307 } 1720 }
1308 AND_INST: 1721 cpu->Reg[15] += cpu->GetInstructionSize();
1309 { 1722 INC_PC(sizeof(add_inst));
1310 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1723 FETCH_INST;
1311 and_inst* const inst_cream = (and_inst*)inst_base->component; 1724 GOTO_NEXT_INST;
1725}
1726AND_INST : {
1727 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1728 and_inst* const inst_cream = (and_inst*)inst_base->component;
1312 1729
1313 u32 lop = RN; 1730 u32 lop = RN;
1314 u32 rop = SHIFTER_OPERAND; 1731 u32 rop = SHIFTER_OPERAND;
1315 1732
1316 if (inst_cream->Rn == 15) 1733 if (inst_cream->Rn == 15)
1317 lop += 2 * cpu->GetInstructionSize(); 1734 lop += 2 * cpu->GetInstructionSize();
1318 1735
1319 RD = lop & rop; 1736 RD = lop & rop;
1320 1737
1321 if (inst_cream->S && (inst_cream->Rd == 15)) { 1738 if (inst_cream->S && (inst_cream->Rd == 15)) {
1322 if (CurrentModeHasSPSR) { 1739 if (CurrentModeHasSPSR) {
1323 cpu->Cpsr = cpu->Spsr_copy; 1740 cpu->Cpsr = cpu->Spsr_copy;
1324 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); 1741 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
1325 LOAD_NZCVT; 1742 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 } 1743 }
1744 } else if (inst_cream->S) {
1745 UPDATE_NFLAG(RD);
1746 UPDATE_ZFLAG(RD);
1747 UPDATE_CFLAG_WITH_SC;
1336 } 1748 }
1337 cpu->Reg[15] += cpu->GetInstructionSize(); 1749 if (inst_cream->Rd == 15) {
1338 INC_PC(sizeof(and_inst)); 1750 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; 1751 goto DISPATCH;
1352 } 1752 }
1353 cpu->Reg[15] += cpu->GetInstructionSize(); 1753 }
1754 cpu->Reg[15] += cpu->GetInstructionSize();
1755 INC_PC(sizeof(and_inst));
1756 FETCH_INST;
1757 GOTO_NEXT_INST;
1758}
1759BBL_INST : {
1760 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1761 bbl_inst* inst_cream = (bbl_inst*)inst_base->component;
1762 if (inst_cream->L) {
1763 LINK_RTN_ADDR;
1764 }
1765 SET_PC;
1354 INC_PC(sizeof(bbl_inst)); 1766 INC_PC(sizeof(bbl_inst));
1355 goto DISPATCH; 1767 goto DISPATCH;
1356 } 1768 }
1357 BIC_INST: 1769 cpu->Reg[15] += cpu->GetInstructionSize();
1358 { 1770 INC_PC(sizeof(bbl_inst));
1359 bic_inst *inst_cream = (bic_inst *)inst_base->component; 1771 goto DISPATCH;
1360 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) { 1772}
1361 u32 lop = RN; 1773BIC_INST : {
1362 if (inst_cream->Rn == 15) { 1774 bic_inst* inst_cream = (bic_inst*)inst_base->component;
1363 lop += 2 * cpu->GetInstructionSize(); 1775 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1364 } 1776 u32 lop = RN;
1365 u32 rop = SHIFTER_OPERAND; 1777 if (inst_cream->Rn == 15) {
1366 RD = lop & (~rop); 1778 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 } 1779 }
1394 cpu->Reg[15] += cpu->GetInstructionSize(); 1780 u32 rop = SHIFTER_OPERAND;
1395 INC_PC(sizeof(bkpt_inst)); 1781 RD = lop & (~rop);
1396 FETCH_INST; 1782 if ((inst_cream->S) && (inst_cream->Rd == 15)) {
1397 GOTO_NEXT_INST; 1783 if (CurrentModeHasSPSR) {
1398 } 1784 cpu->Cpsr = cpu->Spsr_copy;
1399 BLX_INST: 1785 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1400 { 1786 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 } 1787 }
1419 INC_PC(sizeof(blx_inst)); 1788 } else if (inst_cream->S) {
1789 UPDATE_NFLAG(RD);
1790 UPDATE_ZFLAG(RD);
1791 UPDATE_CFLAG_WITH_SC;
1792 }
1793 if (inst_cream->Rd == 15) {
1794 INC_PC(sizeof(bic_inst));
1420 goto DISPATCH; 1795 goto DISPATCH;
1421 } 1796 }
1422 cpu->Reg[15] += cpu->GetInstructionSize(); 1797 }
1798 cpu->Reg[15] += cpu->GetInstructionSize();
1799 INC_PC(sizeof(bic_inst));
1800 FETCH_INST;
1801 GOTO_NEXT_INST;
1802}
1803BKPT_INST : {
1804 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1805 bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
1806 LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: 0x%08X", inst_cream->imm);
1807 }
1808 cpu->Reg[15] += cpu->GetInstructionSize();
1809 INC_PC(sizeof(bkpt_inst));
1810 FETCH_INST;
1811 GOTO_NEXT_INST;
1812}
1813BLX_INST : {
1814 blx_inst* inst_cream = (blx_inst*)inst_base->component;
1815 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1816 unsigned int inst = inst_cream->inst;
1817 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
1818 const u32 jump_address = cpu->Reg[inst_cream->val.Rm];
1819 cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
1820 if (cpu->TFlag)
1821 cpu->Reg[14] |= 0x1;
1822 cpu->Reg[15] = jump_address & 0xfffffffe;
1823 cpu->TFlag = jump_address & 0x1;
1824 } else {
1825 cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
1826 cpu->TFlag = 0x1;
1827 int signed_int = inst_cream->val.signed_immed_24;
1828 signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int;
1829 signed_int = signed_int << 2;
1830 cpu->Reg[15] = cpu->Reg[15] + 8 + signed_int + (BIT(inst, 24) << 1);
1831 }
1423 INC_PC(sizeof(blx_inst)); 1832 INC_PC(sizeof(blx_inst));
1424 goto DISPATCH; 1833 goto DISPATCH;
1425 } 1834 }
1835 cpu->Reg[15] += cpu->GetInstructionSize();
1836 INC_PC(sizeof(blx_inst));
1837 goto DISPATCH;
1838}
1426 1839
1427 BX_INST: 1840BX_INST:
1428 BXJ_INST: 1841BXJ_INST : {
1429 { 1842 // 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 1843 // the facilities for Jazelle emulation are not implemented.
1431 // the facilities for Jazelle emulation are not implemented. 1844 //
1432 // 1845 // 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 1846 // fails, then BXJ functions identically like a regular BX instruction.
1434 // fails, then BXJ functions identically like a regular BX instruction. 1847 //
1435 // 1848 // 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
1438 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1439 bx_inst* const inst_cream = (bx_inst*)inst_base->component;
1440 1849
1441 u32 address = RM; 1850 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1851 bx_inst* const inst_cream = (bx_inst*)inst_base->component;
1442 1852
1443 if (inst_cream->Rm == 15) 1853 u32 address = RM;
1444 address += 2 * cpu->GetInstructionSize();
1445 1854
1446 cpu->TFlag = address & 1; 1855 if (inst_cream->Rm == 15)
1447 cpu->Reg[15] = address & 0xfffffffe; 1856 address += 2 * cpu->GetInstructionSize();
1448 INC_PC(sizeof(bx_inst));
1449 goto DISPATCH;
1450 }
1451 1857
1452 cpu->Reg[15] += cpu->GetInstructionSize(); 1858 cpu->TFlag = address & 1;
1859 cpu->Reg[15] = address & 0xfffffffe;
1453 INC_PC(sizeof(bx_inst)); 1860 INC_PC(sizeof(bx_inst));
1454 goto DISPATCH; 1861 goto DISPATCH;
1455 } 1862 }
1456 1863
1457 CDP_INST: 1864 cpu->Reg[15] += cpu->GetInstructionSize();
1458 { 1865 INC_PC(sizeof(bx_inst));
1459 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1866 goto DISPATCH;
1460 // Undefined instruction here 1867}
1461 cpu->NumInstrsToExecute = 0; 1868
1462 return num_instrs; 1869CDP_INST : {
1870 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1871 // Undefined instruction here
1872 cpu->NumInstrsToExecute = 0;
1873 return num_instrs;
1874 }
1875 cpu->Reg[15] += cpu->GetInstructionSize();
1876 INC_PC(sizeof(cdp_inst));
1877 FETCH_INST;
1878 GOTO_NEXT_INST;
1879}
1880
1881CLREX_INST : {
1882 cpu->UnsetExclusiveMemoryAddress();
1883 cpu->Reg[15] += cpu->GetInstructionSize();
1884 INC_PC(sizeof(clrex_inst));
1885 FETCH_INST;
1886 GOTO_NEXT_INST;
1887}
1888CLZ_INST : {
1889 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1890 clz_inst* inst_cream = (clz_inst*)inst_base->component;
1891 RD = clz(RM);
1892 }
1893 cpu->Reg[15] += cpu->GetInstructionSize();
1894 INC_PC(sizeof(clz_inst));
1895 FETCH_INST;
1896 GOTO_NEXT_INST;
1897}
1898CMN_INST : {
1899 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1900 cmn_inst* const inst_cream = (cmn_inst*)inst_base->component;
1901
1902 u32 rn_val = RN;
1903 if (inst_cream->Rn == 15)
1904 rn_val += 2 * cpu->GetInstructionSize();
1905
1906 bool carry;
1907 bool overflow;
1908 u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
1909
1910 UPDATE_NFLAG(result);
1911 UPDATE_ZFLAG(result);
1912 cpu->CFlag = carry;
1913 cpu->VFlag = overflow;
1914 }
1915 cpu->Reg[15] += cpu->GetInstructionSize();
1916 INC_PC(sizeof(cmn_inst));
1917 FETCH_INST;
1918 GOTO_NEXT_INST;
1919}
1920CMP_INST : {
1921 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1922 cmp_inst* const inst_cream = (cmp_inst*)inst_base->component;
1923
1924 u32 rn_val = RN;
1925 if (inst_cream->Rn == 15)
1926 rn_val += 2 * cpu->GetInstructionSize();
1927
1928 bool carry;
1929 bool overflow;
1930 u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
1931
1932 UPDATE_NFLAG(result);
1933 UPDATE_ZFLAG(result);
1934 cpu->CFlag = carry;
1935 cpu->VFlag = overflow;
1936 }
1937 cpu->Reg[15] += cpu->GetInstructionSize();
1938 INC_PC(sizeof(cmp_inst));
1939 FETCH_INST;
1940 GOTO_NEXT_INST;
1941}
1942CPS_INST : {
1943 cps_inst* inst_cream = (cps_inst*)inst_base->component;
1944 u32 aif_val = 0;
1945 u32 aif_mask = 0;
1946 if (cpu->InAPrivilegedMode()) {
1947 if (inst_cream->imod1) {
1948 if (inst_cream->A) {
1949 aif_val |= (inst_cream->imod0 << 8);
1950 aif_mask |= 1 << 8;
1951 }
1952 if (inst_cream->I) {
1953 aif_val |= (inst_cream->imod0 << 7);
1954 aif_mask |= 1 << 7;
1955 }
1956 if (inst_cream->F) {
1957 aif_val |= (inst_cream->imod0 << 6);
1958 aif_mask |= 1 << 6;
1959 }
1960 aif_mask = ~aif_mask;
1961 cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val;
1463 } 1962 }
1464 cpu->Reg[15] += cpu->GetInstructionSize(); 1963 if (inst_cream->mmod) {
1465 INC_PC(sizeof(cdp_inst)); 1964 cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode;
1466 FETCH_INST; 1965 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 } 1966 }
1484 cpu->Reg[15] += cpu->GetInstructionSize(); 1967 }
1485 INC_PC(sizeof(clz_inst)); 1968 cpu->Reg[15] += cpu->GetInstructionSize();
1486 FETCH_INST; 1969 INC_PC(sizeof(cps_inst));
1487 GOTO_NEXT_INST; 1970 FETCH_INST;
1488 } 1971 GOTO_NEXT_INST;
1489 CMN_INST: 1972}
1490 { 1973CPY_INST : {
1491 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1974 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1492 cmn_inst* const inst_cream = (cmn_inst*)inst_base->component; 1975 mov_inst* inst_cream = (mov_inst*)inst_base->component;
1493 1976
1494 u32 rn_val = RN; 1977 RD = SHIFTER_OPERAND;
1495 if (inst_cream->Rn == 15) 1978 if (inst_cream->Rd == 15) {
1496 rn_val += 2 * cpu->GetInstructionSize(); 1979 INC_PC(sizeof(mov_inst));
1497 1980 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 } 1981 }
1507 cpu->Reg[15] += cpu->GetInstructionSize(); 1982 }
1508 INC_PC(sizeof(cmn_inst)); 1983 cpu->Reg[15] += cpu->GetInstructionSize();
1509 FETCH_INST; 1984 INC_PC(sizeof(mov_inst));
1510 GOTO_NEXT_INST; 1985 FETCH_INST;
1511 } 1986 GOTO_NEXT_INST;
1512 CMP_INST: 1987}
1513 { 1988EOR_INST : {
1514 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 1989 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1515 cmp_inst* const inst_cream = (cmp_inst*)inst_base->component; 1990 eor_inst* inst_cream = (eor_inst*)inst_base->component;
1516 1991
1517 u32 rn_val = RN; 1992 u32 lop = RN;
1518 if (inst_cream->Rn == 15) 1993 if (inst_cream->Rn == 15) {
1519 rn_val += 2 * cpu->GetInstructionSize(); 1994 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 } 1995 }
1530 cpu->Reg[15] += cpu->GetInstructionSize(); 1996 u32 rop = SHIFTER_OPERAND;
1531 INC_PC(sizeof(cmp_inst)); 1997 RD = lop ^ rop;
1532 FETCH_INST; 1998 if (inst_cream->S && (inst_cream->Rd == 15)) {
1533 GOTO_NEXT_INST; 1999 if (CurrentModeHasSPSR) {
1534 } 2000 cpu->Cpsr = cpu->Spsr_copy;
1535 CPS_INST: 2001 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1536 { 2002 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 } 2003 }
2004 } else if (inst_cream->S) {
2005 UPDATE_NFLAG(RD);
2006 UPDATE_ZFLAG(RD);
2007 UPDATE_CFLAG_WITH_SC;
2008 }
2009 if (inst_cream->Rd == 15) {
2010 INC_PC(sizeof(eor_inst));
2011 goto DISPATCH;
1561 } 2012 }
1562 cpu->Reg[15] += cpu->GetInstructionSize();
1563 INC_PC(sizeof(cps_inst));
1564 FETCH_INST;
1565 GOTO_NEXT_INST;
1566 } 2013 }
1567 CPY_INST: 2014 cpu->Reg[15] += cpu->GetInstructionSize();
1568 { 2015 INC_PC(sizeof(eor_inst));
1569 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2016 FETCH_INST;
1570 mov_inst* inst_cream = (mov_inst*)inst_base->component; 2017 GOTO_NEXT_INST;
2018}
2019LDC_INST : {
2020 // Instruction not implemented
2021 // LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
2022 cpu->Reg[15] += cpu->GetInstructionSize();
2023 INC_PC(sizeof(ldc_inst));
2024 FETCH_INST;
2025 GOTO_NEXT_INST;
2026}
2027LDM_INST : {
2028 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2029 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2030 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1571 2031
1572 RD = SHIFTER_OPERAND; 2032 unsigned int inst = inst_cream->inst;
1573 if (inst_cream->Rd == 15) { 2033 if (BIT(inst, 22) && !BIT(inst, 15)) {
1574 INC_PC(sizeof(mov_inst)); 2034 for (int i = 0; i < 13; i++) {
1575 goto DISPATCH; 2035 if (BIT(inst, i)) {
1576 } 2036 cpu->Reg[i] = cpu->ReadMemory32(addr);
1577 } 2037 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 } 2038 }
1600 } else if (inst_cream->S) {
1601 UPDATE_NFLAG(RD);
1602 UPDATE_ZFLAG(RD);
1603 UPDATE_CFLAG_WITH_SC;
1604 } 2039 }
1605 if (inst_cream->Rd == 15) { 2040 if (BIT(inst, 13)) {
1606 INC_PC(sizeof(eor_inst)); 2041 if (cpu->Mode == USER32MODE)
1607 goto DISPATCH; 2042 cpu->Reg[13] = cpu->ReadMemory32(addr);
2043 else
2044 cpu->Reg_usr[0] = cpu->ReadMemory32(addr);
2045
2046 addr += 4;
1608 } 2047 }
1609 } 2048 if (BIT(inst, 14)) {
1610 cpu->Reg[15] += cpu->GetInstructionSize(); 2049 if (cpu->Mode == USER32MODE)
1611 INC_PC(sizeof(eor_inst)); 2050 cpu->Reg[14] = cpu->ReadMemory32(addr);
1612 FETCH_INST; 2051 else
1613 GOTO_NEXT_INST; 2052 cpu->Reg_usr[1] = cpu->ReadMemory32(addr);
1614 } 2053
1615 LDC_INST: 2054 addr += 4;
1616 { 2055 }
1617 // Instruction not implemented 2056 } else if (!BIT(inst, 22)) {
1618 //LOG_CRITICAL(Core_ARM11, "unimplemented instruction"); 2057 for (int i = 0; i < 16; i++) {
1619 cpu->Reg[15] += cpu->GetInstructionSize(); 2058 if (BIT(inst, i)) {
1620 INC_PC(sizeof(ldc_inst)); 2059 unsigned int ret = cpu->ReadMemory32(addr);
1621 FETCH_INST; 2060
1622 GOTO_NEXT_INST; 2061 // For armv5t, should enter thumb when bits[0] is non-zero.
1623 } 2062 if (i == 15) {
1624 LDM_INST: 2063 cpu->TFlag = ret & 0x1;
1625 { 2064 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 } 2065 }
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 2066
2067 cpu->Reg[i] = ret;
1644 addr += 4; 2068 addr += 4;
1645 } 2069 }
1646 if (BIT(inst, 14)) { 2070 }
1647 if (cpu->Mode == USER32MODE) 2071 } else if (BIT(inst, 22) && BIT(inst, 15)) {
1648 cpu->Reg[14] = cpu->ReadMemory32(addr); 2072 for (int i = 0; i < 15; i++) {
1649 else 2073 if (BIT(inst, i)) {
1650 cpu->Reg_usr[1] = cpu->ReadMemory32(addr); 2074 cpu->Reg[i] = cpu->ReadMemory32(addr);
1651
1652 addr += 4; 2075 addr += 4;
1653 } 2076 }
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 } 2077 }
1685 2078
1686 if (BIT(inst, 15)) { 2079 if (CurrentModeHasSPSR) {
1687 INC_PC(sizeof(ldst_inst)); 2080 cpu->Cpsr = cpu->Spsr_copy;
1688 goto DISPATCH; 2081 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
2082 LOAD_NZCVT;
1689 } 2083 }
2084
2085 cpu->Reg[15] = cpu->ReadMemory32(addr);
2086 }
2087
2088 if (BIT(inst, 15)) {
2089 INC_PC(sizeof(ldst_inst));
2090 goto DISPATCH;
1690 } 2091 }
1691 cpu->Reg[15] += cpu->GetInstructionSize();
1692 INC_PC(sizeof(ldst_inst));
1693 FETCH_INST;
1694 GOTO_NEXT_INST;
1695 } 2092 }
1696 SXTH_INST: 2093 cpu->Reg[15] += cpu->GetInstructionSize();
1697 { 2094 INC_PC(sizeof(ldst_inst));
1698 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2095 FETCH_INST;
1699 sxth_inst* inst_cream = (sxth_inst*)inst_base->component; 2096 GOTO_NEXT_INST;
2097}
2098SXTH_INST : {
2099 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2100 sxth_inst* inst_cream = (sxth_inst*)inst_base->component;
1700 2101
1701 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate); 2102 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
1702 if (BIT(operand2, 15)) { 2103 if (BIT(operand2, 15)) {
1703 operand2 |= 0xffff0000; 2104 operand2 |= 0xffff0000;
1704 } else { 2105 } else {
1705 operand2 &= 0xffff; 2106 operand2 &= 0xffff;
1706 }
1707 RD = operand2;
1708 } 2107 }
1709 cpu->Reg[15] += cpu->GetInstructionSize(); 2108 RD = operand2;
1710 INC_PC(sizeof(sxth_inst)); 2109 }
1711 FETCH_INST; 2110 cpu->Reg[15] += cpu->GetInstructionSize();
1712 GOTO_NEXT_INST; 2111 INC_PC(sizeof(sxth_inst));
1713 } 2112 FETCH_INST;
1714 LDR_INST: 2113 GOTO_NEXT_INST;
1715 { 2114}
1716 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2115LDR_INST : {
2116 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2117 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2118
2119 unsigned int value = cpu->ReadMemory32(addr);
2120 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
2121
2122 if (BITS(inst_cream->inst, 12, 15) == 15) {
2123 // For armv5t, should enter thumb when bits[0] is non-zero.
2124 cpu->TFlag = value & 0x1;
2125 cpu->Reg[15] &= 0xFFFFFFFE;
2126 INC_PC(sizeof(ldst_inst));
2127 goto DISPATCH;
2128 }
2129
2130 cpu->Reg[15] += cpu->GetInstructionSize();
2131 INC_PC(sizeof(ldst_inst));
2132 FETCH_INST;
2133 GOTO_NEXT_INST;
2134}
2135LDRCOND_INST : {
2136 if (CondPassed(cpu, inst_base->cond)) {
2137 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1717 inst_cream->get_addr(cpu, inst_cream->inst, addr); 2138 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1718 2139
1719 unsigned int value = cpu->ReadMemory32(addr); 2140 unsigned int value = cpu->ReadMemory32(addr);
@@ -1726,2546 +2147,2433 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
1726 INC_PC(sizeof(ldst_inst)); 2147 INC_PC(sizeof(ldst_inst));
1727 goto DISPATCH; 2148 goto DISPATCH;
1728 } 2149 }
2150 }
2151 cpu->Reg[15] += cpu->GetInstructionSize();
2152 INC_PC(sizeof(ldst_inst));
2153 FETCH_INST;
2154 GOTO_NEXT_INST;
2155}
2156UXTH_INST : {
2157 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2158 uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
2159 RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
2160 }
2161 cpu->Reg[15] += cpu->GetInstructionSize();
2162 INC_PC(sizeof(uxth_inst));
2163 FETCH_INST;
2164 GOTO_NEXT_INST;
2165}
2166UXTAH_INST : {
2167 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2168 uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component;
2169 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
1729 2170
1730 cpu->Reg[15] += cpu->GetInstructionSize(); 2171 RD = RN + operand2;
1731 INC_PC(sizeof(ldst_inst)); 2172 }
1732 FETCH_INST; 2173 cpu->Reg[15] += cpu->GetInstructionSize();
1733 GOTO_NEXT_INST; 2174 INC_PC(sizeof(uxtah_inst));
1734 } 2175 FETCH_INST;
1735 LDRCOND_INST: 2176 GOTO_NEXT_INST;
1736 { 2177}
1737 if (CondPassed(cpu, inst_base->cond)) { 2178LDRB_INST : {
1738 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2179 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1739 inst_cream->get_addr(cpu, inst_cream->inst, addr); 2180 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1740 2181 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1741 unsigned int value = cpu->ReadMemory32(addr); 2182
1742 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 2183 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 } 2184 }
1794 LDRBT_INST: 2185 cpu->Reg[15] += cpu->GetInstructionSize();
1795 { 2186 INC_PC(sizeof(ldst_inst));
1796 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2187 FETCH_INST;
1797 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 2188 GOTO_NEXT_INST;
1798 inst_cream->get_addr(cpu, inst_cream->inst, addr); 2189}
2190LDRBT_INST : {
2191 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2192 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2193 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1799 2194
1800 const u32 dest_index = BITS(inst_cream->inst, 12, 15); 2195 const u32 dest_index = BITS(inst_cream->inst, 12, 15);
1801 const u32 previous_mode = cpu->Mode; 2196 const u32 previous_mode = cpu->Mode;
1802 2197
1803 cpu->ChangePrivilegeMode(USER32MODE); 2198 cpu->ChangePrivilegeMode(USER32MODE);
1804 const u8 value = cpu->ReadMemory8(addr); 2199 const u8 value = cpu->ReadMemory8(addr);
1805 cpu->ChangePrivilegeMode(previous_mode); 2200 cpu->ChangePrivilegeMode(previous_mode);
1806 2201
1807 cpu->Reg[dest_index] = value; 2202 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 } 2203 }
2204 cpu->Reg[15] += cpu->GetInstructionSize();
2205 INC_PC(sizeof(ldst_inst));
2206 FETCH_INST;
2207 GOTO_NEXT_INST;
2208}
2209LDRD_INST : {
2210 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2211 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2212 // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 ||
2213 // addr[2] == 0)
2214 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1833 2215
1834 LDREX_INST: 2216 // The 3DS doesn't have LPAE (Large Physical Access Extension), so it
1835 { 2217 // wouldn't do this as a single read.
1836 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2218 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr);
1837 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 2219 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 2220
1842 RD = cpu->ReadMemory32(read_addr); 2221 // 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 } 2222 }
1849 LDREXB_INST: 2223 cpu->Reg[15] += 4;
1850 { 2224 INC_PC(sizeof(ldst_inst));
1851 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2225 FETCH_INST;
1852 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 2226 GOTO_NEXT_INST;
1853 unsigned int read_addr = RN; 2227}
1854 2228
1855 cpu->SetExclusiveMemoryAddress(read_addr); 2229LDREX_INST : {
2230 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2231 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2232 unsigned int read_addr = RN;
1856 2233
1857 RD = cpu->ReadMemory8(read_addr); 2234 cpu->SetExclusiveMemoryAddress(read_addr);
1858 } 2235
1859 cpu->Reg[15] += cpu->GetInstructionSize(); 2236 RD = cpu->ReadMemory32(read_addr);
1860 INC_PC(sizeof(generic_arm_inst));
1861 FETCH_INST;
1862 GOTO_NEXT_INST;
1863 } 2237 }
1864 LDREXH_INST: 2238 cpu->Reg[15] += cpu->GetInstructionSize();
1865 { 2239 INC_PC(sizeof(generic_arm_inst));
1866 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2240 FETCH_INST;
1867 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 2241 GOTO_NEXT_INST;
1868 unsigned int read_addr = RN; 2242}
2243LDREXB_INST : {
2244 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2245 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2246 unsigned int read_addr = RN;
1869 2247
1870 cpu->SetExclusiveMemoryAddress(read_addr); 2248 cpu->SetExclusiveMemoryAddress(read_addr);
1871 2249
1872 RD = cpu->ReadMemory16(read_addr); 2250 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 } 2251 }
1879 LDREXD_INST: 2252 cpu->Reg[15] += cpu->GetInstructionSize();
1880 { 2253 INC_PC(sizeof(generic_arm_inst));
1881 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2254 FETCH_INST;
1882 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 2255 GOTO_NEXT_INST;
1883 unsigned int read_addr = RN; 2256}
2257LDREXH_INST : {
2258 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2259 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2260 unsigned int read_addr = RN;
1884 2261
1885 cpu->SetExclusiveMemoryAddress(read_addr); 2262 cpu->SetExclusiveMemoryAddress(read_addr);
1886 2263
1887 RD = cpu->ReadMemory32(read_addr); 2264 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 } 2265 }
1941 LDRT_INST: 2266 cpu->Reg[15] += cpu->GetInstructionSize();
1942 { 2267 INC_PC(sizeof(generic_arm_inst));
1943 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2268 FETCH_INST;
1944 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 2269 GOTO_NEXT_INST;
1945 inst_cream->get_addr(cpu, inst_cream->inst, addr); 2270}
2271LDREXD_INST : {
2272 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2273 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2274 unsigned int read_addr = RN;
1946 2275
1947 const u32 dest_index = BITS(inst_cream->inst, 12, 15); 2276 cpu->SetExclusiveMemoryAddress(read_addr);
1948 const u32 previous_mode = cpu->Mode;
1949 2277
1950 cpu->ChangePrivilegeMode(USER32MODE); 2278 RD = cpu->ReadMemory32(read_addr);
1951 const u32 value = cpu->ReadMemory32(addr); 2279 RD2 = cpu->ReadMemory32(read_addr + 4);
1952 cpu->ChangePrivilegeMode(previous_mode); 2280 }
2281 cpu->Reg[15] += cpu->GetInstructionSize();
2282 INC_PC(sizeof(generic_arm_inst));
2283 FETCH_INST;
2284 GOTO_NEXT_INST;
2285}
2286LDRH_INST : {
2287 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2288 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2289 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1953 2290
1954 cpu->Reg[dest_index] = value; 2291 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr);
2292 }
2293 cpu->Reg[15] += cpu->GetInstructionSize();
2294 INC_PC(sizeof(ldst_inst));
2295 FETCH_INST;
2296 GOTO_NEXT_INST;
2297}
2298LDRSB_INST : {
2299 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2300 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2301 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2302 unsigned int value = cpu->ReadMemory8(addr);
2303 if (BIT(value, 7)) {
2304 value |= 0xffffff00;
1955 } 2305 }
1956 cpu->Reg[15] += cpu->GetInstructionSize(); 2306 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
1957 INC_PC(sizeof(ldst_inst));
1958 FETCH_INST;
1959 GOTO_NEXT_INST;
1960 } 2307 }
1961 MCR_INST: 2308 cpu->Reg[15] += cpu->GetInstructionSize();
1962 { 2309 INC_PC(sizeof(ldst_inst));
1963 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2310 FETCH_INST;
1964 mcr_inst* inst_cream = (mcr_inst*)inst_base->component; 2311 GOTO_NEXT_INST;
2312}
2313LDRSH_INST : {
2314 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2315 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2316 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1965 2317
1966 unsigned int inst = inst_cream->inst; 2318 unsigned int value = cpu->ReadMemory16(addr);
1967 if (inst_cream->Rd == 15) { 2319 if (BIT(value, 15)) {
1968 DEBUG_MSG; 2320 value |= 0xffff0000;
1969 } else {
1970 if (inst_cream->cp_num == 15)
1971 cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2);
1972 }
1973 } 2321 }
1974 cpu->Reg[15] += cpu->GetInstructionSize(); 2322 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
1975 INC_PC(sizeof(mcr_inst));
1976 FETCH_INST;
1977 GOTO_NEXT_INST;
1978 } 2323 }
2324 cpu->Reg[15] += cpu->GetInstructionSize();
2325 INC_PC(sizeof(ldst_inst));
2326 FETCH_INST;
2327 GOTO_NEXT_INST;
2328}
2329LDRT_INST : {
2330 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2331 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2332 inst_cream->get_addr(cpu, inst_cream->inst, addr);
1979 2333
1980 MCRR_INST: 2334 const u32 dest_index = BITS(inst_cream->inst, 12, 15);
1981 { 2335 const u32 previous_mode = cpu->Mode;
1982 // Stubbed, as the MPCore doesn't have any registers that are accessible
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 2336
1987 LOG_ERROR(Core_ARM11, "MCRR executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", 2337 cpu->ChangePrivilegeMode(USER32MODE);
1988 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); 2338 const u32 value = cpu->ReadMemory32(addr);
2339 cpu->ChangePrivilegeMode(previous_mode);
2340
2341 cpu->Reg[dest_index] = value;
2342 }
2343 cpu->Reg[15] += cpu->GetInstructionSize();
2344 INC_PC(sizeof(ldst_inst));
2345 FETCH_INST;
2346 GOTO_NEXT_INST;
2347}
2348MCR_INST : {
2349 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2350 mcr_inst* inst_cream = (mcr_inst*)inst_base->component;
2351
2352 unsigned int inst = inst_cream->inst;
2353 if (inst_cream->Rd == 15) {
2354 DEBUG_MSG;
2355 } else {
2356 if (inst_cream->cp_num == 15)
2357 cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2);
1989 } 2358 }
2359 }
2360 cpu->Reg[15] += cpu->GetInstructionSize();
2361 INC_PC(sizeof(mcr_inst));
2362 FETCH_INST;
2363 GOTO_NEXT_INST;
2364}
2365
2366MCRR_INST : {
2367 // Stubbed, as the MPCore doesn't have any registers that are accessible
2368 // through this instruction.
2369 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2370 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
1990 2371
1991 cpu->Reg[15] += cpu->GetInstructionSize(); 2372 LOG_ERROR(Core_ARM11, "MCRR executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u",
1992 INC_PC(sizeof(mcrr_inst)); 2373 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt,
1993 FETCH_INST; 2374 inst_cream->rt2);
1994 GOTO_NEXT_INST;
1995 } 2375 }
1996 2376
1997 MLA_INST: 2377 cpu->Reg[15] += cpu->GetInstructionSize();
1998 { 2378 INC_PC(sizeof(mcrr_inst));
1999 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2379 FETCH_INST;
2000 mla_inst* inst_cream = (mla_inst*)inst_base->component; 2380 GOTO_NEXT_INST;
2381}
2001 2382
2002 u64 rm = RM; 2383MLA_INST : {
2003 u64 rs = RS; 2384 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2004 u64 rn = RN; 2385 mla_inst* inst_cream = (mla_inst*)inst_base->component;
2005 2386
2006 RD = static_cast<u32>((rm * rs + rn) & 0xffffffff); 2387 u64 rm = RM;
2007 if (inst_cream->S) { 2388 u64 rs = RS;
2008 UPDATE_NFLAG(RD); 2389 u64 rn = RN;
2009 UPDATE_ZFLAG(RD); 2390
2010 } 2391 RD = static_cast<u32>((rm * rs + rn) & 0xffffffff);
2392 if (inst_cream->S) {
2393 UPDATE_NFLAG(RD);
2394 UPDATE_ZFLAG(RD);
2011 } 2395 }
2012 cpu->Reg[15] += cpu->GetInstructionSize(); 2396 }
2013 INC_PC(sizeof(mla_inst)); 2397 cpu->Reg[15] += cpu->GetInstructionSize();
2014 FETCH_INST; 2398 INC_PC(sizeof(mla_inst));
2015 GOTO_NEXT_INST; 2399 FETCH_INST;
2016 } 2400 GOTO_NEXT_INST;
2017 MOV_INST: 2401}
2018 { 2402MOV_INST : {
2019 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2403 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2020 mov_inst* inst_cream = (mov_inst*)inst_base->component; 2404 mov_inst* inst_cream = (mov_inst*)inst_base->component;
2021 2405
2022 RD = SHIFTER_OPERAND; 2406 RD = SHIFTER_OPERAND;
2023 if (inst_cream->S && (inst_cream->Rd == 15)) { 2407 if (inst_cream->S && (inst_cream->Rd == 15)) {
2024 if (CurrentModeHasSPSR) { 2408 if (CurrentModeHasSPSR) {
2025 cpu->Cpsr = cpu->Spsr_copy; 2409 cpu->Cpsr = cpu->Spsr_copy;
2026 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 2410 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2027 LOAD_NZCVT; 2411 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 } 2412 }
2413 } else if (inst_cream->S) {
2414 UPDATE_NFLAG(RD);
2415 UPDATE_ZFLAG(RD);
2416 UPDATE_CFLAG_WITH_SC;
2038 } 2417 }
2039 cpu->Reg[15] += cpu->GetInstructionSize(); 2418 if (inst_cream->Rd == 15) {
2040 INC_PC(sizeof(mov_inst)); 2419 INC_PC(sizeof(mov_inst));
2041 FETCH_INST; 2420 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 } 2421 }
2060 cpu->Reg[15] += cpu->GetInstructionSize();
2061 INC_PC(sizeof(mrc_inst));
2062 FETCH_INST;
2063 GOTO_NEXT_INST;
2064 } 2422 }
2423 cpu->Reg[15] += cpu->GetInstructionSize();
2424 INC_PC(sizeof(mov_inst));
2425 FETCH_INST;
2426 GOTO_NEXT_INST;
2427}
2428MRC_INST : {
2429 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2430 mrc_inst* inst_cream = (mrc_inst*)inst_base->component;
2065 2431
2066 MRRC_INST: 2432 if (inst_cream->cp_num == 15) {
2067 { 2433 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 2434
2073 LOG_ERROR(Core_ARM11, "MRRC executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u", 2435 if (inst_cream->Rd == 15) {
2074 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt, inst_cream->rt2); 2436 cpu->Cpsr = (cpu->Cpsr & ~0xF0000000) | (value & 0xF0000000);
2437 LOAD_NZCVT;
2438 } else {
2439 RD = value;
2440 }
2075 } 2441 }
2442 }
2443 cpu->Reg[15] += cpu->GetInstructionSize();
2444 INC_PC(sizeof(mrc_inst));
2445 FETCH_INST;
2446 GOTO_NEXT_INST;
2447}
2076 2448
2077 cpu->Reg[15] += cpu->GetInstructionSize(); 2449MRRC_INST : {
2078 INC_PC(sizeof(mcrr_inst)); 2450 // Stubbed, as the MPCore doesn't have any registers that are accessible
2079 FETCH_INST; 2451 // through this instruction.
2080 GOTO_NEXT_INST; 2452 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2453 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
2454
2455 LOG_ERROR(Core_ARM11, "MRRC executed | Coprocessor: %u, CRm %u, opc1: %u, Rt: %u, Rt2: %u",
2456 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt,
2457 inst_cream->rt2);
2081 } 2458 }
2082 2459
2083 MRS_INST: 2460 cpu->Reg[15] += cpu->GetInstructionSize();
2084 { 2461 INC_PC(sizeof(mcrr_inst));
2085 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2462 FETCH_INST;
2086 mrs_inst* inst_cream = (mrs_inst*)inst_base->component; 2463 GOTO_NEXT_INST;
2464}
2087 2465
2088 if (inst_cream->R) { 2466MRS_INST : {
2089 RD = cpu->Spsr_copy; 2467 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2090 } else { 2468 mrs_inst* inst_cream = (mrs_inst*)inst_base->component;
2091 SAVE_NZCVT; 2469
2092 RD = cpu->Cpsr; 2470 if (inst_cream->R) {
2093 } 2471 RD = cpu->Spsr_copy;
2472 } else {
2473 SAVE_NZCVT;
2474 RD = cpu->Cpsr;
2475 }
2476 }
2477 cpu->Reg[15] += cpu->GetInstructionSize();
2478 INC_PC(sizeof(mrs_inst));
2479 FETCH_INST;
2480 GOTO_NEXT_INST;
2481}
2482MSR_INST : {
2483 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2484 msr_inst* inst_cream = (msr_inst*)inst_base->component;
2485 const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
2486 unsigned int inst = inst_cream->inst;
2487 unsigned int operand;
2488
2489 if (BIT(inst, 25)) {
2490 int rot_imm = BITS(inst, 8, 11) * 2;
2491 operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
2492 } else {
2493 operand = cpu->Reg[BITS(inst, 0, 3)];
2094 } 2494 }
2095 cpu->Reg[15] += cpu->GetInstructionSize(); 2495 u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) |
2096 INC_PC(sizeof(mrs_inst)); 2496 (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
2097 FETCH_INST; 2497 u32 mask = 0;
2098 GOTO_NEXT_INST; 2498 if (!inst_cream->R) {
2099 } 2499 if (cpu->InAPrivilegedMode()) {
2100 MSR_INST: 2500 if ((operand & StateMask) != 0) {
2101 { 2501 /// UNPREDICTABLE
2102 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2502 DEBUG_MSG;
2103 msr_inst* inst_cream = (msr_inst*)inst_base->component; 2503 } else
2104 const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; 2504 mask = byte_mask & (UserMask | PrivMask);
2105 unsigned int inst = inst_cream->inst;
2106 unsigned int operand;
2107
2108 if (BIT(inst, 25)) {
2109 int rot_imm = BITS(inst, 8, 11) * 2;
2110 operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
2111 } else { 2505 } else {
2112 operand = cpu->Reg[BITS(inst, 0, 3)]; 2506 mask = byte_mask & UserMask;
2113 } 2507 }
2114 u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) 2508 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 2509
2129 cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); 2510 cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
2130 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F); 2511 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
2131 LOAD_NZCVT; 2512 LOAD_NZCVT;
2132 } else { 2513 } else {
2133 if (CurrentModeHasSPSR) { 2514 if (CurrentModeHasSPSR) {
2134 mask = byte_mask & (UserMask | PrivMask | StateMask); 2515 mask = byte_mask & (UserMask | PrivMask | StateMask);
2135 cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); 2516 cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask);
2136 }
2137 } 2517 }
2138 } 2518 }
2139 cpu->Reg[15] += cpu->GetInstructionSize(); 2519 }
2140 INC_PC(sizeof(msr_inst)); 2520 cpu->Reg[15] += cpu->GetInstructionSize();
2141 FETCH_INST; 2521 INC_PC(sizeof(msr_inst));
2142 GOTO_NEXT_INST; 2522 FETCH_INST;
2143 } 2523 GOTO_NEXT_INST;
2144 MUL_INST: 2524}
2145 { 2525MUL_INST : {
2146 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2526 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2147 mul_inst* inst_cream = (mul_inst*)inst_base->component; 2527 mul_inst* inst_cream = (mul_inst*)inst_base->component;
2148 2528
2149 u64 rm = RM; 2529 u64 rm = RM;
2150 u64 rs = RS; 2530 u64 rs = RS;
2151 RD = static_cast<u32>((rm * rs) & 0xffffffff); 2531 RD = static_cast<u32>((rm * rs) & 0xffffffff);
2152 if (inst_cream->S) { 2532 if (inst_cream->S) {
2153 UPDATE_NFLAG(RD); 2533 UPDATE_NFLAG(RD);
2154 UPDATE_ZFLAG(RD); 2534 UPDATE_ZFLAG(RD);
2155 }
2156 } 2535 }
2157 cpu->Reg[15] += cpu->GetInstructionSize(); 2536 }
2158 INC_PC(sizeof(mul_inst)); 2537 cpu->Reg[15] += cpu->GetInstructionSize();
2159 FETCH_INST; 2538 INC_PC(sizeof(mul_inst));
2160 GOTO_NEXT_INST; 2539 FETCH_INST;
2161 } 2540 GOTO_NEXT_INST;
2162 MVN_INST: 2541}
2163 { 2542MVN_INST : {
2164 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2543 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2165 mvn_inst* const inst_cream = (mvn_inst*)inst_base->component; 2544 mvn_inst* const inst_cream = (mvn_inst*)inst_base->component;
2166 2545
2167 RD = ~SHIFTER_OPERAND; 2546 RD = ~SHIFTER_OPERAND;
2168 2547
2169 if (inst_cream->S && (inst_cream->Rd == 15)) { 2548 if (inst_cream->S && (inst_cream->Rd == 15)) {
2170 if (CurrentModeHasSPSR) { 2549 if (CurrentModeHasSPSR) {
2171 cpu->Cpsr = cpu->Spsr_copy; 2550 cpu->Cpsr = cpu->Spsr_copy;
2172 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 2551 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2173 LOAD_NZCVT; 2552 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 } 2553 }
2554 } else if (inst_cream->S) {
2555 UPDATE_NFLAG(RD);
2556 UPDATE_ZFLAG(RD);
2557 UPDATE_CFLAG_WITH_SC;
2558 }
2559 if (inst_cream->Rd == 15) {
2560 INC_PC(sizeof(mvn_inst));
2561 goto DISPATCH;
2184 } 2562 }
2185 cpu->Reg[15] += cpu->GetInstructionSize();
2186 INC_PC(sizeof(mvn_inst));
2187 FETCH_INST;
2188 GOTO_NEXT_INST;
2189 } 2563 }
2190 ORR_INST: 2564 cpu->Reg[15] += cpu->GetInstructionSize();
2191 { 2565 INC_PC(sizeof(mvn_inst));
2192 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2566 FETCH_INST;
2193 orr_inst* const inst_cream = (orr_inst*)inst_base->component; 2567 GOTO_NEXT_INST;
2568}
2569ORR_INST : {
2570 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2571 orr_inst* const inst_cream = (orr_inst*)inst_base->component;
2194 2572
2195 u32 lop = RN; 2573 u32 lop = RN;
2196 u32 rop = SHIFTER_OPERAND; 2574 u32 rop = SHIFTER_OPERAND;
2197 2575
2198 if (inst_cream->Rn == 15) 2576 if (inst_cream->Rn == 15)
2199 lop += 2 * cpu->GetInstructionSize(); 2577 lop += 2 * cpu->GetInstructionSize();
2200 2578
2201 RD = lop | rop; 2579 RD = lop | rop;
2202 2580
2203 if (inst_cream->S && (inst_cream->Rd == 15)) { 2581 if (inst_cream->S && (inst_cream->Rd == 15)) {
2204 if (CurrentModeHasSPSR) { 2582 if (CurrentModeHasSPSR) {
2205 cpu->Cpsr = cpu->Spsr_copy; 2583 cpu->Cpsr = cpu->Spsr_copy;
2206 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 2584 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2207 LOAD_NZCVT; 2585 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 } 2586 }
2587 } else if (inst_cream->S) {
2588 UPDATE_NFLAG(RD);
2589 UPDATE_ZFLAG(RD);
2590 UPDATE_CFLAG_WITH_SC;
2591 }
2592 if (inst_cream->Rd == 15) {
2593 INC_PC(sizeof(orr_inst));
2594 goto DISPATCH;
2218 } 2595 }
2219 cpu->Reg[15] += cpu->GetInstructionSize();
2220 INC_PC(sizeof(orr_inst));
2221 FETCH_INST;
2222 GOTO_NEXT_INST;
2223 } 2596 }
2597 cpu->Reg[15] += cpu->GetInstructionSize();
2598 INC_PC(sizeof(orr_inst));
2599 FETCH_INST;
2600 GOTO_NEXT_INST;
2601}
2224 2602
2225 NOP_INST: 2603NOP_INST : {
2226 { 2604 cpu->Reg[15] += cpu->GetInstructionSize();
2227 cpu->Reg[15] += cpu->GetInstructionSize(); 2605 INC_PC_STUB;
2228 INC_PC_STUB; 2606 FETCH_INST;
2229 FETCH_INST; 2607 GOTO_NEXT_INST;
2230 GOTO_NEXT_INST; 2608}
2609
2610PKHBT_INST : {
2611 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2612 pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
2613 RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000);
2231 } 2614 }
2615 cpu->Reg[15] += cpu->GetInstructionSize();
2616 INC_PC(sizeof(pkh_inst));
2617 FETCH_INST;
2618 GOTO_NEXT_INST;
2619}
2232 2620
2233 PKHBT_INST: 2621PKHTB_INST : {
2234 { 2622 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2235 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2623 pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
2236 pkh_inst *inst_cream = (pkh_inst *)inst_base->component; 2624 int shift_imm = inst_cream->imm ? inst_cream->imm : 31;
2237 RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000); 2625 RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000);
2238 } 2626 }
2239 cpu->Reg[15] += cpu->GetInstructionSize(); 2627 cpu->Reg[15] += cpu->GetInstructionSize();
2240 INC_PC(sizeof(pkh_inst)); 2628 INC_PC(sizeof(pkh_inst));
2241 FETCH_INST; 2629 FETCH_INST;
2242 GOTO_NEXT_INST; 2630 GOTO_NEXT_INST;
2243 } 2631}
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 2632
2279 u32 result = 0; 2633PLD_INST : {
2634 // Not implemented. PLD is a hint instruction, so it's optional.
2280 2635
2281 // QADD 2636 cpu->Reg[15] += cpu->GetInstructionSize();
2282 if (op1 == 0x00) { 2637 INC_PC(sizeof(pld_inst));
2283 result = rm_val + rn_val; 2638 FETCH_INST;
2639 GOTO_NEXT_INST;
2640}
2284 2641
2285 if (AddOverflow(rm_val, rn_val, result)) { 2642QADD_INST:
2286 result = POS(result) ? 0x80000000 : 0x7FFFFFFF; 2643QDADD_INST:
2287 cpu->Cpsr |= (1 << 27); 2644QDSUB_INST:
2288 } 2645QSUB_INST : {
2289 } 2646 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2290 // QSUB 2647 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2291 else if (op1 == 0x01) { 2648 const u8 op1 = inst_cream->op1;
2292 result = rm_val - rn_val; 2649 const u32 rm_val = RM;
2650 const u32 rn_val = RN;
2293 2651
2294 if (SubOverflow(rm_val, rn_val, result)) { 2652 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 2653
2303 if (AddOverflow(rn_val, rn_val, rn_val * 2)) { 2654 // QADD
2304 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; 2655 if (op1 == 0x00) {
2305 cpu->Cpsr |= (1 << 27); 2656 result = rm_val + rn_val;
2306 }
2307 2657
2308 result = mul + rm_val; 2658 if (AddOverflow(rm_val, rn_val, result)) {
2659 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2660 cpu->Cpsr |= (1 << 27);
2661 }
2662 }
2663 // QSUB
2664 else if (op1 == 0x01) {
2665 result = rm_val - rn_val;
2309 2666
2310 if (AddOverflow(rm_val, mul, result)) { 2667 if (SubOverflow(rm_val, rn_val, result)) {
2311 result = POS(result) ? 0x80000000 : 0x7FFFFFFF; 2668 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2312 cpu->Cpsr |= (1 << 27); 2669 cpu->Cpsr |= (1 << 27);
2313 }
2314 } 2670 }
2315 // QDSUB 2671 }
2316 else if (op1 == 0x03) { 2672 // QDADD
2317 u32 mul = (rn_val * 2); 2673 else if (op1 == 0x02) {
2674 u32 mul = (rn_val * 2);
2318 2675
2319 if (AddOverflow(rn_val, rn_val, mul)) { 2676 if (AddOverflow(rn_val, rn_val, rn_val * 2)) {
2320 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF; 2677 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
2321 cpu->Cpsr |= (1 << 27); 2678 cpu->Cpsr |= (1 << 27);
2322 } 2679 }
2323 2680
2324 result = rm_val - mul; 2681 result = mul + rm_val;
2325 2682
2326 if (SubOverflow(rm_val, mul, result)) { 2683 if (AddOverflow(rm_val, mul, result)) {
2327 result = POS(result) ? 0x80000000 : 0x7FFFFFFF; 2684 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2328 cpu->Cpsr |= (1 << 27); 2685 cpu->Cpsr |= (1 << 27);
2329 }
2330 } 2686 }
2331
2332 RD = result;
2333 } 2687 }
2688 // QDSUB
2689 else if (op1 == 0x03) {
2690 u32 mul = (rn_val * 2);
2334 2691
2335 cpu->Reg[15] += cpu->GetInstructionSize(); 2692 if (AddOverflow(rn_val, rn_val, mul)) {
2336 INC_PC(sizeof(generic_arm_inst)); 2693 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
2337 FETCH_INST; 2694 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 } 2695 }
2386 // QSUB8 2696
2387 else if (op2 == 0x07) { 2697 result = rm_val - mul;
2388 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) | 2698
2389 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8; 2699 if (SubOverflow(rm_val, mul, result)) {
2390 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) | 2700 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2391 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8; 2701 cpu->Cpsr |= (1 << 27);
2392 } 2702 }
2703 }
2393 2704
2394 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); 2705 RD = result;
2706 }
2707
2708 cpu->Reg[15] += cpu->GetInstructionSize();
2709 INC_PC(sizeof(generic_arm_inst));
2710 FETCH_INST;
2711 GOTO_NEXT_INST;
2712}
2713
2714QADD8_INST:
2715QADD16_INST:
2716QADDSUBX_INST:
2717QSUB8_INST:
2718QSUB16_INST:
2719QSUBADDX_INST : {
2720 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2721 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2722 const u16 rm_lo = (RM & 0xFFFF);
2723 const u16 rm_hi = ((RM >> 16) & 0xFFFF);
2724 const u16 rn_lo = (RN & 0xFFFF);
2725 const u16 rn_hi = ((RN >> 16) & 0xFFFF);
2726 const u8 op2 = inst_cream->op2;
2727
2728 u16 lo_result = 0;
2729 u16 hi_result = 0;
2730
2731 // QADD16
2732 if (op2 == 0x00) {
2733 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
2734 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
2735 }
2736 // QASX
2737 else if (op2 == 0x01) {
2738 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
2739 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
2740 }
2741 // QSAX
2742 else if (op2 == 0x02) {
2743 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
2744 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
2745 }
2746 // QSUB16
2747 else if (op2 == 0x03) {
2748 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
2749 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
2750 }
2751 // QADD8
2752 else if (op2 == 0x04) {
2753 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
2754 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
2755 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
2756 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
2757 }
2758 // QSUB8
2759 else if (op2 == 0x07) {
2760 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
2761 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
2762 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
2763 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
2395 } 2764 }
2396 2765
2397 cpu->Reg[15] += cpu->GetInstructionSize(); 2766 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
2398 INC_PC(sizeof(generic_arm_inst));
2399 FETCH_INST;
2400 GOTO_NEXT_INST;
2401 } 2767 }
2402 2768
2403 REV_INST: 2769 cpu->Reg[15] += cpu->GetInstructionSize();
2404 REV16_INST: 2770 INC_PC(sizeof(generic_arm_inst));
2405 REVSH_INST: 2771 FETCH_INST;
2406 { 2772 GOTO_NEXT_INST;
2773}
2407 2774
2408 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2775REV_INST:
2409 rev_inst* const inst_cream = (rev_inst*)inst_base->component; 2776REV16_INST:
2777REVSH_INST : {
2410 2778
2411 const u8 op1 = inst_cream->op1; 2779 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2412 const u8 op2 = inst_cream->op2; 2780 rev_inst* const inst_cream = (rev_inst*)inst_base->component;
2413 2781
2414 // REV 2782 const u8 op1 = inst_cream->op1;
2415 if (op1 == 0x03 && op2 == 0x01) { 2783 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 2784
2430 cpu->Reg[15] += cpu->GetInstructionSize(); 2785 // REV
2431 INC_PC(sizeof(rev_inst)); 2786 if (op1 == 0x03 && op2 == 0x01) {
2432 FETCH_INST; 2787 RD = ((RM & 0xFF) << 24) | (((RM >> 8) & 0xFF) << 16) | (((RM >> 16) & 0xFF) << 8) |
2433 GOTO_NEXT_INST; 2788 ((RM >> 24) & 0xFF);
2789 }
2790 // REV16
2791 else if (op1 == 0x03 && op2 == 0x05) {
2792 RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8) | ((RM & 0xFF0000) << 8) |
2793 ((RM & 0xFF000000) >> 8);
2794 }
2795 // REVSH
2796 else if (op1 == 0x07 && op2 == 0x05) {
2797 RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8);
2798 if (RD & 0x8000)
2799 RD |= 0xffff0000;
2800 }
2434 } 2801 }
2435 2802
2436 RFE_INST: 2803 cpu->Reg[15] += cpu->GetInstructionSize();
2437 { 2804 INC_PC(sizeof(rev_inst));
2438 // RFE is unconditional 2805 FETCH_INST;
2439 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component; 2806 GOTO_NEXT_INST;
2807}
2440 2808
2441 u32 address = 0; 2809RFE_INST : {
2442 inst_cream->get_addr(cpu, inst_cream->inst, address); 2810 // RFE is unconditional
2811 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
2443 2812
2444 cpu->Cpsr = cpu->ReadMemory32(address); 2813 u32 address = 0;
2445 cpu->Reg[15] = cpu->ReadMemory32(address + 4); 2814 inst_cream->get_addr(cpu, inst_cream->inst, address);
2446 2815
2447 INC_PC(sizeof(ldst_inst)); 2816 cpu->Cpsr = cpu->ReadMemory32(address);
2448 goto DISPATCH; 2817 cpu->Reg[15] = cpu->ReadMemory32(address + 4);
2449 } 2818
2819 INC_PC(sizeof(ldst_inst));
2820 goto DISPATCH;
2821}
2450 2822
2451 RSB_INST: 2823RSB_INST : {
2452 { 2824 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2453 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2825 rsb_inst* const inst_cream = (rsb_inst*)inst_base->component;
2454 rsb_inst* const inst_cream = (rsb_inst*)inst_base->component;
2455 2826
2456 u32 rn_val = RN; 2827 u32 rn_val = RN;
2457 if (inst_cream->Rn == 15) 2828 if (inst_cream->Rn == 15)
2458 rn_val += 2 * cpu->GetInstructionSize(); 2829 rn_val += 2 * cpu->GetInstructionSize();
2459 2830
2460 bool carry; 2831 bool carry;
2461 bool overflow; 2832 bool overflow;
2462 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow); 2833 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow);
2463 2834
2464 if (inst_cream->S && (inst_cream->Rd == 15)) { 2835 if (inst_cream->S && (inst_cream->Rd == 15)) {
2465 if (CurrentModeHasSPSR) { 2836 if (CurrentModeHasSPSR) {
2466 cpu->Cpsr = cpu->Spsr_copy; 2837 cpu->Cpsr = cpu->Spsr_copy;
2467 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 2838 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2468 LOAD_NZCVT; 2839 LOAD_NZCVT;
2469 }
2470 } else if (inst_cream->S) {
2471 UPDATE_NFLAG(RD);
2472 UPDATE_ZFLAG(RD);
2473 cpu->CFlag = carry;
2474 cpu->VFlag = overflow;
2475 } 2840 }
2476 if (inst_cream->Rd == 15) { 2841 } else if (inst_cream->S) {
2477 INC_PC(sizeof(rsb_inst)); 2842 UPDATE_NFLAG(RD);
2478 goto DISPATCH; 2843 UPDATE_ZFLAG(RD);
2844 cpu->CFlag = carry;
2845 cpu->VFlag = overflow;
2846 }
2847 if (inst_cream->Rd == 15) {
2848 INC_PC(sizeof(rsb_inst));
2849 goto DISPATCH;
2850 }
2851 }
2852 cpu->Reg[15] += cpu->GetInstructionSize();
2853 INC_PC(sizeof(rsb_inst));
2854 FETCH_INST;
2855 GOTO_NEXT_INST;
2856}
2857RSC_INST : {
2858 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2859 rsc_inst* const inst_cream = (rsc_inst*)inst_base->component;
2860
2861 u32 rn_val = RN;
2862 if (inst_cream->Rn == 15)
2863 rn_val += 2 * cpu->GetInstructionSize();
2864
2865 bool carry;
2866 bool overflow;
2867 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
2868
2869 if (inst_cream->S && (inst_cream->Rd == 15)) {
2870 if (CurrentModeHasSPSR) {
2871 cpu->Cpsr = cpu->Spsr_copy;
2872 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2873 LOAD_NZCVT;
2479 } 2874 }
2875 } else if (inst_cream->S) {
2876 UPDATE_NFLAG(RD);
2877 UPDATE_ZFLAG(RD);
2878 cpu->CFlag = carry;
2879 cpu->VFlag = overflow;
2480 } 2880 }
2481 cpu->Reg[15] += cpu->GetInstructionSize(); 2881 if (inst_cream->Rd == 15) {
2482 INC_PC(sizeof(rsb_inst)); 2882 INC_PC(sizeof(rsc_inst));
2483 FETCH_INST; 2883 goto DISPATCH;
2484 GOTO_NEXT_INST; 2884 }
2485 } 2885 }
2486 RSC_INST: 2886 cpu->Reg[15] += cpu->GetInstructionSize();
2487 { 2887 INC_PC(sizeof(rsc_inst));
2488 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2888 FETCH_INST;
2489 rsc_inst* const inst_cream = (rsc_inst*)inst_base->component; 2889 GOTO_NEXT_INST;
2490 2890}
2491 u32 rn_val = RN; 2891
2492 if (inst_cream->Rn == 15) 2892SADD8_INST:
2493 rn_val += 2 * cpu->GetInstructionSize(); 2893SSUB8_INST:
2494 2894SADD16_INST:
2495 bool carry; 2895SADDSUBX_INST:
2496 bool overflow; 2896SSUBADDX_INST:
2497 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); 2897SSUB16_INST : {
2498 2898 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2499 if (inst_cream->S && (inst_cream->Rd == 15)) { 2899 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2500 if (CurrentModeHasSPSR) { 2900 const u8 op2 = inst_cream->op2;
2501 cpu->Cpsr = cpu->Spsr_copy; 2901
2502 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 2902 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
2503 LOAD_NZCVT; 2903 const s16 rn_lo = (RN & 0xFFFF);
2504 } 2904 const s16 rn_hi = ((RN >> 16) & 0xFFFF);
2505 } else if (inst_cream->S) { 2905 const s16 rm_lo = (RM & 0xFFFF);
2506 UPDATE_NFLAG(RD); 2906 const s16 rm_hi = ((RM >> 16) & 0xFFFF);
2507 UPDATE_ZFLAG(RD); 2907
2508 cpu->CFlag = carry; 2908 s32 lo_result = 0;
2509 cpu->VFlag = overflow; 2909 s32 hi_result = 0;
2910
2911 // SADD16
2912 if (inst_cream->op2 == 0x00) {
2913 lo_result = (rn_lo + rm_lo);
2914 hi_result = (rn_hi + rm_hi);
2510 } 2915 }
2511 if (inst_cream->Rd == 15) { 2916 // SASX
2512 INC_PC(sizeof(rsc_inst)); 2917 else if (op2 == 0x01) {
2513 goto DISPATCH; 2918 lo_result = (rn_lo - rm_hi);
2919 hi_result = (rn_hi + rm_lo);
2920 }
2921 // SSAX
2922 else if (op2 == 0x02) {
2923 lo_result = (rn_lo + rm_hi);
2924 hi_result = (rn_hi - rm_lo);
2925 }
2926 // SSUB16
2927 else if (op2 == 0x03) {
2928 lo_result = (rn_lo - rm_lo);
2929 hi_result = (rn_hi - rm_hi);
2514 } 2930 }
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 2931
2563 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16); 2932 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
2564 2933
2565 if (lo_result >= 0) { 2934 if (lo_result >= 0) {
2566 cpu->Cpsr |= (1 << 16); 2935 cpu->Cpsr |= (1 << 16);
2567 cpu->Cpsr |= (1 << 17); 2936 cpu->Cpsr |= (1 << 17);
2568 } else { 2937 } else {
2569 cpu->Cpsr &= ~(1 << 16); 2938 cpu->Cpsr &= ~(1 << 16);
2570 cpu->Cpsr &= ~(1 << 17); 2939 cpu->Cpsr &= ~(1 << 17);
2571 } 2940 }
2572 2941
2573 if (hi_result >= 0) { 2942 if (hi_result >= 0) {
2574 cpu->Cpsr |= (1 << 18); 2943 cpu->Cpsr |= (1 << 18);
2575 cpu->Cpsr |= (1 << 19); 2944 cpu->Cpsr |= (1 << 19);
2576 } else { 2945 } else {
2577 cpu->Cpsr &= ~(1 << 18); 2946 cpu->Cpsr &= ~(1 << 18);
2578 cpu->Cpsr &= ~(1 << 19); 2947 cpu->Cpsr &= ~(1 << 19);
2579 } 2948 }
2949 } else if (op2 == 0x04 || op2 == 0x07) {
2950 s32 lo_val1, lo_val2;
2951 s32 hi_val1, hi_val2;
2952
2953 // SADD8
2954 if (op2 == 0x04) {
2955 lo_val1 = (s32)(s8)(RN & 0xFF) + (s32)(s8)(RM & 0xFF);
2956 lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) + (s32)(s8)((RM >> 8) & 0xFF);
2957 hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) + (s32)(s8)((RM >> 16) & 0xFF);
2958 hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) + (s32)(s8)((RM >> 24) & 0xFF);
2959 }
2960 // SSUB8
2961 else {
2962 lo_val1 = (s32)(s8)(RN & 0xFF) - (s32)(s8)(RM & 0xFF);
2963 lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) - (s32)(s8)((RM >> 8) & 0xFF);
2964 hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) - (s32)(s8)((RM >> 16) & 0xFF);
2965 hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) - (s32)(s8)((RM >> 24) & 0xFF);
2580 } 2966 }
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 2967
2600 RD = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24)); 2968 RD = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) |
2969 ((hi_val2 & 0xFF) << 24));
2601 2970
2602 if (lo_val1 >= 0) 2971 if (lo_val1 >= 0)
2603 cpu->Cpsr |= (1 << 16); 2972 cpu->Cpsr |= (1 << 16);
2604 else 2973 else
2605 cpu->Cpsr &= ~(1 << 16); 2974 cpu->Cpsr &= ~(1 << 16);
2606 2975
2607 if (lo_val2 >= 0) 2976 if (lo_val2 >= 0)
2608 cpu->Cpsr |= (1 << 17); 2977 cpu->Cpsr |= (1 << 17);
2609 else 2978 else
2610 cpu->Cpsr &= ~(1 << 17); 2979 cpu->Cpsr &= ~(1 << 17);
2611 2980
2612 if (hi_val1 >= 0) 2981 if (hi_val1 >= 0)
2613 cpu->Cpsr |= (1 << 18); 2982 cpu->Cpsr |= (1 << 18);
2614 else 2983 else
2615 cpu->Cpsr &= ~(1 << 18); 2984 cpu->Cpsr &= ~(1 << 18);
2616 2985
2617 if (hi_val2 >= 0) 2986 if (hi_val2 >= 0)
2618 cpu->Cpsr |= (1 << 19); 2987 cpu->Cpsr |= (1 << 19);
2619 else 2988 else
2620 cpu->Cpsr &= ~(1 << 19); 2989 cpu->Cpsr &= ~(1 << 19);
2621 }
2622 } 2990 }
2623
2624 cpu->Reg[15] += cpu->GetInstructionSize();
2625 INC_PC(sizeof(generic_arm_inst));
2626 FETCH_INST;
2627 GOTO_NEXT_INST;
2628 } 2991 }
2629 2992
2630 SBC_INST: 2993 cpu->Reg[15] += cpu->GetInstructionSize();
2631 { 2994 INC_PC(sizeof(generic_arm_inst));
2632 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 2995 FETCH_INST;
2633 sbc_inst* const inst_cream = (sbc_inst*)inst_base->component; 2996 GOTO_NEXT_INST;
2997}
2634 2998
2635 u32 rn_val = RN; 2999SBC_INST : {
2636 if (inst_cream->Rn == 15) 3000 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2637 rn_val += 2 * cpu->GetInstructionSize(); 3001 sbc_inst* const inst_cream = (sbc_inst*)inst_base->component;
2638 3002
2639 bool carry; 3003 u32 rn_val = RN;
2640 bool overflow; 3004 if (inst_cream->Rn == 15)
2641 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); 3005 rn_val += 2 * cpu->GetInstructionSize();
2642 3006
2643 if (inst_cream->S && (inst_cream->Rd == 15)) { 3007 bool carry;
2644 if (CurrentModeHasSPSR) { 3008 bool overflow;
2645 cpu->Cpsr = cpu->Spsr_copy; 3009 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
2646 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F); 3010
2647 LOAD_NZCVT; 3011 if (inst_cream->S && (inst_cream->Rd == 15)) {
2648 } 3012 if (CurrentModeHasSPSR) {
2649 } else if (inst_cream->S) { 3013 cpu->Cpsr = cpu->Spsr_copy;
2650 UPDATE_NFLAG(RD); 3014 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2651 UPDATE_ZFLAG(RD); 3015 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 } 3016 }
3017 } else if (inst_cream->S) {
3018 UPDATE_NFLAG(RD);
3019 UPDATE_ZFLAG(RD);
3020 cpu->CFlag = carry;
3021 cpu->VFlag = overflow;
3022 }
3023 if (inst_cream->Rd == 15) {
3024 INC_PC(sizeof(sbc_inst));
3025 goto DISPATCH;
2659 } 3026 }
2660 cpu->Reg[15] += cpu->GetInstructionSize();
2661 INC_PC(sizeof(sbc_inst));
2662 FETCH_INST;
2663 GOTO_NEXT_INST;
2664 } 3027 }
3028 cpu->Reg[15] += cpu->GetInstructionSize();
3029 INC_PC(sizeof(sbc_inst));
3030 FETCH_INST;
3031 GOTO_NEXT_INST;
3032}
2665 3033
2666 SEL_INST: 3034SEL_INST : {
2667 { 3035 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2668 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3036 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 3037
2671 const u32 to = RM; 3038 const u32 to = RM;
2672 const u32 from = RN; 3039 const u32 from = RN;
2673 const u32 cpsr = cpu->Cpsr; 3040 const u32 cpsr = cpu->Cpsr;
2674 3041
2675 u32 result; 3042 u32 result;
2676 if (cpsr & (1 << 16)) 3043 if (cpsr & (1 << 16))
2677 result = from & 0xff; 3044 result = from & 0xff;
2678 else 3045 else
2679 result = to & 0xff; 3046 result = to & 0xff;
2680
2681 if (cpsr & (1 << 17))
2682 result |= from & 0x0000ff00;
2683 else
2684 result |= to & 0x0000ff00;
2685 3047
2686 if (cpsr & (1 << 18)) 3048 if (cpsr & (1 << 17))
2687 result |= from & 0x00ff0000; 3049 result |= from & 0x0000ff00;
2688 else 3050 else
2689 result |= to & 0x00ff0000; 3051 result |= to & 0x0000ff00;
2690 3052
2691 if (cpsr & (1 << 19)) 3053 if (cpsr & (1 << 18))
2692 result |= from & 0xff000000; 3054 result |= from & 0x00ff0000;
2693 else 3055 else
2694 result |= to & 0xff000000; 3056 result |= to & 0x00ff0000;
2695 3057
2696 RD = result; 3058 if (cpsr & (1 << 19))
2697 } 3059 result |= from & 0xff000000;
3060 else
3061 result |= to & 0xff000000;
2698 3062
2699 cpu->Reg[15] += cpu->GetInstructionSize(); 3063 RD = result;
2700 INC_PC(sizeof(generic_arm_inst));
2701 FETCH_INST;
2702 GOTO_NEXT_INST;
2703 } 3064 }
2704 3065
2705 SETEND_INST: 3066 cpu->Reg[15] += cpu->GetInstructionSize();
2706 { 3067 INC_PC(sizeof(generic_arm_inst));
2707 // SETEND is unconditional 3068 FETCH_INST;
2708 setend_inst* const inst_cream = (setend_inst*)inst_base->component; 3069 GOTO_NEXT_INST;
2709 const bool big_endian = (inst_cream->set_bigend == 1); 3070}
2710 3071
2711 if (big_endian) 3072SETEND_INST : {
2712 cpu->Cpsr |= (1 << 9); 3073 // SETEND is unconditional
2713 else 3074 setend_inst* const inst_cream = (setend_inst*)inst_base->component;
2714 cpu->Cpsr &= ~(1 << 9); 3075 const bool big_endian = (inst_cream->set_bigend == 1);
2715 3076
2716 LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE"); 3077 if (big_endian)
3078 cpu->Cpsr |= (1 << 9);
3079 else
3080 cpu->Cpsr &= ~(1 << 9);
2717 3081
2718 cpu->Reg[15] += cpu->GetInstructionSize(); 3082 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 3083
2724 SEV_INST: 3084 cpu->Reg[15] += cpu->GetInstructionSize();
2725 { 3085 INC_PC(sizeof(setend_inst));
2726 // Stubbed, as SEV is a hint instruction. 3086 FETCH_INST;
2727 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3087 GOTO_NEXT_INST;
2728 LOG_TRACE(Core_ARM11, "SEV executed."); 3088}
2729 }
2730 3089
2731 cpu->Reg[15] += cpu->GetInstructionSize(); 3090SEV_INST : {
2732 INC_PC_STUB; 3091 // Stubbed, as SEV is a hint instruction.
2733 FETCH_INST; 3092 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2734 GOTO_NEXT_INST; 3093 LOG_TRACE(Core_ARM11, "SEV executed.");
2735 } 3094 }
2736 3095
2737 SHADD8_INST: 3096 cpu->Reg[15] += cpu->GetInstructionSize();
2738 SHADD16_INST: 3097 INC_PC_STUB;
2739 SHADDSUBX_INST: 3098 FETCH_INST;
2740 SHSUB8_INST: 3099 GOTO_NEXT_INST;
2741 SHSUB16_INST: 3100}
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 3101
2747 const u8 op2 = inst_cream->op2; 3102SHADD8_INST:
2748 const u32 rm_val = RM; 3103SHADD16_INST:
2749 const u32 rn_val = RN; 3104SHADDSUBX_INST:
3105SHSUB8_INST:
3106SHSUB16_INST:
3107SHSUBADDX_INST : {
3108 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3109 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2750 3110
2751 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) { 3111 const u8 op2 = inst_cream->op2;
2752 s32 lo_result = 0; 3112 const u32 rm_val = RM;
2753 s32 hi_result = 0; 3113 const u32 rn_val = RN;
2754 3114
2755 // SHADD16 3115 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
2756 if (op2 == 0x00) { 3116 s32 lo_result = 0;
2757 lo_result = ((s16)(rn_val & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1; 3117 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 3118
2776 RD = ((lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16)); 3119 // SHADD16
3120 if (op2 == 0x00) {
3121 lo_result = ((s16)(rn_val & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1;
3122 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3123 }
3124 // SHASX
3125 else if (op2 == 0x01) {
3126 lo_result = ((s16)(rn_val & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3127 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1;
3128 }
3129 // SHSAX
3130 else if (op2 == 0x02) {
3131 lo_result = ((s16)(rn_val & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3132 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
3133 }
3134 // SHSUB16
3135 else if (op2 == 0x03) {
3136 lo_result = ((s16)(rn_val & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
3137 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
2777 } 3138 }
2778 else if (op2 == 0x04 || op2 == 0x07) {
2779 s16 lo_val1, lo_val2;
2780 s16 hi_val1, hi_val2;
2781
2782 // SHADD8
2783 if (op2 == 0x04) {
2784 lo_val1 = ((s8)(rn_val & 0xFF) + (s8)(rm_val & 0xFF)) >> 1;
2785 lo_val2 = ((s8)((rn_val >> 8) & 0xFF) + (s8)((rm_val >> 8) & 0xFF)) >> 1;
2786 3139
2787 hi_val1 = ((s8)((rn_val >> 16) & 0xFF) + (s8)((rm_val >> 16) & 0xFF)) >> 1; 3140 RD = ((lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16));
2788 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) + (s8)((rm_val >> 24) & 0xFF)) >> 1; 3141 } else if (op2 == 0x04 || op2 == 0x07) {
2789 } 3142 s16 lo_val1, lo_val2;
2790 // SHSUB8 3143 s16 hi_val1, hi_val2;
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 3144
2795 hi_val1 = ((s8)((rn_val >> 16) & 0xFF) - (s8)((rm_val >> 16) & 0xFF)) >> 1; 3145 // SHADD8
2796 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) - (s8)((rm_val >> 24) & 0xFF)) >> 1; 3146 if (op2 == 0x04) {
2797 } 3147 lo_val1 = ((s8)(rn_val & 0xFF) + (s8)(rm_val & 0xFF)) >> 1;
3148 lo_val2 = ((s8)((rn_val >> 8) & 0xFF) + (s8)((rm_val >> 8) & 0xFF)) >> 1;
2798 3149
2799 RD = (lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24); 3150 hi_val1 = ((s8)((rn_val >> 16) & 0xFF) + (s8)((rm_val >> 16) & 0xFF)) >> 1;
3151 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) + (s8)((rm_val >> 24) & 0xFF)) >> 1;
2800 } 3152 }
2801 } 3153 // SHSUB8
2802 3154 else {
2803 cpu->Reg[15] += cpu->GetInstructionSize(); 3155 lo_val1 = ((s8)(rn_val & 0xFF) - (s8)(rm_val & 0xFF)) >> 1;
2804 INC_PC(sizeof(generic_arm_inst)); 3156 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 3157
2819 if (inst_cream->y == 0) 3158 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); 3159 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) - (s8)((rm_val >> 24) & 0xFF)) >> 1;
2821 else 3160 }
2822 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
2823 3161
2824 u32 product = operand1 * operand2; 3162 RD = (lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) |
2825 u32 result = product + RN; 3163 ((hi_val2 & 0xFF) << 24);
2826 if (AddOverflow(product, RN, result))
2827 cpu->Cpsr |= (1 << 27);
2828 RD = result;
2829 } 3164 }
2830 cpu->Reg[15] += cpu->GetInstructionSize();
2831 INC_PC(sizeof(smla_inst));
2832 FETCH_INST;
2833 GOTO_NEXT_INST;
2834 } 3165 }
2835 3166
2836 SMLAD_INST: 3167 cpu->Reg[15] += cpu->GetInstructionSize();
2837 SMLSD_INST: 3168 INC_PC(sizeof(generic_arm_inst));
2838 SMUAD_INST: 3169 FETCH_INST;
2839 SMUSD_INST: 3170 GOTO_NEXT_INST;
2840 { 3171}
2841 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3172
2842 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; 3173SMLA_INST : {
2843 const u8 op2 = inst_cream->op2; 3174 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3175 smla_inst* inst_cream = (smla_inst*)inst_base->component;
3176 s32 operand1, operand2;
3177 if (inst_cream->x == 0)
3178 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
3179 else
3180 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
2844 3181
2845 u32 rm_val = cpu->Reg[inst_cream->Rm]; 3182 if (inst_cream->y == 0)
2846 const u32 rn_val = cpu->Reg[inst_cream->Rn]; 3183 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
3184 else
3185 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
3186
3187 u32 product = operand1 * operand2;
3188 u32 result = product + RN;
3189 if (AddOverflow(product, RN, result))
3190 cpu->Cpsr |= (1 << 27);
3191 RD = result;
3192 }
3193 cpu->Reg[15] += cpu->GetInstructionSize();
3194 INC_PC(sizeof(smla_inst));
3195 FETCH_INST;
3196 GOTO_NEXT_INST;
3197}
2847 3198
2848 if (inst_cream->m) 3199SMLAD_INST:
2849 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); 3200SMLSD_INST:
3201SMUAD_INST:
3202SMUSD_INST : {
3203 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3204 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3205 const u8 op2 = inst_cream->op2;
2850 3206
2851 const s16 rm_lo = (rm_val & 0xFFFF); 3207 u32 rm_val = cpu->Reg[inst_cream->Rm];
2852 const s16 rm_hi = ((rm_val >> 16) & 0xFFFF); 3208 const u32 rn_val = cpu->Reg[inst_cream->Rn];
2853 const s16 rn_lo = (rn_val & 0xFFFF);
2854 const s16 rn_hi = ((rn_val >> 16) & 0xFFFF);
2855 3209
2856 const u32 product1 = (rn_lo * rm_lo); 3210 if (inst_cream->m)
2857 const u32 product2 = (rn_hi * rm_hi); 3211 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
2858 3212
2859 // SMUAD and SMLAD 3213 const s16 rm_lo = (rm_val & 0xFFFF);
2860 if (BIT(op2, 1) == 0) { 3214 const s16 rm_hi = ((rm_val >> 16) & 0xFFFF);
2861 u32 rd_val = (product1 + product2); 3215 const s16 rn_lo = (rn_val & 0xFFFF);
3216 const s16 rn_hi = ((rn_val >> 16) & 0xFFFF);
2862 3217
2863 if (inst_cream->Ra != 15) { 3218 const u32 product1 = (rn_lo * rm_lo);
2864 rd_val += cpu->Reg[inst_cream->Ra]; 3219 const u32 product2 = (rn_hi * rm_hi);
2865 3220
2866 if (ARMul_AddOverflowQ(product1 + product2, cpu->Reg[inst_cream->Ra])) 3221 // SMUAD and SMLAD
2867 cpu->Cpsr |= (1 << 27); 3222 if (BIT(op2, 1) == 0) {
2868 } 3223 u32 rd_val = (product1 + product2);
2869 3224
2870 RD = rd_val; 3225 if (inst_cream->Ra != 15) {
3226 rd_val += cpu->Reg[inst_cream->Ra];
2871 3227
2872 if (ARMul_AddOverflowQ(product1, product2)) 3228 if (ARMul_AddOverflowQ(product1 + product2, cpu->Reg[inst_cream->Ra]))
2873 cpu->Cpsr |= (1 << 27); 3229 cpu->Cpsr |= (1 << 27);
2874 } 3230 }
2875 // SMUSD and SMLSD
2876 else {
2877 u32 rd_val = (product1 - product2);
2878 3231
2879 if (inst_cream->Ra != 15) { 3232 RD = rd_val;
2880 rd_val += cpu->Reg[inst_cream->Ra];
2881 3233
2882 if (ARMul_AddOverflowQ(product1 - product2, cpu->Reg[inst_cream->Ra])) 3234 if (ARMul_AddOverflowQ(product1, product2))
2883 cpu->Cpsr |= (1 << 27); 3235 cpu->Cpsr |= (1 << 27);
2884 } 3236 }
3237 // SMUSD and SMLSD
3238 else {
3239 u32 rd_val = (product1 - product2);
3240
3241 if (inst_cream->Ra != 15) {
3242 rd_val += cpu->Reg[inst_cream->Ra];
2885 3243
2886 RD = rd_val; 3244 if (ARMul_AddOverflowQ(product1 - product2, cpu->Reg[inst_cream->Ra]))
3245 cpu->Cpsr |= (1 << 27);
2887 } 3246 }
2888 }
2889 3247
2890 cpu->Reg[15] += cpu->GetInstructionSize(); 3248 RD = rd_val;
2891 INC_PC(sizeof(smlad_inst)); 3249 }
2892 FETCH_INST;
2893 GOTO_NEXT_INST;
2894 } 3250 }
2895 3251
2896 SMLAL_INST: 3252 cpu->Reg[15] += cpu->GetInstructionSize();
2897 { 3253 INC_PC(sizeof(smlad_inst));
2898 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3254 FETCH_INST;
2899 umlal_inst* inst_cream = (umlal_inst*)inst_base->component; 3255 GOTO_NEXT_INST;
2900 long long int rm = RM; 3256}
2901 long long int rs = RS; 3257
2902 if (BIT(rm, 31)) { 3258SMLAL_INST : {
2903 rm |= 0xffffffff00000000LL; 3259 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2904 } 3260 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
2905 if (BIT(rs, 31)) { 3261 long long int rm = RM;
2906 rs |= 0xffffffff00000000LL; 3262 long long int rs = RS;
2907 } 3263 if (BIT(rm, 31)) {
2908 long long int rst = rm * rs; 3264 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 } 3265 }
2919 cpu->Reg[15] += cpu->GetInstructionSize(); 3266 if (BIT(rs, 31)) {
2920 INC_PC(sizeof(umlal_inst)); 3267 rs |= 0xffffffff00000000LL;
2921 FETCH_INST; 3268 }
2922 GOTO_NEXT_INST; 3269 long long int rst = rm * rs;
2923 } 3270 long long int rdhi32 = RDHI;
2924 3271 long long int hilo = (rdhi32 << 32) + RDLO;
2925 SMLALXY_INST: 3272 rst += hilo;
2926 { 3273 RDLO = BITS(rst, 0, 31);
2927 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3274 RDHI = BITS(rst, 32, 63);
2928 smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component; 3275 if (inst_cream->S) {
2929 3276 cpu->NFlag = BIT(RDHI, 31);
2930 u64 operand1 = RN; 3277 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 } 3278 }
2948
2949 cpu->Reg[15] += cpu->GetInstructionSize();
2950 INC_PC(sizeof(smlalxy_inst));
2951 FETCH_INST;
2952 GOTO_NEXT_INST;
2953 } 3279 }
3280 cpu->Reg[15] += cpu->GetInstructionSize();
3281 INC_PC(sizeof(umlal_inst));
3282 FETCH_INST;
3283 GOTO_NEXT_INST;
3284}
2954 3285
2955 SMLAW_INST: 3286SMLALXY_INST : {
2956 { 3287 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2957 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3288 smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component;
2958 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component; 3289
3290 u64 operand1 = RN;
3291 u64 operand2 = RM;
3292
3293 if (inst_cream->x != 0)
3294 operand1 >>= 16;
3295 if (inst_cream->y != 0)
3296 operand2 >>= 16;
3297 operand1 &= 0xFFFF;
3298 if (operand1 & 0x8000)
3299 operand1 -= 65536;
3300 operand2 &= 0xFFFF;
3301 if (operand2 & 0x8000)
3302 operand2 -= 65536;
3303
3304 u64 dest = ((u64)RDHI << 32 | RDLO) + (operand1 * operand2);
3305 RDLO = (dest & 0xFFFFFFFF);
3306 RDHI = ((dest >> 32) & 0xFFFFFFFF);
3307 }
3308
3309 cpu->Reg[15] += cpu->GetInstructionSize();
3310 INC_PC(sizeof(smlalxy_inst));
3311 FETCH_INST;
3312 GOTO_NEXT_INST;
3313}
2959 3314
2960 const u32 rm_val = RM; 3315SMLAW_INST : {
2961 const u32 rn_val = RN; 3316 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2962 const u32 ra_val = cpu->Reg[inst_cream->Ra]; 3317 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
2963 const bool high = (inst_cream->m == 1);
2964 3318
2965 const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF); 3319 const u32 rm_val = RM;
2966 const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16); 3320 const u32 rn_val = RN;
3321 const u32 ra_val = cpu->Reg[inst_cream->Ra];
3322 const bool high = (inst_cream->m == 1);
2967 3323
2968 RD = BITS(result, 16, 47); 3324 const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF);
3325 const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16);
2969 3326
2970 if ((result >> 16) != (s32)RD) 3327 RD = BITS(result, 16, 47);
2971 cpu->Cpsr |= (1 << 27);
2972 }
2973 3328
2974 cpu->Reg[15] += cpu->GetInstructionSize(); 3329 if ((result >> 16) != (s32)RD)
2975 INC_PC(sizeof(smlad_inst)); 3330 cpu->Cpsr |= (1 << 27);
2976 FETCH_INST;
2977 GOTO_NEXT_INST;
2978 } 3331 }
2979 3332
2980 SMLALD_INST: 3333 cpu->Reg[15] += cpu->GetInstructionSize();
2981 SMLSLD_INST: 3334 INC_PC(sizeof(smlad_inst));
2982 { 3335 FETCH_INST;
2983 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3336 GOTO_NEXT_INST;
2984 smlald_inst* const inst_cream = (smlald_inst*)inst_base->component; 3337}
2985 3338
2986 const bool do_swap = (inst_cream->swap == 1); 3339SMLALD_INST:
2987 const u32 rdlo_val = RDLO; 3340SMLSLD_INST : {
2988 const u32 rdhi_val = RDHI; 3341 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2989 const u32 rn_val = RN; 3342 smlald_inst* const inst_cream = (smlald_inst*)inst_base->component;
2990 u32 rm_val = RM;
2991 3343
2992 if (do_swap) 3344 const bool do_swap = (inst_cream->swap == 1);
2993 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16)); 3345 const u32 rdlo_val = RDLO;
3346 const u32 rdhi_val = RDHI;
3347 const u32 rn_val = RN;
3348 u32 rm_val = RM;
2994 3349
2995 const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF); 3350 if (do_swap)
2996 const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF); 3351 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
2997 s64 result;
2998 3352
2999 // SMLALD 3353 const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF);
3000 if (BIT(inst_cream->op2, 1) == 0) { 3354 const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF);
3001 result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32)); 3355 s64 result;
3002 }
3003 // SMLSLD
3004 else {
3005 result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
3006 }
3007 3356
3008 RDLO = (result & 0xFFFFFFFF); 3357 // SMLALD
3009 RDHI = ((result >> 32) & 0xFFFFFFFF); 3358 if (BIT(inst_cream->op2, 1) == 0) {
3359 result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
3360 }
3361 // SMLSLD
3362 else {
3363 result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
3010 } 3364 }
3011 3365
3012 cpu->Reg[15] += cpu->GetInstructionSize(); 3366 RDLO = (result & 0xFFFFFFFF);
3013 INC_PC(sizeof(smlald_inst)); 3367 RDHI = ((result >> 32) & 0xFFFFFFFF);
3014 FETCH_INST;
3015 GOTO_NEXT_INST;
3016 } 3368 }
3017 3369
3018 SMMLA_INST: 3370 cpu->Reg[15] += cpu->GetInstructionSize();
3019 SMMLS_INST: 3371 INC_PC(sizeof(smlald_inst));
3020 SMMUL_INST: 3372 FETCH_INST;
3021 { 3373 GOTO_NEXT_INST;
3022 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3374}
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 3375
3029 // Assume SMMUL by default. 3376SMMLA_INST:
3030 s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val; 3377SMMLS_INST:
3378SMMUL_INST : {
3379 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3380 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3031 3381
3032 if (inst_cream->Ra != 15) { 3382 const u32 rm_val = RM;
3033 const u32 ra_val = cpu->Reg[inst_cream->Ra]; 3383 const u32 rn_val = RN;
3384 const bool do_round = (inst_cream->m == 1);
3034 3385
3035 // SMMLA, otherwise SMMLS 3386 // Assume SMMUL by default.
3036 if (BIT(inst_cream->op2, 1) == 0) 3387 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 3388
3042 if (do_round) 3389 if (inst_cream->Ra != 15) {
3043 result += 0x80000000; 3390 const u32 ra_val = cpu->Reg[inst_cream->Ra];
3044 3391
3045 RD = ((result >> 32) & 0xFFFFFFFF); 3392 // SMMLA, otherwise SMMLS
3393 if (BIT(inst_cream->op2, 1) == 0)
3394 result += ((s64)ra_val << 32);
3395 else
3396 result = ((s64)ra_val << 32) - result;
3046 } 3397 }
3047 3398
3048 cpu->Reg[15] += cpu->GetInstructionSize(); 3399 if (do_round)
3049 INC_PC(sizeof(smlad_inst)); 3400 result += 0x80000000;
3050 FETCH_INST; 3401
3051 GOTO_NEXT_INST; 3402 RD = ((result >> 32) & 0xFFFFFFFF);
3052 } 3403 }
3053 3404
3054 SMUL_INST: 3405 cpu->Reg[15] += cpu->GetInstructionSize();
3055 { 3406 INC_PC(sizeof(smlad_inst));
3056 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3407 FETCH_INST;
3057 smul_inst* inst_cream = (smul_inst*)inst_base->component; 3408 GOTO_NEXT_INST;
3058 u32 operand1, operand2; 3409}
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 3410
3064 if (inst_cream->y == 0) 3411SMUL_INST : {
3065 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15); 3412 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3066 else 3413 smul_inst* inst_cream = (smul_inst*)inst_base->component;
3067 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); 3414 u32 operand1, operand2;
3068 RD = operand1 * operand2; 3415 if (inst_cream->x == 0)
3416 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
3417 else
3418 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
3419
3420 if (inst_cream->y == 0)
3421 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
3422 else
3423 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
3424 RD = operand1 * operand2;
3425 }
3426 cpu->Reg[15] += cpu->GetInstructionSize();
3427 INC_PC(sizeof(smul_inst));
3428 FETCH_INST;
3429 GOTO_NEXT_INST;
3430}
3431SMULL_INST : {
3432 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3433 umull_inst* inst_cream = (umull_inst*)inst_base->component;
3434 s64 rm = RM;
3435 s64 rs = RS;
3436 if (BIT(rm, 31)) {
3437 rm |= 0xffffffff00000000LL;
3069 } 3438 }
3070 cpu->Reg[15] += cpu->GetInstructionSize(); 3439 if (BIT(rs, 31)) {
3071 INC_PC(sizeof(smul_inst)); 3440 rs |= 0xffffffff00000000LL;
3072 FETCH_INST; 3441 }
3073 GOTO_NEXT_INST; 3442 s64 rst = rm * rs;
3074 } 3443 RDHI = BITS(rst, 32, 63);
3075 SMULL_INST: 3444 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 3445
3091 if (inst_cream->S) { 3446 if (inst_cream->S) {
3092 cpu->NFlag = BIT(RDHI, 31); 3447 cpu->NFlag = BIT(RDHI, 31);
3093 cpu->ZFlag = (RDHI == 0 && RDLO == 0); 3448 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
3094 }
3095 } 3449 }
3096 cpu->Reg[15] += cpu->GetInstructionSize();
3097 INC_PC(sizeof(umull_inst));
3098 FETCH_INST;
3099 GOTO_NEXT_INST;
3100 } 3450 }
3451 cpu->Reg[15] += cpu->GetInstructionSize();
3452 INC_PC(sizeof(umull_inst));
3453 FETCH_INST;
3454 GOTO_NEXT_INST;
3455}
3101 3456
3102 SMULW_INST: 3457SMULW_INST : {
3103 { 3458 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3104 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3459 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3105 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3106 3460
3107 s16 rm = (inst_cream->m == 1) ? ((RM >> 16) & 0xFFFF) : (RM & 0xFFFF); 3461 s16 rm = (inst_cream->m == 1) ? ((RM >> 16) & 0xFFFF) : (RM & 0xFFFF);
3108 3462
3109 s64 result = (s64)rm * (s64)(s32)RN; 3463 s64 result = (s64)rm * (s64)(s32)RN;
3110 RD = BITS(result, 16, 47); 3464 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 } 3465 }
3466 cpu->Reg[15] += cpu->GetInstructionSize();
3467 INC_PC(sizeof(smlad_inst));
3468 FETCH_INST;
3469 GOTO_NEXT_INST;
3470}
3117 3471
3118 SRS_INST: 3472SRS_INST : {
3119 { 3473 // SRS is unconditional
3120 // SRS is unconditional 3474 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
3121 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
3122 3475
3123 u32 address = 0; 3476 u32 address = 0;
3124 inst_cream->get_addr(cpu, inst_cream->inst, address); 3477 inst_cream->get_addr(cpu, inst_cream->inst, address);
3125 3478
3126 cpu->WriteMemory32(address + 0, cpu->Reg[14]); 3479 cpu->WriteMemory32(address + 0, cpu->Reg[14]);
3127 cpu->WriteMemory32(address + 4, cpu->Spsr_copy); 3480 cpu->WriteMemory32(address + 4, cpu->Spsr_copy);
3128 3481
3129 cpu->Reg[15] += cpu->GetInstructionSize(); 3482 cpu->Reg[15] += cpu->GetInstructionSize();
3130 INC_PC(sizeof(ldst_inst)); 3483 INC_PC(sizeof(ldst_inst));
3131 FETCH_INST; 3484 FETCH_INST;
3132 GOTO_NEXT_INST; 3485 GOTO_NEXT_INST;
3133 } 3486}
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 3487
3140 u8 shift_type = inst_cream->shift_type; 3488SSAT_INST : {
3141 u8 shift_amount = inst_cream->imm5; 3489 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3142 u32 rn_val = RN; 3490 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
3143 3491
3144 // 32-bit ASR is encoded as an amount of 0. 3492 u8 shift_type = inst_cream->shift_type;
3145 if (shift_type == 1 && shift_amount == 0) 3493 u8 shift_amount = inst_cream->imm5;
3146 shift_amount = 31; 3494 u32 rn_val = RN;
3147 3495
3148 if (shift_type == 0) 3496 // 32-bit ASR is encoded as an amount of 0.
3149 rn_val <<= shift_amount; 3497 if (shift_type == 1 && shift_amount == 0)
3150 else if (shift_type == 1) 3498 shift_amount = 31;
3151 rn_val = ((s32)rn_val >> shift_amount);
3152 3499
3153 bool saturated = false; 3500 if (shift_type == 0)
3154 rn_val = ARMul_SignedSatQ(rn_val, inst_cream->sat_imm, &saturated); 3501 rn_val <<= shift_amount;
3502 else if (shift_type == 1)
3503 rn_val = ((s32)rn_val >> shift_amount);
3155 3504
3156 if (saturated) 3505 bool saturated = false;
3157 cpu->Cpsr |= (1 << 27); 3506 rn_val = ARMul_SignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
3158 3507
3159 RD = rn_val; 3508 if (saturated)
3160 } 3509 cpu->Cpsr |= (1 << 27);
3161 3510
3162 cpu->Reg[15] += cpu->GetInstructionSize(); 3511 RD = rn_val;
3163 INC_PC(sizeof(ssat_inst));
3164 FETCH_INST;
3165 GOTO_NEXT_INST;
3166 } 3512 }
3167 3513
3168 SSAT16_INST: 3514 cpu->Reg[15] += cpu->GetInstructionSize();
3169 { 3515 INC_PC(sizeof(ssat_inst));
3170 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3516 FETCH_INST;
3171 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; 3517 GOTO_NEXT_INST;
3172 const u8 saturate_to = inst_cream->sat_imm; 3518}
3173 3519
3174 bool sat1 = false; 3520SSAT16_INST : {
3175 bool sat2 = false; 3521 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3522 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
3523 const u8 saturate_to = inst_cream->sat_imm;
3176 3524
3177 RD = (ARMul_SignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) | 3525 bool sat1 = false;
3178 ARMul_SignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16; 3526 bool sat2 = false;
3179 3527
3180 if (sat1 || sat2) 3528 RD = (ARMul_SignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) |
3181 cpu->Cpsr |= (1 << 27); 3529 ARMul_SignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16;
3182 }
3183 3530
3184 cpu->Reg[15] += cpu->GetInstructionSize(); 3531 if (sat1 || sat2)
3185 INC_PC(sizeof(ssat_inst)); 3532 cpu->Cpsr |= (1 << 27);
3186 FETCH_INST; 3533 }
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 3534
3535 cpu->Reg[15] += cpu->GetInstructionSize();
3536 INC_PC(sizeof(ssat_inst));
3537 FETCH_INST;
3538 GOTO_NEXT_INST;
3539}
3540
3541STC_INST : {
3542 // Instruction not implemented
3543 // LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
3544 cpu->Reg[15] += cpu->GetInstructionSize();
3545 INC_PC(sizeof(stc_inst));
3546 FETCH_INST;
3547 GOTO_NEXT_INST;
3548}
3549STM_INST : {
3550 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3551 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3552 unsigned int inst = inst_cream->inst;
3553
3554 unsigned int Rn = BITS(inst, 16, 19);
3555 unsigned int old_RN = cpu->Reg[Rn];
3556
3557 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3558 if (BIT(inst_cream->inst, 22) == 1) {
3559 for (int i = 0; i < 13; i++) {
3560 if (BIT(inst_cream->inst, i)) {
3561 cpu->WriteMemory32(addr, cpu->Reg[i]);
3222 addr += 4; 3562 addr += 4;
3223 } 3563 }
3224 if (BIT(inst_cream->inst, 14)) { 3564 }
3225 if (cpu->Mode == USER32MODE) 3565 if (BIT(inst_cream->inst, 13)) {
3226 cpu->WriteMemory32(addr, cpu->Reg[14]); 3566 if (cpu->Mode == USER32MODE)
3567 cpu->WriteMemory32(addr, cpu->Reg[13]);
3568 else
3569 cpu->WriteMemory32(addr, cpu->Reg_usr[0]);
3570
3571 addr += 4;
3572 }
3573 if (BIT(inst_cream->inst, 14)) {
3574 if (cpu->Mode == USER32MODE)
3575 cpu->WriteMemory32(addr, cpu->Reg[14]);
3576 else
3577 cpu->WriteMemory32(addr, cpu->Reg_usr[1]);
3578
3579 addr += 4;
3580 }
3581 if (BIT(inst_cream->inst, 15)) {
3582 cpu->WriteMemory32(addr, cpu->Reg[15] + 8);
3583 }
3584 } else {
3585 for (int i = 0; i < 15; i++) {
3586 if (BIT(inst_cream->inst, i)) {
3587 if (i == Rn)
3588 cpu->WriteMemory32(addr, old_RN);
3227 else 3589 else
3228 cpu->WriteMemory32(addr, cpu->Reg_usr[1]); 3590 cpu->WriteMemory32(addr, cpu->Reg[i]);
3229 3591
3230 addr += 4; 3592 addr += 4;
3231 } 3593 }
3232 if (BIT(inst_cream->inst, 15)) { 3594 }
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 3595
3247 // Check PC reg 3596 // Check PC reg
3248 if (BIT(inst_cream->inst, 15)) { 3597 if (BIT(inst_cream->inst, 15)) {
3249 cpu->WriteMemory32(addr, cpu->Reg[15] + 8); 3598 cpu->WriteMemory32(addr, cpu->Reg[15] + 8);
3250 }
3251 } 3599 }
3252 } 3600 }
3253 cpu->Reg[15] += cpu->GetInstructionSize();
3254 INC_PC(sizeof(ldst_inst));
3255 FETCH_INST;
3256 GOTO_NEXT_INST;
3257 } 3601 }
3258 SXTB_INST: 3602 cpu->Reg[15] += cpu->GetInstructionSize();
3259 { 3603 INC_PC(sizeof(ldst_inst));
3260 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3604 FETCH_INST;
3261 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component; 3605 GOTO_NEXT_INST;
3606}
3607SXTB_INST : {
3608 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3609 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component;
3262 3610
3263 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate); 3611 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
3264 if (BIT(operand2, 7)) { 3612 if (BIT(operand2, 7)) {
3265 operand2 |= 0xffffff00; 3613 operand2 |= 0xffffff00;
3266 } else { 3614 } else {
3267 operand2 &= 0xff; 3615 operand2 &= 0xff;
3268 }
3269 RD = operand2;
3270 } 3616 }
3271 cpu->Reg[15] += cpu->GetInstructionSize(); 3617 RD = operand2;
3272 INC_PC(sizeof(sxtb_inst));
3273 FETCH_INST;
3274 GOTO_NEXT_INST;
3275 } 3618 }
3276 STR_INST: 3619 cpu->Reg[15] += cpu->GetInstructionSize();
3277 { 3620 INC_PC(sizeof(sxtb_inst));
3278 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3621 FETCH_INST;
3279 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 3622 GOTO_NEXT_INST;
3280 inst_cream->get_addr(cpu, inst_cream->inst, addr); 3623}
3624STR_INST : {
3625 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3626 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3627 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3281 3628
3282 unsigned int reg = BITS(inst_cream->inst, 12, 15); 3629 unsigned int reg = BITS(inst_cream->inst, 12, 15);
3283 unsigned int value = cpu->Reg[reg]; 3630 unsigned int value = cpu->Reg[reg];
3284 3631
3285 if (reg == 15) 3632 if (reg == 15)
3286 value += 2 * cpu->GetInstructionSize(); 3633 value += 2 * cpu->GetInstructionSize();
3287 3634
3288 cpu->WriteMemory32(addr, value); 3635 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 } 3636 }
3332 STRBT_INST: 3637 cpu->Reg[15] += cpu->GetInstructionSize();
3333 { 3638 INC_PC(sizeof(ldst_inst));
3334 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3639 FETCH_INST;
3335 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 3640 GOTO_NEXT_INST;
3336 inst_cream->get_addr(cpu, inst_cream->inst, addr); 3641}
3642UXTB_INST : {
3643 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3644 uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component;
3645 RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3646 }
3647 cpu->Reg[15] += cpu->GetInstructionSize();
3648 INC_PC(sizeof(uxtb_inst));
3649 FETCH_INST;
3650 GOTO_NEXT_INST;
3651}
3652UXTAB_INST : {
3653 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3654 uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component;
3337 3655
3338 const u32 previous_mode = cpu->Mode; 3656 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; 3657 RD = RN + operand2;
3658 }
3659 cpu->Reg[15] += cpu->GetInstructionSize();
3660 INC_PC(sizeof(uxtab_inst));
3661 FETCH_INST;
3662 GOTO_NEXT_INST;
3663}
3664STRB_INST : {
3665 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3666 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3667 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3668 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
3669 cpu->WriteMemory8(addr, value);
3670 }
3671 cpu->Reg[15] += cpu->GetInstructionSize();
3672 INC_PC(sizeof(ldst_inst));
3673 FETCH_INST;
3674 GOTO_NEXT_INST;
3675}
3676STRBT_INST : {
3677 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3678 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3679 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3340 3680
3341 cpu->ChangePrivilegeMode(USER32MODE); 3681 const u32 previous_mode = cpu->Mode;
3342 cpu->WriteMemory8(addr, value); 3682 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 3683
3424 cpu->WriteMemory64(write_addr, value); 3684 cpu->ChangePrivilegeMode(USER32MODE);
3425 RD = 0; 3685 cpu->WriteMemory8(addr, value);
3426 } 3686 cpu->ChangePrivilegeMode(previous_mode);
3427 else { 3687 }
3428 // Failed to write due to mutex access 3688 cpu->Reg[15] += cpu->GetInstructionSize();
3429 RD = 1; 3689 INC_PC(sizeof(ldst_inst));
3430 } 3690 FETCH_INST;
3431 } 3691 GOTO_NEXT_INST;
3432 cpu->Reg[15] += cpu->GetInstructionSize(); 3692}
3433 INC_PC(sizeof(generic_arm_inst)); 3693STRD_INST : {
3434 FETCH_INST; 3694 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3435 GOTO_NEXT_INST; 3695 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3436 } 3696 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3437 STREXH_INST: 3697
3438 { 3698 // The 3DS doesn't have the Large Physical Access Extension (LPAE)
3439 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3699 // so STRD wouldn't store these as a single write.
3440 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 3700 cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]);
3441 unsigned int write_addr = cpu->Reg[inst_cream->Rn]; 3701 cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]);
3442 3702 }
3443 if (cpu->IsExclusiveMemoryAccess(write_addr)) { 3703 cpu->Reg[15] += cpu->GetInstructionSize();
3444 cpu->UnsetExclusiveMemoryAddress(); 3704 INC_PC(sizeof(ldst_inst));
3445 cpu->WriteMemory16(write_addr, RM); 3705 FETCH_INST;
3446 RD = 0; 3706 GOTO_NEXT_INST;
3447 } else { 3707}
3448 // Failed to write due to mutex access 3708STREX_INST : {
3449 RD = 1; 3709 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3450 } 3710 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3711 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3712
3713 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3714 cpu->UnsetExclusiveMemoryAddress();
3715 cpu->WriteMemory32(write_addr, RM);
3716 RD = 0;
3717 } else {
3718 // Failed to write due to mutex access
3719 RD = 1;
3451 } 3720 }
3452 cpu->Reg[15] += cpu->GetInstructionSize(); 3721 }
3453 INC_PC(sizeof(generic_arm_inst)); 3722 cpu->Reg[15] += cpu->GetInstructionSize();
3454 FETCH_INST; 3723 INC_PC(sizeof(generic_arm_inst));
3455 GOTO_NEXT_INST; 3724 FETCH_INST;
3456 } 3725 GOTO_NEXT_INST;
3457 STRH_INST: 3726}
3458 { 3727STREXB_INST : {
3459 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3728 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3460 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 3729 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3461 inst_cream->get_addr(cpu, inst_cream->inst, addr); 3730 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3462 3731
3463 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; 3732 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3464 cpu->WriteMemory16(addr, value); 3733 cpu->UnsetExclusiveMemoryAddress();
3734 cpu->WriteMemory8(write_addr, cpu->Reg[inst_cream->Rm]);
3735 RD = 0;
3736 } else {
3737 // Failed to write due to mutex access
3738 RD = 1;
3465 } 3739 }
3466 cpu->Reg[15] += cpu->GetInstructionSize();
3467 INC_PC(sizeof(ldst_inst));
3468 FETCH_INST;
3469 GOTO_NEXT_INST;
3470 } 3740 }
3471 STRT_INST: 3741 cpu->Reg[15] += cpu->GetInstructionSize();
3472 { 3742 INC_PC(sizeof(generic_arm_inst));
3473 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3743 FETCH_INST;
3474 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 3744 GOTO_NEXT_INST;
3475 inst_cream->get_addr(cpu, inst_cream->inst, addr); 3745}
3746STREXD_INST : {
3747 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3748 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3749 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3476 3750
3477 const u32 previous_mode = cpu->Mode; 3751 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3478 const u32 rt_index = BITS(inst_cream->inst, 12, 15); 3752 cpu->UnsetExclusiveMemoryAddress();
3479 3753
3480 u32 value = cpu->Reg[rt_index]; 3754 const u32 rt = cpu->Reg[inst_cream->Rm + 0];
3481 if (rt_index == 15) 3755 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
3482 value += 2 * cpu->GetInstructionSize(); 3756 u64 value;
3483 3757
3484 cpu->ChangePrivilegeMode(USER32MODE); 3758 if (cpu->InBigEndianMode())
3485 cpu->WriteMemory32(addr, value); 3759 value = (((u64)rt << 32) | rt2);
3486 cpu->ChangePrivilegeMode(previous_mode); 3760 else
3761 value = (((u64)rt2 << 32) | rt);
3762
3763 cpu->WriteMemory64(write_addr, value);
3764 RD = 0;
3765 } else {
3766 // Failed to write due to mutex access
3767 RD = 1;
3487 } 3768 }
3488 cpu->Reg[15] += cpu->GetInstructionSize();
3489 INC_PC(sizeof(ldst_inst));
3490 FETCH_INST;
3491 GOTO_NEXT_INST;
3492 } 3769 }
3493 SUB_INST: 3770 cpu->Reg[15] += cpu->GetInstructionSize();
3494 { 3771 INC_PC(sizeof(generic_arm_inst));
3495 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3772 FETCH_INST;
3496 sub_inst* const inst_cream = (sub_inst*)inst_base->component; 3773 GOTO_NEXT_INST;
3774}
3775STREXH_INST : {
3776 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3777 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3778 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3779
3780 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3781 cpu->UnsetExclusiveMemoryAddress();
3782 cpu->WriteMemory16(write_addr, RM);
3783 RD = 0;
3784 } else {
3785 // Failed to write due to mutex access
3786 RD = 1;
3787 }
3788 }
3789 cpu->Reg[15] += cpu->GetInstructionSize();
3790 INC_PC(sizeof(generic_arm_inst));
3791 FETCH_INST;
3792 GOTO_NEXT_INST;
3793}
3794STRH_INST : {
3795 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3796 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3797 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3497 3798
3498 u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn); 3799 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
3800 cpu->WriteMemory16(addr, value);
3801 }
3802 cpu->Reg[15] += cpu->GetInstructionSize();
3803 INC_PC(sizeof(ldst_inst));
3804 FETCH_INST;
3805 GOTO_NEXT_INST;
3806}
3807STRT_INST : {
3808 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3809 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3810 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3499 3811
3500 bool carry; 3812 const u32 previous_mode = cpu->Mode;
3501 bool overflow; 3813 const u32 rt_index = BITS(inst_cream->inst, 12, 15);
3502 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
3503 3814
3504 if (inst_cream->S && (inst_cream->Rd == 15)) { 3815 u32 value = cpu->Reg[rt_index];
3505 if (CurrentModeHasSPSR) { 3816 if (rt_index == 15)
3506 cpu->Cpsr = cpu->Spsr_copy; 3817 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 3818
3533 cpu->Reg[15] += cpu->GetInstructionSize(); 3819 cpu->ChangePrivilegeMode(USER32MODE);
3534 INC_PC(sizeof(swi_inst)); 3820 cpu->WriteMemory32(addr, value);
3535 FETCH_INST; 3821 cpu->ChangePrivilegeMode(previous_mode);
3536 GOTO_NEXT_INST;
3537 } 3822 }
3538 SWP_INST: 3823 cpu->Reg[15] += cpu->GetInstructionSize();
3539 { 3824 INC_PC(sizeof(ldst_inst));
3540 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3825 FETCH_INST;
3541 swp_inst* inst_cream = (swp_inst*)inst_base->component; 3826 GOTO_NEXT_INST;
3827}
3828SUB_INST : {
3829 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3830 sub_inst* const inst_cream = (sub_inst*)inst_base->component;
3542 3831
3543 addr = RN; 3832 u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
3544 unsigned int value = cpu->ReadMemory32(addr);
3545 cpu->WriteMemory32(addr, RM);
3546 3833
3547 RD = value; 3834 bool carry;
3835 bool overflow;
3836 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
3837
3838 if (inst_cream->S && (inst_cream->Rd == 15)) {
3839 if (CurrentModeHasSPSR) {
3840 cpu->Cpsr = cpu->Spsr_copy;
3841 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
3842 LOAD_NZCVT;
3843 }
3844 } else if (inst_cream->S) {
3845 UPDATE_NFLAG(RD);
3846 UPDATE_ZFLAG(RD);
3847 cpu->CFlag = carry;
3848 cpu->VFlag = overflow;
3548 } 3849 }
3549 cpu->Reg[15] += cpu->GetInstructionSize(); 3850 if (inst_cream->Rd == 15) {
3550 INC_PC(sizeof(swp_inst)); 3851 INC_PC(sizeof(sub_inst));
3551 FETCH_INST; 3852 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 } 3853 }
3563 cpu->Reg[15] += cpu->GetInstructionSize();
3564 INC_PC(sizeof(swp_inst));
3565 FETCH_INST;
3566 GOTO_NEXT_INST;
3567 } 3854 }
3568 SXTAB_INST: 3855 cpu->Reg[15] += cpu->GetInstructionSize();
3569 { 3856 INC_PC(sizeof(sub_inst));
3570 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3857 FETCH_INST;
3571 sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component; 3858 GOTO_NEXT_INST;
3859}
3860SWI_INST : {
3861 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3862 swi_inst* const inst_cream = (swi_inst*)inst_base->component;
3863 SVC::CallSVC(inst_cream->num & 0xFFFF);
3864 }
3572 3865
3573 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff; 3866 cpu->Reg[15] += cpu->GetInstructionSize();
3867 INC_PC(sizeof(swi_inst));
3868 FETCH_INST;
3869 GOTO_NEXT_INST;
3870}
3871SWP_INST : {
3872 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3873 swp_inst* inst_cream = (swp_inst*)inst_base->component;
3574 3874
3575 // Sign extend for byte 3875 addr = RN;
3576 operand2 = (0x80 & operand2)? (0xFFFFFF00 | operand2):operand2; 3876 unsigned int value = cpu->ReadMemory32(addr);
3577 RD = RN + operand2; 3877 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 3878
3612 cpu->Reg[15] += cpu->GetInstructionSize(); 3879 RD = value;
3613 INC_PC(sizeof(sxtab_inst));
3614 FETCH_INST;
3615 GOTO_NEXT_INST;
3616 } 3880 }
3881 cpu->Reg[15] += cpu->GetInstructionSize();
3882 INC_PC(sizeof(swp_inst));
3883 FETCH_INST;
3884 GOTO_NEXT_INST;
3885}
3886SWPB_INST : {
3887 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3888 swp_inst* inst_cream = (swp_inst*)inst_base->component;
3889 addr = RN;
3890 unsigned int value = cpu->ReadMemory8(addr);
3891 cpu->WriteMemory8(addr, (RM & 0xFF));
3892 RD = value;
3893 }
3894 cpu->Reg[15] += cpu->GetInstructionSize();
3895 INC_PC(sizeof(swp_inst));
3896 FETCH_INST;
3897 GOTO_NEXT_INST;
3898}
3899SXTAB_INST : {
3900 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3901 sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component;
3617 3902
3618 SXTAH_INST: 3903 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 3904
3623 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; 3905 // Sign extend for byte
3624 // Sign extend for half 3906 operand2 = (0x80 & operand2) ? (0xFFFFFF00 | operand2) : operand2;
3625 operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2; 3907 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 } 3908 }
3909 cpu->Reg[15] += cpu->GetInstructionSize();
3910 INC_PC(sizeof(uxtab_inst));
3911 FETCH_INST;
3912 GOTO_NEXT_INST;
3913}
3633 3914
3634 TEQ_INST: 3915SXTAB16_INST:
3635 { 3916SXTB16_INST : {
3636 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 3917 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3637 teq_inst* const inst_cream = (teq_inst*)inst_base->component; 3918 sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component;
3638
3639 u32 lop = RN;
3640 u32 rop = SHIFTER_OPERAND;
3641 3919
3642 if (inst_cream->Rn == 15) 3920 const u8 rotation = inst_cream->rotate * 8;
3643 lop += cpu->GetInstructionSize() * 2; 3921 u32 rm_val = RM;
3922 u32 rn_val = RN;
3644 3923
3645 u32 result = lop ^ rop; 3924 if (rotation)
3925 rm_val = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
3646 3926
3647 UPDATE_NFLAG(result); 3927 // SXTB16
3648 UPDATE_ZFLAG(result); 3928 if (inst_cream->Rn == 15) {
3649 UPDATE_CFLAG_WITH_SC; 3929 u32 lo = (u32)(s8)rm_val;
3930 u32 hi = (u32)(s8)(rm_val >> 16);
3931 RD = (lo | (hi << 16));
3932 }
3933 // SXTAB16
3934 else {
3935 u32 lo = (rn_val & 0xFFFF) + (u32)(s8)(rm_val & 0xFF);
3936 u32 hi = ((rn_val >> 16) & 0xFFFF) + (u32)(s8)((rm_val >> 16) & 0xFF);
3937 RD = (lo | (hi << 16));
3650 } 3938 }
3651 cpu->Reg[15] += cpu->GetInstructionSize();
3652 INC_PC(sizeof(teq_inst));
3653 FETCH_INST;
3654 GOTO_NEXT_INST;
3655 } 3939 }
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 3940
3661 u32 lop = RN; 3941 cpu->Reg[15] += cpu->GetInstructionSize();
3662 u32 rop = SHIFTER_OPERAND; 3942 INC_PC(sizeof(sxtab_inst));
3663 3943 FETCH_INST;
3664 if (inst_cream->Rn == 15) 3944 GOTO_NEXT_INST;
3665 lop += cpu->GetInstructionSize() * 2; 3945}
3666 3946
3667 u32 result = lop & rop; 3947SXTAH_INST : {
3948 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3949 sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component;
3668 3950
3669 UPDATE_NFLAG(result); 3951 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
3670 UPDATE_ZFLAG(result); 3952 // Sign extend for half
3671 UPDATE_CFLAG_WITH_SC; 3953 operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2;
3672 } 3954 RD = RN + operand2;
3673 cpu->Reg[15] += cpu->GetInstructionSize(); 3955 }
3674 INC_PC(sizeof(tst_inst)); 3956 cpu->Reg[15] += cpu->GetInstructionSize();
3675 FETCH_INST; 3957 INC_PC(sizeof(sxtah_inst));
3676 GOTO_NEXT_INST; 3958 FETCH_INST;
3677 } 3959 GOTO_NEXT_INST;
3678 3960}
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 3961
3693 s32 lo_result = 0; 3962TEQ_INST : {
3694 s32 hi_result = 0; 3963 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3964 teq_inst* const inst_cream = (teq_inst*)inst_base->component;
3695 3965
3696 // UADD16 3966 u32 lop = RN;
3697 if (op2 == 0x00) { 3967 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 3968
3709 if (hi_result & 0xFFFF0000) { 3969 if (inst_cream->Rn == 15)
3710 cpu->Cpsr |= (1 << 18); 3970 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 3971
3730 if (hi_result >= 0x10000) { 3972 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 3973
3751 if (hi_result >= 0) { 3974 UPDATE_NFLAG(result);
3752 cpu->Cpsr |= (1 << 18); 3975 UPDATE_ZFLAG(result);
3753 cpu->Cpsr |= (1 << 19); 3976 UPDATE_CFLAG_WITH_SC;
3754 } else { 3977 }
3755 cpu->Cpsr &= ~(1 << 18); 3978 cpu->Reg[15] += cpu->GetInstructionSize();
3756 cpu->Cpsr &= ~(1 << 19); 3979 INC_PC(sizeof(teq_inst));
3757 } 3980 FETCH_INST;
3758 } 3981 GOTO_NEXT_INST;
3759 // USUB16 3982}
3760 else if (op2 == 0x03) { 3983TST_INST : {
3761 lo_result = (rn_val & 0xFFFF) - (rm_val & 0xFFFF); 3984 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3762 hi_result = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF); 3985 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 3986
3772 if ((hi_result & 0xFFFF0000) == 0) { 3987 u32 lop = RN;
3773 cpu->Cpsr |= (1 << 18); 3988 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 3989
3792 if (sum2 >= 0x100) 3990 if (inst_cream->Rn == 15)
3793 cpu->Cpsr |= (1 << 17); 3991 lop += cpu->GetInstructionSize() * 2;
3794 else
3795 cpu->Cpsr &= ~(1 << 17);
3796 3992
3797 if (sum3 >= 0x100) 3993 u32 result = lop & rop;
3798 cpu->Cpsr |= (1 << 18);
3799 else
3800 cpu->Cpsr &= ~(1 << 18);
3801 3994
3802 if (sum4 >= 0x100) 3995 UPDATE_NFLAG(result);
3803 cpu->Cpsr |= (1 << 19); 3996 UPDATE_ZFLAG(result);
3804 else 3997 UPDATE_CFLAG_WITH_SC;
3805 cpu->Cpsr &= ~(1 << 19); 3998 }
3999 cpu->Reg[15] += cpu->GetInstructionSize();
4000 INC_PC(sizeof(tst_inst));
4001 FETCH_INST;
4002 GOTO_NEXT_INST;
4003}
3806 4004
3807 lo_result = ((sum1 & 0xFF) | (sum2 & 0xFF) << 8); 4005UADD8_INST:
3808 hi_result = ((sum3 & 0xFF) | (sum4 & 0xFF) << 8); 4006UADD16_INST:
4007UADDSUBX_INST:
4008USUB8_INST:
4009USUB16_INST:
4010USUBADDX_INST : {
4011 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4012 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4013
4014 const u8 op2 = inst_cream->op2;
4015 const u32 rm_val = RM;
4016 const u32 rn_val = RN;
4017
4018 s32 lo_result = 0;
4019 s32 hi_result = 0;
4020
4021 // UADD16
4022 if (op2 == 0x00) {
4023 lo_result = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
4024 hi_result = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4025
4026 if (lo_result & 0xFFFF0000) {
4027 cpu->Cpsr |= (1 << 16);
4028 cpu->Cpsr |= (1 << 17);
4029 } else {
4030 cpu->Cpsr &= ~(1 << 16);
4031 cpu->Cpsr &= ~(1 << 17);
3809 } 4032 }
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 4033
3822 if (diff2 >= 0) 4034 if (hi_result & 0xFFFF0000) {
3823 cpu->Cpsr |= (1 << 17); 4035 cpu->Cpsr |= (1 << 18);
3824 else 4036 cpu->Cpsr |= (1 << 19);
3825 cpu->Cpsr &= ~(1 << 17); 4037 } else {
3826 4038 cpu->Cpsr &= ~(1 << 18);
3827 if (diff3 >= 0) 4039 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 } 4040 }
3840
3841 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
3842 } 4041 }
4042 // UASX
4043 else if (op2 == 0x01) {
4044 lo_result = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4045 hi_result = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
4046
4047 if (lo_result >= 0) {
4048 cpu->Cpsr |= (1 << 16);
4049 cpu->Cpsr |= (1 << 17);
4050 } else {
4051 cpu->Cpsr &= ~(1 << 16);
4052 cpu->Cpsr &= ~(1 << 17);
4053 }
3843 4054
3844 cpu->Reg[15] += cpu->GetInstructionSize(); 4055 if (hi_result >= 0x10000) {
3845 INC_PC(sizeof(generic_arm_inst)); 4056 cpu->Cpsr |= (1 << 18);
3846 FETCH_INST; 4057 cpu->Cpsr |= (1 << 19);
3847 GOTO_NEXT_INST; 4058 } else {
3848 } 4059 cpu->Cpsr &= ~(1 << 18);
3849 4060 cpu->Cpsr &= ~(1 << 19);
3850 UHADD8_INST: 4061 }
3851 UHADD16_INST: 4062 }
3852 UHADDSUBX_INST: 4063 // USAX
3853 UHSUBADDX_INST: 4064 else if (op2 == 0x02) {
3854 UHSUB8_INST: 4065 lo_result = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
3855 UHSUB16_INST: 4066 hi_result = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
3856 { 4067
3857 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4068 if (lo_result >= 0x10000) {
3858 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component; 4069 cpu->Cpsr |= (1 << 16);
3859 const u32 rm_val = RM; 4070 cpu->Cpsr |= (1 << 17);
3860 const u32 rn_val = RN; 4071 } else {
3861 const u8 op2 = inst_cream->op2; 4072 cpu->Cpsr &= ~(1 << 16);
3862 4073 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 } 4074 }
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 4075
3915 sum1 >>= 1; 4076 if (hi_result >= 0) {
3916 sum2 >>= 1; 4077 cpu->Cpsr |= (1 << 18);
3917 sum3 >>= 1; 4078 cpu->Cpsr |= (1 << 19);
3918 sum4 >>= 1; 4079 } else {
4080 cpu->Cpsr &= ~(1 << 18);
4081 cpu->Cpsr &= ~(1 << 19);
4082 }
4083 }
4084 // USUB16
4085 else if (op2 == 0x03) {
4086 lo_result = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
4087 hi_result = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4088
4089 if ((lo_result & 0xFFFF0000) == 0) {
4090 cpu->Cpsr |= (1 << 16);
4091 cpu->Cpsr |= (1 << 17);
4092 } else {
4093 cpu->Cpsr &= ~(1 << 16);
4094 cpu->Cpsr &= ~(1 << 17);
4095 }
3919 4096
3920 RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24); 4097 if ((hi_result & 0xFFFF0000) == 0) {
4098 cpu->Cpsr |= (1 << 18);
4099 cpu->Cpsr |= (1 << 19);
4100 } else {
4101 cpu->Cpsr &= ~(1 << 18);
4102 cpu->Cpsr &= ~(1 << 19);
3921 } 4103 }
3922 } 4104 }
4105 // UADD8
4106 else if (op2 == 0x04) {
4107 s16 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
4108 s16 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
4109 s16 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
4110 s16 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
4111
4112 if (sum1 >= 0x100)
4113 cpu->Cpsr |= (1 << 16);
4114 else
4115 cpu->Cpsr &= ~(1 << 16);
3923 4116
3924 cpu->Reg[15] += cpu->GetInstructionSize(); 4117 if (sum2 >= 0x100)
3925 INC_PC(sizeof(generic_arm_inst)); 4118 cpu->Cpsr |= (1 << 17);
3926 FETCH_INST; 4119 else
3927 GOTO_NEXT_INST; 4120 cpu->Cpsr &= ~(1 << 17);
3928 }
3929 4121
3930 UMAAL_INST: 4122 if (sum3 >= 0x100)
3931 { 4123 cpu->Cpsr |= (1 << 18);
3932 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4124 else
3933 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; 4125 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 4126
3940 RDLO = (result & 0xFFFFFFFF); 4127 if (sum4 >= 0x100)
3941 RDHI = ((result >> 32) & 0xFFFFFFFF); 4128 cpu->Cpsr |= (1 << 19);
3942 } 4129 else
3943 cpu->Reg[15] += cpu->GetInstructionSize(); 4130 cpu->Cpsr &= ~(1 << 19);
3944 INC_PC(sizeof(umaal_inst)); 4131
3945 FETCH_INST; 4132 lo_result = ((sum1 & 0xFF) | (sum2 & 0xFF) << 8);
3946 GOTO_NEXT_INST; 4133 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 } 4134 }
3986 cpu->Reg[15] += cpu->GetInstructionSize(); 4135 // USUB8
3987 INC_PC(sizeof(umull_inst)); 4136 else if (op2 == 0x07) {
3988 FETCH_INST; 4137 s16 diff1 = (rn_val & 0xFF) - (rm_val & 0xFF);
3989 GOTO_NEXT_INST; 4138 s16 diff2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
3990 } 4139 s16 diff3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
3991 B_2_THUMB: 4140 s16 diff4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
3992 { 4141
3993 b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component; 4142 if (diff1 >= 0)
3994 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; 4143 cpu->Cpsr |= (1 << 16);
3995 INC_PC(sizeof(b_2_thumb)); 4144 else
3996 goto DISPATCH; 4145 cpu->Cpsr &= ~(1 << 16);
3997 }
3998 B_COND_THUMB:
3999 {
4000 b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component;
4001 4146
4002 if(CondPassed(cpu, inst_cream->cond)) 4147 if (diff2 >= 0)
4003 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; 4148 cpu->Cpsr |= (1 << 17);
4004 else 4149 else
4005 cpu->Reg[15] += 2; 4150 cpu->Cpsr &= ~(1 << 17);
4006 4151
4007 INC_PC(sizeof(b_cond_thumb)); 4152 if (diff3 >= 0)
4008 goto DISPATCH; 4153 cpu->Cpsr |= (1 << 18);
4009 } 4154 else
4010 BL_1_THUMB: 4155 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 4156
4040 UQADD8_INST: 4157 if (diff4 >= 0)
4041 UQADD16_INST: 4158 cpu->Cpsr |= (1 << 19);
4042 UQADDSUBX_INST: 4159 else
4043 UQSUB8_INST: 4160 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 4161
4050 const u8 op2 = inst_cream->op2; 4162 lo_result = (diff1 & 0xFF) | ((diff2 & 0xFF) << 8);
4051 const u32 rm_val = RM; 4163 hi_result = (diff3 & 0xFF) | ((diff4 & 0xFF) << 8);
4052 const u32 rn_val = RN; 4164 }
4053 4165
4054 u16 lo_val = 0; 4166 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
4055 u16 hi_val = 0; 4167 }
4056 4168
4057 // UQADD16 4169 cpu->Reg[15] += cpu->GetInstructionSize();
4170 INC_PC(sizeof(generic_arm_inst));
4171 FETCH_INST;
4172 GOTO_NEXT_INST;
4173}
4174
4175UHADD8_INST:
4176UHADD16_INST:
4177UHADDSUBX_INST:
4178UHSUBADDX_INST:
4179UHSUB8_INST:
4180UHSUB16_INST : {
4181 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4182 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4183 const u32 rm_val = RM;
4184 const u32 rn_val = RN;
4185 const u8 op2 = inst_cream->op2;
4186
4187 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
4188 u32 lo_val = 0;
4189 u32 hi_val = 0;
4190
4191 // UHADD16
4058 if (op2 == 0x00) { 4192 if (op2 == 0x00) {
4059 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF); 4193 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
4060 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); 4194 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4061 } 4195 }
4062 // UQASX 4196 // UHASX
4063 else if (op2 == 0x01) { 4197 else if (op2 == 0x01) {
4064 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); 4198 lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4065 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); 4199 hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
4066 } 4200 }
4067 // UQSAX 4201 // UHSAX
4068 else if (op2 == 0x02) { 4202 else if (op2 == 0x02) {
4069 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF); 4203 lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4070 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF); 4204 hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
4071 } 4205 }
4072 // UQSUB16 4206 // UHSUB16
4073 else if (op2 == 0x03) { 4207 else if (op2 == 0x03) {
4074 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF); 4208 lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
4075 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF); 4209 hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4076 } 4210 }
4077 // UQADD8 4211
4078 else if (op2 == 0x04) { 4212 lo_val >>= 1;
4079 lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) | 4213 hi_val >>= 1;
4080 ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8; 4214
4081 hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) | 4215 RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
4082 ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8; 4216 } else if (op2 == 0x04 || op2 == 0x07) {
4217 u32 sum1;
4218 u32 sum2;
4219 u32 sum3;
4220 u32 sum4;
4221
4222 // UHADD8
4223 if (op2 == 0x04) {
4224 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
4225 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
4226 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
4227 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
4083 } 4228 }
4084 // UQSUB8 4229 // UHSUB8
4085 else { 4230 else {
4086 lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) | 4231 sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
4087 ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8; 4232 sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
4088 hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) | 4233 sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
4089 ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8; 4234 sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
4090 } 4235 }
4091 4236
4092 RD = ((lo_val & 0xFFFF) | hi_val << 16); 4237 sum1 >>= 1;
4238 sum2 >>= 1;
4239 sum3 >>= 1;
4240 sum4 >>= 1;
4241
4242 RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) |
4243 ((sum4 & 0xFF) << 24);
4093 } 4244 }
4245 }
4246
4247 cpu->Reg[15] += cpu->GetInstructionSize();
4248 INC_PC(sizeof(generic_arm_inst));
4249 FETCH_INST;
4250 GOTO_NEXT_INST;
4251}
4094 4252
4095 cpu->Reg[15] += cpu->GetInstructionSize(); 4253UMAAL_INST : {
4096 INC_PC(sizeof(generic_arm_inst)); 4254 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4097 FETCH_INST; 4255 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
4098 GOTO_NEXT_INST; 4256 const u64 rm = RM;
4257 const u64 rn = RN;
4258 const u64 rd_lo = RDLO;
4259 const u64 rd_hi = RDHI;
4260 const u64 result = (rm * rn) + rd_lo + rd_hi;
4261
4262 RDLO = (result & 0xFFFFFFFF);
4263 RDHI = ((result >> 32) & 0xFFFFFFFF);
4264 }
4265 cpu->Reg[15] += cpu->GetInstructionSize();
4266 INC_PC(sizeof(umaal_inst));
4267 FETCH_INST;
4268 GOTO_NEXT_INST;
4269}
4270UMLAL_INST : {
4271 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4272 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
4273 unsigned long long int rm = RM;
4274 unsigned long long int rs = RS;
4275 unsigned long long int rst = rm * rs;
4276 unsigned long long int add = ((unsigned long long)RDHI) << 32;
4277 add += RDLO;
4278 rst += add;
4279 RDLO = BITS(rst, 0, 31);
4280 RDHI = BITS(rst, 32, 63);
4281
4282 if (inst_cream->S) {
4283 cpu->NFlag = BIT(RDHI, 31);
4284 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
4285 }
4286 }
4287 cpu->Reg[15] += cpu->GetInstructionSize();
4288 INC_PC(sizeof(umlal_inst));
4289 FETCH_INST;
4290 GOTO_NEXT_INST;
4291}
4292UMULL_INST : {
4293 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4294 umull_inst* inst_cream = (umull_inst*)inst_base->component;
4295 unsigned long long int rm = RM;
4296 unsigned long long int rs = RS;
4297 unsigned long long int rst = rm * rs;
4298 RDHI = BITS(rst, 32, 63);
4299 RDLO = BITS(rst, 0, 31);
4300
4301 if (inst_cream->S) {
4302 cpu->NFlag = BIT(RDHI, 31);
4303 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
4304 }
4099 } 4305 }
4306 cpu->Reg[15] += cpu->GetInstructionSize();
4307 INC_PC(sizeof(umull_inst));
4308 FETCH_INST;
4309 GOTO_NEXT_INST;
4310}
4311B_2_THUMB : {
4312 b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component;
4313 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
4314 INC_PC(sizeof(b_2_thumb));
4315 goto DISPATCH;
4316}
4317B_COND_THUMB : {
4318 b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component;
4100 4319
4101 USAD8_INST: 4320 if (CondPassed(cpu, inst_cream->cond))
4102 USADA8_INST: 4321 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
4103 { 4322 else
4104 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4323 cpu->Reg[15] += 2;
4105 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4106 4324
4107 const u8 ra_idx = inst_cream->Ra; 4325 INC_PC(sizeof(b_cond_thumb));
4108 const u32 rm_val = RM; 4326 goto DISPATCH;
4109 const u32 rn_val = RN; 4327}
4328BL_1_THUMB : {
4329 bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component;
4330 cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm;
4331 cpu->Reg[15] += cpu->GetInstructionSize();
4332 INC_PC(sizeof(bl_1_thumb));
4333 FETCH_INST;
4334 GOTO_NEXT_INST;
4335}
4336BL_2_THUMB : {
4337 bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component;
4338 int tmp = ((cpu->Reg[15] + 2) | 1);
4339 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm);
4340 cpu->Reg[14] = tmp;
4341 INC_PC(sizeof(bl_2_thumb));
4342 goto DISPATCH;
4343}
4344BLX_1_THUMB : {
4345 // BLX 1 for armv5t and above
4346 u32 tmp = cpu->Reg[15];
4347 blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component;
4348 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC;
4349 cpu->Reg[14] = ((tmp + 2) | 1);
4350 cpu->TFlag = 0;
4351 INC_PC(sizeof(blx_1_thumb));
4352 goto DISPATCH;
4353}
4110 4354
4111 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF); 4355UQADD8_INST:
4112 const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF); 4356UQADD16_INST:
4113 const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF); 4357UQADDSUBX_INST:
4114 const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF); 4358UQSUB8_INST:
4359UQSUB16_INST:
4360UQSUBADDX_INST : {
4361 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4362 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4363
4364 const u8 op2 = inst_cream->op2;
4365 const u32 rm_val = RM;
4366 const u32 rn_val = RN;
4367
4368 u16 lo_val = 0;
4369 u16 hi_val = 0;
4370
4371 // UQADD16
4372 if (op2 == 0x00) {
4373 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
4374 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4375 }
4376 // UQASX
4377 else if (op2 == 0x01) {
4378 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4379 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
4380 }
4381 // UQSAX
4382 else if (op2 == 0x02) {
4383 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4384 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
4385 }
4386 // UQSUB16
4387 else if (op2 == 0x03) {
4388 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF);
4389 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4390 }
4391 // UQADD8
4392 else if (op2 == 0x04) {
4393 lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) |
4394 ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8;
4395 hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) |
4396 ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8;
4397 }
4398 // UQSUB8
4399 else {
4400 lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) |
4401 ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8;
4402 hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) |
4403 ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8;
4404 }
4405
4406 RD = ((lo_val & 0xFFFF) | hi_val << 16);
4407 }
4115 4408
4116 u32 finalDif = (diff1 + diff2 + diff3 + diff4); 4409 cpu->Reg[15] += cpu->GetInstructionSize();
4410 INC_PC(sizeof(generic_arm_inst));
4411 FETCH_INST;
4412 GOTO_NEXT_INST;
4413}
4117 4414
4118 // Op is USADA8 if true. 4415USAD8_INST:
4119 if (ra_idx != 15) 4416USADA8_INST : {
4120 finalDif += cpu->Reg[ra_idx]; 4417 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4418 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4121 4419
4122 RD = finalDif; 4420 const u8 ra_idx = inst_cream->Ra;
4123 } 4421 const u32 rm_val = RM;
4422 const u32 rn_val = RN;
4423
4424 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
4425 const u8 diff2 =
4426 ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
4427 const u8 diff3 =
4428 ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
4429 const u8 diff4 =
4430 ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
4124 4431
4125 cpu->Reg[15] += cpu->GetInstructionSize(); 4432 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
4126 INC_PC(sizeof(generic_arm_inst)); 4433
4127 FETCH_INST; 4434 // Op is USADA8 if true.
4128 GOTO_NEXT_INST; 4435 if (ra_idx != 15)
4436 finalDif += cpu->Reg[ra_idx];
4437
4438 RD = finalDif;
4129 } 4439 }
4130 4440
4131 USAT_INST: 4441 cpu->Reg[15] += cpu->GetInstructionSize();
4132 { 4442 INC_PC(sizeof(generic_arm_inst));
4133 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4443 FETCH_INST;
4134 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; 4444 GOTO_NEXT_INST;
4445}
4135 4446
4136 u8 shift_type = inst_cream->shift_type; 4447USAT_INST : {
4137 u8 shift_amount = inst_cream->imm5; 4448 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4138 u32 rn_val = RN; 4449 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
4139 4450
4140 // 32-bit ASR is encoded as an amount of 0. 4451 u8 shift_type = inst_cream->shift_type;
4141 if (shift_type == 1 && shift_amount == 0) 4452 u8 shift_amount = inst_cream->imm5;
4142 shift_amount = 31; 4453 u32 rn_val = RN;
4143 4454
4144 if (shift_type == 0) 4455 // 32-bit ASR is encoded as an amount of 0.
4145 rn_val <<= shift_amount; 4456 if (shift_type == 1 && shift_amount == 0)
4146 else if (shift_type == 1) 4457 shift_amount = 31;
4147 rn_val = ((s32)rn_val >> shift_amount);
4148 4458
4149 bool saturated = false; 4459 if (shift_type == 0)
4150 rn_val = ARMul_UnsignedSatQ(rn_val, inst_cream->sat_imm, &saturated); 4460 rn_val <<= shift_amount;
4461 else if (shift_type == 1)
4462 rn_val = ((s32)rn_val >> shift_amount);
4151 4463
4152 if (saturated) 4464 bool saturated = false;
4153 cpu->Cpsr |= (1 << 27); 4465 rn_val = ARMul_UnsignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
4154 4466
4155 RD = rn_val; 4467 if (saturated)
4156 } 4468 cpu->Cpsr |= (1 << 27);
4157 4469
4158 cpu->Reg[15] += cpu->GetInstructionSize(); 4470 RD = rn_val;
4159 INC_PC(sizeof(ssat_inst));
4160 FETCH_INST;
4161 GOTO_NEXT_INST;
4162 } 4471 }
4163 4472
4164 USAT16_INST: 4473 cpu->Reg[15] += cpu->GetInstructionSize();
4165 { 4474 INC_PC(sizeof(ssat_inst));
4166 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4475 FETCH_INST;
4167 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component; 4476 GOTO_NEXT_INST;
4168 const u8 saturate_to = inst_cream->sat_imm; 4477}
4169 4478
4170 bool sat1 = false; 4479USAT16_INST : {
4171 bool sat2 = false; 4480 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4481 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
4482 const u8 saturate_to = inst_cream->sat_imm;
4172 4483
4173 RD = (ARMul_UnsignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) | 4484 bool sat1 = false;
4174 ARMul_UnsignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16; 4485 bool sat2 = false;
4175 4486
4176 if (sat1 || sat2) 4487 RD = (ARMul_UnsignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) |
4177 cpu->Cpsr |= (1 << 27); 4488 ARMul_UnsignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16;
4178 }
4179 4489
4180 cpu->Reg[15] += cpu->GetInstructionSize(); 4490 if (sat1 || sat2)
4181 INC_PC(sizeof(ssat_inst)); 4491 cpu->Cpsr |= (1 << 27);
4182 FETCH_INST;
4183 GOTO_NEXT_INST;
4184 } 4492 }
4185 4493
4186 UXTAB16_INST: 4494 cpu->Reg[15] += cpu->GetInstructionSize();
4187 UXTB16_INST: 4495 INC_PC(sizeof(ssat_inst));
4188 { 4496 FETCH_INST;
4189 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4497 GOTO_NEXT_INST;
4190 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component; 4498}
4191 4499
4192 const u8 rn_idx = inst_cream->Rn; 4500UXTAB16_INST:
4193 const u32 rm_val = RM; 4501UXTB16_INST : {
4194 const u32 rotation = inst_cream->rotate * 8; 4502 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4195 const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation)); 4503 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
4196 4504
4197 // UXTB16, otherwise UXTAB16 4505 const u8 rn_idx = inst_cream->Rn;
4198 if (rn_idx == 15) { 4506 const u32 rm_val = RM;
4199 RD = rotated_rm & 0x00FF00FF; 4507 const u32 rotation = inst_cream->rotate * 8;
4200 } else { 4508 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 4509
4207 RD = ((hi_result << 16) | (lo_result & 0xFFFF)); 4510 // UXTB16, otherwise UXTAB16
4208 } 4511 if (rn_idx == 15) {
4209 } 4512 RD = rotated_rm & 0x00FF00FF;
4513 } else {
4514 const u32 rn_val = RN;
4515 const u8 lo_rotated = (rotated_rm & 0xFF);
4516 const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
4517 const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
4518 const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
4210 4519
4211 cpu->Reg[15] += cpu->GetInstructionSize(); 4520 RD = ((hi_result << 16) | (lo_result & 0xFFFF));
4212 INC_PC(sizeof(uxtab_inst)); 4521 }
4213 FETCH_INST;
4214 GOTO_NEXT_INST;
4215 } 4522 }
4216 4523
4217 WFE_INST: 4524 cpu->Reg[15] += cpu->GetInstructionSize();
4218 { 4525 INC_PC(sizeof(uxtab_inst));
4219 // Stubbed, as WFE is a hint instruction. 4526 FETCH_INST;
4220 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4527 GOTO_NEXT_INST;
4221 LOG_TRACE(Core_ARM11, "WFE executed."); 4528}
4222 }
4223 4529
4224 cpu->Reg[15] += cpu->GetInstructionSize(); 4530WFE_INST : {
4225 INC_PC_STUB; 4531 // Stubbed, as WFE is a hint instruction.
4226 FETCH_INST; 4532 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4227 GOTO_NEXT_INST; 4533 LOG_TRACE(Core_ARM11, "WFE executed.");
4228 } 4534 }
4229 4535
4230 WFI_INST: 4536 cpu->Reg[15] += cpu->GetInstructionSize();
4231 { 4537 INC_PC_STUB;
4232 // Stubbed, as WFI is a hint instruction. 4538 FETCH_INST;
4233 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4539 GOTO_NEXT_INST;
4234 LOG_TRACE(Core_ARM11, "WFI executed."); 4540}
4235 }
4236 4541
4237 cpu->Reg[15] += cpu->GetInstructionSize(); 4542WFI_INST : {
4238 INC_PC_STUB; 4543 // Stubbed, as WFI is a hint instruction.
4239 FETCH_INST; 4544 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4240 GOTO_NEXT_INST; 4545 LOG_TRACE(Core_ARM11, "WFI executed.");
4241 } 4546 }
4242 4547
4243 YIELD_INST: 4548 cpu->Reg[15] += cpu->GetInstructionSize();
4244 { 4549 INC_PC_STUB;
4245 // Stubbed, as YIELD is a hint instruction. 4550 FETCH_INST;
4246 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) { 4551 GOTO_NEXT_INST;
4247 LOG_TRACE(Core_ARM11, "YIELD executed."); 4552}
4248 }
4249 4553
4250 cpu->Reg[15] += cpu->GetInstructionSize(); 4554YIELD_INST : {
4251 INC_PC_STUB; 4555 // Stubbed, as YIELD is a hint instruction.
4252 FETCH_INST; 4556 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4253 GOTO_NEXT_INST; 4557 LOG_TRACE(Core_ARM11, "YIELD executed.");
4254 } 4558 }
4255 4559
4256 #define VFP_INTERPRETER_IMPL 4560 cpu->Reg[15] += cpu->GetInstructionSize();
4257 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 4561 INC_PC_STUB;
4258 #undef VFP_INTERPRETER_IMPL 4562 FETCH_INST;
4563 GOTO_NEXT_INST;
4564}
4259 4565
4260 END: 4566#define VFP_INTERPRETER_IMPL
4261 { 4567#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
4262 SAVE_NZCVT; 4568#undef VFP_INTERPRETER_IMPL
4263 cpu->NumInstrsToExecute = 0; 4569
4264 return num_instrs; 4570END : {
4265 } 4571 SAVE_NZCVT;
4266 INIT_INST_LENGTH: 4572 cpu->NumInstrsToExecute = 0;
4267 { 4573 return num_instrs;
4268 cpu->NumInstrsToExecute = 0; 4574}
4269 return num_instrs; 4575INIT_INST_LENGTH : {
4270 } 4576 cpu->NumInstrsToExecute = 0;
4577 return num_instrs;
4578}
4271} 4579}
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..780638638 100644
--- a/src/core/arm/dyncom/arm_dyncom_trans.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_trans.cpp
@@ -1,8 +1,6 @@
1#include <cstdlib> 1#include <cstdlib>
2
3#include "common/assert.h" 2#include "common/assert.h"
4#include "common/common_types.h" 3#include "common/common_types.h"
5
6#include "core/arm/dyncom/arm_dyncom_interpreter.h" 4#include "core/arm/dyncom/arm_dyncom_interpreter.h"
7#include "core/arm/dyncom/arm_dyncom_trans.h" 5#include "core/arm/dyncom/arm_dyncom_trans.h"
8#include "core/arm/skyeye_common/armstate.h" 6#include "core/arm/skyeye_common/armstate.h"
@@ -19,24 +17,23 @@ static void* AllocBuffer(size_t size) {
19 return static_cast<void*>(&trans_cache_buf[start]); 17 return static_cast<void*>(&trans_cache_buf[start]);
20} 18}
21 19
22#define glue(x, y) x ## y 20#define glue(x, y) x##y
23#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s) 21#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s)
24 22
25shtop_fp_t GetShifterOp(unsigned int inst); 23shtop_fp_t GetShifterOp(unsigned int inst);
26get_addr_fp_t GetAddressingOp(unsigned int inst); 24get_addr_fp_t GetAddressingOp(unsigned int inst);
27get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst); 25get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst);
28 26
29static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) 27static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) {
30{ 28 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)); 29 adc_inst* inst_cream = (adc_inst*)inst_base->component;
32 adc_inst *inst_cream = (adc_inst *)inst_base->component;
33 30
34 inst_base->cond = BITS(inst, 28, 31); 31 inst_base->cond = BITS(inst, 28, 31);
35 inst_base->idx = index; 32 inst_base->idx = index;
36 inst_base->br = TransExtData::NON_BRANCH; 33 inst_base->br = TransExtData::NON_BRANCH;
37 34
38 inst_cream->I = BIT(inst, 25); 35 inst_cream->I = BIT(inst, 25);
39 inst_cream->S = BIT(inst, 20); 36 inst_cream->S = BIT(inst, 20);
40 inst_cream->Rn = BITS(inst, 16, 19); 37 inst_cream->Rn = BITS(inst, 16, 19);
41 inst_cream->Rd = BITS(inst, 12, 15); 38 inst_cream->Rd = BITS(inst, 12, 15);
42 inst_cream->shifter_operand = BITS(inst, 0, 11); 39 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -47,17 +44,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index)
47 44
48 return inst_base; 45 return inst_base;
49} 46}
50static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) 47static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) {
51{ 48 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)); 49 add_inst* inst_cream = (add_inst*)inst_base->component;
53 add_inst *inst_cream = (add_inst *)inst_base->component;
54 50
55 inst_base->cond = BITS(inst, 28, 31); 51 inst_base->cond = BITS(inst, 28, 31);
56 inst_base->idx = index; 52 inst_base->idx = index;
57 inst_base->br = TransExtData::NON_BRANCH; 53 inst_base->br = TransExtData::NON_BRANCH;
58 54
59 inst_cream->I = BIT(inst, 25); 55 inst_cream->I = BIT(inst, 25);
60 inst_cream->S = BIT(inst, 20); 56 inst_cream->S = BIT(inst, 20);
61 inst_cream->Rn = BITS(inst, 16, 19); 57 inst_cream->Rn = BITS(inst, 16, 19);
62 inst_cream->Rd = BITS(inst, 12, 15); 58 inst_cream->Rd = BITS(inst, 12, 15);
63 inst_cream->shifter_operand = BITS(inst, 0, 11); 59 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -68,17 +64,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index)
68 64
69 return inst_base; 65 return inst_base;
70} 66}
71static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) 67static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) {
72{ 68 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)); 69 and_inst* inst_cream = (and_inst*)inst_base->component;
74 and_inst *inst_cream = (and_inst *)inst_base->component;
75 70
76 inst_base->cond = BITS(inst, 28, 31); 71 inst_base->cond = BITS(inst, 28, 31);
77 inst_base->idx = index; 72 inst_base->idx = index;
78 inst_base->br = TransExtData::NON_BRANCH; 73 inst_base->br = TransExtData::NON_BRANCH;
79 74
80 inst_cream->I = BIT(inst, 25); 75 inst_cream->I = BIT(inst, 25);
81 inst_cream->S = BIT(inst, 20); 76 inst_cream->S = BIT(inst, 20);
82 inst_cream->Rn = BITS(inst, 16, 19); 77 inst_cream->Rn = BITS(inst, 16, 19);
83 inst_cream->Rd = BITS(inst, 12, 15); 78 inst_cream->Rd = BITS(inst, 12, 15);
84 inst_cream->shifter_operand = BITS(inst, 0, 11); 79 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -89,37 +84,35 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index)
89 84
90 return inst_base; 85 return inst_base;
91} 86}
92static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index) 87static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index) {
93{ 88#define POSBRANCH ((inst & 0x7fffff) << 2)
94 #define POSBRANCH ((inst & 0x7fffff) << 2) 89#define NEGBRANCH ((0xff000000 | (inst & 0xffffff)) << 2)
95 #define NEGBRANCH ((0xff000000 |(inst & 0xffffff)) << 2)
96 90
97 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst)); 91 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst));
98 bbl_inst *inst_cream = (bbl_inst *)inst_base->component; 92 bbl_inst* inst_cream = (bbl_inst*)inst_base->component;
99 93
100 inst_base->cond = BITS(inst, 28, 31); 94 inst_base->cond = BITS(inst, 28, 31);
101 inst_base->idx = index; 95 inst_base->idx = index;
102 inst_base->br = TransExtData::DIRECT_BRANCH; 96 inst_base->br = TransExtData::DIRECT_BRANCH;
103 97
104 if (BIT(inst, 24)) 98 if (BIT(inst, 24))
105 inst_base->br = TransExtData::CALL; 99 inst_base->br = TransExtData::CALL;
106 100
107 inst_cream->L = BIT(inst, 24); 101 inst_cream->L = BIT(inst, 24);
108 inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH; 102 inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH;
109 103
110 return inst_base; 104 return inst_base;
111} 105}
112static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) 106static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) {
113{ 107 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)); 108 bic_inst* inst_cream = (bic_inst*)inst_base->component;
115 bic_inst *inst_cream = (bic_inst *)inst_base->component;
116 109
117 inst_base->cond = BITS(inst, 28, 31); 110 inst_base->cond = BITS(inst, 28, 31);
118 inst_base->idx = index; 111 inst_base->idx = index;
119 inst_base->br = TransExtData::NON_BRANCH; 112 inst_base->br = TransExtData::NON_BRANCH;
120 113
121 inst_cream->I = BIT(inst, 25); 114 inst_cream->I = BIT(inst, 25);
122 inst_cream->S = BIT(inst, 20); 115 inst_cream->S = BIT(inst, 20);
123 inst_cream->Rn = BITS(inst, 16, 19); 116 inst_cream->Rn = BITS(inst, 16, 19);
124 inst_cream->Rd = BITS(inst, 12, 15); 117 inst_cream->Rd = BITS(inst, 12, 15);
125 inst_cream->shifter_operand = BITS(inst, 0, 11); 118 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -130,28 +123,26 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index)
130 return inst_base; 123 return inst_base;
131} 124}
132 125
133static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) 126static 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)); 127 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; 128 bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
137 129
138 inst_base->cond = BITS(inst, 28, 31); 130 inst_base->cond = BITS(inst, 28, 31);
139 inst_base->idx = index; 131 inst_base->idx = index;
140 inst_base->br = TransExtData::NON_BRANCH; 132 inst_base->br = TransExtData::NON_BRANCH;
141 133
142 inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3); 134 inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3);
143 135
144 return inst_base; 136 return inst_base;
145} 137}
146 138
147static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) 139static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) {
148{ 140 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)); 141 blx_inst* inst_cream = (blx_inst*)inst_base->component;
150 blx_inst *inst_cream = (blx_inst *)inst_base->component;
151 142
152 inst_base->cond = BITS(inst, 28, 31); 143 inst_base->cond = BITS(inst, 28, 31);
153 inst_base->idx = index; 144 inst_base->idx = index;
154 inst_base->br = TransExtData::INDIRECT_BRANCH; 145 inst_base->br = TransExtData::INDIRECT_BRANCH;
155 146
156 inst_cream->inst = inst; 147 inst_cream->inst = inst;
157 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { 148 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
@@ -162,36 +153,34 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index)
162 153
163 return inst_base; 154 return inst_base;
164} 155}
165static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) 156static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) {
166{ 157 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)); 158 bx_inst* inst_cream = (bx_inst*)inst_base->component;
168 bx_inst *inst_cream = (bx_inst *)inst_base->component;
169 159
170 inst_base->cond = BITS(inst, 28, 31); 160 inst_base->cond = BITS(inst, 28, 31);
171 inst_base->idx = index; 161 inst_base->idx = index;
172 inst_base->br = TransExtData::INDIRECT_BRANCH; 162 inst_base->br = TransExtData::INDIRECT_BRANCH;
173 163
174 inst_cream->Rm = BITS(inst, 0, 3); 164 inst_cream->Rm = BITS(inst, 0, 3);
175 165
176 return inst_base; 166 return inst_base;
177} 167}
178static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) 168static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) {
179{
180 return INTERPRETER_TRANSLATE(bx)(inst, index); 169 return INTERPRETER_TRANSLATE(bx)(inst, index);
181} 170}
182 171
183static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) { 172static 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)); 173 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst));
185 cdp_inst *inst_cream = (cdp_inst *)inst_base->component; 174 cdp_inst* inst_cream = (cdp_inst*)inst_base->component;
186 175
187 inst_base->cond = BITS(inst, 28, 31); 176 inst_base->cond = BITS(inst, 28, 31);
188 inst_base->idx = index; 177 inst_base->idx = index;
189 inst_base->br = TransExtData::NON_BRANCH; 178 inst_base->br = TransExtData::NON_BRANCH;
190 179
191 inst_cream->CRm = BITS(inst, 0, 3); 180 inst_cream->CRm = BITS(inst, 0, 3);
192 inst_cream->CRd = BITS(inst, 12, 15); 181 inst_cream->CRd = BITS(inst, 12, 15);
193 inst_cream->CRn = BITS(inst, 16, 19); 182 inst_cream->CRn = BITS(inst, 16, 19);
194 inst_cream->cp_num = BITS(inst, 8, 11); 183 inst_cream->cp_num = BITS(inst, 8, 11);
195 inst_cream->opcode_2 = BITS(inst, 5, 7); 184 inst_cream->opcode_2 = BITS(inst, 5, 7);
196 inst_cream->opcode_1 = BITS(inst, 20, 23); 185 inst_cream->opcode_1 = BITS(inst, 20, 23);
197 inst_cream->inst = inst; 186 inst_cream->inst = inst;
@@ -199,91 +188,85 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) {
199 LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index); 188 LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index);
200 return inst_base; 189 return inst_base;
201} 190}
202static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index) 191static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index) {
203{ 192 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); 193 inst_base->cond = BITS(inst, 28, 31);
206 inst_base->idx = index; 194 inst_base->idx = index;
207 inst_base->br = TransExtData::NON_BRANCH; 195 inst_base->br = TransExtData::NON_BRANCH;
208 196
209 return inst_base; 197 return inst_base;
210} 198}
211static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index) 199static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index) {
212{ 200 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)); 201 clz_inst* inst_cream = (clz_inst*)inst_base->component;
214 clz_inst *inst_cream = (clz_inst *)inst_base->component;
215 202
216 inst_base->cond = BITS(inst, 28, 31); 203 inst_base->cond = BITS(inst, 28, 31);
217 inst_base->idx = index; 204 inst_base->idx = index;
218 inst_base->br = TransExtData::NON_BRANCH; 205 inst_base->br = TransExtData::NON_BRANCH;
219 206
220 inst_cream->Rm = BITS(inst, 0, 3); 207 inst_cream->Rm = BITS(inst, 0, 3);
221 inst_cream->Rd = BITS(inst, 12, 15); 208 inst_cream->Rd = BITS(inst, 12, 15);
222 209
223 return inst_base; 210 return inst_base;
224} 211}
225static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) 212static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) {
226{ 213 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)); 214 cmn_inst* inst_cream = (cmn_inst*)inst_base->component;
228 cmn_inst *inst_cream = (cmn_inst *)inst_base->component;
229 215
230 inst_base->cond = BITS(inst, 28, 31); 216 inst_base->cond = BITS(inst, 28, 31);
231 inst_base->idx = index; 217 inst_base->idx = index;
232 inst_base->br = TransExtData::NON_BRANCH; 218 inst_base->br = TransExtData::NON_BRANCH;
233 219
234 inst_cream->I = BIT(inst, 25); 220 inst_cream->I = BIT(inst, 25);
235 inst_cream->Rn = BITS(inst, 16, 19); 221 inst_cream->Rn = BITS(inst, 16, 19);
236 inst_cream->shifter_operand = BITS(inst, 0, 11); 222 inst_cream->shifter_operand = BITS(inst, 0, 11);
237 inst_cream->shtop_func = GetShifterOp(inst); 223 inst_cream->shtop_func = GetShifterOp(inst);
238 224
239 return inst_base; 225 return inst_base;
240} 226}
241static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) 227static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) {
242{ 228 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)); 229 cmp_inst* inst_cream = (cmp_inst*)inst_base->component;
244 cmp_inst *inst_cream = (cmp_inst *)inst_base->component;
245 230
246 inst_base->cond = BITS(inst, 28, 31); 231 inst_base->cond = BITS(inst, 28, 31);
247 inst_base->idx = index; 232 inst_base->idx = index;
248 inst_base->br = TransExtData::NON_BRANCH; 233 inst_base->br = TransExtData::NON_BRANCH;
249 234
250 inst_cream->I = BIT(inst, 25); 235 inst_cream->I = BIT(inst, 25);
251 inst_cream->Rn = BITS(inst, 16, 19); 236 inst_cream->Rn = BITS(inst, 16, 19);
252 inst_cream->shifter_operand = BITS(inst, 0, 11); 237 inst_cream->shifter_operand = BITS(inst, 0, 11);
253 inst_cream->shtop_func = GetShifterOp(inst); 238 inst_cream->shtop_func = GetShifterOp(inst);
254 239
255 return inst_base; 240 return inst_base;
256} 241}
257static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index) 242static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index) {
258{ 243 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)); 244 cps_inst* inst_cream = (cps_inst*)inst_base->component;
260 cps_inst *inst_cream = (cps_inst *)inst_base->component;
261 245
262 inst_base->cond = BITS(inst, 28, 31); 246 inst_base->cond = BITS(inst, 28, 31);
263 inst_base->idx = index; 247 inst_base->idx = index;
264 inst_base->br = TransExtData::NON_BRANCH; 248 inst_base->br = TransExtData::NON_BRANCH;
265 249
266 inst_cream->imod0 = BIT(inst, 18); 250 inst_cream->imod0 = BIT(inst, 18);
267 inst_cream->imod1 = BIT(inst, 19); 251 inst_cream->imod1 = BIT(inst, 19);
268 inst_cream->mmod = BIT(inst, 17); 252 inst_cream->mmod = BIT(inst, 17);
269 inst_cream->A = BIT(inst, 8); 253 inst_cream->A = BIT(inst, 8);
270 inst_cream->I = BIT(inst, 7); 254 inst_cream->I = BIT(inst, 7);
271 inst_cream->F = BIT(inst, 6); 255 inst_cream->F = BIT(inst, 6);
272 inst_cream->mode = BITS(inst, 0, 4); 256 inst_cream->mode = BITS(inst, 0, 4);
273 257
274 return inst_base; 258 return inst_base;
275} 259}
276static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) 260static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) {
277{ 261 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)); 262 mov_inst* inst_cream = (mov_inst*)inst_base->component;
279 mov_inst *inst_cream = (mov_inst *)inst_base->component;
280 263
281 inst_base->cond = BITS(inst, 28, 31); 264 inst_base->cond = BITS(inst, 28, 31);
282 inst_base->idx = index; 265 inst_base->idx = index;
283 inst_base->br = TransExtData::NON_BRANCH; 266 inst_base->br = TransExtData::NON_BRANCH;
284 267
285 inst_cream->I = BIT(inst, 25); 268 inst_cream->I = BIT(inst, 25);
286 inst_cream->S = BIT(inst, 20); 269 inst_cream->S = BIT(inst, 20);
287 inst_cream->Rd = BITS(inst, 12, 15); 270 inst_cream->Rd = BITS(inst, 12, 15);
288 inst_cream->shifter_operand = BITS(inst, 0, 11); 271 inst_cream->shifter_operand = BITS(inst, 0, 11);
289 inst_cream->shtop_func = GetShifterOp(inst); 272 inst_cream->shtop_func = GetShifterOp(inst);
@@ -293,17 +276,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index)
293 } 276 }
294 return inst_base; 277 return inst_base;
295} 278}
296static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) 279static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) {
297{ 280 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)); 281 eor_inst* inst_cream = (eor_inst*)inst_base->component;
299 eor_inst *inst_cream = (eor_inst *)inst_base->component;
300 282
301 inst_base->cond = BITS(inst, 28, 31); 283 inst_base->cond = BITS(inst, 28, 31);
302 inst_base->idx = index; 284 inst_base->idx = index;
303 inst_base->br = TransExtData::NON_BRANCH; 285 inst_base->br = TransExtData::NON_BRANCH;
304 286
305 inst_cream->I = BIT(inst, 25); 287 inst_cream->I = BIT(inst, 25);
306 inst_cream->S = BIT(inst, 20); 288 inst_cream->S = BIT(inst, 20);
307 inst_cream->Rn = BITS(inst, 16, 19); 289 inst_cream->Rn = BITS(inst, 16, 19);
308 inst_cream->Rd = BITS(inst, 12, 15); 290 inst_cream->Rd = BITS(inst, 12, 15);
309 inst_cream->shifter_operand = BITS(inst, 0, 11); 291 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -314,23 +296,21 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index)
314 296
315 return inst_base; 297 return inst_base;
316} 298}
317static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index) 299static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index) {
318{ 300 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); 301 inst_base->cond = BITS(inst, 28, 31);
321 inst_base->idx = index; 302 inst_base->idx = index;
322 inst_base->br = TransExtData::NON_BRANCH; 303 inst_base->br = TransExtData::NON_BRANCH;
323 304
324 return inst_base; 305 return inst_base;
325} 306}
326static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) 307static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) {
327{ 308 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)); 309 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
329 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
330 310
331 inst_base->cond = BITS(inst, 28, 31); 311 inst_base->cond = BITS(inst, 28, 31);
332 inst_base->idx = index; 312 inst_base->idx = index;
333 inst_base->br = TransExtData::NON_BRANCH; 313 inst_base->br = TransExtData::NON_BRANCH;
334 314
335 inst_cream->inst = inst; 315 inst_cream->inst = inst;
336 inst_cream->get_addr = GetAddressingOp(inst); 316 inst_cream->get_addr = GetAddressingOp(inst);
@@ -340,29 +320,27 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index)
340 } 320 }
341 return inst_base; 321 return inst_base;
342} 322}
343static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index) 323static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index) {
344{ 324 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)); 325 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component;
346 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
347 326
348 inst_base->cond = BITS(inst, 28, 31); 327 inst_base->cond = BITS(inst, 28, 31);
349 inst_base->idx = index; 328 inst_base->idx = index;
350 inst_base->br = TransExtData::NON_BRANCH; 329 inst_base->br = TransExtData::NON_BRANCH;
351 330
352 inst_cream->Rd = BITS(inst, 12, 15); 331 inst_cream->Rd = BITS(inst, 12, 15);
353 inst_cream->Rm = BITS(inst, 0, 3); 332 inst_cream->Rm = BITS(inst, 0, 3);
354 inst_cream->rotate = BITS(inst, 10, 11); 333 inst_cream->rotate = BITS(inst, 10, 11);
355 334
356 return inst_base; 335 return inst_base;
357} 336}
358static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) 337static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) {
359{ 338 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)); 339 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
361 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
362 340
363 inst_base->cond = BITS(inst, 28, 31); 341 inst_base->cond = BITS(inst, 28, 31);
364 inst_base->idx = index; 342 inst_base->idx = index;
365 inst_base->br = TransExtData::NON_BRANCH; 343 inst_base->br = TransExtData::NON_BRANCH;
366 344
367 inst_cream->inst = inst; 345 inst_cream->inst = inst;
368 inst_cream->get_addr = GetAddressingOp(inst); 346 inst_cream->get_addr = GetAddressingOp(inst);
@@ -373,14 +351,13 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index)
373 return inst_base; 351 return inst_base;
374} 352}
375 353
376static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) 354static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) {
377{ 355 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)); 356 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
379 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
380 357
381 inst_base->cond = BITS(inst, 28, 31); 358 inst_base->cond = BITS(inst, 28, 31);
382 inst_base->idx = index; 359 inst_base->idx = index;
383 inst_base->br = TransExtData::NON_BRANCH; 360 inst_base->br = TransExtData::NON_BRANCH;
384 361
385 inst_cream->inst = inst; 362 inst_cream->inst = inst;
386 inst_cream->get_addr = GetAddressingOp(inst); 363 inst_cream->get_addr = GetAddressingOp(inst);
@@ -391,155 +368,143 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index)
391 return inst_base; 368 return inst_base;
392} 369}
393 370
394static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index) 371static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index) {
395{ 372 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)); 373 uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
397 uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
398 374
399 inst_base->cond = BITS(inst, 28, 31); 375 inst_base->cond = BITS(inst, 28, 31);
400 inst_base->idx = index; 376 inst_base->idx = index;
401 inst_base->br = TransExtData::NON_BRANCH; 377 inst_base->br = TransExtData::NON_BRANCH;
402 378
403 inst_cream->Rd = BITS(inst, 12, 15); 379 inst_cream->Rd = BITS(inst, 12, 15);
404 inst_cream->rotate = BITS(inst, 10, 11); 380 inst_cream->rotate = BITS(inst, 10, 11);
405 inst_cream->Rm = BITS(inst, 0, 3); 381 inst_cream->Rm = BITS(inst, 0, 3);
406 382
407 return inst_base; 383 return inst_base;
408} 384}
409static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index) 385static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index) {
410{ 386 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)); 387 uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component;
412 uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component;
413 388
414 inst_base->cond = BITS(inst, 28, 31); 389 inst_base->cond = BITS(inst, 28, 31);
415 inst_base->idx = index; 390 inst_base->idx = index;
416 inst_base->br = TransExtData::NON_BRANCH; 391 inst_base->br = TransExtData::NON_BRANCH;
417 392
418 inst_cream->Rn = BITS(inst, 16, 19); 393 inst_cream->Rn = BITS(inst, 16, 19);
419 inst_cream->Rd = BITS(inst, 12, 15); 394 inst_cream->Rd = BITS(inst, 12, 15);
420 inst_cream->rotate = BITS(inst, 10, 11); 395 inst_cream->rotate = BITS(inst, 10, 11);
421 inst_cream->Rm = BITS(inst, 0, 3); 396 inst_cream->Rm = BITS(inst, 0, 3);
422 397
423 return inst_base; 398 return inst_base;
424} 399}
425static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) 400static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) {
426{ 401 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)); 402 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
428 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
429 403
430 inst_base->cond = BITS(inst, 28, 31); 404 inst_base->cond = BITS(inst, 28, 31);
431 inst_base->idx = index; 405 inst_base->idx = index;
432 inst_base->br = TransExtData::NON_BRANCH; 406 inst_base->br = TransExtData::NON_BRANCH;
433 407
434 inst_cream->inst = inst; 408 inst_cream->inst = inst;
435 inst_cream->get_addr = GetAddressingOp(inst); 409 inst_cream->get_addr = GetAddressingOp(inst);
436 410
437 return inst_base; 411 return inst_base;
438} 412}
439static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) 413static 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)); 414 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
442 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 415 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
443 416
444 inst_base->cond = BITS(inst, 28, 31); 417 inst_base->cond = BITS(inst, 28, 31);
445 inst_base->idx = index; 418 inst_base->idx = index;
446 inst_base->br = TransExtData::NON_BRANCH; 419 inst_base->br = TransExtData::NON_BRANCH;
447 420
448 inst_cream->inst = inst; 421 inst_cream->inst = inst;
449 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); 422 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
450 423
451 return inst_base; 424 return inst_base;
452} 425}
453static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) 426static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) {
454{ 427 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)); 428 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
456 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
457 429
458 inst_base->cond = BITS(inst, 28, 31); 430 inst_base->cond = BITS(inst, 28, 31);
459 inst_base->idx = index; 431 inst_base->idx = index;
460 inst_base->br = TransExtData::NON_BRANCH; 432 inst_base->br = TransExtData::NON_BRANCH;
461 433
462 inst_cream->inst = inst; 434 inst_cream->inst = inst;
463 inst_cream->get_addr = GetAddressingOp(inst); 435 inst_cream->get_addr = GetAddressingOp(inst);
464 436
465 return inst_base; 437 return inst_base;
466} 438}
467static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) 439static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) {
468{ 440 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)); 441 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
470 generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component;
471 442
472 inst_base->cond = BITS(inst, 28, 31); 443 inst_base->cond = BITS(inst, 28, 31);
473 inst_base->idx = index; 444 inst_base->idx = index;
474 inst_base->br = (BITS(inst, 12, 15) == 15) ? TransExtData::INDIRECT_BRANCH : TransExtData::NON_BRANCH; // Branch if dest is R15 445 inst_base->br = (BITS(inst, 12, 15) == 15) ? TransExtData::INDIRECT_BRANCH
446 : TransExtData::NON_BRANCH; // Branch if dest is R15
475 447
476 inst_cream->Rn = BITS(inst, 16, 19); 448 inst_cream->Rn = BITS(inst, 16, 19);
477 inst_cream->Rd = BITS(inst, 12, 15); 449 inst_cream->Rd = BITS(inst, 12, 15);
478 450
479 return inst_base; 451 return inst_base;
480} 452}
481static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) 453static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) {
482{
483 return INTERPRETER_TRANSLATE(ldrex)(inst, index); 454 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
484} 455}
485static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index) 456static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index) {
486{
487 return INTERPRETER_TRANSLATE(ldrex)(inst, index); 457 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
488} 458}
489static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index) 459static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index) {
490{
491 return INTERPRETER_TRANSLATE(ldrex)(inst, index); 460 return INTERPRETER_TRANSLATE(ldrex)(inst, index);
492} 461}
493static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) 462static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) {
494{ 463 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)); 464 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
496 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
497 465
498 inst_base->cond = BITS(inst, 28, 31); 466 inst_base->cond = BITS(inst, 28, 31);
499 inst_base->idx = index; 467 inst_base->idx = index;
500 inst_base->br = TransExtData::NON_BRANCH; 468 inst_base->br = TransExtData::NON_BRANCH;
501 469
502 inst_cream->inst = inst; 470 inst_cream->inst = inst;
503 inst_cream->get_addr = GetAddressingOp(inst); 471 inst_cream->get_addr = GetAddressingOp(inst);
504 472
505 return inst_base; 473 return inst_base;
506} 474}
507static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) 475static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) {
508{ 476 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)); 477 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
510 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
511 478
512 inst_base->cond = BITS(inst, 28, 31); 479 inst_base->cond = BITS(inst, 28, 31);
513 inst_base->idx = index; 480 inst_base->idx = index;
514 inst_base->br = TransExtData::NON_BRANCH; 481 inst_base->br = TransExtData::NON_BRANCH;
515 482
516 inst_cream->inst = inst; 483 inst_cream->inst = inst;
517 inst_cream->get_addr = GetAddressingOp(inst); 484 inst_cream->get_addr = GetAddressingOp(inst);
518 485
519 return inst_base; 486 return inst_base;
520} 487}
521static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) 488static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) {
522{ 489 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)); 490 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
524 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
525 491
526 inst_base->cond = BITS(inst, 28, 31); 492 inst_base->cond = BITS(inst, 28, 31);
527 inst_base->idx = index; 493 inst_base->idx = index;
528 inst_base->br = TransExtData::NON_BRANCH; 494 inst_base->br = TransExtData::NON_BRANCH;
529 495
530 inst_cream->inst = inst; 496 inst_cream->inst = inst;
531 inst_cream->get_addr = GetAddressingOp(inst); 497 inst_cream->get_addr = GetAddressingOp(inst);
532 498
533 return inst_base; 499 return inst_base;
534} 500}
535static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) 501static 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)); 502 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
538 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 503 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
539 504
540 inst_base->cond = BITS(inst, 28, 31); 505 inst_base->cond = BITS(inst, 28, 31);
541 inst_base->idx = index; 506 inst_base->idx = index;
542 inst_base->br = TransExtData::NON_BRANCH; 507 inst_base->br = TransExtData::NON_BRANCH;
543 508
544 inst_cream->inst = inst; 509 inst_cream->inst = inst;
545 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); 510 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
@@ -549,70 +514,66 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index)
549 } 514 }
550 return inst_base; 515 return inst_base;
551} 516}
552static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) 517static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) {
553{ 518 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)); 519 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); 520 inst_base->cond = BITS(inst, 28, 31);
557 inst_base->idx = index; 521 inst_base->idx = index;
558 inst_base->br = TransExtData::NON_BRANCH; 522 inst_base->br = TransExtData::NON_BRANCH;
559 523
560 inst_cream->crn = BITS(inst, 16, 19); 524 inst_cream->crn = BITS(inst, 16, 19);
561 inst_cream->crm = BITS(inst, 0, 3); 525 inst_cream->crm = BITS(inst, 0, 3);
562 inst_cream->opcode_1 = BITS(inst, 21, 23); 526 inst_cream->opcode_1 = BITS(inst, 21, 23);
563 inst_cream->opcode_2 = BITS(inst, 5, 7); 527 inst_cream->opcode_2 = BITS(inst, 5, 7);
564 inst_cream->Rd = BITS(inst, 12, 15); 528 inst_cream->Rd = BITS(inst, 12, 15);
565 inst_cream->cp_num = BITS(inst, 8, 11); 529 inst_cream->cp_num = BITS(inst, 8, 11);
566 inst_cream->inst = inst; 530 inst_cream->inst = inst;
567 return inst_base; 531 return inst_base;
568} 532}
569 533
570static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) 534static 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)); 535 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; 536 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
574 537
575 inst_base->cond = BITS(inst, 28, 31); 538 inst_base->cond = BITS(inst, 28, 31);
576 inst_base->idx = index; 539 inst_base->idx = index;
577 inst_base->br = TransExtData::NON_BRANCH; 540 inst_base->br = TransExtData::NON_BRANCH;
578 541
579 inst_cream->crm = BITS(inst, 0, 3); 542 inst_cream->crm = BITS(inst, 0, 3);
580 inst_cream->opcode_1 = BITS(inst, 4, 7); 543 inst_cream->opcode_1 = BITS(inst, 4, 7);
581 inst_cream->cp_num = BITS(inst, 8, 11); 544 inst_cream->cp_num = BITS(inst, 8, 11);
582 inst_cream->rt = BITS(inst, 12, 15); 545 inst_cream->rt = BITS(inst, 12, 15);
583 inst_cream->rt2 = BITS(inst, 16, 19); 546 inst_cream->rt2 = BITS(inst, 16, 19);
584 547
585 return inst_base; 548 return inst_base;
586} 549}
587 550
588static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) 551static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) {
589{ 552 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)); 553 mla_inst* inst_cream = (mla_inst*)inst_base->component;
591 mla_inst *inst_cream = (mla_inst *)inst_base->component;
592 554
593 inst_base->cond = BITS(inst, 28, 31); 555 inst_base->cond = BITS(inst, 28, 31);
594 inst_base->idx = index; 556 inst_base->idx = index;
595 inst_base->br = TransExtData::NON_BRANCH; 557 inst_base->br = TransExtData::NON_BRANCH;
596 558
597 inst_cream->S = BIT(inst, 20); 559 inst_cream->S = BIT(inst, 20);
598 inst_cream->Rn = BITS(inst, 12, 15); 560 inst_cream->Rn = BITS(inst, 12, 15);
599 inst_cream->Rd = BITS(inst, 16, 19); 561 inst_cream->Rd = BITS(inst, 16, 19);
600 inst_cream->Rs = BITS(inst, 8, 11); 562 inst_cream->Rs = BITS(inst, 8, 11);
601 inst_cream->Rm = BITS(inst, 0, 3); 563 inst_cream->Rm = BITS(inst, 0, 3);
602 564
603 return inst_base; 565 return inst_base;
604} 566}
605static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) 567static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) {
606{ 568 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)); 569 mov_inst* inst_cream = (mov_inst*)inst_base->component;
608 mov_inst *inst_cream = (mov_inst *)inst_base->component;
609 570
610 inst_base->cond = BITS(inst, 28, 31); 571 inst_base->cond = BITS(inst, 28, 31);
611 inst_base->idx = index; 572 inst_base->idx = index;
612 inst_base->br = TransExtData::NON_BRANCH; 573 inst_base->br = TransExtData::NON_BRANCH;
613 574
614 inst_cream->I = BIT(inst, 25); 575 inst_cream->I = BIT(inst, 25);
615 inst_cream->S = BIT(inst, 20); 576 inst_cream->S = BIT(inst, 20);
616 inst_cream->Rd = BITS(inst, 12, 15); 577 inst_cream->Rd = BITS(inst, 12, 15);
617 inst_cream->shifter_operand = BITS(inst, 0, 11); 578 inst_cream->shifter_operand = BITS(inst, 0, 11);
618 inst_cream->shtop_func = GetShifterOp(inst); 579 inst_cream->shtop_func = GetShifterOp(inst);
@@ -622,85 +583,79 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index)
622 } 583 }
623 return inst_base; 584 return inst_base;
624} 585}
625static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) 586static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) {
626{ 587 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)); 588 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); 589 inst_base->cond = BITS(inst, 28, 31);
630 inst_base->idx = index; 590 inst_base->idx = index;
631 inst_base->br = TransExtData::NON_BRANCH; 591 inst_base->br = TransExtData::NON_BRANCH;
632 592
633 inst_cream->crn = BITS(inst, 16, 19); 593 inst_cream->crn = BITS(inst, 16, 19);
634 inst_cream->crm = BITS(inst, 0, 3); 594 inst_cream->crm = BITS(inst, 0, 3);
635 inst_cream->opcode_1 = BITS(inst, 21, 23); 595 inst_cream->opcode_1 = BITS(inst, 21, 23);
636 inst_cream->opcode_2 = BITS(inst, 5, 7); 596 inst_cream->opcode_2 = BITS(inst, 5, 7);
637 inst_cream->Rd = BITS(inst, 12, 15); 597 inst_cream->Rd = BITS(inst, 12, 15);
638 inst_cream->cp_num = BITS(inst, 8, 11); 598 inst_cream->cp_num = BITS(inst, 8, 11);
639 inst_cream->inst = inst; 599 inst_cream->inst = inst;
640 return inst_base; 600 return inst_base;
641} 601}
642 602
643static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) 603static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) {
644{
645 return INTERPRETER_TRANSLATE(mcrr)(inst, index); 604 return INTERPRETER_TRANSLATE(mcrr)(inst, index);
646} 605}
647 606
648static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) 607static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) {
649{ 608 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)); 609 mrs_inst* inst_cream = (mrs_inst*)inst_base->component;
651 mrs_inst *inst_cream = (mrs_inst *)inst_base->component;
652 610
653 inst_base->cond = BITS(inst, 28, 31); 611 inst_base->cond = BITS(inst, 28, 31);
654 inst_base->idx = index; 612 inst_base->idx = index;
655 inst_base->br = TransExtData::NON_BRANCH; 613 inst_base->br = TransExtData::NON_BRANCH;
656 614
657 inst_cream->Rd = BITS(inst, 12, 15); 615 inst_cream->Rd = BITS(inst, 12, 15);
658 inst_cream->R = BIT(inst, 22); 616 inst_cream->R = BIT(inst, 22);
659 617
660 return inst_base; 618 return inst_base;
661} 619}
662static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index) 620static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index) {
663{ 621 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)); 622 msr_inst* inst_cream = (msr_inst*)inst_base->component;
665 msr_inst *inst_cream = (msr_inst *)inst_base->component;
666 623
667 inst_base->cond = BITS(inst, 28, 31); 624 inst_base->cond = BITS(inst, 28, 31);
668 inst_base->idx = index; 625 inst_base->idx = index;
669 inst_base->br = TransExtData::NON_BRANCH; 626 inst_base->br = TransExtData::NON_BRANCH;
670 627
671 inst_cream->field_mask = BITS(inst, 16, 19); 628 inst_cream->field_mask = BITS(inst, 16, 19);
672 inst_cream->R = BIT(inst, 22); 629 inst_cream->R = BIT(inst, 22);
673 inst_cream->inst = inst; 630 inst_cream->inst = inst;
674 631
675 return inst_base; 632 return inst_base;
676} 633}
677static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index) 634static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index) {
678{ 635 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)); 636 mul_inst* inst_cream = (mul_inst*)inst_base->component;
680 mul_inst *inst_cream = (mul_inst *)inst_base->component;
681 637
682 inst_base->cond = BITS(inst, 28, 31); 638 inst_base->cond = BITS(inst, 28, 31);
683 inst_base->idx = index; 639 inst_base->idx = index;
684 inst_base->br = TransExtData::NON_BRANCH; 640 inst_base->br = TransExtData::NON_BRANCH;
685 641
686 inst_cream->S = BIT(inst, 20); 642 inst_cream->S = BIT(inst, 20);
687 inst_cream->Rm = BITS(inst, 0, 3); 643 inst_cream->Rm = BITS(inst, 0, 3);
688 inst_cream->Rs = BITS(inst, 8, 11); 644 inst_cream->Rs = BITS(inst, 8, 11);
689 inst_cream->Rd = BITS(inst, 16, 19); 645 inst_cream->Rd = BITS(inst, 16, 19);
690 646
691 return inst_base; 647 return inst_base;
692} 648}
693static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) 649static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) {
694{ 650 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)); 651 mvn_inst* inst_cream = (mvn_inst*)inst_base->component;
696 mvn_inst *inst_cream = (mvn_inst *)inst_base->component;
697 652
698 inst_base->cond = BITS(inst, 28, 31); 653 inst_base->cond = BITS(inst, 28, 31);
699 inst_base->idx = index; 654 inst_base->idx = index;
700 inst_base->br = TransExtData::NON_BRANCH; 655 inst_base->br = TransExtData::NON_BRANCH;
701 656
702 inst_cream->I = BIT(inst, 25); 657 inst_cream->I = BIT(inst, 25);
703 inst_cream->S = BIT(inst, 20); 658 inst_cream->S = BIT(inst, 20);
704 inst_cream->Rd = BITS(inst, 12, 15); 659 inst_cream->Rd = BITS(inst, 12, 15);
705 inst_cream->shifter_operand = BITS(inst, 0, 11); 660 inst_cream->shifter_operand = BITS(inst, 0, 11);
706 inst_cream->shtop_func = GetShifterOp(inst); 661 inst_cream->shtop_func = GetShifterOp(inst);
@@ -709,19 +664,17 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index)
709 inst_base->br = TransExtData::INDIRECT_BRANCH; 664 inst_base->br = TransExtData::INDIRECT_BRANCH;
710 } 665 }
711 return inst_base; 666 return inst_base;
712
713} 667}
714static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) 668static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) {
715{ 669 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)); 670 orr_inst* inst_cream = (orr_inst*)inst_base->component;
717 orr_inst *inst_cream = (orr_inst *)inst_base->component;
718 671
719 inst_base->cond = BITS(inst, 28, 31); 672 inst_base->cond = BITS(inst, 28, 31);
720 inst_base->idx = index; 673 inst_base->idx = index;
721 inst_base->br = TransExtData::NON_BRANCH; 674 inst_base->br = TransExtData::NON_BRANCH;
722 675
723 inst_cream->I = BIT(inst, 25); 676 inst_cream->I = BIT(inst, 25);
724 inst_cream->S = BIT(inst, 20); 677 inst_cream->S = BIT(inst, 20);
725 inst_cream->Rd = BITS(inst, 12, 15); 678 inst_cream->Rd = BITS(inst, 12, 15);
726 inst_cream->Rn = BITS(inst, 16, 19); 679 inst_cream->Rn = BITS(inst, 16, 19);
727 inst_cream->shifter_operand = BITS(inst, 0, 11); 680 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -734,150 +687,132 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index)
734} 687}
735 688
736// NOP introduced in ARMv6K. 689// NOP introduced in ARMv6K.
737static ARM_INST_PTR INTERPRETER_TRANSLATE(nop)(unsigned int inst, int index) 690static ARM_INST_PTR INTERPRETER_TRANSLATE(nop)(unsigned int inst, int index) {
738{
739 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); 691 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
740 692
741 inst_base->cond = BITS(inst, 28, 31); 693 inst_base->cond = BITS(inst, 28, 31);
742 inst_base->idx = index; 694 inst_base->idx = index;
743 inst_base->br = TransExtData::NON_BRANCH; 695 inst_base->br = TransExtData::NON_BRANCH;
744 696
745 return inst_base; 697 return inst_base;
746} 698}
747 699
748static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) 700static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) {
749{ 701 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)); 702 pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
751 pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
752 703
753 inst_base->cond = BITS(inst, 28, 31); 704 inst_base->cond = BITS(inst, 28, 31);
754 inst_base->idx = index; 705 inst_base->idx = index;
755 inst_base->br = TransExtData::NON_BRANCH; 706 inst_base->br = TransExtData::NON_BRANCH;
756 707
757 inst_cream->Rd = BITS(inst, 12, 15); 708 inst_cream->Rd = BITS(inst, 12, 15);
758 inst_cream->Rn = BITS(inst, 16, 19); 709 inst_cream->Rn = BITS(inst, 16, 19);
759 inst_cream->Rm = BITS(inst, 0, 3); 710 inst_cream->Rm = BITS(inst, 0, 3);
760 inst_cream->imm = BITS(inst, 7, 11); 711 inst_cream->imm = BITS(inst, 7, 11);
761 712
762 return inst_base; 713 return inst_base;
763} 714}
764 715
765static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) 716static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) {
766{
767 return INTERPRETER_TRANSLATE(pkhbt)(inst, index); 717 return INTERPRETER_TRANSLATE(pkhbt)(inst, index);
768} 718}
769 719
770static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) 720static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) {
771{ 721 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 722
774 inst_base->cond = BITS(inst, 28, 31); 723 inst_base->cond = BITS(inst, 28, 31);
775 inst_base->idx = index; 724 inst_base->idx = index;
776 inst_base->br = TransExtData::NON_BRANCH; 725 inst_base->br = TransExtData::NON_BRANCH;
777 726
778 return inst_base; 727 return inst_base;
779} 728}
780 729
781static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) 730static 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)); 731 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; 732 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
785 733
786 inst_base->cond = BITS(inst, 28, 31); 734 inst_base->cond = BITS(inst, 28, 31);
787 inst_base->idx = index; 735 inst_base->idx = index;
788 inst_base->br = TransExtData::NON_BRANCH; 736 inst_base->br = TransExtData::NON_BRANCH;
789 737
790 inst_cream->op1 = BITS(inst, 21, 22); 738 inst_cream->op1 = BITS(inst, 21, 22);
791 inst_cream->Rm = BITS(inst, 0, 3); 739 inst_cream->Rm = BITS(inst, 0, 3);
792 inst_cream->Rn = BITS(inst, 16, 19); 740 inst_cream->Rn = BITS(inst, 16, 19);
793 inst_cream->Rd = BITS(inst, 12, 15); 741 inst_cream->Rd = BITS(inst, 12, 15);
794 742
795 return inst_base; 743 return inst_base;
796} 744}
797static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) 745static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) {
798{
799 return INTERPRETER_TRANSLATE(qadd)(inst, index); 746 return INTERPRETER_TRANSLATE(qadd)(inst, index);
800} 747}
801static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) 748static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) {
802{
803 return INTERPRETER_TRANSLATE(qadd)(inst, index); 749 return INTERPRETER_TRANSLATE(qadd)(inst, index);
804} 750}
805static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) 751static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) {
806{
807 return INTERPRETER_TRANSLATE(qadd)(inst, index); 752 return INTERPRETER_TRANSLATE(qadd)(inst, index);
808} 753}
809 754
810static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) 755static 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)); 756 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; 757 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
814 758
815 inst_base->cond = BITS(inst, 28, 31); 759 inst_base->cond = BITS(inst, 28, 31);
816 inst_base->idx = index; 760 inst_base->idx = index;
817 inst_base->br = TransExtData::NON_BRANCH; 761 inst_base->br = TransExtData::NON_BRANCH;
818 762
819 inst_cream->Rm = BITS(inst, 0, 3); 763 inst_cream->Rm = BITS(inst, 0, 3);
820 inst_cream->Rn = BITS(inst, 16, 19); 764 inst_cream->Rn = BITS(inst, 16, 19);
821 inst_cream->Rd = BITS(inst, 12, 15); 765 inst_cream->Rd = BITS(inst, 12, 15);
822 inst_cream->op1 = BITS(inst, 20, 21); 766 inst_cream->op1 = BITS(inst, 20, 21);
823 inst_cream->op2 = BITS(inst, 5, 7); 767 inst_cream->op2 = BITS(inst, 5, 7);
824 768
825 return inst_base; 769 return inst_base;
826} 770}
827static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) 771static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) {
828{
829 return INTERPRETER_TRANSLATE(qadd8)(inst, index); 772 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
830} 773}
831static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) 774static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) {
832{
833 return INTERPRETER_TRANSLATE(qadd8)(inst, index); 775 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
834} 776}
835static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) 777static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) {
836{
837 return INTERPRETER_TRANSLATE(qadd8)(inst, index); 778 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
838} 779}
839static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) 780static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) {
840{
841 return INTERPRETER_TRANSLATE(qadd8)(inst, index); 781 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
842} 782}
843static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) 783static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) {
844{
845 return INTERPRETER_TRANSLATE(qadd8)(inst, index); 784 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
846} 785}
847 786
848static ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) 787static 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)); 788 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; 789 rev_inst* const inst_cream = (rev_inst*)inst_base->component;
852 790
853 inst_base->cond = BITS(inst, 28, 31); 791 inst_base->cond = BITS(inst, 28, 31);
854 inst_base->idx = index; 792 inst_base->idx = index;
855 inst_base->br = TransExtData::NON_BRANCH; 793 inst_base->br = TransExtData::NON_BRANCH;
856 794
857 inst_cream->Rm = BITS(inst, 0, 3); 795 inst_cream->Rm = BITS(inst, 0, 3);
858 inst_cream->Rd = BITS(inst, 12, 15); 796 inst_cream->Rd = BITS(inst, 12, 15);
859 inst_cream->op1 = BITS(inst, 20, 22); 797 inst_cream->op1 = BITS(inst, 20, 22);
860 inst_cream->op2 = BITS(inst, 5, 7); 798 inst_cream->op2 = BITS(inst, 5, 7);
861 799
862 return inst_base; 800 return inst_base;
863} 801}
864static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index) 802static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index) {
865{
866 return INTERPRETER_TRANSLATE(rev)(inst, index); 803 return INTERPRETER_TRANSLATE(rev)(inst, index);
867} 804}
868static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) 805static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) {
869{ 806 return INTERPRETER_TRANSLATE(rev)(inst, index);
870 return INTERPRETER_TRANSLATE(rev)(inst, index);
871} 807}
872 808
873static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) 809static 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)); 810 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; 811 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
877 812
878 inst_base->cond = AL; 813 inst_base->cond = AL;
879 inst_base->idx = index; 814 inst_base->idx = index;
880 inst_base->br = TransExtData::INDIRECT_BRANCH; 815 inst_base->br = TransExtData::INDIRECT_BRANCH;
881 816
882 inst_cream->inst = inst; 817 inst_cream->inst = inst;
883 inst_cream->get_addr = GetAddressingOp(inst); 818 inst_cream->get_addr = GetAddressingOp(inst);
@@ -885,17 +820,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index)
885 return inst_base; 820 return inst_base;
886} 821}
887 822
888static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) 823static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) {
889{ 824 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)); 825 rsb_inst* inst_cream = (rsb_inst*)inst_base->component;
891 rsb_inst *inst_cream = (rsb_inst *)inst_base->component;
892 826
893 inst_base->cond = BITS(inst, 28, 31); 827 inst_base->cond = BITS(inst, 28, 31);
894 inst_base->idx = index; 828 inst_base->idx = index;
895 inst_base->br = TransExtData::NON_BRANCH; 829 inst_base->br = TransExtData::NON_BRANCH;
896 830
897 inst_cream->I = BIT(inst, 25); 831 inst_cream->I = BIT(inst, 25);
898 inst_cream->S = BIT(inst, 20); 832 inst_cream->S = BIT(inst, 20);
899 inst_cream->Rn = BITS(inst, 16, 19); 833 inst_cream->Rn = BITS(inst, 16, 19);
900 inst_cream->Rd = BITS(inst, 12, 15); 834 inst_cream->Rd = BITS(inst, 12, 15);
901 inst_cream->shifter_operand = BITS(inst, 0, 11); 835 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -906,17 +840,16 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index)
906 840
907 return inst_base; 841 return inst_base;
908} 842}
909static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) 843static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) {
910{ 844 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)); 845 rsc_inst* inst_cream = (rsc_inst*)inst_base->component;
912 rsc_inst *inst_cream = (rsc_inst *)inst_base->component;
913 846
914 inst_base->cond = BITS(inst, 28, 31); 847 inst_base->cond = BITS(inst, 28, 31);
915 inst_base->idx = index; 848 inst_base->idx = index;
916 inst_base->br = TransExtData::NON_BRANCH; 849 inst_base->br = TransExtData::NON_BRANCH;
917 850
918 inst_cream->I = BIT(inst, 25); 851 inst_cream->I = BIT(inst, 25);
919 inst_cream->S = BIT(inst, 20); 852 inst_cream->S = BIT(inst, 20);
920 inst_cream->Rn = BITS(inst, 16, 19); 853 inst_cream->Rn = BITS(inst, 16, 19);
921 inst_cream->Rd = BITS(inst, 12, 15); 854 inst_cream->Rd = BITS(inst, 12, 15);
922 inst_cream->shifter_operand = BITS(inst, 0, 11); 855 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -927,55 +860,48 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index)
927 860
928 return inst_base; 861 return inst_base;
929} 862}
930static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index) 863static 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)); 864 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; 865 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
934 866
935 inst_base->cond = BITS(inst, 28, 31); 867 inst_base->cond = BITS(inst, 28, 31);
936 inst_base->idx = index; 868 inst_base->idx = index;
937 inst_base->br = TransExtData::NON_BRANCH; 869 inst_base->br = TransExtData::NON_BRANCH;
938 870
939 inst_cream->Rm = BITS(inst, 0, 3); 871 inst_cream->Rm = BITS(inst, 0, 3);
940 inst_cream->Rn = BITS(inst, 16, 19); 872 inst_cream->Rn = BITS(inst, 16, 19);
941 inst_cream->Rd = BITS(inst, 12, 15); 873 inst_cream->Rd = BITS(inst, 12, 15);
942 inst_cream->op1 = BITS(inst, 20, 21); 874 inst_cream->op1 = BITS(inst, 20, 21);
943 inst_cream->op2 = BITS(inst, 5, 7); 875 inst_cream->op2 = BITS(inst, 5, 7);
944 876
945 return inst_base; 877 return inst_base;
946} 878}
947static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index) 879static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index) {
948{
949 return INTERPRETER_TRANSLATE(sadd8)(inst, index); 880 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
950} 881}
951static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index) 882static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index) {
952{
953 return INTERPRETER_TRANSLATE(sadd8)(inst, index); 883 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
954} 884}
955static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) 885static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) {
956{
957 return INTERPRETER_TRANSLATE(sadd8)(inst, index); 886 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
958} 887}
959static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) 888static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) {
960{
961 return INTERPRETER_TRANSLATE(sadd8)(inst, index); 889 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
962} 890}
963static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index) 891static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index) {
964{
965 return INTERPRETER_TRANSLATE(sadd8)(inst, index); 892 return INTERPRETER_TRANSLATE(sadd8)(inst, index);
966} 893}
967 894
968static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) 895static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) {
969{ 896 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)); 897 sbc_inst* inst_cream = (sbc_inst*)inst_base->component;
971 sbc_inst *inst_cream = (sbc_inst *)inst_base->component;
972 898
973 inst_base->cond = BITS(inst, 28, 31); 899 inst_base->cond = BITS(inst, 28, 31);
974 inst_base->idx = index; 900 inst_base->idx = index;
975 inst_base->br = TransExtData::NON_BRANCH; 901 inst_base->br = TransExtData::NON_BRANCH;
976 902
977 inst_cream->I = BIT(inst, 25); 903 inst_cream->I = BIT(inst, 25);
978 inst_cream->S = BIT(inst, 20); 904 inst_cream->S = BIT(inst, 20);
979 inst_cream->Rn = BITS(inst, 16, 19); 905 inst_cream->Rn = BITS(inst, 16, 19);
980 inst_cream->Rd = BITS(inst, 12, 15); 906 inst_cream->Rd = BITS(inst, 12, 15);
981 inst_cream->shifter_operand = BITS(inst, 0, 11); 907 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -986,98 +912,88 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index)
986 912
987 return inst_base; 913 return inst_base;
988} 914}
989static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) 915static 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)); 916 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; 917 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
993 918
994 inst_base->cond = BITS(inst, 28, 31); 919 inst_base->cond = BITS(inst, 28, 31);
995 inst_base->idx = index; 920 inst_base->idx = index;
996 inst_base->br = TransExtData::NON_BRANCH; 921 inst_base->br = TransExtData::NON_BRANCH;
997 922
998 inst_cream->Rm = BITS(inst, 0, 3); 923 inst_cream->Rm = BITS(inst, 0, 3);
999 inst_cream->Rn = BITS(inst, 16, 19); 924 inst_cream->Rn = BITS(inst, 16, 19);
1000 inst_cream->Rd = BITS(inst, 12, 15); 925 inst_cream->Rd = BITS(inst, 12, 15);
1001 inst_cream->op1 = BITS(inst, 20, 22); 926 inst_cream->op1 = BITS(inst, 20, 22);
1002 inst_cream->op2 = BITS(inst, 5, 7); 927 inst_cream->op2 = BITS(inst, 5, 7);
1003 928
1004 return inst_base; 929 return inst_base;
1005} 930}
1006 931
1007static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) 932static 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)); 933 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; 934 setend_inst* const inst_cream = (setend_inst*)inst_base->component;
1011 935
1012 inst_base->cond = AL; 936 inst_base->cond = AL;
1013 inst_base->idx = index; 937 inst_base->idx = index;
1014 inst_base->br = TransExtData::NON_BRANCH; 938 inst_base->br = TransExtData::NON_BRANCH;
1015 939
1016 inst_cream->set_bigend = BIT(inst, 9); 940 inst_cream->set_bigend = BIT(inst, 9);
1017 941
1018 return inst_base; 942 return inst_base;
1019} 943}
1020 944
1021static ARM_INST_PTR INTERPRETER_TRANSLATE(sev)(unsigned int inst, int index) 945static ARM_INST_PTR INTERPRETER_TRANSLATE(sev)(unsigned int inst, int index) {
1022{
1023 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); 946 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
1024 947
1025 inst_base->cond = BITS(inst, 28, 31); 948 inst_base->cond = BITS(inst, 28, 31);
1026 inst_base->idx = index; 949 inst_base->idx = index;
1027 inst_base->br = TransExtData::NON_BRANCH; 950 inst_base->br = TransExtData::NON_BRANCH;
1028 951
1029 return inst_base; 952 return inst_base;
1030} 953}
1031 954
1032static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) 955static 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)); 956 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; 957 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1036 958
1037 inst_base->cond = BITS(inst, 28, 31); 959 inst_base->cond = BITS(inst, 28, 31);
1038 inst_base->idx = index; 960 inst_base->idx = index;
1039 inst_base->br = TransExtData::NON_BRANCH; 961 inst_base->br = TransExtData::NON_BRANCH;
1040 962
1041 inst_cream->op1 = BITS(inst, 20, 21); 963 inst_cream->op1 = BITS(inst, 20, 21);
1042 inst_cream->op2 = BITS(inst, 5, 7); 964 inst_cream->op2 = BITS(inst, 5, 7);
1043 inst_cream->Rm = BITS(inst, 0, 3); 965 inst_cream->Rm = BITS(inst, 0, 3);
1044 inst_cream->Rn = BITS(inst, 16, 19); 966 inst_cream->Rn = BITS(inst, 16, 19);
1045 inst_cream->Rd = BITS(inst, 12, 15); 967 inst_cream->Rd = BITS(inst, 12, 15);
1046 968
1047 return inst_base; 969 return inst_base;
1048} 970}
1049static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) 971static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) {
1050{
1051 return INTERPRETER_TRANSLATE(shadd8)(inst, index); 972 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
1052} 973}
1053static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) 974static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index) {
1054{
1055 return INTERPRETER_TRANSLATE(shadd8)(inst, index); 975 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
1056} 976}
1057static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) 977static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) {
1058{
1059 return INTERPRETER_TRANSLATE(shadd8)(inst, index); 978 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
1060} 979}
1061static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) 980static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index) {
1062{
1063 return INTERPRETER_TRANSLATE(shadd8)(inst, index); 981 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
1064} 982}
1065static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) 983static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) {
1066{
1067 return INTERPRETER_TRANSLATE(shadd8)(inst, index); 984 return INTERPRETER_TRANSLATE(shadd8)(inst, index);
1068} 985}
1069 986
1070static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) 987static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) {
1071{ 988 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)); 989 smla_inst* inst_cream = (smla_inst*)inst_base->component;
1073 smla_inst *inst_cream = (smla_inst *)inst_base->component;
1074 990
1075 inst_base->cond = BITS(inst, 28, 31); 991 inst_base->cond = BITS(inst, 28, 31);
1076 inst_base->idx = index; 992 inst_base->idx = index;
1077 inst_base->br = TransExtData::NON_BRANCH; 993 inst_base->br = TransExtData::NON_BRANCH;
1078 994
1079 inst_cream->x = BIT(inst, 5); 995 inst_cream->x = BIT(inst, 5);
1080 inst_cream->y = BIT(inst, 6); 996 inst_cream->y = BIT(inst, 6);
1081 inst_cream->Rm = BITS(inst, 0, 3); 997 inst_cream->Rm = BITS(inst, 0, 3);
1082 inst_cream->Rs = BITS(inst, 8, 11); 998 inst_cream->Rs = BITS(inst, 8, 11);
1083 inst_cream->Rd = BITS(inst, 16, 19); 999 inst_cream->Rd = BITS(inst, 16, 19);
@@ -1086,192 +1002,176 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index)
1086 return inst_base; 1002 return inst_base;
1087} 1003}
1088 1004
1089static ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index) 1005static 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)); 1006 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; 1007 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
1093 1008
1094 inst_base->cond = BITS(inst, 28, 31); 1009 inst_base->cond = BITS(inst, 28, 31);
1095 inst_base->idx = index; 1010 inst_base->idx = index;
1096 inst_base->br = TransExtData::NON_BRANCH; 1011 inst_base->br = TransExtData::NON_BRANCH;
1097 1012
1098 inst_cream->m = BIT(inst, 5); 1013 inst_cream->m = BIT(inst, 5);
1099 inst_cream->Rn = BITS(inst, 0, 3); 1014 inst_cream->Rn = BITS(inst, 0, 3);
1100 inst_cream->Rm = BITS(inst, 8, 11); 1015 inst_cream->Rm = BITS(inst, 8, 11);
1101 inst_cream->Rd = BITS(inst, 16, 19); 1016 inst_cream->Rd = BITS(inst, 16, 19);
1102 inst_cream->Ra = BITS(inst, 12, 15); 1017 inst_cream->Ra = BITS(inst, 12, 15);
1103 inst_cream->op1 = BITS(inst, 20, 22); 1018 inst_cream->op1 = BITS(inst, 20, 22);
1104 inst_cream->op2 = BITS(inst, 5, 7); 1019 inst_cream->op2 = BITS(inst, 5, 7);
1105 1020
1106 return inst_base; 1021 return inst_base;
1107} 1022}
1108static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) 1023static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) {
1109{
1110 return INTERPRETER_TRANSLATE(smlad)(inst, index); 1024 return INTERPRETER_TRANSLATE(smlad)(inst, index);
1111} 1025}
1112static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) 1026static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) {
1113{
1114 return INTERPRETER_TRANSLATE(smlad)(inst, index); 1027 return INTERPRETER_TRANSLATE(smlad)(inst, index);
1115} 1028}
1116static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index) 1029static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index) {
1117{
1118 return INTERPRETER_TRANSLATE(smlad)(inst, index); 1030 return INTERPRETER_TRANSLATE(smlad)(inst, index);
1119} 1031}
1120 1032
1121static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) 1033static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) {
1122{ 1034 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)); 1035 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
1124 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
1125 1036
1126 inst_base->cond = BITS(inst, 28, 31); 1037 inst_base->cond = BITS(inst, 28, 31);
1127 inst_base->idx = index; 1038 inst_base->idx = index;
1128 inst_base->br = TransExtData::NON_BRANCH; 1039 inst_base->br = TransExtData::NON_BRANCH;
1129 1040
1130 inst_cream->S = BIT(inst, 20); 1041 inst_cream->S = BIT(inst, 20);
1131 inst_cream->Rm = BITS(inst, 0, 3); 1042 inst_cream->Rm = BITS(inst, 0, 3);
1132 inst_cream->Rs = BITS(inst, 8, 11); 1043 inst_cream->Rs = BITS(inst, 8, 11);
1133 inst_cream->RdHi = BITS(inst, 16, 19); 1044 inst_cream->RdHi = BITS(inst, 16, 19);
1134 inst_cream->RdLo = BITS(inst, 12, 15); 1045 inst_cream->RdLo = BITS(inst, 12, 15);
1135 1046
1136 return inst_base; 1047 return inst_base;
1137} 1048}
1138 1049
1139static ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) 1050static 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)); 1051 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; 1052 smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component;
1143 1053
1144 inst_base->cond = BITS(inst, 28, 31); 1054 inst_base->cond = BITS(inst, 28, 31);
1145 inst_base->idx = index; 1055 inst_base->idx = index;
1146 inst_base->br = TransExtData::NON_BRANCH; 1056 inst_base->br = TransExtData::NON_BRANCH;
1147 1057
1148 inst_cream->x = BIT(inst, 5); 1058 inst_cream->x = BIT(inst, 5);
1149 inst_cream->y = BIT(inst, 6); 1059 inst_cream->y = BIT(inst, 6);
1150 inst_cream->RdLo = BITS(inst, 12, 15); 1060 inst_cream->RdLo = BITS(inst, 12, 15);
1151 inst_cream->RdHi = BITS(inst, 16, 19); 1061 inst_cream->RdHi = BITS(inst, 16, 19);
1152 inst_cream->Rn = BITS(inst, 0, 4); 1062 inst_cream->Rn = BITS(inst, 0, 4);
1153 inst_cream->Rm = BITS(inst, 8, 11); 1063 inst_cream->Rm = BITS(inst, 8, 11);
1154 1064
1155 return inst_base; 1065 return inst_base;
1156} 1066}
1157 1067
1158static ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index) 1068static 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)); 1069 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; 1070 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
1162 1071
1163 inst_base->cond = BITS(inst, 28, 31); 1072 inst_base->cond = BITS(inst, 28, 31);
1164 inst_base->idx = index; 1073 inst_base->idx = index;
1165 inst_base->br = TransExtData::NON_BRANCH; 1074 inst_base->br = TransExtData::NON_BRANCH;
1166 1075
1167 inst_cream->Ra = BITS(inst, 12, 15); 1076 inst_cream->Ra = BITS(inst, 12, 15);
1168 inst_cream->Rm = BITS(inst, 8, 11); 1077 inst_cream->Rm = BITS(inst, 8, 11);
1169 inst_cream->Rn = BITS(inst, 0, 3); 1078 inst_cream->Rn = BITS(inst, 0, 3);
1170 inst_cream->Rd = BITS(inst, 16, 19); 1079 inst_cream->Rd = BITS(inst, 16, 19);
1171 inst_cream->m = BIT(inst, 6); 1080 inst_cream->m = BIT(inst, 6);
1172 1081
1173 return inst_base; 1082 return inst_base;
1174} 1083}
1175 1084
1176static ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) 1085static 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)); 1086 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; 1087 smlald_inst* const inst_cream = (smlald_inst*)inst_base->component;
1180 1088
1181 inst_base->cond = BITS(inst, 28, 31); 1089 inst_base->cond = BITS(inst, 28, 31);
1182 inst_base->idx = index; 1090 inst_base->idx = index;
1183 inst_base->br = TransExtData::NON_BRANCH; 1091 inst_base->br = TransExtData::NON_BRANCH;
1184 1092
1185 inst_cream->Rm = BITS(inst, 8, 11); 1093 inst_cream->Rm = BITS(inst, 8, 11);
1186 inst_cream->Rn = BITS(inst, 0, 3); 1094 inst_cream->Rn = BITS(inst, 0, 3);
1187 inst_cream->RdLo = BITS(inst, 12, 15); 1095 inst_cream->RdLo = BITS(inst, 12, 15);
1188 inst_cream->RdHi = BITS(inst, 16, 19); 1096 inst_cream->RdHi = BITS(inst, 16, 19);
1189 inst_cream->swap = BIT(inst, 5); 1097 inst_cream->swap = BIT(inst, 5);
1190 inst_cream->op1 = BITS(inst, 20, 22); 1098 inst_cream->op1 = BITS(inst, 20, 22);
1191 inst_cream->op2 = BITS(inst, 5, 7); 1099 inst_cream->op2 = BITS(inst, 5, 7);
1192 1100
1193 return inst_base; 1101 return inst_base;
1194} 1102}
1195static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) 1103static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index) {
1196{
1197 return INTERPRETER_TRANSLATE(smlald)(inst, index); 1104 return INTERPRETER_TRANSLATE(smlald)(inst, index);
1198} 1105}
1199 1106
1200static ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index) 1107static 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)); 1108 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; 1109 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
1204 1110
1205 inst_base->cond = BITS(inst, 28, 31); 1111 inst_base->cond = BITS(inst, 28, 31);
1206 inst_base->idx = index; 1112 inst_base->idx = index;
1207 inst_base->br = TransExtData::NON_BRANCH; 1113 inst_base->br = TransExtData::NON_BRANCH;
1208 1114
1209 inst_cream->m = BIT(inst, 5); 1115 inst_cream->m = BIT(inst, 5);
1210 inst_cream->Ra = BITS(inst, 12, 15); 1116 inst_cream->Ra = BITS(inst, 12, 15);
1211 inst_cream->Rm = BITS(inst, 8, 11); 1117 inst_cream->Rm = BITS(inst, 8, 11);
1212 inst_cream->Rn = BITS(inst, 0, 3); 1118 inst_cream->Rn = BITS(inst, 0, 3);
1213 inst_cream->Rd = BITS(inst, 16, 19); 1119 inst_cream->Rd = BITS(inst, 16, 19);
1214 inst_cream->op1 = BITS(inst, 20, 22); 1120 inst_cream->op1 = BITS(inst, 20, 22);
1215 inst_cream->op2 = BITS(inst, 5, 7); 1121 inst_cream->op2 = BITS(inst, 5, 7);
1216 1122
1217 return inst_base; 1123 return inst_base;
1218} 1124}
1219static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index) 1125static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index) {
1220{
1221 return INTERPRETER_TRANSLATE(smmla)(inst, index); 1126 return INTERPRETER_TRANSLATE(smmla)(inst, index);
1222} 1127}
1223static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index) 1128static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index) {
1224{
1225 return INTERPRETER_TRANSLATE(smmla)(inst, index); 1129 return INTERPRETER_TRANSLATE(smmla)(inst, index);
1226} 1130}
1227 1131
1228static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index) 1132static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index) {
1229{ 1133 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)); 1134 smul_inst* inst_cream = (smul_inst*)inst_base->component;
1231 smul_inst *inst_cream = (smul_inst *)inst_base->component;
1232 1135
1233 inst_base->cond = BITS(inst, 28, 31); 1136 inst_base->cond = BITS(inst, 28, 31);
1234 inst_base->idx = index; 1137 inst_base->idx = index;
1235 inst_base->br = TransExtData::NON_BRANCH; 1138 inst_base->br = TransExtData::NON_BRANCH;
1236 1139
1237 inst_cream->Rd = BITS(inst, 16, 19); 1140 inst_cream->Rd = BITS(inst, 16, 19);
1238 inst_cream->Rs = BITS(inst, 8, 11); 1141 inst_cream->Rs = BITS(inst, 8, 11);
1239 inst_cream->Rm = BITS(inst, 0, 3); 1142 inst_cream->Rm = BITS(inst, 0, 3);
1240 1143
1241 inst_cream->x = BIT(inst, 5); 1144 inst_cream->x = BIT(inst, 5);
1242 inst_cream->y = BIT(inst, 6); 1145 inst_cream->y = BIT(inst, 6);
1243 1146
1244 return inst_base; 1147 return inst_base;
1245
1246} 1148}
1247static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index) 1149static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index) {
1248{ 1150 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)); 1151 umull_inst* inst_cream = (umull_inst*)inst_base->component;
1250 umull_inst *inst_cream = (umull_inst *)inst_base->component;
1251 1152
1252 inst_base->cond = BITS(inst, 28, 31); 1153 inst_base->cond = BITS(inst, 28, 31);
1253 inst_base->idx = index; 1154 inst_base->idx = index;
1254 inst_base->br = TransExtData::NON_BRANCH; 1155 inst_base->br = TransExtData::NON_BRANCH;
1255 1156
1256 inst_cream->S = BIT(inst, 20); 1157 inst_cream->S = BIT(inst, 20);
1257 inst_cream->Rm = BITS(inst, 0, 3); 1158 inst_cream->Rm = BITS(inst, 0, 3);
1258 inst_cream->Rs = BITS(inst, 8, 11); 1159 inst_cream->Rs = BITS(inst, 8, 11);
1259 inst_cream->RdHi = BITS(inst, 16, 19); 1160 inst_cream->RdHi = BITS(inst, 16, 19);
1260 inst_cream->RdLo = BITS(inst, 12, 15); 1161 inst_cream->RdLo = BITS(inst, 12, 15);
1261 1162
1262 return inst_base; 1163 return inst_base;
1263} 1164}
1264 1165
1265static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) 1166static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) {
1266{ 1167 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)); 1168 smlad_inst* inst_cream = (smlad_inst*)inst_base->component;
1268 smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
1269 1169
1270 inst_base->cond = BITS(inst, 28, 31); 1170 inst_base->cond = BITS(inst, 28, 31);
1271 inst_base->idx = index; 1171 inst_base->idx = index;
1272 inst_base->br = TransExtData::NON_BRANCH; 1172 inst_base->br = TransExtData::NON_BRANCH;
1273 1173
1274 inst_cream->m = BIT(inst, 6); 1174 inst_cream->m = BIT(inst, 6);
1275 inst_cream->Rm = BITS(inst, 8, 11); 1175 inst_cream->Rm = BITS(inst, 8, 11);
1276 inst_cream->Rn = BITS(inst, 0, 3); 1176 inst_cream->Rn = BITS(inst, 0, 3);
1277 inst_cream->Rd = BITS(inst, 16, 19); 1177 inst_cream->Rd = BITS(inst, 16, 19);
@@ -1279,29 +1179,27 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index)
1279 return inst_base; 1179 return inst_base;
1280} 1180}
1281 1181
1282static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) 1182static 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)); 1183 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; 1184 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
1286 1185
1287 inst_base->cond = AL; 1186 inst_base->cond = AL;
1288 inst_base->idx = index; 1187 inst_base->idx = index;
1289 inst_base->br = TransExtData::NON_BRANCH; 1188 inst_base->br = TransExtData::NON_BRANCH;
1290 1189
1291 inst_cream->inst = inst; 1190 inst_cream->inst = inst;
1292 inst_cream->get_addr = GetAddressingOp(inst); 1191 inst_cream->get_addr = GetAddressingOp(inst);
1293 1192
1294 return inst_base; 1193 return inst_base;
1295} 1194}
1296 1195
1297static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) 1196static 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)); 1197 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; 1198 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
1301 1199
1302 inst_base->cond = BITS(inst, 28, 31); 1200 inst_base->cond = BITS(inst, 28, 31);
1303 inst_base->idx = index; 1201 inst_base->idx = index;
1304 inst_base->br = TransExtData::NON_BRANCH; 1202 inst_base->br = TransExtData::NON_BRANCH;
1305 1203
1306 inst_cream->Rn = BITS(inst, 0, 3); 1204 inst_cream->Rn = BITS(inst, 0, 3);
1307 inst_cream->Rd = BITS(inst, 12, 15); 1205 inst_cream->Rd = BITS(inst, 12, 15);
@@ -1311,211 +1209,195 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index)
1311 1209
1312 return inst_base; 1210 return inst_base;
1313} 1211}
1314static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) 1212static 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)); 1213 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; 1214 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
1318 1215
1319 inst_base->cond = BITS(inst, 28, 31); 1216 inst_base->cond = BITS(inst, 28, 31);
1320 inst_base->idx = index; 1217 inst_base->idx = index;
1321 inst_base->br = TransExtData::NON_BRANCH; 1218 inst_base->br = TransExtData::NON_BRANCH;
1322 1219
1323 inst_cream->Rn = BITS(inst, 0, 3); 1220 inst_cream->Rn = BITS(inst, 0, 3);
1324 inst_cream->Rd = BITS(inst, 12, 15); 1221 inst_cream->Rd = BITS(inst, 12, 15);
1325 inst_cream->sat_imm = BITS(inst, 16, 19); 1222 inst_cream->sat_imm = BITS(inst, 16, 19);
1326 1223
1327 return inst_base; 1224 return inst_base;
1328} 1225}
1329 1226
1330static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index) 1227static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index) {
1331{ 1228 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); 1229 inst_base->cond = BITS(inst, 28, 31);
1334 inst_base->idx = index; 1230 inst_base->idx = index;
1335 inst_base->br = TransExtData::NON_BRANCH; 1231 inst_base->br = TransExtData::NON_BRANCH;
1336 1232
1337 return inst_base; 1233 return inst_base;
1338} 1234}
1339static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) 1235static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) {
1340{ 1236 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)); 1237 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1342 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1343 1238
1344 inst_base->cond = BITS(inst, 28, 31); 1239 inst_base->cond = BITS(inst, 28, 31);
1345 inst_base->idx = index; 1240 inst_base->idx = index;
1346 inst_base->br = TransExtData::NON_BRANCH; 1241 inst_base->br = TransExtData::NON_BRANCH;
1347 1242
1348 inst_cream->inst = inst; 1243 inst_cream->inst = inst;
1349 inst_cream->get_addr = GetAddressingOp(inst); 1244 inst_cream->get_addr = GetAddressingOp(inst);
1350 return inst_base; 1245 return inst_base;
1351} 1246}
1352static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) 1247static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) {
1353{ 1248 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)); 1249 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component;
1355 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
1356 1250
1357 inst_base->cond = BITS(inst, 28, 31); 1251 inst_base->cond = BITS(inst, 28, 31);
1358 inst_base->idx = index; 1252 inst_base->idx = index;
1359 inst_base->br = TransExtData::NON_BRANCH; 1253 inst_base->br = TransExtData::NON_BRANCH;
1360 1254
1361 inst_cream->Rd = BITS(inst, 12, 15); 1255 inst_cream->Rd = BITS(inst, 12, 15);
1362 inst_cream->Rm = BITS(inst, 0, 3); 1256 inst_cream->Rm = BITS(inst, 0, 3);
1363 inst_cream->rotate = BITS(inst, 10, 11); 1257 inst_cream->rotate = BITS(inst, 10, 11);
1364 1258
1365 return inst_base; 1259 return inst_base;
1366} 1260}
1367static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) 1261static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) {
1368{ 1262 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)); 1263 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1370 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1371 1264
1372 inst_base->cond = BITS(inst, 28, 31); 1265 inst_base->cond = BITS(inst, 28, 31);
1373 inst_base->idx = index; 1266 inst_base->idx = index;
1374 inst_base->br = TransExtData::NON_BRANCH; 1267 inst_base->br = TransExtData::NON_BRANCH;
1375 1268
1376 inst_cream->inst = inst; 1269 inst_cream->inst = inst;
1377 inst_cream->get_addr = GetAddressingOp(inst); 1270 inst_cream->get_addr = GetAddressingOp(inst);
1378 1271
1379 return inst_base; 1272 return inst_base;
1380} 1273}
1381static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) 1274static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) {
1382{ 1275 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)); 1276 uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
1384 uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
1385 1277
1386 inst_base->cond = BITS(inst, 28, 31); 1278 inst_base->cond = BITS(inst, 28, 31);
1387 inst_base->idx = index; 1279 inst_base->idx = index;
1388 inst_base->br = TransExtData::NON_BRANCH; 1280 inst_base->br = TransExtData::NON_BRANCH;
1389 1281
1390 inst_cream->Rd = BITS(inst, 12, 15); 1282 inst_cream->Rd = BITS(inst, 12, 15);
1391 inst_cream->rotate = BITS(inst, 10, 11); 1283 inst_cream->rotate = BITS(inst, 10, 11);
1392 inst_cream->Rm = BITS(inst, 0, 3); 1284 inst_cream->Rm = BITS(inst, 0, 3);
1393 1285
1394 return inst_base; 1286 return inst_base;
1395} 1287}
1396static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index) 1288static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index) {
1397{ 1289 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)); 1290 uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component;
1399 uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component;
1400 1291
1401 inst_base->cond = BITS(inst, 28, 31); 1292 inst_base->cond = BITS(inst, 28, 31);
1402 inst_base->idx = index; 1293 inst_base->idx = index;
1403 inst_base->br = TransExtData::NON_BRANCH; 1294 inst_base->br = TransExtData::NON_BRANCH;
1404 1295
1405 inst_cream->Rd = BITS(inst, 12, 15); 1296 inst_cream->Rd = BITS(inst, 12, 15);
1406 inst_cream->rotate = BITS(inst, 10, 11); 1297 inst_cream->rotate = BITS(inst, 10, 11);
1407 inst_cream->Rm = BITS(inst, 0, 3); 1298 inst_cream->Rm = BITS(inst, 0, 3);
1408 inst_cream->Rn = BITS(inst, 16, 19); 1299 inst_cream->Rn = BITS(inst, 16, 19);
1409 1300
1410 return inst_base; 1301 return inst_base;
1411} 1302}
1412static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) 1303static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) {
1413{ 1304 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)); 1305 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1415 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1416 1306
1417 inst_base->cond = BITS(inst, 28, 31); 1307 inst_base->cond = BITS(inst, 28, 31);
1418 inst_base->idx = index; 1308 inst_base->idx = index;
1419 inst_base->br = TransExtData::NON_BRANCH; 1309 inst_base->br = TransExtData::NON_BRANCH;
1420 1310
1421 inst_cream->inst = inst; 1311 inst_cream->inst = inst;
1422 inst_cream->get_addr = GetAddressingOp(inst); 1312 inst_cream->get_addr = GetAddressingOp(inst);
1423 1313
1424 return inst_base; 1314 return inst_base;
1425} 1315}
1426static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) 1316static 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)); 1317 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1429 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 1318 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1430 1319
1431 inst_base->cond = BITS(inst, 28, 31); 1320 inst_base->cond = BITS(inst, 28, 31);
1432 inst_base->idx = index; 1321 inst_base->idx = index;
1433 inst_base->br = TransExtData::NON_BRANCH; 1322 inst_base->br = TransExtData::NON_BRANCH;
1434 1323
1435 inst_cream->inst = inst; 1324 inst_cream->inst = inst;
1436 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); 1325 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
1437 1326
1438 return inst_base; 1327 return inst_base;
1439} 1328}
1440static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){ 1329static 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)); 1330 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1442 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1331 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1443 1332
1444 inst_base->cond = BITS(inst, 28, 31); 1333 inst_base->cond = BITS(inst, 28, 31);
1445 inst_base->idx = index; 1334 inst_base->idx = index;
1446 inst_base->br = TransExtData::NON_BRANCH; 1335 inst_base->br = TransExtData::NON_BRANCH;
1447 1336
1448 inst_cream->inst = inst; 1337 inst_cream->inst = inst;
1449 inst_cream->get_addr = GetAddressingOp(inst); 1338 inst_cream->get_addr = GetAddressingOp(inst);
1450 1339
1451 return inst_base; 1340 return inst_base;
1452} 1341}
1453static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) 1342static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) {
1454{ 1343 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)); 1344 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
1456 generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component;
1457 1345
1458 inst_base->cond = BITS(inst, 28, 31); 1346 inst_base->cond = BITS(inst, 28, 31);
1459 inst_base->idx = index; 1347 inst_base->idx = index;
1460 inst_base->br = TransExtData::NON_BRANCH; 1348 inst_base->br = TransExtData::NON_BRANCH;
1461 1349
1462 inst_cream->Rn = BITS(inst, 16, 19); 1350 inst_cream->Rn = BITS(inst, 16, 19);
1463 inst_cream->Rd = BITS(inst, 12, 15); 1351 inst_cream->Rd = BITS(inst, 12, 15);
1464 inst_cream->Rm = BITS(inst, 0, 3); 1352 inst_cream->Rm = BITS(inst, 0, 3);
1465 1353
1466 return inst_base; 1354 return inst_base;
1467} 1355}
1468static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) 1356static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) {
1469{
1470 return INTERPRETER_TRANSLATE(strex)(inst, index); 1357 return INTERPRETER_TRANSLATE(strex)(inst, index);
1471} 1358}
1472static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index) 1359static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index) {
1473{
1474 return INTERPRETER_TRANSLATE(strex)(inst, index); 1360 return INTERPRETER_TRANSLATE(strex)(inst, index);
1475} 1361}
1476static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index) 1362static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index) {
1477{
1478 return INTERPRETER_TRANSLATE(strex)(inst, index); 1363 return INTERPRETER_TRANSLATE(strex)(inst, index);
1479} 1364}
1480static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) 1365static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) {
1481{ 1366 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)); 1367 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1483 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1484 1368
1485 inst_base->cond = BITS(inst, 28, 31); 1369 inst_base->cond = BITS(inst, 28, 31);
1486 inst_base->idx = index; 1370 inst_base->idx = index;
1487 inst_base->br = TransExtData::NON_BRANCH; 1371 inst_base->br = TransExtData::NON_BRANCH;
1488 1372
1489 inst_cream->inst = inst; 1373 inst_cream->inst = inst;
1490 inst_cream->get_addr = GetAddressingOp(inst); 1374 inst_cream->get_addr = GetAddressingOp(inst);
1491 1375
1492 return inst_base; 1376 return inst_base;
1493} 1377}
1494static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) 1378static 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)); 1379 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1497 ldst_inst* inst_cream = (ldst_inst*)inst_base->component; 1380 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
1498 1381
1499 inst_base->cond = BITS(inst, 28, 31); 1382 inst_base->cond = BITS(inst, 28, 31);
1500 inst_base->idx = index; 1383 inst_base->idx = index;
1501 inst_base->br = TransExtData::NON_BRANCH; 1384 inst_base->br = TransExtData::NON_BRANCH;
1502 1385
1503 inst_cream->inst = inst; 1386 inst_cream->inst = inst;
1504 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); 1387 inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
1505 1388
1506 return inst_base; 1389 return inst_base;
1507} 1390}
1508static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) 1391static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) {
1509{ 1392 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)); 1393 sub_inst* inst_cream = (sub_inst*)inst_base->component;
1511 sub_inst *inst_cream = (sub_inst *)inst_base->component;
1512 1394
1513 inst_base->cond = BITS(inst, 28, 31); 1395 inst_base->cond = BITS(inst, 28, 31);
1514 inst_base->idx = index; 1396 inst_base->idx = index;
1515 inst_base->br = TransExtData::NON_BRANCH; 1397 inst_base->br = TransExtData::NON_BRANCH;
1516 1398
1517 inst_cream->I = BIT(inst, 25); 1399 inst_cream->I = BIT(inst, 25);
1518 inst_cream->S = BIT(inst, 20); 1400 inst_cream->S = BIT(inst, 20);
1519 inst_cream->Rn = BITS(inst, 16, 19); 1401 inst_cream->Rn = BITS(inst, 16, 19);
1520 inst_cream->Rd = BITS(inst, 12, 15); 1402 inst_cream->Rd = BITS(inst, 12, 15);
1521 inst_cream->shifter_operand = BITS(inst, 0, 11); 1403 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -1526,71 +1408,68 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index)
1526 1408
1527 return inst_base; 1409 return inst_base;
1528} 1410}
1529static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index) 1411static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index) {
1530{ 1412 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)); 1413 swi_inst* inst_cream = (swi_inst*)inst_base->component;
1532 swi_inst *inst_cream = (swi_inst *)inst_base->component;
1533 1414
1534 inst_base->cond = BITS(inst, 28, 31); 1415 inst_base->cond = BITS(inst, 28, 31);
1535 inst_base->idx = index; 1416 inst_base->idx = index;
1536 inst_base->br = TransExtData::NON_BRANCH; 1417 inst_base->br = TransExtData::NON_BRANCH;
1537 1418
1538 inst_cream->num = BITS(inst, 0, 23); 1419 inst_cream->num = BITS(inst, 0, 23);
1539 return inst_base; 1420 return inst_base;
1540} 1421}
1541static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) 1422static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) {
1542{ 1423 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)); 1424 swp_inst* inst_cream = (swp_inst*)inst_base->component;
1544 swp_inst *inst_cream = (swp_inst *)inst_base->component;
1545 1425
1546 inst_base->cond = BITS(inst, 28, 31); 1426 inst_base->cond = BITS(inst, 28, 31);
1547 inst_base->idx = index; 1427 inst_base->idx = index;
1548 inst_base->br = TransExtData::NON_BRANCH; 1428 inst_base->br = TransExtData::NON_BRANCH;
1549 1429
1550 inst_cream->Rn = BITS(inst, 16, 19); 1430 inst_cream->Rn = BITS(inst, 16, 19);
1551 inst_cream->Rd = BITS(inst, 12, 15); 1431 inst_cream->Rd = BITS(inst, 12, 15);
1552 inst_cream->Rm = BITS(inst, 0, 3); 1432 inst_cream->Rm = BITS(inst, 0, 3);
1553 1433
1554 return inst_base; 1434 return inst_base;
1555} 1435}
1556static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){ 1436static 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)); 1437 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
1558 swp_inst *inst_cream = (swp_inst *)inst_base->component; 1438 swp_inst* inst_cream = (swp_inst*)inst_base->component;
1559 1439
1560 inst_base->cond = BITS(inst, 28, 31); 1440 inst_base->cond = BITS(inst, 28, 31);
1561 inst_base->idx = index; 1441 inst_base->idx = index;
1562 inst_base->br = TransExtData::NON_BRANCH; 1442 inst_base->br = TransExtData::NON_BRANCH;
1563 1443
1564 inst_cream->Rn = BITS(inst, 16, 19); 1444 inst_cream->Rn = BITS(inst, 16, 19);
1565 inst_cream->Rd = BITS(inst, 12, 15); 1445 inst_cream->Rd = BITS(inst, 12, 15);
1566 inst_cream->Rm = BITS(inst, 0, 3); 1446 inst_cream->Rm = BITS(inst, 0, 3);
1567 1447
1568 return inst_base; 1448 return inst_base;
1569} 1449}
1570static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){ 1450static 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)); 1451 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst));
1572 sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component; 1452 sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component;
1573 1453
1574 inst_base->cond = BITS(inst, 28, 31); 1454 inst_base->cond = BITS(inst, 28, 31);
1575 inst_base->idx = index; 1455 inst_base->idx = index;
1576 inst_base->br = TransExtData::NON_BRANCH; 1456 inst_base->br = TransExtData::NON_BRANCH;
1577 1457
1578 inst_cream->Rd = BITS(inst, 12, 15); 1458 inst_cream->Rd = BITS(inst, 12, 15);
1579 inst_cream->rotate = BITS(inst, 10, 11); 1459 inst_cream->rotate = BITS(inst, 10, 11);
1580 inst_cream->Rm = BITS(inst, 0, 3); 1460 inst_cream->Rm = BITS(inst, 0, 3);
1581 inst_cream->Rn = BITS(inst, 16, 19); 1461 inst_cream->Rn = BITS(inst, 16, 19);
1582 1462
1583 return inst_base; 1463 return inst_base;
1584} 1464}
1585 1465
1586static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) 1466static 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)); 1467 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; 1468 sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component;
1590 1469
1591 inst_base->cond = BITS(inst, 28, 31); 1470 inst_base->cond = BITS(inst, 28, 31);
1592 inst_base->idx = index; 1471 inst_base->idx = index;
1593 inst_base->br = TransExtData::NON_BRANCH; 1472 inst_base->br = TransExtData::NON_BRANCH;
1594 1473
1595 inst_cream->Rm = BITS(inst, 0, 3); 1474 inst_cream->Rm = BITS(inst, 0, 3);
1596 inst_cream->Rn = BITS(inst, 16, 19); 1475 inst_cream->Rn = BITS(inst, 16, 19);
@@ -1599,54 +1478,51 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index)
1599 1478
1600 return inst_base; 1479 return inst_base;
1601} 1480}
1602static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) 1481static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) {
1603{
1604 return INTERPRETER_TRANSLATE(sxtab16)(inst, index); 1482 return INTERPRETER_TRANSLATE(sxtab16)(inst, index);
1605} 1483}
1606 1484
1607static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index) { 1485static 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)); 1486 arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst));
1609 sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component; 1487 sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component;
1610 1488
1611 inst_base->cond = BITS(inst, 28, 31); 1489 inst_base->cond = BITS(inst, 28, 31);
1612 inst_base->idx = index; 1490 inst_base->idx = index;
1613 inst_base->br = TransExtData::NON_BRANCH; 1491 inst_base->br = TransExtData::NON_BRANCH;
1614 1492
1615 inst_cream->Rd = BITS(inst, 12, 15); 1493 inst_cream->Rd = BITS(inst, 12, 15);
1616 inst_cream->rotate = BITS(inst, 10, 11); 1494 inst_cream->rotate = BITS(inst, 10, 11);
1617 inst_cream->Rm = BITS(inst, 0, 3); 1495 inst_cream->Rm = BITS(inst, 0, 3);
1618 inst_cream->Rn = BITS(inst, 16, 19); 1496 inst_cream->Rn = BITS(inst, 16, 19);
1619 1497
1620 return inst_base; 1498 return inst_base;
1621} 1499}
1622 1500
1623static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) 1501static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) {
1624{ 1502 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)); 1503 teq_inst* inst_cream = (teq_inst*)inst_base->component;
1626 teq_inst *inst_cream = (teq_inst *)inst_base->component;
1627 1504
1628 inst_base->cond = BITS(inst, 28, 31); 1505 inst_base->cond = BITS(inst, 28, 31);
1629 inst_base->idx = index; 1506 inst_base->idx = index;
1630 inst_base->br = TransExtData::NON_BRANCH; 1507 inst_base->br = TransExtData::NON_BRANCH;
1631 1508
1632 inst_cream->I = BIT(inst, 25); 1509 inst_cream->I = BIT(inst, 25);
1633 inst_cream->Rn = BITS(inst, 16, 19); 1510 inst_cream->Rn = BITS(inst, 16, 19);
1634 inst_cream->shifter_operand = BITS(inst, 0, 11); 1511 inst_cream->shifter_operand = BITS(inst, 0, 11);
1635 inst_cream->shtop_func = GetShifterOp(inst); 1512 inst_cream->shtop_func = GetShifterOp(inst);
1636 1513
1637 return inst_base; 1514 return inst_base;
1638} 1515}
1639static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) 1516static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) {
1640{ 1517 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)); 1518 tst_inst* inst_cream = (tst_inst*)inst_base->component;
1642 tst_inst *inst_cream = (tst_inst *)inst_base->component;
1643 1519
1644 inst_base->cond = BITS(inst, 28, 31); 1520 inst_base->cond = BITS(inst, 28, 31);
1645 inst_base->idx = index; 1521 inst_base->idx = index;
1646 inst_base->br = TransExtData::NON_BRANCH; 1522 inst_base->br = TransExtData::NON_BRANCH;
1647 1523
1648 inst_cream->I = BIT(inst, 25); 1524 inst_cream->I = BIT(inst, 25);
1649 inst_cream->S = BIT(inst, 20); 1525 inst_cream->S = BIT(inst, 20);
1650 inst_cream->Rn = BITS(inst, 16, 19); 1526 inst_cream->Rn = BITS(inst, 16, 19);
1651 inst_cream->Rd = BITS(inst, 12, 15); 1527 inst_cream->Rd = BITS(inst, 12, 15);
1652 inst_cream->shifter_operand = BITS(inst, 0, 11); 1528 inst_cream->shifter_operand = BITS(inst, 0, 11);
@@ -1655,309 +1531,274 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index)
1655 return inst_base; 1531 return inst_base;
1656} 1532}
1657 1533
1658static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) 1534static 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)); 1535 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; 1536 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1662 1537
1663 inst_base->cond = BITS(inst, 28, 31); 1538 inst_base->cond = BITS(inst, 28, 31);
1664 inst_base->idx = index; 1539 inst_base->idx = index;
1665 inst_base->br = TransExtData::NON_BRANCH; 1540 inst_base->br = TransExtData::NON_BRANCH;
1666 1541
1667 inst_cream->op1 = BITS(inst, 20, 21); 1542 inst_cream->op1 = BITS(inst, 20, 21);
1668 inst_cream->op2 = BITS(inst, 5, 7); 1543 inst_cream->op2 = BITS(inst, 5, 7);
1669 inst_cream->Rm = BITS(inst, 0, 3); 1544 inst_cream->Rm = BITS(inst, 0, 3);
1670 inst_cream->Rn = BITS(inst, 16, 19); 1545 inst_cream->Rn = BITS(inst, 16, 19);
1671 inst_cream->Rd = BITS(inst, 12, 15); 1546 inst_cream->Rd = BITS(inst, 12, 15);
1672 1547
1673 return inst_base; 1548 return inst_base;
1674} 1549}
1675static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) 1550static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) {
1676{
1677 return INTERPRETER_TRANSLATE(uadd8)(inst, index); 1551 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1678} 1552}
1679static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) 1553static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) {
1680{
1681 return INTERPRETER_TRANSLATE(uadd8)(inst, index); 1554 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1682} 1555}
1683static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) 1556static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) {
1684{
1685 return INTERPRETER_TRANSLATE(uadd8)(inst, index); 1557 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1686} 1558}
1687static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) 1559static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) {
1688{
1689 return INTERPRETER_TRANSLATE(uadd8)(inst, index); 1560 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1690} 1561}
1691static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) 1562static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) {
1692{
1693 return INTERPRETER_TRANSLATE(uadd8)(inst, index); 1563 return INTERPRETER_TRANSLATE(uadd8)(inst, index);
1694} 1564}
1695 1565
1696static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) 1566static 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)); 1567 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; 1568 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1700 1569
1701 inst_base->cond = BITS(inst, 28, 31); 1570 inst_base->cond = BITS(inst, 28, 31);
1702 inst_base->idx = index; 1571 inst_base->idx = index;
1703 inst_base->br = TransExtData::NON_BRANCH; 1572 inst_base->br = TransExtData::NON_BRANCH;
1704 1573
1705 inst_cream->op1 = BITS(inst, 20, 21); 1574 inst_cream->op1 = BITS(inst, 20, 21);
1706 inst_cream->op2 = BITS(inst, 5, 7); 1575 inst_cream->op2 = BITS(inst, 5, 7);
1707 inst_cream->Rm = BITS(inst, 0, 3); 1576 inst_cream->Rm = BITS(inst, 0, 3);
1708 inst_cream->Rn = BITS(inst, 16, 19); 1577 inst_cream->Rn = BITS(inst, 16, 19);
1709 inst_cream->Rd = BITS(inst, 12, 15); 1578 inst_cream->Rd = BITS(inst, 12, 15);
1710 1579
1711 return inst_base; 1580 return inst_base;
1712} 1581}
1713static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) 1582static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) {
1714{
1715 return INTERPRETER_TRANSLATE(uhadd8)(inst, index); 1583 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1716} 1584}
1717static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) 1585static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) {
1718{
1719 return INTERPRETER_TRANSLATE(uhadd8)(inst, index); 1586 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1720} 1587}
1721static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) 1588static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) {
1722{
1723 return INTERPRETER_TRANSLATE(uhadd8)(inst, index); 1589 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1724} 1590}
1725static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) 1591static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) {
1726{
1727 return INTERPRETER_TRANSLATE(uhadd8)(inst, index); 1592 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1728} 1593}
1729static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) 1594static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) {
1730{
1731 return INTERPRETER_TRANSLATE(uhadd8)(inst, index); 1595 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
1732} 1596}
1733static ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) 1597static 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)); 1598 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; 1599 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
1737 1600
1738 inst_base->cond = BITS(inst, 28, 31); 1601 inst_base->cond = BITS(inst, 28, 31);
1739 inst_base->idx = index; 1602 inst_base->idx = index;
1740 inst_base->br = TransExtData::NON_BRANCH; 1603 inst_base->br = TransExtData::NON_BRANCH;
1741 1604
1742 inst_cream->Rm = BITS(inst, 8, 11); 1605 inst_cream->Rm = BITS(inst, 8, 11);
1743 inst_cream->Rn = BITS(inst, 0, 3); 1606 inst_cream->Rn = BITS(inst, 0, 3);
1744 inst_cream->RdLo = BITS(inst, 12, 15); 1607 inst_cream->RdLo = BITS(inst, 12, 15);
1745 inst_cream->RdHi = BITS(inst, 16, 19); 1608 inst_cream->RdHi = BITS(inst, 16, 19);
1746 1609
1747 return inst_base; 1610 return inst_base;
1748} 1611}
1749static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) 1612static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) {
1750{ 1613 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)); 1614 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
1752 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
1753 1615
1754 inst_base->cond = BITS(inst, 28, 31); 1616 inst_base->cond = BITS(inst, 28, 31);
1755 inst_base->idx = index; 1617 inst_base->idx = index;
1756 inst_base->br = TransExtData::NON_BRANCH; 1618 inst_base->br = TransExtData::NON_BRANCH;
1757 1619
1758 inst_cream->S = BIT(inst, 20); 1620 inst_cream->S = BIT(inst, 20);
1759 inst_cream->Rm = BITS(inst, 0, 3); 1621 inst_cream->Rm = BITS(inst, 0, 3);
1760 inst_cream->Rs = BITS(inst, 8, 11); 1622 inst_cream->Rs = BITS(inst, 8, 11);
1761 inst_cream->RdHi = BITS(inst, 16, 19); 1623 inst_cream->RdHi = BITS(inst, 16, 19);
1762 inst_cream->RdLo = BITS(inst, 12, 15); 1624 inst_cream->RdLo = BITS(inst, 12, 15);
1763 1625
1764 return inst_base; 1626 return inst_base;
1765} 1627}
1766static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index) 1628static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index) {
1767{ 1629 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)); 1630 umull_inst* inst_cream = (umull_inst*)inst_base->component;
1769 umull_inst *inst_cream = (umull_inst *)inst_base->component;
1770 1631
1771 inst_base->cond = BITS(inst, 28, 31); 1632 inst_base->cond = BITS(inst, 28, 31);
1772 inst_base->idx = index; 1633 inst_base->idx = index;
1773 inst_base->br = TransExtData::NON_BRANCH; 1634 inst_base->br = TransExtData::NON_BRANCH;
1774 1635
1775 inst_cream->S = BIT(inst, 20); 1636 inst_cream->S = BIT(inst, 20);
1776 inst_cream->Rm = BITS(inst, 0, 3); 1637 inst_cream->Rm = BITS(inst, 0, 3);
1777 inst_cream->Rs = BITS(inst, 8, 11); 1638 inst_cream->Rs = BITS(inst, 8, 11);
1778 inst_cream->RdHi = BITS(inst, 16, 19); 1639 inst_cream->RdHi = BITS(inst, 16, 19);
1779 inst_cream->RdLo = BITS(inst, 12, 15); 1640 inst_cream->RdLo = BITS(inst, 12, 15);
1780 1641
1781 return inst_base; 1642 return inst_base;
1782} 1643}
1783 1644
1784static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index) 1645static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index) {
1785{ 1646 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)); 1647 b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component;
1787 b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component;
1788 1648
1789 inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0); 1649 inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0);
1790 1650
1791 inst_base->idx = index; 1651 inst_base->idx = index;
1792 inst_base->br = TransExtData::DIRECT_BRANCH; 1652 inst_base->br = TransExtData::DIRECT_BRANCH;
1793 1653
1794 return inst_base; 1654 return inst_base;
1795} 1655}
1796 1656
1797static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index) 1657static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index) {
1798{ 1658 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)); 1659 b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component;
1800 b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component;
1801 1660
1802 inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0)); 1661 inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0));
1803 inst_cream->cond = ((tinst >> 8) & 0xf); 1662 inst_cream->cond = ((tinst >> 8) & 0xf);
1804 inst_base->idx = index; 1663 inst_base->idx = index;
1805 inst_base->br = TransExtData::DIRECT_BRANCH; 1664 inst_base->br = TransExtData::DIRECT_BRANCH;
1806 1665
1807 return inst_base; 1666 return inst_base;
1808} 1667}
1809 1668
1810static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index) 1669static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index) {
1811{ 1670 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)); 1671 bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component;
1813 bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component;
1814 1672
1815 inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0)); 1673 inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0));
1816 1674
1817 inst_base->idx = index; 1675 inst_base->idx = index;
1818 inst_base->br = TransExtData::NON_BRANCH; 1676 inst_base->br = TransExtData::NON_BRANCH;
1819 return inst_base; 1677 return inst_base;
1820} 1678}
1821static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index) 1679static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index) {
1822{ 1680 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)); 1681 bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component;
1824 bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component;
1825 1682
1826 inst_cream->imm = (tinst & 0x07FF) << 1; 1683 inst_cream->imm = (tinst & 0x07FF) << 1;
1827 1684
1828 inst_base->idx = index; 1685 inst_base->idx = index;
1829 inst_base->br = TransExtData::DIRECT_BRANCH; 1686 inst_base->br = TransExtData::DIRECT_BRANCH;
1830 return inst_base; 1687 return inst_base;
1831} 1688}
1832static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) 1689static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) {
1833{ 1690 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)); 1691 blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component;
1835 blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component;
1836 1692
1837 inst_cream->imm = (tinst & 0x07FF) << 1; 1693 inst_cream->imm = (tinst & 0x07FF) << 1;
1838 inst_cream->instr = tinst; 1694 inst_cream->instr = tinst;
1839 1695
1840 inst_base->idx = index; 1696 inst_base->idx = index;
1841 inst_base->br = TransExtData::DIRECT_BRANCH; 1697 inst_base->br = TransExtData::DIRECT_BRANCH;
1842 return inst_base; 1698 return inst_base;
1843} 1699}
1844 1700
1845static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) 1701static 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)); 1702 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; 1703 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1849 1704
1850 inst_base->cond = BITS(inst, 28, 31); 1705 inst_base->cond = BITS(inst, 28, 31);
1851 inst_base->idx = index; 1706 inst_base->idx = index;
1852 inst_base->br = TransExtData::NON_BRANCH; 1707 inst_base->br = TransExtData::NON_BRANCH;
1853 1708
1854 inst_cream->Rm = BITS(inst, 0, 3); 1709 inst_cream->Rm = BITS(inst, 0, 3);
1855 inst_cream->Rn = BITS(inst, 16, 19); 1710 inst_cream->Rn = BITS(inst, 16, 19);
1856 inst_cream->Rd = BITS(inst, 12, 15); 1711 inst_cream->Rd = BITS(inst, 12, 15);
1857 inst_cream->op1 = BITS(inst, 20, 21); 1712 inst_cream->op1 = BITS(inst, 20, 21);
1858 inst_cream->op2 = BITS(inst, 5, 7); 1713 inst_cream->op2 = BITS(inst, 5, 7);
1859 1714
1860 return inst_base; 1715 return inst_base;
1861} 1716}
1862static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) 1717static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) {
1863{
1864 return INTERPRETER_TRANSLATE(uqadd8)(inst, index); 1718 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1865} 1719}
1866static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) 1720static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) {
1867{
1868 return INTERPRETER_TRANSLATE(uqadd8)(inst, index); 1721 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1869} 1722}
1870static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) 1723static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) {
1871{
1872 return INTERPRETER_TRANSLATE(uqadd8)(inst, index); 1724 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1873} 1725}
1874static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) 1726static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) {
1875{
1876 return INTERPRETER_TRANSLATE(uqadd8)(inst, index); 1727 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1877} 1728}
1878static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) 1729static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) {
1879{
1880 return INTERPRETER_TRANSLATE(uqadd8)(inst, index); 1730 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
1881} 1731}
1882static ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) 1732static 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)); 1733 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; 1734 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
1886 1735
1887 inst_base->cond = BITS(inst, 28, 31); 1736 inst_base->cond = BITS(inst, 28, 31);
1888 inst_base->idx = index; 1737 inst_base->idx = index;
1889 inst_base->br = TransExtData::NON_BRANCH; 1738 inst_base->br = TransExtData::NON_BRANCH;
1890 1739
1891 inst_cream->op1 = BITS(inst, 20, 24); 1740 inst_cream->op1 = BITS(inst, 20, 24);
1892 inst_cream->op2 = BITS(inst, 5, 7); 1741 inst_cream->op2 = BITS(inst, 5, 7);
1893 inst_cream->Rd = BITS(inst, 16, 19); 1742 inst_cream->Rd = BITS(inst, 16, 19);
1894 inst_cream->Rm = BITS(inst, 8, 11); 1743 inst_cream->Rm = BITS(inst, 8, 11);
1895 inst_cream->Rn = BITS(inst, 0, 3); 1744 inst_cream->Rn = BITS(inst, 0, 3);
1896 inst_cream->Ra = BITS(inst, 12, 15); 1745 inst_cream->Ra = BITS(inst, 12, 15);
1897 1746
1898 return inst_base; 1747 return inst_base;
1899} 1748}
1900static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) 1749static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) {
1901{
1902 return INTERPRETER_TRANSLATE(usada8)(inst, index); 1750 return INTERPRETER_TRANSLATE(usada8)(inst, index);
1903} 1751}
1904static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) 1752static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) {
1905{
1906 return INTERPRETER_TRANSLATE(ssat)(inst, index); 1753 return INTERPRETER_TRANSLATE(ssat)(inst, index);
1907} 1754}
1908static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) 1755static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) {
1909{
1910 return INTERPRETER_TRANSLATE(ssat16)(inst, index); 1756 return INTERPRETER_TRANSLATE(ssat16)(inst, index);
1911} 1757}
1912 1758
1913static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) 1759static 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)); 1760 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; 1761 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
1917 1762
1918 inst_base->cond = BITS(inst, 28, 31); 1763 inst_base->cond = BITS(inst, 28, 31);
1919 inst_base->idx = index; 1764 inst_base->idx = index;
1920 inst_base->br = TransExtData::NON_BRANCH; 1765 inst_base->br = TransExtData::NON_BRANCH;
1921 1766
1922 inst_cream->Rm = BITS(inst, 0, 3); 1767 inst_cream->Rm = BITS(inst, 0, 3);
1923 inst_cream->Rn = BITS(inst, 16, 19); 1768 inst_cream->Rn = BITS(inst, 16, 19);
1924 inst_cream->Rd = BITS(inst, 12, 15); 1769 inst_cream->Rd = BITS(inst, 12, 15);
1925 inst_cream->rotate = BITS(inst, 10, 11); 1770 inst_cream->rotate = BITS(inst, 10, 11);
1926 1771
1927 return inst_base; 1772 return inst_base;
1928} 1773}
1929static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) 1774static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) {
1930{
1931 return INTERPRETER_TRANSLATE(uxtab16)(inst, index); 1775 return INTERPRETER_TRANSLATE(uxtab16)(inst, index);
1932} 1776}
1933 1777
1934static ARM_INST_PTR INTERPRETER_TRANSLATE(wfe)(unsigned int inst, int index) 1778static ARM_INST_PTR INTERPRETER_TRANSLATE(wfe)(unsigned int inst, int index) {
1935{
1936 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); 1779 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
1937 1780
1938 inst_base->cond = BITS(inst, 28, 31); 1781 inst_base->cond = BITS(inst, 28, 31);
1939 inst_base->idx = index; 1782 inst_base->idx = index;
1940 inst_base->br = TransExtData::NON_BRANCH; 1783 inst_base->br = TransExtData::NON_BRANCH;
1941 1784
1942 return inst_base; 1785 return inst_base;
1943} 1786}
1944static ARM_INST_PTR INTERPRETER_TRANSLATE(wfi)(unsigned int inst, int index) 1787static ARM_INST_PTR INTERPRETER_TRANSLATE(wfi)(unsigned int inst, int index) {
1945{
1946 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); 1788 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
1947 1789
1948 inst_base->cond = BITS(inst, 28, 31); 1790 inst_base->cond = BITS(inst, 28, 31);
1949 inst_base->idx = index; 1791 inst_base->idx = index;
1950 inst_base->br = TransExtData::NON_BRANCH; 1792 inst_base->br = TransExtData::NON_BRANCH;
1951 1793
1952 return inst_base; 1794 return inst_base;
1953} 1795}
1954static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) 1796static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index) {
1955{
1956 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst)); 1797 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
1957 1798
1958 inst_base->cond = BITS(inst, 28, 31); 1799 inst_base->cond = BITS(inst, 28, 31);
1959 inst_base->idx = index; 1800 inst_base->idx = index;
1960 inst_base->br = TransExtData::NON_BRANCH; 1801 inst_base->br = TransExtData::NON_BRANCH;
1961 1802
1962 return inst_base; 1803 return inst_base;
1963} 1804}
@@ -1968,211 +1809,79 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index)
1968#undef VFP_INTERPRETER_TRANS 1809#undef VFP_INTERPRETER_TRANS
1969 1810
1970const transop_fp_t arm_instruction_trans[] = { 1811const transop_fp_t arm_instruction_trans[] = {
1971 INTERPRETER_TRANSLATE(vmla), 1812 INTERPRETER_TRANSLATE(vmla), INTERPRETER_TRANSLATE(vmls), INTERPRETER_TRANSLATE(vnmla),
1972 INTERPRETER_TRANSLATE(vmls), 1813 INTERPRETER_TRANSLATE(vnmls), INTERPRETER_TRANSLATE(vnmul), INTERPRETER_TRANSLATE(vmul),
1973 INTERPRETER_TRANSLATE(vnmla), 1814 INTERPRETER_TRANSLATE(vadd), INTERPRETER_TRANSLATE(vsub), INTERPRETER_TRANSLATE(vdiv),
1974 INTERPRETER_TRANSLATE(vnmls), 1815 INTERPRETER_TRANSLATE(vmovi), INTERPRETER_TRANSLATE(vmovr), INTERPRETER_TRANSLATE(vabs),
1975 INTERPRETER_TRANSLATE(vnmul), 1816 INTERPRETER_TRANSLATE(vneg), INTERPRETER_TRANSLATE(vsqrt), INTERPRETER_TRANSLATE(vcmp),
1976 INTERPRETER_TRANSLATE(vmul), 1817 INTERPRETER_TRANSLATE(vcmp2), INTERPRETER_TRANSLATE(vcvtbds), INTERPRETER_TRANSLATE(vcvtbff),
1977 INTERPRETER_TRANSLATE(vadd), 1818 INTERPRETER_TRANSLATE(vcvtbfi), INTERPRETER_TRANSLATE(vmovbrs), INTERPRETER_TRANSLATE(vmsr),
1978 INTERPRETER_TRANSLATE(vsub), 1819 INTERPRETER_TRANSLATE(vmovbrc), INTERPRETER_TRANSLATE(vmrs), INTERPRETER_TRANSLATE(vmovbcr),
1979 INTERPRETER_TRANSLATE(vdiv), 1820 INTERPRETER_TRANSLATE(vmovbrrss), INTERPRETER_TRANSLATE(vmovbrrd), INTERPRETER_TRANSLATE(vstr),
1980 INTERPRETER_TRANSLATE(vmovi), 1821 INTERPRETER_TRANSLATE(vpush), INTERPRETER_TRANSLATE(vstm), INTERPRETER_TRANSLATE(vpop),
1981 INTERPRETER_TRANSLATE(vmovr), 1822 INTERPRETER_TRANSLATE(vldr), INTERPRETER_TRANSLATE(vldm),
1982 INTERPRETER_TRANSLATE(vabs), 1823
1983 INTERPRETER_TRANSLATE(vneg), 1824 INTERPRETER_TRANSLATE(srs), INTERPRETER_TRANSLATE(rfe), INTERPRETER_TRANSLATE(bkpt),
1984 INTERPRETER_TRANSLATE(vsqrt), 1825 INTERPRETER_TRANSLATE(blx), INTERPRETER_TRANSLATE(cps), INTERPRETER_TRANSLATE(pld),
1985 INTERPRETER_TRANSLATE(vcmp), 1826 INTERPRETER_TRANSLATE(setend), INTERPRETER_TRANSLATE(clrex), INTERPRETER_TRANSLATE(rev16),
1986 INTERPRETER_TRANSLATE(vcmp2), 1827 INTERPRETER_TRANSLATE(usad8), INTERPRETER_TRANSLATE(sxtb), INTERPRETER_TRANSLATE(uxtb),
1987 INTERPRETER_TRANSLATE(vcvtbds), 1828 INTERPRETER_TRANSLATE(sxth), INTERPRETER_TRANSLATE(sxtb16), INTERPRETER_TRANSLATE(uxth),
1988 INTERPRETER_TRANSLATE(vcvtbff), 1829 INTERPRETER_TRANSLATE(uxtb16), INTERPRETER_TRANSLATE(cpy), INTERPRETER_TRANSLATE(uxtab),
1989 INTERPRETER_TRANSLATE(vcvtbfi), 1830 INTERPRETER_TRANSLATE(ssub8), INTERPRETER_TRANSLATE(shsub8), INTERPRETER_TRANSLATE(ssubaddx),
1990 INTERPRETER_TRANSLATE(vmovbrs), 1831 INTERPRETER_TRANSLATE(strex), INTERPRETER_TRANSLATE(strexb), INTERPRETER_TRANSLATE(swp),
1991 INTERPRETER_TRANSLATE(vmsr), 1832 INTERPRETER_TRANSLATE(swpb), INTERPRETER_TRANSLATE(ssub16), INTERPRETER_TRANSLATE(ssat16),
1992 INTERPRETER_TRANSLATE(vmovbrc), 1833 INTERPRETER_TRANSLATE(shsubaddx), INTERPRETER_TRANSLATE(qsubaddx),
1993 INTERPRETER_TRANSLATE(vmrs), 1834 INTERPRETER_TRANSLATE(shaddsubx), INTERPRETER_TRANSLATE(shadd8), INTERPRETER_TRANSLATE(shadd16),
1994 INTERPRETER_TRANSLATE(vmovbcr), 1835 INTERPRETER_TRANSLATE(sel), INTERPRETER_TRANSLATE(saddsubx), INTERPRETER_TRANSLATE(sadd8),
1995 INTERPRETER_TRANSLATE(vmovbrrss), 1836 INTERPRETER_TRANSLATE(sadd16), INTERPRETER_TRANSLATE(shsub16), INTERPRETER_TRANSLATE(umaal),
1996 INTERPRETER_TRANSLATE(vmovbrrd), 1837 INTERPRETER_TRANSLATE(uxtab16), INTERPRETER_TRANSLATE(usubaddx), INTERPRETER_TRANSLATE(usub8),
1997 INTERPRETER_TRANSLATE(vstr), 1838 INTERPRETER_TRANSLATE(usub16), INTERPRETER_TRANSLATE(usat16), INTERPRETER_TRANSLATE(usada8),
1998 INTERPRETER_TRANSLATE(vpush), 1839 INTERPRETER_TRANSLATE(uqsubaddx), INTERPRETER_TRANSLATE(uqsub8), INTERPRETER_TRANSLATE(uqsub16),
1999 INTERPRETER_TRANSLATE(vstm), 1840 INTERPRETER_TRANSLATE(uqaddsubx), INTERPRETER_TRANSLATE(uqadd8), INTERPRETER_TRANSLATE(uqadd16),
2000 INTERPRETER_TRANSLATE(vpop), 1841 INTERPRETER_TRANSLATE(sxtab), INTERPRETER_TRANSLATE(uhsubaddx), INTERPRETER_TRANSLATE(uhsub8),
2001 INTERPRETER_TRANSLATE(vldr), 1842 INTERPRETER_TRANSLATE(uhsub16), INTERPRETER_TRANSLATE(uhaddsubx), INTERPRETER_TRANSLATE(uhadd8),
2002 INTERPRETER_TRANSLATE(vldm), 1843 INTERPRETER_TRANSLATE(uhadd16), INTERPRETER_TRANSLATE(uaddsubx), INTERPRETER_TRANSLATE(uadd8),
2003 1844 INTERPRETER_TRANSLATE(uadd16), INTERPRETER_TRANSLATE(sxtah), INTERPRETER_TRANSLATE(sxtab16),
2004 INTERPRETER_TRANSLATE(srs), 1845 INTERPRETER_TRANSLATE(qadd8), INTERPRETER_TRANSLATE(bxj), INTERPRETER_TRANSLATE(clz),
2005 INTERPRETER_TRANSLATE(rfe), 1846 INTERPRETER_TRANSLATE(uxtah), INTERPRETER_TRANSLATE(bx), INTERPRETER_TRANSLATE(rev),
2006 INTERPRETER_TRANSLATE(bkpt), 1847 INTERPRETER_TRANSLATE(blx), INTERPRETER_TRANSLATE(revsh), INTERPRETER_TRANSLATE(qadd),
2007 INTERPRETER_TRANSLATE(blx), 1848 INTERPRETER_TRANSLATE(qadd16), INTERPRETER_TRANSLATE(qaddsubx), INTERPRETER_TRANSLATE(ldrex),
2008 INTERPRETER_TRANSLATE(cps), 1849 INTERPRETER_TRANSLATE(qdadd), INTERPRETER_TRANSLATE(qdsub), INTERPRETER_TRANSLATE(qsub),
2009 INTERPRETER_TRANSLATE(pld), 1850 INTERPRETER_TRANSLATE(ldrexb), INTERPRETER_TRANSLATE(qsub8), INTERPRETER_TRANSLATE(qsub16),
2010 INTERPRETER_TRANSLATE(setend), 1851 INTERPRETER_TRANSLATE(smuad), INTERPRETER_TRANSLATE(smmul), INTERPRETER_TRANSLATE(smusd),
2011 INTERPRETER_TRANSLATE(clrex), 1852 INTERPRETER_TRANSLATE(smlsd), INTERPRETER_TRANSLATE(smlsld), INTERPRETER_TRANSLATE(smmla),
2012 INTERPRETER_TRANSLATE(rev16), 1853 INTERPRETER_TRANSLATE(smmls), INTERPRETER_TRANSLATE(smlald), INTERPRETER_TRANSLATE(smlad),
2013 INTERPRETER_TRANSLATE(usad8), 1854 INTERPRETER_TRANSLATE(smlaw), INTERPRETER_TRANSLATE(smulw), INTERPRETER_TRANSLATE(pkhtb),
2014 INTERPRETER_TRANSLATE(sxtb), 1855 INTERPRETER_TRANSLATE(pkhbt), INTERPRETER_TRANSLATE(smul), INTERPRETER_TRANSLATE(smlalxy),
2015 INTERPRETER_TRANSLATE(uxtb), 1856 INTERPRETER_TRANSLATE(smla), INTERPRETER_TRANSLATE(mcrr), INTERPRETER_TRANSLATE(mrrc),
2016 INTERPRETER_TRANSLATE(sxth), 1857 INTERPRETER_TRANSLATE(cmp), INTERPRETER_TRANSLATE(tst), INTERPRETER_TRANSLATE(teq),
2017 INTERPRETER_TRANSLATE(sxtb16), 1858 INTERPRETER_TRANSLATE(cmn), INTERPRETER_TRANSLATE(smull), INTERPRETER_TRANSLATE(umull),
2018 INTERPRETER_TRANSLATE(uxth), 1859 INTERPRETER_TRANSLATE(umlal), INTERPRETER_TRANSLATE(smlal), INTERPRETER_TRANSLATE(mul),
2019 INTERPRETER_TRANSLATE(uxtb16), 1860 INTERPRETER_TRANSLATE(mla), INTERPRETER_TRANSLATE(ssat), INTERPRETER_TRANSLATE(usat),
2020 INTERPRETER_TRANSLATE(cpy), 1861 INTERPRETER_TRANSLATE(mrs), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(and),
2021 INTERPRETER_TRANSLATE(uxtab), 1862 INTERPRETER_TRANSLATE(bic), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(eor),
2022 INTERPRETER_TRANSLATE(ssub8), 1863 INTERPRETER_TRANSLATE(add), INTERPRETER_TRANSLATE(rsb), INTERPRETER_TRANSLATE(rsc),
2023 INTERPRETER_TRANSLATE(shsub8), 1864 INTERPRETER_TRANSLATE(sbc), INTERPRETER_TRANSLATE(adc), INTERPRETER_TRANSLATE(sub),
2024 INTERPRETER_TRANSLATE(ssubaddx), 1865 INTERPRETER_TRANSLATE(orr), INTERPRETER_TRANSLATE(mvn), INTERPRETER_TRANSLATE(mov),
2025 INTERPRETER_TRANSLATE(strex), 1866 INTERPRETER_TRANSLATE(stm), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(ldrsh),
2026 INTERPRETER_TRANSLATE(strexb), 1867 INTERPRETER_TRANSLATE(stm), INTERPRETER_TRANSLATE(ldm), INTERPRETER_TRANSLATE(ldrsb),
2027 INTERPRETER_TRANSLATE(swp), 1868 INTERPRETER_TRANSLATE(strd), INTERPRETER_TRANSLATE(ldrh), INTERPRETER_TRANSLATE(strh),
2028 INTERPRETER_TRANSLATE(swpb), 1869 INTERPRETER_TRANSLATE(ldrd), INTERPRETER_TRANSLATE(strt), INTERPRETER_TRANSLATE(strbt),
2029 INTERPRETER_TRANSLATE(ssub16), 1870 INTERPRETER_TRANSLATE(ldrbt), INTERPRETER_TRANSLATE(ldrt), INTERPRETER_TRANSLATE(mrc),
2030 INTERPRETER_TRANSLATE(ssat16), 1871 INTERPRETER_TRANSLATE(mcr), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr),
2031 INTERPRETER_TRANSLATE(shsubaddx), 1872 INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr), INTERPRETER_TRANSLATE(msr),
2032 INTERPRETER_TRANSLATE(qsubaddx), 1873 INTERPRETER_TRANSLATE(ldrb), INTERPRETER_TRANSLATE(strb), INTERPRETER_TRANSLATE(ldr),
2033 INTERPRETER_TRANSLATE(shaddsubx), 1874 INTERPRETER_TRANSLATE(ldrcond), INTERPRETER_TRANSLATE(str), INTERPRETER_TRANSLATE(cdp),
2034 INTERPRETER_TRANSLATE(shadd8), 1875 INTERPRETER_TRANSLATE(stc), INTERPRETER_TRANSLATE(ldc), INTERPRETER_TRANSLATE(ldrexd),
2035 INTERPRETER_TRANSLATE(shadd16), 1876 INTERPRETER_TRANSLATE(strexd), INTERPRETER_TRANSLATE(ldrexh), INTERPRETER_TRANSLATE(strexh),
2036 INTERPRETER_TRANSLATE(sel), 1877 INTERPRETER_TRANSLATE(nop), INTERPRETER_TRANSLATE(yield), INTERPRETER_TRANSLATE(wfe),
2037 INTERPRETER_TRANSLATE(saddsubx), 1878 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), 1879 INTERPRETER_TRANSLATE(bbl),
2169 1880
2170 // All the thumb instructions should be placed the end of table 1881 // All the thumb instructions should be placed the end of table
2171 INTERPRETER_TRANSLATE(b_2_thumb), 1882 INTERPRETER_TRANSLATE(b_2_thumb), INTERPRETER_TRANSLATE(b_cond_thumb),
2172 INTERPRETER_TRANSLATE(b_cond_thumb), 1883 INTERPRETER_TRANSLATE(bl_1_thumb), INTERPRETER_TRANSLATE(bl_2_thumb),
2173 INTERPRETER_TRANSLATE(bl_1_thumb), 1884 INTERPRETER_TRANSLATE(blx_1_thumb),
2174 INTERPRETER_TRANSLATE(bl_2_thumb),
2175 INTERPRETER_TRANSLATE(blx_1_thumb)
2176}; 1885};
2177 1886
2178const size_t arm_instruction_trans_len = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); 1887const 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..b1ec90662 100644
--- a/src/core/arm/dyncom/arm_dyncom_trans.h
+++ b/src/core/arm/dyncom/arm_dyncom_trans.h
@@ -1,16 +1,19 @@
1#include <cstddef>
2#include "common/common_types.h"
3
1struct ARMul_State; 4struct ARMul_State;
2typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); 5typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
3 6
4enum class TransExtData { 7enum class TransExtData {
5 COND = (1 << 0), 8 COND = (1 << 0),
6 NON_BRANCH = (1 << 1), 9 NON_BRANCH = (1 << 1),
7 DIRECT_BRANCH = (1 << 2), 10 DIRECT_BRANCH = (1 << 2),
8 INDIRECT_BRANCH = (1 << 3), 11 INDIRECT_BRANCH = (1 << 3),
9 CALL = (1 << 4), 12 CALL = (1 << 4),
10 RET = (1 << 5), 13 RET = (1 << 5),
11 END_OF_PAGE = (1 << 6), 14 END_OF_PAGE = (1 << 6),
12 THUMB = (1 << 7), 15 THUMB = (1 << 7),
13 SINGLE_STEP = (1 << 8) 16 SINGLE_STEP = (1 << 8)
14}; 17};
15 18
16struct arm_inst { 19struct arm_inst {
@@ -106,8 +109,7 @@ struct cps_inst {
106 unsigned int mode; 109 unsigned int mode;
107}; 110};
108 111
109struct clrex_inst { 112struct clrex_inst {};
110};
111 113
112struct cpy_inst { 114struct cpy_inst {
113 unsigned int Rm; 115 unsigned int Rm;
@@ -163,11 +165,9 @@ struct bkpt_inst {
163 u32 imm; 165 u32 imm;
164}; 166};
165 167
166struct stc_inst { 168struct stc_inst {};
167};
168 169
169struct ldc_inst { 170struct ldc_inst {};
170};
171 171
172struct swi_inst { 172struct swi_inst {
173 unsigned int num; 173 unsigned int num;
@@ -369,8 +369,7 @@ struct msr_inst {
369 unsigned int inst; 369 unsigned int inst;
370}; 370};
371 371
372struct pld_inst { 372struct pld_inst {};
373};
374 373
375struct sxtb_inst { 374struct sxtb_inst {
376 unsigned int Rd; 375 unsigned int Rd;
@@ -475,7 +474,7 @@ struct pkh_inst {
475#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 474#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
476#undef VFP_INTERPRETER_STRUCT 475#undef VFP_INTERPRETER_STRUCT
477 476
478typedef void (*get_addr_fp_t)(ARMul_State *cpu, unsigned int inst, unsigned int &virt_addr); 477typedef void (*get_addr_fp_t)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr);
479 478
480struct ldst_inst { 479struct ldst_inst {
481 unsigned int inst; 480 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..1465b074e 100644
--- a/src/core/arm/skyeye_common/armstate.cpp
+++ b/src/core/arm/skyeye_common/armstate.cpp
@@ -3,21 +3,19 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include "common/swap.h"
7#include "common/logging/log.h" 6#include "common/logging/log.h"
8#include "core/memory.h" 7#include "common/swap.h"
9#include "core/arm/skyeye_common/armstate.h" 8#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..1a707ff7e 100644
--- a/src/core/arm/skyeye_common/armstate.h
+++ b/src/core/arm/skyeye_common/armstate.h
@@ -19,80 +19,74 @@
19 19
20#include <array> 20#include <array>
21#include <unordered_map> 21#include <unordered_map>
22
23#include "common/common_types.h" 22#include "common/common_types.h"
24#include "core/arm/skyeye_common/arm_regformat.h" 23#include "core/arm/skyeye_common/arm_regformat.h"
25 24
26// Signal levels 25// Signal levels
27enum { 26enum { LOW = 0, HIGH = 1, LOWHIGH = 1, HIGHLOW = 2 };
28 LOW = 0,
29 HIGH = 1,
30 LOWHIGH = 1,
31 HIGHLOW = 2
32};
33 27
34// Cache types 28// Cache types
35enum { 29enum {
36 NONCACHE = 0, 30 NONCACHE = 0,
37 DATACACHE = 1, 31 DATACACHE = 1,
38 INSTCACHE = 2, 32 INSTCACHE = 2,
39}; 33};
40 34
41// ARM privilege modes 35// ARM privilege modes
42enum PrivilegeMode { 36enum PrivilegeMode {
43 USER32MODE = 16, 37 USER32MODE = 16,
44 FIQ32MODE = 17, 38 FIQ32MODE = 17,
45 IRQ32MODE = 18, 39 IRQ32MODE = 18,
46 SVC32MODE = 19, 40 SVC32MODE = 19,
47 ABORT32MODE = 23, 41 ABORT32MODE = 23,
48 UNDEF32MODE = 27, 42 UNDEF32MODE = 27,
49 SYSTEM32MODE = 31 43 SYSTEM32MODE = 31
50}; 44};
51 45
52// ARM privilege mode register banks 46// ARM privilege mode register banks
53enum { 47enum {
54 USERBANK = 0, 48 USERBANK = 0,
55 FIQBANK = 1, 49 FIQBANK = 1,
56 IRQBANK = 2, 50 IRQBANK = 2,
57 SVCBANK = 3, 51 SVCBANK = 3,
58 ABORTBANK = 4, 52 ABORTBANK = 4,
59 UNDEFBANK = 5, 53 UNDEFBANK = 5,
60 DUMMYBANK = 6, 54 DUMMYBANK = 6,
61 SYSTEMBANK = 7 55 SYSTEMBANK = 7
62}; 56};
63 57
64// Hardware vector addresses 58// Hardware vector addresses
65enum { 59enum {
66 ARMResetV = 0, 60 ARMResetV = 0,
67 ARMUndefinedInstrV = 4, 61 ARMUndefinedInstrV = 4,
68 ARMSWIV = 8, 62 ARMSWIV = 8,
69 ARMPrefetchAbortV = 12, 63 ARMPrefetchAbortV = 12,
70 ARMDataAbortV = 16, 64 ARMDataAbortV = 16,
71 ARMAddrExceptnV = 20, 65 ARMAddrExceptnV = 20,
72 ARMIRQV = 24, 66 ARMIRQV = 24,
73 ARMFIQV = 28, 67 ARMFIQV = 28,
74 ARMErrorV = 32, // This is an offset, not an address! 68 ARMErrorV = 32, // This is an offset, not an address!
75 69
76 ARMul_ResetV = ARMResetV, 70 ARMul_ResetV = ARMResetV,
77 ARMul_UndefinedInstrV = ARMUndefinedInstrV, 71 ARMul_UndefinedInstrV = ARMUndefinedInstrV,
78 ARMul_SWIV = ARMSWIV, 72 ARMul_SWIV = ARMSWIV,
79 ARMul_PrefetchAbortV = ARMPrefetchAbortV, 73 ARMul_PrefetchAbortV = ARMPrefetchAbortV,
80 ARMul_DataAbortV = ARMDataAbortV, 74 ARMul_DataAbortV = ARMDataAbortV,
81 ARMul_AddrExceptnV = ARMAddrExceptnV, 75 ARMul_AddrExceptnV = ARMAddrExceptnV,
82 ARMul_IRQV = ARMIRQV, 76 ARMul_IRQV = ARMIRQV,
83 ARMul_FIQV = ARMFIQV 77 ARMul_FIQV = ARMFIQV
84}; 78};
85 79
86// Coprocessor status values 80// Coprocessor status values
87enum { 81enum {
88 ARMul_FIRST = 0, 82 ARMul_FIRST = 0,
89 ARMul_TRANSFER = 1, 83 ARMul_TRANSFER = 1,
90 ARMul_BUSY = 2, 84 ARMul_BUSY = 2,
91 ARMul_DATA = 3, 85 ARMul_DATA = 3,
92 ARMul_INTERRUPT = 4, 86 ARMul_INTERRUPT = 4,
93 ARMul_DONE = 0, 87 ARMul_DONE = 0,
94 ARMul_CANT = 1, 88 ARMul_CANT = 1,
95 ARMul_INC = 3 89 ARMul_INC = 3
96}; 90};
97 91
98// Instruction condition codes 92// Instruction condition codes
@@ -136,15 +130,13 @@ enum : u32 {
136 130
137// Values for Emulate. 131// Values for Emulate.
138enum { 132enum {
139 STOP = 0, // Stop 133 STOP = 0, // Stop
140 CHANGEMODE = 1, // Change mode 134 CHANGEMODE = 1, // Change mode
141 ONCE = 2, // Execute just one iteration 135 ONCE = 2, // Execute just one iteration
142 RUN = 3 // Continuous execution 136 RUN = 3 // Continuous execution
143}; 137};
144 138
145 139struct ARMul_State final {
146struct ARMul_State final
147{
148public: 140public:
149 explicit ARMul_State(PrivilegeMode initial_mode); 141 explicit ARMul_State(PrivilegeMode initial_mode);
150 142
@@ -193,7 +185,7 @@ public:
193 return TFlag ? 2 : 4; 185 return TFlag ? 2 : 4;
194 } 186 }
195 187
196 std::array<u32, 16> Reg{}; // The current register file 188 std::array<u32, 16> Reg{}; // The current register file
197 std::array<u32, 2> Reg_usr{}; 189 std::array<u32, 2> Reg_usr{};
198 std::array<u32, 2> Reg_svc{}; // R13_SVC R14_SVC 190 std::array<u32, 2> Reg_svc{}; // R13_SVC R14_SVC
199 std::array<u32, 2> Reg_abort{}; // R13_ABORT R14_ABORT 191 std::array<u32, 2> Reg_abort{}; // R13_ABORT R14_ABORT
@@ -216,8 +208,8 @@ public:
216 u32 Spsr_copy; 208 u32 Spsr_copy;
217 u32 phys_pc; 209 u32 phys_pc;
218 210
219 u32 Mode; // The current mode 211 u32 Mode; // The current mode
220 u32 Bank; // The current register bank 212 u32 Bank; // The current register bank
221 213
222 u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed 214 u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
223 unsigned int shifter_carry_out; 215 unsigned int shifter_carry_out;
@@ -243,9 +235,9 @@ public:
243private: 235private:
244 void ResetMPCoreCP15Registers(); 236 void ResetMPCoreCP15Registers();
245 237
246 // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag. 238 // 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 239 // tag. This is the smallest granule allowed by the v7 spec, and is coincidentally just large
248 // support LDR/STREXD. 240 // enough to support LDR/STREXD.
249 static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; 241 static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
250 242
251 u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode 243 u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
diff --git a/src/core/arm/skyeye_common/armsupp.cpp b/src/core/arm/skyeye_common/armsupp.cpp
index 883713e86..06aa1b075 100644
--- a/src/core/arm/skyeye_common/armsupp.cpp
+++ b/src/core/arm/skyeye_common/armsupp.cpp
@@ -16,14 +16,12 @@
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17 17
18#include "common/logging/log.h" 18#include "common/logging/log.h"
19
20#include "core/arm/skyeye_common/arm_regformat.h" 19#include "core/arm/skyeye_common/arm_regformat.h"
21#include "core/arm/skyeye_common/armstate.h" 20#include "core/arm/skyeye_common/armstate.h"
22#include "core/arm/skyeye_common/armsupp.h" 21#include "core/arm/skyeye_common/armsupp.h"
23 22
24// Unsigned sum of absolute difference 23// Unsigned sum of absolute difference
25u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) 24u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) {
26{
27 if (left > right) 25 if (left > right)
28 return left - right; 26 return left - right;
29 27
@@ -31,8 +29,8 @@ u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
31} 29}
32 30
33// Add with carry, indicates if a carry-out or signed overflow occurred. 31// 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) 32u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred,
35{ 33 bool* overflow_occurred) {
36 u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; 34 u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in;
37 s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; 35 s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in;
38 u64 result = (unsigned_sum & 0xFFFFFFFF); 36 u64 result = (unsigned_sum & 0xFFFFFFFF);
@@ -47,22 +45,17 @@ u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bo
47} 45}
48 46
49// Compute whether an addition of A and B, giving RESULT, overflowed. 47// Compute whether an addition of A and B, giving RESULT, overflowed.
50bool AddOverflow(u32 a, u32 b, u32 result) 48bool AddOverflow(u32 a, u32 b, u32 result) {
51{ 49 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} 50}
55 51
56// Compute whether a subtraction of A and B, giving RESULT, overflowed. 52// Compute whether a subtraction of A and B, giving RESULT, overflowed.
57bool SubOverflow(u32 a, u32 b, u32 result) 53bool SubOverflow(u32 a, u32 b, u32 result) {
58{ 54 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} 55}
62 56
63// Returns true if the Q flag should be set as a result of overflow. 57// Returns true if the Q flag should be set as a result of overflow.
64bool ARMul_AddOverflowQ(u32 a, u32 b) 58bool ARMul_AddOverflowQ(u32 a, u32 b) {
65{
66 u32 result = a + b; 59 u32 result = a + b;
67 if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0) 60 if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0)
68 return true; 61 return true;
@@ -71,8 +64,7 @@ bool ARMul_AddOverflowQ(u32 a, u32 b)
71} 64}
72 65
73// 8-bit signed saturated addition 66// 8-bit signed saturated addition
74u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) 67u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) {
75{
76 u8 result = left + right; 68 u8 result = left + right;
77 69
78 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) { 70 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) {
@@ -86,8 +78,7 @@ u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
86} 78}
87 79
88// 8-bit signed saturated subtraction 80// 8-bit signed saturated subtraction
89u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) 81u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) {
90{
91 u8 result = left - right; 82 u8 result = left - right;
92 83
93 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) { 84 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) {
@@ -101,8 +92,7 @@ u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
101} 92}
102 93
103// 16-bit signed saturated addition 94// 16-bit signed saturated addition
104u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) 95u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) {
105{
106 u16 result = left + right; 96 u16 result = left + right;
107 97
108 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) { 98 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) {
@@ -116,8 +106,7 @@ u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
116} 106}
117 107
118// 16-bit signed saturated subtraction 108// 16-bit signed saturated subtraction
119u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) 109u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) {
120{
121 u16 result = left - right; 110 u16 result = left - right;
122 111
123 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) { 112 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) {
@@ -131,8 +120,7 @@ u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
131} 120}
132 121
133// 8-bit unsigned saturated addition 122// 8-bit unsigned saturated addition
134u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) 123u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) {
135{
136 u8 result = left + right; 124 u8 result = left + right;
137 125
138 if (result < left) 126 if (result < left)
@@ -142,8 +130,7 @@ u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
142} 130}
143 131
144// 16-bit unsigned saturated addition 132// 16-bit unsigned saturated addition
145u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) 133u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) {
146{
147 u16 result = left + right; 134 u16 result = left + right;
148 135
149 if (result < left) 136 if (result < left)
@@ -153,8 +140,7 @@ u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
153} 140}
154 141
155// 8-bit unsigned saturated subtraction 142// 8-bit unsigned saturated subtraction
156u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) 143u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) {
157{
158 if (left <= right) 144 if (left <= right)
159 return 0; 145 return 0;
160 146
@@ -162,8 +148,7 @@ u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
162} 148}
163 149
164// 16-bit unsigned saturated subtraction 150// 16-bit unsigned saturated subtraction
165u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) 151u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) {
166{
167 if (left <= right) 152 if (left <= right)
168 return 0; 153 return 0;
169 154
@@ -171,16 +156,14 @@ u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
171} 156}
172 157
173// Signed saturation. 158// Signed saturation.
174u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) 159u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) {
175{
176 const u32 max = (1 << shift) - 1; 160 const u32 max = (1 << shift) - 1;
177 const s32 top = (value >> shift); 161 const s32 top = (value >> shift);
178 162
179 if (top > 0) { 163 if (top > 0) {
180 *saturation_occurred = true; 164 *saturation_occurred = true;
181 return max; 165 return max;
182 } 166 } else if (top < -1) {
183 else if (top < -1) {
184 *saturation_occurred = true; 167 *saturation_occurred = true;
185 return ~max; 168 return ~max;
186 } 169 }
@@ -190,8 +173,7 @@ u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
190} 173}
191 174
192// Unsigned saturation 175// Unsigned saturation
193u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) 176u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) {
194{
195 const u32 max = (1 << shift) - 1; 177 const u32 max = (1 << shift) - 1;
196 178
197 if (value < 0) { 179 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..f36c75a07 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -23,20 +23,18 @@
23#include "common/common_funcs.h" 23#include "common/common_funcs.h"
24#include "common/common_types.h" 24#include "common/common_types.h"
25#include "common/logging/log.h" 25#include "common/logging/log.h"
26
27#include "core/arm/skyeye_common/armstate.h" 26#include "core/arm/skyeye_common/armstate.h"
28#include "core/arm/skyeye_common/vfp/asm_vfp.h" 27#include "core/arm/skyeye_common/vfp/asm_vfp.h"
29#include "core/arm/skyeye_common/vfp/vfp.h" 28#include "core/arm/skyeye_common/vfp/vfp.h"
30 29
31void VFPInit(ARMul_State* state) 30void VFPInit(ARMul_State* state) {
32{ 31 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 | 32 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; 33 state->VFP[VFP_FPEXC] = 0;
36 state->VFP[VFP_FPSCR] = 0; 34 state->VFP[VFP_FPSCR] = 0;
37 35
38 // ARM11 MPCore instruction register reset values. 36 // ARM11 MPCore instruction register reset values.
39 state->VFP[VFP_FPINST] = 0xEE000A00; 37 state->VFP[VFP_FPINST] = 0xEE000A00;
40 state->VFP[VFP_FPINST2] = 0; 38 state->VFP[VFP_FPINST2] = 0;
41 39
42 // ARM11 MPCore feature register values. 40 // ARM11 MPCore feature register values.
@@ -44,104 +42,80 @@ void VFPInit(ARMul_State* state)
44 state->VFP[VFP_MVFR1] = 0; 42 state->VFP[VFP_MVFR1] = 0;
45} 43}
46 44
47void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value) 45void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value) {
48{ 46 if (to_arm) {
49 if (to_arm)
50 {
51 *value = state->ExtReg[n]; 47 *value = state->ExtReg[n];
52 } 48 } else {
53 else
54 {
55 state->ExtReg[n] = *value; 49 state->ExtReg[n] = *value;
56 } 50 }
57} 51}
58 52
59void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) 53void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) {
60{ 54 if (to_arm) {
61 if (to_arm) 55 *value2 = state->ExtReg[n * 2 + 1];
62 { 56 *value1 = state->ExtReg[n * 2];
63 *value2 = state->ExtReg[n*2+1]; 57 } else {
64 *value1 = state->ExtReg[n*2]; 58 state->ExtReg[n * 2 + 1] = *value2;
65 } 59 state->ExtReg[n * 2] = *value1;
66 else
67 {
68 state->ExtReg[n*2+1] = *value2;
69 state->ExtReg[n*2] = *value1;
70 } 60 }
71} 61}
72void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) 62void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) {
73{ 63 if (to_arm) {
74 if (to_arm) 64 *value1 = state->ExtReg[n + 0];
75 { 65 *value2 = state->ExtReg[n + 1];
76 *value1 = state->ExtReg[n+0]; 66 } else {
77 *value2 = state->ExtReg[n+1]; 67 state->ExtReg[n + 0] = *value1;
78 } 68 state->ExtReg[n + 1] = *value2;
79 else
80 {
81 state->ExtReg[n+0] = *value1;
82 state->ExtReg[n+1] = *value2;
83 } 69 }
84} 70}
85 71
86void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) 72void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) {
87{ 73 if (single) {
88 if (single)
89 {
90 state->ExtReg[d] = imm; 74 state->ExtReg[d] = imm;
91 } 75 } else {
92 else
93 {
94 /* Check endian please */ 76 /* Check endian please */
95 state->ExtReg[d*2+1] = imm; 77 state->ExtReg[d * 2 + 1] = imm;
96 state->ExtReg[d*2] = 0; 78 state->ExtReg[d * 2] = 0;
97 } 79 }
98} 80}
99void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) 81void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) {
100{ 82 if (single) {
101 if (single)
102 {
103 state->ExtReg[d] = state->ExtReg[m]; 83 state->ExtReg[d] = state->ExtReg[m];
104 } 84 } else {
105 else
106 {
107 /* Check endian please */ 85 /* Check endian please */
108 state->ExtReg[d*2+1] = state->ExtReg[m*2+1]; 86 state->ExtReg[d * 2 + 1] = state->ExtReg[m * 2 + 1];
109 state->ExtReg[d*2] = state->ExtReg[m*2]; 87 state->ExtReg[d * 2] = state->ExtReg[m * 2];
110 } 88 }
111} 89}
112 90
113/* Miscellaneous functions */ 91/* Miscellaneous functions */
114s32 vfp_get_float(ARMul_State* state, unsigned int reg) 92s32 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]); 93 LOG_TRACE(Core_ARM11, "VFP get float: s%d=[%08x]", reg, state->ExtReg[reg]);
117 return state->ExtReg[reg]; 94 return state->ExtReg[reg];
118} 95}
119 96
120void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg) 97void 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); 98 LOG_TRACE(Core_ARM11, "VFP put float: s%d <= [%08x]", reg, val);
123 state->ExtReg[reg] = val; 99 state->ExtReg[reg] = val;
124} 100}
125 101
126u64 vfp_get_double(ARMul_State* state, unsigned int reg) 102u64 vfp_get_double(ARMul_State* state, unsigned int reg) {
127{ 103 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); 104 LOG_TRACE(Core_ARM11, "VFP get double: s[%d-%d]=[%016llx]", reg * 2 + 1, reg * 2, result);
130 return result; 105 return result;
131} 106}
132 107
133void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg) 108void vfp_put_double(ARMul_State* state, u64 val, unsigned int reg) {
134{ 109 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)); 110 (u32)(val >> 32), (u32)(val & 0xffffffff));
136 state->ExtReg[reg*2] = (u32) (val & 0xffffffff); 111 state->ExtReg[reg * 2] = (u32)(val & 0xffffffff);
137 state->ExtReg[reg*2+1] = (u32) (val>>32); 112 state->ExtReg[reg * 2 + 1] = (u32)(val >> 32);
138} 113}
139 114
140/* 115/*
141 * Process bitmask of exception conditions. (from vfpmodule.c) 116 * Process bitmask of exception conditions. (from vfpmodule.c)
142 */ 117 */
143void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) 118void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpscr) {
144{
145 LOG_TRACE(Core_ARM11, "VFP: raising exceptions %08x", exceptions); 119 LOG_TRACE(Core_ARM11, "VFP: raising exceptions %08x", exceptions);
146 120
147 if (exceptions == VFP_EXCEPTION_ERROR) { 121 if (exceptions == VFP_EXCEPTION_ERROR) {
@@ -154,8 +128,8 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc
154 * Comparison instructions always return at least one of 128 * Comparison instructions always return at least one of
155 * these flags set. 129 * these flags set.
156 */ 130 */
157 if (exceptions & (FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG)) 131 if (exceptions & (FPSCR_NFLAG | FPSCR_ZFLAG | FPSCR_CFLAG | FPSCR_VFLAG))
158 fpscr &= ~(FPSCR_NFLAG|FPSCR_ZFLAG|FPSCR_CFLAG|FPSCR_VFLAG); 132 fpscr &= ~(FPSCR_NFLAG | FPSCR_ZFLAG | FPSCR_CFLAG | FPSCR_VFLAG);
159 133
160 fpscr |= exceptions; 134 fpscr |= exceptions;
161 135
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..2886f351f 100644
--- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
@@ -53,24 +53,20 @@
53 53
54#include <algorithm> 54#include <algorithm>
55#include "common/logging/log.h" 55#include "common/logging/log.h"
56#include "core/arm/skyeye_common/vfp/asm_vfp.h"
56#include "core/arm/skyeye_common/vfp/vfp.h" 57#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/vfp_helper.h"
58#include "core/arm/skyeye_common/vfp/asm_vfp.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..1590d89a4 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -53,29 +53,23 @@
53 53
54#include <algorithm> 54#include <algorithm>
55#include <cinttypes> 55#include <cinttypes>
56
57#include "common/common_funcs.h" 56#include "common/common_funcs.h"
58#include "common/common_types.h" 57#include "common/common_types.h"
59#include "common/logging/log.h" 58#include "common/logging/log.h"
60
61#include "core/arm/skyeye_common/vfp/vfp_helper.h"
62#include "core/arm/skyeye_common/vfp/asm_vfp.h" 59#include "core/arm/skyeye_common/vfp/asm_vfp.h"
63#include "core/arm/skyeye_common/vfp/vfp.h" 60#include "core/arm/skyeye_common/vfp/vfp.h"
61#include "core/arm/skyeye_common/vfp/vfp_helper.h"
64 62
65static struct vfp_single vfp_single_default_qnan = { 63static struct vfp_single vfp_single_default_qnan = {
66 255, 64 255, 0, VFP_SINGLE_SIGNIFICAND_QNAN,
67 0,
68 VFP_SINGLE_SIGNIFICAND_QNAN,
69}; 65};
70 66
71static void vfp_single_dump(const char *str, struct vfp_single *s) 67static void vfp_single_dump(const char* str, struct vfp_single* s) {
72{ 68 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", 69 s->exponent, s->significand);
74 str, s->sign != 0, s->exponent, s->significand);
75} 70}
76 71
77static void vfp_single_normalise_denormal(struct vfp_single *vs) 72static void vfp_single_normalise_denormal(struct vfp_single* vs) {
78{
79 int bits = 31 - fls(vs->significand); 73 int bits = 31 - fls(vs->significand);
80 74
81 vfp_single_dump("normalise_denormal: in", vs); 75 vfp_single_dump("normalise_denormal: in", vs);
@@ -88,9 +82,8 @@ static void vfp_single_normalise_denormal(struct vfp_single *vs)
88 vfp_single_dump("normalise_denormal: out", vs); 82 vfp_single_dump("normalise_denormal: out", vs);
89} 83}
90 84
91 85u32 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) 86 const char* func) {
93{
94 u32 significand, incr, rmode; 87 u32 significand, incr, rmode;
95 int exponent, shift, underflow; 88 int exponent, shift, underflow;
96 u32 exceptions = 0; 89 u32 exceptions = 0;
@@ -199,7 +192,7 @@ u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs,
199 vs->exponent = 253; 192 vs->exponent = 253;
200 vs->significand = 0x7fffffff; 193 vs->significand = 0x7fffffff;
201 } else { 194 } else {
202 vs->exponent = 255; /* infinity */ 195 vs->exponent = 255; /* infinity */
203 vs->significand = 0; 196 vs->significand = 0;
204 } 197 }
205 } else { 198 } else {
@@ -217,8 +210,7 @@ pack:
217 vfp_single_dump("pack: final", vs); 210 vfp_single_dump("pack: final", vs);
218 { 211 {
219 s32 d = vfp_single_pack(vs); 212 s32 d = vfp_single_pack(vs);
220 LOG_TRACE(Core_ARM11, "%s: d(s%d)=%08x exceptions=%08x", func, 213 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); 214 vfp_put_float(state, d, sd);
223 } 215 }
224 216
@@ -229,11 +221,9 @@ pack:
229 * Propagate the NaN, setting exceptions if it is signalling. 221 * Propagate the NaN, setting exceptions if it is signalling.
230 * 'n' is always a NaN. 'm' may be a number, NaN or infinity. 222 * 'n' is always a NaN. 'm' may be a number, NaN or infinity.
231 */ 223 */
232static u32 224static 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, 225 u32 fpscr) {
234 struct vfp_single *vsm, u32 fpscr) 226 struct vfp_single* nan;
235{
236 struct vfp_single *nan;
237 int tn, tm = 0; 227 int tn, tm = 0;
238 228
239 tn = vfp_single_type(vsn); 229 tn = vfp_single_type(vsn);
@@ -270,40 +260,35 @@ vfp_propagate_nan(struct vfp_single *vsd, struct vfp_single *vsn,
270 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG; 260 return tn == VFP_SNAN || tm == VFP_SNAN ? FPSCR_IOC : VFP_NAN_FLAG;
271} 261}
272 262
273
274/* 263/*
275 * Extended operations 264 * Extended operations
276 */ 265 */
277static u32 vfp_single_fabs(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 266static 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); 267 vfp_put_float(state, vfp_single_packed_abs(m), sd);
280 return 0; 268 return 0;
281} 269}
282 270
283static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 271static u32 vfp_single_fcpy(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) {
284{
285 vfp_put_float(state, m, sd); 272 vfp_put_float(state, m, sd);
286 return 0; 273 return 0;
287} 274}
288 275
289static u32 vfp_single_fneg(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) 276static 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); 277 vfp_put_float(state, vfp_single_packed_negate(m), sd);
292 return 0; 278 return 0;
293} 279}
294 280
295static const u16 sqrt_oddadjust[] = { 281static const u16 sqrt_oddadjust[] = {
296 0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0, 282 0x0004, 0x0022, 0x005d, 0x00b1, 0x011d, 0x019f, 0x0236, 0x02e0,
297 0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67 283 0x039c, 0x0468, 0x0545, 0x0631, 0x072b, 0x0832, 0x0946, 0x0a67,
298}; 284};
299 285
300static const u16 sqrt_evenadjust[] = { 286static const u16 sqrt_evenadjust[] = {
301 0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e, 287 0x0a2d, 0x08af, 0x075a, 0x0629, 0x051a, 0x0429, 0x0356, 0x029e,
302 0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002 288 0x0200, 0x0179, 0x0109, 0x00af, 0x0068, 0x0034, 0x0012, 0x0002,
303}; 289};
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..49ac8be6e 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -3,9 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <memory>
6
7#include "common/logging/log.h" 6#include "common/logging/log.h"
8
9#include "core/arm/arm_interface.h" 7#include "core/arm/arm_interface.h"
10#include "core/arm/dynarmic/arm_dynarmic.h" 8#include "core/arm/dynarmic/arm_dynarmic.h"
11#include "core/arm/dyncom/arm_dyncom.h" 9#include "core/arm/dyncom/arm_dyncom.h"
@@ -27,8 +25,8 @@ void RunLoop(int tight_loop) {
27 if (GDBStub::g_server_enabled) { 25 if (GDBStub::g_server_enabled) {
28 GDBStub::HandlePacket(); 26 GDBStub::HandlePacket();
29 27
30 // If the loop is halted and we want to step, use a tiny (1) number of instructions to execute. 28 // If the loop is halted and we want to step, use a tiny (1) number of instructions to
31 // Otherwise get out of the loop function. 29 // execute. Otherwise, get out of the loop function.
32 if (GDBStub::GetCpuHaltFlag()) { 30 if (GDBStub::GetCpuHaltFlag()) {
33 if (GDBStub::GetCpuStepFlag()) { 31 if (GDBStub::GetCpuStepFlag()) {
34 GDBStub::SetCpuStepFlag(false); 32 GDBStub::SetCpuStepFlag(false);
@@ -62,7 +60,7 @@ void SingleStep() {
62} 60}
63 61
64/// Halt the core 62/// Halt the core
65void Halt(const char *msg) { 63void Halt(const char* msg) {
66 // TODO(ShizZy): ImplementMe 64 // TODO(ShizZy): ImplementMe
67} 65}
68 66
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..5220b55ea 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -6,11 +6,9 @@
6#include <cinttypes> 6#include <cinttypes>
7#include <mutex> 7#include <mutex>
8#include <vector> 8#include <vector>
9
10#include "common/chunk_file.h" 9#include "common/chunk_file.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12#include "common/string_util.h" 11#include "common/string_util.h"
13
14#include "core/arm/arm_interface.h" 12#include "core/arm/arm_interface.h"
15#include "core/core.h" 13#include "core/core.h"
16#include "core/core_timing.h" 14#include "core/core_timing.h"
@@ -21,14 +19,11 @@ int g_clock_rate_arm11 = 268123480;
21#define INITIAL_SLICE_LENGTH 20000 19#define INITIAL_SLICE_LENGTH 20000
22#define MAX_SLICE_LENGTH 100000000 20#define MAX_SLICE_LENGTH 100000000
23 21
24namespace CoreTiming 22namespace CoreTiming {
25{ 23struct EventType {
26struct EventType
27{
28 EventType() {} 24 EventType() {}
29 25
30 EventType(TimedCallback cb, const char* n) 26 EventType(TimedCallback cb, const char* n) : callback(cb), name(n) {}
31 : callback(cb), name(n) {}
32 27
33 TimedCallback callback; 28 TimedCallback callback;
34 const char* name; 29 const char* name;
@@ -36,8 +31,7 @@ struct EventType
36 31
37static std::vector<EventType> event_types; 32static std::vector<EventType> event_types;
38 33
39struct BaseEvent 34struct BaseEvent {
40{
41 s64 time; 35 s64 time;
42 u64 userdata; 36 u64 userdata;
43 int type; 37 int type;
@@ -200,7 +194,6 @@ u64 GetIdleTicks() {
200 return (u64)idled_cycles; 194 return (u64)idled_cycles;
201} 195}
202 196
203
204// This is to be called when outside threads, such as the graphics thread, wants to 197// 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. 198// schedule things to be executed on the main thread.
206void ScheduleEvent_Threadsafe(s64 cycles_into_future, int event_type, u64 userdata) { 199void ScheduleEvent_Threadsafe(s64 cycles_into_future, int event_type, u64 userdata) {
@@ -222,12 +215,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 215// 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. 216// in which case the event will get handled immediately, before returning.
224void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata) { 217void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata) {
225 if (false) //Core::IsCPUThread()) 218 if (false) // Core::IsCPUThread())
226 { 219 {
227 std::lock_guard<std::recursive_mutex> lock(external_event_section); 220 std::lock_guard<std::recursive_mutex> lock(external_event_section);
228 event_types[event_type].callback(userdata, 0); 221 event_types[event_type].callback(userdata, 0);
229 } 222 } else
230 else
231 ScheduleEvent_Threadsafe(0, event_type, userdata); 223 ScheduleEvent_Threadsafe(0, event_type, userdata);
232} 224}
233 225
@@ -317,8 +309,7 @@ s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata) {
317 } 309 }
318 } 310 }
319 311
320 if (!ts_first) 312 if (!ts_first) {
321 {
322 ts_last = nullptr; 313 ts_last = nullptr;
323 return result; 314 return result;
324 } 315 }
@@ -369,7 +360,7 @@ void RemoveEvent(int event_type) {
369 return; 360 return;
370 while (first) { 361 while (first) {
371 if (first->type == event_type) { 362 if (first->type == event_type) {
372 Event *next = first->next; 363 Event* next = first->next;
373 FreeEvent(first); 364 FreeEvent(first);
374 first = next; 365 first = next;
375 } else { 366 } else {
@@ -509,7 +500,8 @@ void Advance() {
509void LogPendingEvents() { 500void LogPendingEvents() {
510 Event* event = first; 501 Event* event = first;
511 while (event) { 502 while (event) {
512 //LOG_TRACE(Core_Timing, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer, next->time, next->type); 503 // LOG_TRACE(Core_Timing, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer,
504 // next->time, next->type);
513 event = event->next; 505 event = event->next;
514 } 506 }
515} 507}
@@ -531,7 +523,8 @@ void Idle(int max_idle) {
531 } 523 }
532 } 524 }
533 525
534 LOG_TRACE(Core_Timing, "Idle for %" PRId64 " cycles! (%f ms)", cycles_down, cycles_down / (float)(g_clock_rate_arm11 * 0.001f)); 526 LOG_TRACE(Core_Timing, "Idle for %" PRId64 " cycles! (%f ms)", cycles_down,
527 cycles_down / (float)(g_clock_rate_arm11 * 0.001f));
535 528
536 idled_cycles += cycles_down; 529 idled_cycles += cycles_down;
537 Core::g_app_core->down_count -= cycles_down; 530 Core::g_app_core->down_count -= cycles_down;
@@ -551,7 +544,7 @@ std::string GetScheduledEventsSummary() {
551 if (!name) 544 if (!name)
552 name = "[unknown]"; 545 name = "[unknown]";
553 text += Common::StringFromFormat("%s : %i %08x%08x\n", name, (int)event->time, 546 text += Common::StringFromFormat("%s : %i %08x%08x\n", name, (int)event->time,
554 (u32)(event->userdata >> 32), (u32)(event->userdata)); 547 (u32)(event->userdata >> 32), (u32)(event->userdata));
555 event = event->next; 548 event = event->next;
556 } 549 }
557 return text; 550 return text;
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 3d8a7d0c0..b72a1b500 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -4,7 +4,9 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <functional>
7#include <string> 8#include <string>
9#include "common/common_types.h"
8 10
9// This is a system to schedule events into the emulated machine's future. Time is measured 11// This is a system to schedule events into the emulated machine's future. Time is measured
10// in main CPU clock cycles. 12// in main CPU clock cycles.
@@ -19,10 +21,6 @@
19// inside callback: 21// inside callback:
20// ScheduleEvent(periodInCycles - cycles_late, callback, "whatever") 22// ScheduleEvent(periodInCycles - cycles_late, callback, "whatever")
21 23
22#include <functional>
23
24#include "common/common_types.h"
25
26extern int g_clock_rate_arm11; 24extern int g_clock_rate_arm11;
27 25
28inline s64 msToCycles(int ms) { 26inline s64 msToCycles(int ms) {
@@ -61,12 +59,11 @@ inline u64 cyclesToMs(s64 cycles) {
61 return cycles / (g_clock_rate_arm11 / 1000); 59 return cycles / (g_clock_rate_arm11 / 1000);
62} 60}
63 61
64namespace CoreTiming 62namespace CoreTiming {
65{
66void Init(); 63void Init();
67void Shutdown(); 64void Shutdown();
68 65
69typedef void(*MHzChangeCallback)(); 66typedef void (*MHzChangeCallback)();
70typedef std::function<void(u64 userdata, int cycles_late)> TimedCallback; 67typedef std::function<void(u64 userdata, int cycles_late)> TimedCallback;
71 68
72u64 GetTicks(); 69u64 GetTicks();
@@ -81,7 +78,7 @@ u64 GetGlobalTimeUs();
81 */ 78 */
82int RegisterEvent(const char* name, TimedCallback callback); 79int RegisterEvent(const char* name, TimedCallback callback);
83/// For save states. 80/// For save states.
84void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback); 81void RestoreRegisterEvent(int event_type, const char* name, TimedCallback callback);
85void UnregisterAllEvents(); 82void UnregisterAllEvents();
86 83
87/// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk, 84/// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk,
@@ -128,7 +125,7 @@ void ClearPendingEvents();
128void LogPendingEvents(); 125void LogPendingEvents();
129 126
130/// Warning: not included in save states. 127/// Warning: not included in save states.
131void RegisterAdvanceCallback(void(*callback)(int cycles_executed)); 128void RegisterAdvanceCallback(void (*callback)(int cycles_executed));
132void RegisterMHzChangeCallback(MHzChangeCallback callback); 129void RegisterMHzChangeCallback(MHzChangeCallback callback);
133 130
134std::string GetScheduledEventsSummary(); 131std::string GetScheduledEventsSummary();
diff --git a/src/core/file_sys/archive_backend.cpp b/src/core/file_sys/archive_backend.cpp
index cc0aa7022..1fae0ede0 100644
--- a/src/core/file_sys/archive_backend.cpp
+++ b/src/core/file_sys/archive_backend.cpp
@@ -5,34 +5,28 @@
5#include <cstddef> 5#include <cstddef>
6#include <iomanip> 6#include <iomanip>
7#include <sstream> 7#include <sstream>
8
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10#include "common/string_util.h" 9#include "common/string_util.h"
11
12#include "core/file_sys/archive_backend.h" 10#include "core/file_sys/archive_backend.h"
13#include "core/memory.h" 11#include "core/memory.h"
14 12
15
16namespace FileSys { 13namespace FileSys {
17 14
18Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) { 15Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) {
19 switch (type) { 16 switch (type) {
20 case Binary: 17 case Binary: {
21 {
22 binary.resize(size); 18 binary.resize(size);
23 Memory::ReadBlock(pointer, binary.data(), binary.size()); 19 Memory::ReadBlock(pointer, binary.data(), binary.size());
24 break; 20 break;
25 } 21 }
26 22
27 case Char: 23 case Char: {
28 {
29 string.resize(size - 1); // Data is always null-terminated. 24 string.resize(size - 1); // Data is always null-terminated.
30 Memory::ReadBlock(pointer, &string[0], string.size()); 25 Memory::ReadBlock(pointer, &string[0], string.size());
31 break; 26 break;
32 } 27 }
33 28
34 case Wchar: 29 case Wchar: {
35 {
36 u16str.resize(size / 2 - 1); // Data is always null-terminated. 30 u16str.resize(size / 2 - 1); // Data is always null-terminated.
37 Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t)); 31 Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t));
38 break; 32 break;
@@ -50,8 +44,7 @@ std::string Path::DebugStr() const {
50 return "[Invalid]"; 44 return "[Invalid]";
51 case Empty: 45 case Empty:
52 return "[Empty]"; 46 return "[Empty]";
53 case Binary: 47 case Binary: {
54 {
55 std::stringstream res; 48 std::stringstream res;
56 res << "[Binary: "; 49 res << "[Binary: ";
57 for (unsigned byte : binary) 50 for (unsigned byte : binary)
@@ -73,13 +66,13 @@ std::string Path::AsString() const {
73 case Wchar: 66 case Wchar:
74 return Common::UTF16ToUTF8(u16str); 67 return Common::UTF16ToUTF8(u16str);
75 case Empty: 68 case Empty:
76 return{}; 69 return {};
77 case Invalid: 70 case Invalid:
78 case Binary: 71 case Binary:
79 default: 72 default:
80 // TODO(yuriks): Add assert 73 // TODO(yuriks): Add assert
81 LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!"); 74 LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!");
82 return{}; 75 return {};
83 } 76 }
84} 77}
85 78
@@ -90,12 +83,12 @@ std::u16string Path::AsU16Str() const {
90 case Wchar: 83 case Wchar:
91 return u16str; 84 return u16str;
92 case Empty: 85 case Empty:
93 return{}; 86 return {};
94 case Invalid: 87 case Invalid:
95 case Binary: 88 case Binary:
96 // TODO(yuriks): Add assert 89 // TODO(yuriks): Add assert
97 LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!"); 90 LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!");
98 return{}; 91 return {};
99 } 92 }
100} 93}
101 94
@@ -105,25 +98,23 @@ std::vector<u8> Path::AsBinary() const {
105 return binary; 98 return binary;
106 case Char: 99 case Char:
107 return std::vector<u8>(string.begin(), string.end()); 100 return std::vector<u8>(string.begin(), string.end());
108 case Wchar: 101 case Wchar: {
109 {
110 // use two u8 for each character of u16str 102 // use two u8 for each character of u16str
111 std::vector<u8> to_return(u16str.size() * 2); 103 std::vector<u8> to_return(u16str.size() * 2);
112 for (size_t i = 0; i < u16str.size(); ++i) { 104 for (size_t i = 0; i < u16str.size(); ++i) {
113 u16 tmp_char = u16str.at(i); 105 u16 tmp_char = u16str.at(i);
114 to_return[i*2] = (tmp_char & 0xFF00) >> 8; 106 to_return[i * 2] = (tmp_char & 0xFF00) >> 8;
115 to_return[i*2 + 1] = (tmp_char & 0x00FF); 107 to_return[i * 2 + 1] = (tmp_char & 0x00FF);
116 } 108 }
117 return to_return; 109 return to_return;
118 } 110 }
119 case Empty: 111 case Empty:
120 return{}; 112 return {};
121 case Invalid: 113 case Invalid:
122 default: 114 default:
123 // TODO(yuriks): Add assert 115 // TODO(yuriks): Add assert
124 LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!"); 116 LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!");
125 return{}; 117 return {};
126 } 118 }
127} 119}
128
129} 120}
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h
index 5d91e47f3..d69c3c785 100644
--- a/src/core/file_sys/archive_backend.h
+++ b/src/core/file_sys/archive_backend.h
@@ -8,14 +8,11 @@
8#include <string> 8#include <string>
9#include <utility> 9#include <utility>
10#include <vector> 10#include <vector>
11
12#include "common/bit_field.h" 11#include "common/bit_field.h"
13#include "common/common_types.h" 12#include "common/common_types.h"
14#include "common/swap.h" 13#include "common/swap.h"
15
16#include "core/hle/result.h" 14#include "core/hle/result.h"
17 15
18
19namespace FileSys { 16namespace FileSys {
20 17
21class FileBackend; 18class FileBackend;
@@ -24,10 +21,10 @@ class DirectoryBackend;
24// Path string type 21// Path string type
25enum LowPathType : u32 { 22enum LowPathType : u32 {
26 Invalid = 0, 23 Invalid = 0,
27 Empty = 1, 24 Empty = 1,
28 Binary = 2, 25 Binary = 2,
29 Char = 3, 26 Char = 3,
30 Wchar = 4 27 Wchar = 4,
31}; 28};
32 29
33union Mode { 30union Mode {
@@ -44,7 +41,9 @@ public:
44 Path(std::vector<u8> binary_data) : type(Binary), binary(std::move(binary_data)) {} 41 Path(std::vector<u8> binary_data) : type(Binary), binary(std::move(binary_data)) {}
45 Path(LowPathType type, u32 size, u32 pointer); 42 Path(LowPathType type, u32 size, u32 pointer);
46 43
47 LowPathType GetType() const { return type; } 44 LowPathType GetType() const {
45 return type;
46 }
48 47
49 /** 48 /**
50 * Gets the string representation of the path for debugging 49 * Gets the string representation of the path for debugging
@@ -63,18 +62,18 @@ private:
63 std::u16string u16str; 62 std::u16string u16str;
64}; 63};
65 64
65/// Parameters of the archive, as specified in the Create or Format call.
66struct ArchiveFormatInfo { 66struct ArchiveFormatInfo {
67 u32_le total_size; ///< The pre-defined size of the archive, as specified in the Create or Format call 67 u32_le total_size; ///< The pre-defined size of the archive.
68 u32_le number_directories; ///< The pre-defined number of directories in the archive, as specified in the Create or Format call 68 u32_le number_directories; ///< The pre-defined number of directories in the archive.
69 u32_le number_files; ///< The pre-defined number of files in the archive, as specified in the Create or Format call 69 u32_le number_files; ///< The pre-defined number of files in the archive.
70 u8 duplicate_data; ///< Whether the archive should duplicate the data, as specified in the Create or Format call 70 u8 duplicate_data; ///< Whether the archive should duplicate the data.
71}; 71};
72static_assert(std::is_pod<ArchiveFormatInfo>::value, "ArchiveFormatInfo is not POD"); 72static_assert(std::is_pod<ArchiveFormatInfo>::value, "ArchiveFormatInfo is not POD");
73 73
74class ArchiveBackend : NonCopyable { 74class ArchiveBackend : NonCopyable {
75public: 75public:
76 virtual ~ArchiveBackend() { 76 virtual ~ArchiveBackend() {}
77 }
78 77
79 /** 78 /**
80 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) 79 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.)
@@ -87,7 +86,8 @@ public:
87 * @param mode Mode to open the file with 86 * @param mode Mode to open the file with
88 * @return Opened file, or error code 87 * @return Opened file, or error code
89 */ 88 */
90 virtual ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const = 0; 89 virtual ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path,
90 const Mode mode) const = 0;
91 91
92 /** 92 /**
93 * Delete a file specified by its path 93 * Delete a file specified by its path
@@ -150,8 +150,7 @@ public:
150 150
151class ArchiveFactory : NonCopyable { 151class ArchiveFactory : NonCopyable {
152public: 152public:
153 virtual ~ArchiveFactory() { 153 virtual ~ArchiveFactory() {}
154 }
155 154
156 /** 155 /**
157 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) 156 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.)
diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp
index 1d9eaefcb..e1d29efd3 100644
--- a/src/core/file_sys/archive_extsavedata.cpp
+++ b/src/core/file_sys/archive_extsavedata.cpp
@@ -5,12 +5,10 @@
5#include <algorithm> 5#include <algorithm>
6#include <memory> 6#include <memory>
7#include <vector> 7#include <vector>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "common/file_util.h" 9#include "common/file_util.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12#include "common/string_util.h" 11#include "common/string_util.h"
13
14#include "core/file_sys/archive_extsavedata.h" 12#include "core/file_sys/archive_extsavedata.h"
15#include "core/file_sys/disk_archive.h" 13#include "core/file_sys/disk_archive.h"
16#include "core/hle/service/fs/archive.h" 14#include "core/hle/service/fs/archive.h"
@@ -30,10 +28,11 @@ std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path)
30 28
31std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) { 29std::string GetExtDataContainerPath(const std::string& mount_point, bool shared) {
32 if (shared) 30 if (shared)
33 return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(), SYSTEM_ID.c_str()); 31 return Common::StringFromFormat("%sdata/%s/extdata/", mount_point.c_str(),
32 SYSTEM_ID.c_str());
34 33
35 return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(), 34 return Common::StringFromFormat("%sNintendo 3DS/%s/%s/extdata/", mount_point.c_str(),
36 SYSTEM_ID.c_str(), SDCARD_ID.c_str()); 35 SYSTEM_ID.c_str(), SDCARD_ID.c_str());
37} 36}
38 37
39Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) { 38Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) {
@@ -54,11 +53,12 @@ Path ConstructExtDataBinaryPath(u32 media_type, u32 high, u32 low) {
54 for (unsigned i = 0; i < 4; ++i) 53 for (unsigned i = 0; i < 4; ++i)
55 binary_path.push_back((high >> (8 * i)) & 0xFF); 54 binary_path.push_back((high >> (8 * i)) & 0xFF);
56 55
57 return { binary_path }; 56 return {binary_path};
58} 57}
59 58
60ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location, bool shared) 59ArchiveFactory_ExtSaveData::ArchiveFactory_ExtSaveData(const std::string& mount_location,
61 : shared(shared), mount_point(GetExtDataContainerPath(mount_location, shared)) { 60 bool shared)
61 : shared(shared), mount_point(GetExtDataContainerPath(mount_location, shared)) {
62 LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str()); 62 LOG_INFO(Service_FS, "Directory %s set as base for ExtSaveData.", mount_point.c_str());
63} 63}
64 64
@@ -88,7 +88,8 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons
88 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 88 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
89} 89}
90 90
91ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 91ResultCode ArchiveFactory_ExtSaveData::Format(const Path& path,
92 const FileSys::ArchiveFormatInfo& format_info) {
92 // These folders are always created with the ExtSaveData 93 // These folders are always created with the ExtSaveData
93 std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/"; 94 std::string user_path = GetExtSaveDataPath(mount_point, path) + "user/";
94 std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/"; 95 std::string boss_path = GetExtSaveDataPath(mount_point, path) + "boss/";
@@ -115,7 +116,8 @@ ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Pat
115 if (!file.IsOpen()) { 116 if (!file.IsOpen()) {
116 LOG_ERROR(Service_FS, "Could not open metadata information for archive"); 117 LOG_ERROR(Service_FS, "Could not open metadata information for archive");
117 // TODO(Subv): Verify error code 118 // TODO(Subv): Verify error code
118 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); 119 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
120 ErrorSummary::InvalidState, ErrorLevel::Status);
119 } 121 }
120 122
121 ArchiveFormatInfo info = {}; 123 ArchiveFormatInfo info = {};
@@ -123,7 +125,8 @@ ResultVal<ArchiveFormatInfo> ArchiveFactory_ExtSaveData::GetFormatInfo(const Pat
123 return MakeResult<ArchiveFormatInfo>(info); 125 return MakeResult<ArchiveFormatInfo>(info);
124} 126}
125 127
126void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data, size_t icon_size) { 128void ArchiveFactory_ExtSaveData::WriteIcon(const Path& path, const u8* icon_data,
129 size_t icon_size) {
127 std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path); 130 std::string game_path = FileSys::GetExtSaveDataPath(GetMountPoint(), path);
128 FileUtil::IOFile icon_file(game_path + "icon", "wb"); 131 FileUtil::IOFile icon_file(game_path + "icon", "wb");
129 icon_file.WriteBytes(icon_data, icon_size); 132 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..6a3431e94 100644
--- a/src/core/file_sys/archive_extsavedata.h
+++ b/src/core/file_sys/archive_extsavedata.h
@@ -6,9 +6,7 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11
12#include "core/file_sys/archive_backend.h" 10#include "core/file_sys/archive_backend.h"
13#include "core/hle/result.h" 11#include "core/hle/result.h"
14 12
@@ -28,13 +26,17 @@ public:
28 */ 26 */
29 bool Initialize(); 27 bool Initialize();
30 28
31 std::string GetName() const override { return "ExtSaveData"; } 29 std::string GetName() const override {
30 return "ExtSaveData";
31 }
32 32
33 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; 33 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
34 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 34 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
35 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; 35 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
36 36
37 const std::string& GetMountPoint() const { return mount_point; } 37 const std::string& GetMountPoint() const {
38 return mount_point;
39 }
38 40
39 /** 41 /**
40 * Writes the SMDH icon of the ExtSaveData to file 42 * Writes the SMDH icon of the ExtSaveData to file
@@ -45,7 +47,8 @@ public:
45 void WriteIcon(const Path& path, const u8* icon_data, size_t icon_size); 47 void WriteIcon(const Path& path, const u8* icon_data, size_t icon_size);
46 48
47private: 49private:
48 bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData archive 50 bool shared; ///< Whether this archive represents an ExtSaveData archive or a SharedExtSaveData
51 /// archive
49 52
50 /** 53 /**
51 * This holds the full directory path for this archive, it is only set after a successful call 54 * This holds the full directory path for this archive, it is only set after a successful call
@@ -65,7 +68,8 @@ private:
65std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path); 68std::string GetExtSaveDataPath(const std::string& mount_point, const Path& path);
66 69
67/** 70/**
68 * Constructs a path to the base folder to hold concrete ExtSaveData archives in the host file system. 71 * Constructs a path to the base folder to hold concrete ExtSaveData archives in the host file
72 * system.
69 * @param mount_point The base folder where this folder resides, ie. SDMC or NAND. 73 * @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. 74 * @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 75 * @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..6c99ca5b4 100644
--- a/src/core/file_sys/archive_romfs.cpp
+++ b/src/core/file_sys/archive_romfs.cpp
@@ -4,10 +4,8 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <memory> 6#include <memory>
7
8#include "common/common_types.h" 7#include "common/common_types.h"
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10
11#include "core/file_sys/archive_romfs.h" 9#include "core/file_sys/archive_romfs.h"
12#include "core/file_sys/ivfc_archive.h" 10#include "core/file_sys/ivfc_archive.h"
13 11
@@ -28,11 +26,12 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_RomFS::Open(const Path
28 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 26 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
29} 27}
30 28
31ResultCode ArchiveFactory_RomFS::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 29ResultCode ArchiveFactory_RomFS::Format(const Path& path,
30 const FileSys::ArchiveFormatInfo& format_info) {
32 LOG_ERROR(Service_FS, "Attempted to format a RomFS archive."); 31 LOG_ERROR(Service_FS, "Attempted to format a RomFS archive.");
33 // TODO: Verify error code 32 // TODO: Verify error code
34 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, 33 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported,
35 ErrorSummary::NotSupported, ErrorLevel::Permanent); 34 ErrorLevel::Permanent);
36} 35}
37 36
38ResultVal<ArchiveFormatInfo> ArchiveFactory_RomFS::GetFormatInfo(const Path& path) const { 37ResultVal<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..8a8082a05 100644
--- a/src/core/file_sys/archive_romfs.h
+++ b/src/core/file_sys/archive_romfs.h
@@ -7,9 +7,7 @@
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9#include <vector> 9#include <vector>
10
11#include "common/common_types.h" 10#include "common/common_types.h"
12
13#include "core/file_sys/archive_backend.h" 11#include "core/file_sys/archive_backend.h"
14#include "core/hle/result.h" 12#include "core/hle/result.h"
15#include "core/loader/loader.h" 13#include "core/loader/loader.h"
@@ -24,7 +22,9 @@ class ArchiveFactory_RomFS final : public ArchiveFactory {
24public: 22public:
25 ArchiveFactory_RomFS(Loader::AppLoader& app_loader); 23 ArchiveFactory_RomFS(Loader::AppLoader& app_loader);
26 24
27 std::string GetName() const override { return "RomFS"; } 25 std::string GetName() const override {
26 return "RomFS";
27 }
28 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; 28 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
29 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 29 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
30 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; 30 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..6711035ec 100644
--- a/src/core/file_sys/archive_savedata.cpp
+++ b/src/core/file_sys/archive_savedata.cpp
@@ -4,12 +4,10 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <memory> 6#include <memory>
7
8#include "common/common_types.h" 7#include "common/common_types.h"
9#include "common/file_util.h" 8#include "common/file_util.h"
10#include "common/logging/log.h" 9#include "common/logging/log.h"
11#include "common/string_util.h" 10#include "common/string_util.h"
12
13#include "core/file_sys/archive_savedata.h" 11#include "core/file_sys/archive_savedata.h"
14#include "core/file_sys/disk_archive.h" 12#include "core/file_sys/disk_archive.h"
15#include "core/hle/kernel/process.h" 13#include "core/hle/kernel/process.h"
@@ -22,48 +20,54 @@ namespace FileSys {
22 20
23static std::string GetSaveDataContainerPath(const std::string& sdmc_directory) { 21static std::string GetSaveDataContainerPath(const std::string& sdmc_directory) {
24 return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(), 22 return Common::StringFromFormat("%sNintendo 3DS/%s/%s/title/", sdmc_directory.c_str(),
25 SYSTEM_ID.c_str(), SDCARD_ID.c_str()); 23 SYSTEM_ID.c_str(), SDCARD_ID.c_str());
26} 24}
27 25
28static std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) { 26static std::string GetSaveDataPath(const std::string& mount_location, u64 program_id) {
29 u32 high = (u32)(program_id >> 32); 27 u32 high = (u32)(program_id >> 32);
30 u32 low = (u32)(program_id & 0xFFFFFFFF); 28 u32 low = (u32)(program_id & 0xFFFFFFFF);
31 return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high, low); 29 return Common::StringFromFormat("%s%08x/%08x/data/00000001/", mount_location.c_str(), high,
30 low);
32} 31}
33 32
34static std::string GetSaveDataMetadataPath(const std::string& mount_location, u64 program_id) { 33static std::string GetSaveDataMetadataPath(const std::string& mount_location, u64 program_id) {
35 u32 high = (u32)(program_id >> 32); 34 u32 high = (u32)(program_id >> 32);
36 u32 low = (u32)(program_id & 0xFFFFFFFF); 35 u32 low = (u32)(program_id & 0xFFFFFFFF);
37 return Common::StringFromFormat("%s%08x/%08x/data/00000001.metadata", mount_location.c_str(), high, low); 36 return Common::StringFromFormat("%s%08x/%08x/data/00000001.metadata", mount_location.c_str(),
37 high, low);
38} 38}
39 39
40ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory) 40ArchiveFactory_SaveData::ArchiveFactory_SaveData(const std::string& sdmc_directory)
41 : mount_point(GetSaveDataContainerPath(sdmc_directory)) { 41 : mount_point(GetSaveDataContainerPath(sdmc_directory)) {
42 LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str()); 42 LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str());
43} 43}
44 44
45ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) { 45ResultVal<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); 46 std::string concrete_mount_point =
47 GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id);
47 if (!FileUtil::Exists(concrete_mount_point)) { 48 if (!FileUtil::Exists(concrete_mount_point)) {
48 // When a SaveData archive is created for the first time, it is not yet formatted 49 // When a SaveData archive is created for the first time, it is not yet formatted and the
49 // and the save file/directory structure expected by the game has not yet been initialized. 50 // 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 51 // Returning the NotFormatted error code will signal the game to provision the SaveData
51 // with the files and folders that it expects. 52 // archive with the files and folders that it expects.
52 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, 53 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
53 ErrorSummary::InvalidState, ErrorLevel::Status); 54 ErrorSummary::InvalidState, ErrorLevel::Status);
54 } 55 }
55 56
56 auto archive = std::make_unique<DiskArchive>(std::move(concrete_mount_point)); 57 auto archive = std::make_unique<DiskArchive>(std::move(concrete_mount_point));
57 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 58 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
58} 59}
59 60
60ResultCode ArchiveFactory_SaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 61ResultCode ArchiveFactory_SaveData::Format(const Path& path,
61 std::string concrete_mount_point = GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id); 62 const FileSys::ArchiveFormatInfo& format_info) {
63 std::string concrete_mount_point =
64 GetSaveDataPath(mount_point, Kernel::g_current_process->codeset->program_id);
62 FileUtil::DeleteDirRecursively(concrete_mount_point); 65 FileUtil::DeleteDirRecursively(concrete_mount_point);
63 FileUtil::CreateFullPath(concrete_mount_point); 66 FileUtil::CreateFullPath(concrete_mount_point);
64 67
65 // Write the format metadata 68 // Write the format metadata
66 std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); 69 std::string metadata_path =
70 GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id);
67 FileUtil::IOFile file(metadata_path, "wb"); 71 FileUtil::IOFile file(metadata_path, "wb");
68 72
69 if (file.IsOpen()) { 73 if (file.IsOpen()) {
@@ -74,13 +78,15 @@ ResultCode ArchiveFactory_SaveData::Format(const Path& path, const FileSys::Arch
74} 78}
75 79
76ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const { 80ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const {
77 std::string metadata_path = GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id); 81 std::string metadata_path =
82 GetSaveDataMetadataPath(mount_point, Kernel::g_current_process->codeset->program_id);
78 FileUtil::IOFile file(metadata_path, "rb"); 83 FileUtil::IOFile file(metadata_path, "rb");
79 84
80 if (!file.IsOpen()) { 85 if (!file.IsOpen()) {
81 LOG_ERROR(Service_FS, "Could not open metadata information for archive"); 86 LOG_ERROR(Service_FS, "Could not open metadata information for archive");
82 // TODO(Subv): Verify error code 87 // TODO(Subv): Verify error code
83 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, ErrorSummary::InvalidState, ErrorLevel::Status); 88 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
89 ErrorSummary::InvalidState, ErrorLevel::Status);
84 } 90 }
85 91
86 ArchiveFormatInfo info = {}; 92 ArchiveFormatInfo info = {};
diff --git a/src/core/file_sys/archive_savedata.h b/src/core/file_sys/archive_savedata.h
index 7a5a24089..6a372865a 100644
--- a/src/core/file_sys/archive_savedata.h
+++ b/src/core/file_sys/archive_savedata.h
@@ -6,7 +6,6 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9
10#include "core/file_sys/archive_backend.h" 9#include "core/file_sys/archive_backend.h"
11#include "core/hle/result.h" 10#include "core/hle/result.h"
12 11
@@ -20,7 +19,9 @@ class ArchiveFactory_SaveData final : public ArchiveFactory {
20public: 19public:
21 ArchiveFactory_SaveData(const std::string& mount_point); 20 ArchiveFactory_SaveData(const std::string& mount_point);
22 21
23 std::string GetName() const override { return "SaveData"; } 22 std::string GetName() const override {
23 return "SaveData";
24 }
24 25
25 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; 26 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
26 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 27 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..6c4542b7d 100644
--- a/src/core/file_sys/archive_savedatacheck.cpp
+++ b/src/core/file_sys/archive_savedatacheck.cpp
@@ -5,12 +5,10 @@
5#include <algorithm> 5#include <algorithm>
6#include <memory> 6#include <memory>
7#include <vector> 7#include <vector>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "common/file_util.h" 9#include "common/file_util.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12#include "common/string_util.h" 11#include "common/string_util.h"
13
14#include "core/file_sys/archive_savedatacheck.h" 12#include "core/file_sys/archive_savedatacheck.h"
15#include "core/file_sys/ivfc_archive.h" 13#include "core/file_sys/ivfc_archive.h"
16#include "core/hle/service/fs/archive.h" 14#include "core/hle/service/fs/archive.h"
@@ -25,13 +23,12 @@ static std::string GetSaveDataCheckContainerPath(const std::string& nand_directo
25} 23}
26 24
27static std::string GetSaveDataCheckPath(const std::string& mount_point, u32 high, u32 low) { 25static std::string GetSaveDataCheckPath(const std::string& mount_point, u32 high, u32 low) {
28 return Common::StringFromFormat("%s%08x/%08x/content/00000000.app.romfs", 26 return Common::StringFromFormat("%s%08x/%08x/content/00000000.app.romfs", mount_point.c_str(),
29 mount_point.c_str(), high, low); 27 high, low);
30} 28}
31 29
32ArchiveFactory_SaveDataCheck::ArchiveFactory_SaveDataCheck(const std::string& nand_directory) : 30ArchiveFactory_SaveDataCheck::ArchiveFactory_SaveDataCheck(const std::string& nand_directory)
33 mount_point(GetSaveDataCheckContainerPath(nand_directory)) { 31 : mount_point(GetSaveDataCheckContainerPath(nand_directory)) {}
34}
35 32
36ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(const Path& path) { 33ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(const Path& path) {
37 auto vec = path.AsBinary(); 34 auto vec = path.AsBinary();
@@ -48,11 +45,12 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(co
48 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 45 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
49} 46}
50 47
51ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 48ResultCode ArchiveFactory_SaveDataCheck::Format(const Path& path,
49 const FileSys::ArchiveFormatInfo& format_info) {
52 LOG_ERROR(Service_FS, "Attempted to format a SaveDataCheck archive."); 50 LOG_ERROR(Service_FS, "Attempted to format a SaveDataCheck archive.");
53 // TODO: Verify error code 51 // TODO: Verify error code
54 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, 52 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported,
55 ErrorSummary::NotSupported, ErrorLevel::Permanent); 53 ErrorLevel::Permanent);
56} 54}
57 55
58ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveDataCheck::GetFormatInfo(const Path& path) const { 56ResultVal<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..e9cafbed9 100644
--- a/src/core/file_sys/archive_savedatacheck.h
+++ b/src/core/file_sys/archive_savedatacheck.h
@@ -6,7 +6,6 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9
10#include "core/file_sys/archive_backend.h" 9#include "core/file_sys/archive_backend.h"
11#include "core/hle/result.h" 10#include "core/hle/result.h"
12 11
@@ -20,7 +19,9 @@ class ArchiveFactory_SaveDataCheck final : public ArchiveFactory {
20public: 19public:
21 ArchiveFactory_SaveDataCheck(const std::string& mount_point); 20 ArchiveFactory_SaveDataCheck(const std::string& mount_point);
22 21
23 std::string GetName() const override { return "SaveDataCheck"; } 22 std::string GetName() const override {
23 return "SaveDataCheck";
24 }
24 25
25 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; 26 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
26 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 27 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..bcb03ed36 100644
--- a/src/core/file_sys/archive_sdmc.cpp
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -4,10 +4,8 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <memory> 6#include <memory>
7
8#include "common/file_util.h" 7#include "common/file_util.h"
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10
11#include "core/file_sys/archive_sdmc.h" 9#include "core/file_sys/archive_sdmc.h"
12#include "core/file_sys/disk_archive.h" 10#include "core/file_sys/disk_archive.h"
13#include "core/settings.h" 11#include "core/settings.h"
@@ -17,7 +15,8 @@
17 15
18namespace FileSys { 16namespace FileSys {
19 17
20ArchiveFactory_SDMC::ArchiveFactory_SDMC(const std::string& sdmc_directory) : sdmc_directory(sdmc_directory) { 18ArchiveFactory_SDMC::ArchiveFactory_SDMC(const std::string& sdmc_directory)
19 : sdmc_directory(sdmc_directory) {
21 LOG_INFO(Service_FS, "Directory %s set as SDMC.", sdmc_directory.c_str()); 20 LOG_INFO(Service_FS, "Directory %s set as SDMC.", sdmc_directory.c_str());
22} 21}
23 22
@@ -40,7 +39,8 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path&
40 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 39 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
41} 40}
42 41
43ResultCode ArchiveFactory_SDMC::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 42ResultCode ArchiveFactory_SDMC::Format(const Path& path,
43 const FileSys::ArchiveFormatInfo& format_info) {
44 // This is kind of an undesirable operation, so let's just ignore it. :) 44 // This is kind of an undesirable operation, so let's just ignore it. :)
45 return RESULT_SUCCESS; 45 return RESULT_SUCCESS;
46} 46}
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h
index 35c0f3725..88e855351 100644
--- a/src/core/file_sys/archive_sdmc.h
+++ b/src/core/file_sys/archive_sdmc.h
@@ -6,7 +6,6 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9
10#include "core/file_sys/archive_backend.h" 9#include "core/file_sys/archive_backend.h"
11#include "core/hle/result.h" 10#include "core/hle/result.h"
12 11
@@ -26,7 +25,9 @@ public:
26 */ 25 */
27 bool Initialize(); 26 bool Initialize();
28 27
29 std::string GetName() const override { return "SDMC"; } 28 std::string GetName() const override {
29 return "SDMC";
30 }
30 31
31 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override; 32 ResultVal<std::unique_ptr<ArchiveBackend>> Open(const Path& path) override;
32 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 33 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..48ebc0ed4 100644
--- a/src/core/file_sys/archive_systemsavedata.cpp
+++ b/src/core/file_sys/archive_systemsavedata.cpp
@@ -5,11 +5,9 @@
5#include <algorithm> 5#include <algorithm>
6#include <memory> 6#include <memory>
7#include <vector> 7#include <vector>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "common/file_util.h" 9#include "common/file_util.h"
11#include "common/string_util.h" 10#include "common/string_util.h"
12
13#include "core/file_sys/archive_systemsavedata.h" 11#include "core/file_sys/archive_systemsavedata.h"
14#include "core/file_sys/disk_archive.h" 12#include "core/file_sys/disk_archive.h"
15#include "core/hle/service/fs/archive.h" 13#include "core/hle/service/fs/archive.h"
@@ -45,25 +43,25 @@ Path ConstructSystemSaveDataBinaryPath(u32 high, u32 low) {
45 for (unsigned i = 0; i < 4; ++i) 43 for (unsigned i = 0; i < 4; ++i)
46 binary_path.push_back((low >> (8 * i)) & 0xFF); 44 binary_path.push_back((low >> (8 * i)) & 0xFF);
47 45
48 return { binary_path }; 46 return {binary_path};
49} 47}
50 48
51ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path) 49ArchiveFactory_SystemSaveData::ArchiveFactory_SystemSaveData(const std::string& nand_path)
52 : base_path(GetSystemSaveDataContainerPath(nand_path)) { 50 : base_path(GetSystemSaveDataContainerPath(nand_path)) {}
53}
54 51
55ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path) { 52ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(const Path& path) {
56 std::string fullpath = GetSystemSaveDataPath(base_path, path); 53 std::string fullpath = GetSystemSaveDataPath(base_path, path);
57 if (!FileUtil::Exists(fullpath)) { 54 if (!FileUtil::Exists(fullpath)) {
58 // TODO(Subv): Check error code, this one is probably wrong 55 // TODO(Subv): Check error code, this one is probably wrong
59 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, 56 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
60 ErrorSummary::InvalidState, ErrorLevel::Status); 57 ErrorSummary::InvalidState, ErrorLevel::Status);
61 } 58 }
62 auto archive = std::make_unique<DiskArchive>(fullpath); 59 auto archive = std::make_unique<DiskArchive>(fullpath);
63 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive)); 60 return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
64} 61}
65 62
66ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) { 63ResultCode ArchiveFactory_SystemSaveData::Format(const Path& path,
64 const FileSys::ArchiveFormatInfo& format_info) {
67 std::string fullpath = GetSystemSaveDataPath(base_path, path); 65 std::string fullpath = GetSystemSaveDataPath(base_path, path);
68 FileUtil::DeleteDirRecursively(fullpath); 66 FileUtil::DeleteDirRecursively(fullpath);
69 FileUtil::CreateFullPath(fullpath); 67 FileUtil::CreateFullPath(fullpath);
diff --git a/src/core/file_sys/archive_systemsavedata.h b/src/core/file_sys/archive_systemsavedata.h
index 2bc13d4ee..a24b89f2b 100644
--- a/src/core/file_sys/archive_systemsavedata.h
+++ b/src/core/file_sys/archive_systemsavedata.h
@@ -6,9 +6,7 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11
12#include "core/file_sys/archive_backend.h" 10#include "core/file_sys/archive_backend.h"
13#include "core/hle/result.h" 11#include "core/hle/result.h"
14 12
@@ -26,7 +24,9 @@ public:
26 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override; 24 ResultCode Format(const Path& path, const FileSys::ArchiveFormatInfo& format_info) override;
27 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override; 25 ResultVal<ArchiveFormatInfo> GetFormatInfo(const Path& path) const override;
28 26
29 std::string GetName() const override { return "SystemSaveData"; } 27 std::string GetName() const override {
28 return "SystemSaveData";
29 }
30 30
31private: 31private:
32 std::string base_path; 32 std::string base_path;
@@ -42,7 +42,8 @@ private:
42std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& path); 42std::string GetSystemSaveDataPath(const std::string& mount_point, const Path& path);
43 43
44/** 44/**
45 * Constructs a path to the base folder to hold concrete SystemSaveData archives in the host file system. 45 * Constructs a path to the base folder to hold concrete SystemSaveData archives in the host file
46 * system.
46 * @param mount_point The base folder where this folder resides, ie. SDMC or NAND. 47 * @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 48 * @returns The path to the base SystemSaveData archives' folder in the host file system
48 */ 49 */
diff --git a/src/core/file_sys/directory_backend.h b/src/core/file_sys/directory_backend.h
index a25dc0cfa..b55e382ef 100644
--- a/src/core/file_sys/directory_backend.h
+++ b/src/core/file_sys/directory_backend.h
@@ -6,7 +6,6 @@
6 6
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11 10
12//////////////////////////////////////////////////////////////////////////////////////////////////// 11////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -19,15 +18,16 @@ const size_t FILENAME_LENGTH = 0x20C / 2;
19struct Entry { 18struct Entry {
20 char16_t filename[FILENAME_LENGTH]; // Entry name (UTF-16, null-terminated) 19 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) 20 std::array<char, 9> short_name; // 8.3 file name ('longfilename' -> 'LONGFI~1', null-terminated)
22 char unknown1; // unknown (observed values: 0x0A, 0x70, 0xFD) 21 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) 22 std::array<char, 4>
24 char unknown2; // unknown (always 0x01) 23 extension; // 8.3 file extension (set to spaces for directories, null-terminated)
25 char unknown3; // unknown (0x00 or 0x08) 24 char unknown2; // unknown (always 0x01)
25 char unknown3; // unknown (0x00 or 0x08)
26 char is_directory; // directory flag 26 char is_directory; // directory flag
27 char is_hidden; // hidden flag 27 char is_hidden; // hidden flag
28 char is_archive; // archive flag 28 char is_archive; // archive flag
29 char is_read_only; // read-only flag 29 char is_read_only; // read-only flag
30 u64 file_size; // file size (for files only) 30 u64 file_size; // file size (for files only)
31}; 31};
32static_assert(sizeof(Entry) == 0x228, "Directory Entry struct isn't exactly 0x228 bytes long!"); 32static_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."); 33static_assert(offsetof(Entry, short_name) == 0x20C, "Wrong offset for short_name in Entry.");
@@ -37,8 +37,8 @@ static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size i
37 37
38class DirectoryBackend : NonCopyable { 38class DirectoryBackend : NonCopyable {
39public: 39public:
40 DirectoryBackend() { } 40 DirectoryBackend() {}
41 virtual ~DirectoryBackend() { } 41 virtual ~DirectoryBackend() {}
42 42
43 /** 43 /**
44 * Open the directory 44 * Open the directory
diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp
index 489cc96fb..0f66998e1 100644
--- a/src/core/file_sys/disk_archive.cpp
+++ b/src/core/file_sys/disk_archive.cpp
@@ -5,11 +5,9 @@
5#include <algorithm> 5#include <algorithm>
6#include <cstdio> 6#include <cstdio>
7#include <memory> 7#include <memory>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "common/file_util.h" 9#include "common/file_util.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12
13#include "core/file_sys/disk_archive.h" 11#include "core/file_sys/disk_archive.h"
14 12
15//////////////////////////////////////////////////////////////////////////////////////////////////// 13////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -17,7 +15,8 @@
17 15
18namespace FileSys { 16namespace FileSys {
19 17
20ResultVal<std::unique_ptr<FileBackend>> DiskArchive::OpenFile(const Path& path, const Mode mode) const { 18ResultVal<std::unique_ptr<FileBackend>> DiskArchive::OpenFile(const Path& path,
19 const Mode mode) const {
21 LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex); 20 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); 21 auto file = std::make_unique<DiskFile>(*this, path, mode);
23 ResultCode result = file->Open(); 22 ResultCode result = file->Open();
@@ -30,15 +29,18 @@ ResultCode DiskArchive::DeleteFile(const Path& path) const {
30 std::string file_path = mount_point + path.AsString(); 29 std::string file_path = mount_point + path.AsString();
31 30
32 if (FileUtil::IsDirectory(file_path)) 31 if (FileUtil::IsDirectory(file_path))
33 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 32 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled,
33 ErrorLevel::Status);
34 34
35 if (!FileUtil::Exists(file_path)) 35 if (!FileUtil::Exists(file_path))
36 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status); 36 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
37 ErrorLevel::Status);
37 38
38 if (FileUtil::Delete(file_path)) 39 if (FileUtil::Delete(file_path))
39 return RESULT_SUCCESS; 40 return RESULT_SUCCESS;
40 41
41 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 42 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled,
43 ErrorLevel::Status);
42} 44}
43 45
44bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const { 46bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const {
@@ -53,10 +55,12 @@ ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u64 size) const {
53 std::string full_path = mount_point + path.AsString(); 55 std::string full_path = mount_point + path.AsString();
54 56
55 if (FileUtil::IsDirectory(full_path)) 57 if (FileUtil::IsDirectory(full_path))
56 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 58 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled,
59 ErrorLevel::Status);
57 60
58 if (FileUtil::Exists(full_path)) 61 if (FileUtil::Exists(full_path))
59 return ResultCode(ErrorDescription::FS_AlreadyExists, ErrorModule::FS, ErrorSummary::NothingHappened, ErrorLevel::Status); 62 return ResultCode(ErrorDescription::FS_AlreadyExists, ErrorModule::FS,
63 ErrorSummary::NothingHappened, ErrorLevel::Status);
60 64
61 if (size == 0) { 65 if (size == 0) {
62 FileUtil::CreateEmptyFile(full_path); 66 FileUtil::CreateEmptyFile(full_path);
@@ -69,10 +73,10 @@ ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u64 size) const {
69 if (file.Seek(size - 1, SEEK_SET) && file.WriteBytes("", 1) == 1) 73 if (file.Seek(size - 1, SEEK_SET) && file.WriteBytes("", 1) == 1)
70 return RESULT_SUCCESS; 74 return RESULT_SUCCESS;
71 75
72 return ResultCode(ErrorDescription::TooLarge, ErrorModule::FS, ErrorSummary::OutOfResource, ErrorLevel::Info); 76 return ResultCode(ErrorDescription::TooLarge, ErrorModule::FS, ErrorSummary::OutOfResource,
77 ErrorLevel::Info);
73} 78}
74 79
75
76bool DiskArchive::CreateDirectory(const Path& path) const { 80bool DiskArchive::CreateDirectory(const Path& path) const {
77 return FileUtil::CreateDir(mount_point + path.AsString()); 81 return FileUtil::CreateDir(mount_point + path.AsString());
78} 82}
@@ -106,17 +110,21 @@ DiskFile::DiskFile(const DiskArchive& archive, const Path& path, const Mode mode
106 110
107ResultCode DiskFile::Open() { 111ResultCode DiskFile::Open() {
108 if (FileUtil::IsDirectory(path)) 112 if (FileUtil::IsDirectory(path))
109 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 113 return ResultCode(ErrorDescription::FS_NotAFile, ErrorModule::FS, ErrorSummary::Canceled,
114 ErrorLevel::Status);
110 115
111 // Specifying only the Create flag is invalid 116 // Specifying only the Create flag is invalid
112 if (mode.create_flag && !mode.read_flag && !mode.write_flag) { 117 if (mode.create_flag && !mode.read_flag && !mode.write_flag) {
113 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 118 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS,
119 ErrorSummary::Canceled, ErrorLevel::Status);
114 } 120 }
115 121
116 if (!FileUtil::Exists(path)) { 122 if (!FileUtil::Exists(path)) {
117 if (!mode.create_flag) { 123 if (!mode.create_flag) {
118 LOG_ERROR(Service_FS, "Non-existing file %s can't be open without mode create.", path.c_str()); 124 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); 125 path.c_str());
126 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS,
127 ErrorSummary::NotFound, ErrorLevel::Status);
120 } else { 128 } else {
121 // Create the file 129 // Create the file
122 FileUtil::CreateEmptyFile(path); 130 FileUtil::CreateEmptyFile(path);
@@ -135,20 +143,24 @@ ResultCode DiskFile::Open() {
135 file = std::make_unique<FileUtil::IOFile>(path, mode_string.c_str()); 143 file = std::make_unique<FileUtil::IOFile>(path, mode_string.c_str());
136 if (file->IsOpen()) 144 if (file->IsOpen())
137 return RESULT_SUCCESS; 145 return RESULT_SUCCESS;
138 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status); 146 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
147 ErrorLevel::Status);
139} 148}
140 149
141ResultVal<size_t> DiskFile::Read(const u64 offset, const size_t length, u8* buffer) const { 150ResultVal<size_t> DiskFile::Read(const u64 offset, const size_t length, u8* buffer) const {
142 if (!mode.read_flag && !mode.write_flag) 151 if (!mode.read_flag && !mode.write_flag)
143 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 152 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS,
153 ErrorSummary::Canceled, ErrorLevel::Status);
144 154
145 file->Seek(offset, SEEK_SET); 155 file->Seek(offset, SEEK_SET);
146 return MakeResult<size_t>(file->ReadBytes(buffer, length)); 156 return MakeResult<size_t>(file->ReadBytes(buffer, length));
147} 157}
148 158
149ResultVal<size_t> DiskFile::Write(const u64 offset, const size_t length, const bool flush, const u8* buffer) const { 159ResultVal<size_t> DiskFile::Write(const u64 offset, const size_t length, const bool flush,
160 const u8* buffer) const {
150 if (!mode.write_flag) 161 if (!mode.write_flag)
151 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, ErrorSummary::Canceled, ErrorLevel::Status); 162 return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS,
163 ErrorSummary::Canceled, ErrorLevel::Status);
152 164
153 file->Seek(offset, SEEK_SET); 165 file->Seek(offset, SEEK_SET);
154 size_t written = file->WriteBytes(buffer, length); 166 size_t written = file->WriteBytes(buffer, length);
@@ -198,7 +210,8 @@ u32 DiskDirectory::Read(const u32 count, Entry* entries) {
198 const std::string& filename = file.virtualName; 210 const std::string& filename = file.virtualName;
199 Entry& entry = entries[entries_read]; 211 Entry& entry = entries[entries_read];
200 212
201 LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, file.isDirectory); 213 LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size,
214 file.isDirectory);
202 215
203 // TODO(Link Mauve): use a proper conversion to UTF-16. 216 // TODO(Link Mauve): use a proper conversion to UTF-16.
204 for (size_t j = 0; j < FILENAME_LENGTH; ++j) { 217 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..2165f27f9 100644
--- a/src/core/file_sys/disk_archive.h
+++ b/src/core/file_sys/disk_archive.h
@@ -8,10 +8,8 @@
8#include <memory> 8#include <memory>
9#include <string> 9#include <string>
10#include <vector> 10#include <vector>
11
12#include "common/common_types.h" 11#include "common/common_types.h"
13#include "common/file_util.h" 12#include "common/file_util.h"
14
15#include "core/file_sys/archive_backend.h" 13#include "core/file_sys/archive_backend.h"
16#include "core/file_sys/directory_backend.h" 14#include "core/file_sys/directory_backend.h"
17#include "core/file_sys/file_backend.h" 15#include "core/file_sys/file_backend.h"
@@ -31,9 +29,12 @@ class DiskArchive : public ArchiveBackend {
31public: 29public:
32 DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) {} 30 DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) {}
33 31
34 virtual std::string GetName() const override { return "DiskArchive: " + mount_point; } 32 virtual std::string GetName() const override {
33 return "DiskArchive: " + mount_point;
34 }
35 35
36 ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const override; 36 ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path,
37 const Mode mode) const override;
37 ResultCode DeleteFile(const Path& path) const override; 38 ResultCode DeleteFile(const Path& path) const override;
38 bool RenameFile(const Path& src_path, const Path& dest_path) const override; 39 bool RenameFile(const Path& src_path, const Path& dest_path) const override;
39 bool DeleteDirectory(const Path& path) const override; 40 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..ed997537f 100644
--- a/src/core/file_sys/file_backend.h
+++ b/src/core/file_sys/file_backend.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <cstddef> 7#include <cstddef>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "core/hle/result.h" 9#include "core/hle/result.h"
11 10
@@ -16,8 +15,8 @@ namespace FileSys {
16 15
17class FileBackend : NonCopyable { 16class FileBackend : NonCopyable {
18public: 17public:
19 FileBackend() { } 18 FileBackend() {}
20 virtual ~FileBackend() { } 19 virtual ~FileBackend() {}
21 20
22 /** 21 /**
23 * Open the file 22 * Open the file
@@ -42,7 +41,8 @@ public:
42 * @param buffer Buffer to read data from 41 * @param buffer Buffer to read data from
43 * @return Number of bytes written, or error code 42 * @return Number of bytes written, or error code
44 */ 43 */
45 virtual ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const = 0; 44 virtual ResultVal<size_t> Write(u64 offset, size_t length, bool flush,
45 const u8* buffer) const = 0;
46 46
47 /** 47 /**
48 * Get the size of the file in bytes 48 * 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..49cc1de10 100644
--- a/src/core/file_sys/ivfc_archive.cpp
+++ b/src/core/file_sys/ivfc_archive.cpp
@@ -4,10 +4,8 @@
4 4
5#include <cstring> 5#include <cstring>
6#include <memory> 6#include <memory>
7
8#include "common/common_types.h" 7#include "common/common_types.h"
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10
11#include "core/file_sys/ivfc_archive.h" 9#include "core/file_sys/ivfc_archive.h"
12 10
13//////////////////////////////////////////////////////////////////////////////////////////////////// 11////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -19,40 +17,49 @@ std::string IVFCArchive::GetName() const {
19 return "IVFC"; 17 return "IVFC";
20} 18}
21 19
22ResultVal<std::unique_ptr<FileBackend>> IVFCArchive::OpenFile(const Path& path, const Mode mode) const { 20ResultVal<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)); 21 const Mode mode) const {
22 return MakeResult<std::unique_ptr<FileBackend>>(
23 std::make_unique<IVFCFile>(romfs_file, data_offset, data_size));
24} 24}
25 25
26ResultCode IVFCArchive::DeleteFile(const Path& path) const { 26ResultCode IVFCArchive::DeleteFile(const Path& path) const {
27 LOG_CRITICAL(Service_FS, "Attempted to delete a file from an IVFC archive (%s).", GetName().c_str()); 27 LOG_CRITICAL(Service_FS, "Attempted to delete a file from an IVFC archive (%s).",
28 GetName().c_str());
28 // TODO(Subv): Verify error code 29 // TODO(Subv): Verify error code
29 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, 30 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, ErrorSummary::Canceled,
30 ErrorSummary::Canceled, ErrorLevel::Status); 31 ErrorLevel::Status);
31} 32}
32 33
33bool IVFCArchive::RenameFile(const Path& src_path, const Path& dest_path) const { 34bool 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()); 35 LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).",
36 GetName().c_str());
35 return false; 37 return false;
36} 38}
37 39
38bool IVFCArchive::DeleteDirectory(const Path& path) const { 40bool IVFCArchive::DeleteDirectory(const Path& path) const {
39 LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive (%s).", GetName().c_str()); 41 LOG_CRITICAL(Service_FS, "Attempted to delete a directory from an IVFC archive (%s).",
42 GetName().c_str());
40 return false; 43 return false;
41} 44}
42 45
43ResultCode IVFCArchive::CreateFile(const Path& path, u64 size) const { 46ResultCode 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()); 47 LOG_CRITICAL(Service_FS, "Attempted to create a file in an IVFC archive (%s).",
48 GetName().c_str());
45 // TODO: Verify error code 49 // TODO: Verify error code
46 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent); 50 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported,
51 ErrorLevel::Permanent);
47} 52}
48 53
49bool IVFCArchive::CreateDirectory(const Path& path) const { 54bool IVFCArchive::CreateDirectory(const Path& path) const {
50 LOG_CRITICAL(Service_FS, "Attempted to create a directory in an IVFC archive (%s).", GetName().c_str()); 55 LOG_CRITICAL(Service_FS, "Attempted to create a directory in an IVFC archive (%s).",
56 GetName().c_str());
51 return false; 57 return false;
52} 58}
53 59
54bool IVFCArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const { 60bool 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()); 61 LOG_CRITICAL(Service_FS, "Attempted to rename a file within an IVFC archive (%s).",
62 GetName().c_str());
56 return false; 63 return false;
57} 64}
58 65
@@ -75,7 +82,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)); 82 return MakeResult<size_t>(romfs_file->ReadBytes(buffer, read_length));
76} 83}
77 84
78ResultVal<size_t> IVFCFile::Write(const u64 offset, const size_t length, const bool flush, const u8* buffer) const { 85ResultVal<size_t> IVFCFile::Write(const u64 offset, const size_t length, const bool flush,
86 const u8* buffer) const {
79 LOG_ERROR(Service_FS, "Attempted to write to IVFC file"); 87 LOG_ERROR(Service_FS, "Attempted to write to IVFC file");
80 // TODO(Subv): Find error code 88 // TODO(Subv): Find error code
81 return MakeResult<size_t>(0); 89 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..0df6cf83a 100644
--- a/src/core/file_sys/ivfc_archive.h
+++ b/src/core/file_sys/ivfc_archive.h
@@ -8,10 +8,8 @@
8#include <memory> 8#include <memory>
9#include <string> 9#include <string>
10#include <vector> 10#include <vector>
11
12#include "common/common_types.h" 11#include "common/common_types.h"
13#include "common/file_util.h" 12#include "common/file_util.h"
14
15#include "core/file_sys/archive_backend.h" 13#include "core/file_sys/archive_backend.h"
16#include "core/file_sys/directory_backend.h" 14#include "core/file_sys/directory_backend.h"
17#include "core/file_sys/file_backend.h" 15#include "core/file_sys/file_backend.h"
@@ -34,7 +32,8 @@ public:
34 32
35 std::string GetName() const override; 33 std::string GetName() const override;
36 34
37 ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path, const Mode mode) const override; 35 ResultVal<std::unique_ptr<FileBackend>> OpenFile(const Path& path,
36 const Mode mode) const override;
38 ResultCode DeleteFile(const Path& path) const override; 37 ResultCode DeleteFile(const Path& path) const override;
39 bool RenameFile(const Path& src_path, const Path& dest_path) const override; 38 bool RenameFile(const Path& src_path, const Path& dest_path) const override;
40 bool DeleteDirectory(const Path& path) const override; 39 bool DeleteDirectory(const Path& path) const override;
@@ -55,13 +54,17 @@ public:
55 IVFCFile(std::shared_ptr<FileUtil::IOFile> file, u64 offset, u64 size) 54 IVFCFile(std::shared_ptr<FileUtil::IOFile> file, u64 offset, u64 size)
56 : romfs_file(file), data_offset(offset), data_size(size) {} 55 : romfs_file(file), data_offset(offset), data_size(size) {}
57 56
58 ResultCode Open() override { return RESULT_SUCCESS; } 57 ResultCode Open() override {
58 return RESULT_SUCCESS;
59 }
59 ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override; 60 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; 61 ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override;
61 u64 GetSize() const override; 62 u64 GetSize() const override;
62 bool SetSize(u64 size) const override; 63 bool SetSize(u64 size) const override;
63 bool Close() const override { return false; } 64 bool Close() const override {
64 void Flush() const override { } 65 return false;
66 }
67 void Flush() const override {}
65 68
66private: 69private:
67 std::shared_ptr<FileUtil::IOFile> romfs_file; 70 std::shared_ptr<FileUtil::IOFile> romfs_file;
@@ -71,9 +74,15 @@ private:
71 74
72class IVFCDirectory : public DirectoryBackend { 75class IVFCDirectory : public DirectoryBackend {
73public: 76public:
74 bool Open() override { return false; } 77 bool Open() override {
75 u32 Read(const u32 count, Entry* entries) override { return 0; } 78 return false;
76 bool Close() const override { return false; } 79 }
80 u32 Read(const u32 count, Entry* entries) override {
81 return 0;
82 }
83 bool Close() const override {
84 return false;
85 }
77}; 86};
78 87
79} // namespace FileSys 88} // namespace FileSys
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 28d403158..7fc72d801 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -10,31 +10,31 @@
10#include <cstdarg> 10#include <cstdarg>
11#include <cstdio> 11#include <cstdio>
12#include <cstring> 12#include <cstring>
13#include <fcntl.h>
14#include <map> 13#include <map>
15#include <numeric> 14#include <numeric>
15#include <fcntl.h>
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..a7483bb10 100644
--- a/src/core/gdbstub/gdbstub.h
+++ b/src/core/gdbstub/gdbstub.h
@@ -6,18 +6,17 @@
6 6
7#pragma once 7#pragma once
8#include <atomic> 8#include <atomic>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11 10
12namespace GDBStub { 11namespace GDBStub {
13 12
14/// Breakpoint Method 13/// Breakpoint Method
15enum class BreakpointType { 14enum class BreakpointType {
16 None, ///< None 15 None, ///< None
17 Execute, ///< Execution Breakpoint 16 Execute, ///< Execution Breakpoint
18 Read, ///< Read Breakpoint 17 Read, ///< Read Breakpoint
19 Write, ///< Write Breakpoint 18 Write, ///< Write Breakpoint
20 Access ///< Access (R/W) Breakpoint 19 Access ///< Access (R/W) Breakpoint
21}; 20};
22 21
23struct BreakpointAddress { 22struct BreakpointAddress {
@@ -25,7 +24,8 @@ struct BreakpointAddress {
25 BreakpointType type; 24 BreakpointType type;
26}; 25};
27 26
28/// If set to false, the server will never be started and no gdbstub-related functions will be executed. 27/// If set to false, the server will never be started and no gdbstub-related functions will be
28/// executed.
29extern std::atomic<bool> g_server_enabled; 29extern std::atomic<bool> g_server_enabled;
30 30
31/** 31/**
@@ -92,5 +92,4 @@ bool GetCpuStepFlag();
92 * @param is_step 92 * @param is_step
93 */ 93 */
94void SetCpuStepFlag(bool is_step); 94void SetCpuStepFlag(bool is_step);
95
96} 95}
diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp
index ccf35fa07..4311d9897 100644
--- a/src/core/hle/applets/applet.cpp
+++ b/src/core/hle/applets/applet.cpp
@@ -6,10 +6,8 @@
6#include <memory> 6#include <memory>
7#include <type_traits> 7#include <type_traits>
8#include <unordered_map> 8#include <unordered_map>
9
10#include "common/assert.h" 9#include "common/assert.h"
11#include "common/common_types.h" 10#include "common/common_types.h"
12
13#include "core/core_timing.h" 11#include "core/core_timing.h"
14#include "core/hle/applets/applet.h" 12#include "core/hle/applets/applet.h"
15#include "core/hle/applets/erreula.h" 13#include "core/hle/applets/erreula.h"
@@ -23,23 +21,24 @@
23// Specializes std::hash for AppletId, so that we can use it in std::unordered_map. 21// 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 22// Workaround for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970
25namespace std { 23namespace std {
26 template <> 24template <>
27 struct hash<Service::APT::AppletId> { 25struct hash<Service::APT::AppletId> {
28 typedef Service::APT::AppletId argument_type; 26 typedef Service::APT::AppletId argument_type;
29 typedef std::size_t result_type; 27 typedef std::size_t result_type;
30 28
31 result_type operator()(const argument_type& id_code) const { 29 result_type operator()(const argument_type& id_code) const {
32 typedef std::underlying_type<argument_type>::type Type; 30 typedef std::underlying_type<argument_type>::type Type;
33 return std::hash<Type>()(static_cast<Type>(id_code)); 31 return std::hash<Type>()(static_cast<Type>(id_code));
34 } 32 }
35 }; 33};
36} 34}
37 35
38namespace HLE { 36namespace HLE {
39namespace Applets { 37namespace Applets {
40 38
41static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets; 39static 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. 40static u32 applet_update_event =
41 -1; ///< The CoreTiming event identifier for the Applet update callback.
43/// The interval at which the Applet update callback will be called, 16.6ms 42/// The interval at which the Applet update callback will be called, 16.6ms
44static const u64 applet_update_interval_us = 16666; 43static const u64 applet_update_interval_us = 16666;
45 44
@@ -60,7 +59,8 @@ ResultCode Applet::Create(Service::APT::AppletId id) {
60 default: 59 default:
61 LOG_ERROR(Service_APT, "Could not create applet %u", id); 60 LOG_ERROR(Service_APT, "Could not create applet %u", id);
62 // TODO(Subv): Find the right error code 61 // TODO(Subv): Find the right error code
63 return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported, ErrorLevel::Permanent); 62 return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet,
63 ErrorSummary::NotSupported, ErrorLevel::Permanent);
64 } 64 }
65 65
66 return RESULT_SUCCESS; 66 return RESULT_SUCCESS;
@@ -84,7 +84,7 @@ static void AppletUpdateEvent(u64 applet_id, int cycles_late) {
84 // If the applet is still running after the last update, reschedule the event 84 // If the applet is still running after the last update, reschedule the event
85 if (applet->IsRunning()) { 85 if (applet->IsRunning()) {
86 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late, 86 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late,
87 applet_update_event, applet_id); 87 applet_update_event, applet_id);
88 } else { 88 } else {
89 // Otherwise the applet has terminated, in which case we should clean it up 89 // Otherwise the applet has terminated, in which case we should clean it up
90 applets[id] = nullptr; 90 applets[id] = nullptr;
@@ -96,7 +96,8 @@ ResultCode Applet::Start(const Service::APT::AppletStartupParameter& parameter)
96 if (result.IsError()) 96 if (result.IsError())
97 return result; 97 return result;
98 // Schedule the update event 98 // Schedule the update event
99 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event, static_cast<u64>(id)); 99 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event,
100 static_cast<u64>(id));
100 return result; 101 return result;
101} 102}
102 103
@@ -116,6 +117,5 @@ void Init() {
116void Shutdown() { 117void Shutdown() {
117 CoreTiming::RemoveEvent(applet_update_event); 118 CoreTiming::RemoveEvent(applet_update_event);
118} 119}
119
120} 120}
121} // namespace 121} // namespace
diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h
index 754c6f7db..bfdcad126 100644
--- a/src/core/hle/applets/applet.h
+++ b/src/core/hle/applets/applet.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8
9#include "core/hle/result.h" 8#include "core/hle/result.h"
10#include "core/hle/service/apt/apt.h" 9#include "core/hle/service/apt/apt.h"
11 10
@@ -14,8 +13,8 @@ namespace Applets {
14 13
15class Applet { 14class Applet {
16public: 15public:
17 virtual ~Applet() { } 16 virtual ~Applet() {}
18 Applet(Service::APT::AppletId id) : id(id) { } 17 Applet(Service::APT::AppletId id) : id(id) {}
19 18
20 /** 19 /**
21 * Creates an instance of the Applet subclass identified by the parameter. 20 * Creates an instance of the Applet subclass identified by the parameter.
@@ -64,7 +63,7 @@ protected:
64 */ 63 */
65 virtual ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) = 0; 64 virtual ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) = 0;
66 65
67 Service::APT::AppletId id; ///< Id of this Applet 66 Service::APT::AppletId id; ///< Id of this Applet
68 std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet 67 std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet
69}; 68};
70 69
@@ -76,6 +75,5 @@ void Init();
76 75
77/// Shuts down the HLE applets 76/// Shuts down the HLE applets
78void Shutdown(); 77void Shutdown();
79
80} 78}
81} // namespace 79} // namespace
diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp
index 92a4b2323..14964427b 100644
--- a/src/core/hle/applets/erreula.cpp
+++ b/src/core/hle/applets/erreula.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/string_util.h" 5#include "common/string_util.h"
6
7#include "core/hle/applets/erreula.h" 6#include "core/hle/applets/erreula.h"
8#include "core/hle/service/apt/apt.h" 7#include "core/hle/service/apt/apt.h"
9 8
@@ -18,7 +17,8 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param
18 return ResultCode(-1); 17 return ResultCode(-1);
19 } 18 }
20 19
21 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. 20 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared
21 // memory.
22 // Create the SharedMemory that will hold the framebuffer data 22 // Create the SharedMemory that will hold the framebuffer data
23 Service::APT::CaptureBufferInfo capture_info; 23 Service::APT::CaptureBufferInfo capture_info;
24 ASSERT(sizeof(capture_info) == parameter.buffer.size()); 24 ASSERT(sizeof(capture_info) == parameter.buffer.size());
@@ -30,9 +30,9 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param
30 // Allocate a heap block of the required size for this applet. 30 // Allocate a heap block of the required size for this applet.
31 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); 31 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
32 // Create a SharedMemory that directly points to this heap block. 32 // Create a SharedMemory that directly points to this heap block.
33 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), 33 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
34 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 34 heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite,
35 "ErrEula Memory"); 35 MemoryPermission::ReadWrite, "ErrEula Memory");
36 36
37 // Send the response message with the newly created SharedMemory 37 // Send the response message with the newly created SharedMemory
38 Service::APT::MessageParameter result; 38 Service::APT::MessageParameter result;
@@ -49,7 +49,8 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param
49ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) { 49ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
50 started = true; 50 started = true;
51 51
52 // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. 52 // TODO(Subv): Set the expected fields in the response buffer before resending it to the
53 // application.
53 // TODO(Subv): Reverse the parameter format for the ErrEula applet 54 // TODO(Subv): Reverse the parameter format for the ErrEula applet
54 55
55 // Let the application know that we're closing 56 // Let the application know that we're closing
@@ -65,8 +66,7 @@ ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parame
65 return RESULT_SUCCESS; 66 return RESULT_SUCCESS;
66} 67}
67 68
68void ErrEula::Update() { 69void ErrEula::Update() {}
69}
70 70
71} // namespace Applets 71} // namespace Applets
72} // namespace HLE 72} // namespace HLE
diff --git a/src/core/hle/applets/erreula.h b/src/core/hle/applets/erreula.h
index 9fe72ae07..a7ec7ec01 100644
--- a/src/core/hle/applets/erreula.h
+++ b/src/core/hle/applets/erreula.h
@@ -12,16 +12,20 @@ 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 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; 17 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
18 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; 18 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
19 void Update() override; 19 void Update() override;
20 bool IsRunning() const override { return started; } 20 bool IsRunning() const override {
21 return started;
22 }
21 23
22 /// This SharedMemory will be created when we receive the LibAppJustStarted message. 24 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
23 /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo 25 /// It holds the framebuffer info retrieved by the application with
26 /// GSPGPU::ImportDisplayCaptureInfo
24 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; 27 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
28
25private: 29private:
26 /// Whether this applet is currently running instead of the host application or not. 30 /// Whether this applet is currently running instead of the host application or not.
27 bool started = false; 31 bool started = false;
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
index 77f01d208..53a8683a4 100644
--- a/src/core/hle/applets/mii_selector.cpp
+++ b/src/core/hle/applets/mii_selector.cpp
@@ -4,16 +4,13 @@
4 4
5#include <cstring> 5#include <cstring>
6#include <string> 6#include <string>
7
8#include "common/assert.h" 7#include "common/assert.h"
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10#include "common/string_util.h" 9#include "common/string_util.h"
11
12#include "core/hle/applets/mii_selector.h" 10#include "core/hle/applets/mii_selector.h"
13#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/shared_memory.h" 12#include "core/hle/kernel/shared_memory.h"
15#include "core/hle/result.h" 13#include "core/hle/result.h"
16
17#include "video_core/video_core.h" 14#include "video_core/video_core.h"
18 15
19//////////////////////////////////////////////////////////////////////////////////////////////////// 16////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -29,7 +26,8 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
29 return ResultCode(-1); 26 return ResultCode(-1);
30 } 27 }
31 28
32 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. 29 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared
30 // memory.
33 // Create the SharedMemory that will hold the framebuffer data 31 // Create the SharedMemory that will hold the framebuffer data
34 Service::APT::CaptureBufferInfo capture_info; 32 Service::APT::CaptureBufferInfo capture_info;
35 ASSERT(sizeof(capture_info) == parameter.buffer.size()); 33 ASSERT(sizeof(capture_info) == parameter.buffer.size());
@@ -40,9 +38,9 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
40 // Allocate a heap block of the required size for this applet. 38 // Allocate a heap block of the required size for this applet.
41 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); 39 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
42 // Create a SharedMemory that directly points to this heap block. 40 // Create a SharedMemory that directly points to this heap block.
43 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), 41 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
44 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 42 heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite,
45 "MiiSelector Memory"); 43 MemoryPermission::ReadWrite, "MiiSelector Memory");
46 44
47 // Send the response message with the newly created SharedMemory 45 // Send the response message with the newly created SharedMemory
48 Service::APT::MessageParameter result; 46 Service::APT::MessageParameter result;
@@ -59,12 +57,14 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
59ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) { 57ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
60 started = true; 58 started = true;
61 59
62 // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. 60 // TODO(Subv): Set the expected fields in the response buffer before resending it to the
61 // application.
63 // TODO(Subv): Reverse the parameter format for the Mii Selector 62 // TODO(Subv): Reverse the parameter format for the Mii Selector
64 63
65 memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); 64 memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
66 65
67 // TODO(Subv): Find more about this structure, result code 0 is enough to let most games continue. 66 // TODO(Subv): Find more about this structure, result code 0 is enough to let most games
67 // continue.
68 MiiResult result; 68 MiiResult result;
69 memset(&result, 0, sizeof(result)); 69 memset(&result, 0, sizeof(result));
70 result.result_code = 0; 70 result.result_code = 0;
@@ -82,8 +82,6 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa
82 return RESULT_SUCCESS; 82 return RESULT_SUCCESS;
83} 83}
84 84
85void MiiSelector::Update() { 85void MiiSelector::Update() {}
86}
87
88} 86}
89} // namespace 87} // namespace
diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h
index 24e8e721d..e3ab9f0cd 100644
--- a/src/core/hle/applets/mii_selector.h
+++ b/src/core/hle/applets/mii_selector.h
@@ -4,9 +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"
9 8#include "common/common_types.h"
10#include "core/hle/applets/applet.h" 9#include "core/hle/applets/applet.h"
11#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/shared_memory.h" 11#include "core/hle/kernel/shared_memory.h"
@@ -17,28 +16,30 @@ namespace HLE {
17namespace Applets { 16namespace Applets {
18 17
19struct MiiConfig { 18struct MiiConfig {
20 u8 unk_000; 19 u8 unk_000;
21 u8 unk_001; 20 u8 unk_001;
22 u8 unk_002; 21 u8 unk_002;
23 u8 unk_003; 22 u8 unk_003;
24 u8 unk_004; 23 u8 unk_004;
25 INSERT_PADDING_BYTES(3); 24 INSERT_PADDING_BYTES(3);
26 u16 unk_008; 25 u16 unk_008;
27 INSERT_PADDING_BYTES(0x82); 26 INSERT_PADDING_BYTES(0x82);
28 u8 unk_08C; 27 u8 unk_08C;
29 INSERT_PADDING_BYTES(3); 28 INSERT_PADDING_BYTES(3);
30 u16 unk_090; 29 u16 unk_090;
31 INSERT_PADDING_BYTES(2); 30 INSERT_PADDING_BYTES(2);
32 u32 unk_094; 31 u32 unk_094;
33 u16 unk_098; 32 u16 unk_098;
34 u8 unk_09A[0x64]; 33 u8 unk_09A[0x64];
35 u8 unk_0FE; 34 u8 unk_0FE;
36 u8 unk_0FF; 35 u8 unk_0FF;
37 u32 unk_100; 36 u32 unk_100;
38}; 37};
39 38
40static_assert(sizeof(MiiConfig) == 0x104, "MiiConfig structure has incorrect size"); 39static_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") 40#define ASSERT_REG_POSITION(field_name, position) \
41 static_assert(offsetof(MiiConfig, field_name) == position, \
42 "Field " #field_name " has invalid position")
42ASSERT_REG_POSITION(unk_008, 0x08); 43ASSERT_REG_POSITION(unk_008, 0x08);
43ASSERT_REG_POSITION(unk_08C, 0x8C); 44ASSERT_REG_POSITION(unk_08C, 0x8C);
44ASSERT_REG_POSITION(unk_090, 0x90); 45ASSERT_REG_POSITION(unk_090, 0x90);
@@ -55,22 +56,27 @@ struct MiiResult {
55 INSERT_PADDING_BYTES(2); 56 INSERT_PADDING_BYTES(2);
56}; 57};
57static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size"); 58static_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") 59#define ASSERT_REG_POSITION(field_name, position) \
60 static_assert(offsetof(MiiResult, field_name) == position, \
61 "Field " #field_name " has invalid position")
59ASSERT_REG_POSITION(unk_0C, 0x0C); 62ASSERT_REG_POSITION(unk_0C, 0x0C);
60ASSERT_REG_POSITION(unk_6C, 0x6C); 63ASSERT_REG_POSITION(unk_6C, 0x6C);
61#undef ASSERT_REG_POSITION 64#undef ASSERT_REG_POSITION
62 65
63class MiiSelector final : public Applet { 66class MiiSelector final : public Applet {
64public: 67public:
65 MiiSelector(Service::APT::AppletId id) : Applet(id), started(false) { } 68 MiiSelector(Service::APT::AppletId id) : Applet(id), started(false) {}
66 69
67 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; 70 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
68 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; 71 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
69 void Update() override; 72 void Update() override;
70 bool IsRunning() const override { return started; } 73 bool IsRunning() const override {
74 return started;
75 }
71 76
72 /// This SharedMemory will be created when we receive the LibAppJustStarted message. 77 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
73 /// 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
74 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; 80 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
75 81
76 /// Whether this applet is currently running instead of the host application or not. 82 /// Whether this applet is currently running instead of the host application or not.
@@ -78,6 +84,5 @@ public:
78 84
79 MiiConfig config; 85 MiiConfig config;
80}; 86};
81
82} 87}
83} // namespace 88} // namespace
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp
index d87bf3d57..06ddf538b 100644
--- a/src/core/hle/applets/swkbd.cpp
+++ b/src/core/hle/applets/swkbd.cpp
@@ -4,19 +4,16 @@
4 4
5#include <cstring> 5#include <cstring>
6#include <string> 6#include <string>
7
8#include "common/assert.h" 7#include "common/assert.h"
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10#include "common/string_util.h" 9#include "common/string_util.h"
11
12#include "core/hle/applets/swkbd.h" 10#include "core/hle/applets/swkbd.h"
13#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/shared_memory.h" 12#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" 13#include "core/hle/result.h"
14#include "core/hle/service/gsp_gpu.h"
15#include "core/hle/service/hid/hid.h"
18#include "core/memory.h" 16#include "core/memory.h"
19
20#include "video_core/video_core.h" 17#include "video_core/video_core.h"
21 18
22//////////////////////////////////////////////////////////////////////////////////////////////////// 19////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -32,7 +29,8 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
32 return ResultCode(-1); 29 return ResultCode(-1);
33 } 30 }
34 31
35 // 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.
36 // Create the SharedMemory that will hold the framebuffer data 34 // Create the SharedMemory that will hold the framebuffer data
37 Service::APT::CaptureBufferInfo capture_info; 35 Service::APT::CaptureBufferInfo capture_info;
38 ASSERT(sizeof(capture_info) == parameter.buffer.size()); 36 ASSERT(sizeof(capture_info) == parameter.buffer.size());
@@ -43,9 +41,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
43 // Allocate a heap block of the required size for this applet. 41 // Allocate a heap block of the required size for this applet.
44 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); 42 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
45 // Create a SharedMemory that directly points to this heap block. 43 // Create a SharedMemory that directly points to this heap block.
46 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), 44 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
47 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 45 heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite,
48 "SoftwareKeyboard Memory"); 46 MemoryPermission::ReadWrite, "SoftwareKeyboard Memory");
49 47
50 // Send the response message with the newly created SharedMemory 48 // Send the response message with the newly created SharedMemory
51 Service::APT::MessageParameter result; 49 Service::APT::MessageParameter result;
@@ -60,10 +58,12 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
60} 58}
61 59
62ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { 60ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) {
63 ASSERT_MSG(parameter.buffer.size() == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); 61 ASSERT_MSG(parameter.buffer.size() == sizeof(config),
62 "The size of the parameter (SoftwareKeyboardConfig) is wrong");
64 63
65 memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); 64 memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
66 text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); 65 text_memory =
66 boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object);
67 67
68 // TODO(Subv): Verify if this is the correct behavior 68 // TODO(Subv): Verify if this is the correct behavior
69 memset(text_memory->GetPointer(), 0, text_memory->size); 69 memset(text_memory->GetPointer(), 0, text_memory->size);
@@ -115,6 +115,5 @@ void SoftwareKeyboard::Finalize() {
115 115
116 started = false; 116 started = false;
117} 117}
118
119} 118}
120} // namespace 119} // namespace
diff --git a/src/core/hle/applets/swkbd.h b/src/core/hle/applets/swkbd.h
index cf26a8fb7..ea0b1fba9 100644
--- a/src/core/hle/applets/swkbd.h
+++ b/src/core/hle/applets/swkbd.h
@@ -4,9 +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"
9 8#include "common/common_types.h"
10#include "core/hle/applets/applet.h" 9#include "core/hle/applets/applet.h"
11#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/shared_memory.h" 11#include "core/hle/kernel/shared_memory.h"
@@ -53,12 +52,14 @@ static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config
53 52
54class SoftwareKeyboard final : public Applet { 53class SoftwareKeyboard final : public Applet {
55public: 54public:
56 SoftwareKeyboard(Service::APT::AppletId id) : Applet(id), started(false) { } 55 SoftwareKeyboard(Service::APT::AppletId id) : Applet(id), started(false) {}
57 56
58 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; 57 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
59 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; 58 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
60 void Update() override; 59 void Update() override;
61 bool IsRunning() const override { return started; } 60 bool IsRunning() const override {
61 return started;
62 }
62 63
63 /** 64 /**
64 * Draws a keyboard to the current bottom screen framebuffer. 65 * Draws a keyboard to the current bottom screen framebuffer.
@@ -72,7 +73,8 @@ public:
72 void Finalize(); 73 void Finalize();
73 74
74 /// This SharedMemory will be created when we receive the LibAppJustStarted message. 75 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
75 /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo 76 /// It holds the framebuffer info retrieved by the application with
77 /// GSPGPU::ImportDisplayCaptureInfo
76 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; 78 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
77 79
78 /// SharedMemory where the output text will be stored 80 /// SharedMemory where the output text will be stored
@@ -84,6 +86,5 @@ public:
84 /// Whether this applet is currently running instead of the host application or not. 86 /// Whether this applet is currently running instead of the host application or not.
85 bool started; 87 bool started;
86}; 88};
87
88} 89}
89} // namespace 90} // namespace
diff --git a/src/core/hle/config_mem.h b/src/core/hle/config_mem.h
index 24a1254f2..42fa6d789 100644
--- a/src/core/hle/config_mem.h
+++ b/src/core/hle/config_mem.h
@@ -12,7 +12,6 @@
12#include "common/common_funcs.h" 12#include "common/common_funcs.h"
13#include "common/common_types.h" 13#include "common/common_types.h"
14#include "common/swap.h" 14#include "common/swap.h"
15
16#include "core/memory.h" 15#include "core/memory.h"
17 16
18//////////////////////////////////////////////////////////////////////////////////////////////////// 17////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -20,16 +19,16 @@
20namespace ConfigMem { 19namespace ConfigMem {
21 20
22struct ConfigMemDef { 21struct ConfigMemDef {
23 u8 kernel_unk; // 0 22 u8 kernel_unk; // 0
24 u8 kernel_version_rev; // 1 23 u8 kernel_version_rev; // 1
25 u8 kernel_version_min; // 2 24 u8 kernel_version_min; // 2
26 u8 kernel_version_maj; // 3 25 u8 kernel_version_maj; // 3
27 u32_le update_flag; // 4 26 u32_le update_flag; // 4
28 u64_le ns_tid; // 8 27 u64_le ns_tid; // 8
29 u32_le sys_core_ver; // 10 28 u32_le sys_core_ver; // 10
30 u8 unit_info; // 14 29 u8 unit_info; // 14
31 u8 boot_firm; // 15 30 u8 boot_firm; // 15
32 u8 prev_firm; // 16 31 u8 prev_firm; // 16
33 INSERT_PADDING_BYTES(0x1); // 17 32 INSERT_PADDING_BYTES(0x1); // 17
34 u32_le ctr_sdk_ver; // 18 33 u32_le ctr_sdk_ver; // 18
35 INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C 34 INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C
@@ -39,15 +38,16 @@ struct ConfigMemDef {
39 u32_le sys_mem_alloc; // 44 38 u32_le sys_mem_alloc; // 44
40 u32_le base_mem_alloc; // 48 39 u32_le base_mem_alloc; // 48
41 INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C 40 INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C
42 u8 firm_unk; // 60 41 u8 firm_unk; // 60
43 u8 firm_version_rev; // 61 42 u8 firm_version_rev; // 61
44 u8 firm_version_min; // 62 43 u8 firm_version_min; // 62
45 u8 firm_version_maj; // 63 44 u8 firm_version_maj; // 63
46 u32_le firm_sys_core_ver; // 64 45 u32_le firm_sys_core_ver; // 64
47 u32_le firm_ctr_sdk_ver; // 68 46 u32_le firm_ctr_sdk_ver; // 68
48 INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C 47 INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C
49}; 48};
50static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong"); 49static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE,
50 "Config Memory structure size is wrong");
51 51
52extern ConfigMemDef config_mem; 52extern ConfigMemDef config_mem;
53 53
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 8839ce482..8ce0f6d2b 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -5,16 +5,16 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8
9#include "core/arm/arm_interface.h" 8#include "core/arm/arm_interface.h"
10#include "core/memory.h" 9#include "core/core.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..41b772163 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -4,7 +4,6 @@
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7
8#include "core/arm/arm_interface.h" 7#include "core/arm/arm_interface.h"
9#include "core/core.h" 8#include "core/core.h"
10#include "core/hle/hle.h" 9#include "core/hle/hle.h"
@@ -15,13 +14,13 @@
15namespace { 14namespace {
16 15
17bool reschedule; ///< If true, immediately reschedules the CPU to a new thread 16bool reschedule; ///< If true, immediately reschedules the CPU to a new thread
18
19} 17}
20 18
21namespace HLE { 19namespace HLE {
22 20
23void Reschedule(const char *reason) { 21void Reschedule(const char* reason) {
24 DEBUG_ASSERT_MSG(reason != nullptr && strlen(reason) < 256, "Reschedule: Invalid or too long reason."); 22 DEBUG_ASSERT_MSG(reason != nullptr && strlen(reason) < 256,
23 "Reschedule: Invalid or too long reason.");
25 24
26 // TODO(bunnei): It seems that games depend on some CPU execution time elapsing during HLE 25 // 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". 26 // 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..37eec4c84 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -4,12 +4,10 @@
4 4
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
8#include "core/memory.h"
9
10#include "core/hle/hle.h" 7#include "core/hle/hle.h"
11#include "core/hle/kernel/address_arbiter.h" 8#include "core/hle/kernel/address_arbiter.h"
12#include "core/hle/kernel/thread.h" 9#include "core/hle/kernel/thread.h"
10#include "core/memory.h"
13 11
14//////////////////////////////////////////////////////////////////////////////////////////////////// 12////////////////////////////////////////////////////////////////////////////////////////////////////
15// Kernel namespace 13// Kernel namespace
@@ -28,7 +26,7 @@ SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) {
28} 26}
29 27
30ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, 28ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value,
31 u64 nanoseconds) { 29 u64 nanoseconds) {
32 switch (type) { 30 switch (type) {
33 31
34 // Signal thread(s) waiting for arbitrate address... 32 // Signal thread(s) waiting for arbitrate address...
@@ -38,7 +36,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
38 ArbitrateAllThreads(address); 36 ArbitrateAllThreads(address);
39 } else { 37 } else {
40 // Resume first N threads 38 // Resume first N threads
41 for(int i = 0; i < value; i++) 39 for (int i = 0; i < value; i++)
42 ArbitrateHighestPriorityThread(address); 40 ArbitrateHighestPriorityThread(address);
43 } 41 }
44 break; 42 break;
@@ -55,8 +53,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
55 GetCurrentThread()->WakeAfterDelay(nanoseconds); 53 GetCurrentThread()->WakeAfterDelay(nanoseconds);
56 } 54 }
57 break; 55 break;
58 case ArbitrationType::DecrementAndWaitIfLessThan: 56 case ArbitrationType::DecrementAndWaitIfLessThan: {
59 {
60 s32 memory_value = Memory::Read32(address); 57 s32 memory_value = Memory::Read32(address);
61 if (memory_value < value) { 58 if (memory_value < value) {
62 // Only change the memory value if the thread should wait 59 // Only change the memory value if the thread should wait
@@ -65,8 +62,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
65 } 62 }
66 break; 63 break;
67 } 64 }
68 case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: 65 case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: {
69 {
70 s32 memory_value = Memory::Read32(address); 66 s32 memory_value = Memory::Read32(address);
71 if (memory_value < value) { 67 if (memory_value < value) {
72 // Only change the memory value if the thread should wait 68 // Only change the memory value if the thread should wait
@@ -79,17 +75,19 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
79 75
80 default: 76 default:
81 LOG_ERROR(Kernel, "unknown type=%d", type); 77 LOG_ERROR(Kernel, "unknown type=%d", type);
82 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage); 78 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
79 ErrorSummary::WrongArgument, ErrorLevel::Usage);
83 } 80 }
84 81
85 HLE::Reschedule(__func__); 82 HLE::Reschedule(__func__);
86 83
87 // The calls that use a timeout seem to always return a Timeout error even if they did not put the thread to sleep 84 // The calls that use a timeout seem to always return a Timeout error even if they did not put
85 // the thread to sleep
88 if (type == ArbitrationType::WaitIfLessThanWithTimeout || 86 if (type == ArbitrationType::WaitIfLessThanWithTimeout ||
89 type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) { 87 type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) {
90 88
91 return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, 89 return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, ErrorSummary::StatusChanged,
92 ErrorSummary::StatusChanged, ErrorLevel::Info); 90 ErrorLevel::Info);
93 } 91 }
94 return RESULT_SUCCESS; 92 return RESULT_SUCCESS;
95} 93}
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 8f6a1a8df..6a7af93a9 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8
9#include "core/hle/kernel/kernel.h" 8#include "core/hle/kernel/kernel.h"
10 9
11// Address arbiters are an underlying kernel synchronization object that can be created/used via 10// Address arbiters are an underlying kernel synchronization object that can be created/used via
@@ -36,13 +35,19 @@ public:
36 */ 35 */
37 static SharedPtr<AddressArbiter> Create(std::string name = "Unknown"); 36 static SharedPtr<AddressArbiter> Create(std::string name = "Unknown");
38 37
39 std::string GetTypeName() const override { return "Arbiter"; } 38 std::string GetTypeName() const override {
40 std::string GetName() const override { return name; } 39 return "Arbiter";
40 }
41 std::string GetName() const override {
42 return name;
43 }
41 44
42 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; 45 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter;
43 HandleType GetHandleType() const override { return HANDLE_TYPE; } 46 HandleType GetHandleType() const override {
47 return HANDLE_TYPE;
48 }
44 49
45 std::string name; ///< Name of address arbiter object (optional) 50 std::string name; ///< Name of address arbiter object (optional)
46 51
47 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); 52 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds);
48 53
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index 444ce8d45..aedc6f989 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6
7#include "core/hle/kernel/client_port.h" 6#include "core/hle/kernel/client_port.h"
8#include "core/hle/kernel/kernel.h" 7#include "core/hle/kernel/kernel.h"
9#include "core/hle/kernel/server_port.h" 8#include "core/hle/kernel/server_port.h"
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index 480b6ddae..d28147718 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -5,9 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <string> 7#include <string>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10
11#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
12 10
13namespace Kernel { 11namespace Kernel {
@@ -17,16 +15,22 @@ class ServerPort;
17class ClientPort : public Object { 15class ClientPort : public Object {
18public: 16public:
19 friend class ServerPort; 17 friend class ServerPort;
20 std::string GetTypeName() const override { return "ClientPort"; } 18 std::string GetTypeName() const override {
21 std::string GetName() const override { return name; } 19 return "ClientPort";
20 }
21 std::string GetName() const override {
22 return name;
23 }
22 24
23 static const HandleType HANDLE_TYPE = HandleType::ClientPort; 25 static const HandleType HANDLE_TYPE = HandleType::ClientPort;
24 HandleType GetHandleType() const override { return HANDLE_TYPE; } 26 HandleType GetHandleType() const override {
25 27 return HANDLE_TYPE;
26 SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. 28 }
27 u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have 29
28 u32 active_sessions; ///< Number of currently open sessions to this port 30 SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
29 std::string name; ///< Name of client port (optional) 31 u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have
32 u32 active_sessions; ///< Number of currently open sessions to this port
33 std::string name; ///< Name of client port (optional)
30 34
31protected: 35protected:
32 ClientPort(); 36 ClientPort();
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 2b7c6992a..1489c7002 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -2,14 +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 <map>
6#include <algorithm> 5#include <algorithm>
6#include <map>
7#include <vector> 7#include <vector>
8
9#include "common/assert.h" 8#include "common/assert.h"
10
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/event.h" 9#include "core/hle/kernel/event.h"
10#include "core/hle/kernel/kernel.h"
13#include "core/hle/kernel/thread.h" 11#include "core/hle/kernel/thread.h"
14 12
15namespace Kernel { 13namespace Kernel {
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 73d0da419..6fe74065d 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8
9#include "core/hle/kernel/kernel.h" 8#include "core/hle/kernel/kernel.h"
10 9
11namespace Kernel { 10namespace Kernel {
@@ -16,7 +15,6 @@ enum class ResetType {
16 Pulse, 15 Pulse,
17}; 16};
18 17
19
20class Event final : public WaitObject { 18class Event final : public WaitObject {
21public: 19public:
22 /** 20 /**
@@ -26,16 +24,22 @@ public:
26 */ 24 */
27 static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown"); 25 static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown");
28 26
29 std::string GetTypeName() const override { return "Event"; } 27 std::string GetTypeName() const override {
30 std::string GetName() const override { return name; } 28 return "Event";
29 }
30 std::string GetName() const override {
31 return name;
32 }
31 33
32 static const HandleType HANDLE_TYPE = HandleType::Event; 34 static const HandleType HANDLE_TYPE = HandleType::Event;
33 HandleType GetHandleType() const override { return HANDLE_TYPE; } 35 HandleType GetHandleType() const override {
36 return HANDLE_TYPE;
37 }
34 38
35 ResetType reset_type; ///< Current ResetType 39 ResetType reset_type; ///< Current ResetType
36 40
37 bool signaled; ///< Whether the event has already been signaled 41 bool signaled; ///< Whether the event has already been signaled
38 std::string name; ///< Name of event (optional) 42 std::string name; ///< Name of event (optional)
39 43
40 bool ShouldWait() override; 44 bool ShouldWait() override;
41 void Acquire() override; 45 void Acquire() override;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 7a401a965..9a2c8ce05 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -3,10 +3,8 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6
7#include "common/assert.h" 6#include "common/assert.h"
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9
10#include "core/hle/config_mem.h" 8#include "core/hle/config_mem.h"
11#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/memory.h" 10#include "core/hle/kernel/memory.h"
@@ -61,7 +59,8 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
61 59
62 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. 60 // 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. 61 // CTR-OS doesn't use generation 0, so skip straight to 1.
64 if (next_generation >= (1 << 15)) next_generation = 1; 62 if (next_generation >= (1 << 15))
63 next_generation = 1;
65 64
66 generations[slot] = generation; 65 generations[slot] = generation;
67 objects[slot] = std::move(obj); 66 objects[slot] = std::move(obj);
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 27ba3f912..0e95f7ff0 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -4,16 +4,13 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <boost/smart_ptr/intrusive_ptr.hpp>
8
9#include <algorithm> 7#include <algorithm>
10#include <array> 8#include <array>
11#include <cstddef> 9#include <cstddef>
12#include <string> 10#include <string>
13#include <vector> 11#include <vector>
14 12#include <boost/smart_ptr/intrusive_ptr.hpp>
15#include "common/common_types.h" 13#include "common/common_types.h"
16
17#include "core/hle/hle.h" 14#include "core/hle/hle.h"
18#include "core/hle/result.h" 15#include "core/hle/result.h"
19 16
@@ -23,37 +20,37 @@ class Thread;
23 20
24// TODO: Verify code 21// TODO: Verify code
25const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, 22const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
26 ErrorSummary::OutOfResource, ErrorLevel::Temporary); 23 ErrorSummary::OutOfResource, ErrorLevel::Temporary);
27// TOOD: Verify code 24// TOOD: Verify code
28const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, 25const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel,
29 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 26 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
30 27
31enum KernelHandle : Handle { 28enum KernelHandle : Handle {
32 CurrentThread = 0xFFFF8000, 29 CurrentThread = 0xFFFF8000,
33 CurrentProcess = 0xFFFF8001, 30 CurrentProcess = 0xFFFF8001,
34}; 31};
35 32
36enum class HandleType : u32 { 33enum class HandleType : u32 {
37 Unknown = 0, 34 Unknown = 0,
38 35
39 Session = 2, 36 Session = 2,
40 Event = 3, 37 Event = 3,
41 Mutex = 4, 38 Mutex = 4,
42 SharedMemory = 5, 39 SharedMemory = 5,
43 Redirection = 6, 40 Redirection = 6,
44 Thread = 7, 41 Thread = 7,
45 Process = 8, 42 Process = 8,
46 AddressArbiter = 9, 43 AddressArbiter = 9,
47 Semaphore = 10, 44 Semaphore = 10,
48 Timer = 11, 45 Timer = 11,
49 ResourceLimit = 12, 46 ResourceLimit = 12,
50 CodeSet = 13, 47 CodeSet = 13,
51 ClientPort = 14, 48 ClientPort = 14,
52 ServerPort = 15, 49 ServerPort = 15,
53}; 50};
54 51
55enum { 52enum {
56 DEFAULT_STACK_SIZE = 0x4000, 53 DEFAULT_STACK_SIZE = 0x4000,
57}; 54};
58 55
59class Object : NonCopyable { 56class Object : NonCopyable {
@@ -61,10 +58,16 @@ public:
61 virtual ~Object() {} 58 virtual ~Object() {}
62 59
63 /// Returns a unique identifier for the object. For debugging purposes only. 60 /// Returns a unique identifier for the object. For debugging purposes only.
64 unsigned int GetObjectId() const { return object_id; } 61 unsigned int GetObjectId() const {
62 return object_id;
63 }
65 64
66 virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } 65 virtual std::string GetTypeName() const {
67 virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } 66 return "[BAD KERNEL OBJECT TYPE]";
67 }
68 virtual std::string GetName() const {
69 return "[UNKNOWN KERNEL OBJECT]";
70 }
68 virtual Kernel::HandleType GetHandleType() const = 0; 71 virtual Kernel::HandleType GetHandleType() const = 0;
69 72
70 /** 73 /**
@@ -122,7 +125,6 @@ using SharedPtr = boost::intrusive_ptr<T>;
122/// Class that represents a Kernel object that a thread can be waiting on 125/// Class that represents a Kernel object that a thread can be waiting on
123class WaitObject : public Object { 126class WaitObject : public Object {
124public: 127public:
125
126 /** 128 /**
127 * Check if the current thread should wait until the object is available 129 * 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 130 * @return True if the current thread should wait due to this object being unavailable
@@ -247,8 +249,12 @@ private:
247 */ 249 */
248 static const size_t MAX_COUNT = 4096; 250 static const size_t MAX_COUNT = 4096;
249 251
250 static u16 GetSlot(Handle handle) { return handle >> 15; } 252 static u16 GetSlot(Handle handle) {
251 static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; } 253 return handle >> 15;
254 }
255 static u16 GetGeneration(Handle handle) {
256 return handle & 0x7FFF;
257 }
252 258
253 /// Stores the Object referenced by the handle or null if the slot is empty. 259 /// Stores the Object referenced by the handle or null if the slot is empty.
254 std::array<SharedPtr<Object>, MAX_COUNT> objects; 260 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..e65fd5c41 100644
--- a/src/core/hle/kernel/memory.cpp
+++ b/src/core/hle/kernel/memory.cpp
@@ -6,12 +6,9 @@
6#include <memory> 6#include <memory>
7#include <utility> 7#include <utility>
8#include <vector> 8#include <vector>
9
10#include "audio_core/audio_core.h" 9#include "audio_core/audio_core.h"
11
12#include "common/common_types.h" 10#include "common/common_types.h"
13#include "common/logging/log.h" 11#include "common/logging/log.h"
14
15#include "core/hle/config_mem.h" 12#include "core/hle/config_mem.h"
16#include "core/hle/kernel/memory.h" 13#include "core/hle/kernel/memory.h"
17#include "core/hle/kernel/vm_manager.h" 14#include "core/hle/kernel/vm_manager.h"
@@ -31,7 +28,7 @@ static MemoryRegionInfo memory_regions[3];
31static const u32 memory_region_sizes[8][3] = { 28static const u32 memory_region_sizes[8][3] = {
32 // Old 3DS layouts 29 // Old 3DS layouts
33 {0x04000000, 0x02C00000, 0x01400000}, // 0 30 {0x04000000, 0x02C00000, 0x01400000}, // 0
34 { /* This appears to be unused. */ }, // 1 31 {/* This appears to be unused. */}, // 1
35 {0x06000000, 0x00C00000, 0x01400000}, // 2 32 {0x06000000, 0x00C00000, 0x01400000}, // 2
36 {0x05000000, 0x01C00000, 0x01400000}, // 3 33 {0x05000000, 0x01C00000, 0x01400000}, // 3
37 {0x04800000, 0x02400000, 0x01400000}, // 4 34 {0x04800000, 0x02400000, 0x01400000}, // 4
@@ -95,7 +92,6 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) {
95 UNREACHABLE(); 92 UNREACHABLE();
96 } 93 }
97} 94}
98
99} 95}
100 96
101namespace Memory { 97namespace Memory {
@@ -110,9 +106,8 @@ struct MemoryArea {
110 106
111// We don't declare the IO regions in here since its handled by other means. 107// We don't declare the IO regions in here since its handled by other means.
112static MemoryArea memory_areas[] = { 108static MemoryArea memory_areas[] = {
113 {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) 109 {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM)
114}; 110};
115
116} 111}
117 112
118void Init() { 113void Init() {
@@ -125,15 +120,21 @@ void InitLegacyAddressSpace(Kernel::VMManager& address_space) {
125 120
126 for (MemoryArea& area : memory_areas) { 121 for (MemoryArea& area : memory_areas) {
127 auto block = std::make_shared<std::vector<u8>>(area.size); 122 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(); 123 address_space
124 .MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private)
125 .Unwrap();
129 } 126 }
130 127
131 auto cfg_mem_vma = address_space.MapBackingMemory(CONFIG_MEMORY_VADDR, 128 auto cfg_mem_vma = address_space
132 (u8*)&ConfigMem::config_mem, CONFIG_MEMORY_SIZE, MemoryState::Shared).MoveFrom(); 129 .MapBackingMemory(CONFIG_MEMORY_VADDR, (u8*)&ConfigMem::config_mem,
130 CONFIG_MEMORY_SIZE, MemoryState::Shared)
131 .MoveFrom();
133 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); 132 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read);
134 133
135 auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR, 134 auto shared_page_vma = address_space
136 (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom(); 135 .MapBackingMemory(SHARED_PAGE_VADDR, (u8*)&SharedPage::shared_page,
136 SHARED_PAGE_SIZE, MemoryState::Shared)
137 .MoveFrom();
137 address_space.Reprotect(shared_page_vma, VMAPermission::Read); 138 address_space.Reprotect(shared_page_vma, VMAPermission::Read);
138 139
139 AudioCore::AddAddressSpace(address_space); 140 AudioCore::AddAddressSpace(address_space);
diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h
index 091c1f89f..4e1856a41 100644
--- a/src/core/hle/kernel/memory.h
+++ b/src/core/hle/kernel/memory.h
@@ -5,9 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10
11#include "core/hle/kernel/process.h" 9#include "core/hle/kernel/process.h"
12 10
13namespace Kernel { 11namespace Kernel {
@@ -25,7 +23,6 @@ struct MemoryRegionInfo {
25void MemoryInit(u32 mem_type); 23void MemoryInit(u32 mem_type);
26void MemoryShutdown(); 24void MemoryShutdown();
27MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); 25MemoryRegionInfo* GetMemoryRegion(MemoryRegion region);
28
29} 26}
30 27
31namespace Memory { 28namespace Memory {
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index edb97d324..736944bae 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -4,11 +4,8 @@
4 4
5#include <map> 5#include <map>
6#include <vector> 6#include <vector>
7
8#include <boost/range/algorithm_ext/erase.hpp> 7#include <boost/range/algorithm_ext/erase.hpp>
9
10#include "common/assert.h" 8#include "common/assert.h"
11
12#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
13#include "core/hle/kernel/mutex.h" 10#include "core/hle/kernel/mutex.h"
14#include "core/hle/kernel/thread.h" 11#include "core/hle/kernel/thread.h"
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 1746360e4..53c3dc1f1 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -5,9 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <string> 7#include <string>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10
11#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
12 10
13namespace Kernel { 11namespace Kernel {
@@ -24,15 +22,21 @@ public:
24 */ 22 */
25 static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown"); 23 static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown");
26 24
27 std::string GetTypeName() const override { return "Mutex"; } 25 std::string GetTypeName() const override {
28 std::string GetName() const override { return name; } 26 return "Mutex";
27 }
28 std::string GetName() const override {
29 return name;
30 }
29 31
30 static const HandleType HANDLE_TYPE = HandleType::Mutex; 32 static const HandleType HANDLE_TYPE = HandleType::Mutex;
31 HandleType GetHandleType() const override { return HANDLE_TYPE; } 33 HandleType GetHandleType() const override {
34 return HANDLE_TYPE;
35 }
32 36
33 int lock_count; ///< Number of times the mutex has been acquired 37 int lock_count; ///< Number of times the mutex has been acquired
34 std::string name; ///< Name of mutex (optional) 38 std::string name; ///< Name of mutex (optional)
35 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex 39 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
36 40
37 bool ShouldWait() override; 41 bool ShouldWait() override;
38 void Acquire() override; 42 void Acquire() override;
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 69302cc82..ba80fe7f8 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -3,11 +3,9 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <memory>
6
7#include "common/assert.h" 6#include "common/assert.h"
8#include "common/common_funcs.h" 7#include "common/common_funcs.h"
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10
11#include "core/hle/kernel/memory.h" 9#include "core/hle/kernel/memory.h"
12#include "core/hle/kernel/process.h" 10#include "core/hle/kernel/process.h"
13#include "core/hle/kernel/resource_limit.h" 11#include "core/hle/kernel/resource_limit.h"
@@ -60,7 +58,8 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
60 58
61 while (bits && index < svc_access_mask.size()) { 59 while (bits && index < svc_access_mask.size()) {
62 svc_access_mask.set(index, bits & 1); 60 svc_access_mask.set(index, bits & 1);
63 ++index; bits >>= 1; 61 ++index;
62 bits >>= 1;
64 } 63 }
65 } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF 64 } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF
66 // Handle table size 65 // Handle table size
@@ -70,11 +69,11 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
70 flags.raw = descriptor & 0xFFFF; 69 flags.raw = descriptor & 0xFFFF;
71 } else if ((type & 0xFFE) == 0xFF8) { // 0x001F 70 } else if ((type & 0xFFE) == 0xFF8) { // 0x001F
72 // Mapped memory range 71 // Mapped memory range
73 if (i+1 >= len || ((kernel_caps[i+1] >> 20) & 0xFFE) != 0xFF8) { 72 if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) {
74 LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored."); 73 LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored.");
75 continue; 74 continue;
76 } 75 }
77 u32 end_desc = kernel_caps[i+1]; 76 u32 end_desc = kernel_caps[i + 1];
78 ++i; // Skip over the second descriptor on the next iteration 77 ++i; // Skip over the second descriptor on the next iteration
79 78
80 AddressMapping mapping; 79 AddressMapping mapping;
@@ -107,23 +106,28 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
107void Process::Run(s32 main_thread_priority, u32 stack_size) { 106void Process::Run(s32 main_thread_priority, u32 stack_size) {
108 memory_region = GetMemoryRegion(flags.memory_region); 107 memory_region = GetMemoryRegion(flags.memory_region);
109 108
110 auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { 109 auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
111 auto vma = vm_manager.MapMemoryBlock(segment.addr, codeset->memory, 110 MemoryState memory_state) {
112 segment.offset, segment.size, memory_state).Unwrap(); 111 auto vma = vm_manager
112 .MapMemoryBlock(segment.addr, codeset->memory, segment.offset, segment.size,
113 memory_state)
114 .Unwrap();
113 vm_manager.Reprotect(vma, permissions); 115 vm_manager.Reprotect(vma, permissions);
114 misc_memory_used += segment.size; 116 misc_memory_used += segment.size;
115 memory_region->used += segment.size; 117 memory_region->used += segment.size;
116 }; 118 };
117 119
118 // Map CodeSet segments 120 // Map CodeSet segments
119 MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code); 121 MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code);
120 MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code); 122 MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code);
121 MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private); 123 MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private);
122 124
123 // Allocate and map stack 125 // Allocate and map stack
124 vm_manager.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, 126 vm_manager
125 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked 127 .MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size,
126 ).Unwrap(); 128 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size,
129 MemoryState::Locked)
130 .Unwrap();
127 misc_memory_used += stack_size; 131 misc_memory_used += stack_size;
128 memory_region->used += stack_size; 132 memory_region->used += stack_size;
129 133
@@ -143,7 +147,8 @@ VAddr Process::GetLinearHeapLimit() const {
143} 147}
144 148
145ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) { 149ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) {
146 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { 150 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END ||
151 target + size < target) {
147 return ERR_INVALID_ADDRESS; 152 return ERR_INVALID_ADDRESS;
148 } 153 }
149 154
@@ -166,7 +171,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
166 } 171 }
167 ASSERT(heap_end - heap_start == heap_memory->size()); 172 ASSERT(heap_end - heap_start == heap_memory->size());
168 173
169 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, size, MemoryState::Private)); 174 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start,
175 size, MemoryState::Private));
170 vm_manager.Reprotect(vma, perms); 176 vm_manager.Reprotect(vma, perms);
171 177
172 heap_used += size; 178 heap_used += size;
@@ -176,7 +182,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
176} 182}
177 183
178ResultCode Process::HeapFree(VAddr target, u32 size) { 184ResultCode Process::HeapFree(VAddr target, u32 size) {
179 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { 185 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END ||
186 target + size < target) {
180 return ERR_INVALID_ADDRESS; 187 return ERR_INVALID_ADDRESS;
181 } 188 }
182 189
@@ -185,7 +192,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
185 } 192 }
186 193
187 ResultCode result = vm_manager.UnmapRange(target, size); 194 ResultCode result = vm_manager.UnmapRange(target, size);
188 if (result.IsError()) return result; 195 if (result.IsError())
196 return result;
189 197
190 heap_used -= size; 198 heap_used -= size;
191 memory_region->used -= size; 199 memory_region->used -= size;
@@ -203,8 +211,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p
203 target = heap_end; 211 target = heap_end;
204 } 212 }
205 213
206 if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || 214 if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || target > heap_end ||
207 target > heap_end || target + size < target) { 215 target + size < target) {
208 216
209 return ERR_INVALID_ADDRESS; 217 return ERR_INVALID_ADDRESS;
210 } 218 }
@@ -220,7 +228,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 228 // 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. 229 // same region. It is unknown if or how the 3DS kernel checks against this.
222 size_t offset = target - GetLinearHeapBase(); 230 size_t offset = target - GetLinearHeapBase();
223 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, MemoryState::Continuous)); 231 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size,
232 MemoryState::Continuous));
224 vm_manager.Reprotect(vma, perms); 233 vm_manager.Reprotect(vma, perms);
225 234
226 linear_heap_used += size; 235 linear_heap_used += size;
@@ -248,7 +257,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
248 } 257 }
249 258
250 ResultCode result = vm_manager.UnmapRange(target, size); 259 ResultCode result = vm_manager.UnmapRange(target, size);
251 if (result.IsError()) return result; 260 if (result.IsError())
261 return result;
252 262
253 linear_heap_used -= size; 263 linear_heap_used -= size;
254 memory_region->used -= size; 264 memory_region->used -= size;
@@ -272,5 +282,4 @@ Kernel::Process::Process() {}
272Kernel::Process::~Process() {} 282Kernel::Process::~Process() {}
273 283
274SharedPtr<Process> g_current_process; 284SharedPtr<Process> g_current_process;
275
276} 285}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index d781ef32c..b566950b0 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -8,12 +8,9 @@
8#include <cstddef> 8#include <cstddef>
9#include <memory> 9#include <memory>
10#include <string> 10#include <string>
11
12#include <boost/container/static_vector.hpp> 11#include <boost/container/static_vector.hpp>
13
14#include "common/bit_field.h" 12#include "common/bit_field.h"
15#include "common/common_types.h" 13#include "common/common_types.h"
16
17#include "core/hle/kernel/kernel.h" 14#include "core/hle/kernel/kernel.h"
18#include "core/hle/kernel/vm_manager.h" 15#include "core/hle/kernel/vm_manager.h"
19 16
@@ -36,15 +33,18 @@ enum class MemoryRegion : u16 {
36union ProcessFlags { 33union ProcessFlags {
37 u16 raw; 34 u16 raw;
38 35
39 BitField< 0, 1, u16> allow_debug; ///< Allows other processes to attach to and debug this process. 36 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. 37 allow_debug; ///< Allows other processes to attach to and debug this process.
41 BitField< 2, 1, u16> allow_nonalphanum; 38 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. 39 /// don't have allow_debug set.
43 BitField< 4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24. 40 BitField<2, 1, u16> allow_nonalphanum;
44 BitField< 5, 1, u16> allow_main_args; 41 BitField<3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions.
45 BitField< 6, 1, u16> shared_device_mem; 42 BitField<4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24.
46 BitField< 7, 1, u16> runnable_on_sleep; 43 BitField<5, 1, u16> allow_main_args;
47 BitField< 8, 4, MemoryRegion> memory_region; ///< Default region for memory allocations for this process 44 BitField<6, 1, u16> shared_device_mem;
45 BitField<7, 1, u16> runnable_on_sleep;
46 BitField<8, 4, MemoryRegion>
47 memory_region; ///< Default region for memory allocations for this process
48 BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000). 48 BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
49}; 49};
50 50
@@ -54,11 +54,17 @@ struct MemoryRegionInfo;
54struct CodeSet final : public Object { 54struct CodeSet final : public Object {
55 static SharedPtr<CodeSet> Create(std::string name, u64 program_id); 55 static SharedPtr<CodeSet> Create(std::string name, u64 program_id);
56 56
57 std::string GetTypeName() const override { return "CodeSet"; } 57 std::string GetTypeName() const override {
58 std::string GetName() const override { return name; } 58 return "CodeSet";
59 }
60 std::string GetName() const override {
61 return name;
62 }
59 63
60 static const HandleType HANDLE_TYPE = HandleType::CodeSet; 64 static const HandleType HANDLE_TYPE = HandleType::CodeSet;
61 HandleType GetHandleType() const override { return HANDLE_TYPE; } 65 HandleType GetHandleType() const override {
66 return HANDLE_TYPE;
67 }
62 68
63 /// Name of the process 69 /// Name of the process
64 std::string name; 70 std::string name;
@@ -85,11 +91,17 @@ class Process final : public Object {
85public: 91public:
86 static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set); 92 static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set);
87 93
88 std::string GetTypeName() const override { return "Process"; } 94 std::string GetTypeName() const override {
89 std::string GetName() const override { return codeset->name; } 95 return "Process";
96 }
97 std::string GetName() const override {
98 return codeset->name;
99 }
90 100
91 static const HandleType HANDLE_TYPE = HandleType::Process; 101 static const HandleType HANDLE_TYPE = HandleType::Process;
92 HandleType GetHandleType() const override { return HANDLE_TYPE; } 102 HandleType GetHandleType() const override {
103 return HANDLE_TYPE;
104 }
93 105
94 static u32 next_process_id; 106 static u32 next_process_id;
95 107
@@ -124,7 +136,6 @@ public:
124 */ 136 */
125 void Run(s32 main_thread_priority, u32 stack_size); 137 void Run(s32 main_thread_priority, u32 stack_size);
126 138
127
128 /////////////////////////////////////////////////////////////////////////////////////////////// 139 ///////////////////////////////////////////////////////////////////////////////////////////////
129 // Memory Management 140 // Memory Management
130 141
@@ -144,7 +155,8 @@ public:
144 155
145 /// The Thread Local Storage area is allocated as processes create threads, 156 /// 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 157 /// 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. 158 /// holds the TLS for a specific thread. This vector contains which parts are in use for each
159 /// page as a bitmask.
148 /// This vector will grow as more pages are allocated for new threads. 160 /// This vector will grow as more pages are allocated for new threads.
149 std::vector<std::bitset<8>> tls_slots; 161 std::vector<std::bitset<8>> tls_slots;
150 162
@@ -164,5 +176,4 @@ private:
164}; 176};
165 177
166extern SharedPtr<Process> g_current_process; 178extern SharedPtr<Process> g_current_process;
167
168} 179}
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
index 67dde08c2..253ab7045 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -3,9 +3,7 @@
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
7#include "common/logging/log.h" 6#include "common/logging/log.h"
8
9#include "core/hle/kernel/resource_limit.h" 7#include "core/hle/kernel/resource_limit.h"
10 8
11namespace Kernel { 9namespace Kernel {
@@ -23,70 +21,69 @@ SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) {
23} 21}
24 22
25SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { 23SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) {
26 switch (category) 24 switch (category) {
27 { 25 case ResourceLimitCategory::APPLICATION:
28 case ResourceLimitCategory::APPLICATION: 26 case ResourceLimitCategory::SYS_APPLET:
29 case ResourceLimitCategory::SYS_APPLET: 27 case ResourceLimitCategory::LIB_APPLET:
30 case ResourceLimitCategory::LIB_APPLET: 28 case ResourceLimitCategory::OTHER:
31 case ResourceLimitCategory::OTHER: 29 return resource_limits[static_cast<u8>(category)];
32 return resource_limits[static_cast<u8>(category)]; 30 default:
33 default: 31 LOG_CRITICAL(Kernel, "Unknown resource limit category");
34 LOG_CRITICAL(Kernel, "Unknown resource limit category"); 32 UNREACHABLE();
35 UNREACHABLE();
36 } 33 }
37} 34}
38 35
39s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { 36s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const {
40 switch (resource) { 37 switch (resource) {
41 case COMMIT: 38 case COMMIT:
42 return current_commit; 39 return current_commit;
43 case THREAD: 40 case THREAD:
44 return current_threads; 41 return current_threads;
45 case EVENT: 42 case EVENT:
46 return current_events; 43 return current_events;
47 case MUTEX: 44 case MUTEX:
48 return current_mutexes; 45 return current_mutexes;
49 case SEMAPHORE: 46 case SEMAPHORE:
50 return current_semaphores; 47 return current_semaphores;
51 case TIMER: 48 case TIMER:
52 return current_timers; 49 return current_timers;
53 case SHARED_MEMORY: 50 case SHARED_MEMORY:
54 return current_shared_mems; 51 return current_shared_mems;
55 case ADDRESS_ARBITER: 52 case ADDRESS_ARBITER:
56 return current_address_arbiters; 53 return current_address_arbiters;
57 case CPU_TIME: 54 case CPU_TIME:
58 return current_cpu_time; 55 return current_cpu_time;
59 default: 56 default:
60 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); 57 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
61 UNIMPLEMENTED(); 58 UNIMPLEMENTED();
62 return 0; 59 return 0;
63 } 60 }
64} 61}
65 62
66s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { 63s32 ResourceLimit::GetMaxResourceValue(u32 resource) const {
67 switch (resource) { 64 switch (resource) {
68 case COMMIT: 65 case COMMIT:
69 return max_commit; 66 return max_commit;
70 case THREAD: 67 case THREAD:
71 return max_threads; 68 return max_threads;
72 case EVENT: 69 case EVENT:
73 return max_events; 70 return max_events;
74 case MUTEX: 71 case MUTEX:
75 return max_mutexes; 72 return max_mutexes;
76 case SEMAPHORE: 73 case SEMAPHORE:
77 return max_semaphores; 74 return max_semaphores;
78 case TIMER: 75 case TIMER:
79 return max_timers; 76 return max_timers;
80 case SHARED_MEMORY: 77 case SHARED_MEMORY:
81 return max_shared_mems; 78 return max_shared_mems;
82 case ADDRESS_ARBITER: 79 case ADDRESS_ARBITER:
83 return max_address_arbiters; 80 return max_address_arbiters;
84 case CPU_TIME: 81 case CPU_TIME:
85 return max_cpu_time; 82 return max_cpu_time;
86 default: 83 default:
87 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); 84 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
88 UNIMPLEMENTED(); 85 UNIMPLEMENTED();
89 return 0; 86 return 0;
90 } 87 }
91} 88}
92 89
@@ -149,8 +146,6 @@ void ResourceLimitsInit() {
149 resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit; 146 resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit;
150} 147}
151 148
152void ResourceLimitsShutdown() { 149void ResourceLimitsShutdown() {}
153
154}
155 150
156} // namespace 151} // namespace
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index 1b8249c74..6cdfbcf8d 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -5,29 +5,28 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8
9#include "core/hle/kernel/kernel.h" 8#include "core/hle/kernel/kernel.h"
10 9
11namespace Kernel { 10namespace Kernel {
12 11
13enum class ResourceLimitCategory : u8 { 12enum class ResourceLimitCategory : u8 {
14 APPLICATION = 0, 13 APPLICATION = 0,
15 SYS_APPLET = 1, 14 SYS_APPLET = 1,
16 LIB_APPLET = 2, 15 LIB_APPLET = 2,
17 OTHER = 3 16 OTHER = 3
18}; 17};
19 18
20enum ResourceTypes { 19enum ResourceTypes {
21 PRIORITY = 0, 20 PRIORITY = 0,
22 COMMIT = 1, 21 COMMIT = 1,
23 THREAD = 2, 22 THREAD = 2,
24 EVENT = 3, 23 EVENT = 3,
25 MUTEX = 4, 24 MUTEX = 4,
26 SEMAPHORE = 5, 25 SEMAPHORE = 5,
27 TIMER = 6, 26 TIMER = 6,
28 SHARED_MEMORY = 7, 27 SHARED_MEMORY = 7,
29 ADDRESS_ARBITER = 8, 28 ADDRESS_ARBITER = 8,
30 CPU_TIME = 9, 29 CPU_TIME = 9,
31}; 30};
32 31
33class ResourceLimit final : public Object { 32class ResourceLimit final : public Object {
@@ -44,11 +43,17 @@ public:
44 */ 43 */
45 static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category); 44 static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
46 45
47 std::string GetTypeName() const override { return "ResourceLimit"; } 46 std::string GetTypeName() const override {
48 std::string GetName() const override { return name; } 47 return "ResourceLimit";
48 }
49 std::string GetName() const override {
50 return name;
51 }
49 52
50 static const HandleType HANDLE_TYPE = HandleType::ResourceLimit; 53 static const HandleType HANDLE_TYPE = HandleType::ResourceLimit;
51 HandleType GetHandleType() const override { return HANDLE_TYPE; } 54 HandleType GetHandleType() const override {
55 return HANDLE_TYPE;
56 }
52 57
53 /** 58 /**
54 * Gets the current value for the specified resource. 59 * Gets the current value for the specified resource.
@@ -85,10 +90,12 @@ public:
85 /// Max CPU time that the processes in this category can utilize 90 /// Max CPU time that the processes in this category can utilize
86 s32 max_cpu_time = 0; 91 s32 max_cpu_time = 0;
87 92
88 // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that 93 // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind
89 // APPLICATION resource limits should not be affected by the objects created by service modules. 94 // that APPLICATION resource limits should not be affected by the objects created by service
95 // modules.
90 // Currently we have no way of distinguishing if a Create was called by the running application, 96 // 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 97 // or by a service module. Approach this once we have separated the service modules into their
98 // own processes
92 99
93 /// Current memory that the processes in this category are using 100 /// Current memory that the processes in this category are using
94 s32 current_commit = 0; 101 s32 current_commit = 0;
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 4b359ed07..bf7600780 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6
7#include "core/hle/kernel/kernel.h" 6#include "core/hle/kernel/kernel.h"
8#include "core/hle/kernel/semaphore.h" 7#include "core/hle/kernel/semaphore.h"
9#include "core/hle/kernel/thread.h" 8#include "core/hle/kernel/thread.h"
@@ -14,7 +13,7 @@ Semaphore::Semaphore() {}
14Semaphore::~Semaphore() {} 13Semaphore::~Semaphore() {}
15 14
16ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, 15ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
17 std::string name) { 16 std::string name) {
18 17
19 if (initial_count > max_count) 18 if (initial_count > max_count)
20 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, 19 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 390f5e495..e01908a25 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -6,9 +6,7 @@
6 6
7#include <queue> 7#include <queue>
8#include <string> 8#include <string>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11
12#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
13 11
14namespace Kernel { 12namespace Kernel {
@@ -23,17 +21,23 @@ public:
23 * @return The created semaphore 21 * @return The created semaphore
24 */ 22 */
25 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, 23 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count,
26 std::string name = "Unknown"); 24 std::string name = "Unknown");
27 25
28 std::string GetTypeName() const override { return "Semaphore"; } 26 std::string GetTypeName() const override {
29 std::string GetName() const override { return name; } 27 return "Semaphore";
28 }
29 std::string GetName() const override {
30 return name;
31 }
30 32
31 static const HandleType HANDLE_TYPE = HandleType::Semaphore; 33 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
32 HandleType GetHandleType() const override { return HANDLE_TYPE; } 34 HandleType GetHandleType() const override {
35 return HANDLE_TYPE;
36 }
33 37
34 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have 38 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
35 s32 available_count; ///< Number of free slots left in the semaphore 39 s32 available_count; ///< Number of free slots left in the semaphore
36 std::string name; ///< Name of semaphore (optional) 40 std::string name; ///< Name of semaphore (optional)
37 41
38 bool ShouldWait() override; 42 bool ShouldWait() override;
39 void Acquire() override; 43 void Acquire() override;
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index fcc684a20..8e3ec8a14 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -3,9 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <tuple> 5#include <tuple>
6
7#include "common/assert.h" 6#include "common/assert.h"
8
9#include "core/hle/kernel/client_port.h" 7#include "core/hle/kernel/client_port.h"
10#include "core/hle/kernel/kernel.h" 8#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/server_port.h" 9#include "core/hle/kernel/server_port.h"
@@ -25,7 +23,9 @@ void ServerPort::Acquire() {
25 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 23 ASSERT_MSG(!ShouldWait(), "object unavailable!");
26} 24}
27 25
28std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(u32 max_sessions, std::string name) { 26std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(
27 u32 max_sessions, std::string name) {
28
29 SharedPtr<ServerPort> server_port(new ServerPort); 29 SharedPtr<ServerPort> server_port(new ServerPort);
30 SharedPtr<ClientPort> client_port(new ClientPort); 30 SharedPtr<ClientPort> client_port(new ClientPort);
31 31
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index e9c972ce6..fa9448ca0 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -6,9 +6,7 @@
6 6
7#include <string> 7#include <string>
8#include <tuple> 8#include <tuple>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11
12#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
13 11
14namespace Kernel { 12namespace Kernel {
@@ -23,17 +21,25 @@ public:
23 * @param name Optional name of the ports 21 * @param name Optional name of the ports
24 * @return The created port tuple 22 * @return The created port tuple
25 */ 23 */
26 static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(u32 max_sessions, std::string name = "UnknownPort"); 24 static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
25 u32 max_sessions, std::string name = "UnknownPort");
27 26
28 std::string GetTypeName() const override { return "ServerPort"; } 27 std::string GetTypeName() const override {
29 std::string GetName() const override { return name; } 28 return "ServerPort";
29 }
30 std::string GetName() const override {
31 return name;
32 }
30 33
31 static const HandleType HANDLE_TYPE = HandleType::ServerPort; 34 static const HandleType HANDLE_TYPE = HandleType::ServerPort;
32 HandleType GetHandleType() const override { return HANDLE_TYPE; } 35 HandleType GetHandleType() const override {
36 return HANDLE_TYPE;
37 }
33 38
34 std::string name; ///< Name of port (optional) 39 std::string name; ///< Name of port (optional)
35 40
36 std::vector<SharedPtr<WaitObject>> pending_sessions; ///< ServerSessions waiting to be accepted by the port 41 std::vector<SharedPtr<WaitObject>>
42 pending_sessions; ///< ServerSessions waiting to be accepted by the port
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/session.cpp b/src/core/hle/kernel/session.cpp
index 0594967f8..8a2a7e3fd 100644
--- a/src/core/hle/kernel/session.cpp
+++ b/src/core/hle/kernel/session.cpp
@@ -9,5 +9,4 @@ namespace Kernel {
9 9
10Session::Session() {} 10Session::Session() {}
11Session::~Session() {} 11Session::~Session() {}
12
13} 12}
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index 8ec889967..ec025f732 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -5,10 +5,8 @@
5#pragma once 5#pragma once
6 6
7#include <string> 7#include <string>
8
9#include "common/assert.h" 8#include "common/assert.h"
10#include "common/common_types.h" 9#include "common/common_types.h"
11
12#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
13#include "core/hle/kernel/thread.h" 11#include "core/hle/kernel/thread.h"
14#include "core/hle/result.h" 12#include "core/hle/result.h"
@@ -19,12 +17,13 @@ namespace IPC {
19enum DescriptorType : u32 { 17enum DescriptorType : u32 {
20 // Buffer related desciptors types (mask : 0x0F) 18 // Buffer related desciptors types (mask : 0x0F)
21 StaticBuffer = 0x02, 19 StaticBuffer = 0x02,
22 PXIBuffer = 0x04, 20 PXIBuffer = 0x04,
23 MappedBuffer = 0x08, 21 MappedBuffer = 0x08,
24 // Handle related descriptors types (mask : 0x30, but need to check for buffer related descriptors first ) 22 // Handle related descriptors types (mask : 0x30, but need to check for buffer related
25 CopyHandle = 0x00, 23 // descriptors first )
26 MoveHandle = 0x10, 24 CopyHandle = 0x00,
27 CallingPid = 0x20, 25 MoveHandle = 0x10,
26 CallingPid = 0x20,
28}; 27};
29 28
30/** 29/**
@@ -34,24 +33,28 @@ enum DescriptorType : u32 {
34 * @param translate_params_size Size of the translate parameters in words. Up to 63. 33 * @param translate_params_size Size of the translate parameters in words. Up to 63.
35 * @return The created IPC header. 34 * @return The created IPC header.
36 * 35 *
37 * Normal parameters are sent directly to the process while the translate parameters might go through modifications and checks by the kernel. 36 * Normal parameters are sent directly to the process while the translate parameters might go
37 * through modifications and checks by the kernel.
38 * The translate parameters are described by headers generated with the IPC::*Desc functions. 38 * The translate parameters are described by headers generated with the IPC::*Desc functions.
39 * 39 *
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. 40 * @note While #normal_params is equivalent to the number of normal parameters,
41 * #translate_params_size includes the size occupied by the translate parameters headers.
41 */ 42 */
42constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, unsigned int translate_params_size) { 43constexpr 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); 44 unsigned int translate_params_size) {
45 return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) |
46 (u32(translate_params_size) & 0x3F);
44} 47}
45 48
46union Header { 49union Header {
47 u32 raw; 50 u32 raw;
48 BitField< 0, 6, u32> translate_params_size; 51 BitField<0, 6, u32> translate_params_size;
49 BitField< 6, 6, u32> normal_params; 52 BitField<6, 6, u32> normal_params;
50 BitField<16, 16, u32> command_id; 53 BitField<16, 16, u32> command_id;
51}; 54};
52 55
53inline Header ParseHeader(u32 header) { 56inline Header ParseHeader(u32 header) {
54 return{ header }; 57 return {header};
55} 58}
56 59
57constexpr u32 MoveHandleDesc(u32 num_handles = 1) { 60constexpr u32 MoveHandleDesc(u32 num_handles = 1) {
@@ -80,27 +83,29 @@ constexpr u32 StaticBufferDesc(u32 size, u8 buffer_id) {
80 83
81union StaticBufferDescInfo { 84union StaticBufferDescInfo {
82 u32 raw; 85 u32 raw;
83 BitField< 10, 4, u32> buffer_id; 86 BitField<10, 4, u32> buffer_id;
84 BitField< 14, 18, u32> size; 87 BitField<14, 18, u32> size;
85}; 88};
86 89
87inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { 90inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) {
88 return{ desc }; 91 return {desc};
89} 92}
90 93
91/** 94/**
92 * @brief Creates a header describing a buffer to be sent over PXI. 95 * @brief Creates a header describing a buffer to be sent over PXI.
93 * @param size Size of the buffer. Max 0x00FFFFFF. 96 * @param size Size of the buffer. Max 0x00FFFFFF.
94 * @param buffer_id The Id of the buffer. Max 0xF. 97 * @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. 98 * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have
99 * read-write access.
96 * @return The created PXI buffer header. 100 * @return The created PXI buffer header.
97 * 101 *
98 * The next value is a phys-address of a table located in the BASE memregion. 102 * The next value is a phys-address of a table located in the BASE memregion.
99 */ 103 */
100inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) { 104inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) {
101 u32 type = PXIBuffer; 105 u32 type = PXIBuffer;
102 if (is_read_only) type |= 0x2; 106 if (is_read_only)
103 return type | (size << 8) | ((buffer_id & 0xF) << 4); 107 type |= 0x2;
108 return type | (size << 8) | ((buffer_id & 0xF) << 4);
104} 109}
105 110
106enum MappedBufferPermissions { 111enum MappedBufferPermissions {
@@ -115,12 +120,12 @@ constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) {
115 120
116union MappedBufferDescInfo { 121union MappedBufferDescInfo {
117 u32 raw; 122 u32 raw;
118 BitField< 4, 28, u32> size; 123 BitField<4, 28, u32> size;
119 BitField< 1, 2, MappedBufferPermissions> perms; 124 BitField<1, 2, MappedBufferPermissions> perms;
120}; 125};
121 126
122inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { 127inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) {
123 return{ desc }; 128 return {desc};
124} 129}
125 130
126inline DescriptorType GetDescriptorType(u32 descriptor) { 131inline DescriptorType GetDescriptorType(u32 descriptor) {
@@ -153,7 +158,8 @@ static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of
153 * @return Pointer to command buffer 158 * @return Pointer to command buffer
154 */ 159 */
155inline u32* GetCommandBuffer(const int offset = 0) { 160inline u32* GetCommandBuffer(const int offset = 0) {
156 return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset + offset); 161 return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset +
162 offset);
157} 163}
158 164
159/** 165/**
@@ -183,10 +189,14 @@ public:
183 Session(); 189 Session();
184 ~Session() override; 190 ~Session() override;
185 191
186 std::string GetTypeName() const override { return "Session"; } 192 std::string GetTypeName() const override {
193 return "Session";
194 }
187 195
188 static const HandleType HANDLE_TYPE = HandleType::Session; 196 static const HandleType HANDLE_TYPE = HandleType::Session;
189 HandleType GetHandleType() const override { return HANDLE_TYPE; } 197 HandleType GetHandleType() const override {
198 return HANDLE_TYPE;
199 }
190 200
191 /** 201 /**
192 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls 202 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls
@@ -205,5 +215,4 @@ public:
205 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 215 ASSERT_MSG(!ShouldWait(), "object unavailable!");
206 } 216 }
207}; 217};
208
209} 218}
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 6a22c8986..bc1560d12 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -3,20 +3,20 @@
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
7#include "common/logging/log.h" 6#include "common/logging/log.h"
8
9#include "core/memory.h"
10#include "core/hle/kernel/memory.h" 7#include "core/hle/kernel/memory.h"
11#include "core/hle/kernel/shared_memory.h" 8#include "core/hle/kernel/shared_memory.h"
9#include "core/memory.h"
12 10
13namespace Kernel { 11namespace Kernel {
14 12
15SharedMemory::SharedMemory() {} 13SharedMemory::SharedMemory() {}
16SharedMemory::~SharedMemory() {} 14SharedMemory::~SharedMemory() {}
17 15
18SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, 16SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size,
19 MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) { 17 MemoryPermission permissions,
18 MemoryPermission other_permissions, VAddr address,
19 MemoryRegion region, std::string name) {
20 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 20 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
21 21
22 shared_memory->owner_process = owner_process; 22 shared_memory->owner_process = owner_process;
@@ -31,7 +31,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
31 MemoryRegionInfo* memory_region = GetMemoryRegion(region); 31 MemoryRegionInfo* memory_region = GetMemoryRegion(region);
32 auto& linheap_memory = memory_region->linear_heap_memory; 32 auto& linheap_memory = memory_region->linear_heap_memory;
33 33
34 ASSERT_MSG(linheap_memory->size() + size <= memory_region->size, "Not enough space in region to allocate shared memory!"); 34 ASSERT_MSG(linheap_memory->size() + size <= memory_region->size,
35 "Not enough space in region to allocate shared memory!");
35 36
36 shared_memory->backing_block = linheap_memory; 37 shared_memory->backing_block = linheap_memory;
37 shared_memory->backing_block_offset = linheap_memory->size(); 38 shared_memory->backing_block_offset = linheap_memory->size();
@@ -39,7 +40,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
39 linheap_memory->insert(linheap_memory->end(), size, 0); 40 linheap_memory->insert(linheap_memory->end(), size, 0);
40 memory_region->used += size; 41 memory_region->used += size;
41 42
42 shared_memory->linear_heap_phys_address = Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset; 43 shared_memory->linear_heap_phys_address =
44 Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset;
43 45
44 // Increase the amount of used linear heap memory for the owner process. 46 // Increase the amount of used linear heap memory for the owner process.
45 if (shared_memory->owner_process != nullptr) { 47 if (shared_memory->owner_process != nullptr) {
@@ -51,18 +53,20 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
51 Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); 53 Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
52 } 54 }
53 } else { 55 } else {
54 // TODO(Subv): What happens if an application tries to create multiple memory blocks pointing to the same address? 56 // TODO(Subv): What happens if an application tries to create multiple memory blocks
57 // pointing to the same address?
55 auto& vm_manager = shared_memory->owner_process->vm_manager; 58 auto& vm_manager = shared_memory->owner_process->vm_manager;
56 // The memory is already available and mapped in the owner process. 59 // The memory is already available and mapped in the owner process.
57 auto vma = vm_manager.FindVMA(address)->second; 60 auto vma = vm_manager.FindVMA(address)->second;
58 // Copy it over to our own storage 61 // Copy it over to our own storage
59 shared_memory->backing_block = std::make_shared<std::vector<u8>>(vma.backing_block->data() + vma.offset, 62 shared_memory->backing_block = std::make_shared<std::vector<u8>>(
60 vma.backing_block->data() + vma.offset + size); 63 vma.backing_block->data() + vma.offset, vma.backing_block->data() + vma.offset + size);
61 shared_memory->backing_block_offset = 0; 64 shared_memory->backing_block_offset = 0;
62 // Unmap the existing pages 65 // Unmap the existing pages
63 vm_manager.UnmapRange(address, size); 66 vm_manager.UnmapRange(address, size);
64 // Map our own block into the address space 67 // Map our own block into the address space
65 vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size, MemoryState::Shared); 68 vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size,
69 MemoryState::Shared);
66 // Reprotect the block with the new permissions 70 // Reprotect the block with the new permissions
67 vm_manager.ReprotectRange(address, size, ConvertPermissions(permissions)); 71 vm_manager.ReprotectRange(address, size, ConvertPermissions(permissions));
68 } 72 }
@@ -71,8 +75,11 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
71 return shared_memory; 75 return shared_memory;
72} 76}
73 77
74SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, 78SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block,
75 MemoryPermission permissions, MemoryPermission other_permissions, std::string name) { 79 u32 offset, u32 size,
80 MemoryPermission permissions,
81 MemoryPermission other_permissions,
82 std::string name) {
76 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 83 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
77 84
78 shared_memory->owner_process = nullptr; 85 shared_memory->owner_process = nullptr;
@@ -88,27 +95,31 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vecto
88} 95}
89 96
90ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions, 97ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions,
91 MemoryPermission other_permissions) { 98 MemoryPermission other_permissions) {
92 99
93 MemoryPermission own_other_permissions = target_process == owner_process ? this->permissions : this->other_permissions; 100 MemoryPermission own_other_permissions =
101 target_process == owner_process ? this->permissions : this->other_permissions;
94 102
95 // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare 103 // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare
96 if (base_address == 0 && other_permissions != MemoryPermission::DontCare) { 104 if (base_address == 0 && other_permissions != MemoryPermission::DontCare) {
97 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 105 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
106 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
98 } 107 }
99 108
100 // Error out if the requested permissions don't match what the creator process allows. 109 // 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)) { 110 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", 111 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
103 GetObjectId(), address, name.c_str()); 112 GetObjectId(), address, name.c_str());
104 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 113 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
114 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
105 } 115 }
106 116
107 // Heap-backed memory blocks can not be mapped with other_permissions = DontCare 117 // Heap-backed memory blocks can not be mapped with other_permissions = DontCare
108 if (base_address != 0 && other_permissions == MemoryPermission::DontCare) { 118 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", 119 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
110 GetObjectId(), address, name.c_str()); 120 GetObjectId(), address, name.c_str());
111 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 121 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
122 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
112 } 123 }
113 124
114 // Error out if the provided permissions are not compatible with what the creator process needs. 125 // Error out if the provided permissions are not compatible with what the creator process needs.
@@ -116,12 +127,14 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
116 static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) { 127 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", 128 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
118 GetObjectId(), address, name.c_str()); 129 GetObjectId(), address, name.c_str());
119 return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 130 return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS,
131 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
120 } 132 }
121 133
122 // TODO(Subv): Check for the Shared Device Mem flag in the creator process. 134 // TODO(Subv): Check for the Shared Device Mem flag in the creator process.
123 /*if (was_created_with_shared_device_mem && address != 0) { 135 /*if (was_created_with_shared_device_mem && address != 0) {
124 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 136 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
137 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
125 }*/ 138 }*/
126 139
127 // TODO(Subv): The same process that created a SharedMemory object 140 // TODO(Subv): The same process that created a SharedMemory object
@@ -144,23 +157,29 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
144 } 157 }
145 158
146 // Map the memory block into the target process 159 // 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); 160 auto result = target_process->vm_manager.MapMemoryBlock(
161 target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
148 if (result.Failed()) { 162 if (result.Failed()) {
149 LOG_ERROR(Kernel, "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory", 163 LOG_ERROR(
150 GetObjectId(), target_address, name.c_str()); 164 Kernel,
165 "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory",
166 GetObjectId(), target_address, name.c_str());
151 return result.Code(); 167 return result.Code();
152 } 168 }
153 169
154 return target_process->vm_manager.ReprotectRange(target_address, size, ConvertPermissions(permissions)); 170 return target_process->vm_manager.ReprotectRange(target_address, size,
171 ConvertPermissions(permissions));
155} 172}
156 173
157ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) { 174ResultCode 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. 175 // TODO(Subv): Verify what happens if the application tries to unmap an address that is not
176 // mapped to a SharedMemory.
159 return target_process->vm_manager.UnmapRange(address, size); 177 return target_process->vm_manager.UnmapRange(address, size);
160} 178}
161 179
162VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) { 180VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
163 u32 masked_permissions = static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute); 181 u32 masked_permissions =
182 static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute);
164 return static_cast<VMAPermission>(masked_permissions); 183 return static_cast<VMAPermission>(masked_permissions);
165}; 184};
166 185
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 0c404a9f8..94b335ed1 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -5,9 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <string> 7#include <string>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10
11#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/process.h" 10#include "core/hle/kernel/process.h"
13#include "core/hle/result.h" 11#include "core/hle/result.h"
@@ -16,15 +14,15 @@ namespace Kernel {
16 14
17/// Permissions for mapped shared memory blocks 15/// Permissions for mapped shared memory blocks
18enum class MemoryPermission : u32 { 16enum class MemoryPermission : u32 {
19 None = 0, 17 None = 0,
20 Read = (1u << 0), 18 Read = (1u << 0),
21 Write = (1u << 1), 19 Write = (1u << 1),
22 ReadWrite = (Read | Write), 20 ReadWrite = (Read | Write),
23 Execute = (1u << 2), 21 Execute = (1u << 2),
24 ReadExecute = (Read | Execute), 22 ReadExecute = (Read | Execute),
25 WriteExecute = (Write | Execute), 23 WriteExecute = (Write | Execute),
26 ReadWriteExecute = (Read | Write | Execute), 24 ReadWriteExecute = (Read | Write | Execute),
27 DontCare = (1u << 28) 25 DontCare = (1u << 28)
28}; 26};
29 27
30class SharedMemory final : public Object { 28class SharedMemory final : public Object {
@@ -34,13 +32,18 @@ public:
34 * @param owner_process Process that created this shared memory object. 32 * @param owner_process Process that created this shared memory object.
35 * @param size Size of the memory block. Must be page-aligned. 33 * @param size Size of the memory block. Must be page-aligned.
36 * @param permissions Permission restrictions applied to the process which created the block. 34 * @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. 35 * @param other_permissions Permission restrictions applied to other processes mapping the
36 * block.
38 * @param address The address from which to map the Shared Memory. 37 * @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. 38 * @param region If the address is 0, the shared memory will be allocated in this region of the
39 * linear heap.
40 * @param name Optional object name, used for debugging purposes. 40 * @param name Optional object name, used for debugging purposes.
41 */ 41 */
42 static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, 42 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"); 43 MemoryPermission permissions,
44 MemoryPermission other_permissions, VAddr address = 0,
45 MemoryRegion region = MemoryRegion::BASE,
46 std::string name = "Unknown");
44 47
45 /** 48 /**
46 * Creates a shared memory object from a block of memory managed by an HLE applet. 49 * Creates a shared memory object from a block of memory managed by an HLE applet.
@@ -48,17 +51,27 @@ public:
48 * @param offset The offset into the heap block that the SharedMemory will map. 51 * @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. 52 * @param size Size of the memory block. Must be page-aligned.
50 * @param permissions Permission restrictions applied to the process which created the block. 53 * @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. 54 * @param other_permissions Permission restrictions applied to other processes mapping the
55 * block.
52 * @param name Optional object name, used for debugging purposes. 56 * @param name Optional object name, used for debugging purposes.
53 */ 57 */
54 static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, 58 static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block,
55 MemoryPermission permissions, MemoryPermission other_permissions, std::string name = "Unknown Applet"); 59 u32 offset, u32 size,
56 60 MemoryPermission permissions,
57 std::string GetTypeName() const override { return "SharedMemory"; } 61 MemoryPermission other_permissions,
58 std::string GetName() const override { return name; } 62 std::string name = "Unknown Applet");
63
64 std::string GetTypeName() const override {
65 return "SharedMemory";
66 }
67 std::string GetName() const override {
68 return name;
69 }
59 70
60 static const HandleType HANDLE_TYPE = HandleType::SharedMemory; 71 static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
61 HandleType GetHandleType() const override { return HANDLE_TYPE; } 72 HandleType GetHandleType() const override {
73 return HANDLE_TYPE;
74 }
62 75
63 /** 76 /**
64 * Converts the specified MemoryPermission into the equivalent VMAPermission. 77 * Converts the specified MemoryPermission into the equivalent VMAPermission.
@@ -73,7 +86,8 @@ public:
73 * @param permissions Memory block map permissions (specified by SVC field) 86 * @param permissions Memory block map permissions (specified by SVC field)
74 * @param other_permissions Memory block map other permissions (specified by SVC field) 87 * @param other_permissions Memory block map other permissions (specified by SVC field)
75 */ 88 */
76 ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions, MemoryPermission other_permissions); 89 ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions,
90 MemoryPermission other_permissions);
77 91
78 /** 92 /**
79 * Unmaps a shared memory block from the specified address in system memory 93 * Unmaps a shared memory block from the specified address in system memory
@@ -94,7 +108,8 @@ public:
94 SharedPtr<Process> owner_process; 108 SharedPtr<Process> owner_process;
95 /// Address of shared memory block in the owner process if specified. 109 /// Address of shared memory block in the owner process if specified.
96 VAddr base_address; 110 VAddr base_address;
97 /// Physical address of the shared memory block in the linear heap if no address was specified during creation. 111 /// Physical address of the shared memory block in the linear heap if no address was specified
112 /// during creation.
98 PAddr linear_heap_phys_address; 113 PAddr linear_heap_phys_address;
99 /// Backing memory for this shared memory block. 114 /// Backing memory for this shared memory block.
100 std::shared_ptr<std::vector<u8>> backing_block; 115 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..4486a812c 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -5,23 +5,21 @@
5#include <algorithm> 5#include <algorithm>
6#include <list> 6#include <list>
7#include <vector> 7#include <vector>
8
9#include "common/assert.h" 8#include "common/assert.h"
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12#include "common/math_util.h" 11#include "common/math_util.h"
13#include "common/thread_queue_list.h" 12#include "common/thread_queue_list.h"
14
15#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
16#include "core/arm/skyeye_common/armstate.h" 14#include "core/arm/skyeye_common/armstate.h"
17#include "core/core.h" 15#include "core/core.h"
18#include "core/core_timing.h" 16#include "core/core_timing.h"
19#include "core/hle/hle.h" 17#include "core/hle/hle.h"
20#include "core/hle/kernel/kernel.h" 18#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" 19#include "core/hle/kernel/memory.h"
24#include "core/hle/kernel/mutex.h" 20#include "core/hle/kernel/mutex.h"
21#include "core/hle/kernel/process.h"
22#include "core/hle/kernel/thread.h"
25#include "core/hle/result.h" 23#include "core/hle/result.h"
26#include "core/memory.h" 24#include "core/memory.h"
27 25
@@ -46,7 +44,7 @@ static Kernel::HandleTable wakeup_callback_handle_table;
46static std::vector<SharedPtr<Thread>> thread_list; 44static std::vector<SharedPtr<Thread>> thread_list;
47 45
48// Lists only ready thread ids. 46// Lists only ready thread ids.
49static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> ready_queue; 47static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST + 1> ready_queue;
50 48
51static Thread* current_thread; 49static Thread* current_thread;
52 50
@@ -103,7 +101,7 @@ void Thread::Stop() {
103 101
104 // Clean up thread from ready queue 102 // Clean up thread from ready queue
105 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) 103 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
106 if (status == THREADSTATUS_READY){ 104 if (status == THREADSTATUS_READY) {
107 ready_queue.remove(current_priority, this); 105 ready_queue.remove(current_priority, this);
108 } 106 }
109 107
@@ -119,7 +117,8 @@ void Thread::Stop() {
119 117
120 // Mark the TLS slot in the thread's page as free. 118 // Mark the TLS slot in the thread's page as free.
121 u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; 119 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; 120 u32 tls_slot =
121 ((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); 122 Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot);
124 123
125 HLE::Reschedule(__func__); 124 HLE::Reschedule(__func__);
@@ -137,7 +136,7 @@ Thread* ArbitrateHighestPriorityThread(u32 address) {
137 if (thread == nullptr) 136 if (thread == nullptr)
138 continue; 137 continue;
139 138
140 if(thread->current_priority <= priority) { 139 if (thread->current_priority <= priority) {
141 highest_priority_thread = thread.get(); 140 highest_priority_thread = thread.get();
142 priority = thread->current_priority; 141 priority = thread->current_priority;
143 } 142 }
@@ -170,7 +169,7 @@ static void PriorityBoostStarvedThreads() {
170 // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler 169 // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler
171 // should probably be reversed to verify this. 170 // should probably be reversed to verify this.
172 171
173 const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long 172 const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long
174 173
175 u64 delta = current_ticks - thread->last_running_ticks; 174 u64 delta = current_ticks - thread->last_running_ticks;
176 175
@@ -193,10 +192,12 @@ static std::tuple<u32*, u32*> GetWaitSynchTimeoutParameterRegister(Thread* threa
193 192
194 if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) { 193 if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) {
195 // svc #0x24 (WaitSynchronization1) 194 // svc #0x24 (WaitSynchronization1)
196 return std::make_tuple(&thread->context.cpu_registers[2], &thread->context.cpu_registers[3]); 195 return std::make_tuple(&thread->context.cpu_registers[2],
196 &thread->context.cpu_registers[3]);
197 } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) { 197 } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) {
198 // svc #0x25 (WaitSynchronizationN) 198 // svc #0x25 (WaitSynchronizationN)
199 return std::make_tuple(&thread->context.cpu_registers[0], &thread->context.cpu_registers[4]); 199 return std::make_tuple(&thread->context.cpu_registers[0],
200 &thread->context.cpu_registers[4]);
200 } 201 }
201 202
202 UNREACHABLE(); 203 UNREACHABLE();
@@ -245,7 +246,8 @@ static void SwitchContext(Thread* new_thread) {
245 246
246 // Load context of new thread 247 // Load context of new thread
247 if (new_thread) { 248 if (new_thread) {
248 DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); 249 DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY,
250 "Thread must be ready to become running.");
249 251
250 // Cancel any outstanding wakeup events for this thread 252 // Cancel any outstanding wakeup events for this thread
251 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle); 253 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle);
@@ -263,7 +265,7 @@ static void SwitchContext(Thread* new_thread) {
263 new_thread->context.pc -= thumb_mode ? 2 : 4; 265 new_thread->context.pc -= thumb_mode ? 2 : 4;
264 266
265 // Get the register for timeout parameter 267 // Get the register for timeout parameter
266 u32* timeout_low, *timeout_high; 268 u32 *timeout_low, *timeout_high;
267 std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread); 269 std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread);
268 270
269 // Update the timeout parameter 271 // Update the timeout parameter
@@ -307,7 +309,7 @@ static Thread* PopNextReadyThread() {
307 // Otherwise just keep going with the current thread 309 // Otherwise just keep going with the current thread
308 next = thread; 310 next = thread;
309 } 311 }
310 } else { 312 } else {
311 next = ready_queue.pop_first(); 313 next = ready_queue.pop_first();
312 } 314 }
313 315
@@ -321,7 +323,8 @@ void WaitCurrentThread_Sleep() {
321 HLE::Reschedule(__func__); 323 HLE::Reschedule(__func__);
322} 324}
323 325
324void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all) { 326void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects,
327 bool wait_set_output, bool wait_all) {
325 Thread* thread = GetCurrentThread(); 328 Thread* thread = GetCurrentThread();
326 thread->wait_set_output = wait_set_output; 329 thread->wait_set_output = wait_set_output;
327 thread->wait_all = wait_all; 330 thread->wait_all = wait_all;
@@ -352,7 +355,8 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
352 355
353 if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) { 356 if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) {
354 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, 357 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
355 ErrorSummary::StatusChanged, ErrorLevel::Info)); 358 ErrorSummary::StatusChanged,
359 ErrorLevel::Info));
356 360
357 if (thread->wait_set_output) 361 if (thread->wait_set_output)
358 thread->SetWaitSynchronizationOutput(-1); 362 thread->SetWaitSynchronizationOutput(-1);
@@ -372,25 +376,25 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
372 376
373void Thread::ResumeFromWait() { 377void Thread::ResumeFromWait() {
374 switch (status) { 378 switch (status) {
375 case THREADSTATUS_WAIT_SYNCH: 379 case THREADSTATUS_WAIT_SYNCH:
376 case THREADSTATUS_WAIT_ARB: 380 case THREADSTATUS_WAIT_ARB:
377 case THREADSTATUS_WAIT_SLEEP: 381 case THREADSTATUS_WAIT_SLEEP:
378 break; 382 break;
379 383
380 case THREADSTATUS_READY: 384 case THREADSTATUS_READY:
381 // If the thread is waiting on multiple wait objects, it might be awoken more than once 385 // 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 386 // before actually resuming. We can ignore subsequent wakeups if the thread status has
383 // already been set to THREADSTATUS_READY. 387 // already been set to THREADSTATUS_READY.
384 return; 388 return;
385 389
386 case THREADSTATUS_RUNNING: 390 case THREADSTATUS_RUNNING:
387 DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId()); 391 DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId());
388 return; 392 return;
389 case THREADSTATUS_DEAD: 393 case THREADSTATUS_DEAD:
390 // This should never happen, as threads must complete before being stopped. 394 // 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.", 395 DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.",
392 GetObjectId()); 396 GetObjectId());
393 return; 397 return;
394 } 398 }
395 399
396 ready_queue.push_back(current_priority, this); 400 ready_queue.push_back(current_priority, this);
@@ -405,7 +409,8 @@ static void DebugThreadQueue() {
405 if (!thread) { 409 if (!thread) {
406 LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD"); 410 LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD");
407 } else { 411 } else {
408 LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, GetCurrentThread()->GetObjectId()); 412 LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority,
413 GetCurrentThread()->GetObjectId());
409 } 414 }
410 415
411 for (auto& t : thread_list) { 416 for (auto& t : thread_list) {
@@ -448,7 +453,8 @@ std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& t
448 * @param entry_point Address of entry point for execution 453 * @param entry_point Address of entry point for execution
449 * @param arg User argument for thread 454 * @param arg User argument for thread
450 */ 455 */
451static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) { 456static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point,
457 u32 arg) {
452 memset(&context, 0, sizeof(Core::ThreadContext)); 458 memset(&context, 0, sizeof(Core::ThreadContext));
453 459
454 context.cpu_registers[0] = arg; 460 context.cpu_registers[0] = arg;
@@ -458,11 +464,11 @@ static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32
458} 464}
459 465
460ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, 466ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority,
461 u32 arg, s32 processor_id, VAddr stack_top) { 467 u32 arg, s32 processor_id, VAddr stack_top) {
462 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { 468 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
463 s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 469 s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
464 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", 470 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", name.c_str(),
465 name.c_str(), priority, new_priority); 471 priority, new_priority);
466 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm 472 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
467 // validity of this 473 // validity of this
468 priority = new_priority; 474 priority = new_priority;
@@ -472,7 +478,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); 478 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point);
473 // TODO: Verify error 479 // TODO: Verify error
474 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 480 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
475 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 481 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
476 } 482 }
477 483
478 SharedPtr<Thread> thread(new Thread); 484 SharedPtr<Thread> thread(new Thread);
@@ -511,8 +517,10 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
511 auto& linheap_memory = memory_region->linear_heap_memory; 517 auto& linheap_memory = memory_region->linear_heap_memory;
512 518
513 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { 519 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"); 520 LOG_ERROR(Kernel_SVC,
515 return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel, ErrorSummary::OutOfResource, ErrorLevel::Permanent); 521 "Not enough space in region to allocate a new TLS page for thread");
522 return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
523 ErrorSummary::OutOfResource, ErrorLevel::Permanent);
516 } 524 }
517 525
518 u32 offset = linheap_memory->size(); 526 u32 offset = linheap_memory->size();
@@ -537,7 +545,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
537 545
538 // Mark the slot as used 546 // Mark the slot as used
539 tls_slots[available_page].set(available_slot); 547 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; 548 thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE +
549 available_slot * Memory::TLS_ENTRY_SIZE;
541 550
542 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used 551 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
543 // to initialize the context 552 // to initialize the context
@@ -551,10 +560,12 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
551 return MakeResult<SharedPtr<Thread>>(std::move(thread)); 560 return MakeResult<SharedPtr<Thread>>(std::move(thread));
552} 561}
553 562
554// TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be returned. 563// TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be
564// returned.
555static void ClampPriority(const Thread* thread, s32* priority) { 565static void ClampPriority(const Thread* thread, s32* priority) {
556 if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) { 566 if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) {
557 DEBUG_ASSERT_MSG(false, "Application passed an out of range priority. An error should be returned."); 567 DEBUG_ASSERT_MSG(
568 false, "Application passed an out of range priority. An error should be returned.");
558 569
559 s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 570 s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
560 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", 571 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d",
@@ -586,12 +597,13 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) {
586 DEBUG_ASSERT(!GetCurrentThread()); 597 DEBUG_ASSERT(!GetCurrentThread());
587 598
588 // Initialize new "main" thread 599 // Initialize new "main" thread
589 auto thread_res = Thread::Create("main", entry_point, priority, 0, 600 auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0,
590 THREADPROCESSORID_0, Memory::HEAP_VADDR_END); 601 Memory::HEAP_VADDR_END);
591 602
592 SharedPtr<Thread> thread = thread_res.MoveFrom(); 603 SharedPtr<Thread> thread = thread_res.MoveFrom();
593 604
594 thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010 605 thread->context.fpscr =
606 FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010
595 607
596 // Run new "main" thread 608 // Run new "main" thread
597 SwitchContext(thread.get()); 609 SwitchContext(thread.get());
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index deab5d5a6..f63131716 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -6,40 +6,36 @@
6 6
7#include <string> 7#include <string>
8#include <vector> 8#include <vector>
9
10#include <boost/container/flat_set.hpp> 9#include <boost/container/flat_set.hpp>
11
12#include "common/common_types.h" 10#include "common/common_types.h"
13
14#include "core/core.h" 11#include "core/core.h"
15
16#include "core/hle/hle.h" 12#include "core/hle/hle.h"
17#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
18#include "core/hle/result.h" 14#include "core/hle/result.h"
19 15
20enum ThreadPriority : s32{ 16enum ThreadPriority : s32 {
21 THREADPRIO_HIGHEST = 0, ///< Highest thread priority 17 THREADPRIO_HIGHEST = 0, ///< Highest thread priority
22 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps 18 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps
23 THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps 19 THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps
24 THREADPRIO_LOWEST = 63, ///< Lowest thread priority 20 THREADPRIO_LOWEST = 63, ///< Lowest thread priority
25}; 21};
26 22
27enum ThreadProcessorId : s32 { 23enum ThreadProcessorId : s32 {
28 THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader 24 THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader
29 THREADPROCESSORID_ALL = -1, ///< Run thread on either core 25 THREADPROCESSORID_ALL = -1, ///< Run thread on either core
30 THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore) 26 THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore)
31 THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore) 27 THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore)
32 THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this 28 THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this
33}; 29};
34 30
35enum ThreadStatus { 31enum ThreadStatus {
36 THREADSTATUS_RUNNING, ///< Currently running 32 THREADSTATUS_RUNNING, ///< Currently running
37 THREADSTATUS_READY, ///< Ready to run 33 THREADSTATUS_READY, ///< Ready to run
38 THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter 34 THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter
39 THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC 35 THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC
40 THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC 36 THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC
41 THREADSTATUS_DORMANT, ///< Created but not yet made ready 37 THREADSTATUS_DORMANT, ///< Created but not yet made ready
42 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated 38 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
43}; 39};
44 40
45namespace Kernel { 41namespace Kernel {
@@ -60,13 +56,19 @@ public:
60 * @return A shared pointer to the newly created thread 56 * @return A shared pointer to the newly created thread
61 */ 57 */
62 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, 58 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
63 u32 arg, s32 processor_id, VAddr stack_top); 59 u32 arg, s32 processor_id, VAddr stack_top);
64 60
65 std::string GetName() const override { return name; } 61 std::string GetName() const override {
66 std::string GetTypeName() const override { return "Thread"; } 62 return name;
63 }
64 std::string GetTypeName() const override {
65 return "Thread";
66 }
67 67
68 static const HandleType HANDLE_TYPE = HandleType::Thread; 68 static const HandleType HANDLE_TYPE = HandleType::Thread;
69 HandleType GetHandleType() const override { return HANDLE_TYPE; } 69 HandleType GetHandleType() const override {
70 return HANDLE_TYPE;
71 }
70 72
71 bool ShouldWait() override; 73 bool ShouldWait() override;
72 void Acquire() override; 74 void Acquire() override;
@@ -75,7 +77,9 @@ public:
75 * Gets the thread's current priority 77 * Gets the thread's current priority
76 * @return The current thread's priority 78 * @return The current thread's priority
77 */ 79 */
78 s32 GetPriority() const { return current_priority; } 80 s32 GetPriority() const {
81 return current_priority;
82 }
79 83
80 /** 84 /**
81 * Sets the thread's current priority 85 * Sets the thread's current priority
@@ -93,7 +97,9 @@ public:
93 * Gets the thread's thread ID 97 * Gets the thread's thread ID
94 * @return The thread's ID 98 * @return The thread's ID
95 */ 99 */
96 u32 GetThreadId() const { return thread_id; } 100 u32 GetThreadId() const {
101 return thread_id;
102 }
97 103
98 /** 104 /**
99 * Resumes a thread from waiting 105 * Resumes a thread from waiting
@@ -127,7 +133,9 @@ public:
127 * Returns the Thread Local Storage address of the current thread 133 * Returns the Thread Local Storage address of the current thread
128 * @returns VAddr of the thread's TLS 134 * @returns VAddr of the thread's TLS
129 */ 135 */
130 VAddr GetTLSAddress() const { return tls_address; } 136 VAddr GetTLSAddress() const {
137 return tls_address;
138 }
131 139
132 Core::ThreadContext context; 140 Core::ThreadContext context;
133 141
@@ -137,8 +145,8 @@ public:
137 u32 entry_point; 145 u32 entry_point;
138 u32 stack_top; 146 u32 stack_top;
139 147
140 s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application 148 s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application
141 s32 current_priority; ///< Current thread priority, can be temporarily changed 149 s32 current_priority; ///< Current thread priority, can be temporarily changed
142 150
143 u64 last_running_ticks; ///< CPU tick when thread was last running 151 u64 last_running_ticks; ///< CPU tick when thread was last running
144 152
@@ -151,11 +159,11 @@ public:
151 /// Mutexes currently held by this thread, which will be released when it exits. 159 /// Mutexes currently held by this thread, which will be released when it exits.
152 boost::container::flat_set<SharedPtr<Mutex>> held_mutexes; 160 boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
153 161
154 SharedPtr<Process> owner_process; ///< Process that owns this thread 162 SharedPtr<Process> owner_process; ///< Process that owns this thread
155 std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on 163 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 164 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 165 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 166 bool wait_set_output; ///< True if the output parameter should be set on thread wakeup
159 167
160 std::string name; 168 std::string name;
161 169
@@ -205,10 +213,12 @@ void WaitCurrentThread_Sleep();
205/** 213/**
206 * Waits the current thread from a WaitSynchronization call 214 * Waits the current thread from a WaitSynchronization call
207 * @param wait_objects Kernel objects that we are waiting on 215 * @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) 216 * @param wait_set_output If true, set the output parameter on thread wakeup (for
217 * WaitSynchronizationN only)
209 * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only) 218 * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only)
210 */ 219 */
211void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all); 220void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects,
221 bool wait_set_output, bool wait_all);
212 222
213/** 223/**
214 * Waits the current thread from an ArbitrateAddress call 224 * 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..a9f98223c 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -3,14 +3,12 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cinttypes> 5#include <cinttypes>
6
7#include "common/assert.h" 6#include "common/assert.h"
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9
10#include "core/core_timing.h" 8#include "core/core_timing.h"
11#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/timer.h"
13#include "core/hle/kernel/thread.h" 10#include "core/hle/kernel/thread.h"
11#include "core/hle/kernel/timer.h"
14 12
15namespace Kernel { 13namespace Kernel {
16 14
@@ -41,7 +39,7 @@ bool Timer::ShouldWait() {
41} 39}
42 40
43void Timer::Acquire() { 41void Timer::Acquire() {
44 ASSERT_MSG( !ShouldWait(), "object unavailable!"); 42 ASSERT_MSG(!ShouldWait(), "object unavailable!");
45 43
46 if (reset_type == ResetType::OneShot) 44 if (reset_type == ResetType::OneShot)
47 signaled = false; 45 signaled = false;
@@ -55,8 +53,8 @@ void Timer::Set(s64 initial, s64 interval) {
55 interval_delay = interval; 53 interval_delay = interval;
56 54
57 u64 initial_microseconds = initial / 1000; 55 u64 initial_microseconds = initial / 1000;
58 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), 56 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type,
59 timer_callback_event_type, callback_handle); 57 callback_handle);
60 58
61 HLE::Reschedule(__func__); 59 HLE::Reschedule(__func__);
62} 60}
@@ -73,7 +71,8 @@ void Timer::Clear() {
73 71
74/// The timer callback event, called when a timer is fired 72/// The timer callback event, called when a timer is fired
75static void TimerCallback(u64 timer_handle, int cycles_late) { 73static void TimerCallback(u64 timer_handle, int cycles_late) {
76 SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); 74 SharedPtr<Timer> timer =
75 timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle));
77 76
78 if (timer == nullptr) { 77 if (timer == nullptr) {
79 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle); 78 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle);
@@ -91,7 +90,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
91 // Reschedule the timer with the interval delay 90 // Reschedule the timer with the interval delay
92 u64 interval_microseconds = timer->interval_delay / 1000; 91 u64 interval_microseconds = timer->interval_delay / 1000;
93 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, 92 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
94 timer_callback_event_type, timer_handle); 93 timer_callback_event_type, timer_handle);
95 } 94 }
96} 95}
97 96
@@ -100,7 +99,6 @@ void TimersInit() {
100 timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback); 99 timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
101} 100}
102 101
103void TimersShutdown() { 102void TimersShutdown() {}
104}
105 103
106} // namespace 104} // namespace
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index b1db60e8f..59a77aad3 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8
9#include "core/hle/kernel/event.h" 8#include "core/hle/kernel/event.h"
10#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
11 10
@@ -21,19 +20,25 @@ public:
21 */ 20 */
22 static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown"); 21 static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown");
23 22
24 std::string GetTypeName() const override { return "Timer"; } 23 std::string GetTypeName() const override {
25 std::string GetName() const override { return name; } 24 return "Timer";
25 }
26 std::string GetName() const override {
27 return name;
28 }
26 29
27 static const HandleType HANDLE_TYPE = HandleType::Timer; 30 static const HandleType HANDLE_TYPE = HandleType::Timer;
28 HandleType GetHandleType() const override { return HANDLE_TYPE; } 31 HandleType GetHandleType() const override {
32 return HANDLE_TYPE;
33 }
29 34
30 ResetType reset_type; ///< The ResetType of this timer 35 ResetType reset_type; ///< The ResetType of this timer
31 36
32 bool signaled; ///< Whether the timer has been signaled or not 37 bool signaled; ///< Whether the timer has been signaled or not
33 std::string name; ///< Name of timer (optional) 38 std::string name; ///< Name of timer (optional)
34 39
35 u64 initial_delay; ///< The delay until the timer fires for the first time 40 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 41 u64 interval_delay; ///< The delay until the timer fires after the first time
37 42
38 bool ShouldWait() override; 43 bool ShouldWait() override;
39 void Acquire() override; 44 void Acquire() override;
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 066146cff..6dd24f846 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -3,9 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <iterator> 5#include <iterator>
6
7#include "common/assert.h" 6#include "common/assert.h"
8
9#include "core/hle/kernel/vm_manager.h" 7#include "core/hle/kernel/vm_manager.h"
10#include "core/memory.h" 8#include "core/memory.h"
11#include "core/memory_setup.h" 9#include "core/memory_setup.h"
@@ -15,8 +13,8 @@ namespace Kernel {
15 13
16static const char* GetMemoryStateName(MemoryState state) { 14static const char* GetMemoryStateName(MemoryState state) {
17 static const char* names[] = { 15 static const char* names[] = {
18 "Free", "Reserved", "IO", "Static", "Code", "Private", "Shared", "Continuous", "Aliased", 16 "Free", "Reserved", "IO", "Static", "Code", "Private",
19 "Alias", "AliasCode", "Locked", 17 "Shared", "Continuous", "Aliased", "Alias", "AliasCode", "Locked",
20 }; 18 };
21 19
22 return names[(int)state]; 20 return names[(int)state];
@@ -24,13 +22,12 @@ static const char* GetMemoryStateName(MemoryState state) {
24 22
25bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { 23bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
26 ASSERT(base + size == next.base); 24 ASSERT(base + size == next.base);
27 if (permissions != next.permissions || 25 if (permissions != next.permissions || meminfo_state != next.meminfo_state ||
28 meminfo_state != next.meminfo_state || 26 type != next.type) {
29 type != next.type) {
30 return false; 27 return false;
31 } 28 }
32 if (type == VMAType::AllocatedMemoryBlock && 29 if (type == VMAType::AllocatedMemoryBlock &&
33 (backing_block != next.backing_block || offset + size != next.offset)) { 30 (backing_block != next.backing_block || offset + size != next.offset)) {
34 return false; 31 return false;
35 } 32 }
36 if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) { 33 if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) {
@@ -70,7 +67,9 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const {
70} 67}
71 68
72ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, 69ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
73 std::shared_ptr<std::vector<u8>> block, size_t offset, u32 size, MemoryState state) { 70 std::shared_ptr<std::vector<u8>> block,
71 size_t offset, u32 size,
72 MemoryState state) {
74 ASSERT(block != nullptr); 73 ASSERT(block != nullptr);
75 ASSERT(offset + size <= block->size()); 74 ASSERT(offset + size <= block->size());
76 75
@@ -89,7 +88,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
89 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); 88 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
90} 89}
91 90
92ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * memory, u32 size, MemoryState state) { 91ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* memory, u32 size,
92 MemoryState state) {
93 ASSERT(memory != nullptr); 93 ASSERT(memory != nullptr);
94 94
95 // This is the appropriately sized VMA that will turn into our allocation. 95 // This is the appropriately sized VMA that will turn into our allocation.
@@ -106,7 +106,9 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * m
106 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); 106 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
107} 107}
108 108
109ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler) { 109ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size,
110 MemoryState state,
111 Memory::MMIORegionPointer mmio_handler) {
110 // This is the appropriately sized VMA that will turn into our allocation. 112 // This is the appropriately sized VMA that will turn into our allocation.
111 CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size)); 113 CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size));
112 VirtualMemoryArea& final_vma = vma_handle->second; 114 VirtualMemoryArea& final_vma = vma_handle->second;
@@ -191,15 +193,16 @@ void VMManager::RefreshMemoryBlockMappings(const std::vector<u8>* block) {
191void VMManager::LogLayout(Log::Level log_level) const { 193void VMManager::LogLayout(Log::Level log_level) const {
192 for (const auto& p : vma_map) { 194 for (const auto& p : vma_map) {
193 const VirtualMemoryArea& vma = p.second; 195 const VirtualMemoryArea& vma = p.second;
194 LOG_GENERIC(Log::Class::Kernel, log_level, "%08X - %08X size: %8X %c%c%c %s", 196 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, 197 vma.base + vma.size, vma.size,
196 (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-', 198 (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-',
197 (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-', 199 (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-',
198 (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-', GetMemoryStateName(vma.meminfo_state)); 200 (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-',
201 GetMemoryStateName(vma.meminfo_state));
199 } 202 }
200} 203}
201 204
202VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { 205VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) {
203 // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given 206 // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given
204 // non-const access to its container. 207 // non-const access to its container.
205 return vma_map.erase(iter, iter); // Erases an empty range of elements 208 return vma_map.erase(iter, iter); // Erases an empty range of elements
@@ -337,5 +340,4 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
337 break; 340 break;
338 } 341 }
339} 342}
340
341} 343}
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 91d40655b..9055664b2 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -7,21 +7,19 @@
7#include <map> 7#include <map>
8#include <memory> 8#include <memory>
9#include <vector> 9#include <vector>
10
11#include "common/common_types.h" 10#include "common/common_types.h"
12
13#include "core/hle/result.h" 11#include "core/hle/result.h"
14#include "core/mmio.h" 12#include "core/mmio.h"
15 13
16namespace Kernel { 14namespace Kernel {
17 15
18const ResultCode ERR_INVALID_ADDRESS{ // 0xE0E01BF5 16const ResultCode ERR_INVALID_ADDRESS{// 0xE0E01BF5
19 ErrorDescription::InvalidAddress, ErrorModule::OS, 17 ErrorDescription::InvalidAddress, ErrorModule::OS,
20 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 18 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
21 19
22const ResultCode ERR_INVALID_ADDRESS_STATE{ // 0xE0A01BF5 20const ResultCode ERR_INVALID_ADDRESS_STATE{// 0xE0A01BF5
23 ErrorDescription::InvalidAddress, ErrorModule::OS, 21 ErrorDescription::InvalidAddress, ErrorModule::OS,
24 ErrorSummary::InvalidState, ErrorLevel::Usage}; 22 ErrorSummary::InvalidState, ErrorLevel::Usage};
25 23
26enum class VMAType : u8 { 24enum class VMAType : u8 {
27 /// VMA represents an unmapped region of the address space. 25 /// VMA represents an unmapped region of the address space.
@@ -115,7 +113,8 @@ class VMManager final {
115 // TODO(yuriks): Make page tables switchable to support multiple VMManagers 113 // TODO(yuriks): Make page tables switchable to support multiple VMManagers
116public: 114public:
117 /** 115 /**
118 * The maximum amount of address space managed by the kernel. Addresses above this are never used. 116 * The maximum amount of address space managed by the kernel. Addresses above this are never
117 * used.
119 * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000. 118 * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000.
120 */ 119 */
121 static const u32 MAX_ADDRESS = 0x40000000; 120 static const u32 MAX_ADDRESS = 0x40000000;
@@ -151,7 +150,7 @@ public:
151 * @param state MemoryState tag to attach to the VMA. 150 * @param state MemoryState tag to attach to the VMA.
152 */ 151 */
153 ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block, 152 ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block,
154 size_t offset, u32 size, MemoryState state); 153 size_t offset, u32 size, MemoryState state);
155 154
156 /** 155 /**
157 * Maps an unmanaged host memory pointer at a given address. 156 * Maps an unmanaged host memory pointer at a given address.
@@ -172,7 +171,8 @@ public:
172 * @param state MemoryState tag to attach to the VMA. 171 * @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. 172 * @param mmio_handler The handler that will implement read and write for this MMIO region.
174 */ 173 */
175 ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler); 174 ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state,
175 Memory::MMIORegionPointer mmio_handler);
176 176
177 /// Unmaps a range of addresses, splitting VMAs as necessary. 177 /// Unmaps a range of addresses, splitting VMAs as necessary.
178 ResultCode UnmapRange(VAddr target, u32 size); 178 ResultCode UnmapRange(VAddr target, u32 size);
@@ -228,5 +228,4 @@ private:
228 /// Updates the pages corresponding to this VMA so they match the VMA's attributes. 228 /// Updates the pages corresponding to this VMA so they match the VMA's attributes.
229 void UpdatePageTableForVMA(const VirtualMemoryArea& vma); 229 void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
230}; 230};
231
232} 231}
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 268a8dad2..7f8d8e00d 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -6,7 +6,6 @@
6 6
7#include <new> 7#include <new>
8#include <utility> 8#include <utility>
9
10#include "common/assert.h" 9#include "common/assert.h"
11#include "common/bit_field.h" 10#include "common/bit_field.h"
12#include "common/common_funcs.h" 11#include "common/common_funcs.h"
@@ -26,7 +25,8 @@ enum class ErrorDescription : u32 {
26 FS_InvalidOpenFlags = 230, 25 FS_InvalidOpenFlags = 230,
27 FS_NotAFile = 250, 26 FS_NotAFile = 250,
28 FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive 27 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 28 OutofRangeOrMisalignedAddress =
29 513, // TODO(purpasmart): Check if this name fits its actual usage
30 GPU_FirstInitialization = 519, 30 GPU_FirstInitialization = 519,
31 FS_InvalidPath = 702, 31 FS_InvalidPath = 702,
32 InvalidSection = 1000, 32 InvalidSection = 1000,
@@ -168,15 +168,15 @@ enum class ErrorSummary : u32 {
168 Success = 0, 168 Success = 0,
169 NothingHappened = 1, 169 NothingHappened = 1,
170 WouldBlock = 2, 170 WouldBlock = 2,
171 OutOfResource = 3, ///< There are no more kernel resources (memory, table slots) to 171 OutOfResource = 3, ///< There are no more kernel resources (memory, table slots) to
172 ///< execute the operation. 172 ///< execute the operation.
173 NotFound = 4, ///< A file or resource was not found. 173 NotFound = 4, ///< A file or resource was not found.
174 InvalidState = 5, 174 InvalidState = 5,
175 NotSupported = 6, ///< The operation is not supported or not implemented. 175 NotSupported = 6, ///< The operation is not supported or not implemented.
176 InvalidArgument = 7, ///< Returned when a passed argument is invalid in the current runtime 176 InvalidArgument = 7, ///< Returned when a passed argument is invalid in the current runtime
177 ///< context. (Invalid handle, out-of-bounds pointer or size, etc.) 177 ///< 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 178 WrongArgument = 8, ///< Returned when a passed argument is in an incorrect format for use
179 ///< with the function. (E.g. Invalid enum value) 179 ///< with the function. (E.g. Invalid enum value)
180 Canceled = 9, 180 Canceled = 9,
181 StatusChanged = 10, 181 StatusChanged = 10,
182 Internal = 11, 182 Internal = 11,
@@ -208,19 +208,24 @@ union ResultCode {
208 BitField<21, 6, ErrorSummary> summary; 208 BitField<21, 6, ErrorSummary> summary;
209 BitField<27, 5, ErrorLevel> level; 209 BitField<27, 5, ErrorLevel> level;
210 210
211 // The last bit of `level` is checked by apps and the kernel to determine if a result code is an error 211 // The last bit of `level` is checked by apps and the kernel to determine if a result code is an
212 // error
212 BitField<31, 1, u32> is_error; 213 BitField<31, 1, u32> is_error;
213 214
214 explicit ResultCode(u32 raw) : raw(raw) {} 215 explicit ResultCode(u32 raw) : raw(raw) {}
215 ResultCode(ErrorDescription description_, ErrorModule module_, 216 ResultCode(ErrorDescription description_, ErrorModule module_, ErrorSummary summary_,
216 ErrorSummary summary_, ErrorLevel level_) : raw(0) { 217 ErrorLevel level_)
218 : raw(0) {
217 description.Assign(description_); 219 description.Assign(description_);
218 module.Assign(module_); 220 module.Assign(module_);
219 summary.Assign(summary_); 221 summary.Assign(summary_);
220 level.Assign(level_); 222 level.Assign(level_);
221 } 223 }
222 224
223 ResultCode& operator=(const ResultCode& o) { raw = o.raw; return *this; } 225 ResultCode& operator=(const ResultCode& o) {
226 raw = o.raw;
227 return *this;
228 }
224 229
225 bool IsSuccess() const { 230 bool IsSuccess() const {
226 return is_error == 0; 231 return is_error == 0;
@@ -246,8 +251,8 @@ const ResultCode RESULT_SUCCESS(0);
246 251
247/// Might be returned instead of a dummy success for unimplemented APIs. 252/// Might be returned instead of a dummy success for unimplemented APIs.
248inline ResultCode UnimplementedFunction(ErrorModule module) { 253inline ResultCode UnimplementedFunction(ErrorModule module) {
249 return ResultCode(ErrorDescription::NotImplemented, module, 254 return ResultCode(ErrorDescription::NotImplemented, module, ErrorSummary::NotSupported,
250 ErrorSummary::NotSupported, ErrorLevel::Permanent); 255 ErrorLevel::Permanent);
251} 256}
252 257
253/** 258/**
@@ -285,10 +290,9 @@ inline ResultCode UnimplementedFunction(ErrorModule module) {
285template <typename T> 290template <typename T>
286class ResultVal { 291class ResultVal {
287public: 292public:
288 /// Constructs an empty `ResultVal` with the given error code. The code must not be a success code. 293 /// Constructs an empty `ResultVal` with the given error code. The code must not be a success
289 ResultVal(ResultCode error_code = ResultCode(-1)) 294 /// code.
290 : result_code(error_code) 295 ResultVal(ResultCode error_code = ResultCode(-1)) : result_code(error_code) {
291 {
292 ASSERT(error_code.IsError()); 296 ASSERT(error_code.IsError());
293 } 297 }
294 298
@@ -303,17 +307,13 @@ public:
303 return result; 307 return result;
304 } 308 }
305 309
306 ResultVal(const ResultVal& o) 310 ResultVal(const ResultVal& o) : result_code(o.result_code) {
307 : result_code(o.result_code)
308 {
309 if (!o.empty()) { 311 if (!o.empty()) {
310 new (&object) T(o.object); 312 new (&object) T(o.object);
311 } 313 }
312 } 314 }
313 315
314 ResultVal(ResultVal&& o) 316 ResultVal(ResultVal&& o) : result_code(o.result_code) {
315 : result_code(o.result_code)
316 {
317 if (!o.empty()) { 317 if (!o.empty()) {
318 new (&object) T(std::move(o.object)); 318 new (&object) T(std::move(o.object));
319 } 319 }
@@ -357,19 +357,35 @@ public:
357 } 357 }
358 358
359 /// Returns true if the `ResultVal` contains an error code and no value. 359 /// Returns true if the `ResultVal` contains an error code and no value.
360 bool empty() const { return result_code.IsError(); } 360 bool empty() const {
361 return result_code.IsError();
362 }
361 363
362 /// Returns true if the `ResultVal` contains a return value. 364 /// Returns true if the `ResultVal` contains a return value.
363 bool Succeeded() const { return result_code.IsSuccess(); } 365 bool Succeeded() const {
366 return result_code.IsSuccess();
367 }
364 /// Returns true if the `ResultVal` contains an error code and no value. 368 /// Returns true if the `ResultVal` contains an error code and no value.
365 bool Failed() const { return empty(); } 369 bool Failed() const {
370 return empty();
371 }
366 372
367 ResultCode Code() const { return result_code; } 373 ResultCode Code() const {
374 return result_code;
375 }
368 376
369 const T& operator* () const { return object; } 377 const T& operator*() const {
370 T& operator* () { return object; } 378 return object;
371 const T* operator->() const { return &object; } 379 }
372 T* operator->() { return &object; } 380 T& operator*() {
381 return object;
382 }
383 const T* operator->() const {
384 return &object;
385 }
386 T* operator->() {
387 return &object;
388 }
373 389
374 /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing. 390 /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
375 template <typename U> 391 template <typename U>
@@ -390,7 +406,9 @@ public:
390private: 406private:
391 // A union is used to allocate the storage for the value, while allowing us to construct and 407 // A union is used to allocate the storage for the value, while allowing us to construct and
392 // destruct it at will. 408 // destruct it at will.
393 union { T object; }; 409 union {
410 T object;
411 };
394 ResultCode result_code; 412 ResultCode result_code;
395}; 413};
396 414
@@ -409,8 +427,8 @@ ResultVal<T> MakeResult(Args&&... args) {
409 * variable declaration. If it fails the return code is returned from the current function. Thus it 427 * 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. 428 * can be used to cascade errors out, achieving something akin to exception handling.
411 */ 429 */
412#define CASCADE_RESULT(target, source) \ 430#define CASCADE_RESULT(target, source) \
413 auto CONCAT2(check_result_L, __LINE__) = source; \ 431 auto CONCAT2(check_result_L, __LINE__) = source; \
414 if (CONCAT2(check_result_L, __LINE__).Failed()) \ 432 if (CONCAT2(check_result_L, __LINE__).Failed()) \
415 return CONCAT2(check_result_L, __LINE__).Code(); \ 433 return CONCAT2(check_result_L, __LINE__).Code(); \
416 target = std::move(*CONCAT2(check_result_L, __LINE__)) 434 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..12d94f37a 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6
7#include "core/hle/kernel/event.h" 6#include "core/hle/kernel/event.h"
8#include "core/hle/service/ac_u.h" 7#include "core/hle/service/ac_u.h"
9 8
@@ -47,7 +46,7 @@ static void GetWifiStatus(Service::Interface* self) {
47 // it returns a valid result without implementing full functionality. 46 // it returns a valid result without implementing full functionality.
48 47
49 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 48 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
50 cmd_buff[2] = 0; // Connection type set to none 49 cmd_buff[2] = 0; // Connection type set to none
51 50
52 LOG_WARNING(Service_AC, "(STUBBED) called"); 51 LOG_WARNING(Service_AC, "(STUBBED) called");
53} 52}
@@ -62,29 +61,29 @@ static void IsConnected(Service::Interface* self) {
62 u32* cmd_buff = Kernel::GetCommandBuffer(); 61 u32* cmd_buff = Kernel::GetCommandBuffer();
63 62
64 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 63 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
65 cmd_buff[2] = false; // Not connected to ac:u service 64 cmd_buff[2] = false; // Not connected to ac:u service
66 65
67 LOG_WARNING(Service_AC, "(STUBBED) called"); 66 LOG_WARNING(Service_AC, "(STUBBED) called");
68} 67}
69 68
70const Interface::FunctionInfo FunctionTable[] = { 69const Interface::FunctionInfo FunctionTable[] = {
71 {0x00010000, nullptr, "CreateDefaultConfig"}, 70 {0x00010000, nullptr, "CreateDefaultConfig"},
72 {0x00040006, nullptr, "ConnectAsync"}, 71 {0x00040006, nullptr, "ConnectAsync"},
73 {0x00050002, nullptr, "GetConnectResult"}, 72 {0x00050002, nullptr, "GetConnectResult"},
74 {0x00080004, CloseAsync, "CloseAsync"}, 73 {0x00080004, CloseAsync, "CloseAsync"},
75 {0x00090002, nullptr, "GetCloseResult"}, 74 {0x00090002, nullptr, "GetCloseResult"},
76 {0x000A0000, nullptr, "GetLastErrorCode"}, 75 {0x000A0000, nullptr, "GetLastErrorCode"},
77 {0x000D0000, GetWifiStatus, "GetWifiStatus"}, 76 {0x000D0000, GetWifiStatus, "GetWifiStatus"},
78 {0x000E0042, nullptr, "GetCurrentAPInfo"}, 77 {0x000E0042, nullptr, "GetCurrentAPInfo"},
79 {0x00100042, nullptr, "GetCurrentNZoneInfo"}, 78 {0x00100042, nullptr, "GetCurrentNZoneInfo"},
80 {0x00110042, nullptr, "GetNZoneApNumService"}, 79 {0x00110042, nullptr, "GetNZoneApNumService"},
81 {0x00240042, nullptr, "AddDenyApType"}, 80 {0x00240042, nullptr, "AddDenyApType"},
82 {0x00270002, nullptr, "GetInfraPriority"}, 81 {0x00270002, nullptr, "GetInfraPriority"},
83 {0x002D0082, nullptr, "SetRequestEulaVersion"}, 82 {0x002D0082, nullptr, "SetRequestEulaVersion"},
84 {0x00300004, nullptr, "RegisterDisconnectEvent"}, 83 {0x00300004, nullptr, "RegisterDisconnectEvent"},
85 {0x003C0042, nullptr, "GetAPSSIDList"}, 84 {0x003C0042, nullptr, "GetAPSSIDList"},
86 {0x003E0042, IsConnected, "IsConnected"}, 85 {0x003E0042, IsConnected, "IsConnected"},
87 {0x00400042, nullptr, "SetClientVersion"}, 86 {0x00400042, nullptr, "SetClientVersion"},
88}; 87};
89 88
90//////////////////////////////////////////////////////////////////////////////////////////////////// 89////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 3f71e7f2b..f7a990d69 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -3,22 +3,20 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cinttypes> 5#include <cinttypes>
6
7#include "common/logging/log.h" 6#include "common/logging/log.h"
8
9#include "core/hle/service/service.h"
10#include "core/hle/service/am/am.h" 7#include "core/hle/service/am/am.h"
11#include "core/hle/service/am/am_app.h" 8#include "core/hle/service/am/am_app.h"
12#include "core/hle/service/am/am_net.h" 9#include "core/hle/service/am/am_net.h"
13#include "core/hle/service/am/am_sys.h" 10#include "core/hle/service/am/am_sys.h"
14#include "core/hle/service/am/am_u.h" 11#include "core/hle/service/am/am_u.h"
12#include "core/hle/service/service.h"
15 13
16namespace Service { 14namespace Service {
17namespace AM { 15namespace AM {
18 16
19static std::array<u32, 3> am_content_count = { 0, 0, 0 }; 17static std::array<u32, 3> am_content_count = {0, 0, 0};
20static std::array<u32, 3> am_titles_count = { 0, 0, 0 }; 18static std::array<u32, 3> am_titles_count = {0, 0, 0};
21static std::array<u32, 3> am_titles_list_count = { 0, 0, 0 }; 19static std::array<u32, 3> am_titles_list_count = {0, 0, 0};
22static u32 am_ticket_count = 0; 20static u32 am_ticket_count = 0;
23static u32 am_ticket_list_count = 0; 21static u32 am_ticket_list_count = 0;
24 22
@@ -29,7 +27,8 @@ void GetTitleCount(Service::Interface* self) {
29 27
30 cmd_buff[1] = RESULT_SUCCESS.raw; 28 cmd_buff[1] = RESULT_SUCCESS.raw;
31 cmd_buff[2] = am_titles_count[media_type]; 29 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]); 30 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_count=0x%08x", media_type,
31 am_titles_count[media_type]);
33} 32}
34 33
35void FindContentInfos(Service::Interface* self) { 34void FindContentInfos(Service::Interface* self) {
@@ -43,8 +42,10 @@ void FindContentInfos(Service::Interface* self) {
43 am_content_count[media_type] = cmd_buff[4]; 42 am_content_count[media_type] = cmd_buff[4];
44 43
45 cmd_buff[1] = RESULT_SUCCESS.raw; 44 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", 45 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); 46 "content_ids_pointer=0x%08x, content_info_pointer=0x%08x",
47 media_type, title_id, am_content_count[media_type], content_ids_pointer,
48 content_info_pointer);
48} 49}
49 50
50void ListContentInfos(Service::Interface* self) { 51void ListContentInfos(Service::Interface* self) {
@@ -59,8 +60,10 @@ void ListContentInfos(Service::Interface* self) {
59 60
60 cmd_buff[1] = RESULT_SUCCESS.raw; 61 cmd_buff[1] = RESULT_SUCCESS.raw;
61 cmd_buff[2] = am_content_count[media_type]; 62 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", 63 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); 64 ", start_index=0x%08x, content_info_pointer=0x%08X",
65 media_type, am_content_count[media_type], title_id, start_index,
66 content_info_pointer);
64} 67}
65 68
66void DeleteContents(Service::Interface* self) { 69void DeleteContents(Service::Interface* self) {
@@ -73,8 +76,9 @@ void DeleteContents(Service::Interface* self) {
73 am_content_count[media_type] = cmd_buff[4]; 76 am_content_count[media_type] = cmd_buff[4];
74 77
75 cmd_buff[1] = RESULT_SUCCESS.raw; 78 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", 79 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); 80 ", content_count=%u, content_ids_pointer=0x%08x",
81 media_type, title_id, am_content_count[media_type], content_ids_pointer);
78} 82}
79 83
80void GetTitleList(Service::Interface* self) { 84void GetTitleList(Service::Interface* self) {
@@ -87,8 +91,10 @@ void GetTitleList(Service::Interface* self) {
87 91
88 cmd_buff[1] = RESULT_SUCCESS.raw; 92 cmd_buff[1] = RESULT_SUCCESS.raw;
89 cmd_buff[2] = am_titles_list_count[media_type]; 93 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", 94 LOG_WARNING(
91 media_type, am_titles_list_count[media_type], title_ids_output_pointer); 95 Service_AM,
96 "(STUBBED) media_type=%u, titles_list_count=0x%08X, title_ids_output_pointer=0x%08X",
97 media_type, am_titles_list_count[media_type], title_ids_output_pointer);
92} 98}
93 99
94void GetTitleInfo(Service::Interface* self) { 100void GetTitleInfo(Service::Interface* self) {
@@ -101,7 +107,8 @@ void GetTitleInfo(Service::Interface* self) {
101 am_titles_count[media_type] = cmd_buff[2]; 107 am_titles_count[media_type] = cmd_buff[2];
102 108
103 cmd_buff[1] = RESULT_SUCCESS.raw; 109 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", 110 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, total_titles=0x%08X, "
111 "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); 112 media_type, am_titles_count[media_type], title_id_list_pointer, title_list_pointer);
106} 113}
107 114
@@ -122,8 +129,9 @@ void ListDataTitleTicketInfos(Service::Interface* self) {
122 129
123 cmd_buff[1] = RESULT_SUCCESS.raw; 130 cmd_buff[1] = RESULT_SUCCESS.raw;
124 cmd_buff[2] = am_ticket_count; 131 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", 132 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); 133 ", start_index=0x%08X, ticket_info_pointer=0x%08X",
134 am_ticket_count, title_id, start_index, ticket_info_pointer);
127} 135}
128 136
129void GetNumContentInfos(Service::Interface* self) { 137void GetNumContentInfos(Service::Interface* self) {
@@ -140,7 +148,7 @@ void DeleteTicket(Service::Interface* self) {
140 u64 title_id = (static_cast<u64>(cmd_buff[2]) << 32) | cmd_buff[1]; 148 u64 title_id = (static_cast<u64>(cmd_buff[2]) << 32) | cmd_buff[1];
141 149
142 cmd_buff[1] = RESULT_SUCCESS.raw; 150 cmd_buff[1] = RESULT_SUCCESS.raw;
143 LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "",title_id); 151 LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "", title_id);
144} 152}
145 153
146void GetTicketCount(Service::Interface* self) { 154void GetTicketCount(Service::Interface* self) {
@@ -148,7 +156,7 @@ void GetTicketCount(Service::Interface* self) {
148 156
149 cmd_buff[1] = RESULT_SUCCESS.raw; 157 cmd_buff[1] = RESULT_SUCCESS.raw;
150 cmd_buff[2] = am_ticket_count; 158 cmd_buff[2] = am_ticket_count;
151 LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x",am_ticket_count); 159 LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x", am_ticket_count);
152} 160}
153 161
154void GetTicketList(Service::Interface* self) { 162void GetTicketList(Service::Interface* self) {
@@ -161,8 +169,10 @@ void GetTicketList(Service::Interface* self) {
161 169
162 cmd_buff[1] = RESULT_SUCCESS.raw; 170 cmd_buff[1] = RESULT_SUCCESS.raw;
163 cmd_buff[2] = am_ticket_list_count; 171 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", 172 LOG_WARNING(
165 am_ticket_list_count, num_of_skip, ticket_list_pointer); 173 Service_AM,
174 "(STUBBED) ticket_list_count=0x%08x, num_of_skip=0x%08x, ticket_list_pointer=0x%08x",
175 am_ticket_list_count, num_of_skip, ticket_list_pointer);
166} 176}
167 177
168void Init() { 178void Init() {
@@ -174,9 +184,7 @@ void Init() {
174 AddService(new AM_U_Interface); 184 AddService(new AM_U_Interface);
175} 185}
176 186
177void Shutdown() { 187void Shutdown() {}
178
179}
180 188
181} // namespace AM 189} // namespace AM
182 190
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..a2268303c 100644
--- a/src/core/hle/service/am/am_sys.cpp
+++ b/src/core/hle/service/am/am_sys.cpp
@@ -9,27 +9,27 @@ 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, "GetPendingTitleCount"}, 31 {0x00230080, nullptr, "GetPendingTitleCount"},
32 {0x002400C2, nullptr, "GetPendingTitleList"} 32 {0x002400C2, nullptr, "GetPendingTitleList"},
33}; 33};
34 34
35AM_SYS_Interface::AM_SYS_Interface() { 35AM_SYS_Interface::AM_SYS_Interface() {
diff --git a/src/core/hle/service/am/am_u.cpp b/src/core/hle/service/am/am_u.cpp
index d583dd9e6..151b5e42b 100644
--- a/src/core/hle/service/am/am_u.cpp
+++ b/src/core/hle/service/am/am_u.cpp
@@ -9,40 +9,40 @@ 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}; 46};
47 47
48AM_U_Interface::AM_U_Interface() { 48AM_U_Interface::AM_U_Interface() {
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 4d2956638..c4bd65986 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -5,9 +5,11 @@
5#include "common/common_paths.h" 5#include "common/common_paths.h"
6#include "common/file_util.h" 6#include "common/file_util.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8
9#include "core/hle/applets/applet.h" 8#include "core/hle/applets/applet.h"
10#include "core/hle/service/service.h" 9#include "core/hle/kernel/event.h"
10#include "core/hle/kernel/mutex.h"
11#include "core/hle/kernel/process.h"
12#include "core/hle/kernel/shared_memory.h"
11#include "core/hle/service/apt/apt.h" 13#include "core/hle/service/apt/apt.h"
12#include "core/hle/service/apt/apt_a.h" 14#include "core/hle/service/apt/apt_a.h"
13#include "core/hle/service/apt/apt_s.h" 15#include "core/hle/service/apt/apt_s.h"
@@ -15,11 +17,7 @@
15#include "core/hle/service/apt/bcfnt/bcfnt.h" 17#include "core/hle/service/apt/bcfnt/bcfnt.h"
16#include "core/hle/service/fs/archive.h" 18#include "core/hle/service/fs/archive.h"
17#include "core/hle/service/ptm/ptm.h" 19#include "core/hle/service/ptm/ptm.h"
18 20#include "core/hle/service/service.h"
19#include "core/hle/kernel/event.h"
20#include "core/hle/kernel/mutex.h"
21#include "core/hle/kernel/process.h"
22#include "core/hle/kernel/shared_memory.h"
23 21
24namespace Service { 22namespace Service {
25namespace APT { 23namespace APT {
@@ -30,7 +28,7 @@ static bool shared_font_relocated = false;
30 28
31static Kernel::SharedPtr<Kernel::Mutex> lock; 29static Kernel::SharedPtr<Kernel::Mutex> lock;
32static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event 30static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event
33static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event 31static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event
34 32
35static u32 cpu_percent; ///< CPU time available to the running application 33static u32 cpu_percent; ///< CPU time available to the running application
36 34
@@ -51,7 +49,7 @@ void SendParameter(const MessageParameter& parameter) {
51void Initialize(Service::Interface* self) { 49void Initialize(Service::Interface* self) {
52 u32* cmd_buff = Kernel::GetCommandBuffer(); 50 u32* cmd_buff = Kernel::GetCommandBuffer();
53 u32 app_id = cmd_buff[1]; 51 u32 app_id = cmd_buff[1];
54 u32 flags = cmd_buff[2]; 52 u32 flags = cmd_buff[2];
55 53
56 cmd_buff[2] = IPC::CopyHandleDesc(2); 54 cmd_buff[2] = IPC::CopyHandleDesc(2);
57 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); 55 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom();
@@ -75,21 +73,23 @@ void GetSharedFont(Service::Interface* self) {
75 if (!shared_font_mem) { 73 if (!shared_font_mem) {
76 LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds"); 74 LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds");
77 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); 75 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2);
78 cmd_buff[1] = -1; // TODO: Find the right error code 76 cmd_buff[1] = -1; // TODO: Find the right error code
79 return; 77 return;
80 } 78 }
81 79
82 // The shared font has to be relocated to the new address before being passed to the application. 80 // 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); 81 // application.
82 VAddr target_address =
83 Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address);
84 if (!shared_font_relocated) { 84 if (!shared_font_relocated) {
85 BCFNT::RelocateSharedFont(shared_font_mem, target_address); 85 BCFNT::RelocateSharedFont(shared_font_mem, target_address);
86 shared_font_relocated = true; 86 shared_font_relocated = true;
87 } 87 }
88 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); 88 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2);
89 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 89 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
90 // Since the SharedMemory interface doesn't provide the address at which the memory was allocated, 90 // 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) 91 // allocated, the real APT service calculates this address by scanning the entire address space
92 // and searches for an allocation of the same size as the Shared Font. 92 // (using svcQueryMemory) and searches for an allocation of the same size as the Shared Font.
93 cmd_buff[2] = target_address; 93 cmd_buff[2] = target_address;
94 cmd_buff[3] = IPC::CopyHandleDesc(); 94 cmd_buff[3] = IPC::CopyHandleDesc();
95 cmd_buff[4] = Kernel::g_handle_table.Create(shared_font_mem).MoveFrom(); 95 cmd_buff[4] = Kernel::g_handle_table.Create(shared_font_mem).MoveFrom();
@@ -112,18 +112,19 @@ void GetLockHandle(Service::Interface* self) {
112 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 112 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
113 113
114 cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable. 114 cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable.
115 cmd_buff[3] = 0; // Least significant bit = power button state 115 cmd_buff[3] = 0; // Least significant bit = power button state
116 cmd_buff[4] = IPC::CopyHandleDesc(); 116 cmd_buff[4] = IPC::CopyHandleDesc();
117 cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom(); 117 cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom();
118 118
119 LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5], applet_attributes); 119 LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5],
120 applet_attributes);
120} 121}
121 122
122void Enable(Service::Interface* self) { 123void Enable(Service::Interface* self) {
123 u32* cmd_buff = Kernel::GetCommandBuffer(); 124 u32* cmd_buff = Kernel::GetCommandBuffer();
124 u32 attributes = cmd_buff[1]; 125 u32 attributes = cmd_buff[1];
125 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 126 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
126 parameter_event->Signal(); // Let the application know that it has been started 127 parameter_event->Signal(); // Let the application know that it has been started
127 LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes); 128 LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes);
128} 129}
129 130
@@ -133,7 +134,7 @@ void GetAppletManInfo(Service::Interface* self) {
133 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 134 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
134 cmd_buff[2] = 0; 135 cmd_buff[2] = 0;
135 cmd_buff[3] = 0; 136 cmd_buff[3] = 0;
136 cmd_buff[4] = static_cast<u32>(AppletId::HomeMenu); // Home menu AppID 137 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 138 cmd_buff[5] = static_cast<u32>(AppletId::Application); // TODO(purpasmart96): Do this correctly
138 139
139 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); 140 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk);
@@ -159,23 +160,24 @@ void IsRegistered(Service::Interface* self) {
159void InquireNotification(Service::Interface* self) { 160void InquireNotification(Service::Interface* self) {
160 u32* cmd_buff = Kernel::GetCommandBuffer(); 161 u32* cmd_buff = Kernel::GetCommandBuffer();
161 u32 app_id = cmd_buff[1]; 162 u32 app_id = cmd_buff[1];
162 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 163 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
163 cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type 164 cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type
164 LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); 165 LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id);
165} 166}
166 167
167void SendParameter(Service::Interface* self) { 168void SendParameter(Service::Interface* self) {
168 u32* cmd_buff = Kernel::GetCommandBuffer(); 169 u32* cmd_buff = Kernel::GetCommandBuffer();
169 u32 src_app_id = cmd_buff[1]; 170 u32 src_app_id = cmd_buff[1];
170 u32 dst_app_id = cmd_buff[2]; 171 u32 dst_app_id = cmd_buff[2];
171 u32 signal_type = cmd_buff[3]; 172 u32 signal_type = cmd_buff[3];
172 u32 buffer_size = cmd_buff[4]; 173 u32 buffer_size = cmd_buff[4];
173 u32 value = cmd_buff[5]; 174 u32 value = cmd_buff[5];
174 u32 handle = cmd_buff[6]; 175 u32 handle = cmd_buff[6];
175 u32 size = cmd_buff[7]; 176 u32 size = cmd_buff[7];
176 u32 buffer = cmd_buff[8]; 177 u32 buffer = cmd_buff[8];
177 178
178 std::shared_ptr<HLE::Applets::Applet> dest_applet = HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id)); 179 std::shared_ptr<HLE::Applets::Applet> dest_applet =
180 HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id));
179 181
180 if (dest_applet == nullptr) { 182 if (dest_applet == nullptr) {
181 LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id); 183 LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id);
@@ -193,9 +195,11 @@ void SendParameter(Service::Interface* self) {
193 195
194 cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; 196 cmd_buff[1] = dest_applet->ReceiveParameter(param).raw;
195 197
196 LOG_WARNING(Service_APT, "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," 198 LOG_WARNING(
197 "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X", 199 Service_APT,
198 src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, buffer); 200 "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X,"
201 "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X",
202 src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, buffer);
199} 203}
200 204
201void ReceiveParameter(Service::Interface* self) { 205void ReceiveParameter(Service::Interface* self) {
@@ -206,7 +210,7 @@ void ReceiveParameter(Service::Interface* self) {
206 210
207 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 211 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
208 cmd_buff[2] = next_parameter.sender_id; 212 cmd_buff[2] = next_parameter.sender_id;
209 cmd_buff[3] = next_parameter.signal; // Signal type 213 cmd_buff[3] = next_parameter.signal; // Signal type
210 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size 214 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size
211 cmd_buff[5] = 0x10; 215 cmd_buff[5] = 0x10;
212 cmd_buff[6] = 0; 216 cmd_buff[6] = 0;
@@ -228,7 +232,7 @@ void GlanceParameter(Service::Interface* self) {
228 232
229 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 233 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
230 cmd_buff[2] = next_parameter.sender_id; 234 cmd_buff[2] = next_parameter.sender_id;
231 cmd_buff[3] = next_parameter.signal; // Signal type 235 cmd_buff[3] = next_parameter.signal; // Signal type
232 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size 236 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size
233 cmd_buff[5] = 0x10; 237 cmd_buff[5] = 0x10;
234 cmd_buff[6] = 0; 238 cmd_buff[6] = 0;
@@ -237,32 +241,34 @@ void GlanceParameter(Service::Interface* self) {
237 cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; 241 cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2;
238 cmd_buff[8] = buffer; 242 cmd_buff[8] = buffer;
239 243
240 Memory::WriteBlock(buffer, next_parameter.buffer.data(), std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size())); 244 Memory::WriteBlock(buffer, next_parameter.buffer.data(),
245 std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size()));
241 246
242 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); 247 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size);
243} 248}
244 249
245void CancelParameter(Service::Interface* self) { 250void CancelParameter(Service::Interface* self) {
246 u32* cmd_buff = Kernel::GetCommandBuffer(); 251 u32* cmd_buff = Kernel::GetCommandBuffer();
247 u32 flag1 = cmd_buff[1]; 252 u32 flag1 = cmd_buff[1];
248 u32 unk = cmd_buff[2]; 253 u32 unk = cmd_buff[2];
249 u32 flag2 = cmd_buff[3]; 254 u32 flag2 = cmd_buff[3];
250 u32 app_id = cmd_buff[4]; 255 u32 app_id = cmd_buff[4];
251 256
252 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 257 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
253 cmd_buff[2] = 1; // Set to Success 258 cmd_buff[2] = 1; // Set to Success
254 259
255 LOG_WARNING(Service_APT, "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X", 260 LOG_WARNING(Service_APT,
256 flag1, unk, flag2, app_id); 261 "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X", flag1,
262 unk, flag2, app_id);
257} 263}
258 264
259void PrepareToStartApplication(Service::Interface* self) { 265void PrepareToStartApplication(Service::Interface* self) {
260 u32* cmd_buff = Kernel::GetCommandBuffer(); 266 u32* cmd_buff = Kernel::GetCommandBuffer();
261 u32 title_info1 = cmd_buff[1]; 267 u32 title_info1 = cmd_buff[1];
262 u32 title_info2 = cmd_buff[2]; 268 u32 title_info2 = cmd_buff[2];
263 u32 title_info3 = cmd_buff[3]; 269 u32 title_info3 = cmd_buff[3];
264 u32 title_info4 = cmd_buff[4]; 270 u32 title_info4 = cmd_buff[4];
265 u32 flags = cmd_buff[5]; 271 u32 flags = cmd_buff[5];
266 272
267 if (flags & 0x00000100) { 273 if (flags & 0x00000100) {
268 unknown_ns_state_field = 1; 274 unknown_ns_state_field = 1;
@@ -270,25 +276,28 @@ void PrepareToStartApplication(Service::Interface* self) {
270 276
271 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 277 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
272 278
273 LOG_WARNING(Service_APT, "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X," 279 LOG_WARNING(Service_APT,
274 "title_info4=0x%08X, flags=0x%08X", title_info1, title_info2, title_info3, title_info4, flags); 280 "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X,"
281 "title_info4=0x%08X, flags=0x%08X",
282 title_info1, title_info2, title_info3, title_info4, flags);
275} 283}
276 284
277void StartApplication(Service::Interface* self) { 285void StartApplication(Service::Interface* self) {
278 u32* cmd_buff = Kernel::GetCommandBuffer(); 286 u32* cmd_buff = Kernel::GetCommandBuffer();
279 u32 buffer1_size = cmd_buff[1]; 287 u32 buffer1_size = cmd_buff[1];
280 u32 buffer2_size = cmd_buff[2]; 288 u32 buffer2_size = cmd_buff[2];
281 u32 flag = cmd_buff[3]; 289 u32 flag = cmd_buff[3];
282 u32 size1 = cmd_buff[4]; 290 u32 size1 = cmd_buff[4];
283 u32 buffer1_ptr = cmd_buff[5]; 291 u32 buffer1_ptr = cmd_buff[5];
284 u32 size2 = cmd_buff[6]; 292 u32 size2 = cmd_buff[6];
285 u32 buffer2_ptr = cmd_buff[7]; 293 u32 buffer2_ptr = cmd_buff[7];
286 294
287 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 295 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
288 296
289 LOG_WARNING(Service_APT, "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X," 297 LOG_WARNING(Service_APT,
290 "size1=0x%08X, buffer1_ptr=0x%08X, size2=0x%08X, buffer2_ptr=0x%08X", 298 "(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); 299 "size1=0x%08X, buffer1_ptr=0x%08X, size2=0x%08X, buffer2_ptr=0x%08X",
300 buffer1_size, buffer2_size, flag, size1, buffer1_ptr, size2, buffer2_ptr);
292} 301}
293 302
294void AppletUtility(Service::Interface* self) { 303void AppletUtility(Service::Interface* self) {
@@ -303,14 +312,15 @@ void AppletUtility(Service::Interface* self) {
303 312
304 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 313 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
305 314
306 LOG_WARNING(Service_APT, "(STUBBED) called command=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, " 315 LOG_WARNING(Service_APT,
307 "buffer1_addr=0x%08X, buffer2_addr=0x%08X", command, buffer1_size, buffer2_size, 316 "(STUBBED) called command=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, "
308 buffer1_addr, buffer2_addr); 317 "buffer1_addr=0x%08X, buffer2_addr=0x%08X",
318 command, buffer1_size, buffer2_size, buffer1_addr, buffer2_addr);
309} 319}
310 320
311void SetAppCpuTimeLimit(Service::Interface* self) { 321void SetAppCpuTimeLimit(Service::Interface* self) {
312 u32* cmd_buff = Kernel::GetCommandBuffer(); 322 u32* cmd_buff = Kernel::GetCommandBuffer();
313 u32 value = cmd_buff[1]; 323 u32 value = cmd_buff[1];
314 cpu_percent = cmd_buff[2]; 324 cpu_percent = cmd_buff[2];
315 325
316 if (value != 1) { 326 if (value != 1) {
@@ -393,7 +403,8 @@ void SetScreenCapPostPermission(Service::Interface* self) {
393 403
394 cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0); 404 cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0);
395 cmd_buff[1] = RESULT_SUCCESS.raw; 405 cmd_buff[1] = RESULT_SUCCESS.raw;
396 LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", screen_capture_post_permission); 406 LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u",
407 screen_capture_post_permission);
397} 408}
398 409
399void GetScreenCapPostPermission(Service::Interface* self) { 410void GetScreenCapPostPermission(Service::Interface* self) {
@@ -402,7 +413,8 @@ void GetScreenCapPostPermission(Service::Interface* self) {
402 cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0); 413 cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0);
403 cmd_buff[1] = RESULT_SUCCESS.raw; 414 cmd_buff[1] = RESULT_SUCCESS.raw;
404 cmd_buff[2] = static_cast<u32>(screen_capture_post_permission); 415 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); 416 LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u",
417 screen_capture_post_permission);
406} 418}
407 419
408void GetAppletInfo(Service::Interface* self) { 420void GetAppletInfo(Service::Interface* self) {
@@ -418,7 +430,8 @@ void GetAppletInfo(Service::Interface* self) {
418 cmd_buff[7] = 0; // Applet Attributes 430 cmd_buff[7] = 0; // Applet Attributes
419 } else { 431 } else {
420 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, 432 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Applet,
421 ErrorSummary::NotFound, ErrorLevel::Status).raw; 433 ErrorSummary::NotFound, ErrorLevel::Status)
434 .raw;
422 } 435 }
423 LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id); 436 LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id);
424} 437}
@@ -429,11 +442,15 @@ void GetStartupArgument(Service::Interface* self) {
429 StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(cmd_buff[2]); 442 StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(cmd_buff[2]);
430 443
431 if (parameter_size >= 0x300) { 444 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); 445 LOG_ERROR(
446 Service_APT,
447 "Parameter size is outside the valid range (capped to 0x300): parameter_size=0x%08x",
448 parameter_size);
433 return; 449 return;
434 } 450 }
435 451
436 LOG_WARNING(Service_APT,"(stubbed) called startup_argument_type=%u , parameter_size=0x%08x , parameter_value=0x%08x", 452 LOG_WARNING(Service_APT, "(stubbed) called startup_argument_type=%u , parameter_size=0x%08x , "
453 "parameter_value=0x%08x",
437 startup_argument_type, parameter_size, Memory::Read32(cmd_buff[41])); 454 startup_argument_type, parameter_size, Memory::Read32(cmd_buff[41]));
438 455
439 cmd_buff[1] = RESULT_SUCCESS.raw; 456 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -484,8 +501,10 @@ void Init() {
484 if (file.IsOpen()) { 501 if (file.IsOpen()) {
485 // Create shared font memory object 502 // Create shared font memory object
486 using Kernel::MemoryPermission; 503 using Kernel::MemoryPermission;
487 shared_font_mem = Kernel::SharedMemory::Create(nullptr, 0x332000, // 3272 KB 504 shared_font_mem =
488 MemoryPermission::ReadWrite, MemoryPermission::Read, 0, Kernel::MemoryRegion::SYSTEM, "APT:SharedFont"); 505 Kernel::SharedMemory::Create(nullptr, 0x332000, // 3272 KB
506 MemoryPermission::ReadWrite, MemoryPermission::Read, 0,
507 Kernel::MemoryRegion::SYSTEM, "APT:SharedFont");
489 // Read shared font data 508 // Read shared font data
490 file.ReadBytes(shared_font_mem->GetPointer(), file.GetSize()); 509 file.ReadBytes(shared_font_mem->GetPointer(), file.GetSize());
491 } else { 510 } else {
@@ -497,7 +516,8 @@ void Init() {
497 516
498 cpu_percent = 0; 517 cpu_percent = 0;
499 unknown_ns_state_field = 0; 518 unknown_ns_state_field = 0;
500 screen_capture_post_permission = ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value 519 screen_capture_post_permission =
520 ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value
501 521
502 // TODO(bunnei): Check if these are created in Initialize or on APT process startup. 522 // 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"); 523 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..a118cda1f 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -6,7 +6,6 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/swap.h" 8#include "common/swap.h"
9
10#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
11 10
12namespace Service { 11namespace Service {
@@ -46,58 +45,58 @@ static_assert(sizeof(CaptureBufferInfo) == 0x20, "CaptureBufferInfo struct has i
46 45
47/// Signals used by APT functions 46/// Signals used by APT functions
48enum class SignalType : u32 { 47enum class SignalType : u32 {
49 None = 0x0, 48 None = 0x0,
50 AppJustStarted = 0x1, 49 AppJustStarted = 0x1,
51 LibAppJustStarted = 0x2, 50 LibAppJustStarted = 0x2,
52 LibAppFinished = 0x3, 51 LibAppFinished = 0x3,
53 LibAppClosed = 0xA, 52 LibAppClosed = 0xA,
54 ReturningToApp = 0xB, 53 ReturningToApp = 0xB,
55 ExitingApp = 0xC, 54 ExitingApp = 0xC,
56}; 55};
57 56
58/// App Id's used by APT functions 57/// App Id's used by APT functions
59enum class AppletId : u32 { 58enum class AppletId : u32 {
60 HomeMenu = 0x101, 59 HomeMenu = 0x101,
61 AlternateMenu = 0x103, 60 AlternateMenu = 0x103,
62 Camera = 0x110, 61 Camera = 0x110,
63 FriendsList = 0x112, 62 FriendsList = 0x112,
64 GameNotes = 0x113, 63 GameNotes = 0x113,
65 InternetBrowser = 0x114, 64 InternetBrowser = 0x114,
66 InstructionManual = 0x115, 65 InstructionManual = 0x115,
67 Notifications = 0x116, 66 Notifications = 0x116,
68 Miiverse = 0x117, 67 Miiverse = 0x117,
69 MiiversePost = 0x118, 68 MiiversePost = 0x118,
70 AmiiboSettings = 0x119, 69 AmiiboSettings = 0x119,
71 SoftwareKeyboard1 = 0x201, 70 SoftwareKeyboard1 = 0x201,
72 Ed1 = 0x202, 71 Ed1 = 0x202,
73 PnoteApp = 0x204, 72 PnoteApp = 0x204,
74 SnoteApp = 0x205, 73 SnoteApp = 0x205,
75 Error = 0x206, 74 Error = 0x206,
76 Mint = 0x207, 75 Mint = 0x207,
77 Extrapad = 0x208, 76 Extrapad = 0x208,
78 Memolib = 0x209, 77 Memolib = 0x209,
79 Application = 0x300, 78 Application = 0x300,
80 AnyLibraryApplet = 0x400, 79 AnyLibraryApplet = 0x400,
81 SoftwareKeyboard2 = 0x401, 80 SoftwareKeyboard2 = 0x401,
82 Ed2 = 0x402, 81 Ed2 = 0x402,
83 PnoteApp2 = 0x404, 82 PnoteApp2 = 0x404,
84 SnoteApp2 = 0x405, 83 SnoteApp2 = 0x405,
85 Error2 = 0x406, 84 Error2 = 0x406,
86 Mint2 = 0x407, 85 Mint2 = 0x407,
87 Extrapad2 = 0x408, 86 Extrapad2 = 0x408,
88 Memolib2 = 0x409, 87 Memolib2 = 0x409,
89}; 88};
90 89
91enum class StartupArgumentType : u32 { 90enum class StartupArgumentType : u32 {
92 OtherApp = 0, 91 OtherApp = 0,
93 Restart = 1, 92 Restart = 1,
94 OtherMedia = 2, 93 OtherMedia = 2,
95}; 94};
96 95
97enum class ScreencapPostPermission : u32 { 96enum class ScreencapPostPermission : u32 {
98 CleanThePermission = 0, //TODO(JamePeng): verify what "zero" means 97 CleanThePermission = 0, // TODO(JamePeng): verify what "zero" means
99 NoExplicitSetting = 1, 98 NoExplicitSetting = 1,
100 EnableScreenshotPostingToMiiverse = 2, 99 EnableScreenshotPostingToMiiverse = 2,
101 DisableScreenshotPostingToMiiverse = 3 100 DisableScreenshotPostingToMiiverse = 3
102}; 101};
103 102
@@ -182,10 +181,11 @@ void GetAppletManInfo(Service::Interface* self);
182void GetAppletInfo(Service::Interface* self); 181void GetAppletInfo(Service::Interface* self);
183 182
184/** 183/**
185 * APT::IsRegistered service function. This returns whether the specified AppID is registered with NS yet. 184 * 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 185 * NS yet. An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home
187 * command to determine when the launched process is running and to determine when to stop using GSP etc, 186 * Menu uses this command to determine when the launched process is running and to determine when to
188 * while displaying the "Nintendo 3DS" loading screen. 187 * stop using GSP, etc., while displaying the "Nintendo 3DS" loading screen.
188 *
189 * Inputs: 189 * Inputs:
190 * 1 : AppID 190 * 1 : AppID
191 * Outputs: 191 * Outputs:
@@ -260,9 +260,11 @@ void GlanceParameter(Service::Interface* self);
260 * clears the flag which indicates that parameter data is available 260 * clears the flag which indicates that parameter data is available
261 * (same flag cleared by APT:ReceiveParameter). 261 * (same flag cleared by APT:ReceiveParameter).
262 * Inputs: 262 * Inputs:
263 * 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS state. 263 * 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS
264 * state.
264 * 2 : Unknown, this is the same as the first unknown field returned by APT:ReceiveParameter. 265 * 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. 266 * 3 : Flag, when non-zero NS will compare the word after this one with a field in the NS
267 * state.
266 * 4 : AppID 268 * 4 : AppID
267 * Outputs: 269 * Outputs:
268 * 0 : Return header 270 * 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..f27ad91b7 100644
--- a/src/core/hle/service/apt/apt_a.cpp
+++ b/src/core/hle/service/apt/apt_a.cpp
@@ -9,34 +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}; 40};
41 41
42APT_A_Interface::APT_A_Interface() { 42APT_A_Interface::APT_A_Interface() {
diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp
index c70f2201f..c4556a5de 100644
--- a/src/core/hle/service/apt/apt_s.cpp
+++ b/src/core/hle/service/apt/apt_s.cpp
@@ -9,94 +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}; 100};
101 101
102APT_S_Interface::APT_S_Interface() { 102APT_S_Interface::APT_S_Interface() {
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp
index 7bb804ffa..d6ad42e21 100644
--- a/src/core/hle/service/apt/apt_u.cpp
+++ b/src/core/hle/service/apt/apt_u.cpp
@@ -9,94 +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}; 100};
101 101
102APT_U_Interface::APT_U_Interface() { 102APT_U_Interface::APT_U_Interface() {
diff --git a/src/core/hle/service/apt/bcfnt/bcfnt.h b/src/core/hle/service/apt/bcfnt/bcfnt.h
index 8936dcf63..453bf7606 100644
--- a/src/core/hle/service/apt/bcfnt/bcfnt.h
+++ b/src/core/hle/service/apt/bcfnt/bcfnt.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include "common/swap.h" 7#include "common/swap.h"
8
9#include "core/hle/kernel/shared_memory.h" 8#include "core/hle/kernel/shared_memory.h"
10#include "core/hle/service/service.h" 9#include "core/hle/service/service.h"
11 10
diff --git a/src/core/hle/service/boss/boss.cpp b/src/core/hle/service/boss/boss.cpp
index 419ec976e..757a8c2c7 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 {
@@ -17,8 +17,7 @@ void Init() {
17 AddService(new BOSS_U_Interface); 17 AddService(new BOSS_U_Interface);
18} 18}
19 19
20void Shutdown() { 20void Shutdown() {}
21}
22 21
23} // namespace BOSS 22} // namespace BOSS
24 23
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..5594aedab 100644
--- a/src/core/hle/service/cam/cam.cpp
+++ b/src/core/hle/service/cam/cam.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6
7#include "core/hle/kernel/event.h" 6#include "core/hle/kernel/event.h"
8#include "core/hle/service/cam/cam.h" 7#include "core/hle/service/cam/cam.h"
9#include "core/hle/service/cam/cam_c.h" 8#include "core/hle/service/cam/cam_c.h"
@@ -71,15 +70,15 @@ void GetBufferErrorInterruptEvent(Service::Interface* self) {
71} 70}
72 71
73void SetReceiving(Service::Interface* self) { 72void SetReceiving(Service::Interface* self) {
74 u32* cmd_buff = Kernel::GetCommandBuffer(); 73 u32* cmd_buff = Kernel::GetCommandBuffer();
75 74
76 VAddr dest = cmd_buff[1]; 75 VAddr dest = cmd_buff[1];
77 u8 port = cmd_buff[2] & 0xFF; 76 u8 port = cmd_buff[2] & 0xFF;
78 u32 image_size = cmd_buff[3]; 77 u32 image_size = cmd_buff[3];
79 u16 trans_unit = cmd_buff[4] & 0xFFFF; 78 u16 trans_unit = cmd_buff[4] & 0xFFFF;
80 79
81 Kernel::Event* completion_event = (Port)port == Port::Cam2 ? 80 Kernel::Event* completion_event =
82 completion_event_cam2.get() : completion_event_cam1.get(); 81 (Port)port == Port::Cam2 ? completion_event_cam2.get() : completion_event_cam1.get();
83 82
84 completion_event->Signal(); 83 completion_event->Signal();
85 84
@@ -89,36 +88,36 @@ void SetReceiving(Service::Interface* self) {
89 cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom(); 88 cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom();
90 89
91 LOG_WARNING(Service_CAM, "(STUBBED) called, addr=0x%X, port=%d, image_size=%d, trans_unit=%d", 90 LOG_WARNING(Service_CAM, "(STUBBED) called, addr=0x%X, port=%d, image_size=%d, trans_unit=%d",
92 dest, port, image_size, trans_unit); 91 dest, port, image_size, trans_unit);
93} 92}
94 93
95void SetTransferLines(Service::Interface* self) { 94void SetTransferLines(Service::Interface* self) {
96 u32* cmd_buff = Kernel::GetCommandBuffer(); 95 u32* cmd_buff = Kernel::GetCommandBuffer();
97 96
98 u8 port = cmd_buff[1] & 0xFF; 97 u8 port = cmd_buff[1] & 0xFF;
99 u16 transfer_lines = cmd_buff[2] & 0xFFFF; 98 u16 transfer_lines = cmd_buff[2] & 0xFFFF;
100 u16 width = cmd_buff[3] & 0xFFFF; 99 u16 width = cmd_buff[3] & 0xFFFF;
101 u16 height = cmd_buff[4] & 0xFFFF; 100 u16 height = cmd_buff[4] & 0xFFFF;
102 101
103 cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0); 102 cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0);
104 cmd_buff[1] = RESULT_SUCCESS.raw; 103 cmd_buff[1] = RESULT_SUCCESS.raw;
105 104
106 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, lines=%d, width=%d, height=%d", 105 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, lines=%d, width=%d, height=%d", port,
107 port, transfer_lines, width, height); 106 transfer_lines, width, height);
108} 107}
109 108
110void GetMaxLines(Service::Interface* self) { 109void GetMaxLines(Service::Interface* self) {
111 u32* cmd_buff = Kernel::GetCommandBuffer(); 110 u32* cmd_buff = Kernel::GetCommandBuffer();
112 111
113 u16 width = cmd_buff[1] & 0xFFFF; 112 u16 width = cmd_buff[1] & 0xFFFF;
114 u16 height = cmd_buff[2] & 0xFFFF; 113 u16 height = cmd_buff[2] & 0xFFFF;
115 114
116 cmd_buff[0] = IPC::MakeHeader(0xA, 2, 0); 115 cmd_buff[0] = IPC::MakeHeader(0xA, 2, 0);
117 cmd_buff[1] = RESULT_SUCCESS.raw; 116 cmd_buff[1] = RESULT_SUCCESS.raw;
118 cmd_buff[2] = TRANSFER_BYTES / (2 * width); 117 cmd_buff[2] = TRANSFER_BYTES / (2 * width);
119 118
120 LOG_WARNING(Service_CAM, "(STUBBED) called, width=%d, height=%d, lines = %d", 119 LOG_WARNING(Service_CAM, "(STUBBED) called, width=%d, height=%d, lines = %d", width, height,
121 width, height, cmd_buff[2]); 120 cmd_buff[2]);
122} 121}
123 122
124void GetTransferBytes(Service::Interface* self) { 123void GetTransferBytes(Service::Interface* self) {
@@ -136,7 +135,7 @@ void GetTransferBytes(Service::Interface* self) {
136void SetTrimming(Service::Interface* self) { 135void SetTrimming(Service::Interface* self) {
137 u32* cmd_buff = Kernel::GetCommandBuffer(); 136 u32* cmd_buff = Kernel::GetCommandBuffer();
138 137
139 u8 port = cmd_buff[1] & 0xFF; 138 u8 port = cmd_buff[1] & 0xFF;
140 bool trim = (cmd_buff[2] & 0xFF) != 0; 139 bool trim = (cmd_buff[2] & 0xFF) != 0;
141 140
142 cmd_buff[0] = IPC::MakeHeader(0xE, 1, 0); 141 cmd_buff[0] = IPC::MakeHeader(0xE, 1, 0);
@@ -148,17 +147,17 @@ void SetTrimming(Service::Interface* self) {
148void SetTrimmingParamsCenter(Service::Interface* self) { 147void SetTrimmingParamsCenter(Service::Interface* self) {
149 u32* cmd_buff = Kernel::GetCommandBuffer(); 148 u32* cmd_buff = Kernel::GetCommandBuffer();
150 149
151 u8 port = cmd_buff[1] & 0xFF; 150 u8 port = cmd_buff[1] & 0xFF;
152 s16 trimW = cmd_buff[2] & 0xFFFF; 151 s16 trimW = cmd_buff[2] & 0xFFFF;
153 s16 trimH = cmd_buff[3] & 0xFFFF; 152 s16 trimH = cmd_buff[3] & 0xFFFF;
154 s16 camW = cmd_buff[4] & 0xFFFF; 153 s16 camW = cmd_buff[4] & 0xFFFF;
155 s16 camH = cmd_buff[5] & 0xFFFF; 154 s16 camH = cmd_buff[5] & 0xFFFF;
156 155
157 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); 156 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0);
158 cmd_buff[1] = RESULT_SUCCESS.raw; 157 cmd_buff[1] = RESULT_SUCCESS.raw;
159 158
160 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trimW=%d, trimH=%d, camW=%d, camH=%d", 159 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trimW=%d, trimH=%d, camW=%d, camH=%d",
161 port, trimW, trimH, camW, camH); 160 port, trimW, trimH, camW, camH);
162} 161}
163 162
164void Activate(Service::Interface* self) { 163void Activate(Service::Interface* self) {
@@ -169,36 +168,35 @@ void Activate(Service::Interface* self) {
169 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); 168 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0);
170 cmd_buff[1] = RESULT_SUCCESS.raw; 169 cmd_buff[1] = RESULT_SUCCESS.raw;
171 170
172 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d", 171 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d", cam_select);
173 cam_select);
174} 172}
175 173
176void FlipImage(Service::Interface* self) { 174void FlipImage(Service::Interface* self) {
177 u32* cmd_buff = Kernel::GetCommandBuffer(); 175 u32* cmd_buff = Kernel::GetCommandBuffer();
178 176
179 u8 cam_select = cmd_buff[1] & 0xFF; 177 u8 cam_select = cmd_buff[1] & 0xFF;
180 u8 flip = cmd_buff[2] & 0xFF; 178 u8 flip = cmd_buff[2] & 0xFF;
181 u8 context = cmd_buff[3] & 0xFF; 179 u8 context = cmd_buff[3] & 0xFF;
182 180
183 cmd_buff[0] = IPC::MakeHeader(0x1D, 1, 0); 181 cmd_buff[0] = IPC::MakeHeader(0x1D, 1, 0);
184 cmd_buff[1] = RESULT_SUCCESS.raw; 182 cmd_buff[1] = RESULT_SUCCESS.raw;
185 183
186 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, flip=%d, context=%d", 184 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, flip=%d, context=%d", cam_select,
187 cam_select, flip, context); 185 flip, context);
188} 186}
189 187
190void SetSize(Service::Interface* self) { 188void SetSize(Service::Interface* self) {
191 u32* cmd_buff = Kernel::GetCommandBuffer(); 189 u32* cmd_buff = Kernel::GetCommandBuffer();
192 190
193 u8 cam_select = cmd_buff[1] & 0xFF; 191 u8 cam_select = cmd_buff[1] & 0xFF;
194 u8 size = cmd_buff[2] & 0xFF; 192 u8 size = cmd_buff[2] & 0xFF;
195 u8 context = cmd_buff[3] & 0xFF; 193 u8 context = cmd_buff[3] & 0xFF;
196 194
197 cmd_buff[0] = IPC::MakeHeader(0x1F, 1, 0); 195 cmd_buff[0] = IPC::MakeHeader(0x1F, 1, 0);
198 cmd_buff[1] = RESULT_SUCCESS.raw; 196 cmd_buff[1] = RESULT_SUCCESS.raw;
199 197
200 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, size=%d, context=%d", 198 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, size=%d, context=%d", cam_select,
201 cam_select, size, context); 199 size, context);
202} 200}
203 201
204void SetFrameRate(Service::Interface* self) { 202void SetFrameRate(Service::Interface* self) {
@@ -210,8 +208,8 @@ void SetFrameRate(Service::Interface* self) {
210 cmd_buff[0] = IPC::MakeHeader(0x20, 1, 0); 208 cmd_buff[0] = IPC::MakeHeader(0x20, 1, 0);
211 cmd_buff[1] = RESULT_SUCCESS.raw; 209 cmd_buff[1] = RESULT_SUCCESS.raw;
212 210
213 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, frame_rate=%d", 211 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, frame_rate=%d", cam_select,
214 cam_select, frame_rate); 212 frame_rate);
215} 213}
216 214
217void GetStereoCameraCalibrationData(Service::Interface* self) { 215void GetStereoCameraCalibrationData(Service::Interface* self) {
@@ -293,10 +291,14 @@ void Init() {
293 AddService(new CAM_S_Interface); 291 AddService(new CAM_S_Interface);
294 AddService(new CAM_U_Interface); 292 AddService(new CAM_U_Interface);
295 293
296 completion_event_cam1 = Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam1"); 294 completion_event_cam1 =
297 completion_event_cam2 = Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam2"); 295 Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam1");
298 interrupt_error_event = Kernel::Event::Create(ResetType::OneShot, "CAM_U::interrupt_error_event"); 296 completion_event_cam2 =
299 vsync_interrupt_error_event = Kernel::Event::Create(ResetType::OneShot, "CAM_U::vsync_interrupt_error_event"); 297 Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam2");
298 interrupt_error_event =
299 Kernel::Event::Create(ResetType::OneShot, "CAM_U::interrupt_error_event");
300 vsync_interrupt_error_event =
301 Kernel::Event::Create(ResetType::OneShot, "CAM_U::vsync_interrupt_error_event");
300} 302}
301 303
302void Shutdown() { 304void Shutdown() {
diff --git a/src/core/hle/service/cam/cam.h b/src/core/hle/service/cam/cam.h
index 2f4923728..c9b6f8acf 100644
--- a/src/core/hle/service/cam/cam.h
+++ b/src/core/hle/service/cam/cam.h
@@ -7,19 +7,13 @@
7#include "common/common_funcs.h" 7#include "common/common_funcs.h"
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "common/swap.h" 9#include "common/swap.h"
10
11#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
12#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
13 12
14namespace Service { 13namespace Service {
15namespace CAM { 14namespace CAM {
16 15
17enum class Port : u8 { 16enum 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 17
24enum class CameraSelect : u8 { 18enum class CameraSelect : u8 {
25 None = 0, 19 None = 0,
@@ -29,7 +23,7 @@ enum class CameraSelect : u8 {
29 In1Out1 = Out1 | In1, 23 In1Out1 = Out1 | In1,
30 Out1Out2 = Out1 | Out2, 24 Out1Out2 = Out1 | Out2,
31 In1Out2 = In1 | Out2, 25 In1Out2 = In1 | Out2,
32 All = Out1 | In1 | Out2 26 All = Out1 | In1 | Out2,
33}; 27};
34 28
35enum class Effect : u8 { 29enum class Effect : u8 {
@@ -38,21 +32,21 @@ enum class Effect : u8 {
38 Sepia = 2, 32 Sepia = 2,
39 Negative = 3, 33 Negative = 3,
40 Negafilm = 4, 34 Negafilm = 4,
41 Sepia01 = 5 35 Sepia01 = 5,
42}; 36};
43 37
44enum class Context : u8 { 38enum class Context : u8 {
45 None = 0, 39 None = 0,
46 A = 1, 40 A = 1,
47 B = 2, 41 B = 2,
48 Both = A | B 42 Both = A | B,
49}; 43};
50 44
51enum class Flip : u8 { 45enum class Flip : u8 {
52 None = 0, 46 None = 0,
53 Horizontal = 1, 47 Horizontal = 1,
54 Vertical = 2, 48 Vertical = 2,
55 Reverse = 3 49 Reverse = 3,
56}; 50};
57 51
58enum class Size : u8 { 52enum class Size : u8 {
@@ -64,7 +58,7 @@ enum class Size : u8 {
64 DS_LCD = 5, 58 DS_LCD = 5,
65 DS_LCDx4 = 6, 59 DS_LCDx4 = 6,
66 CTR_TOP_LCD = 7, 60 CTR_TOP_LCD = 7,
67 CTR_BOTTOM_LCD = QVGA 61 CTR_BOTTOM_LCD = QVGA,
68}; 62};
69 63
70enum class FrameRate : u8 { 64enum class FrameRate : u8 {
@@ -80,13 +74,13 @@ enum class FrameRate : u8 {
80 Rate_30_To_5 = 9, 74 Rate_30_To_5 = 9,
81 Rate_15_To_10 = 10, 75 Rate_15_To_10 = 10,
82 Rate_20_To_10 = 11, 76 Rate_20_To_10 = 11,
83 Rate_30_To_10 = 12 77 Rate_30_To_10 = 12,
84}; 78};
85 79
86enum class ShutterSoundType : u8 { 80enum class ShutterSoundType : u8 {
87 Normal = 0, 81 Normal = 0,
88 Movie = 1, 82 Movie = 1,
89 MovieEnd = 2 83 MovieEnd = 2,
90}; 84};
91 85
92enum class WhiteBalance : u8 { 86enum class WhiteBalance : u8 {
@@ -103,7 +97,7 @@ enum class WhiteBalance : u8 {
103 BalanceDaylight = Balance5200K, 97 BalanceDaylight = Balance5200K,
104 BalanceCloudy = Balance6000K, 98 BalanceCloudy = Balance6000K,
105 BalanceHorizon = Balance6000K, 99 BalanceHorizon = Balance6000K,
106 BalanceShade = Balance7000K 100 BalanceShade = Balance7000K,
107}; 101};
108 102
109enum class PhotoMode : u8 { 103enum class PhotoMode : u8 {
@@ -111,7 +105,7 @@ enum class PhotoMode : u8 {
111 Portrait = 1, 105 Portrait = 1,
112 Landscape = 2, 106 Landscape = 2,
113 Nightview = 3, 107 Nightview = 3,
114 Letter0 = 4 108 Letter0 = 4,
115}; 109};
116 110
117enum class LensCorrection : u8 { 111enum class LensCorrection : u8 {
@@ -120,7 +114,7 @@ enum class LensCorrection : u8 {
120 On90 = 2, 114 On90 = 2,
121 Dark = Off, 115 Dark = Off,
122 Normal = On70, 116 Normal = On70,
123 Bright = On90 117 Bright = On90,
124}; 118};
125 119
126enum class Contrast : u8 { 120enum class Contrast : u8 {
@@ -137,24 +131,24 @@ enum class Contrast : u8 {
137 Pattern11 = 11, 131 Pattern11 = 11,
138 Low = Pattern05, 132 Low = Pattern05,
139 Normal = Pattern06, 133 Normal = Pattern06,
140 High = Pattern07 134 High = Pattern07,
141}; 135};
142 136
143enum class OutputFormat : u8 { 137enum class OutputFormat : u8 {
144 YUV422 = 0, 138 YUV422 = 0,
145 RGB565 = 1 139 RGB565 = 1,
146}; 140};
147 141
148/// Stereo camera calibration data. 142/// Stereo camera calibration data.
149struct StereoCameraCalibrationData { 143struct StereoCameraCalibrationData {
150 u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid. 144 u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid.
151 INSERT_PADDING_BYTES(3); 145 INSERT_PADDING_BYTES(3);
152 float_le scale; ///< Scale to match the left camera image with the right. 146 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. 147 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. 148 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. 149 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. 150 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. 151 float_le rotationY; ///< Y axis rotation to match the left camera image with the right.
158 float_le angleOfViewRight; ///< Right camera angle of view. 152 float_le angleOfViewRight; ///< Right camera angle of view.
159 float_le angleOfViewLeft; ///< Left camera angle of view. 153 float_le angleOfViewLeft; ///< Left camera angle of view.
160 float_le distanceToChart; ///< Distance between cameras and measurement chart. 154 float_le distanceToChart; ///< Distance between cameras and measurement chart.
@@ -163,7 +157,8 @@ struct StereoCameraCalibrationData {
163 s16_le imageHeight; ///< Image height. 157 s16_le imageHeight; ///< Image height.
164 INSERT_PADDING_BYTES(16); 158 INSERT_PADDING_BYTES(16);
165}; 159};
166static_assert(sizeof(StereoCameraCalibrationData) == 64, "StereoCameraCalibrationData structure size is wrong"); 160static_assert(sizeof(StereoCameraCalibrationData) == 64,
161 "StereoCameraCalibrationData structure size is wrong");
167 162
168struct PackageParameterCameraSelect { 163struct PackageParameterCameraSelect {
169 CameraSelect camera; 164 CameraSelect camera;
@@ -188,7 +183,8 @@ struct PackageParameterCameraSelect {
188 s16 auto_white_balance_window_height; 183 s16 auto_white_balance_window_height;
189}; 184};
190 185
191static_assert(sizeof(PackageParameterCameraSelect) == 28, "PackageParameterCameraSelect structure size is wrong"); 186static_assert(sizeof(PackageParameterCameraSelect) == 28,
187 "PackageParameterCameraSelect structure size is wrong");
192 188
193/** 189/**
194 * Unknown 190 * 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..515b344e6 100644
--- a/src/core/hle/service/cecd/cecd.cpp
+++ b/src/core/hle/service/cecd/cecd.cpp
@@ -3,12 +3,11 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6
7#include "core/hle/kernel/event.h" 6#include "core/hle/kernel/event.h"
8#include "core/hle/service/service.h"
9#include "core/hle/service/cecd/cecd.h" 7#include "core/hle/service/cecd/cecd.h"
10#include "core/hle/service/cecd/cecd_s.h" 8#include "core/hle/service/cecd/cecd_s.h"
11#include "core/hle/service/cecd/cecd_u.h" 9#include "core/hle/service/cecd/cecd_u.h"
10#include "core/hle/service/service.h"
12 11
13namespace Service { 12namespace Service {
14namespace CECD { 13namespace CECD {
@@ -28,7 +27,7 @@ void GetCecStateAbbreviated(Service::Interface* self) {
28void GetCecInfoEventHandle(Service::Interface* self) { 27void GetCecInfoEventHandle(Service::Interface* self) {
29 u32* cmd_buff = Kernel::GetCommandBuffer(); 28 u32* cmd_buff = Kernel::GetCommandBuffer();
30 29
31 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 30 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
32 cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle 31 cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle
33 32
34 LOG_WARNING(Service_CECD, "(STUBBED) called"); 33 LOG_WARNING(Service_CECD, "(STUBBED) called");
@@ -37,7 +36,7 @@ void GetCecInfoEventHandle(Service::Interface* self) {
37void GetChangeStateEventHandle(Service::Interface* self) { 36void GetChangeStateEventHandle(Service::Interface* self) {
38 u32* cmd_buff = Kernel::GetCommandBuffer(); 37 u32* cmd_buff = Kernel::GetCommandBuffer();
39 38
40 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 39 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
41 cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle 40 cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle
42 41
43 LOG_WARNING(Service_CECD, "(STUBBED) called"); 42 LOG_WARNING(Service_CECD, "(STUBBED) called");
@@ -48,7 +47,8 @@ void Init() {
48 AddService(new CECD_U_Interface); 47 AddService(new CECD_U_Interface);
49 48
50 cecinfo_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::cecinfo_event"); 49 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"); 50 change_state_event =
51 Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::change_state_event");
52} 52}
53 53
54void Shutdown() { 54void 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..24eee6903 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -3,15 +3,12 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6
7#include "common/file_util.h" 6#include "common/file_util.h"
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9#include "common/string_util.h" 8#include "common/string_util.h"
10#include "common/swap.h" 9#include "common/swap.h"
11
12#include "core/file_sys/archive_systemsavedata.h" 10#include "core/file_sys/archive_systemsavedata.h"
13#include "core/file_sys/file_backend.h" 11#include "core/file_sys/file_backend.h"
14#include "core/settings.h"
15#include "core/hle/result.h" 12#include "core/hle/result.h"
16#include "core/hle/service/cfg/cfg.h" 13#include "core/hle/service/cfg/cfg.h"
17#include "core/hle/service/cfg/cfg_i.h" 14#include "core/hle/service/cfg/cfg_i.h"
@@ -19,6 +16,7 @@
19#include "core/hle/service/cfg/cfg_u.h" 16#include "core/hle/service/cfg/cfg_u.h"
20#include "core/hle/service/fs/archive.h" 17#include "core/hle/service/fs/archive.h"
21#include "core/hle/service/service.h" 18#include "core/hle/service/service.h"
19#include "core/settings.h"
22 20
23namespace Service { 21namespace Service {
24namespace CFG { 22namespace CFG {
@@ -33,25 +31,29 @@ namespace {
33 * contains information about the blocks in the file 31 * contains information about the blocks in the file
34 */ 32 */
35struct SaveFileConfig { 33struct SaveFileConfig {
36 u16 total_entries; ///< The total number of set entries in the config file 34 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 35 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 36 /// to 0x455C as per hardware
39 u32 unknown; ///< This field is unknown, possibly padding, 0 has been observed in hardware 37 SaveConfigBlockEntry block_entries[CONFIG_FILE_MAX_BLOCK_ENTRIES]; ///< The block headers, the
38 /// maximum possible value is
39 /// 1479 as per hardware
40 u32 unknown; ///< This field is unknown, possibly padding, 0 has been observed in hardware
40}; 41};
41static_assert(sizeof(SaveFileConfig) == 0x455C, "SaveFileConfig header must be exactly 0x455C bytes"); 42static_assert(sizeof(SaveFileConfig) == 0x455C,
43 "SaveFileConfig header must be exactly 0x455C bytes");
42 44
43enum ConfigBlockID { 45enum ConfigBlockID {
44 StereoCameraSettingsBlockID = 0x00050005, 46 StereoCameraSettingsBlockID = 0x00050005,
45 SoundOutputModeBlockID = 0x00070001, 47 SoundOutputModeBlockID = 0x00070001,
46 ConsoleUniqueIDBlockID = 0x00090001, 48 ConsoleUniqueIDBlockID = 0x00090001,
47 UsernameBlockID = 0x000A0000, 49 UsernameBlockID = 0x000A0000,
48 BirthdayBlockID = 0x000A0001, 50 BirthdayBlockID = 0x000A0001,
49 LanguageBlockID = 0x000A0002, 51 LanguageBlockID = 0x000A0002,
50 CountryInfoBlockID = 0x000B0000, 52 CountryInfoBlockID = 0x000B0000,
51 CountryNameBlockID = 0x000B0001, 53 CountryNameBlockID = 0x000B0001,
52 StateNameBlockID = 0x000B0002, 54 StateNameBlockID = 0x000B0002,
53 EULAVersionBlockID = 0x000D0000, 55 EULAVersionBlockID = 0x000D0000,
54 ConsoleModelBlockID = 0x000F0004, 56 ConsoleModelBlockID = 0x000F0004,
55}; 57};
56 58
57struct UsernameBlock { 59struct UsernameBlock {
@@ -68,8 +70,8 @@ struct BirthdayBlock {
68static_assert(sizeof(BirthdayBlock) == 2, "BirthdayBlock must be exactly 2 bytes"); 70static_assert(sizeof(BirthdayBlock) == 2, "BirthdayBlock must be exactly 2 bytes");
69 71
70struct ConsoleModelInfo { 72struct ConsoleModelInfo {
71 u8 model; ///< The console model (3DS, 2DS, etc) 73 u8 model; ///< The console model (3DS, 2DS, etc)
72 u8 unknown[3]; ///< Unknown data 74 u8 unknown[3]; ///< Unknown data
73}; 75};
74static_assert(sizeof(ConsoleModelInfo) == 4, "ConsoleModelInfo must be exactly 4 bytes"); 76static_assert(sizeof(ConsoleModelInfo) == 4, "ConsoleModelInfo must be exactly 4 bytes");
75 77
@@ -78,36 +80,38 @@ struct ConsoleCountryInfo {
78 u8 country_code; ///< The country code of the console 80 u8 country_code; ///< The country code of the console
79}; 81};
80static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes"); 82static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes");
81
82} 83}
83 84
84static const u64 CFG_SAVE_ID = 0x00010017; 85static const u64 CFG_SAVE_ID = 0x00010017;
85static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; 86static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE;
86static const ConsoleModelInfo CONSOLE_MODEL = { NINTENDO_3DS_XL, { 0, 0, 0 } }; 87static const ConsoleModelInfo CONSOLE_MODEL = {NINTENDO_3DS_XL, {0, 0, 0}};
87static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; 88static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN;
88static const UsernameBlock CONSOLE_USERNAME_BLOCK = { u"CITRA", 0, 0 }; 89static const UsernameBlock CONSOLE_USERNAME_BLOCK = {u"CITRA", 0, 0};
89static const BirthdayBlock PROFILE_BIRTHDAY = { 3, 25 }; // March 25th, 2014 90static const BirthdayBlock PROFILE_BIRTHDAY = {3, 25}; // March 25th, 2014
90static const u8 SOUND_OUTPUT_MODE = SOUND_SURROUND; 91static const u8 SOUND_OUTPUT_MODE = SOUND_SURROUND;
91static const u8 UNITED_STATES_COUNTRY_ID = 49; 92static const u8 UNITED_STATES_COUNTRY_ID = 49;
92/// TODO(Subv): Find what the other bytes are 93/// TODO(Subv): Find what the other bytes are
93static const ConsoleCountryInfo COUNTRY_INFO = { { 0, 0, 0 }, UNITED_STATES_COUNTRY_ID }; 94static const ConsoleCountryInfo COUNTRY_INFO = {{0, 0, 0}, UNITED_STATES_COUNTRY_ID};
94 95
95/** 96/**
96 * TODO(Subv): Find out what this actually is, these values fix some NaN uniforms in some games, 97 * TODO(Subv): Find out what this actually is, these values fix some NaN uniforms in some games,
97 * for example Nintendo Zone 98 * for example Nintendo Zone
98 * Thanks Normmatt for providing this information 99 * Thanks Normmatt for providing this information
99 */ 100 */
100static const std::array<float, 8> STEREO_CAMERA_SETTINGS = {{ 101static const std::array<float, 8> STEREO_CAMERA_SETTINGS = {
101 62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f, 102 62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f,
102 10.0f, 5.0f, 55.58000183105469f, 21.56999969482422f 103 10.0f, 5.0f, 55.58000183105469f, 21.56999969482422f,
103}}; 104};
104static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20, "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes"); 105static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20,
106 "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes");
105 107
106static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; 108static const u32 CONFIG_SAVEFILE_SIZE = 0x8000;
107static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer; 109static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
108 110
109static Service::FS::ArchiveHandle cfg_system_save_data_archive; 111static 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 }; 112static const std::vector<u8> cfg_system_savedata_id = {
113 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00,
114};
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!");
@@ -491,8 +528,7 @@ void Init() {
491 LoadConfigNANDSaveFile(); 528 LoadConfigNANDSaveFile();
492} 529}
493 530
494void Shutdown() { 531void Shutdown() {}
495}
496 532
497void SetUsername(const std::u16string& name) { 533void SetUsername(const std::u16string& name) {
498 ASSERT(name.size() <= 10); 534 ASSERT(name.size() <= 10);
@@ -515,7 +551,7 @@ std::u16string GetUsername() {
515} 551}
516 552
517void SetBirthday(u8 month, u8 day) { 553void SetBirthday(u8 month, u8 day) {
518 BirthdayBlock block = { month, day }; 554 BirthdayBlock block = {month, day};
519 SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block); 555 SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block);
520} 556}
521 557
diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h
index 18f60f4ca..fb47c2aa5 100644
--- a/src/core/hle/service/cfg/cfg.h
+++ b/src/core/hle/service/cfg/cfg.h
@@ -6,7 +6,6 @@
6 6
7#include <array> 7#include <array>
8#include <string> 8#include <string>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11 10
12union ResultCode; 11union ResultCode;
@@ -40,16 +39,13 @@ enum SystemLanguage {
40 LANGUAGE_TW = 11 39 LANGUAGE_TW = 11
41}; 40};
42 41
43enum SoundOutputMode { 42enum SoundOutputMode { SOUND_MONO = 0, SOUND_STEREO = 1, SOUND_SURROUND = 2 };
44 SOUND_MONO = 0,
45 SOUND_STEREO = 1,
46 SOUND_SURROUND = 2
47};
48 43
49/// Block header in the config savedata file 44/// Block header in the config savedata file
50struct SaveConfigBlockEntry { 45struct SaveConfigBlockEntry {
51 u32 block_id; ///< The id of the current block 46 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 47 u32 offset_or_data; ///< This is the absolute offset to the block data if the size is greater
48 /// than 4 bytes, otherwise it contains the data itself
53 u16 size; ///< The size of the block 49 u16 size; ///< The size of the block
54 u16 flags; ///< The flags of the block, possibly used for access control 50 u16 flags; ///< The flags of the block, possibly used for access control
55}; 51};
@@ -82,7 +78,7 @@ static const std::array<u16, 187> country_codes = {{
82 C("CN"), 0, 0, 0, 0, 0, 0, 0, // 160-167 78 C("CN"), 0, 0, 0, 0, 0, 0, 0, // 160-167
83 C("AE"), C("IN"), C("EG"), C("OM"), C("QA"), C("KW"), C("SA"), C("SY"), // 168-175 79 C("AE"), C("IN"), C("EG"), C("OM"), C("QA"), C("KW"), C("SA"), C("SY"), // 168-175
84 C("BH"), C("JO"), 0, 0, 0, 0, 0, 0, // 176-183 80 C("BH"), C("JO"), 0, 0, 0, 0, 0, 0, // 176-183
85 C("SM"), C("VA"), C("BM") // 184-186 81 C("SM"), C("VA"), C("BM"), // 184-186
86}}; 82}};
87 83
88/** 84/**
@@ -221,8 +217,9 @@ void FormatConfig(Service::Interface* self);
221 217
222/** 218/**
223 * Reads a block with the specified id and flag from the Config savegame buffer 219 * Reads a block with the specified id and flag from the Config savegame buffer
224 * and writes the output to output. 220 * and writes the output to output. The input size must match exactly the size of the requested
225 * The input size must match exactly the size of the requested block 221 * block.
222 *
226 * @param block_id The id of the block we want to read 223 * @param block_id The id of the block we want to read
227 * @param size The size of the block we want to read 224 * @param size The size of the block we want to read
228 * @param flag The requested block must have this flag set 225 * @param flag The requested block must have this flag set
@@ -233,8 +230,8 @@ ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output);
233 230
234/** 231/**
235 * Reads data from input and writes to a block with the specified id and flag 232 * Reads data from input and writes to a block with the specified id and flag
236 * in the Config savegame buffer. 233 * in the Config savegame buffer. The input size must match exactly the size of the target block.
237 * The input size must match exactly the size of the target block 234 *
238 * @param block_id The id of the block we want to write 235 * @param block_id The id of the block we want to write
239 * @param size The size of the block we want to write 236 * @param size The size of the block we want to write
240 * @param flag The target block must have this flag set 237 * @param flag The target block must have this flag set
@@ -244,8 +241,9 @@ 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
248 * The config savegame file in the filesystem is not updated. 245 * memory. The config savegame file in the filesystem is not updated.
246 *
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
251 * @param flags The flags of the new block 249 * @param flags The flags of the new block
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..20c759ad7 100644
--- a/src/core/hle/service/csnd_snd.cpp
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -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..8f4b67a5d 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 {
@@ -17,8 +17,7 @@ void Init() {
17 AddService(new DLP_SRVR_Interface); 17 AddService(new DLP_SRVR_Interface);
18} 18}
19 19
20void Shutdown() { 20void Shutdown() {}
21}
22 21
23} // namespace DLP 22} // namespace DLP
24} // namespace Service 23} // namespace Service
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..49d5b8d1c 100644
--- a/src/core/hle/service/dlp/dlp_srvr.cpp
+++ b/src/core/hle/service/dlp/dlp_srvr.cpp
@@ -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..a15aa3696 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -4,12 +4,9 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <cinttypes> 6#include <cinttypes>
7
8#include "audio_core/hle/pipe.h" 7#include "audio_core/hle/pipe.h"
9
10#include "common/hash.h" 8#include "common/hash.h"
11#include "common/logging/log.h" 9#include "common/logging/log.h"
12
13#include "core/hle/kernel/event.h" 10#include "core/hle/kernel/event.h"
14#include "core/hle/service/dsp_dsp.h" 11#include "core/hle/service/dsp_dsp.h"
15 12
@@ -23,9 +20,7 @@ namespace DSP_DSP {
23static Kernel::SharedPtr<Kernel::Event> semaphore_event; 20static Kernel::SharedPtr<Kernel::Event> semaphore_event;
24 21
25/// There are three types of interrupts 22/// There are three types of interrupts
26enum class InterruptType { 23enum class InterruptType { Zero, One, Pipe };
27 Zero, One, Pipe
28};
29constexpr size_t NUM_INTERRUPT_TYPE = 3; 24constexpr size_t NUM_INTERRUPT_TYPE = 3;
30 25
31class InterruptEvents final { 26class InterruptEvents final {
@@ -57,9 +52,8 @@ public:
57 // Actual service implementation only has 6 'slots' for interrupts. 52 // Actual service implementation only has 6 'slots' for interrupts.
58 constexpr size_t max_number_of_interrupt_events = 6; 53 constexpr size_t max_number_of_interrupt_events = 6;
59 54
60 size_t number = std::count_if(pipe.begin(), pipe.end(), [](const auto& evt) { 55 size_t number =
61 return evt != nullptr; 56 std::count_if(pipe.begin(), pipe.end(), [](const auto& evt) { return evt != nullptr; });
62 });
63 57
64 if (zero != nullptr) 58 if (zero != nullptr)
65 number++; 59 number++;
@@ -105,7 +99,8 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) {
105 cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0); 99 cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0);
106 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 100 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
107 101
108 // TODO(merry): There is a per-region offset missing in this calculation (that seems to be always zero). 102 // TODO(merry): There is a per-region offset missing in this calculation (that seems to be
103 // always zero).
109 cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000); 104 cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000);
110 105
111 LOG_DEBUG(Service_DSP, "addr=0x%08X", addr); 106 LOG_DEBUG(Service_DSP, "addr=0x%08X", addr);
@@ -126,15 +121,15 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) {
126static void LoadComponent(Service::Interface* self) { 121static void LoadComponent(Service::Interface* self) {
127 u32* cmd_buff = Kernel::GetCommandBuffer(); 122 u32* cmd_buff = Kernel::GetCommandBuffer();
128 123
129 u32 size = cmd_buff[1]; 124 u32 size = cmd_buff[1];
130 u32 prog_mask = cmd_buff[2]; 125 u32 prog_mask = cmd_buff[2];
131 u32 data_mask = cmd_buff[3]; 126 u32 data_mask = cmd_buff[3];
132 u32 desc = cmd_buff[4]; 127 u32 desc = cmd_buff[4];
133 u32 buffer = cmd_buff[5]; 128 u32 buffer = cmd_buff[5];
134 129
135 cmd_buff[0] = IPC::MakeHeader(0x11, 2, 2); 130 cmd_buff[0] = IPC::MakeHeader(0x11, 2, 2);
136 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 131 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
137 cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware 132 cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware
138 cmd_buff[3] = desc; 133 cmd_buff[3] = desc;
139 cmd_buff[4] = buffer; 134 cmd_buff[4] = buffer;
140 135
@@ -145,12 +140,15 @@ static void LoadComponent(Service::Interface* self) {
145 std::vector<u8> component_data(size); 140 std::vector<u8> component_data(size);
146 Memory::ReadBlock(buffer, component_data.data(), component_data.size()); 141 Memory::ReadBlock(buffer, component_data.data(), component_data.size());
147 142
148 LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(component_data.data(), component_data.size())); 143 LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64,
144 Common::ComputeHash64(component_data.data(), component_data.size()));
149 // Some versions of the firmware have the location of DSP structures listed here. 145 // Some versions of the firmware have the location of DSP structures listed here.
150 ASSERT(size > 0x37C); 146 ASSERT(size > 0x37C);
151 LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(component_data.data() + 0x340, 60)); 147 LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64,
148 Common::ComputeHash64(component_data.data() + 0x340, 60));
152 149
153 LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X", 150 LOG_WARNING(Service_DSP,
151 "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X",
154 size, prog_mask, data_mask, buffer); 152 size, prog_mask, data_mask, buffer);
155} 153}
156 154
@@ -187,13 +185,14 @@ static void GetSemaphoreEventHandle(Service::Interface* self) {
187static void FlushDataCache(Service::Interface* self) { 185static void FlushDataCache(Service::Interface* self) {
188 u32* cmd_buff = Kernel::GetCommandBuffer(); 186 u32* cmd_buff = Kernel::GetCommandBuffer();
189 u32 address = cmd_buff[1]; 187 u32 address = cmd_buff[1];
190 u32 size = cmd_buff[2]; 188 u32 size = cmd_buff[2];
191 u32 process = cmd_buff[4]; 189 u32 process = cmd_buff[4];
192 190
193 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); 191 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0);
194 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 192 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
195 193
196 LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size, process); 194 LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size,
195 process);
197} 196}
198 197
199/** 198/**
@@ -224,23 +223,29 @@ static void RegisterInterruptEvents(Service::Interface* self) {
224 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]); 223 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
225 224
226 if (!evt) { 225 if (!evt) {
227 LOG_INFO(Service_DSP, "Invalid event handle! type=%u, pipe=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); 226 LOG_INFO(Service_DSP, "Invalid event handle! type=%u, pipe=%u, event_handle=0x%08X",
227 type_index, pipe_index, event_handle);
228 ASSERT(false); // TODO: This should really be handled at an IPC translation layer. 228 ASSERT(false); // TODO: This should really be handled at an IPC translation layer.
229 } 229 }
230 230
231 if (interrupt_events.HasTooManyEventsRegistered()) { 231 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)", 232 LOG_INFO(Service_DSP, "Ran out of space to register interrupts (Attempted to register "
233 "type=%u, pipe=%u, event_handle=0x%08X)",
233 type_index, pipe_index, event_handle); 234 type_index, pipe_index, event_handle);
234 cmd_buff[1] = ResultCode(ErrorDescription::InvalidResultValue, ErrorModule::DSP, ErrorSummary::OutOfResource, ErrorLevel::Status).raw; 235 cmd_buff[1] = ResultCode(ErrorDescription::InvalidResultValue, ErrorModule::DSP,
236 ErrorSummary::OutOfResource, ErrorLevel::Status)
237 .raw;
235 return; 238 return;
236 } 239 }
237 240
238 interrupt_events.Get(type, pipe) = evt; 241 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); 242 LOG_INFO(Service_DSP, "Registered type=%u, pipe=%u, event_handle=0x%08X", type_index,
243 pipe_index, event_handle);
240 cmd_buff[1] = RESULT_SUCCESS.raw; 244 cmd_buff[1] = RESULT_SUCCESS.raw;
241 } else { 245 } else {
242 interrupt_events.Get(type, pipe) = nullptr; 246 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); 247 LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X",
248 type_index, pipe_index, event_handle);
244 cmd_buff[1] = RESULT_SUCCESS.raw; 249 cmd_buff[1] = RESULT_SUCCESS.raw;
245 } 250 }
246} 251}
@@ -282,13 +287,18 @@ static void WriteProcessPipe(Service::Interface* self) {
282 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); 287 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index);
283 288
284 if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) { 289 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); 290 LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). pipe=%u, "
291 "size=0x%X, buffer=0x%08X",
292 cmd_buff[3], pipe_index, size, buffer);
286 cmd_buff[0] = IPC::MakeHeader(0, 1, 0); 293 cmd_buff[0] = IPC::MakeHeader(0, 1, 0);
287 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; 294 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
295 ErrorSummary::WrongArgument, ErrorLevel::Permanent)
296 .raw;
288 return; 297 return;
289 } 298 }
290 299
291 ASSERT_MSG(Memory::IsValidVirtualAddress(buffer), "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); 300 ASSERT_MSG(Memory::IsValidVirtualAddress(buffer),
301 "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
292 302
293 std::vector<u8> message(size); 303 std::vector<u8> message(size);
294 for (u32 i = 0; i < size; i++) { 304 for (u32 i = 0; i < size; i++) {
@@ -327,7 +337,9 @@ static void ReadPipeIfPossible(Service::Interface* self) {
327 337
328 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); 338 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index);
329 339
330 ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); 340 ASSERT_MSG(Memory::IsValidVirtualAddress(addr),
341 "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown,
342 size, addr);
331 343
332 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); 344 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2);
333 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 345 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
@@ -343,7 +355,9 @@ static void ReadPipeIfPossible(Service::Interface* self) {
343 cmd_buff[3] = IPC::StaticBufferDesc(size, 0); 355 cmd_buff[3] = IPC::StaticBufferDesc(size, 0);
344 cmd_buff[4] = addr; 356 cmd_buff[4] = addr;
345 357
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]); 358 LOG_DEBUG(Service_DSP,
359 "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X",
360 pipe_index, unknown, size, addr, cmd_buff[2]);
347} 361}
348 362
349/** 363/**
@@ -367,7 +381,9 @@ static void ReadPipe(Service::Interface* self) {
367 381
368 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); 382 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index);
369 383
370 ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); 384 ASSERT_MSG(Memory::IsValidVirtualAddress(addr),
385 "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown,
386 size, addr);
371 387
372 if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { 388 if (DSP::HLE::GetPipeReadableSize(pipe) >= size) {
373 std::vector<u8> response = DSP::HLE::PipeRead(pipe, size); 389 std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
@@ -384,7 +400,9 @@ static void ReadPipe(Service::Interface* self) {
384 UNREACHABLE(); 400 UNREACHABLE();
385 } 401 }
386 402
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]); 403 LOG_DEBUG(Service_DSP,
404 "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X",
405 pipe_index, unknown, size, addr, cmd_buff[2]);
388} 406}
389 407
390/** 408/**
@@ -408,7 +426,8 @@ static void GetPipeReadableSize(Service::Interface* self) {
408 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 426 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
409 cmd_buff[2] = static_cast<u32>(DSP::HLE::GetPipeReadableSize(pipe)); 427 cmd_buff[2] = static_cast<u32>(DSP::HLE::GetPipeReadableSize(pipe));
410 428
411 LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, cmd_buff[2]); 429 LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe_index,
430 unknown, cmd_buff[2]);
412} 431}
413 432
414/** 433/**
@@ -443,7 +462,7 @@ static void GetHeadphoneStatus(Service::Interface* self) {
443 462
444 cmd_buff[0] = IPC::MakeHeader(0x1F, 2, 0); 463 cmd_buff[0] = IPC::MakeHeader(0x1F, 2, 0);
445 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 464 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
446 cmd_buff[2] = 0; // Not using headphones 465 cmd_buff[2] = 0; // Not using headphones
447 466
448 LOG_DEBUG(Service_DSP, "called"); 467 LOG_DEBUG(Service_DSP, "called");
449} 468}
@@ -466,7 +485,8 @@ static void RecvData(Service::Interface* self) {
466 485
467 ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number); 486 ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number);
468 487
469 // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown or slept. 488 // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown
489 // or slept.
470 490
471 cmd_buff[0] = IPC::MakeHeader(0x1, 2, 0); 491 cmd_buff[0] = IPC::MakeHeader(0x1, 2, 0);
472 cmd_buff[1] = RESULT_SUCCESS.raw; 492 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -512,39 +532,39 @@ static void RecvDataIsReady(Service::Interface* self) {
512} 532}
513 533
514const Interface::FunctionInfo FunctionTable[] = { 534const Interface::FunctionInfo FunctionTable[] = {
515 {0x00010040, RecvData, "RecvData"}, 535 {0x00010040, RecvData, "RecvData"},
516 {0x00020040, RecvDataIsReady, "RecvDataIsReady"}, 536 {0x00020040, RecvDataIsReady, "RecvDataIsReady"},
517 {0x00030080, nullptr, "SendData"}, 537 {0x00030080, nullptr, "SendData"},
518 {0x00040040, nullptr, "SendDataIsEmpty"}, 538 {0x00040040, nullptr, "SendDataIsEmpty"},
519 {0x000500C2, nullptr, "SendFifoEx"}, 539 {0x000500C2, nullptr, "SendFifoEx"},
520 {0x000600C0, nullptr, "RecvFifoEx"}, 540 {0x000600C0, nullptr, "RecvFifoEx"},
521 {0x00070040, SetSemaphore, "SetSemaphore"}, 541 {0x00070040, SetSemaphore, "SetSemaphore"},
522 {0x00080000, nullptr, "GetSemaphore"}, 542 {0x00080000, nullptr, "GetSemaphore"},
523 {0x00090040, nullptr, "ClearSemaphore"}, 543 {0x00090040, nullptr, "ClearSemaphore"},
524 {0x000A0040, nullptr, "MaskSemaphore"}, 544 {0x000A0040, nullptr, "MaskSemaphore"},
525 {0x000B0000, nullptr, "CheckSemaphoreRequest"}, 545 {0x000B0000, nullptr, "CheckSemaphoreRequest"},
526 {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"}, 546 {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"},
527 {0x000D0082, WriteProcessPipe, "WriteProcessPipe"}, 547 {0x000D0082, WriteProcessPipe, "WriteProcessPipe"},
528 {0x000E00C0, ReadPipe, "ReadPipe"}, 548 {0x000E00C0, ReadPipe, "ReadPipe"},
529 {0x000F0080, GetPipeReadableSize, "GetPipeReadableSize"}, 549 {0x000F0080, GetPipeReadableSize, "GetPipeReadableSize"},
530 {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"}, 550 {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"},
531 {0x001100C2, LoadComponent, "LoadComponent"}, 551 {0x001100C2, LoadComponent, "LoadComponent"},
532 {0x00120000, nullptr, "UnloadComponent"}, 552 {0x00120000, nullptr, "UnloadComponent"},
533 {0x00130082, FlushDataCache, "FlushDataCache"}, 553 {0x00130082, FlushDataCache, "FlushDataCache"},
534 {0x00140082, nullptr, "InvalidateDCache"}, 554 {0x00140082, nullptr, "InvalidateDCache"},
535 {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"}, 555 {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"},
536 {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"}, 556 {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"},
537 {0x00170040, SetSemaphoreMask, "SetSemaphoreMask"}, 557 {0x00170040, SetSemaphoreMask, "SetSemaphoreMask"},
538 {0x00180040, nullptr, "GetPhysicalAddress"}, 558 {0x00180040, nullptr, "GetPhysicalAddress"},
539 {0x00190040, nullptr, "GetVirtualAddress"}, 559 {0x00190040, nullptr, "GetVirtualAddress"},
540 {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"}, 560 {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"},
541 {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"}, 561 {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"},
542 {0x001C0082, nullptr, "SetIirFilterEQ"}, 562 {0x001C0082, nullptr, "SetIirFilterEQ"},
543 {0x001D00C0, nullptr, "ReadMultiEx_SPI2"}, 563 {0x001D00C0, nullptr, "ReadMultiEx_SPI2"},
544 {0x001E00C2, nullptr, "WriteMultiEx_SPI2"}, 564 {0x001E00C2, nullptr, "WriteMultiEx_SPI2"},
545 {0x001F0000, GetHeadphoneStatus, "GetHeadphoneStatus"}, 565 {0x001F0000, GetHeadphoneStatus, "GetHeadphoneStatus"},
546 {0x00200040, nullptr, "ForceHeadphoneOut"}, 566 {0x00200040, nullptr, "ForceHeadphoneOut"},
547 {0x00210000, nullptr, "GetIsDspOccupied"}, 567 {0x00210000, nullptr, "GetIsDspOccupied"},
548}; 568};
549 569
550//////////////////////////////////////////////////////////////////////////////////////////////////// 570////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h
index 22f6687cc..3e97da6eb 100644
--- a/src/core/hle/service/dsp_dsp.h
+++ b/src/core/hle/service/dsp_dsp.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <string> 7#include <string>
8
9#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
10 9
11namespace DSP { 10namespace DSP {
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 5f9cf6e94..3ca4f98de 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -5,7 +5,6 @@
5#include "common/bit_field.h" 5#include "common/bit_field.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8
9#include "core/hle/service/err_f.h" 8#include "core/hle/service/err_f.h"
10 9
11//////////////////////////////////////////////////////////////////////////////////////////////////// 10////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -35,70 +34,70 @@ union ErrInfo {
35 u8 specifier; 34 u8 specifier;
36 35
37 struct { 36 struct {
38 u8 specifier; // 0x0 37 u8 specifier; // 0x0
39 u8 rev_high; // 0x1 38 u8 rev_high; // 0x1
40 u16 rev_low; // 0x2 39 u16 rev_low; // 0x2
41 RSL result_code; // 0x4 40 RSL result_code; // 0x4
42 u32 address; // 0x8 41 u32 address; // 0x8
43 INSERT_PADDING_BYTES(4); // 0xC 42 INSERT_PADDING_BYTES(4); // 0xC
44 u32 pid_low; // 0x10 43 u32 pid_low; // 0x10
45 u32 pid_high; // 0x14 44 u32 pid_high; // 0x14
46 u32 aid_low; // 0x18 45 u32 aid_low; // 0x18
47 u32 aid_high; // 0x1C 46 u32 aid_high; // 0x1C
48 } errtype1; 47 } errtype1;
49 48
50 struct { 49 struct {
51 u8 specifier; // 0x0 50 u8 specifier; // 0x0
52 u8 rev_high; // 0x1 51 u8 rev_high; // 0x1
53 u16 rev_low; // 0x2 52 u16 rev_low; // 0x2
54 INSERT_PADDING_BYTES(0xC); // 0x4 53 INSERT_PADDING_BYTES(0xC); // 0x4
55 u32 pid_low; // 0x10 54 u32 pid_low; // 0x10
56 u32 pid_high; // 0x14 55 u32 pid_high; // 0x14
57 u32 aid_low; // 0x18 56 u32 aid_low; // 0x18
58 u32 aid_high; // 0x1C 57 u32 aid_high; // 0x1C
59 u8 error_type; // 0x20 58 u8 error_type; // 0x20
60 INSERT_PADDING_BYTES(3); // 0x21 59 INSERT_PADDING_BYTES(3); // 0x21
61 u32 fault_status_reg; // 0x24 60 u32 fault_status_reg; // 0x24
62 u32 fault_addr; // 0x28 61 u32 fault_addr; // 0x28
63 u32 fpexc; // 0x2C 62 u32 fpexc; // 0x2C
64 u32 finst; // 0x30 63 u32 finst; // 0x30
65 u32 finst2; // 0x34 64 u32 finst2; // 0x34
66 INSERT_PADDING_BYTES(0x34); // 0x38 65 INSERT_PADDING_BYTES(0x34); // 0x38
67 u32 sp; // 0x6C 66 u32 sp; // 0x6C
68 u32 pc; // 0x70 67 u32 pc; // 0x70
69 u32 lr; // 0x74 68 u32 lr; // 0x74
70 u32 cpsr; // 0x78 69 u32 cpsr; // 0x78
71 } errtype3; 70 } errtype3;
72 71
73 struct { 72 struct {
74 u8 specifier; // 0x0 73 u8 specifier; // 0x0
75 u8 rev_high; // 0x1 74 u8 rev_high; // 0x1
76 u16 rev_low; // 0x2 75 u16 rev_low; // 0x2
77 RSL result_code; // 0x4 76 RSL result_code; // 0x4
78 INSERT_PADDING_BYTES(8); // 0x8 77 INSERT_PADDING_BYTES(8); // 0x8
79 u32 pid_low; // 0x10 78 u32 pid_low; // 0x10
80 u32 pid_high; // 0x14 79 u32 pid_high; // 0x14
81 u32 aid_low; // 0x18 80 u32 aid_low; // 0x18
82 u32 aid_high; // 0x1C 81 u32 aid_high; // 0x1C
83 char debug_string1[0x2E]; // 0x20 82 char debug_string1[0x2E]; // 0x20
84 char debug_string2[0x2E]; // 0x4E 83 char debug_string2[0x2E]; // 0x4E
85 } errtype4; 84 } errtype4;
86}; 85};
87 86
88enum { 87enum { PrefetchAbort = 0, DataAbort = 1, UndefInstr = 2, VectorFP = 3 };
89 PrefetchAbort = 0,
90 DataAbort = 1,
91 UndefInstr = 2,
92 VectorFP = 3
93};
94 88
95static std::string GetErrInfo3Type(u8 type_code) { 89static std::string GetErrInfo3Type(u8 type_code) {
96 switch (type_code) { 90 switch (type_code) {
97 case PrefetchAbort: return "Prefetch Abort"; 91 case PrefetchAbort:
98 case DataAbort: return "Data Abort"; 92 return "Prefetch Abort";
99 case UndefInstr: return "Undefined Instruction"; 93 case DataAbort:
100 case VectorFP: return "Vector Floating Point"; 94 return "Data Abort";
101 default: return "unknown"; 95 case UndefInstr:
96 return "Undefined Instruction";
97 case VectorFP:
98 return "Vector Floating Point";
99 default:
100 return "unknown";
102 } 101 }
103} 102}
104 103
@@ -110,8 +109,7 @@ static void ThrowFatalError(Service::Interface* self) {
110 109
111 switch (errinfo->specifier) { 110 switch (errinfo->specifier) {
112 case ErrSpecifier0: 111 case ErrSpecifier0:
113 case ErrSpecifier1: 112 case ErrSpecifier1: {
114 {
115 const auto& errtype = errinfo->errtype1; 113 const auto& errtype = errinfo->errtype1;
116 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); 114 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)); 115 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
@@ -119,15 +117,14 @@ static void ThrowFatalError(Service::Interface* self) {
119 LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address); 117 LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address);
120 118
121 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); 119 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
122 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value()); 120 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
123 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value()); 121 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
124 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value()); 122 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
125 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value()); 123 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
126 break; 124 break;
127 } 125 }
128 126
129 case ErrSpecifier3: 127 case ErrSpecifier3: {
130 {
131 const auto& errtype = errinfo->errtype3; 128 const auto& errtype = errinfo->errtype3;
132 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); 129 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)); 130 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
@@ -154,18 +151,17 @@ static void ThrowFatalError(Service::Interface* self) {
154 break; 151 break;
155 } 152 }
156 153
157 case ErrSpecifier4: 154 case ErrSpecifier4: {
158 {
159 const auto& errtype = errinfo->errtype4; 155 const auto& errtype = errinfo->errtype4;
160 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); 156 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)); 157 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); 158 LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
163 159
164 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); 160 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
165 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value()); 161 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
166 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value()); 162 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
167 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value()); 163 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
168 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value()); 164 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
169 165
170 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1); 166 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1);
171 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2); 167 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2);
@@ -177,7 +173,7 @@ static void ThrowFatalError(Service::Interface* self) {
177} 173}
178 174
179const Interface::FunctionInfo FunctionTable[] = { 175const Interface::FunctionInfo FunctionTable[] = {
180 {0x00010800, ThrowFatalError, "ThrowFatalError"} 176 {0x00010800, ThrowFatalError, "ThrowFatalError"},
181}; 177};
182 178
183//////////////////////////////////////////////////////////////////////////////////////////////////// 179////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp
index 29d144365..fa5080535 100644
--- a/src/core/hle/service/frd/frd.cpp
+++ b/src/core/hle/service/frd/frd.cpp
@@ -3,11 +3,10 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/string_util.h" 5#include "common/string_util.h"
6
7#include "core/hle/service/service.h"
8#include "core/hle/service/frd/frd.h" 6#include "core/hle/service/frd/frd.h"
9#include "core/hle/service/frd/frd_a.h" 7#include "core/hle/service/frd/frd_a.h"
10#include "core/hle/service/frd/frd_u.h" 8#include "core/hle/service/frd/frd_u.h"
9#include "core/hle/service/service.h"
11 10
12namespace Service { 11namespace Service {
13namespace FRD { 12namespace FRD {
@@ -43,7 +42,7 @@ void GetFriendKeyList(Service::Interface* self) {
43 } 42 }
44 43
45 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 44 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
46 cmd_buff[2] = 0; // 0 friends 45 cmd_buff[2] = 0; // 0 friends
47 LOG_WARNING(Service_FRD, "(STUBBED) called, unknown=%d, frd_count=%d, frd_key_addr=0x%08X", 46 LOG_WARNING(Service_FRD, "(STUBBED) called, unknown=%d, frd_count=%d, frd_key_addr=0x%08X",
48 unknown, frd_count, frd_key_addr); 47 unknown, frd_count, frd_key_addr);
49} 48}
@@ -61,25 +60,27 @@ void GetFriendProfile(Service::Interface* self) {
61 } 60 }
62 61
63 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 62 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", 63 LOG_WARNING(Service_FRD,
65 count, frd_key_addr, profiles_addr); 64 "(STUBBED) called, count=%d, frd_key_addr=0x%08X, profiles_addr=0x%08X", count,
65 frd_key_addr, profiles_addr);
66} 66}
67 67
68void GetFriendAttributeFlags(Service::Interface* self) { 68void GetFriendAttributeFlags(Service::Interface* self) {
69 u32* cmd_buff = Kernel::GetCommandBuffer(); 69 u32* cmd_buff = Kernel::GetCommandBuffer();
70 70
71 u32 count = cmd_buff[1]; 71 u32 count = cmd_buff[1];
72 u32 frd_key_addr = cmd_buff[3]; 72 u32 frd_key_addr = cmd_buff[3];
73 u32 attr_flags_addr = cmd_buff[65]; 73 u32 attr_flags_addr = cmd_buff[65];
74 74
75 for (u32 i = 0; i < count; ++i) { 75 for (u32 i = 0; i < count; ++i) {
76 //TODO:(mailwl) figure out AttributeFlag size and zero all buffer. Assume 1 byte 76 // TODO:(mailwl) figure out AttributeFlag size and zero all buffer. Assume 1 byte
77 Memory::Write8(attr_flags_addr + i, 0); 77 Memory::Write8(attr_flags_addr + i, 0);
78 } 78 }
79 79
80 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 80 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", 81 LOG_WARNING(Service_FRD,
82 count, frd_key_addr, attr_flags_addr); 82 "(STUBBED) called, count=%d, frd_key_addr=0x%08X, attr_flags_addr=0x%08X", count,
83 frd_key_addr, attr_flags_addr);
83} 84}
84 85
85void GetMyFriendKey(Service::Interface* self) { 86void GetMyFriendKey(Service::Interface* self) {
@@ -106,8 +107,7 @@ void Init() {
106 AddService(new FRD_U_Interface); 107 AddService(new FRD_U_Interface);
107} 108}
108 109
109void Shutdown() { 110void Shutdown() {}
110}
111 111
112} // namespace FRD 112} // namespace FRD
113 113
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..4dc7e1e3c 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -3,19 +3,16 @@
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
12#include <boost/container/flat_map.hpp> 11#include <boost/container/flat_map.hpp>
13
14#include "common/assert.h" 12#include "common/assert.h"
15#include "common/common_types.h" 13#include "common/common_types.h"
16#include "common/file_util.h" 14#include "common/file_util.h"
17#include "common/logging/log.h" 15#include "common/logging/log.h"
18
19#include "core/file_sys/archive_backend.h" 16#include "core/file_sys/archive_backend.h"
20#include "core/file_sys/archive_extsavedata.h" 17#include "core/file_sys/archive_extsavedata.h"
21#include "core/file_sys/archive_savedata.h" 18#include "core/file_sys/archive_savedata.h"
@@ -25,25 +22,25 @@
25#include "core/file_sys/directory_backend.h" 22#include "core/file_sys/directory_backend.h"
26#include "core/file_sys/file_backend.h" 23#include "core/file_sys/file_backend.h"
27#include "core/hle/hle.h" 24#include "core/hle/hle.h"
28#include "core/hle/service/service.h" 25#include "core/hle/result.h"
29#include "core/hle/service/fs/archive.h" 26#include "core/hle/service/fs/archive.h"
30#include "core/hle/service/fs/fs_user.h" 27#include "core/hle/service/fs/fs_user.h"
31#include "core/hle/result.h" 28#include "core/hle/service/service.h"
32#include "core/memory.h" 29#include "core/memory.h"
33 30
34// Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. 31// 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 32// Workaroung for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970
36namespace std { 33namespace std {
37 template <> 34template <>
38 struct hash<Service::FS::ArchiveIdCode> { 35struct hash<Service::FS::ArchiveIdCode> {
39 typedef Service::FS::ArchiveIdCode argument_type; 36 typedef Service::FS::ArchiveIdCode argument_type;
40 typedef std::size_t result_type; 37 typedef std::size_t result_type;
41 38
42 result_type operator()(const argument_type& id_code) const { 39 result_type operator()(const argument_type& id_code) const {
43 typedef std::underlying_type<argument_type>::type Type; 40 typedef std::underlying_type<argument_type>::type Type;
44 return std::hash<Type>()(static_cast<Type>(id_code)); 41 return std::hash<Type>()(static_cast<Type>(id_code));
45 } 42 }
46 }; 43};
47} 44}
48 45
49/// TODO(Subv): Confirm length of these strings 46/// TODO(Subv): Confirm length of these strings
@@ -56,39 +53,40 @@ namespace FS {
56// TODO: Verify code 53// TODO: Verify code
57/// Returned when a function is passed an invalid handle. 54/// Returned when a function is passed an invalid handle.
58const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS, 55const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS,
59 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 56 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
60 57
61/// Returned when a function is passed an invalid archive handle. 58/// Returned when a function is passed an invalid archive handle.
62const ResultCode ERR_INVALID_ARCHIVE_HANDLE(ErrorDescription::FS_ArchiveNotMounted, ErrorModule::FS, 59const ResultCode ERR_INVALID_ARCHIVE_HANDLE(ErrorDescription::FS_ArchiveNotMounted, ErrorModule::FS,
63 ErrorSummary::NotFound, ErrorLevel::Status); // 0xC8804465 60 ErrorSummary::NotFound,
61 ErrorLevel::Status); // 0xC8804465
64 62
65// Command to access archive file 63// Command to access archive file
66enum class FileCommand : u32 { 64enum class FileCommand : u32 {
67 Dummy1 = 0x000100C6, 65 Dummy1 = 0x000100C6,
68 Control = 0x040100C4, 66 Control = 0x040100C4,
69 OpenSubFile = 0x08010100, 67 OpenSubFile = 0x08010100,
70 Read = 0x080200C2, 68 Read = 0x080200C2,
71 Write = 0x08030102, 69 Write = 0x08030102,
72 GetSize = 0x08040000, 70 GetSize = 0x08040000,
73 SetSize = 0x08050080, 71 SetSize = 0x08050080,
74 GetAttributes = 0x08060000, 72 GetAttributes = 0x08060000,
75 SetAttributes = 0x08070040, 73 SetAttributes = 0x08070040,
76 Close = 0x08080000, 74 Close = 0x08080000,
77 Flush = 0x08090000, 75 Flush = 0x08090000,
78 SetPriority = 0x080A0040, 76 SetPriority = 0x080A0040,
79 GetPriority = 0x080B0000, 77 GetPriority = 0x080B0000,
80 OpenLinkFile = 0x080C0000, 78 OpenLinkFile = 0x080C0000,
81}; 79};
82 80
83// Command to access directory 81// Command to access directory
84enum class DirectoryCommand : u32 { 82enum class DirectoryCommand : u32 {
85 Dummy1 = 0x000100C6, 83 Dummy1 = 0x000100C6,
86 Control = 0x040100C4, 84 Control = 0x040100C4,
87 Read = 0x08010042, 85 Read = 0x08010042,
88 Close = 0x08020000, 86 Close = 0x08020000,
89}; 87};
90 88
91File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path & path) 89File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path)
92 : path(path), priority(0), backend(std::move(backend)) {} 90 : path(path), priority(0), backend(std::move(backend)) {}
93 91
94File::~File() {} 92File::~File() {}
@@ -98,117 +96,110 @@ ResultVal<bool> File::SyncRequest() {
98 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 96 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
99 switch (cmd) { 97 switch (cmd) {
100 98
101 // Read from file... 99 // Read from file...
102 case FileCommand::Read: 100 case FileCommand::Read: {
103 { 101 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32;
104 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; 102 u32 length = cmd_buff[3];
105 u32 length = cmd_buff[3]; 103 u32 address = cmd_buff[5];
106 u32 address = cmd_buff[5]; 104 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", 105 GetTypeName().c_str(), GetName().c_str(), offset, length, address);
108 GetTypeName().c_str(), GetName().c_str(), offset, length, address); 106
109 107 if (offset + length > backend->GetSize()) {
110 if (offset + length > backend->GetSize()) { 108 LOG_ERROR(Service_FS,
111 LOG_ERROR(Service_FS, "Reading from out of bounds offset=0x%llX length=0x%08X file_size=0x%llX", 109 "Reading from out of bounds offset=0x%llX length=0x%08X file_size=0x%llX",
112 offset, length, backend->GetSize()); 110 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 } 111 }
125 112
126 // Write to file... 113 std::vector<u8> data(length);
127 case FileCommand::Write: 114 ResultVal<size_t> read = backend->Read(offset, data.size(), data.data());
128 { 115 if (read.Failed()) {
129 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; 116 cmd_buff[1] = read.Code().raw;
130 u32 length = cmd_buff[3]; 117 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 } 118 }
119 Memory::WriteBlock(address, data.data(), *read);
120 cmd_buff[2] = static_cast<u32>(*read);
121 break;
122 }
146 123
147 case FileCommand::GetSize: 124 // Write to file...
148 { 125 case FileCommand::Write: {
149 LOG_TRACE(Service_FS, "GetSize %s %s", GetTypeName().c_str(), GetName().c_str()); 126 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32;
150 u64 size = backend->GetSize(); 127 u32 length = cmd_buff[3];
151 cmd_buff[2] = (u32)size; 128 u32 flush = cmd_buff[4];
152 cmd_buff[3] = size >> 32; 129 u32 address = cmd_buff[6];
153 break; 130 LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x",
131 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush);
132
133 std::vector<u8> data(length);
134 Memory::ReadBlock(address, data.data(), data.size());
135 ResultVal<size_t> written = backend->Write(offset, data.size(), flush != 0, data.data());
136 if (written.Failed()) {
137 cmd_buff[1] = written.Code().raw;
138 return written.Code();
154 } 139 }
140 cmd_buff[2] = static_cast<u32>(*written);
141 break;
142 }
155 143
156 case FileCommand::SetSize: 144 case FileCommand::GetSize: {
157 { 145 LOG_TRACE(Service_FS, "GetSize %s %s", GetTypeName().c_str(), GetName().c_str());
158 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); 146 u64 size = backend->GetSize();
159 LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", 147 cmd_buff[2] = (u32)size;
160 GetTypeName().c_str(), GetName().c_str(), size); 148 cmd_buff[3] = size >> 32;
161 backend->SetSize(size); 149 break;
162 break; 150 }
163 }
164 151
165 case FileCommand::Close: 152 case FileCommand::SetSize: {
166 { 153 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
167 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); 154 LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", GetTypeName().c_str(), GetName().c_str(),
168 backend->Close(); 155 size);
169 break; 156 backend->SetSize(size);
170 } 157 break;
158 }
171 159
172 case FileCommand::Flush: 160 case FileCommand::Close: {
173 { 161 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
174 LOG_TRACE(Service_FS, "Flush"); 162 backend->Close();
175 backend->Flush(); 163 break;
176 break; 164 }
177 }
178 165
179 case FileCommand::OpenLinkFile: 166 case FileCommand::Flush: {
180 { 167 LOG_TRACE(Service_FS, "Flush");
181 LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); 168 backend->Flush();
182 cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE); 169 break;
183 break; 170 }
184 }
185 171
186 case FileCommand::SetPriority: 172 case FileCommand::OpenLinkFile: {
187 { 173 LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str());
188 priority = cmd_buff[1]; 174 cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE);
189 LOG_TRACE(Service_FS, "SetPriority %u", priority); 175 break;
190 break; 176 }
191 }
192 177
193 case FileCommand::GetPriority: 178 case FileCommand::SetPriority: {
194 { 179 priority = cmd_buff[1];
195 cmd_buff[2] = priority; 180 LOG_TRACE(Service_FS, "SetPriority %u", priority);
196 LOG_TRACE(Service_FS, "GetPriority"); 181 break;
197 break; 182 }
198 } 183
184 case FileCommand::GetPriority: {
185 cmd_buff[2] = priority;
186 LOG_TRACE(Service_FS, "GetPriority");
187 break;
188 }
199 189
200 // Unknown command... 190 // Unknown command...
201 default: 191 default:
202 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); 192 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
203 ResultCode error = UnimplementedFunction(ErrorModule::FS); 193 ResultCode error = UnimplementedFunction(ErrorModule::FS);
204 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. 194 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
205 return error; 195 return error;
206 } 196 }
207 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 197 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
208 return MakeResult<bool>(false); 198 return MakeResult<bool>(false);
209} 199}
210 200
211Directory::Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path & path) 201Directory::Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend,
202 const FileSys::Path& path)
212 : path(path), backend(std::move(backend)) {} 203 : path(path), backend(std::move(backend)) {}
213 204
214Directory::~Directory() {} 205Directory::~Directory() {}
@@ -218,35 +209,33 @@ ResultVal<bool> Directory::SyncRequest() {
218 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); 209 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
219 switch (cmd) { 210 switch (cmd) {
220 211
221 // Read from directory... 212 // Read from directory...
222 case DirectoryCommand::Read: 213 case DirectoryCommand::Read: {
223 { 214 u32 count = cmd_buff[1];
224 u32 count = cmd_buff[1]; 215 u32 address = cmd_buff[3];
225 u32 address = cmd_buff[3]; 216 std::vector<FileSys::Entry> entries(count);
226 std::vector<FileSys::Entry> entries(count); 217 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", 218 count);
228 GetTypeName().c_str(), GetName().c_str(), count); 219
229 220 // Number of entries actually read
230 // Number of entries actually read 221 u32 read = backend->Read(entries.size(), entries.data());
231 u32 read = backend->Read(entries.size(), entries.data()); 222 cmd_buff[2] = read;
232 cmd_buff[2] = read; 223 Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry));
233 Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry)); 224 break;
234 break; 225 }
235 }
236 226
237 case DirectoryCommand::Close: 227 case DirectoryCommand::Close: {
238 { 228 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()); 229 backend->Close();
240 backend->Close(); 230 break;
241 break; 231 }
242 }
243 232
244 // Unknown command... 233 // Unknown command...
245 default: 234 default:
246 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); 235 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
247 ResultCode error = UnimplementedFunction(ErrorModule::FS); 236 ResultCode error = UnimplementedFunction(ErrorModule::FS);
248 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. 237 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
249 return MakeResult<bool>(false); 238 return MakeResult<bool>(false);
250 } 239 }
251 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 240 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
252 return MakeResult<bool>(false); 241 return MakeResult<bool>(false);
@@ -280,8 +269,8 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
280 auto itr = id_code_map.find(id_code); 269 auto itr = id_code_map.find(id_code);
281 if (itr == id_code_map.end()) { 270 if (itr == id_code_map.end()) {
282 // TODO: Verify error against hardware 271 // TODO: Verify error against hardware
283 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, 272 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, ErrorSummary::NotFound,
284 ErrorSummary::NotFound, ErrorLevel::Permanent); 273 ErrorLevel::Permanent);
285 } 274 }
286 275
287 CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); 276 CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path));
@@ -303,19 +292,22 @@ ResultCode CloseArchive(ArchiveHandle handle) {
303 292
304// TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in 293// 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 294// http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22
306ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code) { 295ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory,
296 ArchiveIdCode id_code) {
307 auto result = id_code_map.emplace(id_code, std::move(factory)); 297 auto result = id_code_map.emplace(id_code, std::move(factory));
308 298
309 bool inserted = result.second; 299 bool inserted = result.second;
310 ASSERT_MSG(inserted, "Tried to register more than one archive with same id code"); 300 ASSERT_MSG(inserted, "Tried to register more than one archive with same id code");
311 301
312 auto& archive = result.first->second; 302 auto& archive = result.first->second;
313 LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); 303 LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(),
304 id_code);
314 return RESULT_SUCCESS; 305 return RESULT_SUCCESS;
315} 306}
316 307
317ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, 308ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle,
318 const FileSys::Path& path, const FileSys::Mode mode) { 309 const FileSys::Path& path,
310 const FileSys::Mode mode) {
319 ArchiveBackend* archive = GetArchive(archive_handle); 311 ArchiveBackend* archive = GetArchive(archive_handle);
320 if (archive == nullptr) 312 if (archive == nullptr)
321 return ERR_INVALID_ARCHIVE_HANDLE; 313 return ERR_INVALID_ARCHIVE_HANDLE;
@@ -336,8 +328,10 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa
336 return archive->DeleteFile(path); 328 return archive->DeleteFile(path);
337} 329}
338 330
339ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 331ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle,
340 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { 332 const FileSys::Path& src_path,
333 ArchiveHandle dest_archive_handle,
334 const FileSys::Path& dest_path) {
341 ArchiveBackend* src_archive = GetArchive(src_archive_handle); 335 ArchiveBackend* src_archive = GetArchive(src_archive_handle);
342 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); 336 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle);
343 if (src_archive == nullptr || dest_archive == nullptr) 337 if (src_archive == nullptr || dest_archive == nullptr)
@@ -368,7 +362,8 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
368 ErrorSummary::Canceled, ErrorLevel::Status); 362 ErrorSummary::Canceled, ErrorLevel::Status);
369} 363}
370 364
371ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u64 file_size) { 365ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path,
366 u64 file_size) {
372 ArchiveBackend* archive = GetArchive(archive_handle); 367 ArchiveBackend* archive = GetArchive(archive_handle);
373 if (archive == nullptr) 368 if (archive == nullptr)
374 return ERR_INVALID_ARCHIVE_HANDLE; 369 return ERR_INVALID_ARCHIVE_HANDLE;
@@ -387,8 +382,10 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
387 ErrorSummary::Canceled, ErrorLevel::Status); 382 ErrorSummary::Canceled, ErrorLevel::Status);
388} 383}
389 384
390ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 385ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle,
391 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { 386 const FileSys::Path& src_path,
387 ArchiveHandle dest_archive_handle,
388 const FileSys::Path& dest_path) {
392 ArchiveBackend* src_archive = GetArchive(src_archive_handle); 389 ArchiveBackend* src_archive = GetArchive(src_archive_handle);
393 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); 390 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle);
394 if (src_archive == nullptr || dest_archive == nullptr) 391 if (src_archive == nullptr || dest_archive == nullptr)
@@ -409,15 +406,15 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
409} 406}
410 407
411ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, 408ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
412 const FileSys::Path& path) { 409 const FileSys::Path& path) {
413 ArchiveBackend* archive = GetArchive(archive_handle); 410 ArchiveBackend* archive = GetArchive(archive_handle);
414 if (archive == nullptr) 411 if (archive == nullptr)
415 return ERR_INVALID_ARCHIVE_HANDLE; 412 return ERR_INVALID_ARCHIVE_HANDLE;
416 413
417 std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path); 414 std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path);
418 if (backend == nullptr) { 415 if (backend == nullptr) {
419 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, 416 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
420 ErrorSummary::NotFound, ErrorLevel::Permanent); 417 ErrorLevel::Permanent);
421 } 418 }
422 419
423 auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path)); 420 auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path));
@@ -431,7 +428,8 @@ ResultVal<u64> GetFreeBytesInArchive(ArchiveHandle archive_handle) {
431 return MakeResult<u64>(archive->GetFreeBytes()); 428 return MakeResult<u64>(archive->GetFreeBytes());
432} 429}
433 430
434ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, const FileSys::Path& path) { 431ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info,
432 const FileSys::Path& path) {
435 auto archive_itr = id_code_map.find(id_code); 433 auto archive_itr = id_code_map.find(id_code);
436 if (archive_itr == id_code_map.end()) { 434 if (archive_itr == id_code_map.end()) {
437 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error 435 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
@@ -440,7 +438,8 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo
440 return archive_itr->second->Format(path, format_info); 438 return archive_itr->second->Format(path, format_info);
441} 439}
442 440
443ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, FileSys::Path& archive_path) { 441ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code,
442 FileSys::Path& archive_path) {
444 auto archive = id_code_map.find(id_code); 443 auto archive = id_code_map.find(id_code);
445 if (archive == id_code_map.end()) { 444 if (archive == id_code_map.end()) {
446 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error 445 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
@@ -449,11 +448,14 @@ ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code
449 return archive->second->GetFormatInfo(archive_path); 448 return archive->second->GetFormatInfo(archive_path);
450} 449}
451 450
452ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size, const FileSys::ArchiveFormatInfo& format_info) { 451ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer,
452 u32 icon_size, const FileSys::ArchiveFormatInfo& format_info) {
453 // Construct the binary path to the archive first 453 // Construct the binary path to the archive first
454 FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); 454 FileSys::Path path =
455 FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low);
455 456
456 auto archive = id_code_map.find(media_type == MediaType::NAND ? ArchiveIdCode::SharedExtSaveData : ArchiveIdCode::ExtSaveData); 457 auto archive = id_code_map.find(media_type == MediaType::NAND ? ArchiveIdCode::SharedExtSaveData
458 : ArchiveIdCode::ExtSaveData);
457 459
458 if (archive == id_code_map.end()) { 460 if (archive == id_code_map.end()) {
459 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error 461 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
@@ -476,7 +478,8 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon
476 478
477ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) { 479ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) {
478 // Construct the binary path to the archive first 480 // Construct the binary path to the archive first
479 FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); 481 FileSys::Path path =
482 FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low);
480 483
481 std::string media_type_directory; 484 std::string media_type_directory;
482 if (media_type == MediaType::NAND) { 485 if (media_type == MediaType::NAND) {
@@ -489,7 +492,8 @@ ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) {
489 } 492 }
490 493
491 // Delete all directories (/user, /boss) and the icon file. 494 // Delete all directories (/user, /boss) and the icon file.
492 std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND); 495 std::string base_path =
496 FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND);
493 std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path); 497 std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path);
494 if (FileUtil::Exists(extsavedata_path) && !FileUtil::DeleteDirRecursively(extsavedata_path)) 498 if (FileUtil::Exists(extsavedata_path) && !FileUtil::DeleteDirRecursively(extsavedata_path))
495 return ResultCode(-1); // TODO(Subv): Find the right error code 499 return ResultCode(-1); // TODO(Subv): Find the right error code
@@ -530,30 +534,36 @@ void RegisterArchiveTypes() {
530 if (sdmc_factory->Initialize()) 534 if (sdmc_factory->Initialize())
531 RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC); 535 RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC);
532 else 536 else
533 LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); 537 LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s",
538 sdmc_directory.c_str());
534 539
535 // Create the SaveData archive 540 // Create the SaveData archive
536 auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); 541 auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory);
537 RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); 542 RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData);
538 543
539 auto extsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); 544 auto extsavedata_factory =
545 std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false);
540 if (extsavedata_factory->Initialize()) 546 if (extsavedata_factory->Initialize())
541 RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData); 547 RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData);
542 else 548 else
543 LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_factory->GetMountPoint().c_str()); 549 LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s",
550 extsavedata_factory->GetMountPoint().c_str());
544 551
545 auto sharedextsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true); 552 auto sharedextsavedata_factory =
553 std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true);
546 if (sharedextsavedata_factory->Initialize()) 554 if (sharedextsavedata_factory->Initialize())
547 RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); 555 RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData);
548 else 556 else
549 LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", 557 LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s",
550 sharedextsavedata_factory->GetMountPoint().c_str()); 558 sharedextsavedata_factory->GetMountPoint().c_str());
551 559
552 // Create the SaveDataCheck archive, basically a small variation of the RomFS archive 560 // Create the SaveDataCheck archive, basically a small variation of the RomFS archive
553 auto savedatacheck_factory = std::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); 561 auto savedatacheck_factory =
562 std::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory);
554 RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); 563 RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck);
555 564
556 auto systemsavedata_factory = std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory); 565 auto systemsavedata_factory =
566 std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
557 RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData); 567 RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData);
558} 568}
559 569
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index f7a50a3a7..533be34a4 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -6,9 +6,7 @@
6 6
7#include <memory> 7#include <memory>
8#include <string> 8#include <string>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11
12#include "core/file_sys/archive_backend.h" 10#include "core/file_sys/archive_backend.h"
13#include "core/hle/kernel/session.h" 11#include "core/hle/kernel/session.h"
14#include "core/hle/result.h" 12#include "core/hle/result.h"
@@ -28,21 +26,18 @@ namespace FS {
28 26
29/// Supported archive types 27/// Supported archive types
30enum class ArchiveIdCode : u32 { 28enum class ArchiveIdCode : u32 {
31 RomFS = 0x00000003, 29 RomFS = 0x00000003,
32 SaveData = 0x00000004, 30 SaveData = 0x00000004,
33 ExtSaveData = 0x00000006, 31 ExtSaveData = 0x00000006,
34 SharedExtSaveData = 0x00000007, 32 SharedExtSaveData = 0x00000007,
35 SystemSaveData = 0x00000008, 33 SystemSaveData = 0x00000008,
36 SDMC = 0x00000009, 34 SDMC = 0x00000009,
37 SDMCWriteOnly = 0x0000000A, 35 SDMCWriteOnly = 0x0000000A,
38 SaveDataCheck = 0x2345678A, 36 SaveDataCheck = 0x2345678A,
39}; 37};
40 38
41/// Media types for the archives 39/// Media types for the archives
42enum class MediaType : u32 { 40enum class MediaType : u32 { NAND = 0, SDMC = 1 };
43 NAND = 0,
44 SDMC = 1
45};
46 41
47typedef u64 ArchiveHandle; 42typedef u64 ArchiveHandle;
48 43
@@ -51,11 +46,13 @@ public:
51 File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path); 46 File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path);
52 ~File(); 47 ~File();
53 48
54 std::string GetName() const override { return "Path: " + path.DebugStr(); } 49 std::string GetName() const override {
50 return "Path: " + path.DebugStr();
51 }
55 ResultVal<bool> SyncRequest() override; 52 ResultVal<bool> SyncRequest() override;
56 53
57 FileSys::Path path; ///< Path of the file 54 FileSys::Path path; ///< Path of the file
58 u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means 55 u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means
59 std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface 56 std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface
60}; 57};
61 58
@@ -64,10 +61,12 @@ public:
64 Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path); 61 Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path);
65 ~Directory(); 62 ~Directory();
66 63
67 std::string GetName() const override { return "Directory: " + path.DebugStr(); } 64 std::string GetName() const override {
65 return "Directory: " + path.DebugStr();
66 }
68 ResultVal<bool> SyncRequest() override; 67 ResultVal<bool> SyncRequest() override;
69 68
70 FileSys::Path path; ///< Path of the directory 69 FileSys::Path path; ///< Path of the directory
71 std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface 70 std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface
72}; 71};
73 72
@@ -90,7 +89,8 @@ ResultCode CloseArchive(ArchiveHandle handle);
90 * @param factory File system backend interface to the archive 89 * @param factory File system backend interface to the archive
91 * @param id_code Id code used to access this type of archive 90 * @param id_code Id code used to access this type of archive
92 */ 91 */
93ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code); 92ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory,
93 ArchiveIdCode id_code);
94 94
95/** 95/**
96 * Open a File from an Archive 96 * Open a File from an Archive
@@ -100,7 +100,8 @@ ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factor
100 * @return The opened File object as a Session 100 * @return The opened File object as a Session
101 */ 101 */
102ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, 102ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle,
103 const FileSys::Path& path, const FileSys::Mode mode); 103 const FileSys::Path& path,
104 const FileSys::Mode mode);
104 105
105/** 106/**
106 * Delete a File from an Archive 107 * Delete a File from an Archive
@@ -118,8 +119,10 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa
118 * @param dest_path Path to the File inside of the destination Archive 119 * @param dest_path Path to the File inside of the destination Archive
119 * @return Whether rename succeeded 120 * @return Whether rename succeeded
120 */ 121 */
121ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 122ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle,
122 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); 123 const FileSys::Path& src_path,
124 ArchiveHandle dest_archive_handle,
125 const FileSys::Path& dest_path);
123 126
124/** 127/**
125 * Delete a Directory from an Archive 128 * Delete a Directory from an Archive
@@ -136,7 +139,8 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
136 * @param file_size The size of the new file, filled with zeroes 139 * @param file_size The size of the new file, filled with zeroes
137 * @return File creation result code 140 * @return File creation result code
138 */ 141 */
139ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u64 file_size); 142ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path,
143 u64 file_size);
140 144
141/** 145/**
142 * Create a Directory from an Archive 146 * Create a Directory from an Archive
@@ -154,8 +158,10 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
154 * @param dest_path Path to the Directory inside of the destination Archive 158 * @param dest_path Path to the Directory inside of the destination Archive
155 * @return Whether rename succeeded 159 * @return Whether rename succeeded
156 */ 160 */
157ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 161ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle,
158 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); 162 const FileSys::Path& src_path,
163 ArchiveHandle dest_archive_handle,
164 const FileSys::Path& dest_path);
159 165
160/** 166/**
161 * Open a Directory from an Archive 167 * Open a Directory from an Archive
@@ -164,7 +170,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
164 * @return The opened Directory object as a Session 170 * @return The opened Directory object as a Session
165 */ 171 */
166ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, 172ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
167 const FileSys::Path& path); 173 const FileSys::Path& path);
168 174
169/** 175/**
170 * Get the free space in an Archive 176 * Get the free space in an Archive
@@ -181,7 +187,8 @@ ResultVal<u64> GetFreeBytesInArchive(ArchiveHandle archive_handle);
181 * @param path The path to the archive, if relevant. 187 * @param path The path to the archive, if relevant.
182 * @return ResultCode 0 on success or the corresponding code on error 188 * @return ResultCode 0 on success or the corresponding code on error
183 */ 189 */
184ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, const FileSys::Path& path = FileSys::Path()); 190ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info,
191 const FileSys::Path& path = FileSys::Path());
185 192
186/** 193/**
187 * Retrieves the format info about the archive of the specified type and path. 194 * Retrieves the format info about the archive of the specified type and path.
@@ -190,7 +197,8 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo
190 * @param archive_path The path of the archive, if relevant 197 * @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. 198 * @return The format info of the archive, or the corresponding error code if failed.
192 */ 199 */
193ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, FileSys::Path& archive_path); 200ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code,
201 FileSys::Path& archive_path);
194 202
195/** 203/**
196 * Creates a blank SharedExtSaveData archive for the specified extdata ID 204 * Creates a blank SharedExtSaveData archive for the specified extdata ID
@@ -202,7 +210,8 @@ ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code
202 * @param format_info Format information about the new archive 210 * @param format_info Format information about the new archive
203 * @return ResultCode 0 on success or the corresponding code on error 211 * @return ResultCode 0 on success or the corresponding code on error
204 */ 212 */
205ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size, const FileSys::ArchiveFormatInfo& format_info); 213ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer,
214 u32 icon_size, const FileSys::ArchiveFormatInfo& format_info);
206 215
207/** 216/**
208 * Deletes the SharedExtSaveData archive for the specified extdata ID 217 * 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..94f053dc2 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -8,7 +8,6 @@
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "common/scope_exit.h" 9#include "common/scope_exit.h"
10#include "common/string_util.h" 10#include "common/string_util.h"
11
12#include "core/hle/result.h" 11#include "core/hle/result.h"
13#include "core/hle/service/fs/archive.h" 12#include "core/hle/service/fs/archive.h"
14#include "core/hle/service/fs/fs_user.h" 13#include "core/hle/service/fs/fs_user.h"
@@ -57,14 +56,16 @@ static void OpenFile(Service::Interface* self) {
57 u32* cmd_buff = Kernel::GetCommandBuffer(); 56 u32* cmd_buff = Kernel::GetCommandBuffer();
58 57
59 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 58 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
60 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 59 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
61 u32 filename_size = cmd_buff[5]; 60 u32 filename_size = cmd_buff[5];
62 FileSys::Mode mode; mode.hex = cmd_buff[6]; 61 FileSys::Mode mode;
63 u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes. 62 mode.hex = cmd_buff[6];
64 u32 filename_ptr = cmd_buff[9]; 63 u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes.
64 u32 filename_ptr = cmd_buff[9];
65 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 65 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
66 66
67 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); 67 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex,
68 attributes);
68 69
69 ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); 70 ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode);
70 cmd_buff[1] = file_res.Code().raw; 71 cmd_buff[1] = file_res.Code().raw;
@@ -98,24 +99,27 @@ static void OpenFile(Service::Interface* self) {
98static void OpenFileDirectly(Service::Interface* self) { 99static void OpenFileDirectly(Service::Interface* self) {
99 u32* cmd_buff = Kernel::GetCommandBuffer(); 100 u32* cmd_buff = Kernel::GetCommandBuffer();
100 101
101 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[2]); 102 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[2]);
102 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); 103 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]);
103 u32 archivename_size = cmd_buff[4]; 104 u32 archivename_size = cmd_buff[4];
104 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]); 105 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]);
105 u32 filename_size = cmd_buff[6]; 106 u32 filename_size = cmd_buff[6];
106 FileSys::Mode mode; mode.hex = cmd_buff[7]; 107 FileSys::Mode mode;
107 u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes. 108 mode.hex = cmd_buff[7];
108 u32 archivename_ptr = cmd_buff[10]; 109 u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes.
109 u32 filename_ptr = cmd_buff[12]; 110 u32 archivename_ptr = cmd_buff[10];
111 u32 filename_ptr = cmd_buff[12];
110 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); 112 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
111 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 113 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
112 114
113 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s file_path=%s, mode=%u attributes=%d", 115 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); 116 archive_id, archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex,
117 attributes);
115 118
116 ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path); 119 ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path);
117 if (archive_handle.Failed()) { 120 if (archive_handle.Failed()) {
118 LOG_ERROR(Service_FS, "failed to get a handle for archive archive_id=0x%08X archive_path=%s", 121 LOG_ERROR(Service_FS,
122 "failed to get a handle for archive archive_id=0x%08X archive_path=%s",
119 archive_id, archive_path.DebugStr().c_str()); 123 archive_id, archive_path.DebugStr().c_str());
120 cmd_buff[1] = archive_handle.Code().raw; 124 cmd_buff[1] = archive_handle.Code().raw;
121 cmd_buff[3] = 0; 125 cmd_buff[3] = 0;
@@ -149,14 +153,14 @@ static void DeleteFile(Service::Interface* self) {
149 u32* cmd_buff = Kernel::GetCommandBuffer(); 153 u32* cmd_buff = Kernel::GetCommandBuffer();
150 154
151 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 155 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
152 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 156 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
153 u32 filename_size = cmd_buff[5]; 157 u32 filename_size = cmd_buff[5];
154 u32 filename_ptr = cmd_buff[7]; 158 u32 filename_ptr = cmd_buff[7];
155 159
156 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 160 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
157 161
158 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", 162 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", filename_type, filename_size,
159 filename_type, filename_size, file_path.DebugStr().c_str()); 163 file_path.DebugStr().c_str());
160 164
161 cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw; 165 cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw;
162} 166}
@@ -181,22 +185,26 @@ static void RenameFile(Service::Interface* self) {
181 u32* cmd_buff = Kernel::GetCommandBuffer(); 185 u32* cmd_buff = Kernel::GetCommandBuffer();
182 186
183 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 187 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
184 auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 188 auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
185 u32 src_filename_size = cmd_buff[5]; 189 u32 src_filename_size = cmd_buff[5];
186 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);; 190 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);
187 auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); 191 ;
188 u32 dest_filename_size = cmd_buff[9]; 192 auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
189 u32 src_filename_ptr = cmd_buff[11]; 193 u32 dest_filename_size = cmd_buff[9];
190 u32 dest_filename_ptr = cmd_buff[13]; 194 u32 src_filename_ptr = cmd_buff[11];
195 u32 dest_filename_ptr = cmd_buff[13];
191 196
192 FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr); 197 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); 198 FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr);
194 199
195 LOG_DEBUG(Service_FS, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s", 200 LOG_DEBUG(Service_FS,
201 "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(), 202 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()); 203 dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str());
198 204
199 cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw; 205 cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle,
206 dest_file_path)
207 .raw;
200} 208}
201 209
202/* 210/*
@@ -214,14 +222,14 @@ static void DeleteDirectory(Service::Interface* self) {
214 u32* cmd_buff = Kernel::GetCommandBuffer(); 222 u32* cmd_buff = Kernel::GetCommandBuffer();
215 223
216 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 224 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
217 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 225 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
218 u32 dirname_size = cmd_buff[5]; 226 u32 dirname_size = cmd_buff[5];
219 u32 dirname_ptr = cmd_buff[7]; 227 u32 dirname_ptr = cmd_buff[7];
220 228
221 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); 229 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
222 230
223 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", 231 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size,
224 dirname_type, dirname_size, dir_path.DebugStr().c_str()); 232 dir_path.DebugStr().c_str());
225 233
226 cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw; 234 cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw;
227} 235}
@@ -243,14 +251,15 @@ static void CreateFile(Service::Interface* self) {
243 u32* cmd_buff = Kernel::GetCommandBuffer(); 251 u32* cmd_buff = Kernel::GetCommandBuffer();
244 252
245 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 253 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
246 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 254 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
247 u32 filename_size = cmd_buff[5]; 255 u32 filename_size = cmd_buff[5];
248 u64 file_size = ((u64)cmd_buff[8] << 32) | cmd_buff[7]; 256 u64 file_size = ((u64)cmd_buff[8] << 32) | cmd_buff[7];
249 u32 filename_ptr = cmd_buff[10]; 257 u32 filename_ptr = cmd_buff[10];
250 258
251 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 259 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
252 260
253 LOG_DEBUG(Service_FS, "type=%d size=%llu data=%s", filename_type, file_size, file_path.DebugStr().c_str()); 261 LOG_DEBUG(Service_FS, "type=%d size=%llu data=%s", filename_type, file_size,
262 file_path.DebugStr().c_str());
254 263
255 cmd_buff[1] = CreateFileInArchive(archive_handle, file_path, file_size).raw; 264 cmd_buff[1] = CreateFileInArchive(archive_handle, file_path, file_size).raw;
256} 265}
@@ -276,7 +285,8 @@ static void CreateDirectory(Service::Interface* self) {
276 285
277 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); 286 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
278 287
279 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); 288 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size,
289 dir_path.DebugStr().c_str());
280 290
281 cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw; 291 cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw;
282} 292}
@@ -301,22 +311,25 @@ static void RenameDirectory(Service::Interface* self) {
301 u32* cmd_buff = Kernel::GetCommandBuffer(); 311 u32* cmd_buff = Kernel::GetCommandBuffer();
302 312
303 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 313 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
304 auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 314 auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
305 u32 src_dirname_size = cmd_buff[5]; 315 u32 src_dirname_size = cmd_buff[5];
306 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]); 316 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);
307 auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); 317 auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
308 u32 dest_dirname_size = cmd_buff[9]; 318 u32 dest_dirname_size = cmd_buff[9];
309 u32 src_dirname_ptr = cmd_buff[11]; 319 u32 src_dirname_ptr = cmd_buff[11];
310 u32 dest_dirname_ptr = cmd_buff[13]; 320 u32 dest_dirname_ptr = cmd_buff[13];
311 321
312 FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr); 322 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); 323 FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr);
314 324
315 LOG_DEBUG(Service_FS, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s", 325 LOG_DEBUG(Service_FS,
326 "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(), 327 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()); 328 dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str());
318 329
319 cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw; 330 cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path,
331 dest_archive_handle, dest_dir_path)
332 .raw;
320} 333}
321 334
322/** 335/**
@@ -342,7 +355,8 @@ static void OpenDirectory(Service::Interface* self) {
342 355
343 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); 356 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
344 357
345 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); 358 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size,
359 dir_path.DebugStr().c_str());
346 360
347 ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); 361 ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path);
348 cmd_buff[1] = dir_res.Code().raw; 362 cmd_buff[1] = dir_res.Code().raw;
@@ -370,13 +384,14 @@ static void OpenDirectory(Service::Interface* self) {
370static void OpenArchive(Service::Interface* self) { 384static void OpenArchive(Service::Interface* self) {
371 u32* cmd_buff = Kernel::GetCommandBuffer(); 385 u32* cmd_buff = Kernel::GetCommandBuffer();
372 386
373 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]); 387 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]);
374 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); 388 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]);
375 u32 archivename_size = cmd_buff[3]; 389 u32 archivename_size = cmd_buff[3];
376 u32 archivename_ptr = cmd_buff[5]; 390 u32 archivename_ptr = cmd_buff[5];
377 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); 391 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
378 392
379 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s", archive_id, archive_path.DebugStr().c_str()); 393 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s", archive_id,
394 archive_path.DebugStr().c_str());
380 395
381 ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path); 396 ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path);
382 cmd_buff[1] = handle.Code().raw; 397 cmd_buff[1] = handle.Code().raw;
@@ -385,7 +400,8 @@ static void OpenArchive(Service::Interface* self) {
385 cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF; 400 cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF;
386 } else { 401 } else {
387 cmd_buff[2] = cmd_buff[3] = 0; 402 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", 403 LOG_ERROR(Service_FS,
404 "failed to get a handle for archive archive_id=0x%08X archive_path=%s",
389 archive_id, archive_path.DebugStr().c_str()); 405 archive_id, archive_path.DebugStr().c_str());
390 } 406 }
391} 407}
@@ -471,7 +487,8 @@ static void FormatSaveData(Service::Interface* self) {
471 if (archive_id != FS::ArchiveIdCode::SaveData) { 487 if (archive_id != FS::ArchiveIdCode::SaveData) {
472 LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", archive_id); 488 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, 489 cmd_buff[1] = ResultCode(ErrorDescription::FS_InvalidPath, ErrorModule::FS,
474 ErrorSummary::InvalidArgument, ErrorLevel::Usage).raw; 490 ErrorSummary::InvalidArgument, ErrorLevel::Usage)
491 .raw;
475 return; 492 return;
476 } 493 }
477 494
@@ -571,18 +588,21 @@ static void CreateExtSaveData(Service::Interface* self) {
571 u32 icon_size = cmd_buff[9]; 588 u32 icon_size = cmd_buff[9];
572 VAddr icon_buffer = cmd_buff[11]; 589 VAddr icon_buffer = cmd_buff[11];
573 590
574 LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " 591 LOG_WARNING(
575 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " 592 Service_FS,
576 "icon_size=%08X icon_descriptor=%08X icon_buffer=%08X", save_high, save_low, 593 "(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, 594 "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); 595 "icon_size=%08X icon_descriptor=%08X icon_buffer=%08X",
596 save_high, save_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7],
597 cmd_buff[8], icon_size, cmd_buff[10], icon_buffer);
579 598
580 FileSys::ArchiveFormatInfo format_info; 599 FileSys::ArchiveFormatInfo format_info;
581 format_info.number_directories = cmd_buff[5]; 600 format_info.number_directories = cmd_buff[5];
582 format_info.number_files = cmd_buff[6]; 601 format_info.number_files = cmd_buff[6];
583 format_info.duplicate_data = false; 602 format_info.duplicate_data = false;
584 format_info.total_size = 0; 603 format_info.total_size = 0;
585 cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size, format_info).raw; 604 cmd_buff[1] =
605 CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size, format_info).raw;
586} 606}
587 607
588/** 608/**
@@ -604,7 +624,7 @@ static void DeleteExtSaveData(Service::Interface* self) {
604 u32 unknown = cmd_buff[4]; // TODO(Subv): Figure out what this is 624 u32 unknown = cmd_buff[4]; // TODO(Subv): Figure out what this is
605 625
606 LOG_WARNING(Service_FS, "(STUBBED) save_low=%08X save_high=%08X media_type=%08X unknown=%08X", 626 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); 627 save_low, save_high, cmd_buff[1] & 0xFF, unknown);
608 628
609 cmd_buff[1] = DeleteExtSaveData(media_type, save_high, save_low).raw; 629 cmd_buff[1] = DeleteExtSaveData(media_type, save_high, save_low).raw;
610} 630}
@@ -662,10 +682,13 @@ static void CreateSystemSaveData(Service::Interface* self) {
662 u32 savedata_high = cmd_buff[1]; 682 u32 savedata_high = cmd_buff[1];
663 u32 savedata_low = cmd_buff[2]; 683 u32 savedata_low = cmd_buff[2];
664 684
665 LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " 685 LOG_WARNING(
666 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " 686 Service_FS,
667 "cmd_buff[9]=%08X", savedata_high, savedata_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], 687 "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X "
668 cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9]); 688 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X "
689 "cmd_buff[9]=%08X",
690 savedata_high, savedata_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6],
691 cmd_buff[7], cmd_buff[8], cmd_buff[9]);
669 692
670 cmd_buff[1] = CreateSystemSaveData(savedata_high, savedata_low).raw; 693 cmd_buff[1] = CreateSystemSaveData(savedata_high, savedata_low).raw;
671} 694}
@@ -692,10 +715,13 @@ static void CreateLegacySystemSaveData(Service::Interface* self) {
692 u32* cmd_buff = Kernel::GetCommandBuffer(); 715 u32* cmd_buff = Kernel::GetCommandBuffer();
693 u32 savedata_id = cmd_buff[1]; 716 u32 savedata_id = cmd_buff[1];
694 717
695 LOG_WARNING(Service_FS, "(STUBBED) savedata_id=%08X cmd_buff[3]=%08X " 718 LOG_WARNING(
696 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " 719 Service_FS,
697 "cmd_buff[9]=%08X", savedata_id, cmd_buff[3], cmd_buff[4], cmd_buff[5], 720 "(STUBBED) savedata_id=%08X cmd_buff[3]=%08X "
698 cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9]); 721 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X "
722 "cmd_buff[9]=%08X",
723 savedata_id, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8],
724 cmd_buff[9]);
699 725
700 cmd_buff[0] = IPC::MakeHeader(0x810, 0x1, 0); 726 cmd_buff[0] = IPC::MakeHeader(0x810, 0x1, 0);
701 // With this command, the SystemSaveData always has save_high = 0 (Always created in the NAND) 727 // With this command, the SystemSaveData always has save_high = 0 (Always created in the NAND)
@@ -721,8 +747,8 @@ static void InitializeWithSdkVersion(Service::Interface* self) {
721 747
722 cmd_buff[1] = RESULT_SUCCESS.raw; 748 cmd_buff[1] = RESULT_SUCCESS.raw;
723 749
724 LOG_WARNING(Service_FS, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, unk3=0x%08X", 750 LOG_WARNING(Service_FS, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, unk3=0x%08X", unk1, unk2,
725 unk1, unk2, unk3); 751 unk3);
726} 752}
727 753
728/** 754/**
@@ -834,114 +860,114 @@ static void GetFormatInfo(Service::Interface* self) {
834} 860}
835 861
836const Interface::FunctionInfo FunctionTable[] = { 862const Interface::FunctionInfo FunctionTable[] = {
837 {0x000100C6, nullptr, "Dummy1"}, 863 {0x000100C6, nullptr, "Dummy1"},
838 {0x040100C4, nullptr, "Control"}, 864 {0x040100C4, nullptr, "Control"},
839 {0x08010002, Initialize, "Initialize"}, 865 {0x08010002, Initialize, "Initialize"},
840 {0x080201C2, OpenFile, "OpenFile"}, 866 {0x080201C2, OpenFile, "OpenFile"},
841 {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, 867 {0x08030204, OpenFileDirectly, "OpenFileDirectly"},
842 {0x08040142, DeleteFile, "DeleteFile"}, 868 {0x08040142, DeleteFile, "DeleteFile"},
843 {0x08050244, RenameFile, "RenameFile"}, 869 {0x08050244, RenameFile, "RenameFile"},
844 {0x08060142, DeleteDirectory, "DeleteDirectory"}, 870 {0x08060142, DeleteDirectory, "DeleteDirectory"},
845 {0x08070142, nullptr, "DeleteDirectoryRecursively"}, 871 {0x08070142, nullptr, "DeleteDirectoryRecursively"},
846 {0x08080202, CreateFile, "CreateFile"}, 872 {0x08080202, CreateFile, "CreateFile"},
847 {0x08090182, CreateDirectory, "CreateDirectory"}, 873 {0x08090182, CreateDirectory, "CreateDirectory"},
848 {0x080A0244, RenameDirectory, "RenameDirectory"}, 874 {0x080A0244, RenameDirectory, "RenameDirectory"},
849 {0x080B0102, OpenDirectory, "OpenDirectory"}, 875 {0x080B0102, OpenDirectory, "OpenDirectory"},
850 {0x080C00C2, OpenArchive, "OpenArchive"}, 876 {0x080C00C2, OpenArchive, "OpenArchive"},
851 {0x080D0144, nullptr, "ControlArchive"}, 877 {0x080D0144, nullptr, "ControlArchive"},
852 {0x080E0080, CloseArchive, "CloseArchive"}, 878 {0x080E0080, CloseArchive, "CloseArchive"},
853 {0x080F0180, FormatThisUserSaveData, "FormatThisUserSaveData"}, 879 {0x080F0180, FormatThisUserSaveData, "FormatThisUserSaveData"},
854 {0x08100200, CreateLegacySystemSaveData, "CreateLegacySystemSaveData"}, 880 {0x08100200, CreateLegacySystemSaveData, "CreateLegacySystemSaveData"},
855 {0x08110040, nullptr, "DeleteSystemSaveData"}, 881 {0x08110040, nullptr, "DeleteSystemSaveData"},
856 {0x08120080, GetFreeBytes, "GetFreeBytes"}, 882 {0x08120080, GetFreeBytes, "GetFreeBytes"},
857 {0x08130000, nullptr, "GetCardType"}, 883 {0x08130000, nullptr, "GetCardType"},
858 {0x08140000, nullptr, "GetSdmcArchiveResource"}, 884 {0x08140000, nullptr, "GetSdmcArchiveResource"},
859 {0x08150000, nullptr, "GetNandArchiveResource"}, 885 {0x08150000, nullptr, "GetNandArchiveResource"},
860 {0x08160000, nullptr, "GetSdmcFatfsError"}, 886 {0x08160000, nullptr, "GetSdmcFatfsError"},
861 {0x08170000, IsSdmcDetected, "IsSdmcDetected"}, 887 {0x08170000, IsSdmcDetected, "IsSdmcDetected"},
862 {0x08180000, IsSdmcWriteable, "IsSdmcWritable"}, 888 {0x08180000, IsSdmcWriteable, "IsSdmcWritable"},
863 {0x08190042, nullptr, "GetSdmcCid"}, 889 {0x08190042, nullptr, "GetSdmcCid"},
864 {0x081A0042, nullptr, "GetNandCid"}, 890 {0x081A0042, nullptr, "GetNandCid"},
865 {0x081B0000, nullptr, "GetSdmcSpeedInfo"}, 891 {0x081B0000, nullptr, "GetSdmcSpeedInfo"},
866 {0x081C0000, nullptr, "GetNandSpeedInfo"}, 892 {0x081C0000, nullptr, "GetNandSpeedInfo"},
867 {0x081D0042, nullptr, "GetSdmcLog"}, 893 {0x081D0042, nullptr, "GetSdmcLog"},
868 {0x081E0042, nullptr, "GetNandLog"}, 894 {0x081E0042, nullptr, "GetNandLog"},
869 {0x081F0000, nullptr, "ClearSdmcLog"}, 895 {0x081F0000, nullptr, "ClearSdmcLog"},
870 {0x08200000, nullptr, "ClearNandLog"}, 896 {0x08200000, nullptr, "ClearNandLog"},
871 {0x08210000, CardSlotIsInserted, "CardSlotIsInserted"}, 897 {0x08210000, CardSlotIsInserted, "CardSlotIsInserted"},
872 {0x08220000, nullptr, "CardSlotPowerOn"}, 898 {0x08220000, nullptr, "CardSlotPowerOn"},
873 {0x08230000, nullptr, "CardSlotPowerOff"}, 899 {0x08230000, nullptr, "CardSlotPowerOff"},
874 {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"}, 900 {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"},
875 {0x08250040, nullptr, "CardNorDirectCommand"}, 901 {0x08250040, nullptr, "CardNorDirectCommand"},
876 {0x08260080, nullptr, "CardNorDirectCommandWithAddress"}, 902 {0x08260080, nullptr, "CardNorDirectCommandWithAddress"},
877 {0x08270082, nullptr, "CardNorDirectRead"}, 903 {0x08270082, nullptr, "CardNorDirectRead"},
878 {0x082800C2, nullptr, "CardNorDirectReadWithAddress"}, 904 {0x082800C2, nullptr, "CardNorDirectReadWithAddress"},
879 {0x08290082, nullptr, "CardNorDirectWrite"}, 905 {0x08290082, nullptr, "CardNorDirectWrite"},
880 {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"}, 906 {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"},
881 {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"}, 907 {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"},
882 {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"}, 908 {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"},
883 {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"}, 909 {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"},
884 {0x082E0040, nullptr, "GetProductInfo"}, 910 {0x082E0040, nullptr, "GetProductInfo"},
885 {0x082F0040, nullptr, "GetProgramLaunchInfo"}, 911 {0x082F0040, nullptr, "GetProgramLaunchInfo"},
886 {0x08300182, nullptr, "CreateExtSaveData"}, 912 {0x08300182, nullptr, "CreateExtSaveData"},
887 {0x08310180, nullptr, "CreateSharedExtSaveData"}, 913 {0x08310180, nullptr, "CreateSharedExtSaveData"},
888 {0x08320102, nullptr, "ReadExtSaveDataIcon"}, 914 {0x08320102, nullptr, "ReadExtSaveDataIcon"},
889 {0x08330082, nullptr, "EnumerateExtSaveData"}, 915 {0x08330082, nullptr, "EnumerateExtSaveData"},
890 {0x08340082, nullptr, "EnumerateSharedExtSaveData"}, 916 {0x08340082, nullptr, "EnumerateSharedExtSaveData"},
891 {0x08350080, nullptr, "DeleteExtSaveData"}, 917 {0x08350080, nullptr, "DeleteExtSaveData"},
892 {0x08360080, nullptr, "DeleteSharedExtSaveData"}, 918 {0x08360080, nullptr, "DeleteSharedExtSaveData"},
893 {0x08370040, nullptr, "SetCardSpiBaudRate"}, 919 {0x08370040, nullptr, "SetCardSpiBaudRate"},
894 {0x08380040, nullptr, "SetCardSpiBusMode"}, 920 {0x08380040, nullptr, "SetCardSpiBusMode"},
895 {0x08390000, nullptr, "SendInitializeInfoTo9"}, 921 {0x08390000, nullptr, "SendInitializeInfoTo9"},
896 {0x083A0100, nullptr, "GetSpecialContentIndex"}, 922 {0x083A0100, nullptr, "GetSpecialContentIndex"},
897 {0x083B00C2, nullptr, "GetLegacyRomHeader"}, 923 {0x083B00C2, nullptr, "GetLegacyRomHeader"},
898 {0x083C00C2, nullptr, "GetLegacyBannerData"}, 924 {0x083C00C2, nullptr, "GetLegacyBannerData"},
899 {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"}, 925 {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"},
900 {0x083E00C2, nullptr, "QueryTotalQuotaSize"}, 926 {0x083E00C2, nullptr, "QueryTotalQuotaSize"},
901 {0x083F00C0, nullptr, "GetExtDataBlockSize"}, 927 {0x083F00C0, nullptr, "GetExtDataBlockSize"},
902 {0x08400040, nullptr, "AbnegateAccessRight"}, 928 {0x08400040, nullptr, "AbnegateAccessRight"},
903 {0x08410000, nullptr, "DeleteSdmcRoot"}, 929 {0x08410000, nullptr, "DeleteSdmcRoot"},
904 {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"}, 930 {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"},
905 {0x08430000, nullptr, "InitializeCtrFileSystem"}, 931 {0x08430000, nullptr, "InitializeCtrFileSystem"},
906 {0x08440000, nullptr, "CreateSeed"}, 932 {0x08440000, nullptr, "CreateSeed"},
907 {0x084500C2, GetFormatInfo, "GetFormatInfo"}, 933 {0x084500C2, GetFormatInfo, "GetFormatInfo"},
908 {0x08460102, nullptr, "GetLegacyRomHeader2"}, 934 {0x08460102, nullptr, "GetLegacyRomHeader2"},
909 {0x08470180, nullptr, "FormatCtrCardUserSaveData"}, 935 {0x08470180, nullptr, "FormatCtrCardUserSaveData"},
910 {0x08480042, nullptr, "GetSdmcCtrRootPath"}, 936 {0x08480042, nullptr, "GetSdmcCtrRootPath"},
911 {0x08490040, GetArchiveResource, "GetArchiveResource"}, 937 {0x08490040, GetArchiveResource, "GetArchiveResource"},
912 {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"}, 938 {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"},
913 {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"}, 939 {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"},
914 {0x084C0242, FormatSaveData, "FormatSaveData"}, 940 {0x084C0242, FormatSaveData, "FormatSaveData"},
915 {0x084D0102, nullptr, "GetLegacySubBannerData"}, 941 {0x084D0102, nullptr, "GetLegacySubBannerData"},
916 {0x084E0342, nullptr, "UpdateSha256Context"}, 942 {0x084E0342, nullptr, "UpdateSha256Context"},
917 {0x084F0102, nullptr, "ReadSpecialFile"}, 943 {0x084F0102, nullptr, "ReadSpecialFile"},
918 {0x08500040, nullptr, "GetSpecialFileSize"}, 944 {0x08500040, nullptr, "GetSpecialFileSize"},
919 {0x08510242, CreateExtSaveData, "CreateExtSaveData"}, 945 {0x08510242, CreateExtSaveData, "CreateExtSaveData"},
920 {0x08520100, DeleteExtSaveData, "DeleteExtSaveData"}, 946 {0x08520100, DeleteExtSaveData, "DeleteExtSaveData"},
921 {0x08530142, nullptr, "ReadExtSaveDataIcon"}, 947 {0x08530142, nullptr, "ReadExtSaveDataIcon"},
922 {0x085400C0, nullptr, "GetExtDataBlockSize"}, 948 {0x085400C0, nullptr, "GetExtDataBlockSize"},
923 {0x08550102, nullptr, "EnumerateExtSaveData"}, 949 {0x08550102, nullptr, "EnumerateExtSaveData"},
924 {0x08560240, CreateSystemSaveData, "CreateSystemSaveData"}, 950 {0x08560240, CreateSystemSaveData, "CreateSystemSaveData"},
925 {0x08570080, DeleteSystemSaveData, "DeleteSystemSaveData"}, 951 {0x08570080, DeleteSystemSaveData, "DeleteSystemSaveData"},
926 {0x08580000, nullptr, "StartDeviceMoveAsSource"}, 952 {0x08580000, nullptr, "StartDeviceMoveAsSource"},
927 {0x08590200, nullptr, "StartDeviceMoveAsDestination"}, 953 {0x08590200, nullptr, "StartDeviceMoveAsDestination"},
928 {0x085A00C0, nullptr, "SetArchivePriority"}, 954 {0x085A00C0, nullptr, "SetArchivePriority"},
929 {0x085B0080, nullptr, "GetArchivePriority"}, 955 {0x085B0080, nullptr, "GetArchivePriority"},
930 {0x085C00C0, nullptr, "SetCtrCardLatencyParameter"}, 956 {0x085C00C0, nullptr, "SetCtrCardLatencyParameter"},
931 {0x085D01C0, nullptr, "SetFsCompatibilityInfo"}, 957 {0x085D01C0, nullptr, "SetFsCompatibilityInfo"},
932 {0x085E0040, nullptr, "ResetCardCompatibilityParameter"}, 958 {0x085E0040, nullptr, "ResetCardCompatibilityParameter"},
933 {0x085F0040, nullptr, "SwitchCleanupInvalidSaveData"}, 959 {0x085F0040, nullptr, "SwitchCleanupInvalidSaveData"},
934 {0x08600042, nullptr, "EnumerateSystemSaveData"}, 960 {0x08600042, nullptr, "EnumerateSystemSaveData"},
935 {0x08610042, InitializeWithSdkVersion, "InitializeWithSdkVersion"}, 961 {0x08610042, InitializeWithSdkVersion, "InitializeWithSdkVersion"},
936 {0x08620040, SetPriority, "SetPriority"}, 962 {0x08620040, SetPriority, "SetPriority"},
937 {0x08630000, GetPriority, "GetPriority"}, 963 {0x08630000, GetPriority, "GetPriority"},
938 {0x08640000, nullptr, "GetNandInfo"}, 964 {0x08640000, nullptr, "GetNandInfo"},
939 {0x08650140, nullptr, "SetSaveDataSecureValue"}, 965 {0x08650140, nullptr, "SetSaveDataSecureValue"},
940 {0x086600C0, nullptr, "GetSaveDataSecureValue"}, 966 {0x086600C0, nullptr, "GetSaveDataSecureValue"},
941 {0x086700C4, nullptr, "ControlSecureSave"}, 967 {0x086700C4, nullptr, "ControlSecureSave"},
942 {0x08680000, nullptr, "GetMediaType"}, 968 {0x08680000, nullptr, "GetMediaType"},
943 {0x08690000, nullptr, "GetNandEraseCount"}, 969 {0x08690000, nullptr, "GetNandEraseCount"},
944 {0x086A0082, nullptr, "ReadNandReport"} 970 {0x086A0082, nullptr, "ReadNandReport"},
945}; 971};
946 972
947//////////////////////////////////////////////////////////////////////////////////////////////////// 973////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index ec565f46d..710e0e485 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -4,19 +4,16 @@
4 4
5#include "common/bit_field.h" 5#include "common/bit_field.h"
6#include "common/microprofile.h" 6#include "common/microprofile.h"
7
8#include "core/memory.h"
9#include "core/hle/kernel/event.h" 7#include "core/hle/kernel/event.h"
10#include "core/hle/kernel/shared_memory.h" 8#include "core/hle/kernel/shared_memory.h"
11#include "core/hle/result.h" 9#include "core/hle/result.h"
12#include "core/hw/hw.h"
13#include "core/hw/gpu.h" 10#include "core/hw/gpu.h"
11#include "core/hw/hw.h"
14#include "core/hw/lcd.h" 12#include "core/hw/lcd.h"
15 13#include "core/memory.h"
16#include "video_core/gpu_debugger.h"
17#include "video_core/debug_utils/debug_utils.h"
18
19#include "gsp_gpu.h" 14#include "gsp_gpu.h"
15#include "video_core/debug_utils/debug_utils.h"
16#include "video_core/gpu_debugger.h"
20 17
21// Main graphics debugger object - TODO: Here is probably not the best place for this 18// Main graphics debugger object - TODO: Here is probably not the best place for this
22GraphicsDebugger g_debugger; 19GraphicsDebugger g_debugger;
@@ -29,12 +26,15 @@ const static u32 REGS_BEGIN = 0x1EB00000;
29 26
30namespace GSP_GPU { 27namespace GSP_GPU {
31 28
32const ResultCode ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED(ErrorDescription::OutofRangeOrMisalignedAddress, ErrorModule::GX, 29const ResultCode ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED(
33 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02A01 30 ErrorDescription::OutofRangeOrMisalignedAddress, ErrorModule::GX, ErrorSummary::InvalidArgument,
31 ErrorLevel::Usage); // 0xE0E02A01
34const ResultCode ERR_GSP_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX, 32const ResultCode ERR_GSP_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX,
35 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BF2 33 ErrorSummary::InvalidArgument,
34 ErrorLevel::Usage); // 0xE0E02BF2
36const ResultCode ERR_GSP_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX, 35const ResultCode ERR_GSP_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX,
37 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BEC 36 ErrorSummary::InvalidArgument,
37 ErrorLevel::Usage); // 0xE0E02BEC
38 38
39/// Event triggered when GSP interrupt has been signalled 39/// Event triggered when GSP interrupt has been signalled
40Kernel::SharedPtr<Kernel::Event> g_interrupt_event; 40Kernel::SharedPtr<Kernel::Event> g_interrupt_event;
@@ -73,7 +73,8 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) {
73 * @param data Data to be written 73 * @param data Data to be written
74 */ 74 */
75static void WriteSingleHWReg(u32 base_address, u32 data) { 75static 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"); 76 DEBUG_ASSERT_MSG((base_address & 3) == 0 && base_address < 0x420000,
77 "Write address out of range or misaligned");
77 HW::Write<u32>(base_address + REGS_BEGIN, data); 78 HW::Write<u32>(base_address + REGS_BEGIN, data);
78} 79}
79 80
@@ -90,7 +91,8 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_va
90 const u32 max_size_in_bytes = 0x80; 91 const u32 max_size_in_bytes = 0x80;
91 92
92 if (base_address & 3 || base_address >= 0x420000) { 93 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)", 94 LOG_ERROR(Service_GSP,
95 "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)",
94 base_address, size_in_bytes); 96 base_address, size_in_bytes);
95 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; 97 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED;
96 } else if (size_in_bytes <= max_size_in_bytes) { 98 } else if (size_in_bytes <= max_size_in_bytes) {
@@ -124,12 +126,14 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_va
124 * @param masks A pointer to the masks 126 * @param masks A pointer to the masks
125 * @return RESULT_SUCCESS if the parameters are valid, error code otherwise 127 * @return RESULT_SUCCESS if the parameters are valid, error code otherwise
126 */ 128 */
127static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr, VAddr masks_vaddr) { 129static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr,
130 VAddr masks_vaddr) {
128 // This magic number is verified to be done by the gsp module 131 // This magic number is verified to be done by the gsp module
129 const u32 max_size_in_bytes = 0x80; 132 const u32 max_size_in_bytes = 0x80;
130 133
131 if (base_address & 3 || base_address >= 0x420000) { 134 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)", 135 LOG_ERROR(Service_GSP,
136 "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)",
133 base_address, size_in_bytes); 137 base_address, size_in_bytes);
134 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; 138 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED;
135 } else if (size_in_bytes <= max_size_in_bytes) { 139 } else if (size_in_bytes <= max_size_in_bytes) {
@@ -214,7 +218,8 @@ static void ReadHWRegs(Service::Interface* self) {
214 218
215 // TODO: Return proper error codes 219 // TODO: Return proper error codes
216 if (reg_addr + size >= 0x420000) { 220 if (reg_addr + size >= 0x420000) {
217 LOG_ERROR(Service_GSP, "Read address out of range! (address=0x%08x, size=0x%08x)", reg_addr, size); 221 LOG_ERROR(Service_GSP, "Read address out of range! (address=0x%08x, size=0x%08x)", reg_addr,
222 size);
218 return; 223 return;
219 } 224 }
220 225
@@ -243,22 +248,34 @@ ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
243 PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); 248 PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left);
244 PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); 249 PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right);
245 if (info.active_fb == 0) { 250 if (info.active_fb == 0) {
246 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), 251 WriteSingleHWReg(
247 phys_address_left); 252 base_address +
248 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), 253 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)),
249 phys_address_right); 254 phys_address_left);
255 WriteSingleHWReg(
256 base_address +
257 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)),
258 phys_address_right);
250 } else { 259 } else {
251 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), 260 WriteSingleHWReg(
252 phys_address_left); 261 base_address +
253 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), 262 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)),
254 phys_address_right); 263 phys_address_left);
264 WriteSingleHWReg(
265 base_address +
266 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)),
267 phys_address_right);
255 } 268 }
256 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), 269 WriteSingleHWReg(base_address +
270 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)),
257 info.stride); 271 info.stride);
258 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), 272 WriteSingleHWReg(
259 info.format); 273 base_address +
260 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 274 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)),
261 info.shown_fb); 275 info.format);
276 WriteSingleHWReg(
277 base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)),
278 info.shown_fb);
262 279
263 if (Pica::g_debug_context) 280 if (Pica::g_debug_context)
264 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); 281 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr);
@@ -305,15 +322,15 @@ static void SetBufferSwap(Service::Interface* self) {
305static void FlushDataCache(Service::Interface* self) { 322static void FlushDataCache(Service::Interface* self) {
306 u32* cmd_buff = Kernel::GetCommandBuffer(); 323 u32* cmd_buff = Kernel::GetCommandBuffer();
307 u32 address = cmd_buff[1]; 324 u32 address = cmd_buff[1];
308 u32 size = cmd_buff[2]; 325 u32 size = cmd_buff[2];
309 u32 process = cmd_buff[4]; 326 u32 process = cmd_buff[4];
310 327
311 // TODO(purpasmart96): Verify return header on HW 328 // TODO(purpasmart96): Verify return header on HW
312 329
313 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 330 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
314 331
315 LOG_DEBUG(Service_GSP, "(STUBBED) called address=0x%08X, size=0x%08X, process=0x%08X", 332 LOG_DEBUG(Service_GSP, "(STUBBED) called address=0x%08X, size=0x%08X, process=0x%08X", address,
316 address, size, process); 333 size, process);
317} 334}
318 335
319/** 336/**
@@ -356,11 +373,12 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) {
356 // This specific code is required for a successful initialization, rather than 0 373 // This specific code is required for a successful initialization, rather than 0
357 first_initialization = false; 374 first_initialization = false;
358 cmd_buff[1] = ResultCode(ErrorDescription::GPU_FirstInitialization, ErrorModule::GX, 375 cmd_buff[1] = ResultCode(ErrorDescription::GPU_FirstInitialization, ErrorModule::GX,
359 ErrorSummary::Success, ErrorLevel::Success).raw; 376 ErrorSummary::Success, ErrorLevel::Success)
377 .raw;
360 } else { 378 } else {
361 cmd_buff[1] = RESULT_SUCCESS.raw; 379 cmd_buff[1] = RESULT_SUCCESS.raw;
362 } 380 }
363 cmd_buff[2] = g_thread_id++; // Thread ID 381 cmd_buff[2] = g_thread_id++; // Thread ID
364 cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // GSP shared memory 382 cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // GSP shared memory
365 383
366 g_interrupt_event->Signal(); // TODO(bunnei): Is this correct? 384 g_interrupt_event->Signal(); // TODO(bunnei): Is this correct?
@@ -416,7 +434,8 @@ void SignalInterrupt(InterruptId interrupt_id) {
416 // Update framebuffer information if requested 434 // Update framebuffer information if requested
417 // TODO(yuriks): Confirm where this code should be called. It is definitely updated without 435 // TODO(yuriks): Confirm where this code should be called. It is definitely updated without
418 // executing any GSP commands, only waiting on the event. 436 // executing any GSP commands, only waiting on the event.
419 int screen_id = (interrupt_id == InterruptId::PDC0) ? 0 : (interrupt_id == InterruptId::PDC1) ? 1 : -1; 437 int screen_id =
438 (interrupt_id == InterruptId::PDC0) ? 0 : (interrupt_id == InterruptId::PDC1) ? 1 : -1;
420 if (screen_id != -1) { 439 if (screen_id != -1) {
421 FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id); 440 FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id);
422 if (info->is_dirty) { 441 if (info->is_dirty) {
@@ -440,25 +459,27 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
440 switch (command.id) { 459 switch (command.id) {
441 460
442 // GX request DMA - typically used for copying memory from GSP heap to VRAM 461 // GX request DMA - typically used for copying memory from GSP heap to VRAM
443 case CommandId::REQUEST_DMA: 462 case CommandId::REQUEST_DMA: {
444 {
445 MICROPROFILE_SCOPE(GPU_GSP_DMA); 463 MICROPROFILE_SCOPE(GPU_GSP_DMA);
446 464
447 // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever possible/likely 465 // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever
448 Memory::RasterizerFlushRegion(Memory::VirtualToPhysicalAddress(command.dma_request.source_address), 466 // possible/likely
449 command.dma_request.size); 467 Memory::RasterizerFlushRegion(
450 Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), 468 Memory::VirtualToPhysicalAddress(command.dma_request.source_address),
451 command.dma_request.size); 469 command.dma_request.size);
470 Memory::RasterizerFlushAndInvalidateRegion(
471 Memory::VirtualToPhysicalAddress(command.dma_request.dest_address),
472 command.dma_request.size);
452 473
453 // TODO(Subv): These memory accesses should not go through the application's memory mapping. 474 // 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. 475 // 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); 476 Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address,
477 command.dma_request.size);
456 SignalInterrupt(InterruptId::DMA); 478 SignalInterrupt(InterruptId::DMA);
457 break; 479 break;
458 } 480 }
459 // TODO: This will need some rework in the future. (why?) 481 // TODO: This will need some rework in the future. (why?)
460 case CommandId::SUBMIT_GPU_CMDLIST: 482 case CommandId::SUBMIT_GPU_CMDLIST: {
461 {
462 auto& params = command.submit_gpu_cmdlist; 483 auto& params = command.submit_gpu_cmdlist;
463 484
464 if (params.do_flush) { 485 if (params.do_flush) {
@@ -468,10 +489,12 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
468 } 489 }
469 490
470 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)), 491 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)),
471 Memory::VirtualToPhysicalAddress(params.address) >> 3); 492 Memory::VirtualToPhysicalAddress(params.address) >> 3);
472 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.size)), params.size); 493 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.size)),
494 params.size);
473 495
474 // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though 496 // TODO: Not sure if we are supposed to always write this .. seems to trigger processing
497 // though
475 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.trigger)), 1); 498 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.trigger)), 1);
476 499
477 // TODO(yuriks): Figure out the meaning of the `flags` field. 500 // TODO(yuriks): Figure out the meaning of the `flags` field.
@@ -481,67 +504,70 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
481 504
482 // It's assumed that the two "blocks" behave equivalently. 505 // It's assumed that the two "blocks" behave equivalently.
483 // Presumably this is done simply to allow two memory fills to run in parallel. 506 // Presumably this is done simply to allow two memory fills to run in parallel.
484 case CommandId::SET_MEMORY_FILL: 507 case CommandId::SET_MEMORY_FILL: {
485 {
486 auto& params = command.memory_fill; 508 auto& params = command.memory_fill;
487 509
488 if (params.start1 != 0) { 510 if (params.start1 != 0) {
489 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)), 511 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)),
490 Memory::VirtualToPhysicalAddress(params.start1) >> 3); 512 Memory::VirtualToPhysicalAddress(params.start1) >> 3);
491 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)), 513 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)),
492 Memory::VirtualToPhysicalAddress(params.end1) >> 3); 514 Memory::VirtualToPhysicalAddress(params.end1) >> 3);
493 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)), params.value1); 515 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); 516 params.value1);
517 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)),
518 params.control1);
495 } 519 }
496 520
497 if (params.start2 != 0) { 521 if (params.start2 != 0) {
498 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)), 522 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)),
499 Memory::VirtualToPhysicalAddress(params.start2) >> 3); 523 Memory::VirtualToPhysicalAddress(params.start2) >> 3);
500 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)), 524 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)),
501 Memory::VirtualToPhysicalAddress(params.end2) >> 3); 525 Memory::VirtualToPhysicalAddress(params.end2) >> 3);
502 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)), params.value2); 526 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); 527 params.value2);
528 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)),
529 params.control2);
504 } 530 }
505 break; 531 break;
506 } 532 }
507 533
508 case CommandId::SET_DISPLAY_TRANSFER: 534 case CommandId::SET_DISPLAY_TRANSFER: {
509 {
510 auto& params = command.display_transfer; 535 auto& params = command.display_transfer;
511 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)), 536 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)),
512 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); 537 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3);
513 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)), 538 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)),
514 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); 539 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3);
515 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_size)), params.in_buffer_size); 540 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); 541 params.in_buffer_size);
517 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.flags)), params.flags); 542 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_size)),
543 params.out_buffer_size);
544 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.flags)),
545 params.flags);
518 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.trigger)), 1); 546 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.trigger)), 1);
519 break; 547 break;
520 } 548 }
521 549
522 case CommandId::SET_TEXTURE_COPY: 550 case CommandId::SET_TEXTURE_COPY: {
523 {
524 auto& params = command.texture_copy; 551 auto& params = command.texture_copy;
525 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.input_address), 552 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.input_address),
526 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); 553 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3);
527 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.output_address), 554 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.output_address),
528 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); 555 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3);
529 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.size), 556 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.size),
530 params.size); 557 params.size);
531 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.input_size), 558 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.input_size),
532 params.in_width_gap); 559 params.in_width_gap);
533 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.output_size), 560 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.output_size),
534 params.out_width_gap); 561 params.out_width_gap);
535 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.flags), 562 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.flags), params.flags);
536 params.flags);
537 563
538 // NOTE: Actual GSP ORs 1 with current register instead of overwriting. Doesn't seem to matter. 564 // NOTE: Actual GSP ORs 1 with current register instead of overwriting. Doesn't seem to
565 // matter.
539 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.trigger), 1); 566 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.trigger), 1);
540 break; 567 break;
541 } 568 }
542 569
543 case CommandId::CACHE_FLUSH: 570 case CommandId::CACHE_FLUSH: {
544 {
545 // NOTE: Rasterizer flushing handled elsewhere in CPU read/write and other GPU handlers 571 // NOTE: Rasterizer flushing handled elsewhere in CPU read/write and other GPU handlers
546 // Use command.cache_flush.regions to implement this handler 572 // Use command.cache_flush.regions to implement this handler
547 break; 573 break;
@@ -552,7 +578,8 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
552 } 578 }
553 579
554 if (Pica::g_debug_context) 580 if (Pica::g_debug_context)
555 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::GSPCommandProcessed, (void*)&command); 581 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::GSPCommandProcessed,
582 (void*)&command);
556} 583}
557 584
558/** 585/**
@@ -575,7 +602,7 @@ static void SetLcdForceBlack(Service::Interface* self) {
575 // the color to black (all zero). 602 // the color to black (all zero).
576 data.is_enabled.Assign(enable_black); 603 data.is_enabled.Assign(enable_black);
577 604
578 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_top), data.raw); // Top LCD 605 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 606 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_bottom), data.raw); // Bottom LCD
580 607
581 cmd_buff[1] = RESULT_SUCCESS.raw; 608 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -679,37 +706,37 @@ static void ReleaseRight(Service::Interface* self) {
679} 706}
680 707
681const Interface::FunctionInfo FunctionTable[] = { 708const Interface::FunctionInfo FunctionTable[] = {
682 {0x00010082, WriteHWRegs, "WriteHWRegs"}, 709 {0x00010082, WriteHWRegs, "WriteHWRegs"},
683 {0x00020084, WriteHWRegsWithMask, "WriteHWRegsWithMask"}, 710 {0x00020084, WriteHWRegsWithMask, "WriteHWRegsWithMask"},
684 {0x00030082, nullptr, "WriteHWRegRepeat"}, 711 {0x00030082, nullptr, "WriteHWRegRepeat"},
685 {0x00040080, ReadHWRegs, "ReadHWRegs"}, 712 {0x00040080, ReadHWRegs, "ReadHWRegs"},
686 {0x00050200, SetBufferSwap, "SetBufferSwap"}, 713 {0x00050200, SetBufferSwap, "SetBufferSwap"},
687 {0x00060082, nullptr, "SetCommandList"}, 714 {0x00060082, nullptr, "SetCommandList"},
688 {0x000700C2, nullptr, "RequestDma"}, 715 {0x000700C2, nullptr, "RequestDma"},
689 {0x00080082, FlushDataCache, "FlushDataCache"}, 716 {0x00080082, FlushDataCache, "FlushDataCache"},
690 {0x00090082, nullptr, "InvalidateDataCache"}, 717 {0x00090082, nullptr, "InvalidateDataCache"},
691 {0x000A0044, nullptr, "RegisterInterruptEvents"}, 718 {0x000A0044, nullptr, "RegisterInterruptEvents"},
692 {0x000B0040, SetLcdForceBlack, "SetLcdForceBlack"}, 719 {0x000B0040, SetLcdForceBlack, "SetLcdForceBlack"},
693 {0x000C0000, TriggerCmdReqQueue, "TriggerCmdReqQueue"}, 720 {0x000C0000, TriggerCmdReqQueue, "TriggerCmdReqQueue"},
694 {0x000D0140, nullptr, "SetDisplayTransfer"}, 721 {0x000D0140, nullptr, "SetDisplayTransfer"},
695 {0x000E0180, nullptr, "SetTextureCopy"}, 722 {0x000E0180, nullptr, "SetTextureCopy"},
696 {0x000F0200, nullptr, "SetMemoryFill"}, 723 {0x000F0200, nullptr, "SetMemoryFill"},
697 {0x00100040, SetAxiConfigQoSMode, "SetAxiConfigQoSMode"}, 724 {0x00100040, SetAxiConfigQoSMode, "SetAxiConfigQoSMode"},
698 {0x00110040, nullptr, "SetPerfLogMode"}, 725 {0x00110040, nullptr, "SetPerfLogMode"},
699 {0x00120000, nullptr, "GetPerfLog"}, 726 {0x00120000, nullptr, "GetPerfLog"},
700 {0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"}, 727 {0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"},
701 {0x00140000, UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"}, 728 {0x00140000, UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"},
702 {0x00150002, nullptr, "TryAcquireRight"}, 729 {0x00150002, nullptr, "TryAcquireRight"},
703 {0x00160042, AcquireRight, "AcquireRight"}, 730 {0x00160042, AcquireRight, "AcquireRight"},
704 {0x00170000, ReleaseRight, "ReleaseRight"}, 731 {0x00170000, ReleaseRight, "ReleaseRight"},
705 {0x00180000, ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"}, 732 {0x00180000, ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"},
706 {0x00190000, nullptr, "SaveVramSysArea"}, 733 {0x00190000, nullptr, "SaveVramSysArea"},
707 {0x001A0000, nullptr, "RestoreVramSysArea"}, 734 {0x001A0000, nullptr, "RestoreVramSysArea"},
708 {0x001B0000, nullptr, "ResetGpuCore"}, 735 {0x001B0000, nullptr, "ResetGpuCore"},
709 {0x001C0040, nullptr, "SetLedForceOff"}, 736 {0x001C0040, nullptr, "SetLedForceOff"},
710 {0x001D0040, nullptr, "SetTestCommand"}, 737 {0x001D0040, nullptr, "SetTestCommand"},
711 {0x001E0080, nullptr, "SetInternalPriorities"}, 738 {0x001E0080, nullptr, "SetInternalPriorities"},
712 {0x001F0082, nullptr, "StoreDataCache"}, 739 {0x001F0082, nullptr, "StoreDataCache"},
713}; 740};
714 741
715//////////////////////////////////////////////////////////////////////////////////////////////////// 742////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -721,9 +748,9 @@ Interface::Interface() {
721 g_interrupt_event = nullptr; 748 g_interrupt_event = nullptr;
722 749
723 using Kernel::MemoryPermission; 750 using Kernel::MemoryPermission;
724 g_shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000, 751 g_shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite,
725 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 752 MemoryPermission::ReadWrite, 0,
726 0, Kernel::MemoryRegion::BASE, "GSP:SharedMemory"); 753 Kernel::MemoryRegion::BASE, "GSP:SharedMemory");
727 754
728 g_thread_id = 0; 755 g_thread_id = 0;
729 gpu_right_acquired = false; 756 gpu_right_acquired = false;
diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h
index 3b4b678a3..79a72f77d 100644
--- a/src/core/hle/service/gsp_gpu.h
+++ b/src/core/hle/service/gsp_gpu.h
@@ -6,10 +6,8 @@
6 6
7#include <cstddef> 7#include <cstddef>
8#include <string> 8#include <string>
9
10#include "common/bit_field.h" 9#include "common/bit_field.h"
11#include "common/common_types.h" 10#include "common/common_types.h"
12
13#include "core/hle/result.h" 11#include "core/hle/result.h"
14#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
15 13
@@ -20,30 +18,30 @@ namespace GSP_GPU {
20 18
21/// GSP interrupt ID 19/// GSP interrupt ID
22enum class InterruptId : u8 { 20enum class InterruptId : u8 {
23 PSC0 = 0x00, 21 PSC0 = 0x00,
24 PSC1 = 0x01, 22 PSC1 = 0x01,
25 PDC0 = 0x02, // Seems called every vertical screen line 23 PDC0 = 0x02, // Seems called every vertical screen line
26 PDC1 = 0x03, // Seems called every frame 24 PDC1 = 0x03, // Seems called every frame
27 PPF = 0x04, 25 PPF = 0x04,
28 P3D = 0x05, 26 P3D = 0x05,
29 DMA = 0x06, 27 DMA = 0x06,
30}; 28};
31 29
32/// GSP command ID 30/// GSP command ID
33enum class CommandId : u32 { 31enum class CommandId : u32 {
34 REQUEST_DMA = 0x00, 32 REQUEST_DMA = 0x00,
35 /// Submits a commandlist for execution by the GPU. 33 /// Submits a commandlist for execution by the GPU.
36 SUBMIT_GPU_CMDLIST = 0x01, 34 SUBMIT_GPU_CMDLIST = 0x01,
37 35
38 // Fills a given memory range with a particular value 36 // Fills a given memory range with a particular value
39 SET_MEMORY_FILL = 0x02, 37 SET_MEMORY_FILL = 0x02,
40 38
41 // Copies an image and optionally performs color-conversion or scaling. 39 // Copies an image and optionally performs color-conversion or scaling.
42 // This is highly similar to the GameCube's EFB copy feature 40 // This is highly similar to the GameCube's EFB copy feature
43 SET_DISPLAY_TRANSFER = 0x03, 41 SET_DISPLAY_TRANSFER = 0x03,
44 42
45 // Conceptionally similar to SET_DISPLAY_TRANSFER and presumable uses the same hardware path 43 // Conceptionally similar to SET_DISPLAY_TRANSFER and presumable uses the same hardware path
46 SET_TEXTURE_COPY = 0x04, 44 SET_TEXTURE_COPY = 0x04,
47 /// Flushes up to 3 cache regions in a single command. 45 /// Flushes up to 3 cache regions in a single command.
48 CACHE_FLUSH = 0x05, 46 CACHE_FLUSH = 0x05,
49}; 47};
@@ -61,19 +59,18 @@ struct InterruptRelayQueue {
61 u32 missed_PDC0; 59 u32 missed_PDC0;
62 u32 missed_PDC1; 60 u32 missed_PDC1;
63 61
64 InterruptId slot[0x34]; ///< Interrupt ID slots 62 InterruptId slot[0x34]; ///< Interrupt ID slots
65}; 63};
66static_assert(sizeof(InterruptRelayQueue) == 0x40, 64static_assert(sizeof(InterruptRelayQueue) == 0x40, "InterruptRelayQueue struct has incorrect size");
67 "InterruptRelayQueue struct has incorrect size");
68 65
69struct FrameBufferInfo { 66struct FrameBufferInfo {
70 BitField<0, 1, u32> active_fb; // 0 = first, 1 = second 67 BitField<0, 1, u32> active_fb; // 0 = first, 1 = second
71 68
72 u32 address_left; 69 u32 address_left;
73 u32 address_right; 70 u32 address_right;
74 u32 stride; // maps to 0x1EF00X90 ? 71 u32 stride; // maps to 0x1EF00X90 ?
75 u32 format; // maps to 0x1EF00X70 ? 72 u32 format; // maps to 0x1EF00X70 ?
76 u32 shown_fb; // maps to 0x1EF00X78 ? 73 u32 shown_fb; // maps to 0x1EF00X78 ?
77 u32 unknown; 74 u32 unknown;
78}; 75};
79static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size"); 76static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size");
@@ -91,7 +88,8 @@ static_assert(sizeof(FrameBufferUpdate) == 0x40, "Struct has incorrect size");
91// TODO: Not sure if this padding is correct. 88// TODO: Not sure if this padding is correct.
92// Chances are the second block is stored at offset 0x24 rather than 0x20. 89// Chances are the second block is stored at offset 0x24 rather than 0x20.
93#ifndef _MSC_VER 90#ifndef _MSC_VER
94static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20, "FrameBufferInfo element has incorrect alignment"); 91static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20,
92 "FrameBufferInfo element has incorrect alignment");
95#endif 93#endif
96 94
97/// GSP command 95/// GSP command
@@ -163,13 +161,13 @@ struct CommandBuffer {
163 // Current command index. This index is updated by GSP module after loading the command 161 // 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, 162 // 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. 163 // the total commands field is decreased by one as well.
166 BitField<0,8,u32> index; 164 BitField<0, 8, u32> index;
167 165
168 // Total commands to process, must not be value 0 when GSP module handles commands. This 166 // 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 167 // 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 168 // application when writing a command to shared memory, after increasing this value
171 // TriggerCmdReqQueue is only used if this field is value 1. 169 // TriggerCmdReqQueue is only used if this field is value 1.
172 BitField<8,8,u32> number_commands; 170 BitField<8, 8, u32> number_commands;
173 }; 171 };
174 172
175 u32 unk[7]; 173 u32 unk[7];
diff --git a/src/core/hle/service/gsp_lcd.cpp b/src/core/hle/service/gsp_lcd.cpp
index c700c21c5..b916dd759 100644
--- a/src/core/hle/service/gsp_lcd.cpp
+++ b/src/core/hle/service/gsp_lcd.cpp
@@ -10,11 +10,13 @@
10namespace GSP_LCD { 10namespace GSP_LCD {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {
13 // clang-format off
13 {0x000F0000, nullptr, "PowerOnAllBacklights"}, 14 {0x000F0000, nullptr, "PowerOnAllBacklights"},
14 {0x00100000, nullptr, "PowerOffAllBacklights"}, 15 {0x00100000, nullptr, "PowerOffAllBacklights"},
15 {0x00110040, nullptr, "PowerOnBacklight"}, 16 {0x00110040, nullptr, "PowerOnBacklight"},
16 {0x00120040, nullptr, "PowerOffBacklight"}, 17 {0x00120040, nullptr, "PowerOffBacklight"},
17 {0x00130040, nullptr, "SetLedForceOff"} 18 {0x00130040, nullptr, "SetLedForceOff"},
19 // clang-format on
18}; 20};
19 21
20//////////////////////////////////////////////////////////////////////////////////////////////////// 22////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index cdec11388..99baded11 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -3,19 +3,15 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cmath> 5#include <cmath>
6
7#include "common/logging/log.h"
8#include "common/emu_window.h" 6#include "common/emu_window.h"
9 7#include "common/logging/log.h"
10#include "core/hle/service/service.h"
11#include "core/hle/service/hid/hid.h"
12#include "core/hle/service/hid/hid_spvr.h"
13#include "core/hle/service/hid/hid_user.h"
14
15#include "core/core_timing.h" 8#include "core/core_timing.h"
16#include "core/hle/kernel/event.h" 9#include "core/hle/kernel/event.h"
17#include "core/hle/kernel/shared_memory.h" 10#include "core/hle/kernel/shared_memory.h"
18 11#include "core/hle/service/hid/hid.h"
12#include "core/hle/service/hid/hid_spvr.h"
13#include "core/hle/service/hid/hid_user.h"
14#include "core/hle/service/service.h"
19#include "video_core/video_core.h" 15#include "video_core/video_core.h"
20 16
21namespace Service { 17namespace Service {
@@ -37,11 +33,13 @@ static u32 next_accelerometer_index;
37static u32 next_gyroscope_index; 33static u32 next_gyroscope_index;
38 34
39static int enable_accelerometer_count = 0; // positive means enabled 35static int enable_accelerometer_count = 0; // positive means enabled
40static int enable_gyroscope_count = 0; // positive means enabled 36static int enable_gyroscope_count = 0; // positive means enabled
41 37
42static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) { 38static 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 39 // 30 degree and 60 degree are angular thresholds for directions
44 constexpr int CIRCLE_PAD_THRESHOLD_SQUARE = 40 * 40; // a circle pad radius greater than 40 will trigger circle pad direction 40 constexpr float TAN30 = 0.577350269, TAN60 = 1 / TAN30;
41 // a circle pad radius greater than 40 will trigger circle pad direction
42 constexpr int CIRCLE_PAD_THRESHOLD_SQUARE = 40 * 40;
45 PadState state; 43 PadState state;
46 state.hex = 0; 44 state.hex = 0;
47 45
@@ -90,7 +88,7 @@ void Update() {
90 PadState old_state = mem->pad.entries[last_entry_index].current_state; 88 PadState old_state = mem->pad.entries[last_entry_index].current_state;
91 89
92 // Compute bitmask with 1s for bits different from the old state 90 // Compute bitmask with 1s for bits different from the old state
93 PadState changed = { { (state.hex ^ old_state.hex) } }; 91 PadState changed = {{(state.hex ^ old_state.hex)}};
94 92
95 // Get the current Pad entry 93 // Get the current Pad entry
96 PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index]; 94 PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index];
@@ -135,11 +133,13 @@ void Update() {
135 // Update accelerometer 133 // Update accelerometer
136 if (enable_accelerometer_count > 0) { 134 if (enable_accelerometer_count > 0) {
137 mem->accelerometer.index = next_accelerometer_index; 135 mem->accelerometer.index = next_accelerometer_index;
138 next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size(); 136 next_accelerometer_index =
137 (next_accelerometer_index + 1) % mem->accelerometer.entries.size();
139 138
140 AccelerometerDataEntry& accelerometer_entry = mem->accelerometer.entries[mem->accelerometer.index]; 139 AccelerometerDataEntry& accelerometer_entry =
141 std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) 140 mem->accelerometer.entries[mem->accelerometer.index];
142 = VideoCore::g_emu_window->GetAccelerometerState(); 141 std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) =
142 VideoCore::g_emu_window->GetAccelerometerState();
143 143
144 // Make up "raw" entry 144 // Make up "raw" entry
145 // TODO(wwylele): 145 // TODO(wwylele):
@@ -167,8 +167,8 @@ void Update() {
167 next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size(); 167 next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size();
168 168
169 GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index]; 169 GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];
170 std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) 170 std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) =
171 = VideoCore::g_emu_window->GetGyroscopeState(); 171 VideoCore::g_emu_window->GetGyroscopeState();
172 172
173 // Make up "raw" entry 173 // Make up "raw" entry
174 mem->gyroscope.raw_entry.x = gyroscope_entry.x; 174 mem->gyroscope.raw_entry.x = gyroscope_entry.x;
@@ -188,7 +188,7 @@ void Update() {
188void GetIPCHandles(Service::Interface* self) { 188void GetIPCHandles(Service::Interface* self) {
189 u32* cmd_buff = Kernel::GetCommandBuffer(); 189 u32* cmd_buff = Kernel::GetCommandBuffer();
190 190
191 cmd_buff[1] = 0; // No error 191 cmd_buff[1] = 0; // No error
192 cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header 192 cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header
193 // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling) 193 // 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(); 194 cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).MoveFrom();
@@ -259,9 +259,7 @@ void GetGyroscopeLowCalibrateParam(Service::Interface* self) {
259 259
260 const s16 param_unit = 6700; // an approximate value taken from hw 260 const s16 param_unit = 6700; // an approximate value taken from hw
261 GyroscopeCalibrateParam param = { 261 GyroscopeCalibrateParam param = {
262 { 0, param_unit, -param_unit }, 262 {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 }; 263 };
266 memcpy(&cmd_buff[2], &param, sizeof(param)); 264 memcpy(&cmd_buff[2], &param, sizeof(param));
267 265
@@ -286,9 +284,9 @@ void Init() {
286 AddService(new HID_SPVR_Interface); 284 AddService(new HID_SPVR_Interface);
287 285
288 using Kernel::MemoryPermission; 286 using Kernel::MemoryPermission;
289 shared_mem = SharedMemory::Create(nullptr, 0x1000, 287 shared_mem =
290 MemoryPermission::ReadWrite, MemoryPermission::Read, 288 SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read,
291 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); 289 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");
292 290
293 next_pad_index = 0; 291 next_pad_index = 0;
294 next_touch_index = 0; 292 next_touch_index = 0;
@@ -296,9 +294,9 @@ void Init() {
296 // Create event handles 294 // Create event handles
297 event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1"); 295 event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1");
298 event_pad_or_touch_2 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch2"); 296 event_pad_or_touch_2 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch2");
299 event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer"); 297 event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer");
300 event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope"); 298 event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope");
301 event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad"); 299 event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad");
302} 300}
303 301
304void Shutdown() { 302void Shutdown() {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 669b1f723..7904e7355 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -5,14 +5,13 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8
9#ifndef _MSC_VER 8#ifndef _MSC_VER
10#include <cstddef> 9#include <cstddef>
11#endif 10#endif
12#include "core/settings.h"
13#include "common/bit_field.h" 11#include "common/bit_field.h"
14#include "common/common_funcs.h" 12#include "common/common_funcs.h"
15#include "common/common_types.h" 13#include "common/common_types.h"
14#include "core/settings.h"
16 15
17namespace Service { 16namespace Service {
18 17
@@ -103,7 +102,7 @@ struct SharedMem {
103 struct { 102 struct {
104 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 103 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` 104 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
106 u32 index; ///< Index of the last updated pad state entry 105 u32 index; ///< Index of the last updated pad state entry
107 106
108 INSERT_PADDING_WORDS(0x2); 107 INSERT_PADDING_WORDS(0x2);
109 108
@@ -121,7 +120,7 @@ struct SharedMem {
121 struct { 120 struct {
122 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 121 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` 122 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
124 u32 index; ///< Index of the last updated touch entry 123 u32 index; ///< Index of the last updated touch entry
125 124
126 INSERT_PADDING_WORDS(0x1); 125 INSERT_PADDING_WORDS(0x1);
127 126
@@ -135,7 +134,7 @@ struct SharedMem {
135 struct { 134 struct {
136 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 135 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` 136 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
138 u32 index; ///< Index of the last updated accelerometer entry 137 u32 index; ///< Index of the last updated accelerometer entry
139 138
140 INSERT_PADDING_WORDS(0x1); 139 INSERT_PADDING_WORDS(0x1);
141 140
@@ -149,7 +148,7 @@ struct SharedMem {
149 struct { 148 struct {
150 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 149 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` 150 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
152 u32 index; ///< Index of the last updated accelerometer entry 151 u32 index; ///< Index of the last updated accelerometer entry
153 152
154 INSERT_PADDING_WORDS(0x1); 153 INSERT_PADDING_WORDS(0x1);
155 154
@@ -176,9 +175,9 @@ struct GyroscopeCalibrateParam {
176// is technically allowed since C++11. This macro should be enabled once MSVC adds 175// is technically allowed since C++11. This macro should be enabled once MSVC adds
177// support for that. 176// support for that.
178#ifndef _MSC_VER 177#ifndef _MSC_VER
179#define ASSERT_REG_POSITION(field_name, position) \ 178#define ASSERT_REG_POSITION(field_name, position) \
180 static_assert(offsetof(SharedMem, field_name) == position * 4, \ 179 static_assert(offsetof(SharedMem, field_name) == position * 4, \
181 "Field "#field_name" has invalid position") 180 "Field " #field_name " has invalid position")
182 181
183ASSERT_REG_POSITION(pad.index_reset_ticks, 0x0); 182ASSERT_REG_POSITION(pad.index_reset_ticks, 0x0);
184ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A); 183ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A);
@@ -187,33 +186,33 @@ ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A);
187#endif // !defined(_MSC_VER) 186#endif // !defined(_MSC_VER)
188 187
189// Pre-defined PadStates for single button presses 188// Pre-defined PadStates for single button presses
190const PadState PAD_NONE = {{0}}; 189const PadState PAD_NONE = {{0}};
191const PadState PAD_A = {{1u << 0}}; 190const PadState PAD_A = {{1u << 0}};
192const PadState PAD_B = {{1u << 1}}; 191const PadState PAD_B = {{1u << 1}};
193const PadState PAD_SELECT = {{1u << 2}}; 192const PadState PAD_SELECT = {{1u << 2}};
194const PadState PAD_START = {{1u << 3}}; 193const PadState PAD_START = {{1u << 3}};
195const PadState PAD_RIGHT = {{1u << 4}}; 194const PadState PAD_RIGHT = {{1u << 4}};
196const PadState PAD_LEFT = {{1u << 5}}; 195const PadState PAD_LEFT = {{1u << 5}};
197const PadState PAD_UP = {{1u << 6}}; 196const PadState PAD_UP = {{1u << 6}};
198const PadState PAD_DOWN = {{1u << 7}}; 197const PadState PAD_DOWN = {{1u << 7}};
199const PadState PAD_R = {{1u << 8}}; 198const PadState PAD_R = {{1u << 8}};
200const PadState PAD_L = {{1u << 9}}; 199const PadState PAD_L = {{1u << 9}};
201const PadState PAD_X = {{1u << 10}}; 200const PadState PAD_X = {{1u << 10}};
202const PadState PAD_Y = {{1u << 11}}; 201const PadState PAD_Y = {{1u << 11}};
203 202
204const PadState PAD_ZL = {{1u << 14}}; 203const PadState PAD_ZL = {{1u << 14}};
205const PadState PAD_ZR = {{1u << 15}}; 204const PadState PAD_ZR = {{1u << 15}};
206 205
207const PadState PAD_TOUCH = {{1u << 20}}; 206const PadState PAD_TOUCH = {{1u << 20}};
208 207
209const PadState PAD_C_RIGHT = {{1u << 24}}; 208const PadState PAD_C_RIGHT = {{1u << 24}};
210const PadState PAD_C_LEFT = {{1u << 25}}; 209const PadState PAD_C_LEFT = {{1u << 25}};
211const PadState PAD_C_UP = {{1u << 26}}; 210const PadState PAD_C_UP = {{1u << 26}};
212const PadState PAD_C_DOWN = {{1u << 27}}; 211const PadState PAD_C_DOWN = {{1u << 27}};
213const PadState PAD_CIRCLE_RIGHT = {{1u << 28}}; 212const PadState PAD_CIRCLE_RIGHT = {{1u << 28}};
214const PadState PAD_CIRCLE_LEFT = {{1u << 29}}; 213const PadState PAD_CIRCLE_LEFT = {{1u << 29}};
215const PadState PAD_CIRCLE_UP = {{1u << 30}}; 214const PadState PAD_CIRCLE_UP = {{1u << 30}};
216const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; 215const PadState PAD_CIRCLE_DOWN = {{1u << 31}};
217 216
218/** 217/**
219 * HID::GetIPCHandles service function 218 * HID::GetIPCHandles service function
@@ -305,6 +304,5 @@ void Init();
305 304
306/// Shutdown HID service 305/// Shutdown HID service
307void Shutdown(); 306void Shutdown();
308
309} 307}
310} 308}
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..4d6639ded 100644
--- a/src/core/hle/service/ir/ir.cpp
+++ b/src/core/hle/service/ir/ir.cpp
@@ -4,12 +4,11 @@
4 4
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
8#include "core/hle/service/service.h"
9#include "core/hle/service/ir/ir.h" 7#include "core/hle/service/ir/ir.h"
10#include "core/hle/service/ir/ir_rst.h" 8#include "core/hle/service/ir/ir_rst.h"
11#include "core/hle/service/ir/ir_u.h" 9#include "core/hle/service/ir/ir_u.h"
12#include "core/hle/service/ir/ir_user.h" 10#include "core/hle/service/ir/ir_user.h"
11#include "core/hle/service/service.h"
13 12
14namespace Service { 13namespace Service {
15namespace IR { 14namespace IR {
@@ -32,14 +31,14 @@ void InitializeIrNopShared(Interface* self) {
32 u32* cmd_buff = Kernel::GetCommandBuffer(); 31 u32* cmd_buff = Kernel::GetCommandBuffer();
33 32
34 u32 transfer_buff_size = cmd_buff[1]; 33 u32 transfer_buff_size = cmd_buff[1];
35 u32 recv_buff_size = cmd_buff[2]; 34 u32 recv_buff_size = cmd_buff[2];
36 u32 unk1 = cmd_buff[3]; 35 u32 unk1 = cmd_buff[3];
37 u32 send_buff_size = cmd_buff[4]; 36 u32 send_buff_size = cmd_buff[4];
38 u32 unk2 = cmd_buff[5]; 37 u32 unk2 = cmd_buff[5];
39 u8 baud_rate = cmd_buff[6] & 0xFF; 38 u8 baud_rate = cmd_buff[6] & 0xFF;
40 Handle handle = cmd_buff[8]; 39 Handle handle = cmd_buff[8];
41 40
42 if(Kernel::g_handle_table.IsValid(handle)) { 41 if (Kernel::g_handle_table.IsValid(handle)) {
43 transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle); 42 transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle);
44 transfer_shared_memory->name = "IR:TransferSharedMemory"; 43 transfer_shared_memory->name = "IR:TransferSharedMemory";
45 } 44 }
@@ -47,7 +46,7 @@ void InitializeIrNopShared(Interface* self) {
47 cmd_buff[1] = RESULT_SUCCESS.raw; 46 cmd_buff[1] = RESULT_SUCCESS.raw;
48 47
49 LOG_WARNING(Service_IR, "(STUBBED) called, transfer_buff_size=%d, recv_buff_size=%d, " 48 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", 49 "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); 50 transfer_buff_size, recv_buff_size, unk1, send_buff_size, unk2, baud_rate, handle);
52} 51}
53 52
@@ -94,13 +93,13 @@ void Init() {
94 AddService(new IR_User_Interface); 93 AddService(new IR_User_Interface);
95 94
96 using Kernel::MemoryPermission; 95 using Kernel::MemoryPermission;
97 shared_memory = SharedMemory::Create(nullptr, 0x1000, 96 shared_memory = SharedMemory::Create(nullptr, 0x1000, Kernel::MemoryPermission::ReadWrite,
98 Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::ReadWrite, 97 Kernel::MemoryPermission::ReadWrite, 0,
99 0, Kernel::MemoryRegion::BASE, "IR:SharedMemory"); 98 Kernel::MemoryRegion::BASE, "IR:SharedMemory");
100 transfer_shared_memory = nullptr; 99 transfer_shared_memory = nullptr;
101 100
102 // Create event handle(s) 101 // Create event handle(s)
103 handle_event = Event::Create(ResetType::OneShot, "IR:HandleEvent"); 102 handle_event = Event::Create(ResetType::OneShot, "IR:HandleEvent");
104 conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent"); 103 conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent");
105} 104}
106 105
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..429615f31 100644
--- a/src/core/hle/service/ir/ir_u.cpp
+++ b/src/core/hle/service/ir/ir_u.cpp
@@ -8,24 +8,26 @@ namespace Service {
8namespace IR { 8namespace IR {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x00010000, nullptr, "Initialize"}, 11 // clang-format off
12 {0x00020000, nullptr, "Shutdown"}, 12 {0x00010000, nullptr, "Initialize"},
13 {0x00030042, nullptr, "StartSendTransfer"}, 13 {0x00020000, nullptr, "Shutdown"},
14 {0x00040000, nullptr, "WaitSendTransfer"}, 14 {0x00030042, nullptr, "StartSendTransfer"},
15 {0x000500C2, nullptr, "StartRecvTransfer"}, 15 {0x00040000, nullptr, "WaitSendTransfer"},
16 {0x00060000, nullptr, "WaitRecvTransfer"}, 16 {0x000500C2, nullptr, "StartRecvTransfer"},
17 {0x00070080, nullptr, "GetRecvTransferCount"}, 17 {0x00060000, nullptr, "WaitRecvTransfer"},
18 {0x00080000, nullptr, "GetSendState"}, 18 {0x00070080, nullptr, "GetRecvTransferCount"},
19 {0x00090040, nullptr, "SetBitRate"}, 19 {0x00080000, nullptr, "GetSendState"},
20 {0x000A0000, nullptr, "GetBitRate"}, 20 {0x00090040, nullptr, "SetBitRate"},
21 {0x000B0040, nullptr, "SetIRLEDState"}, 21 {0x000A0000, nullptr, "GetBitRate"},
22 {0x000C0000, nullptr, "GetIRLEDRecvState"}, 22 {0x000B0040, nullptr, "SetIRLEDState"},
23 {0x000D0000, nullptr, "GetSendFinishedEvent"}, 23 {0x000C0000, nullptr, "GetIRLEDRecvState"},
24 {0x000E0000, nullptr, "GetRecvFinishedEvent"}, 24 {0x000D0000, nullptr, "GetSendFinishedEvent"},
25 {0x000F0000, nullptr, "GetTransferState"}, 25 {0x000E0000, nullptr, "GetRecvFinishedEvent"},
26 {0x00100000, nullptr, "GetErrorStatus"}, 26 {0x000F0000, nullptr, "GetTransferState"},
27 {0x00110040, nullptr, "SetSleepModeActive"}, 27 {0x00100000, nullptr, "GetErrorStatus"},
28 {0x00120040, nullptr, "SetSleepModeState"}, 28 {0x00110040, nullptr, "SetSleepModeActive"},
29 {0x00120040, nullptr, "SetSleepModeState"},
30 // clang-format off
29}; 31};
30 32
31IR_U_Interface::IR_U_Interface() { 33IR_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..b7d250312 100644
--- a/src/core/hle/service/ldr_ro/cro_helper.cpp
+++ b/src/core/hle/service/ldr_ro/cro_helper.cpp
@@ -5,7 +5,6 @@
5#include "common/alignment.h" 5#include "common/alignment.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "common/scope_exit.h" 7#include "common/scope_exit.h"
8
9#include "core/hle/service/ldr_ro/cro_helper.h" 8#include "core/hle/service/ldr_ro/cro_helper.h"
10 9
11//////////////////////////////////////////////////////////////////////////////////////////////////// 10////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -14,37 +13,30 @@
14namespace LDR_RO { 13namespace LDR_RO {
15 14
16static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F 15static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F
17 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 16 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument,
17 ErrorLevel::Usage);
18 18
19static ResultCode CROFormatError(u32 description) { 19static ResultCode CROFormatError(u32 description) {
20 return ResultCode(static_cast<ErrorDescription>(description), ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 20 return ResultCode(static_cast<ErrorDescription>(description), ErrorModule::RO,
21 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
21} 22}
22 23
23const std::array<int, 17> CROHelper::ENTRY_SIZE {{ 24const std::array<int, 17> CROHelper::ENTRY_SIZE{{
24 1, // code 25 1, // code
25 1, // data 26 1, // data
26 1, // module name 27 1, // module name
27 sizeof(SegmentEntry), 28 sizeof(SegmentEntry), sizeof(ExportNamedSymbolEntry), sizeof(ExportIndexedSymbolEntry),
28 sizeof(ExportNamedSymbolEntry),
29 sizeof(ExportIndexedSymbolEntry),
30 1, // export strings 29 1, // export strings
31 sizeof(ExportTreeEntry), 30 sizeof(ExportTreeEntry), sizeof(ImportModuleEntry), sizeof(ExternalRelocationEntry),
32 sizeof(ImportModuleEntry), 31 sizeof(ImportNamedSymbolEntry), sizeof(ImportIndexedSymbolEntry),
33 sizeof(ExternalRelocationEntry),
34 sizeof(ImportNamedSymbolEntry),
35 sizeof(ImportIndexedSymbolEntry),
36 sizeof(ImportAnonymousSymbolEntry), 32 sizeof(ImportAnonymousSymbolEntry),
37 1, // import strings 33 1, // import strings
38 sizeof(StaticAnonymousSymbolEntry), 34 sizeof(StaticAnonymousSymbolEntry), sizeof(InternalRelocationEntry),
39 sizeof(InternalRelocationEntry), 35 sizeof(StaticRelocationEntry),
40 sizeof(StaticRelocationEntry)
41}}; 36}};
42 37
43const std::array<CROHelper::HeaderField, 4> CROHelper::FIX_BARRIERS {{ 38const std::array<CROHelper::HeaderField, 4> CROHelper::FIX_BARRIERS{{
44 Fix0Barrier, 39 Fix0Barrier, Fix1Barrier, Fix2Barrier, Fix3Barrier,
45 Fix1Barrier,
46 Fix2Barrier,
47 Fix3Barrier
48}}; 40}};
49 41
50VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const { 42VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const {
@@ -63,7 +55,7 @@ VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const {
63} 55}
64 56
65ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType relocation_type, 57ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType relocation_type,
66 u32 addend, u32 symbol_address, u32 target_future_address) { 58 u32 addend, u32 symbol_address, u32 target_future_address) {
67 59
68 switch (relocation_type) { 60 switch (relocation_type) {
69 case RelocationType::Nothing: 61 case RelocationType::Nothing:
@@ -124,7 +116,8 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool
124 return CROFormatError(0x12); 116 return CROFormatError(0x12);
125 } 117 }
126 118
127 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, symbol_address, relocation_target); 119 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend,
120 symbol_address, relocation_target);
128 if (result.IsError()) { 121 if (result.IsError()) {
129 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); 122 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
130 return result; 123 return result;
@@ -167,7 +160,7 @@ VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const {
167 160
168 if (test_byte >= len) { 161 if (test_byte >= len) {
169 next.raw = entry.left.raw; 162 next.raw = entry.left.raw;
170 } else if((name[test_byte] >> test_bit_in_byte) & 1) { 163 } else if ((name[test_byte] >> test_bit_in_byte) & 1) {
171 next.raw = entry.right.raw; 164 next.raw = entry.right.raw;
172 } else { 165 } else {
173 next.raw = entry.left.raw; 166 next.raw = entry.left.raw;
@@ -213,24 +206,12 @@ ResultCode CROHelper::RebaseHeader(u32 cro_size) {
213 206
214 // verifies that all offsets are in the correct order 207 // verifies that all offsets are in the correct order
215 constexpr std::array<HeaderField, 18> OFFSET_ORDER = {{ 208 constexpr std::array<HeaderField, 18> OFFSET_ORDER = {{
216 CodeOffset, 209 CodeOffset, ModuleNameOffset, SegmentTableOffset, ExportNamedSymbolTableOffset,
217 ModuleNameOffset, 210 ExportTreeTableOffset, ExportIndexedSymbolTableOffset, ExportStringsOffset,
218 SegmentTableOffset, 211 ImportModuleTableOffset, ExternalRelocationTableOffset, ImportNamedSymbolTableOffset,
219 ExportNamedSymbolTableOffset, 212 ImportIndexedSymbolTableOffset, ImportAnonymousSymbolTableOffset, ImportStringsOffset,
220 ExportTreeTableOffset, 213 StaticAnonymousSymbolTableOffset, InternalRelocationTableOffset,
221 ExportIndexedSymbolTableOffset, 214 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 }}; 215 }};
235 216
236 u32 prev_offset = GetField(OFFSET_ORDER[0]); 217 u32 prev_offset = GetField(OFFSET_ORDER[0]);
@@ -266,9 +247,9 @@ ResultCode CROHelper::RebaseHeader(u32 cro_size) {
266 return RESULT_SUCCESS; 247 return RESULT_SUCCESS;
267} 248}
268 249
269ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, 250ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, VAddr data_segment_address,
270 VAddr data_segment_address, u32 data_segment_size, 251 u32 data_segment_size, VAddr bss_segment_address,
271 VAddr bss_segment_address, u32 bss_segment_size) { 252 u32 bss_segment_size) {
272 253
273 u32 prev_data_segment = 0; 254 u32 prev_data_segment = 0;
274 u32 segment_num = GetField(SegmentNum); 255 u32 segment_num = GetField(SegmentNum);
@@ -309,8 +290,8 @@ ResultCode CROHelper::RebaseExportNamedSymbolTable() {
309 290
310 if (entry.name_offset != 0) { 291 if (entry.name_offset != 0) {
311 entry.name_offset += module_address; 292 entry.name_offset += module_address;
312 if (entry.name_offset < export_strings_offset 293 if (entry.name_offset < export_strings_offset ||
313 || entry.name_offset >= export_strings_end) { 294 entry.name_offset >= export_strings_end) {
314 return CROFormatError(0x11); 295 return CROFormatError(0x11);
315 } 296 }
316 } 297 }
@@ -337,9 +318,13 @@ ResultCode CROHelper::RebaseImportModuleTable() {
337 VAddr import_strings_offset = GetField(ImportStringsOffset); 318 VAddr import_strings_offset = GetField(ImportStringsOffset);
338 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); 319 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize);
339 VAddr import_indexed_symbol_table_offset = GetField(ImportIndexedSymbolTableOffset); 320 VAddr import_indexed_symbol_table_offset = GetField(ImportIndexedSymbolTableOffset);
340 VAddr index_import_table_end = import_indexed_symbol_table_offset + GetField(ImportIndexedSymbolNum) * sizeof(ImportIndexedSymbolEntry); 321 VAddr index_import_table_end =
322 import_indexed_symbol_table_offset +
323 GetField(ImportIndexedSymbolNum) * sizeof(ImportIndexedSymbolEntry);
341 VAddr import_anonymous_symbol_table_offset = GetField(ImportAnonymousSymbolTableOffset); 324 VAddr import_anonymous_symbol_table_offset = GetField(ImportAnonymousSymbolTableOffset);
342 VAddr offset_import_table_end = import_anonymous_symbol_table_offset + GetField(ImportAnonymousSymbolNum) * sizeof(ImportAnonymousSymbolEntry); 325 VAddr offset_import_table_end =
326 import_anonymous_symbol_table_offset +
327 GetField(ImportAnonymousSymbolNum) * sizeof(ImportAnonymousSymbolEntry);
343 328
344 u32 module_num = GetField(ImportModuleNum); 329 u32 module_num = GetField(ImportModuleNum);
345 for (u32 i = 0; i < module_num; ++i) { 330 for (u32 i = 0; i < module_num; ++i) {
@@ -348,24 +333,24 @@ ResultCode CROHelper::RebaseImportModuleTable() {
348 333
349 if (entry.name_offset != 0) { 334 if (entry.name_offset != 0) {
350 entry.name_offset += module_address; 335 entry.name_offset += module_address;
351 if (entry.name_offset < import_strings_offset 336 if (entry.name_offset < import_strings_offset ||
352 || entry.name_offset >= import_strings_end) { 337 entry.name_offset >= import_strings_end) {
353 return CROFormatError(0x18); 338 return CROFormatError(0x18);
354 } 339 }
355 } 340 }
356 341
357 if (entry.import_indexed_symbol_table_offset != 0) { 342 if (entry.import_indexed_symbol_table_offset != 0) {
358 entry.import_indexed_symbol_table_offset += module_address; 343 entry.import_indexed_symbol_table_offset += module_address;
359 if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset 344 if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset ||
360 || entry.import_indexed_symbol_table_offset > index_import_table_end) { 345 entry.import_indexed_symbol_table_offset > index_import_table_end) {
361 return CROFormatError(0x18); 346 return CROFormatError(0x18);
362 } 347 }
363 } 348 }
364 349
365 if (entry.import_anonymous_symbol_table_offset != 0) { 350 if (entry.import_anonymous_symbol_table_offset != 0) {
366 entry.import_anonymous_symbol_table_offset += module_address; 351 entry.import_anonymous_symbol_table_offset += module_address;
367 if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset 352 if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset ||
368 || entry.import_anonymous_symbol_table_offset > offset_import_table_end) { 353 entry.import_anonymous_symbol_table_offset > offset_import_table_end) {
369 return CROFormatError(0x18); 354 return CROFormatError(0x18);
370 } 355 }
371 } 356 }
@@ -379,25 +364,27 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() {
379 VAddr import_strings_offset = GetField(ImportStringsOffset); 364 VAddr import_strings_offset = GetField(ImportStringsOffset);
380 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); 365 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize);
381 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); 366 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset);
382 VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); 367 VAddr external_relocation_table_end =
368 external_relocation_table_offset +
369 GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
383 370
384 u32 num = GetField(ImportNamedSymbolNum); 371 u32 num = GetField(ImportNamedSymbolNum);
385 for (u32 i = 0; i < num ; ++i) { 372 for (u32 i = 0; i < num; ++i) {
386 ImportNamedSymbolEntry entry; 373 ImportNamedSymbolEntry entry;
387 GetEntry(i, entry); 374 GetEntry(i, entry);
388 375
389 if (entry.name_offset != 0) { 376 if (entry.name_offset != 0) {
390 entry.name_offset += module_address; 377 entry.name_offset += module_address;
391 if (entry.name_offset < import_strings_offset 378 if (entry.name_offset < import_strings_offset ||
392 || entry.name_offset >= import_strings_end) { 379 entry.name_offset >= import_strings_end) {
393 return CROFormatError(0x1B); 380 return CROFormatError(0x1B);
394 } 381 }
395 } 382 }
396 383
397 if (entry.relocation_batch_offset != 0) { 384 if (entry.relocation_batch_offset != 0) {
398 entry.relocation_batch_offset += module_address; 385 entry.relocation_batch_offset += module_address;
399 if (entry.relocation_batch_offset < external_relocation_table_offset 386 if (entry.relocation_batch_offset < external_relocation_table_offset ||
400 || entry.relocation_batch_offset > external_relocation_table_end) { 387 entry.relocation_batch_offset > external_relocation_table_end) {
401 return CROFormatError(0x1B); 388 return CROFormatError(0x1B);
402 } 389 }
403 } 390 }
@@ -409,17 +396,19 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() {
409 396
410ResultCode CROHelper::RebaseImportIndexedSymbolTable() { 397ResultCode CROHelper::RebaseImportIndexedSymbolTable() {
411 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); 398 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset);
412 VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); 399 VAddr external_relocation_table_end =
400 external_relocation_table_offset +
401 GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
413 402
414 u32 num = GetField(ImportIndexedSymbolNum); 403 u32 num = GetField(ImportIndexedSymbolNum);
415 for (u32 i = 0; i < num ; ++i) { 404 for (u32 i = 0; i < num; ++i) {
416 ImportIndexedSymbolEntry entry; 405 ImportIndexedSymbolEntry entry;
417 GetEntry(i, entry); 406 GetEntry(i, entry);
418 407
419 if (entry.relocation_batch_offset != 0) { 408 if (entry.relocation_batch_offset != 0) {
420 entry.relocation_batch_offset += module_address; 409 entry.relocation_batch_offset += module_address;
421 if (entry.relocation_batch_offset < external_relocation_table_offset 410 if (entry.relocation_batch_offset < external_relocation_table_offset ||
422 || entry.relocation_batch_offset > external_relocation_table_end) { 411 entry.relocation_batch_offset > external_relocation_table_end) {
423 return CROFormatError(0x14); 412 return CROFormatError(0x14);
424 } 413 }
425 } 414 }
@@ -431,17 +420,19 @@ ResultCode CROHelper::RebaseImportIndexedSymbolTable() {
431 420
432ResultCode CROHelper::RebaseImportAnonymousSymbolTable() { 421ResultCode CROHelper::RebaseImportAnonymousSymbolTable() {
433 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); 422 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset);
434 VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); 423 VAddr external_relocation_table_end =
424 external_relocation_table_offset +
425 GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
435 426
436 u32 num = GetField(ImportAnonymousSymbolNum); 427 u32 num = GetField(ImportAnonymousSymbolNum);
437 for (u32 i = 0; i < num ; ++i) { 428 for (u32 i = 0; i < num; ++i) {
438 ImportAnonymousSymbolEntry entry; 429 ImportAnonymousSymbolEntry entry;
439 GetEntry(i, entry); 430 GetEntry(i, entry);
440 431
441 if (entry.relocation_batch_offset != 0) { 432 if (entry.relocation_batch_offset != 0) {
442 entry.relocation_batch_offset += module_address; 433 entry.relocation_batch_offset += module_address;
443 if (entry.relocation_batch_offset < external_relocation_table_offset 434 if (entry.relocation_batch_offset < external_relocation_table_offset ||
444 || entry.relocation_batch_offset > external_relocation_table_end) { 435 entry.relocation_batch_offset > external_relocation_table_end) {
445 return CROFormatError(0x17); 436 return CROFormatError(0x17);
446 } 437 }
447 } 438 }
@@ -475,7 +466,8 @@ ResultCode CROHelper::ResetExternalRelocations() {
475 return CROFormatError(0x12); 466 return CROFormatError(0x12);
476 } 467 }
477 468
478 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, unresolved_symbol, relocation_target); 469 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend,
470 unresolved_symbol, relocation_target);
479 if (result.IsError()) { 471 if (result.IsError()) {
480 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); 472 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
481 return result; 473 return result;
@@ -528,23 +520,27 @@ ResultCode CROHelper::ClearExternalRelocations() {
528 520
529ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) { 521ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) {
530 VAddr static_relocation_table_offset = GetField(StaticRelocationTableOffset); 522 VAddr static_relocation_table_offset = GetField(StaticRelocationTableOffset);
531 VAddr static_relocation_table_end = static_relocation_table_offset + GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); 523 VAddr static_relocation_table_end =
524 static_relocation_table_offset +
525 GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry);
532 526
533 CROHelper crs(crs_address); 527 CROHelper crs(crs_address);
534 u32 offset_export_num = GetField(StaticAnonymousSymbolNum); 528 u32 offset_export_num = GetField(StaticAnonymousSymbolNum);
535 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d static anonymous symbols", ModuleName().data(), offset_export_num); 529 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d static anonymous symbols", ModuleName().data(),
530 offset_export_num);
536 for (u32 i = 0; i < offset_export_num; ++i) { 531 for (u32 i = 0; i < offset_export_num; ++i) {
537 StaticAnonymousSymbolEntry entry; 532 StaticAnonymousSymbolEntry entry;
538 GetEntry(i, entry); 533 GetEntry(i, entry);
539 u32 batch_address = entry.relocation_batch_offset + module_address; 534 u32 batch_address = entry.relocation_batch_offset + module_address;
540 535
541 if (batch_address < static_relocation_table_offset 536 if (batch_address < static_relocation_table_offset ||
542 || batch_address > static_relocation_table_end) { 537 batch_address > static_relocation_table_end) {
543 return CROFormatError(0x16); 538 return CROFormatError(0x16);
544 } 539 }
545 540
546 u32 symbol_address = SegmentTagToAddress(entry.symbol_position); 541 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); 542 LOG_TRACE(Service_LDR, "CRO \"%s\" exports 0x%08X to the static module",
543 ModuleName().data(), symbol_address);
548 ResultCode result = crs.ApplyRelocationBatch(batch_address, symbol_address); 544 ResultCode result = crs.ApplyRelocationBatch(batch_address, symbol_address);
549 if (result.IsError()) { 545 if (result.IsError()) {
550 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 546 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
@@ -571,7 +567,8 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) {
571 567
572 if (target_segment.type == SegmentType::Data) { 568 if (target_segment.type == SegmentType::Data) {
573 // If the relocation is to the .data segment, we need to relocate it in the old buffer 569 // 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; 570 target_address =
571 old_data_segment_address + relocation.target_position.offset_into_segment;
575 } else { 572 } else {
576 target_address = target_addressB; 573 target_address = target_addressB;
577 } 574 }
@@ -582,8 +579,10 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) {
582 579
583 SegmentEntry symbol_segment; 580 SegmentEntry symbol_segment;
584 GetEntry(relocation.symbol_segment, symbol_segment); 581 GetEntry(relocation.symbol_segment, symbol_segment);
585 LOG_TRACE(Service_LDR, "Internally relocates 0x%08X with 0x%08X", target_address, symbol_segment.offset); 582 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); 583 symbol_segment.offset);
584 ResultCode result = ApplyRelocation(target_address, relocation.type, relocation.addend,
585 symbol_segment.offset, target_addressB);
587 if (result.IsError()) { 586 if (result.IsError()) {
588 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); 587 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
589 return result; 588 return result;
@@ -734,25 +733,29 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) {
734 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 733 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
735 734
736 if (!relocation_entry.is_batch_resolved) { 735 if (!relocation_entry.is_batch_resolved) {
737 ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { 736 ResultCode result =
738 std::string symbol_name = Memory::ReadCString(entry.name_offset, import_strings_size); 737 ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> {
739 u32 symbol_address = source.FindExportNamedSymbol(symbol_name); 738 std::string symbol_name =
740 739 Memory::ReadCString(entry.name_offset, import_strings_size);
741 if (symbol_address != 0) { 740 u32 symbol_address = source.FindExportNamedSymbol(symbol_name);
742 LOG_TRACE(Service_LDR, "CRO \"%s\" imports \"%s\" from \"%s\"", 741
743 ModuleName().data(), symbol_name.data(), source.ModuleName().data()); 742 if (symbol_address != 0) {
744 743 LOG_TRACE(Service_LDR, "CRO \"%s\" imports \"%s\" from \"%s\"",
745 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); 744 ModuleName().data(), symbol_name.data(),
746 if (result.IsError()) { 745 source.ModuleName().data());
747 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 746
748 return result; 747 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address);
748 if (result.IsError()) {
749 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
750 result.raw);
751 return result;
752 }
753
754 return MakeResult<bool>(false);
749 } 755 }
750 756
751 return MakeResult<bool>(false); 757 return MakeResult<bool>(true);
752 } 758 });
753
754 return MakeResult<bool>(true);
755 });
756 if (result.IsError()) { 759 if (result.IsError()) {
757 return result; 760 return result;
758 } 761 }
@@ -777,7 +780,6 @@ ResultCode CROHelper::ResetImportNamedSymbol() {
777 LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw); 780 LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw);
778 return result; 781 return result;
779 } 782 }
780
781 } 783 }
782 return RESULT_SUCCESS; 784 return RESULT_SUCCESS;
783} 785}
@@ -831,40 +833,47 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
831 GetEntry(i, entry); 833 GetEntry(i, entry);
832 std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size); 834 std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size);
833 835
834 ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { 836 ResultCode result =
835 if (want_cro_name == source.ModuleName()) { 837 ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> {
836 LOG_INFO(Service_LDR, "CRO \"%s\" imports %d indexed symbols from \"%s\"", 838 if (want_cro_name == source.ModuleName()) {
837 ModuleName().data(), entry.import_indexed_symbol_num, source.ModuleName().data()); 839 LOG_INFO(Service_LDR, "CRO \"%s\" imports %d indexed symbols from \"%s\"",
838 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { 840 ModuleName().data(), entry.import_indexed_symbol_num,
839 ImportIndexedSymbolEntry im; 841 source.ModuleName().data());
840 entry.GetImportIndexedSymbolEntry(j, im); 842 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
841 ExportIndexedSymbolEntry ex; 843 ImportIndexedSymbolEntry im;
842 source.GetEntry(im.index, ex); 844 entry.GetImportIndexedSymbolEntry(j, im);
843 u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position); 845 ExportIndexedSymbolEntry ex;
844 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); 846 source.GetEntry(im.index, ex);
845 ResultCode result = ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 847 u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position);
846 if (result.IsError()) { 848 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address);
847 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 849 ResultCode result =
848 return result; 850 ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
851 if (result.IsError()) {
852 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
853 result.raw);
854 return result;
855 }
849 } 856 }
850 } 857 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\"", 858 ModuleName().data(), entry.import_anonymous_symbol_num,
852 ModuleName().data(), entry.import_anonymous_symbol_num, source.ModuleName().data()); 859 source.ModuleName().data());
853 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { 860 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
854 ImportAnonymousSymbolEntry im; 861 ImportAnonymousSymbolEntry im;
855 entry.GetImportAnonymousSymbolEntry(j, im); 862 entry.GetImportAnonymousSymbolEntry(j, im);
856 u32 symbol_address = source.SegmentTagToAddress(im.symbol_position); 863 u32 symbol_address = source.SegmentTagToAddress(im.symbol_position);
857 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); 864 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address);
858 ResultCode result = ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 865 ResultCode result =
859 if (result.IsError()) { 866 ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
860 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 867 if (result.IsError()) {
861 return result; 868 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
869 result.raw);
870 return result;
871 }
862 } 872 }
873 return MakeResult<bool>(false);
863 } 874 }
864 return MakeResult<bool>(false); 875 return MakeResult<bool>(true);
865 } 876 });
866 return MakeResult<bool>(true);
867 });
868 if (result.IsError()) { 877 if (result.IsError()) {
869 return result; 878 return result;
870 } 879 }
@@ -873,8 +882,8 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
873} 882}
874 883
875ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { 884ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
876 LOG_DEBUG(Service_LDR, "CRO \"%s\" exports named symbols to \"%s\"", 885 LOG_DEBUG(Service_LDR, "CRO \"%s\" exports named symbols to \"%s\"", ModuleName().data(),
877 ModuleName().data(), target.ModuleName().data()); 886 target.ModuleName().data());
878 u32 target_import_strings_size = target.GetField(ImportStringsSize); 887 u32 target_import_strings_size = target.GetField(ImportStringsSize);
879 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); 888 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum);
880 for (u32 i = 0; i < target_symbol_import_num; ++i) { 889 for (u32 i = 0; i < target_symbol_import_num; ++i) {
@@ -885,7 +894,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
885 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 894 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
886 895
887 if (!relocation_entry.is_batch_resolved) { 896 if (!relocation_entry.is_batch_resolved) {
888 std::string symbol_name = Memory::ReadCString(entry.name_offset, target_import_strings_size); 897 std::string symbol_name =
898 Memory::ReadCString(entry.name_offset, target_import_strings_size);
889 u32 symbol_address = FindExportNamedSymbol(symbol_name); 899 u32 symbol_address = FindExportNamedSymbol(symbol_name);
890 if (symbol_address != 0) { 900 if (symbol_address != 0) {
891 LOG_TRACE(Service_LDR, " exports symbol \"%s\"", symbol_name.data()); 901 LOG_TRACE(Service_LDR, " exports symbol \"%s\"", symbol_name.data());
@@ -901,8 +911,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
901} 911}
902 912
903ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) { 913ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) {
904 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"", 914 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"", ModuleName().data(),
905 ModuleName().data(), target.ModuleName().data()); 915 target.ModuleName().data());
906 u32 unresolved_symbol = target.GetOnUnresolvedAddress(); 916 u32 unresolved_symbol = target.GetOnUnresolvedAddress();
907 u32 target_import_strings_size = target.GetField(ImportStringsSize); 917 u32 target_import_strings_size = target.GetField(ImportStringsSize);
908 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); 918 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum);
@@ -914,11 +924,13 @@ ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) {
914 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 924 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
915 925
916 if (relocation_entry.is_batch_resolved) { 926 if (relocation_entry.is_batch_resolved) {
917 std::string symbol_name = Memory::ReadCString(entry.name_offset, target_import_strings_size); 927 std::string symbol_name =
928 Memory::ReadCString(entry.name_offset, target_import_strings_size);
918 u32 symbol_address = FindExportNamedSymbol(symbol_name); 929 u32 symbol_address = FindExportNamedSymbol(symbol_name);
919 if (symbol_address != 0) { 930 if (symbol_address != 0) {
920 LOG_TRACE(Service_LDR, " unexports symbol \"%s\"", symbol_name.data()); 931 LOG_TRACE(Service_LDR, " unexports symbol \"%s\"", symbol_name.data());
921 ResultCode result = target.ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); 932 ResultCode result =
933 target.ApplyRelocationBatch(relocation_addr, unresolved_symbol, true);
922 if (result.IsError()) { 934 if (result.IsError()) {
923 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 935 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
924 return result; 936 return result;
@@ -940,8 +952,8 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
940 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) 952 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name)
941 continue; 953 continue;
942 954
943 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d indexed symbols to \"%s\"", 955 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()); 956 entry.import_indexed_symbol_num, target.ModuleName().data());
945 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { 957 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
946 ImportIndexedSymbolEntry im; 958 ImportIndexedSymbolEntry im;
947 entry.GetImportIndexedSymbolEntry(j, im); 959 entry.GetImportIndexedSymbolEntry(j, im);
@@ -949,7 +961,8 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
949 GetEntry(im.index, ex); 961 GetEntry(im.index, ex);
950 u32 symbol_address = SegmentTagToAddress(ex.symbol_position); 962 u32 symbol_address = SegmentTagToAddress(ex.symbol_position);
951 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); 963 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address);
952 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 964 ResultCode result =
965 target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
953 if (result.IsError()) { 966 if (result.IsError()) {
954 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 967 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
955 return result; 968 return result;
@@ -957,13 +970,14 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
957 } 970 }
958 971
959 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d anonymous symbols to \"%s\"", 972 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d anonymous symbols to \"%s\"",
960 module_name.data(), entry.import_anonymous_symbol_num, target.ModuleName().data()); 973 module_name.data(), entry.import_anonymous_symbol_num, target.ModuleName().data());
961 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { 974 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
962 ImportAnonymousSymbolEntry im; 975 ImportAnonymousSymbolEntry im;
963 entry.GetImportAnonymousSymbolEntry(j, im); 976 entry.GetImportAnonymousSymbolEntry(j, im);
964 u32 symbol_address = SegmentTagToAddress(im.symbol_position); 977 u32 symbol_address = SegmentTagToAddress(im.symbol_position);
965 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); 978 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address);
966 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 979 ResultCode result =
980 target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
967 if (result.IsError()) { 981 if (result.IsError()) {
968 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 982 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
969 return result; 983 return result;
@@ -987,12 +1001,13 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
987 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) 1001 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name)
988 continue; 1002 continue;
989 1003
990 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports indexed symbols to \"%s\"", 1004 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports indexed symbols to \"%s\"", module_name.data(),
991 module_name.data(), target.ModuleName().data()); 1005 target.ModuleName().data());
992 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { 1006 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
993 ImportIndexedSymbolEntry im; 1007 ImportIndexedSymbolEntry im;
994 entry.GetImportIndexedSymbolEntry(j, im); 1008 entry.GetImportIndexedSymbolEntry(j, im);
995 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); 1009 ResultCode result =
1010 target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true);
996 if (result.IsError()) { 1011 if (result.IsError()) {
997 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 1012 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
998 return result; 1013 return result;
@@ -1000,11 +1015,12 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
1000 } 1015 }
1001 1016
1002 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"", 1017 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"",
1003 module_name.data(), target.ModuleName().data()); 1018 module_name.data(), target.ModuleName().data());
1004 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { 1019 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
1005 ImportAnonymousSymbolEntry im; 1020 ImportAnonymousSymbolEntry im;
1006 entry.GetImportAnonymousSymbolEntry(j, im); 1021 entry.GetImportAnonymousSymbolEntry(j, im);
1007 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); 1022 ResultCode result =
1023 target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true);
1008 if (result.IsError()) { 1024 if (result.IsError()) {
1009 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 1025 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
1010 return result; 1026 return result;
@@ -1025,25 +1041,27 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) {
1025 ExternalRelocationEntry relocation_entry; 1041 ExternalRelocationEntry relocation_entry;
1026 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 1042 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
1027 1043
1028 if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit"){ 1044 if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") {
1029 ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { 1045 ResultCode result =
1030 u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); 1046 ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> {
1047 u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_");
1031 1048
1032 if (symbol_address != 0) { 1049 if (symbol_address != 0) {
1033 LOG_DEBUG(Service_LDR, "CRO \"%s\" import exit function from \"%s\"", 1050 LOG_DEBUG(Service_LDR, "CRO \"%s\" import exit function from \"%s\"",
1034 ModuleName().data(), source.ModuleName().data()); 1051 ModuleName().data(), source.ModuleName().data());
1035 1052
1036 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); 1053 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address);
1037 if (result.IsError()) { 1054 if (result.IsError()) {
1038 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 1055 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
1039 return result; 1056 result.raw);
1040 } 1057 return result;
1058 }
1041 1059
1042 return MakeResult<bool>(false); 1060 return MakeResult<bool>(false);
1043 } 1061 }
1044 1062
1045 return MakeResult<bool>(true); 1063 return MakeResult<bool>(true);
1046 }); 1064 });
1047 if (result.IsError()) { 1065 if (result.IsError()) {
1048 LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw); 1066 LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw);
1049 return result; 1067 return result;
@@ -1070,9 +1088,9 @@ static ResultCode VerifyStringTableLength(VAddr address, u32 size) {
1070 return RESULT_SUCCESS; 1088 return RESULT_SUCCESS;
1071} 1089}
1072 1090
1073ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, 1091ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment_addresss,
1074 VAddr data_segment_addresss, u32 data_segment_size, 1092 u32 data_segment_size, VAddr bss_segment_address, u32 bss_segment_size,
1075 VAddr bss_segment_address, u32 bss_segment_size, bool is_crs) { 1093 bool is_crs) {
1076 1094
1077 ResultCode result = RebaseHeader(cro_size); 1095 ResultCode result = RebaseHeader(cro_size);
1078 if (result.IsError()) { 1096 if (result.IsError()) {
@@ -1088,9 +1106,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size,
1088 1106
1089 u32 prev_data_segment_address = 0; 1107 u32 prev_data_segment_address = 0;
1090 if (!is_crs) { 1108 if (!is_crs) {
1091 auto result_val = RebaseSegmentTable(cro_size, 1109 auto result_val = RebaseSegmentTable(cro_size, data_segment_addresss, data_segment_size,
1092 data_segment_addresss, data_segment_size, 1110 bss_segment_address, bss_segment_size);
1093 bss_segment_address, bss_segment_size);
1094 if (result_val.Failed()) { 1111 if (result_val.Failed()) {
1095 LOG_ERROR(Service_LDR, "Error rebasing segment table %08X", result_val.Code().raw); 1112 LOG_ERROR(Service_LDR, "Error rebasing segment table %08X", result_val.Code().raw);
1096 return result_val.Code(); 1113 return result_val.Code();
@@ -1374,7 +1391,8 @@ void CROHelper::Unregister(VAddr crs_address) {
1374 CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule()); 1391 CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule());
1375 CROHelper next(NextModule()), previous(PreviousModule()); 1392 CROHelper next(NextModule()), previous(PreviousModule());
1376 1393
1377 if (module_address == next_head.module_address || module_address == previous_head.module_address) { 1394 if (module_address == next_head.module_address ||
1395 module_address == previous_head.module_address) {
1378 // removing head 1396 // removing head
1379 if (next.module_address) { 1397 if (next.module_address) {
1380 // the next is new head 1398 // the next is new head
@@ -1400,7 +1418,8 @@ void CROHelper::Unregister(VAddr crs_address) {
1400 // let head's previous point to the new tail 1418 // let head's previous point to the new tail
1401 if (next_head.module_address && next_head.PreviousModule() == module_address) { 1419 if (next_head.module_address && next_head.PreviousModule() == module_address) {
1402 next_head.SetPreviousModule(previous.module_address); 1420 next_head.SetPreviousModule(previous.module_address);
1403 } else if (previous_head.module_address && previous_head.PreviousModule() == module_address) { 1421 } else if (previous_head.module_address &&
1422 previous_head.PreviousModule() == module_address) {
1404 previous_head.SetPreviousModule(previous.module_address); 1423 previous_head.SetPreviousModule(previous.module_address);
1405 } else { 1424 } else {
1406 UNREACHABLE(); 1425 UNREACHABLE();
@@ -1419,9 +1438,9 @@ u32 CROHelper::GetFixEnd(u32 fix_level) const {
1419 u32 entry_size_i = 2; 1438 u32 entry_size_i = 2;
1420 int field = ModuleNameOffset; 1439 int field = ModuleNameOffset;
1421 while (true) { 1440 while (true) {
1422 end = std::max<u32>(end, 1441 end = std::max<u32>(end, GetField(static_cast<HeaderField>(field)) +
1423 GetField(static_cast<HeaderField>(field)) + 1442 GetField(static_cast<HeaderField>(field + 1)) *
1424 GetField(static_cast<HeaderField>(field + 1)) * ENTRY_SIZE[entry_size_i]); 1443 ENTRY_SIZE[entry_size_i]);
1425 1444
1426 ++entry_size_i; 1445 ++entry_size_i;
1427 field += 2; 1446 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..6a0d0d3bf 100644
--- a/src/core/hle/service/ldr_ro/cro_helper.h
+++ b/src/core/hle/service/ldr_ro/cro_helper.h
@@ -6,12 +6,10 @@
6 6
7#include <array> 7#include <array>
8#include <tuple> 8#include <tuple>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "common/swap.h" 10#include "common/swap.h"
12
13#include "core/memory.h"
14#include "core/hle/result.h" 11#include "core/hle/result.h"
12#include "core/memory.h"
15 13
16//////////////////////////////////////////////////////////////////////////////////////////////////// 14////////////////////////////////////////////////////////////////////////////////////////////////////
17// Namespace LDR_RO 15// Namespace LDR_RO
@@ -21,14 +19,17 @@ namespace LDR_RO {
21// GCC versions < 5.0 do not implement std::is_trivially_copyable. 19// GCC versions < 5.0 do not implement std::is_trivially_copyable.
22// Excluding MSVC because it has weird behaviour for std::is_trivially_copyable. 20// Excluding MSVC because it has weird behaviour for std::is_trivially_copyable.
23#if (__GNUC__ >= 5) || defined(__clang__) 21#if (__GNUC__ >= 5) || defined(__clang__)
24 #define ASSERT_CRO_STRUCT(name, size) \ 22#define ASSERT_CRO_STRUCT(name, size) \
25 static_assert(std::is_standard_layout<name>::value, "CRO structure " #name " doesn't use standard layout"); \ 23 static_assert(std::is_standard_layout<name>::value, \
26 static_assert(std::is_trivially_copyable<name>::value, "CRO structure " #name " isn't trivially copyable"); \ 24 "CRO structure " #name " doesn't use standard layout"); \
27 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) 25 static_assert(std::is_trivially_copyable<name>::value, \
26 "CRO structure " #name " isn't trivially copyable"); \
27 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name)
28#else 28#else
29 #define ASSERT_CRO_STRUCT(name, size) \ 29#define ASSERT_CRO_STRUCT(name, size) \
30 static_assert(std::is_standard_layout<name>::value, "CRO structure " #name " doesn't use standard layout"); \ 30 static_assert(std::is_standard_layout<name>::value, \
31 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) 31 "CRO structure " #name " doesn't use standard layout"); \
32 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name)
32#endif 33#endif
33 34
34static constexpr u32 CRO_HEADER_SIZE = 0x138; 35static constexpr u32 CRO_HEADER_SIZE = 0x138;
@@ -37,8 +38,7 @@ static constexpr u32 CRO_HASH_SIZE = 0x80;
37/// Represents a loaded module (CRO) with interfaces manipulating it. 38/// Represents a loaded module (CRO) with interfaces manipulating it.
38class CROHelper final { 39class CROHelper final {
39public: 40public:
40 explicit CROHelper(VAddr cro_address) : module_address(cro_address) { 41 explicit CROHelper(VAddr cro_address) : module_address(cro_address) {}
41 }
42 42
43 std::string ModuleName() const { 43 std::string ModuleName() const {
44 return Memory::ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize)); 44 return Memory::ReadCString(GetField(ModuleNameOffset), GetField(ModuleNameSize));
@@ -59,9 +59,9 @@ public:
59 * @param is_crs true if the module itself is the static module 59 * @param is_crs true if the module itself is the static module
60 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 60 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
61 */ 61 */
62 ResultCode Rebase(VAddr crs_address, u32 cro_size, 62 ResultCode Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment_addresss,
63 VAddr data_segment_addresss, u32 data_segment_size, 63 u32 data_segment_size, VAddr bss_segment_address, u32 bss_segment_size,
64 VAddr bss_segment_address, u32 bss_segment_size, bool is_crs); 64 bool is_crs);
65 65
66 /** 66 /**
67 * Unrebases the module. 67 * Unrebases the module.
@@ -148,8 +148,9 @@ private:
148 const VAddr module_address; ///< the virtual address of this module 148 const VAddr module_address; ///< the virtual address of this module
149 149
150 /** 150 /**
151 * Each item in this enum represents a u32 field in the header begin from address+0x80, successively. 151 * 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. 152 * successively. We don't directly use a struct here, to avoid GetPointer, reinterpret_cast, or
153 * Read/WriteBlock repeatedly.
153 */ 154 */
154 enum HeaderField { 155 enum HeaderField {
155 Magic = 0, 156 Magic = 0,
@@ -208,18 +209,20 @@ private:
208 Fix2Barrier = ImportModuleTableOffset, 209 Fix2Barrier = ImportModuleTableOffset,
209 Fix1Barrier = StaticAnonymousSymbolTableOffset, 210 Fix1Barrier = StaticAnonymousSymbolTableOffset,
210 }; 211 };
211 static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4, "CRO Header fields are wrong!"); 212 static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4,
213 "CRO Header fields are wrong!");
212 214
213 enum class SegmentType : u32 { 215 enum class SegmentType : u32 {
214 Code = 0, 216 Code = 0,
215 ROData = 1, 217 ROData = 1,
216 Data = 2, 218 Data = 2,
217 BSS = 3, 219 BSS = 3,
218 }; 220 };
219 221
220 /** 222 /**
221 * Identifies a program location inside of a segment. 223 * 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. 224 * Required to refer to program locations because individual segments may be relocated
225 * independently of each other.
223 */ 226 */
224 union SegmentTag { 227 union SegmentTag {
225 u32_le raw; 228 u32_le raw;
@@ -282,7 +285,7 @@ private:
282 285
283 /// Identifies an indexed symbol imported from another module. 286 /// Identifies an indexed symbol imported from another module.
284 struct ImportIndexedSymbolEntry { 287 struct ImportIndexedSymbolEntry {
285 u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module 288 u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module
286 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable 289 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable
287 290
288 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportIndexedSymbolTableOffset; 291 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportIndexedSymbolTableOffset;
@@ -291,8 +294,8 @@ private:
291 294
292 /// Identifies an anonymous symbol imported from another module. 295 /// Identifies an anonymous symbol imported from another module.
293 struct ImportAnonymousSymbolEntry { 296 struct ImportAnonymousSymbolEntry {
294 SegmentTag symbol_position; // in the exporting segment 297 SegmentTag symbol_position; // in the exporting segment
295 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable 298 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable
296 299
297 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportAnonymousSymbolTableOffset; 300 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportAnonymousSymbolTableOffset;
298 }; 301 };
@@ -300,42 +303,47 @@ private:
300 303
301 /// Information of a imported module and symbols imported from it. 304 /// Information of a imported module and symbols imported from it.
302 struct ImportModuleEntry { 305 struct ImportModuleEntry {
303 u32_le name_offset; // pointing to a substring in ImportStrings 306 u32_le name_offset; // pointing to a substring in ImportStrings
304 u32_le import_indexed_symbol_table_offset; // pointing to a subtable in ImportIndexedSymbolTable 307 u32_le import_indexed_symbol_table_offset; // pointing to a subtable in
308 // ImportIndexedSymbolTable
305 u32_le import_indexed_symbol_num; 309 u32_le import_indexed_symbol_num;
306 u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in ImportAnonymousSymbolTable 310 u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in
311 // ImportAnonymousSymbolTable
307 u32_le import_anonymous_symbol_num; 312 u32_le import_anonymous_symbol_num;
308 313
309 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset; 314 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset;
310 315
311 void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) { 316 void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) {
312 Memory::ReadBlock(import_indexed_symbol_table_offset + index * sizeof(ImportIndexedSymbolEntry), 317 Memory::ReadBlock(import_indexed_symbol_table_offset +
313 &entry, sizeof(ImportIndexedSymbolEntry)); 318 index * sizeof(ImportIndexedSymbolEntry),
319 &entry, sizeof(ImportIndexedSymbolEntry));
314 } 320 }
315 321
316 void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) { 322 void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) {
317 Memory::ReadBlock(import_anonymous_symbol_table_offset + index * sizeof(ImportAnonymousSymbolEntry), 323 Memory::ReadBlock(import_anonymous_symbol_table_offset +
318 &entry, sizeof(ImportAnonymousSymbolEntry)); 324 index * sizeof(ImportAnonymousSymbolEntry),
325 &entry, sizeof(ImportAnonymousSymbolEntry));
319 } 326 }
320 }; 327 };
321 ASSERT_CRO_STRUCT(ImportModuleEntry, 20); 328 ASSERT_CRO_STRUCT(ImportModuleEntry, 20);
322 329
323 enum class RelocationType : u8 { 330 enum class RelocationType : u8 {
324 Nothing = 0, 331 Nothing = 0,
325 AbsoluteAddress = 2, 332 AbsoluteAddress = 2,
326 RelativeAddress = 3, 333 RelativeAddress = 3,
327 ThumbBranch = 10, 334 ThumbBranch = 10,
328 ArmBranch = 28, 335 ArmBranch = 28,
329 ModifyArmBranch = 29, 336 ModifyArmBranch = 29,
330 AbsoluteAddress2 = 38, 337 AbsoluteAddress2 = 38,
331 AlignedRelativeAddress = 42, 338 AlignedRelativeAddress = 42,
332 }; 339 };
333 340
334 struct RelocationEntry { 341 struct RelocationEntry {
335 SegmentTag target_position; // to self's segment as an ExternalRelocationEntry; to static module segment as a StaticRelocationEntry 342 SegmentTag target_position; // to self's segment as an ExternalRelocationEntry; to static
343 // module segment as a StaticRelocationEntry
336 RelocationType type; 344 RelocationType type;
337 u8 is_batch_end; 345 u8 is_batch_end;
338 u8 is_batch_resolved; // set at a batch beginning if the batch is resolved 346 u8 is_batch_resolved; // set at a batch beginning if the batch is resolved
339 INSERT_PADDING_BYTES(1); 347 INSERT_PADDING_BYTES(1);
340 u32_le addend; 348 u32_le addend;
341 }; 349 };
@@ -366,8 +374,8 @@ private:
366 374
367 /// Identifies a special static anonymous symbol (no game is known using this). 375 /// Identifies a special static anonymous symbol (no game is known using this).
368 struct StaticAnonymousSymbolEntry { 376 struct StaticAnonymousSymbolEntry {
369 SegmentTag symbol_position; // to self's segment 377 SegmentTag symbol_position; // to self's segment
370 u32_le relocation_batch_offset; // pointing to a relocation batch in StaticRelocationTable 378 u32_le relocation_batch_offset; // pointing to a relocation batch in StaticRelocationTable
371 379
372 static constexpr HeaderField TABLE_OFFSET_FIELD = StaticAnonymousSymbolTableOffset; 380 static constexpr HeaderField TABLE_OFFSET_FIELD = StaticAnonymousSymbolTableOffset;
373 }; 381 };
@@ -446,12 +454,15 @@ private:
446 } 454 }
447 455
448 /** 456 /**
449 * A helper function iterating over all registered auto-link modules, including the static module. 457 * A helper function iterating over all registered auto-link modules, including the static
458 * module.
450 * @param crs_address the virtual address of the static module 459 * @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 460 * @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, 461 * CROHelper and returns ResultVal<bool>. It should return true to continue the
462 * iteration,
453 * false to stop the iteration, or an error code (which will also stop the iteration). 463 * 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, 464 * @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration
465 * success,
455 * otherwise error code of the last iteration. 466 * otherwise error code of the last iteration.
456 */ 467 */
457 template <typename FunctionObject> 468 template <typename FunctionObject>
@@ -477,8 +488,8 @@ private:
477 * Usually equals to target_address, but will be different for a target in .data segment 488 * 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. 489 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
479 */ 490 */
480 ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type, 491 ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type, u32 addend,
481 u32 addend, u32 symbol_address, u32 target_future_address); 492 u32 symbol_address, u32 target_future_address);
482 493
483 /** 494 /**
484 * Clears a relocation to zero 495 * Clears a relocation to zero
@@ -492,7 +503,8 @@ private:
492 * Applies or resets a batch of relocations 503 * Applies or resets a batch of relocations
493 * @param batch the virtual address of the first relocation in the batch 504 * @param batch the virtual address of the first relocation in the batch
494 * @param symbol_address the symbol address to be relocated with 505 * @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 506 * @param reset false to set the batch to resolved state, true to reset the batch to unresolved
507 * state
496 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 508 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
497 */ 509 */
498 ResultCode ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset = false); 510 ResultCode ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset = false);
@@ -507,7 +519,8 @@ private:
507 /** 519 /**
508 * Rebases offsets in module header according to module address. 520 * Rebases offsets in module header according to module address.
509 * @param cro_size the size of the CRO file 521 * @param cro_size the size of the CRO file
510 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 522 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
523 * code.
511 */ 524 */
512 ResultCode RebaseHeader(u32 cro_size); 525 ResultCode RebaseHeader(u32 cro_size);
513 526
@@ -520,43 +533,49 @@ private:
520 * @param bss_segment_size the buffer size for .bss segment 533 * @param bss_segment_size the buffer size for .bss segment
521 * @returns ResultVal<VAddr> with the virtual address of .data segment in CRO. 534 * @returns ResultVal<VAddr> with the virtual address of .data segment in CRO.
522 */ 535 */
523 ResultVal<VAddr> RebaseSegmentTable(u32 cro_size, 536 ResultVal<VAddr> RebaseSegmentTable(u32 cro_size, VAddr data_segment_address,
524 VAddr data_segment_address, u32 data_segment_size, 537 u32 data_segment_size, VAddr bss_segment_address,
525 VAddr bss_segment_address, u32 bss_segment_size); 538 u32 bss_segment_size);
526 539
527 /** 540 /**
528 * Rebases offsets in exported named symbol table according to module address. 541 * 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. 542 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
543 * code.
530 */ 544 */
531 ResultCode RebaseExportNamedSymbolTable(); 545 ResultCode RebaseExportNamedSymbolTable();
532 546
533 /** 547 /**
534 * Verifies indices in export tree table. 548 * Verifies indices in export tree table.
535 * @returns ResultCode RESULT_SUCCESS if all indices are verified as valid, otherwise error code. 549 * @returns ResultCode RESULT_SUCCESS if all indices are verified as valid, otherwise error
550 * code.
536 */ 551 */
537 ResultCode VerifyExportTreeTable() const; 552 ResultCode VerifyExportTreeTable() const;
538 553
539 /** 554 /**
540 * Rebases offsets in exported module table according to module address. 555 * 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. 556 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
557 * code.
542 */ 558 */
543 ResultCode RebaseImportModuleTable(); 559 ResultCode RebaseImportModuleTable();
544 560
545 /** 561 /**
546 * Rebases offsets in imported named symbol table according to module address. 562 * 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. 563 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
564 * code.
548 */ 565 */
549 ResultCode RebaseImportNamedSymbolTable(); 566 ResultCode RebaseImportNamedSymbolTable();
550 567
551 /** 568 /**
552 * Rebases offsets in imported indexed symbol table according to module address. 569 * 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. 570 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
571 * code.
554 */ 572 */
555 ResultCode RebaseImportIndexedSymbolTable(); 573 ResultCode RebaseImportIndexedSymbolTable();
556 574
557 /** 575 /**
558 * Rebases offsets in imported anonymous symbol table according to module address. 576 * 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. 577 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
578 * code.
560 */ 579 */
561 ResultCode RebaseImportAnonymousSymbolTable(); 580 ResultCode RebaseImportAnonymousSymbolTable();
562 581
@@ -621,7 +640,8 @@ private:
621 void UnrebaseHeader(); 640 void UnrebaseHeader();
622 641
623 /** 642 /**
624 * Looks up all imported named symbols of this module in all registered auto-link modules, and resolves them if found. 643 * Looks up all imported named symbols of this module in all registered auto-link modules, and
644 * resolves them if found.
625 * @param crs_address the virtual address of the static module 645 * @param crs_address the virtual address of the static module
626 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 646 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
627 */ 647 */
@@ -646,7 +666,8 @@ private:
646 ResultCode ResetImportAnonymousSymbol(); 666 ResultCode ResetImportAnonymousSymbol();
647 667
648 /** 668 /**
649 * Finds registered auto-link modules that this module imports, and resolves indexed and anonymous symbols exported by them. 669 * Finds registered auto-link modules that this module imports, and resolves indexed and
670 * anonymous symbols exported by them.
650 * @param crs_address the virtual address of the static module 671 * @param crs_address the virtual address of the static module
651 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 672 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
652 */ 673 */
@@ -667,7 +688,8 @@ private:
667 ResultCode ResetExportNamedSymbol(CROHelper target); 688 ResultCode ResetExportNamedSymbol(CROHelper target);
668 689
669 /** 690 /**
670 * Resolves imported indexed and anonymous symbols in the target module which imports this module. 691 * Resolves imported indexed and anonymous symbols in the target module which imports this
692 * module.
671 * @param target the module to resolve. 693 * @param target the module to resolve.
672 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 694 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
673 */ 695 */
diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp
index 8ba73ea8d..ec183d1f5 100644
--- a/src/core/hle/service/ldr_ro/ldr_ro.cpp
+++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp
@@ -5,7 +5,6 @@
5#include "common/alignment.h" 5#include "common/alignment.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8
9#include "core/arm/arm_interface.h" 8#include "core/arm/arm_interface.h"
10#include "core/hle/kernel/process.h" 9#include "core/hle/kernel/process.h"
11#include "core/hle/kernel/vm_manager.h" 10#include "core/hle/kernel/vm_manager.h"
@@ -18,24 +17,33 @@
18 17
19namespace LDR_RO { 18namespace LDR_RO {
20 19
21static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9 20static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9
22 ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent); 21 ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal,
23static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8 22 ErrorLevel::Permanent);
24 ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent); 23static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8
25static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F 24 ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal,
26 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 25 ErrorLevel::Permanent);
27static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1 26static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F
28 ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 27 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument,
29static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2 28 ErrorLevel::Usage);
30 ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 29static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1
31static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F 30 ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument,
32 ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Usage); 31 ErrorLevel::Permanent);
33static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08 32static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2
34 ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent); 33 ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument,
35static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D 34 ErrorLevel::Permanent);
36 ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent); 35static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F
37static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830 36 ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal,
38 ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 37 ErrorLevel::Usage);
38static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08
39 ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState,
40 ErrorLevel::Permanent);
41static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D
42 ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState,
43 ErrorLevel::Permanent);
44static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830
45 ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
46 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
39 47
40static MemorySynchronizer memory_synchronizer; 48static MemorySynchronizer memory_synchronizer;
41 49
@@ -44,10 +52,10 @@ static VAddr loaded_crs; ///< the virtual address of the static module
44 52
45static bool VerifyBufferState(VAddr buffer_ptr, u32 size) { 53static bool VerifyBufferState(VAddr buffer_ptr, u32 size) {
46 auto vma = Kernel::g_current_process->vm_manager.FindVMA(buffer_ptr); 54 auto vma = Kernel::g_current_process->vm_manager.FindVMA(buffer_ptr);
47 return vma != Kernel::g_current_process->vm_manager.vma_map.end() 55 return vma != Kernel::g_current_process->vm_manager.vma_map.end() &&
48 && vma->second.base + vma->second.size >= buffer_ptr + size 56 vma->second.base + vma->second.size >= buffer_ptr + size &&
49 && vma->second.permissions == Kernel::VMAPermission::ReadWrite 57 vma->second.permissions == Kernel::VMAPermission::ReadWrite &&
50 && vma->second.meminfo_state == Kernel::MemoryState::Private; 58 vma->second.meminfo_state == Kernel::MemoryState::Private;
51} 59}
52 60
53/** 61/**
@@ -66,13 +74,14 @@ static bool VerifyBufferState(VAddr buffer_ptr, u32 size) {
66static void Initialize(Service::Interface* self) { 74static void Initialize(Service::Interface* self) {
67 u32* cmd_buff = Kernel::GetCommandBuffer(); 75 u32* cmd_buff = Kernel::GetCommandBuffer();
68 VAddr crs_buffer_ptr = cmd_buff[1]; 76 VAddr crs_buffer_ptr = cmd_buff[1];
69 u32 crs_size = cmd_buff[2]; 77 u32 crs_size = cmd_buff[2];
70 VAddr crs_address = cmd_buff[3]; 78 VAddr crs_address = cmd_buff[3];
71 u32 descriptor = cmd_buff[4]; 79 u32 descriptor = cmd_buff[4];
72 u32 process = cmd_buff[5]; 80 u32 process = cmd_buff[5];
73 81
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", 82 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); 83 "descriptor=0x%08X, process=0x%08X",
84 crs_buffer_ptr, crs_address, crs_size, descriptor, process);
76 85
77 if (descriptor != 0) { 86 if (descriptor != 0) {
78 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 87 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -119,7 +128,8 @@ static void Initialize(Service::Interface* self) {
119 return; 128 return;
120 } 129 }
121 130
122 if (crs_address < Memory::PROCESS_IMAGE_VADDR || crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) { 131 if (crs_address < Memory::PROCESS_IMAGE_VADDR ||
132 crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) {
123 LOG_ERROR(Service_LDR, "CRS mapping address is not in the process image region"); 133 LOG_ERROR(Service_LDR, "CRS mapping address is not in the process image region");
124 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; 134 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw;
125 return; 135 return;
@@ -131,14 +141,17 @@ static void Initialize(Service::Interface* self) {
131 // TODO(wwylele): should be memory aliasing 141 // TODO(wwylele): should be memory aliasing
132 std::shared_ptr<std::vector<u8>> crs_mem = std::make_shared<std::vector<u8>>(crs_size); 142 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); 143 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(); 144 result = Kernel::g_current_process->vm_manager
145 .MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code)
146 .Code();
135 if (result.IsError()) { 147 if (result.IsError()) {
136 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); 148 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw);
137 cmd_buff[1] = result.raw; 149 cmd_buff[1] = result.raw;
138 return; 150 return;
139 } 151 }
140 152
141 result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size, Kernel::VMAPermission::Read); 153 result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size,
154 Kernel::VMAPermission::Read);
142 if (result.IsError()) { 155 if (result.IsError()) {
143 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); 156 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
144 cmd_buff[1] = result.raw; 157 cmd_buff[1] = result.raw;
@@ -186,9 +199,9 @@ static void Initialize(Service::Interface* self) {
186static void LoadCRR(Service::Interface* self) { 199static void LoadCRR(Service::Interface* self) {
187 u32* cmd_buff = Kernel::GetCommandBuffer(); 200 u32* cmd_buff = Kernel::GetCommandBuffer();
188 u32 crr_buffer_ptr = cmd_buff[1]; 201 u32 crr_buffer_ptr = cmd_buff[1];
189 u32 crr_size = cmd_buff[2]; 202 u32 crr_size = cmd_buff[2];
190 u32 descriptor = cmd_buff[3]; 203 u32 descriptor = cmd_buff[3];
191 u32 process = cmd_buff[4]; 204 u32 process = cmd_buff[4];
192 205
193 if (descriptor != 0) { 206 if (descriptor != 0) {
194 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 207 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -200,7 +213,8 @@ static void LoadCRR(Service::Interface* self) {
200 cmd_buff[0] = IPC::MakeHeader(2, 1, 0); 213 cmd_buff[0] = IPC::MakeHeader(2, 1, 0);
201 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 214 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
202 215
203 LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, descriptor=0x%08X, process=0x%08X", 216 LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, "
217 "descriptor=0x%08X, process=0x%08X",
204 crr_buffer_ptr, crr_size, descriptor, process); 218 crr_buffer_ptr, crr_size, descriptor, process);
205} 219}
206 220
@@ -218,8 +232,8 @@ static void LoadCRR(Service::Interface* self) {
218static void UnloadCRR(Service::Interface* self) { 232static void UnloadCRR(Service::Interface* self) {
219 u32* cmd_buff = Kernel::GetCommandBuffer(); 233 u32* cmd_buff = Kernel::GetCommandBuffer();
220 u32 crr_buffer_ptr = cmd_buff[1]; 234 u32 crr_buffer_ptr = cmd_buff[1];
221 u32 descriptor = cmd_buff[2]; 235 u32 descriptor = cmd_buff[2];
222 u32 process = cmd_buff[3]; 236 u32 process = cmd_buff[3];
223 237
224 if (descriptor != 0) { 238 if (descriptor != 0) {
225 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 239 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -231,7 +245,8 @@ static void UnloadCRR(Service::Interface* self) {
231 cmd_buff[0] = IPC::MakeHeader(3, 1, 0); 245 cmd_buff[0] = IPC::MakeHeader(3, 1, 0);
232 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 246 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
233 247
234 LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", 248 LOG_WARNING(Service_LDR,
249 "(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X",
235 crr_buffer_ptr, descriptor, process); 250 crr_buffer_ptr, descriptor, process);
236} 251}
237 252
@@ -263,27 +278,28 @@ static void UnloadCRR(Service::Interface* self) {
263 */ 278 */
264static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { 279static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
265 u32* cmd_buff = Kernel::GetCommandBuffer(); 280 u32* cmd_buff = Kernel::GetCommandBuffer();
266 VAddr cro_buffer_ptr = cmd_buff[1]; 281 VAddr cro_buffer_ptr = cmd_buff[1];
267 VAddr cro_address = cmd_buff[2]; 282 VAddr cro_address = cmd_buff[2];
268 u32 cro_size = cmd_buff[3]; 283 u32 cro_size = cmd_buff[3];
269 VAddr data_segment_address = cmd_buff[4]; 284 VAddr data_segment_address = cmd_buff[4];
270 u32 zero = cmd_buff[5]; 285 u32 zero = cmd_buff[5];
271 u32 data_segment_size = cmd_buff[6]; 286 u32 data_segment_size = cmd_buff[6];
272 u32 bss_segment_address = cmd_buff[7]; 287 u32 bss_segment_address = cmd_buff[7];
273 u32 bss_segment_size = cmd_buff[8]; 288 u32 bss_segment_size = cmd_buff[8];
274 bool auto_link = (cmd_buff[9] & 0xFF) != 0; 289 bool auto_link = (cmd_buff[9] & 0xFF) != 0;
275 u32 fix_level = cmd_buff[10]; 290 u32 fix_level = cmd_buff[10];
276 VAddr crr_address = cmd_buff[11]; 291 VAddr crr_address = cmd_buff[11];
277 u32 descriptor = cmd_buff[12]; 292 u32 descriptor = cmd_buff[12];
278 u32 process = cmd_buff[13]; 293 u32 process = cmd_buff[13];
279 294
280 LOG_DEBUG(Service_LDR, "called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, " 295 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, " 296 "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", 297 "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, 298 "bss_segment_address=0x%08X, bss_segment_size=0x%X, "
284 data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size, 299 "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 300 link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size,
286 ); 301 data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size,
302 auto_link ? "true" : "false", fix_level, crr_address, descriptor, process);
287 303
288 if (descriptor != 0) { 304 if (descriptor != 0) {
289 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 305 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -330,8 +346,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
330 return; 346 return;
331 } 347 }
332 348
333 if (cro_address < Memory::PROCESS_IMAGE_VADDR 349 if (cro_address < Memory::PROCESS_IMAGE_VADDR ||
334 || cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) { 350 cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) {
335 LOG_ERROR(Service_LDR, "CRO mapping address is not in the process image region"); 351 LOG_ERROR(Service_LDR, "CRO mapping address is not in the process image region");
336 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; 352 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw;
337 return; 353 return;
@@ -339,7 +355,9 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
339 355
340 if (zero) { 356 if (zero) {
341 LOG_ERROR(Service_LDR, "Zero is not zero %d", zero); 357 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; 358 cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO,
359 ErrorSummary::Internal, ErrorLevel::Usage)
360 .raw;
343 return; 361 return;
344 } 362 }
345 363
@@ -349,14 +367,17 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
349 // TODO(wwylele): should be memory aliasing 367 // TODO(wwylele): should be memory aliasing
350 std::shared_ptr<std::vector<u8>> cro_mem = std::make_shared<std::vector<u8>>(cro_size); 368 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); 369 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(); 370 result = Kernel::g_current_process->vm_manager
371 .MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code)
372 .Code();
353 if (result.IsError()) { 373 if (result.IsError()) {
354 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); 374 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw);
355 cmd_buff[1] = result.raw; 375 cmd_buff[1] = result.raw;
356 return; 376 return;
357 } 377 }
358 378
359 result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size, Kernel::VMAPermission::Read); 379 result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size,
380 Kernel::VMAPermission::Read);
360 if (result.IsError()) { 381 if (result.IsError()) {
361 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); 382 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
362 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); 383 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
@@ -384,7 +405,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
384 return; 405 return;
385 } 406 }
386 407
387 result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size, bss_segment_address, bss_segment_size, false); 408 result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size,
409 bss_segment_address, bss_segment_size, false);
388 if (result.IsError()) { 410 if (result.IsError()) {
389 LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw); 411 LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw);
390 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); 412 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
@@ -409,7 +431,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
409 // TODO(wwylele): verify the behaviour when buffer_ptr == address 431 // TODO(wwylele): verify the behaviour when buffer_ptr == address
410 if (cro_buffer_ptr != cro_address) { 432 if (cro_buffer_ptr != cro_address) {
411 if (fix_size != cro_size) { 433 if (fix_size != cro_size) {
412 result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size, cro_size - fix_size); 434 result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size,
435 cro_size - fix_size);
413 if (result.IsError()) { 436 if (result.IsError()) {
414 LOG_ERROR(Service_LDR, "Error unmapping memory block %08X", result.raw); 437 LOG_ERROR(Service_LDR, "Error unmapping memory block %08X", result.raw);
415 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); 438 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
@@ -426,7 +449,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
426 u32 exe_size; 449 u32 exe_size;
427 std::tie(exe_begin, exe_size) = cro.GetExecutablePages(); 450 std::tie(exe_begin, exe_size) = cro.GetExecutablePages();
428 if (exe_begin) { 451 if (exe_begin) {
429 result = Kernel::g_current_process->vm_manager.ReprotectRange(exe_begin, exe_size, Kernel::VMAPermission::ReadExecute); 452 result = Kernel::g_current_process->vm_manager.ReprotectRange(
453 exe_begin, exe_size, Kernel::VMAPermission::ReadExecute);
430 if (result.IsError()) { 454 if (result.IsError()) {
431 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); 455 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
432 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fix_size); 456 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fix_size);
@@ -437,8 +461,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
437 461
438 Core::g_app_core->ClearInstructionCache(); 462 Core::g_app_core->ClearInstructionCache();
439 463
440 LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", 464 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); 465 cro_address, cro_address + fix_size);
442 466
443 cmd_buff[1] = RESULT_SUCCESS.raw; 467 cmd_buff[1] = RESULT_SUCCESS.raw;
444 cmd_buff[2] = fix_size; 468 cmd_buff[2] = fix_size;
@@ -464,14 +488,15 @@ static void LoadCRO(Service::Interface* self) {
464 */ 488 */
465static void UnloadCRO(Service::Interface* self) { 489static void UnloadCRO(Service::Interface* self) {
466 u32* cmd_buff = Kernel::GetCommandBuffer(); 490 u32* cmd_buff = Kernel::GetCommandBuffer();
467 VAddr cro_address = cmd_buff[1]; 491 VAddr cro_address = cmd_buff[1];
468 u32 zero = cmd_buff[2]; 492 u32 zero = cmd_buff[2];
469 VAddr cro_buffer_ptr = cmd_buff[3]; 493 VAddr cro_buffer_ptr = cmd_buff[3];
470 u32 descriptor = cmd_buff[4]; 494 u32 descriptor = cmd_buff[4];
471 u32 process = cmd_buff[5]; 495 u32 process = cmd_buff[5];
472 496
473 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", 497 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); 498 "descriptor=0x%08X, process=0x%08X",
499 cro_address, zero, cro_buffer_ptr, descriptor, process);
475 500
476 if (descriptor != 0) { 501 if (descriptor != 0) {
477 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 502 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -558,11 +583,11 @@ static void UnloadCRO(Service::Interface* self) {
558static void LinkCRO(Service::Interface* self) { 583static void LinkCRO(Service::Interface* self) {
559 u32* cmd_buff = Kernel::GetCommandBuffer(); 584 u32* cmd_buff = Kernel::GetCommandBuffer();
560 VAddr cro_address = cmd_buff[1]; 585 VAddr cro_address = cmd_buff[1];
561 u32 descriptor = cmd_buff[2]; 586 u32 descriptor = cmd_buff[2];
562 u32 process = cmd_buff[3]; 587 u32 process = cmd_buff[3];
563 588
564 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", 589 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X",
565 cro_address, descriptor, process); 590 cro_address, descriptor, process);
566 591
567 if (descriptor != 0) { 592 if (descriptor != 0) {
568 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 593 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -620,11 +645,11 @@ static void LinkCRO(Service::Interface* self) {
620static void UnlinkCRO(Service::Interface* self) { 645static void UnlinkCRO(Service::Interface* self) {
621 u32* cmd_buff = Kernel::GetCommandBuffer(); 646 u32* cmd_buff = Kernel::GetCommandBuffer();
622 VAddr cro_address = cmd_buff[1]; 647 VAddr cro_address = cmd_buff[1];
623 u32 descriptor = cmd_buff[2]; 648 u32 descriptor = cmd_buff[2];
624 u32 process = cmd_buff[3]; 649 u32 process = cmd_buff[3];
625 650
626 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", 651 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X",
627 cro_address, descriptor, process); 652 cro_address, descriptor, process);
628 653
629 if (descriptor != 0) { 654 if (descriptor != 0) {
630 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 655 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -682,11 +707,11 @@ static void UnlinkCRO(Service::Interface* self) {
682static void Shutdown(Service::Interface* self) { 707static void Shutdown(Service::Interface* self) {
683 u32* cmd_buff = Kernel::GetCommandBuffer(); 708 u32* cmd_buff = Kernel::GetCommandBuffer();
684 VAddr crs_buffer_ptr = cmd_buff[1]; 709 VAddr crs_buffer_ptr = cmd_buff[1];
685 u32 descriptor = cmd_buff[2]; 710 u32 descriptor = cmd_buff[2];
686 u32 process = cmd_buff[3]; 711 u32 process = cmd_buff[3];
687 712
688 LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", 713 LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X",
689 crs_buffer_ptr, descriptor, process); 714 crs_buffer_ptr, descriptor, process);
690 715
691 if (descriptor != 0) { 716 if (descriptor != 0) {
692 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 717 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -724,15 +749,17 @@ static void Shutdown(Service::Interface* self) {
724} 749}
725 750
726const Interface::FunctionInfo FunctionTable[] = { 751const Interface::FunctionInfo FunctionTable[] = {
727 {0x000100C2, Initialize, "Initialize"}, 752 // clang-format off
728 {0x00020082, LoadCRR, "LoadCRR"}, 753 {0x000100C2, Initialize, "Initialize"},
729 {0x00030042, UnloadCRR, "UnloadCRR"}, 754 {0x00020082, LoadCRR, "LoadCRR"},
730 {0x000402C2, LoadCRO<false>, "LoadCRO"}, 755 {0x00030042, UnloadCRR, "UnloadCRR"},
731 {0x000500C2, UnloadCRO, "UnloadCRO"}, 756 {0x000402C2, LoadCRO<false>, "LoadCRO"},
732 {0x00060042, LinkCRO, "LinkCRO"}, 757 {0x000500C2, UnloadCRO, "UnloadCRO"},
733 {0x00070042, UnlinkCRO, "UnlinkCRO"}, 758 {0x00060042, LinkCRO, "LinkCRO"},
734 {0x00080042, Shutdown, "Shutdown"}, 759 {0x00070042, UnlinkCRO, "UnlinkCRO"},
735 {0x000902C2, LoadCRO<true>, "LoadCRO_New"}, 760 {0x00080042, Shutdown, "Shutdown"},
761 {0x000902C2, LoadCRO<true>, "LoadCRO_New"},
762 // clang-format on
736}; 763};
737 764
738//////////////////////////////////////////////////////////////////////////////////////////////////// 765////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ldr_ro/memory_synchronizer.cpp b/src/core/hle/service/ldr_ro/memory_synchronizer.cpp
index 4402876e6..989887264 100644
--- a/src/core/hle/service/ldr_ro/memory_synchronizer.cpp
+++ b/src/core/hle/service/ldr_ro/memory_synchronizer.cpp
@@ -3,9 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6
7#include "common/assert.h" 6#include "common/assert.h"
8
9#include "core/hle/service/ldr_ro/memory_synchronizer.h" 7#include "core/hle/service/ldr_ro/memory_synchronizer.h"
10 8
11//////////////////////////////////////////////////////////////////////////////////////////////////// 9////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -14,9 +12,8 @@
14namespace LDR_RO { 12namespace LDR_RO {
15 13
16auto MemorySynchronizer::FindMemoryBlock(VAddr mapping, VAddr original) { 14auto MemorySynchronizer::FindMemoryBlock(VAddr mapping, VAddr original) {
17 auto block = std::find_if(memory_blocks.begin(), memory_blocks.end(), [=](MemoryBlock& b){ 15 auto block = std::find_if(memory_blocks.begin(), memory_blocks.end(),
18 return b.original == original; 16 [=](MemoryBlock& b) { return b.original == original; });
19 });
20 ASSERT(block->mapping == mapping); 17 ASSERT(block->mapping == mapping);
21 return block; 18 return block;
22} 19}
diff --git a/src/core/hle/service/ldr_ro/memory_synchronizer.h b/src/core/hle/service/ldr_ro/memory_synchronizer.h
index 92f267912..883ee4acf 100644
--- a/src/core/hle/service/ldr_ro/memory_synchronizer.h
+++ b/src/core/hle/service/ldr_ro/memory_synchronizer.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <vector> 7#include <vector>
8
9#include "core/memory.h" 8#include "core/memory.h"
10 9
11//////////////////////////////////////////////////////////////////////////////////////////////////// 10////////////////////////////////////////////////////////////////////////////////////////////////////
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..5eb97f0d3 100644
--- a/src/core/hle/service/ndm/ndm.cpp
+++ b/src/core/hle/service/ndm/ndm.cpp
@@ -4,21 +4,23 @@
4 4
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#include "core/hle/service/service.h"
8#include "core/hle/service/ndm/ndm.h" 7#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 {
15 DEFAULT_RETRY_INTERVAL = 10, 15 DEFAULT_RETRY_INTERVAL = 10,
16 DEFAULT_SCAN_INTERVAL = 30 16 DEFAULT_SCAN_INTERVAL = 30,
17}; 17};
18 18
19static DaemonMask daemon_bit_mask = DaemonMask::Default; 19static DaemonMask daemon_bit_mask = DaemonMask::Default;
20static DaemonMask default_daemon_bit_mask = DaemonMask::Default; 20static DaemonMask default_daemon_bit_mask = DaemonMask::Default;
21static std::array<DaemonStatus, 4> daemon_status = { DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle }; 21static std::array<DaemonStatus, 4> daemon_status = {
22 DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle,
23};
22static ExclusiveState exclusive_state = ExclusiveState::None; 24static ExclusiveState exclusive_state = ExclusiveState::None;
23static u32 scan_interval = DEFAULT_SCAN_INTERVAL; 25static u32 scan_interval = DEFAULT_SCAN_INTERVAL;
24static u32 retry_interval = DEFAULT_RETRY_INTERVAL; 26static u32 retry_interval = DEFAULT_RETRY_INTERVAL;
@@ -72,7 +74,8 @@ void UnlockState(Service::Interface* self) {
72void SuspendDaemons(Service::Interface* self) { 74void SuspendDaemons(Service::Interface* self) {
73 u32* cmd_buff = Kernel::GetCommandBuffer(); 75 u32* cmd_buff = Kernel::GetCommandBuffer();
74 u32 bit_mask = cmd_buff[1] & 0xF; 76 u32 bit_mask = cmd_buff[1] & 0xF;
75 daemon_bit_mask = static_cast<DaemonMask>(static_cast<u32>(default_daemon_bit_mask) & ~bit_mask); 77 daemon_bit_mask =
78 static_cast<DaemonMask>(static_cast<u32>(default_daemon_bit_mask) & ~bit_mask);
76 for (size_t index = 0; index < daemon_status.size(); ++index) { 79 for (size_t index = 0; index < daemon_status.size(); ++index) {
77 if (bit_mask & (1 << index)) { 80 if (bit_mask & (1 << index)) {
78 daemon_status[index] = DaemonStatus::Suspended; 81 daemon_status[index] = DaemonStatus::Suspended;
@@ -228,9 +231,7 @@ void Init() {
228 AddService(new NDM_U_Interface); 231 AddService(new NDM_U_Interface);
229} 232}
230 233
231void Shutdown() { 234void Shutdown() {}
232
233}
234 235
235}// namespace NDM 236} // namespace NDM
236}// namespace Service 237} // namespace Service
diff --git a/src/core/hle/service/ndm/ndm.h b/src/core/hle/service/ndm/ndm.h
index 5c2b968dc..979e7fcf1 100644
--- a/src/core/hle/service/ndm/ndm.h
+++ b/src/core/hle/service/ndm/ndm.h
@@ -13,35 +13,30 @@ class Interface;
13namespace NDM { 13namespace NDM {
14 14
15enum class Daemon : u32 { 15enum class Daemon : u32 {
16 Cec = 0, 16 Cec = 0,
17 Boss = 1, 17 Boss = 1,
18 Nim = 2, 18 Nim = 2,
19 Friend = 3 19 Friend = 3,
20}; 20};
21 21
22enum class DaemonMask : u32 { 22enum class DaemonMask : u32 {
23 None = 0, 23 None = 0,
24 Cec = (1 << static_cast<u32>(Daemon::Cec)), 24 Cec = (1 << static_cast<u32>(Daemon::Cec)),
25 Boss = (1 << static_cast<u32>(Daemon::Boss)), 25 Boss = (1 << static_cast<u32>(Daemon::Boss)),
26 Nim = (1 << static_cast<u32>(Daemon::Nim)), 26 Nim = (1 << static_cast<u32>(Daemon::Nim)),
27 Friend = (1 << static_cast<u32>(Daemon::Friend)), 27 Friend = (1 << static_cast<u32>(Daemon::Friend)),
28 Default = Cec | Friend, 28 Default = Cec | Friend,
29 All = Cec | Boss | Nim | Friend 29 All = Cec | Boss | Nim | Friend,
30}; 30};
31 31
32enum class DaemonStatus : u32 { 32enum 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 33
39enum class ExclusiveState : u32 { 34enum class ExclusiveState : u32 {
40 None = 0, 35 None = 0,
41 Infrastructure = 1, 36 Infrastructure = 1,
42 LocalCommunications = 2, 37 LocalCommunications = 2,
43 Streetpass = 3, 38 Streetpass = 3,
44 StreetpassData = 4, 39 StreetpassData = 4,
45}; 40};
46 41
47/** 42/**
@@ -205,7 +200,6 @@ void SetRetryInterval(Service::Interface* self);
205 */ 200 */
206void GetRetryInterval(Service::Interface* self); 201void GetRetryInterval(Service::Interface* self);
207 202
208
209/** 203/**
210 * NDM::OverrideDefaultDaemons service function 204 * NDM::OverrideDefaultDaemons service function
211 * Inputs: 205 * Inputs:
@@ -233,7 +227,8 @@ void ResetDefaultDaemons(Service::Interface* self);
233 * 1 : Result, 0 on success, otherwise error code 227 * 1 : Result, 0 on success, otherwise error code
234 * 2 : Daemon bit mask 228 * 2 : Daemon bit mask
235 * Note: 229 * Note:
236 * Gets the current default daemon bit mask. The default value is (DAEMONMASK_CEC | DAEMONMASK_FRIENDS) 230 * Gets the current default daemon bit mask. The default value is (DAEMONMASK_CEC |
231 * DAEMONMASK_FRIENDS)
237 */ 232 */
238void GetDefaultDaemons(Service::Interface* self); 233void GetDefaultDaemons(Service::Interface* self);
239 234
@@ -252,5 +247,5 @@ void Init();
252/// Shutdown NDM service 247/// Shutdown NDM service
253void Shutdown(); 248void Shutdown();
254 249
255}// namespace NDM 250} // namespace NDM
256}// namespace Service 251} // 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..8b70ec45b 100644
--- a/src/core/hle/service/news/news.cpp
+++ b/src/core/hle/service/news/news.cpp
@@ -3,11 +3,10 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6
7#include "core/hle/service/service.h"
8#include "core/hle/service/news/news.h" 6#include "core/hle/service/news/news.h"
9#include "core/hle/service/news/news_s.h" 7#include "core/hle/service/news/news_s.h"
10#include "core/hle/service/news/news_u.h" 8#include "core/hle/service/news/news_u.h"
9#include "core/hle/service/service.h"
11 10
12namespace Service { 11namespace Service {
13namespace NEWS { 12namespace NEWS {
@@ -19,8 +18,7 @@ void Init() {
19 AddService(new NEWS_U_Interface); 18 AddService(new NEWS_U_Interface);
20} 19}
21 20
22void Shutdown() { 21void Shutdown() {}
23}
24 22
25} // namespace NEWS 23} // namespace NEWS
26 24
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..0be94322c 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -4,12 +4,11 @@
4 4
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
8#include "core/hle/service/service.h"
9#include "core/hle/service/nim/nim.h" 7#include "core/hle/service/nim/nim.h"
10#include "core/hle/service/nim/nim_aoc.h" 8#include "core/hle/service/nim/nim_aoc.h"
11#include "core/hle/service/nim/nim_s.h" 9#include "core/hle/service/nim/nim_s.h"
12#include "core/hle/service/nim/nim_u.h" 10#include "core/hle/service/nim/nim_u.h"
11#include "core/hle/service/service.h"
13 12
14namespace Service { 13namespace Service {
15namespace NIM { 14namespace NIM {
@@ -31,8 +30,7 @@ void Init() {
31 AddService(new NIM_U_Interface); 30 AddService(new NIM_U_Interface);
32} 31}
33 32
34void Shutdown() { 33void Shutdown() {}
35}
36 34
37} // namespace NIM 35} // namespace NIM
38 36
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/nim/nim_u.h b/src/core/hle/service/nim/nim_u.h
index bc89dc0f3..c4b74985a 100644
--- a/src/core/hle/service/nim/nim_u.h
+++ b/src/core/hle/service/nim/nim_u.h
@@ -1,6 +1,6 @@
1// Copyright 2015 Citra Emulator Project 1// Copyright 2015 Citra Emulator Project
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#pragma once 5#pragma once
6 6
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..27e829209 100644
--- a/src/core/hle/service/nwm_uds.cpp
+++ b/src/core/hle/service/nwm_uds.cpp
@@ -4,7 +4,6 @@
4 4
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
8#include "core/hle/kernel/event.h" 7#include "core/hle/kernel/event.h"
9#include "core/hle/service/nwm_uds.h" 8#include "core/hle/service/nwm_uds.h"
10 9
@@ -54,22 +53,23 @@ static void Shutdown(Service::Interface* self) {
54static void RecvBeaconBroadcastData(Service::Interface* self) { 53static void RecvBeaconBroadcastData(Service::Interface* self) {
55 u32* cmd_buff = Kernel::GetCommandBuffer(); 54 u32* cmd_buff = Kernel::GetCommandBuffer();
56 u32 out_buffer_size = cmd_buff[1]; 55 u32 out_buffer_size = cmd_buff[1];
57 u32 unk1 = cmd_buff[2]; 56 u32 unk1 = cmd_buff[2];
58 u32 unk2 = cmd_buff[3]; 57 u32 unk2 = cmd_buff[3];
59 u32 mac_address = cmd_buff[4]; 58 u32 mac_address = cmd_buff[4];
60 59
61 u32 unk3 = cmd_buff[6]; 60 u32 unk3 = cmd_buff[6];
62 61
63 u32 wlan_comm_id = cmd_buff[15]; 62 u32 wlan_comm_id = cmd_buff[15];
64 u32 ctr_gen_id = cmd_buff[16]; 63 u32 ctr_gen_id = cmd_buff[16];
65 u32 value = cmd_buff[17]; 64 u32 value = cmd_buff[17];
66 u32 input_handle = cmd_buff[18]; 65 u32 input_handle = cmd_buff[18];
67 u32 new_buffer_size = cmd_buff[19]; 66 u32 new_buffer_size = cmd_buff[19];
68 u32 out_buffer_ptr = cmd_buff[20]; 67 u32 out_buffer_ptr = cmd_buff[20];
69 68
70 cmd_buff[1] = RESULT_SUCCESS.raw; 69 cmd_buff[1] = RESULT_SUCCESS.raw;
71 70
72 LOG_WARNING(Service_NWM, "(STUBBED) called out_buffer_size=0x%08X, unk1=0x%08X, unk2=0x%08X," 71 LOG_WARNING(Service_NWM,
72 "(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," 73 "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", 74 "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, 75 out_buffer_size, unk1, unk2, mac_address, unk3, wlan_comm_id, ctr_gen_id, value,
@@ -92,46 +92,47 @@ static void RecvBeaconBroadcastData(Service::Interface* self) {
92 */ 92 */
93static void Initialize(Service::Interface* self) { 93static void Initialize(Service::Interface* self) {
94 u32* cmd_buff = Kernel::GetCommandBuffer(); 94 u32* cmd_buff = Kernel::GetCommandBuffer();
95 u32 unk1 = cmd_buff[1]; 95 u32 unk1 = cmd_buff[1];
96 u32 unk2 = cmd_buff[12]; 96 u32 unk2 = cmd_buff[12];
97 u32 value = cmd_buff[13]; 97 u32 value = cmd_buff[13];
98 u32 handle = cmd_buff[14]; 98 u32 handle = cmd_buff[14];
99 99
100 cmd_buff[1] = RESULT_SUCCESS.raw; 100 cmd_buff[1] = RESULT_SUCCESS.raw;
101 cmd_buff[2] = 0; 101 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 102 cmd_buff[3] = Kernel::g_handle_table.Create(handle_event)
103 .MoveFrom(); // TODO(purpasmart): Verify if this is a event handle
103 104
104 LOG_WARNING(Service_NWM, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, value=%u, handle=0x%08X", 105 LOG_WARNING(Service_NWM, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, value=%u, handle=0x%08X",
105 unk1, unk2, value, handle); 106 unk1, unk2, value, handle);
106} 107}
107 108
108const Interface::FunctionInfo FunctionTable[] = { 109const Interface::FunctionInfo FunctionTable[] = {
109 {0x00020000, nullptr, "Scrap"}, 110 {0x00020000, nullptr, "Scrap"},
110 {0x00030000, Shutdown, "Shutdown"}, 111 {0x00030000, Shutdown, "Shutdown"},
111 {0x00040402, nullptr, "CreateNetwork"}, 112 {0x00040402, nullptr, "CreateNetwork"},
112 {0x00050040, nullptr, "EjectClient"}, 113 {0x00050040, nullptr, "EjectClient"},
113 {0x00060000, nullptr, "EjectSpectator"}, 114 {0x00060000, nullptr, "EjectSpectator"},
114 {0x00070080, nullptr, "UpdateNetworkAttribute"}, 115 {0x00070080, nullptr, "UpdateNetworkAttribute"},
115 {0x00080000, nullptr, "DestroyNetwork"}, 116 {0x00080000, nullptr, "DestroyNetwork"},
116 {0x000A0000, nullptr, "DisconnectNetwork"}, 117 {0x000A0000, nullptr, "DisconnectNetwork"},
117 {0x000B0000, nullptr, "GetConnectionStatus"}, 118 {0x000B0000, nullptr, "GetConnectionStatus"},
118 {0x000D0040, nullptr, "GetNodeInformation"}, 119 {0x000D0040, nullptr, "GetNodeInformation"},
119 {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"}, 120 {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"},
120 {0x00100042, nullptr, "SetBeaconAdditionalData"}, 121 {0x00100042, nullptr, "SetBeaconAdditionalData"},
121 {0x00110040, nullptr, "GetApplicationData"}, 122 {0x00110040, nullptr, "GetApplicationData"},
122 {0x00120100, nullptr, "Bind"}, 123 {0x00120100, nullptr, "Bind"},
123 {0x00130040, nullptr, "Unbind"}, 124 {0x00130040, nullptr, "Unbind"},
124 {0x001400C0, nullptr, "RecvBroadcastDataFrame"}, 125 {0x001400C0, nullptr, "RecvBroadcastDataFrame"},
125 {0x00150080, nullptr, "SetMaxSendDelay"}, 126 {0x00150080, nullptr, "SetMaxSendDelay"},
126 {0x00170182, nullptr, "SendTo"}, 127 {0x00170182, nullptr, "SendTo"},
127 {0x001A0000, nullptr, "GetChannel"}, 128 {0x001A0000, nullptr, "GetChannel"},
128 {0x001B0302, Initialize, "Initialize"}, 129 {0x001B0302, Initialize, "Initialize"},
129 {0x001D0044, nullptr, "BeginHostingNetwork"}, 130 {0x001D0044, nullptr, "BeginHostingNetwork"},
130 {0x001E0084, nullptr, "ConnectToNetwork"}, 131 {0x001E0084, nullptr, "ConnectToNetwork"},
131 {0x001F0006, nullptr, "DecryptBeaconData"}, 132 {0x001F0006, nullptr, "DecryptBeaconData"},
132 {0x00200040, nullptr, "Flush"}, 133 {0x00200040, nullptr, "Flush"},
133 {0x00210080, nullptr, "SetProbeResponseParam"}, 134 {0x00210080, nullptr, "SetProbeResponseParam"},
134 {0x00220402, nullptr, "ScanOnConnection"}, 135 {0x00220402, nullptr, "ScanOnConnection"},
135}; 136};
136 137
137//////////////////////////////////////////////////////////////////////////////////////////////////// 138////////////////////////////////////////////////////////////////////////////////////////////////////
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..6e6b63329 100644
--- a/src/core/hle/service/ptm/ptm.cpp
+++ b/src/core/hle/service/ptm/ptm.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "core/settings.h"
7#include "core/file_sys/file_backend.h" 6#include "core/file_sys/file_backend.h"
8#include "core/hle/service/fs/archive.h" 7#include "core/hle/service/fs/archive.h"
9#include "core/hle/service/ptm/ptm.h" 8#include "core/hle/service/ptm/ptm.h"
@@ -11,12 +10,13 @@
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,18 +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}
142 148
143} // namespace PTM 149} // namespace PTM
144} // namespace Service 150} // namespace Service
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..ca7eeac8a 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -4,42 +4,40 @@
4 4
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
8#include "core/hle/service/service.h"
9#include "core/hle/service/ac_u.h" 7#include "core/hle/service/ac_u.h"
10#include "core/hle/service/act_a.h" 8#include "core/hle/service/act_a.h"
11#include "core/hle/service/act_u.h" 9#include "core/hle/service/act_u.h"
12#include "core/hle/service/csnd_snd.h"
13#include "core/hle/service/dsp_dsp.h"
14#include "core/hle/service/err_f.h"
15#include "core/hle/service/gsp_gpu.h"
16#include "core/hle/service/gsp_lcd.h"
17#include "core/hle/service/http_c.h"
18#include "core/hle/service/mic_u.h"
19#include "core/hle/service/ns_s.h"
20#include "core/hle/service/nwm_uds.h"
21#include "core/hle/service/pm_app.h"
22#include "core/hle/service/soc_u.h"
23#include "core/hle/service/srv.h"
24#include "core/hle/service/ssl_c.h"
25#include "core/hle/service/y2r_u.h"
26
27#include "core/hle/service/am/am.h" 10#include "core/hle/service/am/am.h"
28#include "core/hle/service/apt/apt.h" 11#include "core/hle/service/apt/apt.h"
29#include "core/hle/service/boss/boss.h" 12#include "core/hle/service/boss/boss.h"
30#include "core/hle/service/cam/cam.h" 13#include "core/hle/service/cam/cam.h"
31#include "core/hle/service/cecd/cecd.h" 14#include "core/hle/service/cecd/cecd.h"
15#include "core/hle/service/cfg/cfg.h"
16#include "core/hle/service/csnd_snd.h"
32#include "core/hle/service/dlp/dlp.h" 17#include "core/hle/service/dlp/dlp.h"
18#include "core/hle/service/dsp_dsp.h"
19#include "core/hle/service/err_f.h"
33#include "core/hle/service/frd/frd.h" 20#include "core/hle/service/frd/frd.h"
34#include "core/hle/service/fs/archive.h" 21#include "core/hle/service/fs/archive.h"
35#include "core/hle/service/cfg/cfg.h" 22#include "core/hle/service/gsp_gpu.h"
23#include "core/hle/service/gsp_lcd.h"
36#include "core/hle/service/hid/hid.h" 24#include "core/hle/service/hid/hid.h"
25#include "core/hle/service/http_c.h"
37#include "core/hle/service/ir/ir.h" 26#include "core/hle/service/ir/ir.h"
38#include "core/hle/service/ldr_ro/ldr_ro.h" 27#include "core/hle/service/ldr_ro/ldr_ro.h"
28#include "core/hle/service/mic_u.h"
39#include "core/hle/service/ndm/ndm.h" 29#include "core/hle/service/ndm/ndm.h"
40#include "core/hle/service/news/news.h" 30#include "core/hle/service/news/news.h"
41#include "core/hle/service/nim/nim.h" 31#include "core/hle/service/nim/nim.h"
32#include "core/hle/service/ns_s.h"
33#include "core/hle/service/nwm_uds.h"
34#include "core/hle/service/pm_app.h"
42#include "core/hle/service/ptm/ptm.h" 35#include "core/hle/service/ptm/ptm.h"
36#include "core/hle/service/service.h"
37#include "core/hle/service/soc_u.h"
38#include "core/hle/service/srv.h"
39#include "core/hle/service/ssl_c.h"
40#include "core/hle/service/y2r_u.h"
43 41
44namespace Service { 42namespace Service {
45 43
@@ -50,11 +48,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 48 * 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. 49 * on what's passed in) the port name, and all the cmd_buff arguments.
52 */ 50 */
53static std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) { 51static std::string MakeFunctionString(const char* name, const char* port_name,
52 const u32* cmd_buff) {
54 // Number of params == bits 0-5 + bits 6-11 53 // Number of params == bits 0-5 + bits 6-11
55 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); 54 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
56 55
57 std::string function_string = Common::StringFromFormat("function '%s': port=%s", name, port_name); 56 std::string function_string =
57 Common::StringFromFormat("function '%s': port=%s", name, port_name);
58 for (int i = 1; i <= num_params; ++i) { 58 for (int i = 1; i <= num_params; ++i) {
59 function_string += Common::StringFromFormat(", cmd_buff[%i]=0x%X", i, cmd_buff[i]); 59 function_string += Common::StringFromFormat(", cmd_buff[%i]=0x%X", i, cmd_buff[i]);
60 } 60 }
@@ -66,14 +66,19 @@ ResultVal<bool> Interface::SyncRequest() {
66 auto itr = m_functions.find(cmd_buff[0]); 66 auto itr = m_functions.find(cmd_buff[0]);
67 67
68 if (itr == m_functions.end() || itr->second.func == nullptr) { 68 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; 69 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()); 70 ? Common::StringFromFormat("0x%08X", cmd_buff[0])
71 : itr->second.name;
72 LOG_ERROR(
73 Service, "unknown / unimplemented %s",
74 MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str());
71 75
72 // TODO(bunnei): Hack - ignore error 76 // TODO(bunnei): Hack - ignore error
73 cmd_buff[1] = 0; 77 cmd_buff[1] = 0;
74 return MakeResult<bool>(false); 78 return MakeResult<bool>(false);
75 } 79 }
76 LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str()); 80 LOG_TRACE(Service, "%s",
81 MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
77 82
78 itr->second.func(this); 83 itr->second.func(this);
79 84
@@ -163,6 +168,4 @@ void Shutdown() {
163 g_kernel_named_ports.clear(); 168 g_kernel_named_ports.clear();
164 LOG_DEBUG(Service, "shutdown OK"); 169 LOG_DEBUG(Service, "shutdown OK");
165} 170}
166
167
168} 171}
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index f31135212..39b5ffaae 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -7,11 +7,8 @@
7#include <cstddef> 7#include <cstddef>
8#include <string> 8#include <string>
9#include <unordered_map> 9#include <unordered_map>
10
11#include <boost/container/flat_map.hpp> 10#include <boost/container/flat_map.hpp>
12
13#include "common/common_types.h" 11#include "common/common_types.h"
14
15#include "core/hle/kernel/session.h" 12#include "core/hle/kernel/session.h"
16#include "core/hle/result.h" 13#include "core/hle/result.h"
17 14
@@ -28,13 +25,15 @@ class Interface : public Kernel::Session {
28 // just something that encapsulates a session and acts as a helper to implement service 25 // just something that encapsulates a session and acts as a helper to implement service
29 // processes. 26 // processes.
30public: 27public:
31 std::string GetName() const override { return GetPortName(); } 28 std::string GetName() const override {
29 return GetPortName();
30 }
32 31
33 typedef void (*Function)(Interface*); 32 typedef void (*Function)(Interface*);
34 33
35 struct FunctionInfo { 34 struct FunctionInfo {
36 u32 id; 35 u32 id;
37 Function func; 36 Function func;
38 const char* name; 37 const char* name;
39 }; 38 };
40 39
@@ -49,7 +48,6 @@ public:
49 ResultVal<bool> SyncRequest() override; 48 ResultVal<bool> SyncRequest() override;
50 49
51protected: 50protected:
52
53 /** 51 /**
54 * Registers the functions in the service 52 * Registers the functions in the service
55 */ 53 */
@@ -62,7 +60,6 @@ protected:
62 60
63private: 61private:
64 boost::container::flat_map<u32, FunctionInfo> m_functions; 62 boost::container::flat_map<u32, FunctionInfo> m_functions;
65
66}; 63};
67 64
68/// Initialize ServiceManager 65/// Initialize ServiceManager
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index 9b285567b..4279b67fb 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -6,53 +6,51 @@
6#include <cstring> 6#include <cstring>
7#include <unordered_map> 7#include <unordered_map>
8#include <vector> 8#include <vector>
9
10#include "common/assert.h" 9#include "common/assert.h"
11#include "common/bit_field.h" 10#include "common/bit_field.h"
12#include "common/common_types.h" 11#include "common/common_types.h"
13#include "common/logging/log.h" 12#include "common/logging/log.h"
14#include "common/scope_exit.h" 13#include "common/scope_exit.h"
15
16#include "core/hle/kernel/session.h" 14#include "core/hle/kernel/session.h"
17#include "core/hle/result.h" 15#include "core/hle/result.h"
18#include "core/hle/service/soc_u.h" 16#include "core/hle/service/soc_u.h"
19#include "core/memory.h" 17#include "core/memory.h"
20 18
21#ifdef _WIN32 19#ifdef _WIN32
22 #include <winsock2.h> 20#include <winsock2.h>
23 #include <ws2tcpip.h> 21#include <ws2tcpip.h>
24 22
25 // MinGW does not define several errno constants 23// MinGW does not define several errno constants
26 #ifndef _MSC_VER 24#ifndef _MSC_VER
27 #define EBADMSG 104 25#define EBADMSG 104
28 #define ENODATA 120 26#define ENODATA 120
29 #define ENOMSG 122 27#define ENOMSG 122
30 #define ENOSR 124 28#define ENOSR 124
31 #define ENOSTR 125 29#define ENOSTR 125
32 #define ETIME 137 30#define ETIME 137
33 #define EIDRM 2001 31#define EIDRM 2001
34 #define ENOLINK 2002 32#define ENOLINK 2002
35 #endif // _MSC_VER 33#endif // _MSC_VER
36#else 34#else
37 #include <cerrno> 35#include <cerrno>
38 #include <fcntl.h> 36#include <fcntl.h>
39 #include <netinet/in.h> 37#include <netdb.h>
40 #include <netdb.h> 38#include <netinet/in.h>
41 #include <poll.h> 39#include <poll.h>
42 #include <sys/socket.h> 40#include <sys/socket.h>
43 #include <unistd.h> 41#include <unistd.h>
44#endif 42#endif
45 43
46#ifdef _WIN32 44#ifdef _WIN32
47# define WSAEAGAIN WSAEWOULDBLOCK 45#define WSAEAGAIN WSAEWOULDBLOCK
48# define WSAEMULTIHOP -1 // Invalid dummy value 46#define WSAEMULTIHOP -1 // Invalid dummy value
49# define ERRNO(x) WSA##x 47#define ERRNO(x) WSA##x
50# define GET_ERRNO WSAGetLastError() 48#define GET_ERRNO WSAGetLastError()
51# define poll(x, y, z) WSAPoll(x, y, z); 49#define poll(x, y, z) WSAPoll(x, y, z);
52#else 50#else
53# define ERRNO(x) x 51#define ERRNO(x) x
54# define GET_ERRNO errno 52#define GET_ERRNO errno
55# define closesocket(x) close(x) 53#define closesocket(x) close(x)
56#endif 54#endif
57 55
58static const s32 SOCKET_ERROR_VALUE = -1; 56static const s32 SOCKET_ERROR_VALUE = -1;
@@ -63,83 +61,83 @@ static const s32 SOCKET_ERROR_VALUE = -1;
63namespace SOC_U { 61namespace SOC_U {
64 62
65/// Holds the translation from system network errors to 3DS network errors 63/// Holds the translation from system network errors to 3DS network errors
66static const std::unordered_map<int, int> error_map = { { 64static const std::unordered_map<int, int> error_map = {{
67 { E2BIG, 1 }, 65 {E2BIG, 1},
68 { ERRNO(EACCES), 2 }, 66 {ERRNO(EACCES), 2},
69 { ERRNO(EADDRINUSE), 3 }, 67 {ERRNO(EADDRINUSE), 3},
70 { ERRNO(EADDRNOTAVAIL), 4 }, 68 {ERRNO(EADDRNOTAVAIL), 4},
71 { ERRNO(EAFNOSUPPORT), 5 }, 69 {ERRNO(EAFNOSUPPORT), 5},
72 { ERRNO(EAGAIN), 6 }, 70 {ERRNO(EAGAIN), 6},
73 { ERRNO(EALREADY), 7 }, 71 {ERRNO(EALREADY), 7},
74 { ERRNO(EBADF), 8 }, 72 {ERRNO(EBADF), 8},
75 { EBADMSG, 9 }, 73 {EBADMSG, 9},
76 { EBUSY, 10 }, 74 {EBUSY, 10},
77 { ECANCELED, 11 }, 75 {ECANCELED, 11},
78 { ECHILD, 12 }, 76 {ECHILD, 12},
79 { ERRNO(ECONNABORTED), 13 }, 77 {ERRNO(ECONNABORTED), 13},
80 { ERRNO(ECONNREFUSED), 14 }, 78 {ERRNO(ECONNREFUSED), 14},
81 { ERRNO(ECONNRESET), 15 }, 79 {ERRNO(ECONNRESET), 15},
82 { EDEADLK, 16 }, 80 {EDEADLK, 16},
83 { ERRNO(EDESTADDRREQ), 17 }, 81 {ERRNO(EDESTADDRREQ), 17},
84 { EDOM, 18 }, 82 {EDOM, 18},
85 { ERRNO(EDQUOT), 19 }, 83 {ERRNO(EDQUOT), 19},
86 { EEXIST, 20 }, 84 {EEXIST, 20},
87 { ERRNO(EFAULT), 21 }, 85 {ERRNO(EFAULT), 21},
88 { EFBIG, 22 }, 86 {EFBIG, 22},
89 { ERRNO(EHOSTUNREACH), 23 }, 87 {ERRNO(EHOSTUNREACH), 23},
90 { EIDRM, 24 }, 88 {EIDRM, 24},
91 { EILSEQ, 25 }, 89 {EILSEQ, 25},
92 { ERRNO(EINPROGRESS), 26 }, 90 {ERRNO(EINPROGRESS), 26},
93 { ERRNO(EINTR), 27 }, 91 {ERRNO(EINTR), 27},
94 { ERRNO(EINVAL), 28 }, 92 {ERRNO(EINVAL), 28},
95 { EIO, 29 }, 93 {EIO, 29},
96 { ERRNO(EISCONN), 30 }, 94 {ERRNO(EISCONN), 30},
97 { EISDIR, 31 }, 95 {EISDIR, 31},
98 { ERRNO(ELOOP), 32 }, 96 {ERRNO(ELOOP), 32},
99 { ERRNO(EMFILE), 33 }, 97 {ERRNO(EMFILE), 33},
100 { EMLINK, 34 }, 98 {EMLINK, 34},
101 { ERRNO(EMSGSIZE), 35 }, 99 {ERRNO(EMSGSIZE), 35},
102 { ERRNO(EMULTIHOP), 36 }, 100 {ERRNO(EMULTIHOP), 36},
103 { ERRNO(ENAMETOOLONG), 37 }, 101 {ERRNO(ENAMETOOLONG), 37},
104 { ERRNO(ENETDOWN), 38 }, 102 {ERRNO(ENETDOWN), 38},
105 { ERRNO(ENETRESET), 39 }, 103 {ERRNO(ENETRESET), 39},
106 { ERRNO(ENETUNREACH), 40 }, 104 {ERRNO(ENETUNREACH), 40},
107 { ENFILE, 41 }, 105 {ENFILE, 41},
108 { ERRNO(ENOBUFS), 42 }, 106 {ERRNO(ENOBUFS), 42},
109 { ENODATA, 43 }, 107 {ENODATA, 43},
110 { ENODEV, 44 }, 108 {ENODEV, 44},
111 { ENOENT, 45 }, 109 {ENOENT, 45},
112 { ENOEXEC, 46 }, 110 {ENOEXEC, 46},
113 { ENOLCK, 47 }, 111 {ENOLCK, 47},
114 { ENOLINK, 48 }, 112 {ENOLINK, 48},
115 { ENOMEM, 49 }, 113 {ENOMEM, 49},
116 { ENOMSG, 50 }, 114 {ENOMSG, 50},
117 { ERRNO(ENOPROTOOPT), 51 }, 115 {ERRNO(ENOPROTOOPT), 51},
118 { ENOSPC, 52 }, 116 {ENOSPC, 52},
119 { ENOSR, 53 }, 117 {ENOSR, 53},
120 { ENOSTR, 54 }, 118 {ENOSTR, 54},
121 { ENOSYS, 55 }, 119 {ENOSYS, 55},
122 { ERRNO(ENOTCONN), 56 }, 120 {ERRNO(ENOTCONN), 56},
123 { ENOTDIR, 57 }, 121 {ENOTDIR, 57},
124 { ERRNO(ENOTEMPTY), 58 }, 122 {ERRNO(ENOTEMPTY), 58},
125 { ERRNO(ENOTSOCK), 59 }, 123 {ERRNO(ENOTSOCK), 59},
126 { ENOTSUP, 60 }, 124 {ENOTSUP, 60},
127 { ENOTTY, 61 }, 125 {ENOTTY, 61},
128 { ENXIO, 62 }, 126 {ENXIO, 62},
129 { ERRNO(EOPNOTSUPP), 63 }, 127 {ERRNO(EOPNOTSUPP), 63},
130 { EOVERFLOW, 64 }, 128 {EOVERFLOW, 64},
131 { EPERM, 65 }, 129 {EPERM, 65},
132 { EPIPE, 66 }, 130 {EPIPE, 66},
133 { EPROTO, 67 }, 131 {EPROTO, 67},
134 { ERRNO(EPROTONOSUPPORT), 68 }, 132 {ERRNO(EPROTONOSUPPORT), 68},
135 { ERRNO(EPROTOTYPE), 69 }, 133 {ERRNO(EPROTOTYPE), 69},
136 { ERANGE, 70 }, 134 {ERANGE, 70},
137 { EROFS, 71 }, 135 {EROFS, 71},
138 { ESPIPE, 72 }, 136 {ESPIPE, 72},
139 { ESRCH, 73 }, 137 {ESRCH, 73},
140 { ERRNO(ESTALE), 74 }, 138 {ERRNO(ESTALE), 74},
141 { ETIME, 75 }, 139 {ETIME, 75},
142 { ERRNO(ETIMEDOUT), 76 } 140 {ERRNO(ETIMEDOUT), 76},
143}}; 141}};
144 142
145/// Converts a network error from platform-specific to 3ds-specific 143/// Converts a network error from platform-specific to 3ds-specific
@@ -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/soc_u.h b/src/core/hle/service/soc_u.h
index a091f597c..8d02ed30f 100644
--- a/src/core/hle/service/soc_u.h
+++ b/src/core/hle/service/soc_u.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <string> 7#include <string>
8
9#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
10 9
11//////////////////////////////////////////////////////////////////////////////////////////////////// 10////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index 3c05f836b..b25be413a 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -4,9 +4,8 @@
4 4
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
8#include "core/hle/service/srv.h"
9#include "core/hle/kernel/event.h" 7#include "core/hle/kernel/event.h"
8#include "core/hle/service/srv.h"
10 9
11//////////////////////////////////////////////////////////////////////////////////////////////////// 10////////////////////////////////////////////////////////////////////////////////////////////////////
12// Namespace SRV 11// Namespace SRV
@@ -28,13 +27,14 @@ static void RegisterClient(Service::Interface* self) {
28 u32* cmd_buff = Kernel::GetCommandBuffer(); 27 u32* cmd_buff = Kernel::GetCommandBuffer();
29 28
30 if (cmd_buff[1] != IPC::CallingPidDesc()) { 29 if (cmd_buff[1] != IPC::CallingPidDesc()) {
31 cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); //0x40 30 cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); // 0x40
32 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, 31 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
33 ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; 32 ErrorSummary::WrongArgument, ErrorLevel::Permanent)
33 .raw;
34 return; 34 return;
35 } 35 }
36 cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); //0x10040 36 cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); // 0x10040
37 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 37 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
38 LOG_WARNING(Service_SRV, "(STUBBED) called"); 38 LOG_WARNING(Service_SRV, "(STUBBED) called");
39} 39}
40 40
@@ -56,7 +56,7 @@ static void EnableNotification(Service::Interface* self) {
56 event_handle->Clear(); 56 event_handle->Clear();
57 57
58 cmd_buff[0] = IPC::MakeHeader(0x2, 0x1, 0x2); // 0x20042 58 cmd_buff[0] = IPC::MakeHeader(0x2, 0x1, 0x2); // 0x20042
59 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 59 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
60 cmd_buff[2] = IPC::CopyHandleDesc(1); 60 cmd_buff[2] = IPC::CopyHandleDesc(1);
61 cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom(); 61 cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom();
62 LOG_WARNING(Service_SRV, "(STUBBED) called"); 62 LOG_WARNING(Service_SRV, "(STUBBED) called");
@@ -105,7 +105,7 @@ static void Subscribe(Service::Interface* self) {
105 u32 notification_id = cmd_buff[1]; 105 u32 notification_id = cmd_buff[1];
106 106
107 cmd_buff[0] = IPC::MakeHeader(0x9, 0x1, 0); // 0x90040 107 cmd_buff[0] = IPC::MakeHeader(0x9, 0x1, 0); // 0x90040
108 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 108 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
109 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); 109 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id);
110} 110}
111 111
@@ -124,7 +124,7 @@ static void Unsubscribe(Service::Interface* self) {
124 u32 notification_id = cmd_buff[1]; 124 u32 notification_id = cmd_buff[1];
125 125
126 cmd_buff[0] = IPC::MakeHeader(0xA, 0x1, 0); // 0xA0040 126 cmd_buff[0] = IPC::MakeHeader(0xA, 0x1, 0); // 0xA0040
127 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 127 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
128 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); 128 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id);
129} 129}
130 130
@@ -145,25 +145,26 @@ static void PublishToSubscriber(Service::Interface* self) {
145 u8 flags = cmd_buff[2] & 0xFF; 145 u8 flags = cmd_buff[2] & 0xFF;
146 146
147 cmd_buff[0] = IPC::MakeHeader(0xC, 0x1, 0); // 0xC0040 147 cmd_buff[0] = IPC::MakeHeader(0xC, 0x1, 0); // 0xC0040
148 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 148 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
149 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X, flags=%u", notification_id, flags); 149 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X, flags=%u", notification_id,
150 flags);
150} 151}
151 152
152const Interface::FunctionInfo FunctionTable[] = { 153const Interface::FunctionInfo FunctionTable[] = {
153 {0x00010002, RegisterClient, "RegisterClient"}, 154 {0x00010002, RegisterClient, "RegisterClient"},
154 {0x00020000, EnableNotification, "EnableNotification"}, 155 {0x00020000, EnableNotification, "EnableNotification"},
155 {0x00030100, nullptr, "RegisterService"}, 156 {0x00030100, nullptr, "RegisterService"},
156 {0x000400C0, nullptr, "UnregisterService"}, 157 {0x000400C0, nullptr, "UnregisterService"},
157 {0x00050100, GetServiceHandle, "GetServiceHandle"}, 158 {0x00050100, GetServiceHandle, "GetServiceHandle"},
158 {0x000600C2, nullptr, "RegisterPort"}, 159 {0x000600C2, nullptr, "RegisterPort"},
159 {0x000700C0, nullptr, "UnregisterPort"}, 160 {0x000700C0, nullptr, "UnregisterPort"},
160 {0x00080100, nullptr, "GetPort"}, 161 {0x00080100, nullptr, "GetPort"},
161 {0x00090040, Subscribe, "Subscribe"}, 162 {0x00090040, Subscribe, "Subscribe"},
162 {0x000A0040, Unsubscribe, "Unsubscribe"}, 163 {0x000A0040, Unsubscribe, "Unsubscribe"},
163 {0x000B0000, nullptr, "ReceiveNotification"}, 164 {0x000B0000, nullptr, "ReceiveNotification"},
164 {0x000C0080, PublishToSubscriber, "PublishToSubscriber"}, 165 {0x000C0080, PublishToSubscriber, "PublishToSubscriber"},
165 {0x000D0040, nullptr, "PublishAndGetSubscriber"}, 166 {0x000D0040, nullptr, "PublishAndGetSubscriber"},
166 {0x000E00C0, nullptr, "IsServiceRegistered"}, 167 {0x000E00C0, nullptr, "IsServiceRegistered"},
167}; 168};
168 169
169//////////////////////////////////////////////////////////////////////////////////////////////////// 170////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp
index a8aff1abf..abab1d271 100644
--- a/src/core/hle/service/ssl_c.cpp
+++ b/src/core/hle/service/ssl_c.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <random> 5#include <random>
6
7#include "common/common_types.h" 6#include "common/common_types.h"
8#include "core/hle/service/ssl_c.h" 7#include "core/hle/service/ssl_c.h"
9 8
@@ -37,7 +36,8 @@ static void GenerateRandomData(Service::Interface* self) {
37 u32 i = 0; 36 u32 i = 0;
38 while (i < size) { 37 while (i < size) {
39 if ((i % 4) == 0) { 38 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 39 // The random number generator returns 4 bytes worth of data, so generate new random
40 // data when i == 0 and when i is divisible by 4
41 data = rand_gen(); 41 data = rand_gen();
42 } 42 }
43 43
@@ -59,26 +59,26 @@ static void GenerateRandomData(Service::Interface* self) {
59} 59}
60 60
61const Interface::FunctionInfo FunctionTable[] = { 61const Interface::FunctionInfo FunctionTable[] = {
62 {0x00010002, Initialize, "Initialize"}, 62 {0x00010002, Initialize, "Initialize"},
63 {0x000200C2, nullptr, "CreateContext"}, 63 {0x000200C2, nullptr, "CreateContext"},
64 {0x00030000, nullptr, "CreateRootCertChain"}, 64 {0x00030000, nullptr, "CreateRootCertChain"},
65 {0x00040040, nullptr, "DestroyRootCertChain"}, 65 {0x00040040, nullptr, "DestroyRootCertChain"},
66 {0x00050082, nullptr, "AddTrustedRootCA"}, 66 {0x00050082, nullptr, "AddTrustedRootCA"},
67 {0x00060080, nullptr, "RootCertChainAddDefaultCert"}, 67 {0x00060080, nullptr, "RootCertChainAddDefaultCert"},
68 {0x00070080, nullptr, "RootCertChainRemoveCert"}, 68 {0x00070080, nullptr, "RootCertChainRemoveCert"},
69 {0x000E0040, nullptr, "OpenDefaultClientCertContext"}, 69 {0x000E0040, nullptr, "OpenDefaultClientCertContext"},
70 {0x000F0040, nullptr, "CloseClientCertContext"}, 70 {0x000F0040, nullptr, "CloseClientCertContext"},
71 {0x00110042, GenerateRandomData, "GenerateRandomData"}, 71 {0x00110042, GenerateRandomData, "GenerateRandomData"},
72 {0x00120042, nullptr, "InitializeConnectionSession"}, 72 {0x00120042, nullptr, "InitializeConnectionSession"},
73 {0x00130040, nullptr, "StartConnection"}, 73 {0x00130040, nullptr, "StartConnection"},
74 {0x00140040, nullptr, "StartConnectionGetOut"}, 74 {0x00140040, nullptr, "StartConnectionGetOut"},
75 {0x00150082, nullptr, "Read"}, 75 {0x00150082, nullptr, "Read"},
76 {0x00170082, nullptr, "Write"}, 76 {0x00170082, nullptr, "Write"},
77 {0x00180080, nullptr, "ContextSetRootCertChain"}, 77 {0x00180080, nullptr, "ContextSetRootCertChain"},
78 {0x00190080, nullptr, "ContextSetClientCert"}, 78 {0x00190080, nullptr, "ContextSetClientCert"},
79 {0x001B0080, nullptr, "ContextClearOpt"}, 79 {0x001B0080, nullptr, "ContextClearOpt"},
80 {0x001E0040, nullptr, "DestroyContext"}, 80 {0x001E0040, nullptr, "DestroyContext"},
81 {0x001F0082, nullptr, "ContextInitSharedmem"} 81 {0x001F0082, nullptr, "ContextInitSharedmem"},
82}; 82};
83 83
84//////////////////////////////////////////////////////////////////////////////////////////////////// 84////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index d16578f87..097e09d28 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -3,11 +3,9 @@
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
7#include "common/common_funcs.h" 6#include "common/common_funcs.h"
8#include "common/common_types.h" 7#include "common/common_types.h"
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10
11#include "core/hle/kernel/event.h" 9#include "core/hle/kernel/event.h"
12#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
13#include "core/hle/service/y2r_u.h" 11#include "core/hle/service/y2r_u.h"
@@ -39,16 +37,16 @@ static u32 transfer_end_interrupt_enabled = 0;
39static u32 spacial_dithering_enabled = 0; 37static u32 spacial_dithering_enabled = 0;
40 38
41static const CoefficientSet standard_coefficients[4] = { 39static const CoefficientSet standard_coefficients[4] = {
42 {{ 0x100, 0x166, 0xB6, 0x58, 0x1C5, -0x166F, 0x10EE, -0x1C5B }}, // ITU_Rec601 40 {{0x100, 0x166, 0xB6, 0x58, 0x1C5, -0x166F, 0x10EE, -0x1C5B}}, // ITU_Rec601
43 {{ 0x100, 0x193, 0x77, 0x2F, 0x1DB, -0x1933, 0xA7C, -0x1D51 }}, // ITU_Rec709 41 {{0x100, 0x193, 0x77, 0x2F, 0x1DB, -0x1933, 0xA7C, -0x1D51}}, // ITU_Rec709
44 {{ 0x12A, 0x198, 0xD0, 0x64, 0x204, -0x1BDE, 0x10F2, -0x229B }}, // ITU_Rec601_Scaling 42 {{0x12A, 0x198, 0xD0, 0x64, 0x204, -0x1BDE, 0x10F2, -0x229B}}, // ITU_Rec601_Scaling
45 {{ 0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421 }}, // ITU_Rec709_Scaling 43 {{0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421}}, // ITU_Rec709_Scaling
46}; 44};
47 45
48ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) { 46ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) {
49 if (width == 0 || width > 1024 || width % 8 != 0) { 47 if (width == 0 || width > 1024 || width % 8 != 0) {
50 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, 48 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM,
51 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD 49 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD
52 } 50 }
53 51
54 // Note: The hardware uses the register value 0 to represent a width of 1024, so for a width of 52 // Note: The hardware uses the register value 0 to represent a width of 1024, so for a width of
@@ -61,7 +59,7 @@ ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) {
61ResultCode ConversionConfiguration::SetInputLines(u16 lines) { 59ResultCode ConversionConfiguration::SetInputLines(u16 lines) {
62 if (lines == 0 || lines > 1024) { 60 if (lines == 0 || lines > 1024) {
63 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, 61 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM,
64 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD 62 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD
65 } 63 }
66 64
67 // Note: In what appears to be a bug, the `camera` module does not set the hardware register at 65 // Note: In what appears to be a bug, the `camera` module does not set the hardware register at
@@ -73,11 +71,12 @@ ResultCode ConversionConfiguration::SetInputLines(u16 lines) {
73 return RESULT_SUCCESS; 71 return RESULT_SUCCESS;
74} 72}
75 73
76ResultCode ConversionConfiguration::SetStandardCoefficient(StandardCoefficient standard_coefficient) { 74ResultCode ConversionConfiguration::SetStandardCoefficient(
75 StandardCoefficient standard_coefficient) {
77 size_t index = static_cast<size_t>(standard_coefficient); 76 size_t index = static_cast<size_t>(standard_coefficient);
78 if (index >= ARRAY_SIZE(standard_coefficients)) { 77 if (index >= ARRAY_SIZE(standard_coefficients)) {
79 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM, 78 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM,
80 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053ED 79 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053ED
81 } 80 }
82 81
83 std::memcpy(coefficients.data(), standard_coefficients[index].data(), sizeof(coefficients)); 82 std::memcpy(coefficients.data(), standard_coefficients[index].data(), sizeof(coefficients));
@@ -294,8 +293,10 @@ static void SetSendingY(Service::Interface* self) {
294 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0); 293 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0);
295 cmd_buff[1] = RESULT_SUCCESS.raw; 294 cmd_buff[1] = RESULT_SUCCESS.raw;
296 295
297 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 296 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]); 297 "src_process_handle=0x%08X",
298 conversion.src_Y.image_size, conversion.src_Y.transfer_unit, conversion.src_Y.gap,
299 cmd_buff[6]);
299} 300}
300 301
301static void SetSendingU(Service::Interface* self) { 302static void SetSendingU(Service::Interface* self) {
@@ -309,8 +310,10 @@ static void SetSendingU(Service::Interface* self) {
309 cmd_buff[0] = IPC::MakeHeader(0x11, 1, 0); 310 cmd_buff[0] = IPC::MakeHeader(0x11, 1, 0);
310 cmd_buff[1] = RESULT_SUCCESS.raw; 311 cmd_buff[1] = RESULT_SUCCESS.raw;
311 312
312 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 313 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]); 314 "src_process_handle=0x%08X",
315 conversion.src_U.image_size, conversion.src_U.transfer_unit, conversion.src_U.gap,
316 cmd_buff[6]);
314} 317}
315 318
316static void SetSendingV(Service::Interface* self) { 319static void SetSendingV(Service::Interface* self) {
@@ -324,8 +327,10 @@ static void SetSendingV(Service::Interface* self) {
324 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); 327 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0);
325 cmd_buff[1] = RESULT_SUCCESS.raw; 328 cmd_buff[1] = RESULT_SUCCESS.raw;
326 329
327 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 330 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]); 331 "src_process_handle=0x%08X",
332 conversion.src_V.image_size, conversion.src_V.transfer_unit, conversion.src_V.gap,
333 cmd_buff[6]);
329} 334}
330 335
331static void SetSendingYUYV(Service::Interface* self) { 336static void SetSendingYUYV(Service::Interface* self) {
@@ -339,8 +344,10 @@ static void SetSendingYUYV(Service::Interface* self) {
339 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); 344 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0);
340 cmd_buff[1] = RESULT_SUCCESS.raw; 345 cmd_buff[1] = RESULT_SUCCESS.raw;
341 346
342 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 347 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]); 348 "src_process_handle=0x%08X",
349 conversion.src_YUYV.image_size, conversion.src_YUYV.transfer_unit,
350 conversion.src_YUYV.gap, cmd_buff[6]);
344} 351}
345 352
346/** 353/**
@@ -418,8 +425,10 @@ static void SetReceiving(Service::Interface* self) {
418 cmd_buff[0] = IPC::MakeHeader(0x18, 1, 0); 425 cmd_buff[0] = IPC::MakeHeader(0x18, 1, 0);
419 cmd_buff[1] = RESULT_SUCCESS.raw; 426 cmd_buff[1] = RESULT_SUCCESS.raw;
420 427
421 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, dst_process_handle=0x%08X", 428 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]); 429 "dst_process_handle=0x%08X",
430 conversion.dst.image_size, conversion.dst.transfer_unit, conversion.dst.gap,
431 cmd_buff[6]);
423} 432}
424 433
425/** 434/**
@@ -486,8 +495,8 @@ static void SetCoefficient(Service::Interface* self) {
486 cmd_buff[1] = RESULT_SUCCESS.raw; 495 cmd_buff[1] = RESULT_SUCCESS.raw;
487 496
488 LOG_DEBUG(Service_Y2R, "called coefficients=[%hX, %hX, %hX, %hX, %hX, %hX, %hX, %hX]", 497 LOG_DEBUG(Service_Y2R, "called coefficients=[%hX, %hX, %hX, %hX, %hX, %hX, %hX, %hX]",
489 coefficients[0], coefficients[1], coefficients[2], coefficients[3], 498 coefficients[0], coefficients[1], coefficients[2], coefficients[3], coefficients[4],
490 coefficients[4], coefficients[5], coefficients[6], coefficients[7]); 499 coefficients[5], coefficients[6], coefficients[7]);
491} 500}
492 501
493static void GetCoefficient(Service::Interface* self) { 502static void GetCoefficient(Service::Interface* self) {
@@ -575,8 +584,10 @@ static void StartConversion(Service::Interface* self) {
575 u32* cmd_buff = Kernel::GetCommandBuffer(); 584 u32* cmd_buff = Kernel::GetCommandBuffer();
576 585
577 // dst_image_size would seem to be perfect for this, but it doesn't include the gap :( 586 // 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); 587 u32 total_output_size =
579 Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size); 588 conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap);
589 Memory::RasterizerFlushAndInvalidateRegion(
590 Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size);
580 591
581 HW::Y2R::PerformConversion(conversion); 592 HW::Y2R::PerformConversion(conversion);
582 593
@@ -648,10 +659,13 @@ cleanup:
648 cmd_buff[0] = IPC::MakeHeader(0x29, 1, 0); 659 cmd_buff[0] = IPC::MakeHeader(0x29, 1, 0);
649 cmd_buff[1] = result.raw; 660 cmd_buff[1] = result.raw;
650 661
651 LOG_DEBUG(Service_Y2R, "called input_format=%hhu output_format=%hhu rotation=%hhu block_alignment=%hhu " 662 LOG_DEBUG(
652 "input_line_width=%hu input_lines=%hu standard_coefficient=%hhu reserved=%hhu alpha=%hX", 663 Service_Y2R,
653 params->input_format, params->output_format, params->rotation, params->block_alignment, 664 "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); 665 "input_line_width=%hu input_lines=%hu standard_coefficient=%hhu reserved=%hhu alpha=%hX",
666 params->input_format, params->output_format, params->rotation, params->block_alignment,
667 params->input_line_width, params->input_lines, params->standard_coefficient,
668 params->padding, params->alpha);
655} 669}
656 670
657static void PingProcess(Service::Interface* self) { 671static void PingProcess(Service::Interface* self) {
@@ -699,7 +713,6 @@ static void DriverFinalize(Service::Interface* self) {
699 LOG_DEBUG(Service_Y2R, "called"); 713 LOG_DEBUG(Service_Y2R, "called");
700} 714}
701 715
702
703static void GetPackageParameter(Service::Interface* self) { 716static void GetPackageParameter(Service::Interface* self) {
704 u32* cmd_buff = Kernel::GetCommandBuffer(); 717 u32* cmd_buff = Kernel::GetCommandBuffer();
705 718
@@ -711,51 +724,51 @@ static void GetPackageParameter(Service::Interface* self) {
711} 724}
712 725
713const Interface::FunctionInfo FunctionTable[] = { 726const Interface::FunctionInfo FunctionTable[] = {
714 {0x00010040, SetInputFormat, "SetInputFormat"}, 727 {0x00010040, SetInputFormat, "SetInputFormat"},
715 {0x00020000, GetInputFormat, "GetInputFormat"}, 728 {0x00020000, GetInputFormat, "GetInputFormat"},
716 {0x00030040, SetOutputFormat, "SetOutputFormat"}, 729 {0x00030040, SetOutputFormat, "SetOutputFormat"},
717 {0x00040000, GetOutputFormat, "GetOutputFormat"}, 730 {0x00040000, GetOutputFormat, "GetOutputFormat"},
718 {0x00050040, SetRotation, "SetRotation"}, 731 {0x00050040, SetRotation, "SetRotation"},
719 {0x00060000, GetRotation, "GetRotation"}, 732 {0x00060000, GetRotation, "GetRotation"},
720 {0x00070040, SetBlockAlignment, "SetBlockAlignment"}, 733 {0x00070040, SetBlockAlignment, "SetBlockAlignment"},
721 {0x00080000, GetBlockAlignment, "GetBlockAlignment"}, 734 {0x00080000, GetBlockAlignment, "GetBlockAlignment"},
722 {0x00090040, SetSpacialDithering, "SetSpacialDithering"}, 735 {0x00090040, SetSpacialDithering, "SetSpacialDithering"},
723 {0x000A0000, GetSpacialDithering, "GetSpacialDithering"}, 736 {0x000A0000, GetSpacialDithering, "GetSpacialDithering"},
724 {0x000B0040, SetTemporalDithering, "SetTemporalDithering"}, 737 {0x000B0040, SetTemporalDithering, "SetTemporalDithering"},
725 {0x000C0000, GetTemporalDithering, "GetTemporalDithering"}, 738 {0x000C0000, GetTemporalDithering, "GetTemporalDithering"},
726 {0x000D0040, SetTransferEndInterrupt, "SetTransferEndInterrupt"}, 739 {0x000D0040, SetTransferEndInterrupt, "SetTransferEndInterrupt"},
727 {0x000E0000, GetTransferEndInterrupt, "GetTransferEndInterrupt"}, 740 {0x000E0000, GetTransferEndInterrupt, "GetTransferEndInterrupt"},
728 {0x000F0000, GetTransferEndEvent, "GetTransferEndEvent"}, 741 {0x000F0000, GetTransferEndEvent, "GetTransferEndEvent"},
729 {0x00100102, SetSendingY, "SetSendingY"}, 742 {0x00100102, SetSendingY, "SetSendingY"},
730 {0x00110102, SetSendingU, "SetSendingU"}, 743 {0x00110102, SetSendingU, "SetSendingU"},
731 {0x00120102, SetSendingV, "SetSendingV"}, 744 {0x00120102, SetSendingV, "SetSendingV"},
732 {0x00130102, SetSendingYUYV, "SetSendingYUYV"}, 745 {0x00130102, SetSendingYUYV, "SetSendingYUYV"},
733 {0x00140000, IsFinishedSendingYuv, "IsFinishedSendingYuv"}, 746 {0x00140000, IsFinishedSendingYuv, "IsFinishedSendingYuv"},
734 {0x00150000, IsFinishedSendingY, "IsFinishedSendingY"}, 747 {0x00150000, IsFinishedSendingY, "IsFinishedSendingY"},
735 {0x00160000, IsFinishedSendingU, "IsFinishedSendingU"}, 748 {0x00160000, IsFinishedSendingU, "IsFinishedSendingU"},
736 {0x00170000, IsFinishedSendingV, "IsFinishedSendingV"}, 749 {0x00170000, IsFinishedSendingV, "IsFinishedSendingV"},
737 {0x00180102, SetReceiving, "SetReceiving"}, 750 {0x00180102, SetReceiving, "SetReceiving"},
738 {0x00190000, IsFinishedReceiving, "IsFinishedReceiving"}, 751 {0x00190000, IsFinishedReceiving, "IsFinishedReceiving"},
739 {0x001A0040, SetInputLineWidth, "SetInputLineWidth"}, 752 {0x001A0040, SetInputLineWidth, "SetInputLineWidth"},
740 {0x001B0000, GetInputLineWidth, "GetInputLineWidth"}, 753 {0x001B0000, GetInputLineWidth, "GetInputLineWidth"},
741 {0x001C0040, SetInputLines, "SetInputLines"}, 754 {0x001C0040, SetInputLines, "SetInputLines"},
742 {0x001D0000, GetInputLines, "GetInputLines"}, 755 {0x001D0000, GetInputLines, "GetInputLines"},
743 {0x001E0100, SetCoefficient, "SetCoefficient"}, 756 {0x001E0100, SetCoefficient, "SetCoefficient"},
744 {0x001F0000, GetCoefficient, "GetCoefficient"}, 757 {0x001F0000, GetCoefficient, "GetCoefficient"},
745 {0x00200040, SetStandardCoefficient, "SetStandardCoefficient"}, 758 {0x00200040, SetStandardCoefficient, "SetStandardCoefficient"},
746 {0x00210040, GetStandardCoefficient, "GetStandardCoefficient"}, 759 {0x00210040, GetStandardCoefficient, "GetStandardCoefficient"},
747 {0x00220040, SetAlpha, "SetAlpha"}, 760 {0x00220040, SetAlpha, "SetAlpha"},
748 {0x00230000, GetAlpha, "GetAlpha"}, 761 {0x00230000, GetAlpha, "GetAlpha"},
749 {0x00240200, SetDitheringWeightParams,"SetDitheringWeightParams"}, 762 {0x00240200, SetDitheringWeightParams, "SetDitheringWeightParams"},
750 {0x00250000, GetDitheringWeightParams,"GetDitheringWeightParams"}, 763 {0x00250000, GetDitheringWeightParams, "GetDitheringWeightParams"},
751 {0x00260000, StartConversion, "StartConversion"}, 764 {0x00260000, StartConversion, "StartConversion"},
752 {0x00270000, StopConversion, "StopConversion"}, 765 {0x00270000, StopConversion, "StopConversion"},
753 {0x00280000, IsBusyConversion, "IsBusyConversion"}, 766 {0x00280000, IsBusyConversion, "IsBusyConversion"},
754 {0x002901C0, SetPackageParameter, "SetPackageParameter"}, 767 {0x002901C0, SetPackageParameter, "SetPackageParameter"},
755 {0x002A0000, PingProcess, "PingProcess"}, 768 {0x002A0000, PingProcess, "PingProcess"},
756 {0x002B0000, DriverInitialize, "DriverInitialize"}, 769 {0x002B0000, DriverInitialize, "DriverInitialize"},
757 {0x002C0000, DriverFinalize, "DriverFinalize"}, 770 {0x002C0000, DriverFinalize, "DriverFinalize"},
758 {0x002D0000, GetPackageParameter, "GetPackageParameter"}, 771 {0x002D0000, GetPackageParameter, "GetPackageParameter"},
759}; 772};
760 773
761//////////////////////////////////////////////////////////////////////////////////////////////////// 774////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/y2r_u.h b/src/core/hle/service/y2r_u.h
index 95fa2fdb7..1b47b5322 100644
--- a/src/core/hle/service/y2r_u.h
+++ b/src/core/hle/service/y2r_u.h
@@ -6,9 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <string> 8#include <string>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11
12#include "core/hle/result.h" 10#include "core/hle/result.h"
13#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
14 12
diff --git a/src/core/hle/shared_page.cpp b/src/core/hle/shared_page.cpp
index 4d9272923..d0d92487d 100644
--- a/src/core/hle/shared_page.cpp
+++ b/src/core/hle/shared_page.cpp
@@ -5,7 +5,6 @@
5#include <chrono> 5#include <chrono>
6#include <cstring> 6#include <cstring>
7#include <ctime> 7#include <ctime>
8
9#include "core/core_timing.h" 8#include "core/core_timing.h"
10#include "core/hle/shared_page.h" 9#include "core/hle/shared_page.h"
11 10
@@ -52,8 +51,8 @@ static u64 GetSystemTime() {
52} 51}
53 52
54static void UpdateTimeCallback(u64 userdata, int cycles_late) { 53static void UpdateTimeCallback(u64 userdata, int cycles_late) {
55 DateTime& date_time = shared_page.date_time_counter % 2 ? 54 DateTime& date_time =
56 shared_page.date_time_0 : shared_page.date_time_1; 55 shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1;
57 56
58 date_time.date_time = GetSystemTime(); 57 date_time.date_time = GetSystemTime();
59 date_time.update_tick = CoreTiming::GetTicks(); 58 date_time.update_tick = CoreTiming::GetTicks();
@@ -74,7 +73,8 @@ void Init() {
74 // Some games wait until this value becomes 0x1, before asking running_hw 73 // Some games wait until this value becomes 0x1, before asking running_hw
75 shared_page.unknown_value = 0x1; 74 shared_page.unknown_value = 0x1;
76 75
77 update_time_event = CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback); 76 update_time_event =
77 CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback);
78 CoreTiming::ScheduleEvent(0, update_time_event); 78 CoreTiming::ScheduleEvent(0, update_time_event);
79} 79}
80 80
diff --git a/src/core/hle/shared_page.h b/src/core/hle/shared_page.h
index cd9246726..106e47efc 100644
--- a/src/core/hle/shared_page.h
+++ b/src/core/hle/shared_page.h
@@ -13,7 +13,6 @@
13#include "common/common_funcs.h" 13#include "common/common_funcs.h"
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "common/swap.h" 15#include "common/swap.h"
16
17#include "core/memory.h" 16#include "core/memory.h"
18 17
19//////////////////////////////////////////////////////////////////////////////////////////////////// 18////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -32,27 +31,28 @@ static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong");
32 31
33struct SharedPageDef { 32struct SharedPageDef {
34 // Most of these names are taken from the 3dbrew page linked above. 33 // Most of these names are taken from the 3dbrew page linked above.
35 u32_le date_time_counter; // 0 34 u32_le date_time_counter; // 0
36 u8 running_hw; // 4 35 u8 running_hw; // 4
37 /// "Microcontroller hardware info" 36 /// "Microcontroller hardware info"
38 u8 mcu_hw_info; // 5 37 u8 mcu_hw_info; // 5
39 INSERT_PADDING_BYTES(0x20 - 0x6); // 6 38 INSERT_PADDING_BYTES(0x20 - 0x6); // 6
40 DateTime date_time_0; // 20 39 DateTime date_time_0; // 20
41 DateTime date_time_1; // 40 40 DateTime date_time_1; // 40
42 u8 wifi_macaddr[6]; // 60 41 u8 wifi_macaddr[6]; // 60
43 u8 wifi_link_level; // 66 42 u8 wifi_link_level; // 66
44 u8 wifi_unknown2; // 67 43 u8 wifi_unknown2; // 67
45 INSERT_PADDING_BYTES(0x80 - 0x68); // 68 44 INSERT_PADDING_BYTES(0x80 - 0x68); // 68
46 float_le sliderstate_3d; // 80 45 float_le sliderstate_3d; // 80
47 u8 ledstate_3d; // 84 46 u8 ledstate_3d; // 84
48 INSERT_PADDING_BYTES(1); // 85 47 INSERT_PADDING_BYTES(1); // 85
49 u8 unknown_value; // 86 48 u8 unknown_value; // 86
50 INSERT_PADDING_BYTES(0xA0 - 0x87); // 87 49 INSERT_PADDING_BYTES(0xA0 - 0x87); // 87
51 u64_le menu_title_id; // A0 50 u64_le menu_title_id; // A0
52 u64_le active_menu_title_id; // A8 51 u64_le active_menu_title_id; // A8
53 INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0 52 INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0
54}; 53};
55static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong"); 54static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE,
55 "Shared page structure size is wrong");
56 56
57extern SharedPageDef shared_page; 57extern SharedPageDef shared_page;
58 58
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 5d71d5619..02b397eba 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -3,16 +3,14 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map> 5#include <map>
6
7#include "common/logging/log.h" 6#include "common/logging/log.h"
8#include "common/microprofile.h" 7#include "common/microprofile.h"
9#include "common/scope_exit.h" 8#include "common/scope_exit.h"
10#include "common/string_util.h" 9#include "common/string_util.h"
11#include "common/symbols.h" 10#include "common/symbols.h"
12
13#include "core/core_timing.h"
14#include "core/arm/arm_interface.h" 11#include "core/arm/arm_interface.h"
15 12#include "core/core_timing.h"
13#include "core/hle/function_wrappers.h"
16#include "core/hle/kernel/address_arbiter.h" 14#include "core/hle/kernel/address_arbiter.h"
17#include "core/hle/kernel/client_port.h" 15#include "core/hle/kernel/client_port.h"
18#include "core/hle/kernel/event.h" 16#include "core/hle/kernel/event.h"
@@ -26,8 +24,6 @@
26#include "core/hle/kernel/thread.h" 24#include "core/hle/kernel/thread.h"
27#include "core/hle/kernel/timer.h" 25#include "core/hle/kernel/timer.h"
28#include "core/hle/kernel/vm_manager.h" 26#include "core/hle/kernel/vm_manager.h"
29
30#include "core/hle/function_wrappers.h"
31#include "core/hle/result.h" 27#include "core/hle/result.h"
32#include "core/hle/service/service.h" 28#include "core/hle/service/service.h"
33 29
@@ -40,43 +36,46 @@ using Kernel::ERR_INVALID_HANDLE;
40namespace SVC { 36namespace SVC {
41 37
42const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, 38const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel,
43 ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA 39 ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA
44const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, 40const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS,
45 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E 41 ErrorSummary::InvalidArgument,
46 42 ErrorLevel::Usage); // 0xE0E0181E
47const ResultCode ERR_MISALIGNED_ADDRESS{ // 0xE0E01BF1 43
48 ErrorDescription::MisalignedAddress, ErrorModule::OS, 44const ResultCode ERR_MISALIGNED_ADDRESS{// 0xE0E01BF1
49 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 45 ErrorDescription::MisalignedAddress, ErrorModule::OS,
50const ResultCode ERR_MISALIGNED_SIZE{ // 0xE0E01BF2 46 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
51 ErrorDescription::MisalignedSize, ErrorModule::OS, 47const ResultCode ERR_MISALIGNED_SIZE{// 0xE0E01BF2
52 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 48 ErrorDescription::MisalignedSize, ErrorModule::OS,
53const ResultCode ERR_INVALID_COMBINATION{ // 0xE0E01BEE 49 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
54 ErrorDescription::InvalidCombination, ErrorModule::OS, 50const ResultCode ERR_INVALID_COMBINATION{// 0xE0E01BEE
55 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 51 ErrorDescription::InvalidCombination, ErrorModule::OS,
52 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
56 53
57enum ControlMemoryOperation { 54enum ControlMemoryOperation {
58 MEMOP_FREE = 1, 55 MEMOP_FREE = 1,
59 MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel 56 MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel
60 MEMOP_COMMIT = 3, 57 MEMOP_COMMIT = 3,
61 MEMOP_MAP = 4, 58 MEMOP_MAP = 4,
62 MEMOP_UNMAP = 5, 59 MEMOP_UNMAP = 5,
63 MEMOP_PROTECT = 6, 60 MEMOP_PROTECT = 6,
64 MEMOP_OPERATION_MASK = 0xFF, 61 MEMOP_OPERATION_MASK = 0xFF,
65 62
66 MEMOP_REGION_APP = 0x100, 63 MEMOP_REGION_APP = 0x100,
67 MEMOP_REGION_SYSTEM = 0x200, 64 MEMOP_REGION_SYSTEM = 0x200,
68 MEMOP_REGION_BASE = 0x300, 65 MEMOP_REGION_BASE = 0x300,
69 MEMOP_REGION_MASK = 0xF00, 66 MEMOP_REGION_MASK = 0xF00,
70 67
71 MEMOP_LINEAR = 0x10000, 68 MEMOP_LINEAR = 0x10000,
72}; 69};
73 70
74/// Map application or GSP heap memory 71/// Map application or GSP heap memory
75static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { 72static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size,
73 u32 permissions) {
76 using namespace Kernel; 74 using namespace Kernel;
77 75
78 LOG_DEBUG(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=0x%X, permissions=0x%08X", 76 LOG_DEBUG(Kernel_SVC,
79 operation, addr0, addr1, size, permissions); 77 "called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=0x%X, permissions=0x%08X",
78 operation, addr0, addr1, size, permissions);
80 79
81 if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) { 80 if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) {
82 return ERR_MISALIGNED_ADDRESS; 81 return ERR_MISALIGNED_ADDRESS;
@@ -89,7 +88,8 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
89 operation &= ~MEMOP_REGION_MASK; 88 operation &= ~MEMOP_REGION_MASK;
90 89
91 if (region != 0) { 90 if (region != 0) {
92 LOG_WARNING(Kernel_SVC, "ControlMemory with specified region not supported, region=%X", region); 91 LOG_WARNING(Kernel_SVC, "ControlMemory with specified region not supported, region=%X",
92 region);
93 } 93 }
94 94
95 if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) { 95 if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) {
@@ -100,15 +100,17 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
100 auto& process = *g_current_process; 100 auto& process = *g_current_process;
101 101
102 switch (operation & MEMOP_OPERATION_MASK) { 102 switch (operation & MEMOP_OPERATION_MASK) {
103 case MEMOP_FREE: 103 case MEMOP_FREE: {
104 { 104 // 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? 105 // SharedMemory pointing to it?
106 if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) { 106 if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) {
107 ResultCode result = process.HeapFree(addr0, size); 107 ResultCode result = process.HeapFree(addr0, size);
108 if (result.IsError()) return result; 108 if (result.IsError())
109 return result;
109 } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) { 110 } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) {
110 ResultCode result = process.LinearFree(addr0, size); 111 ResultCode result = process.LinearFree(addr0, size);
111 if (result.IsError()) return result; 112 if (result.IsError())
113 return result;
112 } else { 114 } else {
113 return ERR_INVALID_ADDRESS; 115 return ERR_INVALID_ADDRESS;
114 } 116 }
@@ -116,8 +118,7 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
116 break; 118 break;
117 } 119 }
118 120
119 case MEMOP_COMMIT: 121 case MEMOP_COMMIT: {
120 {
121 if (operation & MEMOP_LINEAR) { 122 if (operation & MEMOP_LINEAR) {
122 CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions)); 123 CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions));
123 } else { 124 } else {
@@ -126,23 +127,26 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
126 break; 127 break;
127 } 128 }
128 129
129 case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented 130 case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is
130 { 131 // implemented
131 CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions)); 132 {
132 break; 133 CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions));
133 } 134 break;
135 }
134 136
135 case MEMOP_UNMAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented 137 case MEMOP_UNMAP: // TODO: This is just a hack to avoid regressions until memory aliasing is
136 { 138 // implemented
137 ResultCode result = process.HeapFree(addr0, size); 139 {
138 if (result.IsError()) return result; 140 ResultCode result = process.HeapFree(addr0, size);
139 break; 141 if (result.IsError())
140 } 142 return result;
143 break;
144 }
141 145
142 case MEMOP_PROTECT: 146 case MEMOP_PROTECT: {
143 {
144 ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions); 147 ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions);
145 if (result.IsError()) return result; 148 if (result.IsError())
149 return result;
146 break; 150 break;
147 } 151 }
148 152
@@ -161,8 +165,9 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
161 using Kernel::SharedMemory; 165 using Kernel::SharedMemory;
162 using Kernel::MemoryPermission; 166 using Kernel::MemoryPermission;
163 167
164 LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", 168 LOG_TRACE(Kernel_SVC,
165 handle, addr, permissions, other_permissions); 169 "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
170 handle, addr, permissions, other_permissions);
166 171
167 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); 172 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
168 if (shared_memory == nullptr) 173 if (shared_memory == nullptr)
@@ -179,12 +184,13 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
179 case MemoryPermission::ReadWriteExecute: 184 case MemoryPermission::ReadWriteExecute:
180 case MemoryPermission::DontCare: 185 case MemoryPermission::DontCare:
181 return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type, 186 return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type,
182 static_cast<MemoryPermission>(other_permissions)); 187 static_cast<MemoryPermission>(other_permissions));
183 default: 188 default:
184 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); 189 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
185 } 190 }
186 191
187 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 192 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
193 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
188} 194}
189 195
190static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) { 196static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) {
@@ -249,7 +255,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
249 return ERR_INVALID_HANDLE; 255 return ERR_INVALID_HANDLE;
250 256
251 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, 257 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle,
252 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); 258 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds);
253 259
254 HLE::Reschedule(__func__); 260 HLE::Reschedule(__func__);
255 261
@@ -257,7 +263,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
257 if (object->ShouldWait()) { 263 if (object->ShouldWait()) {
258 264
259 object->AddWaitingThread(thread); 265 object->AddWaitingThread(thread);
260 Kernel::WaitCurrentThread_WaitSynchronization({ object }, false, false); 266 Kernel::WaitCurrentThread_WaitSynchronization({object}, false, false);
261 267
262 // Create an event to wake the thread up after the specified nanosecond delay has passed 268 // Create an event to wake the thread up after the specified nanosecond delay has passed
263 thread->WakeAfterDelay(nano_seconds); 269 thread->WakeAfterDelay(nano_seconds);
@@ -272,7 +278,8 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
272} 278}
273 279
274/// Wait for the given handles to synchronize, timeout after the specified nanoseconds 280/// 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) { 281static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all,
282 s64 nano_seconds) {
276 bool wait_thread = !wait_all; 283 bool wait_thread = !wait_all;
277 int handle_index = 0; 284 int handle_index = 0;
278 Kernel::Thread* thread = Kernel::GetCurrentThread(); 285 Kernel::Thread* thread = Kernel::GetCurrentThread();
@@ -281,7 +288,8 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
281 288
282 // Check if 'handles' is invalid 289 // Check if 'handles' is invalid
283 if (handles == nullptr) 290 if (handles == nullptr)
284 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 291 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel,
292 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
285 293
286 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If 294 // 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. 295 // this happens, the running application will crash.
@@ -289,7 +297,8 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
289 297
290 // Check if 'handle_count' is invalid 298 // Check if 'handle_count' is invalid
291 if (handle_count < 0) 299 if (handle_count < 0)
292 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 300 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS,
301 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
293 302
294 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if 303 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if
295 // necessary 304 // necessary
@@ -329,7 +338,9 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
329 } 338 }
330 } 339 }
331 340
332 SCOPE_EXIT({HLE::Reschedule("WaitSynchronizationN");}); // Reschedule after putting the threads to sleep. 341 SCOPE_EXIT({
342 HLE::Reschedule("WaitSynchronizationN");
343 }); // Reschedule after putting the threads to sleep.
333 344
334 // If thread should wait, then set its state to waiting 345 // If thread should wait, then set its state to waiting
335 if (wait_thread) { 346 if (wait_thread) {
@@ -386,18 +397,19 @@ static ResultCode CreateAddressArbiter(Handle* out_handle) {
386} 397}
387 398
388/// Arbitrate address 399/// Arbitrate address
389static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds) { 400static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value,
401 s64 nanoseconds) {
390 using Kernel::AddressArbiter; 402 using Kernel::AddressArbiter;
391 403
392 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle, 404 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle,
393 address, type, value); 405 address, type, value);
394 406
395 SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle); 407 SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle);
396 if (arbiter == nullptr) 408 if (arbiter == nullptr)
397 return ERR_INVALID_HANDLE; 409 return ERR_INVALID_HANDLE;
398 410
399 auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), 411 auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), address, value,
400 address, value, nanoseconds); 412 nanoseconds);
401 413
402 return res; 414 return res;
403} 415}
@@ -406,10 +418,18 @@ static void Break(u8 break_reason) {
406 LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); 418 LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
407 std::string reason_str; 419 std::string reason_str;
408 switch (break_reason) { 420 switch (break_reason) {
409 case 0: reason_str = "PANIC"; break; 421 case 0:
410 case 1: reason_str = "ASSERT"; break; 422 reason_str = "PANIC";
411 case 2: reason_str = "USER"; break; 423 break;
412 default: reason_str = "UNKNOWN"; break; 424 case 1:
425 reason_str = "ASSERT";
426 break;
427 case 2:
428 reason_str = "USER";
429 break;
430 default:
431 reason_str = "UNKNOWN";
432 break;
413 } 433 }
414 LOG_CRITICAL(Debug_Emulated, "Break reason: %s", reason_str.c_str()); 434 LOG_CRITICAL(Debug_Emulated, "Break reason: %s", reason_str.c_str());
415} 435}
@@ -423,7 +443,8 @@ static void OutputDebugString(const char* string) {
423static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) { 443static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) {
424 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); 444 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
425 445
426 SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); 446 SharedPtr<Kernel::Process> process =
447 Kernel::g_handle_table.Get<Kernel::Process>(process_handle);
427 if (process == nullptr) 448 if (process == nullptr)
428 return ERR_INVALID_HANDLE; 449 return ERR_INVALID_HANDLE;
429 450
@@ -433,12 +454,13 @@ static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle
433} 454}
434 455
435/// Get resource limit current values 456/// Get resource limit current values
436static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names, 457static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle,
437 u32 name_count) { 458 u32* names, u32 name_count) {
438 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", 459 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
439 resource_limit_handle, names, name_count); 460 resource_limit_handle, names, name_count);
440 461
441 SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); 462 SharedPtr<Kernel::ResourceLimit> resource_limit =
463 Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
442 if (resource_limit == nullptr) 464 if (resource_limit == nullptr)
443 return ERR_INVALID_HANDLE; 465 return ERR_INVALID_HANDLE;
444 466
@@ -450,11 +472,12 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_lim
450 472
451/// Get resource limit max values 473/// Get resource limit max values
452static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, 474static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names,
453 u32 name_count) { 475 u32 name_count) {
454 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", 476 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
455 resource_limit_handle, names, name_count); 477 resource_limit_handle, names, name_count);
456 478
457 SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); 479 SharedPtr<Kernel::ResourceLimit> resource_limit =
480 Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
458 if (resource_limit == nullptr) 481 if (resource_limit == nullptr)
459 return ERR_INVALID_HANDLE; 482 return ERR_INVALID_HANDLE;
460 483
@@ -465,7 +488,8 @@ static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit
465} 488}
466 489
467/// Creates a new thread 490/// Creates a new thread
468static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { 491static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg,
492 u32 stack_top, s32 processor_id) {
469 using Kernel::Thread; 493 using Kernel::Thread;
470 494
471 std::string name; 495 std::string name;
@@ -499,20 +523,23 @@ static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point
499 } 523 }
500 524
501 if (processor_id == THREADPROCESSORID_1 || processor_id == THREADPROCESSORID_ALL || 525 if (processor_id == THREADPROCESSORID_1 || processor_id == THREADPROCESSORID_ALL ||
502 (processor_id == THREADPROCESSORID_DEFAULT && Kernel::g_current_process->ideal_processor == THREADPROCESSORID_1)) { 526 (processor_id == THREADPROCESSORID_DEFAULT &&
503 LOG_WARNING(Kernel_SVC, "Newly created thread is allowed to be run in the SysCore, unimplemented."); 527 Kernel::g_current_process->ideal_processor == THREADPROCESSORID_1)) {
528 LOG_WARNING(Kernel_SVC,
529 "Newly created thread is allowed to be run in the SysCore, unimplemented.");
504 } 530 }
505 531
506 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create( 532 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create(name, entry_point, priority,
507 name, entry_point, priority, arg, processor_id, stack_top)); 533 arg, processor_id, stack_top));
508 534
509 thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000 535 thread->context.fpscr =
536 FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000
510 537
511 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); 538 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread)));
512 539
513 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " 540 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, 541 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X",
515 name.c_str(), arg, stack_top, priority, processor_id, *out_handle); 542 entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle);
516 543
517 return RESULT_SUCCESS; 544 return RESULT_SUCCESS;
518} 545}
@@ -552,7 +579,7 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
552 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); 579 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
553 580
554 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", 581 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
555 initial_locked ? "true" : "false", *out_handle); 582 initial_locked ? "true" : "false", *out_handle);
556 583
557 return RESULT_SUCCESS; 584 return RESULT_SUCCESS;
558} 585}
@@ -576,7 +603,8 @@ static ResultCode ReleaseMutex(Handle handle) {
576static ResultCode GetProcessId(u32* process_id, Handle process_handle) { 603static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
577 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); 604 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
578 605
579 const SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); 606 const SharedPtr<Kernel::Process> process =
607 Kernel::g_handle_table.Get<Kernel::Process>(process_handle);
580 if (process == nullptr) 608 if (process == nullptr)
581 return ERR_INVALID_HANDLE; 609 return ERR_INVALID_HANDLE;
582 610
@@ -588,7 +616,8 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
588static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { 616static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
589 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); 617 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
590 618
591 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle); 619 const SharedPtr<Kernel::Thread> thread =
620 Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle);
592 if (thread == nullptr) 621 if (thread == nullptr)
593 return ERR_INVALID_HANDLE; 622 return ERR_INVALID_HANDLE;
594 623
@@ -620,7 +649,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))); 649 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore)));
621 650
622 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", 651 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
623 initial_count, max_count, *out_handle); 652 initial_count, max_count, *out_handle);
624 return RESULT_SUCCESS; 653 return RESULT_SUCCESS;
625} 654}
626 655
@@ -640,7 +669,8 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count)
640} 669}
641 670
642/// Query process memory 671/// Query process memory
643static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info, Handle process_handle, u32 addr) { 672static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info,
673 Handle process_handle, u32 addr) {
644 using Kernel::Process; 674 using Kernel::Process;
645 Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle); 675 Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle);
646 if (process == nullptr) 676 if (process == nullptr)
@@ -649,7 +679,8 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_inf
649 auto vma = process->vm_manager.FindVMA(addr); 679 auto vma = process->vm_manager.FindVMA(addr);
650 680
651 if (vma == Kernel::g_current_process->vm_manager.vma_map.end()) 681 if (vma == Kernel::g_current_process->vm_manager.vma_map.end())
652 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 682 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
683 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
653 684
654 memory_info->base_address = vma->second.base; 685 memory_info->base_address = vma->second.base;
655 memory_info->permission = static_cast<u32>(vma->second.permissions); 686 memory_info->permission = static_cast<u32>(vma->second.permissions);
@@ -673,8 +704,8 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
673 SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type)); 704 SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type));
674 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); 705 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
675 706
676 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 707 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
677 reset_type, *out_handle); 708 *out_handle);
678 return RESULT_SUCCESS; 709 return RESULT_SUCCESS;
679} 710}
680 711
@@ -719,8 +750,8 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
719 SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type)); 750 SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type));
720 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); 751 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
721 752
722 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 753 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
723 reset_type, *out_handle); 754 *out_handle);
724 return RESULT_SUCCESS; 755 return RESULT_SUCCESS;
725} 756}
726 757
@@ -783,17 +814,19 @@ static void SleepThread(s64 nanoseconds) {
783static s64 GetSystemTick() { 814static s64 GetSystemTick() {
784 s64 result = CoreTiming::GetTicks(); 815 s64 result = CoreTiming::GetTicks();
785 // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end. 816 // 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 817 Core::g_app_core->AddTicks(
818 150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b
787 return result; 819 return result;
788} 820}
789 821
790/// Creates a memory block at the specified address with the specified permissions and size 822/// 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, 823static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission,
792 u32 other_permission) { 824 u32 other_permission) {
793 using Kernel::SharedMemory; 825 using Kernel::SharedMemory;
794 826
795 if (size % Memory::PAGE_SIZE != 0) 827 if (size % Memory::PAGE_SIZE != 0)
796 return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 828 return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS,
829 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
797 830
798 SharedPtr<SharedMemory> shared_memory = nullptr; 831 SharedPtr<SharedMemory> shared_memory = nullptr;
799 832
@@ -818,25 +851,29 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
818 ErrorSummary::InvalidArgument, ErrorLevel::Usage); 851 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
819 852
820 if (addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) { 853 if (addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) {
821 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 854 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
855 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
822 } 856 }
823 857
824 // When trying to create a memory block with address = 0, 858 // When trying to create a memory block with address = 0,
825 // if the process has the Shared Device Memory flag in the exheader, 859 // 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. 860 // then we have to allocate from the same region as the caller process instead of the BASE
861 // region.
827 Kernel::MemoryRegion region = Kernel::MemoryRegion::BASE; 862 Kernel::MemoryRegion region = Kernel::MemoryRegion::BASE;
828 if (addr == 0 && Kernel::g_current_process->flags.shared_device_mem) 863 if (addr == 0 && Kernel::g_current_process->flags.shared_device_mem)
829 region = Kernel::g_current_process->flags.memory_region; 864 region = Kernel::g_current_process->flags.memory_region;
830 865
831 shared_memory = SharedMemory::Create(Kernel::g_current_process, size, 866 shared_memory = SharedMemory::Create(
832 static_cast<MemoryPermission>(my_permission), static_cast<MemoryPermission>(other_permission), addr, region); 867 Kernel::g_current_process, size, static_cast<MemoryPermission>(my_permission),
868 static_cast<MemoryPermission>(other_permission), addr, region);
833 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); 869 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
834 870
835 LOG_WARNING(Kernel_SVC, "called addr=0x%08X", addr); 871 LOG_WARNING(Kernel_SVC, "called addr=0x%08X", addr);
836 return RESULT_SUCCESS; 872 return RESULT_SUCCESS;
837} 873}
838 874
839static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name, u32 max_sessions) { 875static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name,
876 u32 max_sessions) {
840 // TODO(Subv): Implement named ports. 877 // TODO(Subv): Implement named ports.
841 ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented"); 878 ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented");
842 879
@@ -845,9 +882,12 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, const cha
845 using Kernel::SharedPtr; 882 using Kernel::SharedPtr;
846 883
847 auto ports = ServerPort::CreatePortPair(max_sessions); 884 auto ports = ServerPort::CreatePortPair(max_sessions);
848 CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports)))); 885 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. 886 std::move(std::get<SharedPtr<ClientPort>>(ports))));
850 CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ServerPort>>(ports)))); 887 // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
888 // created.
889 CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create(
890 std::move(std::get<SharedPtr<ServerPort>>(ports))));
851 891
852 LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions); 892 LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions);
853 return RESULT_SUCCESS; 893 return RESULT_SUCCESS;
@@ -862,9 +902,9 @@ static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
862 case SystemInfoType::REGION_MEMORY_USAGE: 902 case SystemInfoType::REGION_MEMORY_USAGE:
863 switch ((SystemInfoMemUsageRegion)param) { 903 switch ((SystemInfoMemUsageRegion)param) {
864 case SystemInfoMemUsageRegion::ALL: 904 case SystemInfoMemUsageRegion::ALL:
865 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used 905 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used +
866 + Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used 906 Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used +
867 + Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used; 907 Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used;
868 break; 908 break;
869 case SystemInfoMemUsageRegion::APPLICATION: 909 case SystemInfoMemUsageRegion::APPLICATION:
870 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used; 910 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used;
@@ -912,7 +952,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 952 // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure
913 // what's the difference between them. 953 // what's the difference between them.
914 *out = process->heap_used + process->linear_heap_used + process->misc_memory_used; 954 *out = process->heap_used + process->linear_heap_used + process->misc_memory_used;
915 if(*out % Memory::PAGE_SIZE != 0) { 955 if (*out % Memory::PAGE_SIZE != 0) {
916 LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned"); 956 LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned");
917 return ERR_MISALIGNED_SIZE; 957 return ERR_MISALIGNED_SIZE;
918 } 958 }
@@ -935,12 +975,12 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
935 975
936 if (type >= 21 && type <= 23) { 976 if (type >= 21 && type <= 23) {
937 return ResultCode( // 0xE0E01BF4 977 return ResultCode( // 0xE0E01BF4
938 ErrorDescription::NotImplemented, ErrorModule::OS, 978 ErrorDescription::NotImplemented, ErrorModule::OS, ErrorSummary::InvalidArgument,
939 ErrorSummary::InvalidArgument, ErrorLevel::Usage); 979 ErrorLevel::Usage);
940 } else { 980 } else {
941 return ResultCode( // 0xD8E007ED 981 return ResultCode( // 0xD8E007ED
942 ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, 982 ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
943 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 983 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
944 } 984 }
945 break; 985 break;
946 } 986 }
@@ -949,142 +989,142 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
949} 989}
950 990
951namespace { 991namespace {
952 struct FunctionDef { 992struct FunctionDef {
953 using Func = void(); 993 using Func = void();
954 994
955 u32 id; 995 u32 id;
956 Func* func; 996 Func* func;
957 const char* name; 997 const char* name;
958 }; 998};
959} 999}
960 1000
961static const FunctionDef SVC_Table[] = { 1001static const FunctionDef SVC_Table[] = {
962 {0x00, nullptr, "Unknown"}, 1002 {0x00, nullptr, "Unknown"},
963 {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"}, 1003 {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"},
964 {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"}, 1004 {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"},
965 {0x03, nullptr, "ExitProcess"}, 1005 {0x03, nullptr, "ExitProcess"},
966 {0x04, nullptr, "GetProcessAffinityMask"}, 1006 {0x04, nullptr, "GetProcessAffinityMask"},
967 {0x05, nullptr, "SetProcessAffinityMask"}, 1007 {0x05, nullptr, "SetProcessAffinityMask"},
968 {0x06, nullptr, "GetProcessIdealProcessor"}, 1008 {0x06, nullptr, "GetProcessIdealProcessor"},
969 {0x07, nullptr, "SetProcessIdealProcessor"}, 1009 {0x07, nullptr, "SetProcessIdealProcessor"},
970 {0x08, HLE::Wrap<CreateThread>, "CreateThread"}, 1010 {0x08, HLE::Wrap<CreateThread>, "CreateThread"},
971 {0x09, ExitThread, "ExitThread"}, 1011 {0x09, ExitThread, "ExitThread"},
972 {0x0A, HLE::Wrap<SleepThread>, "SleepThread"}, 1012 {0x0A, HLE::Wrap<SleepThread>, "SleepThread"},
973 {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"}, 1013 {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"},
974 {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"}, 1014 {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"},
975 {0x0D, nullptr, "GetThreadAffinityMask"}, 1015 {0x0D, nullptr, "GetThreadAffinityMask"},
976 {0x0E, nullptr, "SetThreadAffinityMask"}, 1016 {0x0E, nullptr, "SetThreadAffinityMask"},
977 {0x0F, nullptr, "GetThreadIdealProcessor"}, 1017 {0x0F, nullptr, "GetThreadIdealProcessor"},
978 {0x10, nullptr, "SetThreadIdealProcessor"}, 1018 {0x10, nullptr, "SetThreadIdealProcessor"},
979 {0x11, nullptr, "GetCurrentProcessorNumber"}, 1019 {0x11, nullptr, "GetCurrentProcessorNumber"},
980 {0x12, nullptr, "Run"}, 1020 {0x12, nullptr, "Run"},
981 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, 1021 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"},
982 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, 1022 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"},
983 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"}, 1023 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"},
984 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"}, 1024 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"},
985 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, 1025 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"},
986 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, 1026 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"},
987 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, 1027 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"},
988 {0x1A, HLE::Wrap<CreateTimer>, "CreateTimer"}, 1028 {0x1A, HLE::Wrap<CreateTimer>, "CreateTimer"},
989 {0x1B, HLE::Wrap<SetTimer>, "SetTimer"}, 1029 {0x1B, HLE::Wrap<SetTimer>, "SetTimer"},
990 {0x1C, HLE::Wrap<CancelTimer>, "CancelTimer"}, 1030 {0x1C, HLE::Wrap<CancelTimer>, "CancelTimer"},
991 {0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"}, 1031 {0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"},
992 {0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"}, 1032 {0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"},
993 {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"}, 1033 {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"},
994 {0x20, HLE::Wrap<UnmapMemoryBlock>, "UnmapMemoryBlock"}, 1034 {0x20, HLE::Wrap<UnmapMemoryBlock>, "UnmapMemoryBlock"},
995 {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"}, 1035 {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"},
996 {0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"}, 1036 {0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"},
997 {0x23, HLE::Wrap<CloseHandle>, "CloseHandle"}, 1037 {0x23, HLE::Wrap<CloseHandle>, "CloseHandle"},
998 {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"}, 1038 {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"},
999 {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"}, 1039 {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"},
1000 {0x26, nullptr, "SignalAndWait"}, 1040 {0x26, nullptr, "SignalAndWait"},
1001 {0x27, HLE::Wrap<DuplicateHandle>, "DuplicateHandle"}, 1041 {0x27, HLE::Wrap<DuplicateHandle>, "DuplicateHandle"},
1002 {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"}, 1042 {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"},
1003 {0x29, nullptr, "GetHandleInfo"}, 1043 {0x29, nullptr, "GetHandleInfo"},
1004 {0x2A, HLE::Wrap<GetSystemInfo>, "GetSystemInfo"}, 1044 {0x2A, HLE::Wrap<GetSystemInfo>, "GetSystemInfo"},
1005 {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"}, 1045 {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"},
1006 {0x2C, nullptr, "GetThreadInfo"}, 1046 {0x2C, nullptr, "GetThreadInfo"},
1007 {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"}, 1047 {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"},
1008 {0x2E, nullptr, "SendSyncRequest1"}, 1048 {0x2E, nullptr, "SendSyncRequest1"},
1009 {0x2F, nullptr, "SendSyncRequest2"}, 1049 {0x2F, nullptr, "SendSyncRequest2"},
1010 {0x30, nullptr, "SendSyncRequest3"}, 1050 {0x30, nullptr, "SendSyncRequest3"},
1011 {0x31, nullptr, "SendSyncRequest4"}, 1051 {0x31, nullptr, "SendSyncRequest4"},
1012 {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"}, 1052 {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"},
1013 {0x33, nullptr, "OpenProcess"}, 1053 {0x33, nullptr, "OpenProcess"},
1014 {0x34, nullptr, "OpenThread"}, 1054 {0x34, nullptr, "OpenThread"},
1015 {0x35, HLE::Wrap<GetProcessId>, "GetProcessId"}, 1055 {0x35, HLE::Wrap<GetProcessId>, "GetProcessId"},
1016 {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"}, 1056 {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"},
1017 {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"}, 1057 {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"},
1018 {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"}, 1058 {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"},
1019 {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"}, 1059 {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"},
1020 {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"}, 1060 {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"},
1021 {0x3B, nullptr, "GetThreadContext"}, 1061 {0x3B, nullptr, "GetThreadContext"},
1022 {0x3C, HLE::Wrap<Break>, "Break"}, 1062 {0x3C, HLE::Wrap<Break>, "Break"},
1023 {0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"}, 1063 {0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"},
1024 {0x3E, nullptr, "ControlPerformanceCounter"}, 1064 {0x3E, nullptr, "ControlPerformanceCounter"},
1025 {0x3F, nullptr, "Unknown"}, 1065 {0x3F, nullptr, "Unknown"},
1026 {0x40, nullptr, "Unknown"}, 1066 {0x40, nullptr, "Unknown"},
1027 {0x41, nullptr, "Unknown"}, 1067 {0x41, nullptr, "Unknown"},
1028 {0x42, nullptr, "Unknown"}, 1068 {0x42, nullptr, "Unknown"},
1029 {0x43, nullptr, "Unknown"}, 1069 {0x43, nullptr, "Unknown"},
1030 {0x44, nullptr, "Unknown"}, 1070 {0x44, nullptr, "Unknown"},
1031 {0x45, nullptr, "Unknown"}, 1071 {0x45, nullptr, "Unknown"},
1032 {0x46, nullptr, "Unknown"}, 1072 {0x46, nullptr, "Unknown"},
1033 {0x47, HLE::Wrap<CreatePort>, "CreatePort"}, 1073 {0x47, HLE::Wrap<CreatePort>, "CreatePort"},
1034 {0x48, nullptr, "CreateSessionToPort"}, 1074 {0x48, nullptr, "CreateSessionToPort"},
1035 {0x49, nullptr, "CreateSession"}, 1075 {0x49, nullptr, "CreateSession"},
1036 {0x4A, nullptr, "AcceptSession"}, 1076 {0x4A, nullptr, "AcceptSession"},
1037 {0x4B, nullptr, "ReplyAndReceive1"}, 1077 {0x4B, nullptr, "ReplyAndReceive1"},
1038 {0x4C, nullptr, "ReplyAndReceive2"}, 1078 {0x4C, nullptr, "ReplyAndReceive2"},
1039 {0x4D, nullptr, "ReplyAndReceive3"}, 1079 {0x4D, nullptr, "ReplyAndReceive3"},
1040 {0x4E, nullptr, "ReplyAndReceive4"}, 1080 {0x4E, nullptr, "ReplyAndReceive4"},
1041 {0x4F, nullptr, "ReplyAndReceive"}, 1081 {0x4F, nullptr, "ReplyAndReceive"},
1042 {0x50, nullptr, "BindInterrupt"}, 1082 {0x50, nullptr, "BindInterrupt"},
1043 {0x51, nullptr, "UnbindInterrupt"}, 1083 {0x51, nullptr, "UnbindInterrupt"},
1044 {0x52, nullptr, "InvalidateProcessDataCache"}, 1084 {0x52, nullptr, "InvalidateProcessDataCache"},
1045 {0x53, nullptr, "StoreProcessDataCache"}, 1085 {0x53, nullptr, "StoreProcessDataCache"},
1046 {0x54, nullptr, "FlushProcessDataCache"}, 1086 {0x54, nullptr, "FlushProcessDataCache"},
1047 {0x55, nullptr, "StartInterProcessDma"}, 1087 {0x55, nullptr, "StartInterProcessDma"},
1048 {0x56, nullptr, "StopDma"}, 1088 {0x56, nullptr, "StopDma"},
1049 {0x57, nullptr, "GetDmaState"}, 1089 {0x57, nullptr, "GetDmaState"},
1050 {0x58, nullptr, "RestartDma"}, 1090 {0x58, nullptr, "RestartDma"},
1051 {0x59, nullptr, "Unknown"}, 1091 {0x59, nullptr, "Unknown"},
1052 {0x5A, nullptr, "Unknown"}, 1092 {0x5A, nullptr, "Unknown"},
1053 {0x5B, nullptr, "Unknown"}, 1093 {0x5B, nullptr, "Unknown"},
1054 {0x5C, nullptr, "Unknown"}, 1094 {0x5C, nullptr, "Unknown"},
1055 {0x5D, nullptr, "Unknown"}, 1095 {0x5D, nullptr, "Unknown"},
1056 {0x5E, nullptr, "Unknown"}, 1096 {0x5E, nullptr, "Unknown"},
1057 {0x5F, nullptr, "Unknown"}, 1097 {0x5F, nullptr, "Unknown"},
1058 {0x60, nullptr, "DebugActiveProcess"}, 1098 {0x60, nullptr, "DebugActiveProcess"},
1059 {0x61, nullptr, "BreakDebugProcess"}, 1099 {0x61, nullptr, "BreakDebugProcess"},
1060 {0x62, nullptr, "TerminateDebugProcess"}, 1100 {0x62, nullptr, "TerminateDebugProcess"},
1061 {0x63, nullptr, "GetProcessDebugEvent"}, 1101 {0x63, nullptr, "GetProcessDebugEvent"},
1062 {0x64, nullptr, "ContinueDebugEvent"}, 1102 {0x64, nullptr, "ContinueDebugEvent"},
1063 {0x65, nullptr, "GetProcessList"}, 1103 {0x65, nullptr, "GetProcessList"},
1064 {0x66, nullptr, "GetThreadList"}, 1104 {0x66, nullptr, "GetThreadList"},
1065 {0x67, nullptr, "GetDebugThreadContext"}, 1105 {0x67, nullptr, "GetDebugThreadContext"},
1066 {0x68, nullptr, "SetDebugThreadContext"}, 1106 {0x68, nullptr, "SetDebugThreadContext"},
1067 {0x69, nullptr, "QueryDebugProcessMemory"}, 1107 {0x69, nullptr, "QueryDebugProcessMemory"},
1068 {0x6A, nullptr, "ReadProcessMemory"}, 1108 {0x6A, nullptr, "ReadProcessMemory"},
1069 {0x6B, nullptr, "WriteProcessMemory"}, 1109 {0x6B, nullptr, "WriteProcessMemory"},
1070 {0x6C, nullptr, "SetHardwareBreakPoint"}, 1110 {0x6C, nullptr, "SetHardwareBreakPoint"},
1071 {0x6D, nullptr, "GetDebugThreadParam"}, 1111 {0x6D, nullptr, "GetDebugThreadParam"},
1072 {0x6E, nullptr, "Unknown"}, 1112 {0x6E, nullptr, "Unknown"},
1073 {0x6F, nullptr, "Unknown"}, 1113 {0x6F, nullptr, "Unknown"},
1074 {0x70, nullptr, "ControlProcessMemory"}, 1114 {0x70, nullptr, "ControlProcessMemory"},
1075 {0x71, nullptr, "MapProcessMemory"}, 1115 {0x71, nullptr, "MapProcessMemory"},
1076 {0x72, nullptr, "UnmapProcessMemory"}, 1116 {0x72, nullptr, "UnmapProcessMemory"},
1077 {0x73, nullptr, "CreateCodeSet"}, 1117 {0x73, nullptr, "CreateCodeSet"},
1078 {0x74, nullptr, "RandomStub"}, 1118 {0x74, nullptr, "RandomStub"},
1079 {0x75, nullptr, "CreateProcess"}, 1119 {0x75, nullptr, "CreateProcess"},
1080 {0x76, nullptr, "TerminateProcess"}, 1120 {0x76, nullptr, "TerminateProcess"},
1081 {0x77, nullptr, "SetProcessResourceLimits"}, 1121 {0x77, nullptr, "SetProcessResourceLimits"},
1082 {0x78, nullptr, "CreateResourceLimit"}, 1122 {0x78, nullptr, "CreateResourceLimit"},
1083 {0x79, nullptr, "SetResourceLimitValues"}, 1123 {0x79, nullptr, "SetResourceLimitValues"},
1084 {0x7A, nullptr, "AddCodeSegment"}, 1124 {0x7A, nullptr, "AddCodeSegment"},
1085 {0x7B, nullptr, "Backdoor"}, 1125 {0x7B, nullptr, "Backdoor"},
1086 {0x7C, nullptr, "KernelSetState"}, 1126 {0x7C, nullptr, "KernelSetState"},
1087 {0x7D, HLE::Wrap<QueryProcessMemory>, "QueryProcessMemory"}, 1127 {0x7D, HLE::Wrap<QueryProcessMemory>, "QueryProcessMemory"},
1088}; 1128};
1089 1129
1090static const FunctionDef* GetSVCInfo(u32 func_num) { 1130static const FunctionDef* GetSVCInfo(u32 func_num) {
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index a4dfb7e43..0e6b91e3a 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -5,34 +5,26 @@
5#include <cstring> 5#include <cstring>
6#include <numeric> 6#include <numeric>
7#include <type_traits> 7#include <type_traits>
8
9#include "common/color.h" 8#include "common/color.h"
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12#include "common/microprofile.h" 11#include "common/microprofile.h"
13#include "common/vector_math.h" 12#include "common/vector_math.h"
14
15#include "core/settings.h"
16#include "core/memory.h"
17#include "core/core_timing.h" 13#include "core/core_timing.h"
18
19#include "core/hle/service/gsp_gpu.h" 14#include "core/hle/service/gsp_gpu.h"
20#include "core/hle/service/hid/hid.h" 15#include "core/hle/service/hid/hid.h"
21
22#include "core/hw/hw.h"
23#include "core/hw/gpu.h" 16#include "core/hw/gpu.h"
24 17#include "core/hw/hw.h"
18#include "core/memory.h"
19#include "core/settings.h"
25#include "core/tracer/recorder.h" 20#include "core/tracer/recorder.h"
26
27#include "video_core/command_processor.h" 21#include "video_core/command_processor.h"
22#include "video_core/debug_utils/debug_utils.h"
28#include "video_core/rasterizer_interface.h" 23#include "video_core/rasterizer_interface.h"
29#include "video_core/renderer_base.h" 24#include "video_core/renderer_base.h"
30#include "video_core/utils.h" 25#include "video_core/utils.h"
31#include "video_core/video_core.h" 26#include "video_core/video_core.h"
32 27
33#include "video_core/debug_utils/debug_utils.h"
34
35
36namespace GPU { 28namespace GPU {
37 29
38Regs g_regs; 30Regs g_regs;
@@ -49,7 +41,7 @@ static u64 frame_count;
49static bool last_skip_frame; 41static bool last_skip_frame;
50 42
51template <typename T> 43template <typename T>
52inline void Read(T &var, const u32 raw_addr) { 44inline void Read(T& var, const u32 raw_addr) {
53 u32 addr = raw_addr - HW::VADDR_GPU; 45 u32 addr = raw_addr - HW::VADDR_GPU;
54 u32 index = addr / 4; 46 u32 index = addr / 4;
55 47
@@ -105,8 +97,7 @@ inline void Write(u32 addr, const T data) {
105 97
106 // Memory fills are triggered once the fill value is written. 98 // Memory fills are triggered once the fill value is written.
107 case GPU_REG_INDEX_WORKAROUND(memory_fill_config[0].trigger, 0x00004 + 0x3): 99 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): 100 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)); 101 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]; 102 auto& config = g_regs.memory_fill_config[is_second_filler];
112 103
@@ -125,7 +116,9 @@ inline void Write(u32 addr, const T data) {
125 // regions that were between surfaces or within the touching 116 // regions that were between surfaces or within the touching
126 // ones for cpu to manually fill here. 117 // ones for cpu to manually fill here.
127 if (!VideoCore::g_renderer->Rasterizer()->AccelerateFill(config)) { 118 if (!VideoCore::g_renderer->Rasterizer()->AccelerateFill(config)) {
128 Memory::RasterizerFlushAndInvalidateRegion(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress()); 119 Memory::RasterizerFlushAndInvalidateRegion(config.GetStartAddress(),
120 config.GetEndAddress() -
121 config.GetStartAddress());
129 122
130 if (config.fill_24bit) { 123 if (config.fill_24bit) {
131 // fill with 24-bit values 124 // fill with 24-bit values
@@ -150,7 +143,8 @@ inline void Write(u32 addr, const T data) {
150 } 143 }
151 } 144 }
152 145
153 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress()); 146 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(),
147 config.GetEndAddress());
154 148
155 if (!is_second_filler) { 149 if (!is_second_filler) {
156 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0); 150 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0);
@@ -167,15 +161,15 @@ inline void Write(u32 addr, const T data) {
167 break; 161 break;
168 } 162 }
169 163
170 case GPU_REG_INDEX(display_transfer_config.trigger): 164 case GPU_REG_INDEX(display_transfer_config.trigger): {
171 {
172 MICROPROFILE_SCOPE(GPU_DisplayTransfer); 165 MICROPROFILE_SCOPE(GPU_DisplayTransfer);
173 166
174 const auto& config = g_regs.display_transfer_config; 167 const auto& config = g_regs.display_transfer_config;
175 if (config.trigger & 1) { 168 if (config.trigger & 1) {
176 169
177 if (Pica::g_debug_context) 170 if (Pica::g_debug_context)
178 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::IncomingDisplayTransfer, nullptr); 171 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::IncomingDisplayTransfer,
172 nullptr);
179 173
180 if (!VideoCore::g_renderer->Rasterizer()->AccelerateDisplayTransfer(config)) { 174 if (!VideoCore::g_renderer->Rasterizer()->AccelerateDisplayTransfer(config)) {
181 u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress()); 175 u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress());
@@ -187,17 +181,23 @@ inline void Write(u32 addr, const T data) {
187 u32 output_width = config.texture_copy.output_width * 16; 181 u32 output_width = config.texture_copy.output_width * 16;
188 u32 output_gap = config.texture_copy.output_gap * 16; 182 u32 output_gap = config.texture_copy.output_gap * 16;
189 183
190 size_t contiguous_input_size = config.texture_copy.size / input_width * (input_width + input_gap); 184 size_t contiguous_input_size =
191 Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), static_cast<u32>(contiguous_input_size)); 185 config.texture_copy.size / input_width * (input_width + input_gap);
186 Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(),
187 static_cast<u32>(contiguous_input_size));
192 188
193 size_t contiguous_output_size = config.texture_copy.size / output_width * (output_width + output_gap); 189 size_t contiguous_output_size =
194 Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), static_cast<u32>(contiguous_output_size)); 190 config.texture_copy.size / output_width * (output_width + output_gap);
191 Memory::RasterizerFlushAndInvalidateRegion(
192 config.GetPhysicalOutputAddress(),
193 static_cast<u32>(contiguous_output_size));
195 194
196 u32 remaining_size = config.texture_copy.size; 195 u32 remaining_size = config.texture_copy.size;
197 u32 remaining_input = input_width; 196 u32 remaining_input = input_width;
198 u32 remaining_output = output_width; 197 u32 remaining_output = output_width;
199 while (remaining_size > 0) { 198 while (remaining_size > 0) {
200 u32 copy_size = std::min({ remaining_input, remaining_output, remaining_size }); 199 u32 copy_size =
200 std::min({remaining_input, remaining_output, remaining_size});
201 201
202 std::memcpy(dst_pointer, src_pointer, copy_size); 202 std::memcpy(dst_pointer, src_pointer, copy_size);
203 src_pointer += copy_size; 203 src_pointer += copy_size;
@@ -217,10 +217,11 @@ inline void Write(u32 addr, const T data) {
217 } 217 }
218 } 218 }
219 219
220 LOG_TRACE(HW_GPU, "TextureCopy: 0x%X bytes from 0x%08X(%u+%u)-> 0x%08X(%u+%u), flags 0x%08X", 220 LOG_TRACE(
221 config.texture_copy.size, 221 HW_GPU,
222 config.GetPhysicalInputAddress(), input_width, input_gap, 222 "TextureCopy: 0x%X bytes from 0x%08X(%u+%u)-> 0x%08X(%u+%u), flags 0x%08X",
223 config.GetPhysicalOutputAddress(), output_width, output_gap, 223 config.texture_copy.size, config.GetPhysicalInputAddress(), input_width,
224 input_gap, config.GetPhysicalOutputAddress(), output_width, output_gap,
224 config.flags); 225 config.flags);
225 226
226 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); 227 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF);
@@ -228,7 +229,8 @@ inline void Write(u32 addr, const T data) {
228 } 229 }
229 230
230 if (config.scaling > config.ScaleXY) { 231 if (config.scaling > config.ScaleXY) {
231 LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode %u", config.scaling.Value()); 232 LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode %u",
233 config.scaling.Value());
232 UNIMPLEMENTED(); 234 UNIMPLEMENTED();
233 break; 235 break;
234 } 236 }
@@ -245,11 +247,14 @@ inline void Write(u32 addr, const T data) {
245 u32 output_width = config.output_width >> horizontal_scale; 247 u32 output_width = config.output_width >> horizontal_scale;
246 u32 output_height = config.output_height >> vertical_scale; 248 u32 output_height = config.output_height >> vertical_scale;
247 249
248 u32 input_size = config.input_width * config.input_height * GPU::Regs::BytesPerPixel(config.input_format); 250 u32 input_size = config.input_width * config.input_height *
249 u32 output_size = output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format); 251 GPU::Regs::BytesPerPixel(config.input_format);
252 u32 output_size =
253 output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format);
250 254
251 Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), input_size); 255 Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), input_size);
252 Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), output_size); 256 Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(),
257 output_size);
253 258
254 for (u32 y = 0; y < output_height; ++y) { 259 for (u32 y = 0; y < output_height; ++y) {
255 for (u32 x = 0; x < output_width; ++x) { 260 for (u32 x = 0; x < output_width; ++x) {
@@ -278,11 +283,14 @@ inline void Write(u32 addr, const T data) {
278 u32 coarse_y = y & ~7; 283 u32 coarse_y = y & ~7;
279 u32 stride = output_width * dst_bytes_per_pixel; 284 u32 stride = output_width * dst_bytes_per_pixel;
280 285
281 src_offset = (input_x + input_y * config.input_width) * src_bytes_per_pixel; 286 src_offset =
282 dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + coarse_y * stride; 287 (input_x + input_y * config.input_width) * src_bytes_per_pixel;
288 dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) +
289 coarse_y * stride;
283 } else { 290 } else {
284 // Both input and output are linear 291 // Both input and output are linear
285 src_offset = (input_x + input_y * config.input_width) * src_bytes_per_pixel; 292 src_offset =
293 (input_x + input_y * config.input_width) * src_bytes_per_pixel;
286 dst_offset = (x + y * output_width) * dst_bytes_per_pixel; 294 dst_offset = (x + y * output_width) * dst_bytes_per_pixel;
287 } 295 }
288 } else { 296 } else {
@@ -291,7 +299,9 @@ inline void Write(u32 addr, const T data) {
291 u32 coarse_y = input_y & ~7; 299 u32 coarse_y = input_y & ~7;
292 u32 stride = config.input_width * src_bytes_per_pixel; 300 u32 stride = config.input_width * src_bytes_per_pixel;
293 301
294 src_offset = VideoCore::GetMortonOffset(input_x, input_y, src_bytes_per_pixel) + coarse_y * stride; 302 src_offset = VideoCore::GetMortonOffset(input_x, input_y,
303 src_bytes_per_pixel) +
304 coarse_y * stride;
295 dst_offset = (x + y * output_width) * dst_bytes_per_pixel; 305 dst_offset = (x + y * output_width) * dst_bytes_per_pixel;
296 } else { 306 } else {
297 // Both input and output are tiled 307 // Both input and output are tiled
@@ -301,20 +311,27 @@ inline void Write(u32 addr, const T data) {
301 u32 in_coarse_y = input_y & ~7; 311 u32 in_coarse_y = input_y & ~7;
302 u32 in_stride = config.input_width * src_bytes_per_pixel; 312 u32 in_stride = config.input_width * src_bytes_per_pixel;
303 313
304 src_offset = VideoCore::GetMortonOffset(input_x, input_y, src_bytes_per_pixel) + in_coarse_y * in_stride; 314 src_offset = VideoCore::GetMortonOffset(input_x, input_y,
305 dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + out_coarse_y * out_stride; 315 src_bytes_per_pixel) +
316 in_coarse_y * in_stride;
317 dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) +
318 out_coarse_y * out_stride;
306 } 319 }
307 } 320 }
308 321
309 const u8* src_pixel = src_pointer + src_offset; 322 const u8* src_pixel = src_pointer + src_offset;
310 src_color = DecodePixel(config.input_format, src_pixel); 323 src_color = DecodePixel(config.input_format, src_pixel);
311 if (config.scaling == config.ScaleX) { 324 if (config.scaling == config.ScaleX) {
312 Math::Vec4<u8> pixel = DecodePixel(config.input_format, src_pixel + src_bytes_per_pixel); 325 Math::Vec4<u8> pixel =
326 DecodePixel(config.input_format, src_pixel + src_bytes_per_pixel);
313 src_color = ((src_color + pixel) / 2).Cast<u8>(); 327 src_color = ((src_color + pixel) / 2).Cast<u8>();
314 } else if (config.scaling == config.ScaleXY) { 328 } else if (config.scaling == config.ScaleXY) {
315 Math::Vec4<u8> pixel1 = DecodePixel(config.input_format, src_pixel + 1 * src_bytes_per_pixel); 329 Math::Vec4<u8> pixel1 = DecodePixel(
316 Math::Vec4<u8> pixel2 = DecodePixel(config.input_format, src_pixel + 2 * src_bytes_per_pixel); 330 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); 331 Math::Vec4<u8> pixel2 = DecodePixel(
332 config.input_format, src_pixel + 2 * src_bytes_per_pixel);
333 Math::Vec4<u8> pixel3 = DecodePixel(
334 config.input_format, src_pixel + 3 * src_bytes_per_pixel);
318 src_color = (((src_color + pixel1) + (pixel2 + pixel3)) / 4).Cast<u8>(); 335 src_color = (((src_color + pixel1) + (pixel2 + pixel3)) / 4).Cast<u8>();
319 } 336 }
320 337
@@ -341,17 +358,20 @@ inline void Write(u32 addr, const T data) {
341 break; 358 break;
342 359
343 default: 360 default:
344 LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x", config.output_format.Value()); 361 LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x",
362 config.output_format.Value());
345 break; 363 break;
346 } 364 }
347 } 365 }
348 } 366 }
349 367
350 LOG_TRACE(HW_GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), dst format %x, flags 0x%08X", 368 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), 369 "0x%08x(%ux%u), dst format %x, flags 0x%08X",
352 config.GetPhysicalInputAddress(), config.input_width.Value(), config.input_height.Value(), 370 config.output_height * output_width *
353 config.GetPhysicalOutputAddress(), output_width, output_height, 371 GPU::Regs::BytesPerPixel(config.output_format),
354 config.output_format.Value(), config.flags); 372 config.GetPhysicalInputAddress(), config.input_width.Value(),
373 config.input_height.Value(), config.GetPhysicalOutputAddress(),
374 output_width, output_height, config.output_format.Value(), config.flags);
355 } 375 }
356 376
357 g_regs.display_transfer_config.trigger = 0; 377 g_regs.display_transfer_config.trigger = 0;
@@ -361,17 +381,16 @@ inline void Write(u32 addr, const T data) {
361 } 381 }
362 382
363 // Seems like writing to this register triggers processing 383 // Seems like writing to this register triggers processing
364 case GPU_REG_INDEX(command_processor_config.trigger): 384 case GPU_REG_INDEX(command_processor_config.trigger): {
365 {
366 const auto& config = g_regs.command_processor_config; 385 const auto& config = g_regs.command_processor_config;
367 if (config.trigger & 1) 386 if (config.trigger & 1) {
368 {
369 MICROPROFILE_SCOPE(GPU_CmdlistProcessing); 387 MICROPROFILE_SCOPE(GPU_CmdlistProcessing);
370 388
371 u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress()); 389 u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress());
372 390
373 if (Pica::g_debug_context && Pica::g_debug_context->recorder) { 391 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()); 392 Pica::g_debug_context->recorder->MemoryAccessed(
393 (u8*)buffer, config.size * sizeof(u32), config.GetPhysicalAddress());
375 } 394 }
376 395
377 Pica::CommandProcessor::ProcessCommandList(buffer, config.size); 396 Pica::CommandProcessor::ProcessCommandList(buffer, config.size);
@@ -389,16 +408,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. 408 // 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) { 409 if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
391 // addr + GPU VBase - IO VBase + IO PBase 410 // addr + GPU VBase - IO VBase + IO PBase
392 Pica::g_debug_context->recorder->RegisterWritten<T>(addr + 0x1EF00000 - 0x1EC00000 + 0x10100000, data); 411 Pica::g_debug_context->recorder->RegisterWritten<T>(
412 addr + 0x1EF00000 - 0x1EC00000 + 0x10100000, data);
393 } 413 }
394} 414}
395 415
396// Explicitly instantiate template functions because we aren't defining this in the header: 416// Explicitly instantiate template functions because we aren't defining this in the header:
397 417
398template void Read<u64>(u64 &var, const u32 addr); 418template void Read<u64>(u64& var, const u32 addr);
399template void Read<u32>(u32 &var, const u32 addr); 419template void Read<u32>(u32& var, const u32 addr);
400template void Read<u16>(u16 &var, const u32 addr); 420template void Read<u16>(u16& var, const u32 addr);
401template void Read<u8>(u8 &var, const u32 addr); 421template void Read<u8>(u8& var, const u32 addr);
402 422
403template void Write<u64>(u32 addr, const u64 data); 423template void Write<u64>(u32 addr, const u64 data);
404template void Write<u32>(u32 addr, const u32 data); 424template void Write<u32>(u32 addr, const u32 data);
@@ -417,8 +437,9 @@ static void VBlankCallback(u64 userdata, int cycles_late) {
417 // - If frameskip == 0 (disabled), always swap buffers 437 // - If frameskip == 0 (disabled), always swap buffers
418 // - If frameskip == 1, swap buffers every other frame (starting from the first frame) 438 // - 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) 439 // - 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) || 440 if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) &&
421 Settings::values.frame_skip == 0) { 441 last_skip_frame != g_skip_frame) ||
442 Settings::values.frame_skip == 0) {
422 VideoCore::g_renderer->SwapBuffers(); 443 VideoCore::g_renderer->SwapBuffers();
423 } 444 }
424 445
@@ -448,12 +469,12 @@ void Init() {
448 // .. or at least these are the ones used by system applets. 469 // .. or at least these are the ones used by system applets.
449 // There's probably a smarter way to come up with addresses 470 // There's probably a smarter way to come up with addresses
450 // like this which does not require hardcoding. 471 // like this which does not require hardcoding.
451 framebuffer_top.address_left1 = 0x181E6000; 472 framebuffer_top.address_left1 = 0x181E6000;
452 framebuffer_top.address_left2 = 0x1822C800; 473 framebuffer_top.address_left2 = 0x1822C800;
453 framebuffer_top.address_right1 = 0x18273000; 474 framebuffer_top.address_right1 = 0x18273000;
454 framebuffer_top.address_right2 = 0x182B9800; 475 framebuffer_top.address_right2 = 0x182B9800;
455 framebuffer_sub.address_left1 = 0x1848F000; 476 framebuffer_sub.address_left1 = 0x1848F000;
456 framebuffer_sub.address_left2 = 0x184C7800; 477 framebuffer_sub.address_left2 = 0x184C7800;
457 478
458 framebuffer_top.width.Assign(240); 479 framebuffer_top.width.Assign(240);
459 framebuffer_top.height.Assign(400); 480 framebuffer_top.height.Assign(400);
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index da4c345b4..32ddc5697 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -6,7 +6,6 @@
6 6
7#include <cstddef> 7#include <cstddef>
8#include <type_traits> 8#include <type_traits>
9
10#include "common/assert.h" 9#include "common/assert.h"
11#include "common/bit_field.h" 10#include "common/bit_field.h"
12#include "common/common_funcs.h" 11#include "common/common_funcs.h"
@@ -17,7 +16,8 @@ namespace GPU {
17// Returns index corresponding to the Regs member labeled by field_name 16// 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 17// 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])). 18// 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 19// For details cf.
20// 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. 21// Hopefully, this will be fixed sometime in the future.
22// For lack of better alternatives, we currently hardcode the offsets when constant 22// 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 23// expressions are needed via GPU_REG_INDEX_WORKAROUND (on sane compilers, static_asserts
@@ -30,8 +30,9 @@ namespace GPU {
30// really is this annoying. This macro just forwards its first argument to GPU_REG_INDEX 30// 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 31// 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. 32// field offset. Otherwise, the compiler will fail to compile this code.
33#define GPU_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ 33#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)) 34 ((typename std::enable_if<backup_workaround_index == GPU_REG_INDEX(field_name), size_t>::type) \
35 GPU_REG_INDEX(field_name))
35#endif 36#endif
36 37
37// MMIO region 0x1EFxxxxx 38// MMIO region 0x1EFxxxxx
@@ -44,18 +45,18 @@ struct Regs {
44// support for that. 45// support for that.
45#define ASSERT_MEMBER_SIZE(name, size_in_bytes) 46#define ASSERT_MEMBER_SIZE(name, size_in_bytes)
46#else 47#else
47#define ASSERT_MEMBER_SIZE(name, size_in_bytes) \ 48#define ASSERT_MEMBER_SIZE(name, size_in_bytes) \
48 static_assert(sizeof(name) == size_in_bytes, \ 49 static_assert(sizeof(name) == size_in_bytes, \
49 "Structure size and register block length don't match") 50 "Structure size and register block length don't match")
50#endif 51#endif
51 52
52 // Components are laid out in reverse byte order, most significant bits first. 53 // Components are laid out in reverse byte order, most significant bits first.
53 enum class PixelFormat : u32 { 54 enum class PixelFormat : u32 {
54 RGBA8 = 0, 55 RGBA8 = 0,
55 RGB8 = 1, 56 RGB8 = 1,
56 RGB565 = 2, 57 RGB565 = 2,
57 RGB5A1 = 3, 58 RGB5A1 = 3,
58 RGBA4 = 4, 59 RGBA4 = 4,
59 }; 60 };
60 61
61 /** 62 /**
@@ -88,8 +89,8 @@ struct Regs {
88 BitField<0, 16, u32> value_16bit; 89 BitField<0, 16, u32> value_16bit;
89 90
90 // TODO: Verify component order 91 // TODO: Verify component order
91 BitField< 0, 8, u32> value_24bit_r; 92 BitField<0, 8, u32> value_24bit_r;
92 BitField< 8, 8, u32> value_24bit_g; 93 BitField<8, 8, u32> value_24bit_g;
93 BitField<16, 8, u32> value_24bit_b; 94 BitField<16, 8, u32> value_24bit_b;
94 }; 95 };
95 96
@@ -126,7 +127,7 @@ struct Regs {
126 union { 127 union {
127 u32 size; 128 u32 size;
128 129
129 BitField< 0, 16, u32> width; 130 BitField<0, 16, u32> width;
130 BitField<16, 16, u32> height; 131 BitField<16, 16, u32> height;
131 }; 132 };
132 133
@@ -138,7 +139,7 @@ struct Regs {
138 union { 139 union {
139 u32 format; 140 u32 format;
140 141
141 BitField< 0, 3, PixelFormat> color_format; 142 BitField<0, 3, PixelFormat> color_format;
142 }; 143 };
143 144
144 INSERT_PADDING_WORDS(0x1); 145 INSERT_PADDING_WORDS(0x1);
@@ -180,35 +181,37 @@ struct Regs {
180 union { 181 union {
181 u32 output_size; 182 u32 output_size;
182 183
183 BitField< 0, 16, u32> output_width; 184 BitField<0, 16, u32> output_width;
184 BitField<16, 16, u32> output_height; 185 BitField<16, 16, u32> output_height;
185 }; 186 };
186 187
187 union { 188 union {
188 u32 input_size; 189 u32 input_size;
189 190
190 BitField< 0, 16, u32> input_width; 191 BitField<0, 16, u32> input_width;
191 BitField<16, 16, u32> input_height; 192 BitField<16, 16, u32> input_height;
192 }; 193 };
193 194
194 enum ScalingMode : u32 { 195 enum ScalingMode : u32 {
195 NoScale = 0, // Doesn't scale the image 196 NoScale = 0, // Doesn't scale the image
196 ScaleX = 1, // Downscales the image in half in the X axis and applies a box filter 197 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 198 ScaleXY =
199 2, // Downscales the image in half in both the X and Y axes and applies a box filter
198 }; 200 };
199 201
200 union { 202 union {
201 u32 flags; 203 u32 flags;
202 204
203 BitField< 0, 1, u32> flip_vertically; // flips input data vertically 205 BitField<0, 1, u32> flip_vertically; // flips input data vertically
204 BitField< 1, 1, u32> input_linear; // Converts from linear to tiled format 206 BitField<1, 1, u32> input_linear; // Converts from linear to tiled format
205 BitField< 2, 1, u32> crop_input_lines; 207 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 208 BitField<3, 1, u32> is_texture_copy; // Copies the data without performing any
207 BitField< 5, 1, u32> dont_swizzle; 209 // processing and respecting texture copy fields
208 BitField< 8, 3, PixelFormat> input_format; 210 BitField<5, 1, u32> dont_swizzle;
211 BitField<8, 3, PixelFormat> input_format;
209 BitField<12, 3, PixelFormat> output_format; 212 BitField<12, 3, PixelFormat> output_format;
210 /// Uses some kind of 32x32 block swizzling mode, instead of the usual 8x8 one. 213 /// Uses some kind of 32x32 block swizzling mode, instead of the usual 8x8 one.
211 BitField<16, 1, u32> block_32; // TODO(yuriks): unimplemented 214 BitField<16, 1, u32> block_32; // TODO(yuriks): unimplemented
212 BitField<24, 2, ScalingMode> scaling; // Determines the scaling mode of the transfer 215 BitField<24, 2, ScalingMode> scaling; // Determines the scaling mode of the transfer
213 }; 216 };
214 217
@@ -225,14 +228,14 @@ struct Regs {
225 union { 228 union {
226 u32 input_size; 229 u32 input_size;
227 230
228 BitField< 0, 16, u32> input_width; 231 BitField<0, 16, u32> input_width;
229 BitField<16, 16, u32> input_gap; 232 BitField<16, 16, u32> input_gap;
230 }; 233 };
231 234
232 union { 235 union {
233 u32 output_size; 236 u32 output_size;
234 237
235 BitField< 0, 16, u32> output_width; 238 BitField<0, 16, u32> output_width;
236 BitField<16, 16, u32> output_gap; 239 BitField<16, 16, u32> output_gap;
237 }; 240 };
238 } texture_copy; 241 } texture_copy;
@@ -267,12 +270,12 @@ struct Regs {
267 return sizeof(Regs) / sizeof(u32); 270 return sizeof(Regs) / sizeof(u32);
268 } 271 }
269 272
270 const u32& operator [] (int index) const { 273 const u32& operator[](int index) const {
271 const u32* content = reinterpret_cast<const u32*>(this); 274 const u32* content = reinterpret_cast<const u32*>(this);
272 return content[index]; 275 return content[index];
273 } 276 }
274 277
275 u32& operator [] (int index) { 278 u32& operator[](int index) {
276 u32* content = reinterpret_cast<u32*>(this); 279 u32* content = reinterpret_cast<u32*>(this);
277 return content[index]; 280 return content[index];
278 } 281 }
@@ -294,28 +297,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 297// is technically allowed since C++11. This macro should be enabled once MSVC adds
295// support for that. 298// support for that.
296#ifndef _MSC_VER 299#ifndef _MSC_VER
297#define ASSERT_REG_POSITION(field_name, position) \ 300#define ASSERT_REG_POSITION(field_name, position) \
298 static_assert(offsetof(Regs, field_name) == position * 4, \ 301 static_assert(offsetof(Regs, field_name) == position * 4, \
299 "Field "#field_name" has invalid position") 302 "Field " #field_name " has invalid position")
300 303
301ASSERT_REG_POSITION(memory_fill_config[0], 0x00004); 304ASSERT_REG_POSITION(memory_fill_config[0], 0x00004);
302ASSERT_REG_POSITION(memory_fill_config[1], 0x00008); 305ASSERT_REG_POSITION(memory_fill_config[1], 0x00008);
303ASSERT_REG_POSITION(framebuffer_config[0], 0x00117); 306ASSERT_REG_POSITION(framebuffer_config[0], 0x00117);
304ASSERT_REG_POSITION(framebuffer_config[1], 0x00157); 307ASSERT_REG_POSITION(framebuffer_config[1], 0x00157);
305ASSERT_REG_POSITION(display_transfer_config, 0x00300); 308ASSERT_REG_POSITION(display_transfer_config, 0x00300);
306ASSERT_REG_POSITION(command_processor_config, 0x00638); 309ASSERT_REG_POSITION(command_processor_config, 0x00638);
307 310
308#undef ASSERT_REG_POSITION 311#undef ASSERT_REG_POSITION
309#endif // !defined(_MSC_VER) 312#endif // !defined(_MSC_VER)
310 313
311// The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value anyway. 314// The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value
315// anyway.
312static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of register set"); 316static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of register set");
313 317
314extern Regs g_regs; 318extern Regs g_regs;
315extern bool g_skip_frame; 319extern bool g_skip_frame;
316 320
317template <typename T> 321template <typename T>
318void Read(T &var, const u32 addr); 322void Read(T& var, const u32 addr);
319 323
320template <typename T> 324template <typename T>
321void Write(u32 addr, const T data); 325void Write(u32 addr, const T data);
@@ -326,5 +330,4 @@ void Init();
326/// Shutdown hardware 330/// Shutdown hardware
327void Shutdown(); 331void Shutdown();
328 332
329
330} // namespace 333} // namespace
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp
index b5fdbf9c1..9ff8825b2 100644
--- a/src/core/hw/hw.cpp
+++ b/src/core/hw/hw.cpp
@@ -4,15 +4,14 @@
4 4
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
8#include "core/hw/hw.h"
9#include "core/hw/gpu.h" 7#include "core/hw/gpu.h"
8#include "core/hw/hw.h"
10#include "core/hw/lcd.h" 9#include "core/hw/lcd.h"
11 10
12namespace HW { 11namespace HW {
13 12
14template <typename T> 13template <typename T>
15inline void Read(T &var, const u32 addr) { 14inline void Read(T& var, const u32 addr) {
16 switch (addr & 0xFFFFF000) { 15 switch (addr & 0xFFFFF000) {
17 case VADDR_GPU: 16 case VADDR_GPU:
18 case VADDR_GPU + 0x1000: 17 case VADDR_GPU + 0x1000:
@@ -71,10 +70,10 @@ inline void Write(u32 addr, const T data) {
71 70
72// Explicitly instantiate template functions because we aren't defining this in the header: 71// Explicitly instantiate template functions because we aren't defining this in the header:
73 72
74template void Read<u64>(u64 &var, const u32 addr); 73template void Read<u64>(u64& var, const u32 addr);
75template void Read<u32>(u32 &var, const u32 addr); 74template void Read<u32>(u32& var, const u32 addr);
76template void Read<u16>(u16 &var, const u32 addr); 75template void Read<u16>(u16& var, const u32 addr);
77template void Read<u8>(u8 &var, const u32 addr); 76template void Read<u8>(u8& var, const u32 addr);
78 77
79template void Write<u64>(u32 addr, const u64 data); 78template void Write<u64>(u32 addr, const u64 data);
80template void Write<u32>(u32 addr, const u32 data); 79template void Write<u32>(u32 addr, const u32 data);
@@ -82,8 +81,7 @@ template void Write<u16>(u32 addr, const u16 data);
82template void Write<u8>(u32 addr, const u8 data); 81template void Write<u8>(u32 addr, const u8 data);
83 82
84/// Update hardware 83/// Update hardware
85void Update() { 84void Update() {}
86}
87 85
88/// Initialize hardware 86/// Initialize hardware
89void Init() { 87void Init() {
@@ -98,5 +96,4 @@ void Shutdown() {
98 LCD::Shutdown(); 96 LCD::Shutdown();
99 LOG_DEBUG(HW, "shutdown OK"); 97 LOG_DEBUG(HW, "shutdown OK");
100} 98}
101
102} 99}
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..2aa89de18 100644
--- a/src/core/hw/lcd.cpp
+++ b/src/core/hw/lcd.cpp
@@ -3,13 +3,10 @@
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
7#include "common/common_types.h" 6#include "common/common_types.h"
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9
10#include "core/hw/hw.h" 8#include "core/hw/hw.h"
11#include "core/hw/lcd.h" 9#include "core/hw/lcd.h"
12
13#include "core/tracer/recorder.h" 10#include "core/tracer/recorder.h"
14#include "video_core/debug_utils/debug_utils.h" 11#include "video_core/debug_utils/debug_utils.h"
15 12
@@ -18,7 +15,7 @@ namespace LCD {
18Regs g_regs; 15Regs g_regs;
19 16
20template <typename T> 17template <typename T>
21inline void Read(T &var, const u32 raw_addr) { 18inline void Read(T& var, const u32 raw_addr) {
22 u32 addr = raw_addr - HW::VADDR_LCD; 19 u32 addr = raw_addr - HW::VADDR_LCD;
23 u32 index = addr / 4; 20 u32 index = addr / 4;
24 21
@@ -48,16 +45,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. 45 // 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) { 46 if (Pica::g_debug_context && Pica::g_debug_context->recorder) {
50 // addr + GPU VBase - IO VBase + IO PBase 47 // addr + GPU VBase - IO VBase + IO PBase
51 Pica::g_debug_context->recorder->RegisterWritten<T>(addr + HW::VADDR_LCD - 0x1EC00000 + 0x10100000, data); 48 Pica::g_debug_context->recorder->RegisterWritten<T>(
49 addr + HW::VADDR_LCD - 0x1EC00000 + 0x10100000, data);
52 } 50 }
53} 51}
54 52
55// Explicitly instantiate template functions because we aren't defining this in the header: 53// Explicitly instantiate template functions because we aren't defining this in the header:
56 54
57template void Read<u64>(u64 &var, const u32 addr); 55template void Read<u64>(u64& var, const u32 addr);
58template void Read<u32>(u32 &var, const u32 addr); 56template void Read<u32>(u32& var, const u32 addr);
59template void Read<u16>(u16 &var, const u32 addr); 57template void Read<u16>(u16& var, const u32 addr);
60template void Read<u8>(u8 &var, const u32 addr); 58template void Read<u8>(u8& var, const u32 addr);
61 59
62template void Write<u64>(u32 addr, const u64 data); 60template void Write<u64>(u32 addr, const u64 data);
63template void Write<u32>(u32 addr, const u32 data); 61template void Write<u32>(u32 addr, const u32 data);
diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h
index 57029c5e8..191fd44af 100644
--- a/src/core/hw/lcd.h
+++ b/src/core/hw/lcd.h
@@ -6,7 +6,6 @@
6 6
7#include <cstddef> 7#include <cstddef>
8#include <type_traits> 8#include <type_traits>
9
10#include "common/bit_field.h" 9#include "common/bit_field.h"
11#include "common/common_funcs.h" 10#include "common/common_funcs.h"
12#include "common/common_types.h" 11#include "common/common_types.h"
@@ -42,16 +41,15 @@ struct Regs {
42 return sizeof(Regs) / sizeof(u32); 41 return sizeof(Regs) / sizeof(u32);
43 } 42 }
44 43
45 const u32& operator [] (int index) const { 44 const u32& operator[](int index) const {
46 const u32* content = reinterpret_cast<const u32*>(this); 45 const u32* content = reinterpret_cast<const u32*>(this);
47 return content[index]; 46 return content[index];
48 } 47 }
49 48
50 u32& operator [] (int index) { 49 u32& operator[](int index) {
51 u32* content = reinterpret_cast<u32*>(this); 50 u32* content = reinterpret_cast<u32*>(this);
52 return content[index]; 51 return content[index];
53 } 52 }
54
55}; 53};
56static_assert(std::is_standard_layout<Regs>::value, "Structure does not use standard layout"); 54static_assert(std::is_standard_layout<Regs>::value, "Structure does not use standard layout");
57 55
@@ -59,14 +57,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 57// is technically allowed since C++11. This macro should be enabled once MSVC adds
60// support for that. 58// support for that.
61#ifndef _MSC_VER 59#ifndef _MSC_VER
62#define ASSERT_REG_POSITION(field_name, position) \ 60#define ASSERT_REG_POSITION(field_name, position) \
63 static_assert(offsetof(Regs, field_name) == position * 4, \ 61 static_assert(offsetof(Regs, field_name) == position * 4, \
64 "Field "#field_name" has invalid position") 62 "Field " #field_name " has invalid position")
65 63
66ASSERT_REG_POSITION(color_fill_top, 0x81); 64ASSERT_REG_POSITION(color_fill_top, 0x81);
67ASSERT_REG_POSITION(backlight_top, 0x90); 65ASSERT_REG_POSITION(backlight_top, 0x90);
68ASSERT_REG_POSITION(color_fill_bottom, 0x281); 66ASSERT_REG_POSITION(color_fill_bottom, 0x281);
69ASSERT_REG_POSITION(backlight_bottom, 0x290); 67ASSERT_REG_POSITION(backlight_bottom, 0x290);
70 68
71#undef ASSERT_REG_POSITION 69#undef ASSERT_REG_POSITION
72#endif // !defined(_MSC_VER) 70#endif // !defined(_MSC_VER)
@@ -74,7 +72,7 @@ ASSERT_REG_POSITION(backlight_bottom, 0x290);
74extern Regs g_regs; 72extern Regs g_regs;
75 73
76template <typename T> 74template <typename T>
77void Read(T &var, const u32 addr); 75void Read(T& var, const u32 addr);
78 76
79template <typename T> 77template <typename T>
80void Write(u32 addr, const T data); 78void Write(u32 addr, const T data);
diff --git a/src/core/hw/y2r.cpp b/src/core/hw/y2r.cpp
index 083391e83..6a6c707a2 100644
--- a/src/core/hw/y2r.cpp
+++ b/src/core/hw/y2r.cpp
@@ -6,13 +6,11 @@
6#include <array> 6#include <array>
7#include <cstddef> 7#include <cstddef>
8#include <memory> 8#include <memory>
9
10#include "common/assert.h" 9#include "common/assert.h"
11#include "common/color.h" 10#include "common/color.h"
12#include "common/common_types.h" 11#include "common/common_types.h"
13#include "common/math_util.h" 12#include "common/math_util.h"
14#include "common/vector_math.h" 13#include "common/vector_math.h"
15
16#include "core/hle/service/y2r_u.h" 14#include "core/hle/service/y2r_u.h"
17#include "core/hw/y2r.h" 15#include "core/hw/y2r.h"
18#include "core/memory.h" 16#include "core/memory.h"
@@ -27,9 +25,9 @@ static const size_t TILE_SIZE = 8 * 8;
27using ImageTile = std::array<u32, TILE_SIZE>; 25using ImageTile = std::array<u32, TILE_SIZE>;
28 26
29/// Converts a image strip from the source YUV format into individual 8x8 RGB32 tiles. 27/// Converts a image strip from the source YUV format into individual 8x8 RGB32 tiles.
30static void ConvertYUVToRGB(InputFormat input_format, 28static 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[], 29 const u8* input_V, ImageTile output[], unsigned int width,
32 unsigned int width, unsigned int height, const CoefficientSet& coefficients) { 30 unsigned int height, const CoefficientSet& coefficients) {
33 31
34 for (unsigned int y = 0; y < height; ++y) { 32 for (unsigned int y = 0; y < height; ++y) {
35 for (unsigned int x = 0; x < width; ++x) { 33 for (unsigned int x = 0; x < width; ++x) {
@@ -58,11 +56,11 @@ static void ConvertYUVToRGB(InputFormat input_format,
58 56
59 // This conversion process is bit-exact with hardware, as far as could be tested. 57 // This conversion process is bit-exact with hardware, as far as could be tested.
60 auto& c = coefficients; 58 auto& c = coefficients;
61 s32 cY = c[0]*Y; 59 s32 cY = c[0] * Y;
62 60
63 s32 r = cY + c[1]*V; 61 s32 r = cY + c[1] * V;
64 s32 g = cY - c[3]*U - c[2]*V; 62 s32 g = cY - c[2] * V - c[3] * U;
65 s32 b = cY + c[4]*U; 63 s32 b = cY + c[4] * U;
66 64
67 const s32 rounding_offset = 0x18; 65 const s32 rounding_offset = 0x18;
68 r = (r >> 3) + c[5] + rounding_offset; 66 r = (r >> 3) + c[5] + rounding_offset;
@@ -74,14 +72,14 @@ static void ConvertYUVToRGB(InputFormat input_format,
74 u32* out = &output[tile][y * 8 + tile_x]; 72 u32* out = &output[tile][y * 8 + tile_x];
75 73
76 using MathUtil::Clamp; 74 using MathUtil::Clamp;
77 *out = ((u32)Clamp(r >> 5, 0, 0xFF) << 24) | 75 *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); 76 ((u32)Clamp(b >> 5, 0, 0xFF) << 8);
80 } 77 }
81 } 78 }
82} 79}
83 80
84/// Simulates an incoming CDMA transfer. The N parameter is used to automatically convert 16-bit formats to 8-bit. 81/// Simulates an incoming CDMA transfer. The N parameter is used to automatically convert 16-bit
82/// formats to 8-bit.
85template <size_t N> 83template <size_t N>
86static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data) { 84static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data) {
87 const u8* input = Memory::GetPointer(buf.address); 85 const u8* input = Memory::GetPointer(buf.address);
@@ -103,9 +101,10 @@ static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data
103 } 101 }
104} 102}
105 103
106/// Convert intermediate RGB32 format to the final output format while simulating an outgoing CDMA transfer. 104/// Convert intermediate RGB32 format to the final output format while simulating an outgoing CDMA
105/// transfer.
107static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data, 106static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data,
108 OutputFormat output_format, u8 alpha) { 107 OutputFormat output_format, u8 alpha) {
109 108
110 u8* output = Memory::GetPointer(buf.address); 109 u8* output = Memory::GetPointer(buf.address);
111 110
@@ -113,9 +112,7 @@ static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data
113 u8* unit_end = output + buf.transfer_unit; 112 u8* unit_end = output + buf.transfer_unit;
114 while (output < unit_end) { 113 while (output < unit_end) {
115 u32 color = *input++; 114 u32 color = *input++;
116 Math::Vec4<u8> col_vec{ 115 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 116
120 switch (output_format) { 117 switch (output_format) {
121 case OutputFormat::RGBA8: 118 case OutputFormat::RGBA8:
@@ -145,7 +142,8 @@ static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data
145 } 142 }
146} 143}
147 144
148static const u8 linear_lut[64] = { 145static const u8 linear_lut[TILE_SIZE] = {
146 // clang-format off
149 0, 1, 2, 3, 4, 5, 6, 7, 147 0, 1, 2, 3, 4, 5, 6, 7,
150 8, 9, 10, 11, 12, 13, 14, 15, 148 8, 9, 10, 11, 12, 13, 14, 15,
151 16, 17, 18, 19, 20, 21, 22, 23, 149 16, 17, 18, 19, 20, 21, 22, 23,
@@ -154,9 +152,11 @@ static const u8 linear_lut[64] = {
154 40, 41, 42, 43, 44, 45, 46, 47, 152 40, 41, 42, 43, 44, 45, 46, 47,
155 48, 49, 50, 51, 52, 53, 54, 55, 153 48, 49, 50, 51, 52, 53, 54, 55,
156 56, 57, 58, 59, 60, 61, 62, 63, 154 56, 57, 58, 59, 60, 61, 62, 63,
155 // clang-format on
157}; 156};
158 157
159static const u8 morton_lut[64] = { 158static const u8 morton_lut[TILE_SIZE] = {
159 // clang-format off
160 0, 1, 4, 5, 16, 17, 20, 21, 160 0, 1, 4, 5, 16, 17, 20, 21,
161 2, 3, 6, 7, 18, 19, 22, 23, 161 2, 3, 6, 7, 18, 19, 22, 23,
162 8, 9, 12, 13, 24, 25, 28, 29, 162 8, 9, 12, 13, 24, 25, 28, 29,
@@ -165,15 +165,18 @@ static const u8 morton_lut[64] = {
165 34, 35, 38, 39, 50, 51, 54, 55, 165 34, 35, 38, 39, 50, 51, 54, 55,
166 40, 41, 44, 45, 56, 57, 60, 61, 166 40, 41, 44, 45, 56, 57, 60, 61,
167 42, 43, 46, 47, 58, 59, 62, 63, 167 42, 43, 46, 47, 58, 59, 62, 63,
168 // clang-format on
168}; 169};
169 170
170static void RotateTile0(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { 171static void RotateTile0(const ImageTile& input, ImageTile& output, int height,
172 const u8 out_map[64]) {
171 for (int i = 0; i < height * 8; ++i) { 173 for (int i = 0; i < height * 8; ++i) {
172 output[out_map[i]] = input[i]; 174 output[out_map[i]] = input[i];
173 } 175 }
174} 176}
175 177
176static void RotateTile90(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { 178static void RotateTile90(const ImageTile& input, ImageTile& output, int height,
179 const u8 out_map[64]) {
177 int out_i = 0; 180 int out_i = 0;
178 for (int x = 0; x < 8; ++x) { 181 for (int x = 0; x < 8; ++x) {
179 for (int y = height - 1; y >= 0; --y) { 182 for (int y = height - 1; y >= 0; --y) {
@@ -182,16 +185,18 @@ static void RotateTile90(const ImageTile& input, ImageTile& output, int height,
182 } 185 }
183} 186}
184 187
185static void RotateTile180(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { 188static void RotateTile180(const ImageTile& input, ImageTile& output, int height,
189 const u8 out_map[64]) {
186 int out_i = 0; 190 int out_i = 0;
187 for (int i = height * 8 - 1; i >= 0; --i) { 191 for (int i = height * 8 - 1; i >= 0; --i) {
188 output[out_map[out_i++]] = input[i]; 192 output[out_map[out_i++]] = input[i];
189 } 193 }
190} 194}
191 195
192static void RotateTile270(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { 196static void RotateTile270(const ImageTile& input, ImageTile& output, int height,
197 const u8 out_map[64]) {
193 int out_i = 0; 198 int out_i = 0;
194 for (int x = 8-1; x >= 0; --x) { 199 for (int x = 8 - 1; x >= 0; --x) {
195 for (int y = 0; y < height; ++y) { 200 for (int y = 0; y < height; ++y) {
196 output[out_map[out_i++]] = input[y * 8 + x]; 201 output[out_map[out_i++]] = input[y * 8 + x];
197 } 202 }
@@ -274,9 +279,11 @@ void PerformConversion(ConversionConfiguration& cvt) {
274 const u8* tile_remap = nullptr; 279 const u8* tile_remap = nullptr;
275 switch (cvt.block_alignment) { 280 switch (cvt.block_alignment) {
276 case BlockAlignment::Linear: 281 case BlockAlignment::Linear:
277 tile_remap = linear_lut; break; 282 tile_remap = linear_lut;
283 break;
278 case BlockAlignment::Block8x8: 284 case BlockAlignment::Block8x8:
279 tile_remap = morton_lut; break; 285 tile_remap = morton_lut;
286 break;
280 } 287 }
281 288
282 for (unsigned int y = 0; y < cvt.input_lines; y += 8) { 289 for (unsigned int y = 0; y < cvt.input_lines; y += 8) {
@@ -320,7 +327,7 @@ void PerformConversion(ConversionConfiguration& cvt) {
320 // Note(yuriks): If additional optimization is required, input_format can be moved to a 327 // 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. 328 // 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(), 329 ConvertYUVToRGB(cvt.input_format, input_Y, input_U, input_V, tiles.get(),
323 cvt.input_line_width, row_height, cvt.coefficients); 330 cvt.input_line_width, row_height, cvt.coefficients);
324 331
325 u32* output_buffer = reinterpret_cast<u32*>(data_buffer.get()); 332 u32* output_buffer = reinterpret_cast<u32*>(data_buffer.get());
326 333
@@ -367,9 +374,9 @@ void PerformConversion(ConversionConfiguration& cvt) {
367 374
368 // Note(yuriks): If additional optimization is required, output_format can be moved to a 375 // 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. 376 // 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); 377 SendData(reinterpret_cast<u32*>(data_buffer.get()), cvt.dst, (int)row_data_size,
378 cvt.output_format, (u8)cvt.alpha);
371 } 379 }
372} 380}
373
374} 381}
375} 382}
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..1c10740a0 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -4,9 +4,7 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <vector> 6#include <vector>
7
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9
10#include "core/file_sys/archive_romfs.h" 8#include "core/file_sys/archive_romfs.h"
11#include "core/hle/kernel/process.h" 9#include "core/hle/kernel/process.h"
12#include "core/hle/kernel/resource_limit.h" 10#include "core/hle/kernel/resource_limit.h"
@@ -37,20 +35,14 @@ namespace Loader {
37 * The BSS section must be cleared manually by the application. 35 * The BSS section must be cleared manually by the application.
38 */ 36 */
39 37
40enum THREEDSX_Error { 38enum 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 39
47static const u32 RELOCBUFSIZE = 512; 40static const u32 RELOCBUFSIZE = 512;
48static const unsigned int NUM_SEGMENTS = 3; 41static const unsigned int NUM_SEGMENTS = 3;
49 42
50// File header 43// File header
51#pragma pack(1) 44#pragma pack(1)
52struct THREEDSX_Header 45struct THREEDSX_Header {
53{
54 u32 magic; 46 u32 magic;
55 u16 header_size, reloc_hdr_size; 47 u16 header_size, reloc_hdr_size;
56 u32 format_ver; 48 u32 format_ver;
@@ -66,11 +58,11 @@ struct THREEDSX_Header
66}; 58};
67 59
68// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts. 60// Relocation header: all fields (even extra unknown fields) are guaranteed to be relocation counts.
69struct THREEDSX_RelocHdr 61struct THREEDSX_RelocHdr {
70{
71 // # of absolute relocations (that is, fix address to post-relocation memory layout) 62 // # of absolute relocations (that is, fix address to post-relocation memory layout)
72 u32 cross_segment_absolute; 63 u32 cross_segment_absolute;
73 // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be patched) 64 // # of cross-segment relative relocations (that is, 32bit signed offsets that need to be
65 // patched)
74 u32 cross_segment_relative; 66 u32 cross_segment_relative;
75 // more? 67 // more?
76 68
@@ -80,21 +72,18 @@ struct THREEDSX_RelocHdr
80}; 72};
81 73
82// Relocation entry: from the current pointer, skip X words and patch Y words 74// Relocation entry: from the current pointer, skip X words and patch Y words
83struct THREEDSX_Reloc 75struct THREEDSX_Reloc {
84{
85 u16 skip, patch; 76 u16 skip, patch;
86}; 77};
87#pragma pack() 78#pragma pack()
88 79
89struct THREEloadinfo 80struct THREEloadinfo {
90{
91 u8* seg_ptrs[3]; // code, rodata & data 81 u8* seg_ptrs[3]; // code, rodata & data
92 u32 seg_addrs[3]; 82 u32 seg_addrs[3];
93 u32 seg_sizes[3]; 83 u32 seg_sizes[3];
94}; 84};
95 85
96static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets) 86static u32 TranslateAddr(u32 addr, const THREEloadinfo* loadinfo, u32* offsets) {
97{
98 if (addr < offsets[0]) 87 if (addr < offsets[0])
99 return loadinfo->seg_addrs[0] + addr; 88 return loadinfo->seg_addrs[0] + addr;
100 if (addr < offsets[1]) 89 if (addr < offsets[1])
@@ -105,8 +94,8 @@ static u32 TranslateAddr(u32 addr, const THREEloadinfo *loadinfo, u32* offsets)
105using Kernel::SharedPtr; 94using Kernel::SharedPtr;
106using Kernel::CodeSet; 95using Kernel::CodeSet;
107 96
108static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, SharedPtr<CodeSet>* out_codeset) 97static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr,
109{ 98 SharedPtr<CodeSet>* out_codeset) {
110 if (!file.IsOpen()) 99 if (!file.IsOpen())
111 return ERROR_FILE; 100 return ERROR_FILE;
112 101
@@ -118,13 +107,14 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
118 return ERROR_READ; 107 return ERROR_READ;
119 108
120 THREEloadinfo loadinfo; 109 THREEloadinfo loadinfo;
121 //loadinfo segments must be a multiple of 0x1000 110 // loadinfo segments must be a multiple of 0x1000
122 loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) &~0xFFF; 111 loadinfo.seg_sizes[0] = (hdr.code_seg_size + 0xFFF) & ~0xFFF;
123 loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) &~0xFFF; 112 loadinfo.seg_sizes[1] = (hdr.rodata_seg_size + 0xFFF) & ~0xFFF;
124 loadinfo.seg_sizes[2] = (hdr.data_seg_size + 0xFFF) &~0xFFF; 113 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] }; 114 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); 115 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]); 116 std::vector<u8> program_image(loadinfo.seg_sizes[0] + loadinfo.seg_sizes[1] +
117 loadinfo.seg_sizes[2]);
128 118
129 loadinfo.seg_addrs[0] = base_addr; 119 loadinfo.seg_addrs[0] = base_addr;
130 loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0]; 120 loadinfo.seg_addrs[1] = loadinfo.seg_addrs[0] + loadinfo.seg_sizes[0];
@@ -149,7 +139,8 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
149 return ERROR_READ; 139 return ERROR_READ;
150 if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size) 140 if (file.ReadBytes(loadinfo.seg_ptrs[1], hdr.rodata_seg_size) != hdr.rodata_seg_size)
151 return ERROR_READ; 141 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) 142 if (file.ReadBytes(loadinfo.seg_ptrs[2], hdr.data_seg_size - hdr.bss_size) !=
143 hdr.data_seg_size - hdr.bss_size)
153 return ERROR_READ; 144 return ERROR_READ;
154 145
155 // BSS clear 146 // BSS clear
@@ -157,11 +148,12 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
157 148
158 // Relocate the segments 149 // Relocate the segments
159 for (unsigned int current_segment = 0; current_segment < NUM_SEGMENTS; ++current_segment) { 150 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++) { 151 for (unsigned current_segment_reloc_table = 0; current_segment_reloc_table < n_reloc_tables;
152 current_segment_reloc_table++) {
161 u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table]; 153 u32 n_relocs = relocs[current_segment * n_reloc_tables + current_segment_reloc_table];
162 if (current_segment_reloc_table >= 2) { 154 if (current_segment_reloc_table >= 2) {
163 // We are not using this table - ignore it because we don't know what it dose 155 // 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); 156 file.Seek(n_relocs * sizeof(THREEDSX_Reloc), SEEK_CUR);
165 continue; 157 continue;
166 } 158 }
167 THREEDSX_Reloc reloc_table[RELOCBUFSIZE]; 159 THREEDSX_Reloc reloc_table[RELOCBUFSIZE];
@@ -173,17 +165,20 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
173 u32 remaining = std::min(RELOCBUFSIZE, n_relocs); 165 u32 remaining = std::min(RELOCBUFSIZE, n_relocs);
174 n_relocs -= remaining; 166 n_relocs -= remaining;
175 167
176 if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) != remaining * sizeof(THREEDSX_Reloc)) 168 if (file.ReadBytes(reloc_table, remaining * sizeof(THREEDSX_Reloc)) !=
169 remaining * sizeof(THREEDSX_Reloc))
177 return ERROR_READ; 170 return ERROR_READ;
178 171
179 for (unsigned current_inprogress = 0; current_inprogress < remaining && pos < end_pos; current_inprogress++) { 172 for (unsigned current_inprogress = 0;
173 current_inprogress < remaining && pos < end_pos; current_inprogress++) {
180 const auto& table = reloc_table[current_inprogress]; 174 const auto& table = reloc_table[current_inprogress];
181 LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)", current_segment_reloc_table, 175 LOG_TRACE(Loader, "(t=%d,skip=%u,patch=%u)", current_segment_reloc_table,
182 static_cast<u32>(table.skip), static_cast<u32>(table.patch)); 176 static_cast<u32>(table.skip), static_cast<u32>(table.patch));
183 pos += table.skip; 177 pos += table.skip;
184 s32 num_patches = table.patch; 178 s32 num_patches = table.patch;
185 while (0 < num_patches && pos < end_pos) { 179 while (0 < num_patches && pos < end_pos) {
186 u32 in_addr = static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data()); 180 u32 in_addr =
181 static_cast<u32>(reinterpret_cast<u8*>(pos) - program_image.data());
187 u32 addr = TranslateAddr(*pos, &loadinfo, offsets); 182 u32 addr = TranslateAddr(*pos, &loadinfo, offsets);
188 LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)", 183 LOG_TRACE(Loader, "Patching %08X <-- rel(%08X,%d) (%08X)",
189 base_addr + in_addr, addr, current_segment_reloc_table, *pos); 184 base_addr + in_addr, addr, current_segment_reloc_table, *pos);
@@ -195,7 +190,7 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
195 *pos = static_cast<u32>(addr - in_addr); 190 *pos = static_cast<u32>(addr - in_addr);
196 break; 191 break;
197 default: 192 default:
198 break; //this should never happen 193 break; // this should never happen
199 } 194 }
200 pos++; 195 pos++;
201 num_patches--; 196 num_patches--;
@@ -209,23 +204,24 @@ static THREEDSX_Error Load3DSXFile(FileUtil::IOFile& file, u32 base_addr, Shared
209 SharedPtr<CodeSet> code_set = CodeSet::Create("", 0); 204 SharedPtr<CodeSet> code_set = CodeSet::Create("", 0);
210 205
211 code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data(); 206 code_set->code.offset = loadinfo.seg_ptrs[0] - program_image.data();
212 code_set->code.addr = loadinfo.seg_addrs[0]; 207 code_set->code.addr = loadinfo.seg_addrs[0];
213 code_set->code.size = loadinfo.seg_sizes[0]; 208 code_set->code.size = loadinfo.seg_sizes[0];
214 209
215 code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data(); 210 code_set->rodata.offset = loadinfo.seg_ptrs[1] - program_image.data();
216 code_set->rodata.addr = loadinfo.seg_addrs[1]; 211 code_set->rodata.addr = loadinfo.seg_addrs[1];
217 code_set->rodata.size = loadinfo.seg_sizes[1]; 212 code_set->rodata.size = loadinfo.seg_sizes[1];
218 213
219 code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data(); 214 code_set->data.offset = loadinfo.seg_ptrs[2] - program_image.data();
220 code_set->data.addr = loadinfo.seg_addrs[2]; 215 code_set->data.addr = loadinfo.seg_addrs[2];
221 code_set->data.size = loadinfo.seg_sizes[2]; 216 code_set->data.size = loadinfo.seg_sizes[2];
222 217
223 code_set->entrypoint = code_set->code.addr; 218 code_set->entrypoint = code_set->code.addr;
224 code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image)); 219 code_set->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
225 220
226 LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]); 221 LOG_DEBUG(Loader, "code size: 0x%X", loadinfo.seg_sizes[0]);
227 LOG_DEBUG(Loader, "rodata size: 0x%X", loadinfo.seg_sizes[1]); 222 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); 223 LOG_DEBUG(Loader, "data size: 0x%X (including 0x%X of bss)", loadinfo.seg_sizes[2],
224 hdr.bss_size);
229 225
230 *out_codeset = code_set; 226 *out_codeset = code_set;
231 return ERROR_NONE; 227 return ERROR_NONE;
@@ -260,17 +256,20 @@ ResultStatus AppLoader_THREEDSX::Load() {
260 Kernel::g_current_process->address_mappings = default_address_mappings; 256 Kernel::g_current_process->address_mappings = default_address_mappings;
261 257
262 // Attach the default resource limit (APPLICATION) to the process 258 // Attach the default resource limit (APPLICATION) to the process
263 Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); 259 Kernel::g_current_process->resource_limit =
260 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
264 261
265 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); 262 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
266 263
267 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), Service::FS::ArchiveIdCode::RomFS); 264 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this),
265 Service::FS::ArchiveIdCode::RomFS);
268 266
269 is_loaded = true; 267 is_loaded = true;
270 return ResultStatus::Success; 268 return ResultStatus::Success;
271} 269}
272 270
273ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { 271ResultStatus AppLoader_THREEDSX::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file,
272 u64& offset, u64& size) {
274 if (!file.IsOpen()) 273 if (!file.IsOpen())
275 return ResultStatus::Error; 274 return ResultStatus::Error;
276 275
diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h
index 90b20c61c..cfcc21cc4 100644
--- a/src/core/loader/3dsx.h
+++ b/src/core/loader/3dsx.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <string> 7#include <string>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "core/loader/loader.h" 9#include "core/loader/loader.h"
11 10
@@ -17,7 +16,8 @@ namespace Loader {
17/// Loads an 3DSX file 16/// Loads an 3DSX file
18class AppLoader_THREEDSX final : public AppLoader { 17class AppLoader_THREEDSX final : public AppLoader {
19public: 18public:
20 AppLoader_THREEDSX(FileUtil::IOFile&& file, const std::string& filename, const std::string& filepath) 19 AppLoader_THREEDSX(FileUtil::IOFile&& file, const std::string& filename,
20 const std::string& filepath)
21 : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {} 21 : AppLoader(std::move(file)), filename(std::move(filename)), filepath(filepath) {}
22 22
23 /** 23 /**
@@ -55,7 +55,8 @@ public:
55 * @param size Size of the RomFS in bytes 55 * @param size Size of the RomFS in bytes
56 * @return ResultStatus result of function 56 * @return ResultStatus result of function
57 */ 57 */
58 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) override; 58 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
59 u64& size) override;
59 60
60private: 61private:
61 std::string filename; 62 std::string filename;
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 69df94324..8eb5200ab 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -3,14 +3,12 @@
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>
8 7#include <string>
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "common/file_util.h" 9#include "common/file_util.h"
11#include "common/logging/log.h" 10#include "common/logging/log.h"
12#include "common/symbols.h" 11#include "common/symbols.h"
13
14#include "core/hle/kernel/process.h" 12#include "core/hle/kernel/process.h"
15#include "core/hle/kernel/resource_limit.h" 13#include "core/hle/kernel/resource_limit.h"
16#include "core/loader/elf.h" 14#include "core/loader/elf.h"
@@ -24,112 +22,111 @@ using Kernel::CodeSet;
24 22
25// File type 23// File type
26enum ElfType { 24enum ElfType {
27 ET_NONE = 0, 25 ET_NONE = 0,
28 ET_REL = 1, 26 ET_REL = 1,
29 ET_EXEC = 2, 27 ET_EXEC = 2,
30 ET_DYN = 3, 28 ET_DYN = 3,
31 ET_CORE = 4, 29 ET_CORE = 4,
32 ET_LOPROC = 0xFF00, 30 ET_LOPROC = 0xFF00,
33 ET_HIPROC = 0xFFFF, 31 ET_HIPROC = 0xFFFF,
34}; 32};
35 33
36// Machine/Architecture 34// Machine/Architecture
37enum ElfMachine { 35enum ElfMachine {
38 EM_NONE = 0, 36 EM_NONE = 0,
39 EM_M32 = 1, 37 EM_M32 = 1,
40 EM_SPARC = 2, 38 EM_SPARC = 2,
41 EM_386 = 3, 39 EM_386 = 3,
42 EM_68K = 4, 40 EM_68K = 4,
43 EM_88K = 5, 41 EM_88K = 5,
44 EM_860 = 7, 42 EM_860 = 7,
45 EM_MIPS = 8 43 EM_MIPS = 8
46}; 44};
47 45
48// File version 46// File version
49#define EV_NONE 0 47#define EV_NONE 0
50#define EV_CURRENT 1 48#define EV_CURRENT 1
51 49
52// Identification index 50// Identification index
53#define EI_MAG0 0 51#define EI_MAG0 0
54#define EI_MAG1 1 52#define EI_MAG1 1
55#define EI_MAG2 2 53#define EI_MAG2 2
56#define EI_MAG3 3 54#define EI_MAG3 3
57#define EI_CLASS 4 55#define EI_CLASS 4
58#define EI_DATA 5 56#define EI_DATA 5
59#define EI_VERSION 6 57#define EI_VERSION 6
60#define EI_PAD 7 58#define EI_PAD 7
61#define EI_NIDENT 16 59#define EI_NIDENT 16
62 60
63// Sections constants 61// Sections constants
64 62
65// Section types 63// Section types
66#define SHT_NULL 0 64#define SHT_NULL 0
67#define SHT_PROGBITS 1 65#define SHT_PROGBITS 1
68#define SHT_SYMTAB 2 66#define SHT_SYMTAB 2
69#define SHT_STRTAB 3 67#define SHT_STRTAB 3
70#define SHT_RELA 4 68#define SHT_RELA 4
71#define SHT_HASH 5 69#define SHT_HASH 5
72#define SHT_DYNAMIC 6 70#define SHT_DYNAMIC 6
73#define SHT_NOTE 7 71#define SHT_NOTE 7
74#define SHT_NOBITS 8 72#define SHT_NOBITS 8
75#define SHT_REL 9 73#define SHT_REL 9
76#define SHT_SHLIB 10 74#define SHT_SHLIB 10
77#define SHT_DYNSYM 11 75#define SHT_DYNSYM 11
78#define SHT_LOPROC 0x70000000 76#define SHT_LOPROC 0x70000000
79#define SHT_HIPROC 0x7FFFFFFF 77#define SHT_HIPROC 0x7FFFFFFF
80#define SHT_LOUSER 0x80000000 78#define SHT_LOUSER 0x80000000
81#define SHT_HIUSER 0xFFFFFFFF 79#define SHT_HIUSER 0xFFFFFFFF
82 80
83// Section flags 81// Section flags
84enum ElfSectionFlags 82enum ElfSectionFlags {
85{ 83 SHF_WRITE = 0x1,
86 SHF_WRITE = 0x1, 84 SHF_ALLOC = 0x2,
87 SHF_ALLOC = 0x2,
88 SHF_EXECINSTR = 0x4, 85 SHF_EXECINSTR = 0x4,
89 SHF_MASKPROC = 0xF0000000, 86 SHF_MASKPROC = 0xF0000000,
90}; 87};
91 88
92// Segment types 89// Segment types
93#define PT_NULL 0 90#define PT_NULL 0
94#define PT_LOAD 1 91#define PT_LOAD 1
95#define PT_DYNAMIC 2 92#define PT_DYNAMIC 2
96#define PT_INTERP 3 93#define PT_INTERP 3
97#define PT_NOTE 4 94#define PT_NOTE 4
98#define PT_SHLIB 5 95#define PT_SHLIB 5
99#define PT_PHDR 6 96#define PT_PHDR 6
100#define PT_LOPROC 0x70000000 97#define PT_LOPROC 0x70000000
101#define PT_HIPROC 0x7FFFFFFF 98#define PT_HIPROC 0x7FFFFFFF
102 99
103// Segment flags 100// Segment flags
104#define PF_X 0x1 101#define PF_X 0x1
105#define PF_W 0x2 102#define PF_W 0x2
106#define PF_R 0x4 103#define PF_R 0x4
107#define PF_MASKPROC 0xF0000000 104#define PF_MASKPROC 0xF0000000
108 105
109typedef unsigned int Elf32_Addr; 106typedef unsigned int Elf32_Addr;
110typedef unsigned short Elf32_Half; 107typedef unsigned short Elf32_Half;
111typedef unsigned int Elf32_Off; 108typedef unsigned int Elf32_Off;
112typedef signed int Elf32_Sword; 109typedef signed int Elf32_Sword;
113typedef unsigned int Elf32_Word; 110typedef unsigned int Elf32_Word;
114 111
115//////////////////////////////////////////////////////////////////////////////////////////////////// 112////////////////////////////////////////////////////////////////////////////////////////////////////
116// ELF file header 113// ELF file header
117 114
118struct Elf32_Ehdr { 115struct Elf32_Ehdr {
119 unsigned char e_ident[EI_NIDENT]; 116 unsigned char e_ident[EI_NIDENT];
120 Elf32_Half e_type; 117 Elf32_Half e_type;
121 Elf32_Half e_machine; 118 Elf32_Half e_machine;
122 Elf32_Word e_version; 119 Elf32_Word e_version;
123 Elf32_Addr e_entry; 120 Elf32_Addr e_entry;
124 Elf32_Off e_phoff; 121 Elf32_Off e_phoff;
125 Elf32_Off e_shoff; 122 Elf32_Off e_shoff;
126 Elf32_Word e_flags; 123 Elf32_Word e_flags;
127 Elf32_Half e_ehsize; 124 Elf32_Half e_ehsize;
128 Elf32_Half e_phentsize; 125 Elf32_Half e_phentsize;
129 Elf32_Half e_phnum; 126 Elf32_Half e_phnum;
130 Elf32_Half e_shentsize; 127 Elf32_Half e_shentsize;
131 Elf32_Half e_shnum; 128 Elf32_Half e_shnum;
132 Elf32_Half e_shstrndx; 129 Elf32_Half e_shstrndx;
133}; 130};
134 131
135// Section header 132// Section header
@@ -138,7 +135,7 @@ struct Elf32_Shdr {
138 Elf32_Word sh_type; 135 Elf32_Word sh_type;
139 Elf32_Word sh_flags; 136 Elf32_Word sh_flags;
140 Elf32_Addr sh_addr; 137 Elf32_Addr sh_addr;
141 Elf32_Off sh_offset; 138 Elf32_Off sh_offset;
142 Elf32_Word sh_size; 139 Elf32_Word sh_size;
143 Elf32_Word sh_link; 140 Elf32_Word sh_link;
144 Elf32_Word sh_info; 141 Elf32_Word sh_info;
@@ -149,7 +146,7 @@ struct Elf32_Shdr {
149// Segment header 146// Segment header
150struct Elf32_Phdr { 147struct Elf32_Phdr {
151 Elf32_Word p_type; 148 Elf32_Word p_type;
152 Elf32_Off p_offset; 149 Elf32_Off p_offset;
153 Elf32_Addr p_vaddr; 150 Elf32_Addr p_vaddr;
154 Elf32_Addr p_paddr; 151 Elf32_Addr p_paddr;
155 Elf32_Word p_filesz; 152 Elf32_Word p_filesz;
@@ -160,12 +157,12 @@ struct Elf32_Phdr {
160 157
161// Symbol table entry 158// Symbol table entry
162struct Elf32_Sym { 159struct Elf32_Sym {
163 Elf32_Word st_name; 160 Elf32_Word st_name;
164 Elf32_Addr st_value; 161 Elf32_Addr st_value;
165 Elf32_Word st_size; 162 Elf32_Word st_size;
166 unsigned char st_info; 163 unsigned char st_info;
167 unsigned char st_other; 164 unsigned char st_other;
168 Elf32_Half st_shndx; 165 Elf32_Half st_shndx;
169}; 166};
170 167
171// Relocation entries 168// Relocation entries
@@ -181,35 +178,51 @@ typedef int SectionID;
181 178
182class ElfReader { 179class ElfReader {
183private: 180private:
184 char *base; 181 char* base;
185 u32 *base32; 182 u32* base32;
186 183
187 Elf32_Ehdr *header; 184 Elf32_Ehdr* header;
188 Elf32_Phdr *segments; 185 Elf32_Phdr* segments;
189 Elf32_Shdr *sections; 186 Elf32_Shdr* sections;
190 187
191 u32 *sectionAddrs; 188 u32* sectionAddrs;
192 bool relocate; 189 bool relocate;
193 u32 entryPoint; 190 u32 entryPoint;
194 191
195public: 192public:
196 ElfReader(void *ptr); 193 ElfReader(void* ptr);
197 194
198 u32 Read32(int off) const { return base32[off >> 2]; } 195 u32 Read32(int off) const {
196 return base32[off >> 2];
197 }
199 198
200 // Quick accessors 199 // Quick accessors
201 ElfType GetType() const { return (ElfType)(header->e_type); } 200 ElfType GetType() const {
202 ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); } 201 return (ElfType)(header->e_type);
203 u32 GetEntryPoint() const { return entryPoint; } 202 }
204 u32 GetFlags() const { return (u32)(header->e_flags); } 203 ElfMachine GetMachine() const {
204 return (ElfMachine)(header->e_machine);
205 }
206 u32 GetEntryPoint() const {
207 return entryPoint;
208 }
209 u32 GetFlags() const {
210 return (u32)(header->e_flags);
211 }
205 SharedPtr<CodeSet> LoadInto(u32 vaddr); 212 SharedPtr<CodeSet> LoadInto(u32 vaddr);
206 bool LoadSymbols(); 213 bool LoadSymbols();
207 214
208 int GetNumSegments() const { return (int)(header->e_phnum); } 215 int GetNumSegments() const {
209 int GetNumSections() const { return (int)(header->e_shnum); } 216 return (int)(header->e_phnum);
210 const u8 *GetPtr(int offset) const { return (u8*)base + offset; } 217 }
211 const char *GetSectionName(int section) const; 218 int GetNumSections() const {
212 const u8 *GetSectionDataPtr(int section) const { 219 return (int)(header->e_shnum);
220 }
221 const u8* GetPtr(int offset) const {
222 return (u8*)base + offset;
223 }
224 const char* GetSectionName(int section) const;
225 const u8* GetSectionDataPtr(int section) const {
213 if (section < 0 || section >= header->e_shnum) 226 if (section < 0 || section >= header->e_shnum)
214 return nullptr; 227 return nullptr;
215 if (sections[section].sh_type != SHT_NOBITS) 228 if (sections[section].sh_type != SHT_NOBITS)
@@ -220,19 +233,23 @@ public:
220 bool IsCodeSection(int section) const { 233 bool IsCodeSection(int section) const {
221 return sections[section].sh_type == SHT_PROGBITS; 234 return sections[section].sh_type == SHT_PROGBITS;
222 } 235 }
223 const u8 *GetSegmentPtr(int segment) { 236 const u8* GetSegmentPtr(int segment) {
224 return GetPtr(segments[segment].p_offset); 237 return GetPtr(segments[segment].p_offset);
225 } 238 }
226 u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; } 239 u32 GetSectionAddr(SectionID section) const {
227 unsigned int GetSectionSize(SectionID section) const { return sections[section].sh_size; } 240 return sectionAddrs[section];
228 SectionID GetSectionByName(const char *name, int firstSection = 0) const; //-1 for not found 241 }
242 unsigned int GetSectionSize(SectionID section) const {
243 return sections[section].sh_size;
244 }
245 SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found
229 246
230 bool DidRelocate() const { 247 bool DidRelocate() const {
231 return relocate; 248 return relocate;
232 } 249 }
233}; 250};
234 251
235ElfReader::ElfReader(void *ptr) { 252ElfReader::ElfReader(void* ptr) {
236 base = (char*)ptr; 253 base = (char*)ptr;
237 base32 = (u32*)ptr; 254 base32 = (u32*)ptr;
238 header = (Elf32_Ehdr*)ptr; 255 header = (Elf32_Ehdr*)ptr;
@@ -245,7 +262,7 @@ ElfReader::ElfReader(void *ptr) {
245 LoadSymbols(); 262 LoadSymbols();
246} 263}
247 264
248const char *ElfReader::GetSectionName(int section) const { 265const char* ElfReader::GetSectionName(int section) const {
249 if (sections[section].sh_type == SHT_NULL) 266 if (sections[section].sh_type == SHT_NULL)
250 return nullptr; 267 return nullptr;
251 268
@@ -303,12 +320,15 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
303 } else if (permission_flags == (PF_R | PF_W)) { 320 } else if (permission_flags == (PF_R | PF_W)) {
304 codeset_segment = &codeset->data; 321 codeset_segment = &codeset->data;
305 } else { 322 } else {
306 LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i, p->p_flags); 323 LOG_ERROR(Loader, "Unexpected ELF PT_LOAD segment id %u with flags %X", i,
324 p->p_flags);
307 continue; 325 continue;
308 } 326 }
309 327
310 if (codeset_segment->size != 0) { 328 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); 329 LOG_ERROR(Loader, "ELF has more than one segment of the same type. Skipping extra "
330 "segment (id %i)",
331 i);
312 continue; 332 continue;
313 } 333 }
314 334
@@ -332,9 +352,9 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
332 return codeset; 352 return codeset;
333} 353}
334 354
335SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const { 355SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const {
336 for (int i = firstSection; i < header->e_shnum; i++) { 356 for (int i = firstSection; i < header->e_shnum; i++) {
337 const char *secname = GetSectionName(i); 357 const char* secname = GetSectionName(i);
338 358
339 if (secname != nullptr && strcmp(name, secname) == 0) 359 if (secname != nullptr && strcmp(name, secname) == 0)
340 return i; 360 return i;
@@ -347,9 +367,9 @@ bool ElfReader::LoadSymbols() {
347 SectionID sec = GetSectionByName(".symtab"); 367 SectionID sec = GetSectionByName(".symtab");
348 if (sec != -1) { 368 if (sec != -1) {
349 int stringSection = sections[sec].sh_link; 369 int stringSection = sections[sec].sh_link;
350 const char *stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection)); 370 const char* stringBase = reinterpret_cast<const char*>(GetSectionDataPtr(stringSection));
351 371
352 //We have a symbol table! 372 // We have a symbol table!
353 const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec)); 373 const Elf32_Sym* symtab = reinterpret_cast<const Elf32_Sym*>(GetSectionDataPtr(sec));
354 unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym); 374 unsigned int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
355 for (unsigned sym = 0; sym < numSymbols; sym++) { 375 for (unsigned sym = 0; sym < numSymbols; sym++) {
@@ -359,7 +379,7 @@ bool ElfReader::LoadSymbols() {
359 379
360 int type = symtab[sym].st_info & 0xF; 380 int type = symtab[sym].st_info & 0xF;
361 381
362 const char *name = stringBase + symtab[sym].st_name; 382 const char* name = stringBase + symtab[sym].st_name;
363 383
364 Symbols::Add(symtab[sym].st_value, name, size, type); 384 Symbols::Add(symtab[sym].st_value, name, size, type);
365 385
@@ -411,7 +431,8 @@ ResultStatus AppLoader_ELF::Load() {
411 Kernel::g_current_process->address_mappings = default_address_mappings; 431 Kernel::g_current_process->address_mappings = default_address_mappings;
412 432
413 // Attach the default resource limit (APPLICATION) to the process 433 // Attach the default resource limit (APPLICATION) to the process
414 Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); 434 Kernel::g_current_process->resource_limit =
435 Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
415 436
416 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); 437 Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE);
417 438
diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h
index cb3724f9d..584bf6e27 100644
--- a/src/core/loader/elf.h
+++ b/src/core/loader/elf.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <string> 7#include <string>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "core/loader/loader.h" 9#include "core/loader/loader.h"
11 10
@@ -18,7 +17,7 @@ namespace Loader {
18class AppLoader_ELF final : public AppLoader { 17class AppLoader_ELF final : public AppLoader {
19public: 18public:
20 AppLoader_ELF(FileUtil::IOFile&& file, std::string filename) 19 AppLoader_ELF(FileUtil::IOFile&& file, std::string filename)
21 : AppLoader(std::move(file)), filename(std::move(filename)) { } 20 : AppLoader(std::move(file)), filename(std::move(filename)) {}
22 21
23 /** 22 /**
24 * Returns the type of the file 23 * Returns the type of the file
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 9719d30d5..147bf8591 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -4,10 +4,8 @@
4 4
5#include <memory> 5#include <memory>
6#include <string> 6#include <string>
7
8#include "common/logging/log.h" 7#include "common/logging/log.h"
9#include "common/string_util.h" 8#include "common/string_util.h"
10
11#include "core/hle/kernel/process.h" 9#include "core/hle/kernel/process.h"
12#include "core/loader/3dsx.h" 10#include "core/loader/3dsx.h"
13#include "core/loader/elf.h" 11#include "core/loader/elf.h"
@@ -18,17 +16,17 @@
18namespace Loader { 16namespace Loader {
19 17
20const std::initializer_list<Kernel::AddressMapping> default_address_mappings = { 18const std::initializer_list<Kernel::AddressMapping> default_address_mappings = {
21 { 0x1FF50000, 0x8000, true }, // part of DSP RAM 19 {0x1FF50000, 0x8000, true}, // part of DSP RAM
22 { 0x1FF70000, 0x8000, true }, // part of DSP RAM 20 {0x1FF70000, 0x8000, true}, // part of DSP RAM
23 { 0x1F000000, 0x600000, false }, // entire VRAM 21 {0x1F000000, 0x600000, false}, // entire VRAM
24}; 22};
25 23
26FileType IdentifyFile(FileUtil::IOFile& file) { 24FileType IdentifyFile(FileUtil::IOFile& file) {
27 FileType type; 25 FileType type;
28 26
29#define CHECK_TYPE(loader) \ 27#define CHECK_TYPE(loader) \
30 type = AppLoader_##loader::IdentifyType(file); \ 28 type = AppLoader_##loader::IdentifyType(file); \
31 if (FileType::Error != type) \ 29 if (FileType::Error != type) \
32 return type; 30 return type;
33 31
34 CHECK_TYPE(THREEDSX) 32 CHECK_TYPE(THREEDSX)
@@ -100,7 +98,8 @@ const char* GetFileTypeString(FileType type) {
100 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type 98 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type
101 */ 99 */
102static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileType type, 100static std::unique_ptr<AppLoader> GetFileLoader(FileUtil::IOFile&& file, FileType type,
103 const std::string& filename, const std::string& filepath) { 101 const std::string& filename,
102 const std::string& filepath) {
104 switch (type) { 103 switch (type) {
105 104
106 // 3DSX file format. 105 // 3DSX file format.
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 77d87afe1..9652d7ac5 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -9,7 +9,6 @@
9#include <memory> 9#include <memory>
10#include <string> 10#include <string>
11#include <vector> 11#include <vector>
12
13#include "common/common_types.h" 12#include "common/common_types.h"
14#include "common/file_util.h" 13#include "common/file_util.h"
15 14
@@ -30,7 +29,7 @@ enum class FileType {
30 CXI, 29 CXI,
31 CIA, 30 CIA,
32 ELF, 31 ELF,
33 THREEDSX, //3DSX 32 THREEDSX, // 3DSX
34}; 33};
35 34
36/** 35/**
@@ -81,8 +80,8 @@ constexpr u32 MakeMagic(char a, char b, char c, char d) {
81/// Interface for loading an application 80/// Interface for loading an application
82class AppLoader : NonCopyable { 81class AppLoader : NonCopyable {
83public: 82public:
84 AppLoader(FileUtil::IOFile&& file) : file(std::move(file)) { } 83 AppLoader(FileUtil::IOFile&& file) : file(std::move(file)) {}
85 virtual ~AppLoader() { } 84 virtual ~AppLoader() {}
86 85
87 /** 86 /**
88 * Returns the type of this file 87 * Returns the type of this file
@@ -140,7 +139,8 @@ public:
140 * @param size The size of the romfs 139 * @param size The size of the romfs
141 * @return ResultStatus result of function 140 * @return ResultStatus result of function
142 */ 141 */
143 virtual ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { 142 virtual ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
143 u64& size) {
144 return ResultStatus::ErrorNotImplemented; 144 return ResultStatus::ErrorNotImplemented;
145 } 145 }
146 146
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index fca091ff9..2e4510857 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -5,11 +5,9 @@
5#include <algorithm> 5#include <algorithm>
6#include <cstring> 6#include <cstring>
7#include <memory> 7#include <memory>
8
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10#include "common/string_util.h" 9#include "common/string_util.h"
11#include "common/swap.h" 10#include "common/swap.h"
12
13#include "core/file_sys/archive_romfs.h" 11#include "core/file_sys/archive_romfs.h"
14#include "core/hle/kernel/process.h" 12#include "core/hle/kernel/process.h"
15#include "core/hle/kernel/resource_limit.h" 13#include "core/hle/kernel/resource_limit.h"
@@ -22,8 +20,8 @@
22 20
23namespace Loader { 21namespace Loader {
24 22
25static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs 23static const int kMaxSections = 8; ///< Maximum number of sections (files) in an ExeFs
26static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes) 24static const int kBlockSize = 0x200; ///< Size of ExeFS blocks (in bytes)
27 25
28/** 26/**
29 * Get the decompressed size of an LZSS compressed ExeFS file 27 * Get the decompressed size of an LZSS compressed ExeFS file
@@ -44,7 +42,8 @@ static u32 LZSS_GetDecompressedSize(const u8* buffer, u32 size) {
44 * @param decompressed_size Size of decompressed buffer 42 * @param decompressed_size Size of decompressed buffer
45 * @return True on success, otherwise false 43 * @return True on success, otherwise false
46 */ 44 */
47static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decompressed, u32 decompressed_size) { 45static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decompressed,
46 u32 decompressed_size) {
48 const u8* footer = compressed + compressed_size - 8; 47 const u8* footer = compressed + compressed_size - 8;
49 u32 buffer_top_and_bottom = *reinterpret_cast<const u32*>(footer); 48 u32 buffer_top_and_bottom = *reinterpret_cast<const u32*>(footer);
50 u32 out = decompressed_size; 49 u32 out = decompressed_size;
@@ -55,7 +54,7 @@ static bool LZSS_Decompress(const u8* compressed, u32 compressed_size, u8* decom
55 memcpy(decompressed, compressed, compressed_size); 54 memcpy(decompressed, compressed, compressed_size);
56 55
57 while (index > stop_index) { 56 while (index > stop_index) {
58 u8 control = compressed[--index]; 57 u8 control = compressed[--index];
59 58
60 for (unsigned i = 0; i < 8; i++) { 59 for (unsigned i = 0; i < 8; i++) {
61 if (index <= stop_index) 60 if (index <= stop_index)
@@ -128,7 +127,7 @@ ResultStatus AppLoader_NCCH::LoadExec() {
128 std::vector<u8> code; 127 std::vector<u8> code;
129 if (ResultStatus::Success == ReadCode(code)) { 128 if (ResultStatus::Success == ReadCode(code)) {
130 std::string process_name = Common::StringFromFixedZeroTerminatedBuffer( 129 std::string process_name = Common::StringFromFixedZeroTerminatedBuffer(
131 (const char*)exheader_header.codeset_info.name, 8); 130 (const char*)exheader_header.codeset_info.name, 8);
132 131
133 SharedPtr<CodeSet> codeset = CodeSet::Create(process_name, ncch_header.program_id); 132 SharedPtr<CodeSet> codeset = CodeSet::Create(process_name, ncch_header.program_id);
134 133
@@ -147,7 +146,8 @@ ResultStatus AppLoader_NCCH::LoadExec() {
147 146
148 codeset->data.offset = codeset->rodata.offset + codeset->rodata.size; 147 codeset->data.offset = codeset->rodata.offset + codeset->rodata.size;
149 codeset->data.addr = exheader_header.codeset_info.data.address; 148 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; 149 codeset->data.size =
150 exheader_header.codeset_info.data.num_max_pages * Memory::PAGE_SIZE + bss_page_size;
151 151
152 codeset->entrypoint = codeset->code.addr; 152 codeset->entrypoint = codeset->code.addr;
153 codeset->memory = std::make_shared<std::vector<u8>>(std::move(code)); 153 codeset->memory = std::make_shared<std::vector<u8>>(std::move(code));
@@ -155,15 +155,18 @@ ResultStatus AppLoader_NCCH::LoadExec() {
155 Kernel::g_current_process = Kernel::Process::Create(std::move(codeset)); 155 Kernel::g_current_process = Kernel::Process::Create(std::move(codeset));
156 156
157 // Attach a resource limit to the process based on the resource limit category 157 // Attach a resource limit to the process based on the resource limit category
158 Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory( 158 Kernel::g_current_process->resource_limit =
159 static_cast<Kernel::ResourceLimitCategory>(exheader_header.arm11_system_local_caps.resource_limit_category)); 159 Kernel::ResourceLimit::GetForCategory(static_cast<Kernel::ResourceLimitCategory>(
160 exheader_header.arm11_system_local_caps.resource_limit_category));
160 161
161 // Set the default CPU core for this process 162 // Set the default CPU core for this process
162 Kernel::g_current_process->ideal_processor = exheader_header.arm11_system_local_caps.ideal_processor; 163 Kernel::g_current_process->ideal_processor =
164 exheader_header.arm11_system_local_caps.ideal_processor;
163 165
164 // Copy data while converting endianess 166 // Copy data while converting endianess
165 std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps; 167 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)); 168 std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(),
169 begin(kernel_caps));
167 Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size()); 170 Kernel::g_current_process->ParseKernelCaps(kernel_caps.data(), kernel_caps.size());
168 171
169 s32 priority = exheader_header.arm11_system_local_caps.priority; 172 s32 priority = exheader_header.arm11_system_local_caps.priority;
@@ -192,7 +195,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, 195 LOG_DEBUG(Loader, "%d - offset: 0x%08X, size: 0x%08X, name: %s", section_number,
193 section.offset, section.size, section.name); 196 section.offset, section.size, section.name);
194 197
195 s64 section_offset = (section.offset + exefs_offset + sizeof(ExeFs_Header) + ncch_offset); 198 s64 section_offset =
199 (section.offset + exefs_offset + sizeof(ExeFs_Header) + ncch_offset);
196 file.Seek(section_offset, SEEK_SET); 200 file.Seek(section_offset, SEEK_SET);
197 201
198 if (strcmp(section.name, ".code") == 0 && is_compressed) { 202 if (strcmp(section.name, ".code") == 0 && is_compressed) {
@@ -254,25 +258,25 @@ ResultStatus AppLoader_NCCH::LoadExeFS() {
254 if (file.ReadBytes(&exheader_header, sizeof(ExHeader_Header)) != sizeof(ExHeader_Header)) 258 if (file.ReadBytes(&exheader_header, sizeof(ExHeader_Header)) != sizeof(ExHeader_Header))
255 return ResultStatus::Error; 259 return ResultStatus::Error;
256 260
257 is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1; 261 is_compressed = (exheader_header.codeset_info.flags.flag & 1) == 1;
258 entry_point = exheader_header.codeset_info.text.address; 262 entry_point = exheader_header.codeset_info.text.address;
259 code_size = exheader_header.codeset_info.text.code_size; 263 code_size = exheader_header.codeset_info.text.code_size;
260 stack_size = exheader_header.codeset_info.stack_size; 264 stack_size = exheader_header.codeset_info.stack_size;
261 bss_size = exheader_header.codeset_info.bss_size; 265 bss_size = exheader_header.codeset_info.bss_size;
262 core_version = exheader_header.arm11_system_local_caps.core_version; 266 core_version = exheader_header.arm11_system_local_caps.core_version;
263 priority = exheader_header.arm11_system_local_caps.priority; 267 priority = exheader_header.arm11_system_local_caps.priority;
264 resource_limit_category = exheader_header.arm11_system_local_caps.resource_limit_category; 268 resource_limit_category = exheader_header.arm11_system_local_caps.resource_limit_category;
265 269
266 LOG_INFO(Loader, "Name: %s" , exheader_header.codeset_info.name); 270 LOG_INFO(Loader, "Name: %s", exheader_header.codeset_info.name);
267 LOG_INFO(Loader, "Program ID: %016llX" , ncch_header.program_id); 271 LOG_INFO(Loader, "Program ID: %016llX", ncch_header.program_id);
268 LOG_DEBUG(Loader, "Code compressed: %s" , is_compressed ? "yes" : "no"); 272 LOG_DEBUG(Loader, "Code compressed: %s", is_compressed ? "yes" : "no");
269 LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point); 273 LOG_DEBUG(Loader, "Entry point: 0x%08X", entry_point);
270 LOG_DEBUG(Loader, "Code size: 0x%08X", code_size); 274 LOG_DEBUG(Loader, "Code size: 0x%08X", code_size);
271 LOG_DEBUG(Loader, "Stack size: 0x%08X", stack_size); 275 LOG_DEBUG(Loader, "Stack size: 0x%08X", stack_size);
272 LOG_DEBUG(Loader, "Bss size: 0x%08X", bss_size); 276 LOG_DEBUG(Loader, "Bss size: 0x%08X", bss_size);
273 LOG_DEBUG(Loader, "Core version: %d" , core_version); 277 LOG_DEBUG(Loader, "Core version: %d", core_version);
274 LOG_DEBUG(Loader, "Thread priority: 0x%X" , priority); 278 LOG_DEBUG(Loader, "Thread priority: 0x%X", priority);
275 LOG_DEBUG(Loader, "Resource limit category: %d" , resource_limit_category); 279 LOG_DEBUG(Loader, "Resource limit category: %d", resource_limit_category);
276 280
277 if (exheader_header.arm11_system_local_caps.program_id != ncch_header.program_id) { 281 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."); 282 LOG_ERROR(Loader, "ExHeader Program ID mismatch: the ROM is probably encrypted.");
@@ -309,7 +313,8 @@ ResultStatus AppLoader_NCCH::Load() {
309 if (ResultStatus::Success != result) 313 if (ResultStatus::Success != result)
310 return result; 314 return result;
311 315
312 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this), Service::FS::ArchiveIdCode::RomFS); 316 Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(*this),
317 Service::FS::ArchiveIdCode::RomFS);
313 return ResultStatus::Success; 318 return ResultStatus::Success;
314} 319}
315 320
@@ -329,7 +334,8 @@ ResultStatus AppLoader_NCCH::ReadLogo(std::vector<u8>& buffer) {
329 return LoadSectionExeFS("logo", buffer); 334 return LoadSectionExeFS("logo", buffer);
330} 335}
331 336
332ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) { 337ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
338 u64& size) {
333 if (!file.IsOpen()) 339 if (!file.IsOpen())
334 return ResultStatus::Error; 340 return ResultStatus::Error;
335 341
@@ -341,7 +347,7 @@ ResultStatus AppLoader_NCCH::ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_
341 LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset); 347 LOG_DEBUG(Loader, "RomFS offset: 0x%08X", romfs_offset);
342 LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size); 348 LOG_DEBUG(Loader, "RomFS size: 0x%08X", romfs_size);
343 349
344 if (file.GetSize () < romfs_offset + romfs_size) 350 if (file.GetSize() < romfs_offset + romfs_size)
345 return ResultStatus::Error; 351 return ResultStatus::Error;
346 352
347 // We reopen the file, to allow its position to be independent from file's 353 // 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..04350d006 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -5,11 +5,9 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8
9#include "common/bit_field.h" 8#include "common/bit_field.h"
10#include "common/common_types.h" 9#include "common/common_types.h"
11#include "common/swap.h" 10#include "common/swap.h"
12
13#include "core/loader/loader.h" 11#include "core/loader/loader.h"
14 12
15//////////////////////////////////////////////////////////////////////////////////////////////////// 13////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -164,7 +162,7 @@ namespace Loader {
164class AppLoader_NCCH final : public AppLoader { 162class AppLoader_NCCH final : public AppLoader {
165public: 163public:
166 AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath) 164 AppLoader_NCCH(FileUtil::IOFile&& file, const std::string& filepath)
167 : AppLoader(std::move(file)), filepath(filepath) { } 165 : AppLoader(std::move(file)), filepath(filepath) {}
168 166
169 /** 167 /**
170 * Returns the type of the file 168 * Returns the type of the file
@@ -222,10 +220,10 @@ public:
222 * @param size Size of the RomFS in bytes 220 * @param size Size of the RomFS in bytes
223 * @return ResultStatus result of function 221 * @return ResultStatus result of function
224 */ 222 */
225 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset, u64& size) override; 223 ResultStatus ReadRomFS(std::shared_ptr<FileUtil::IOFile>& romfs_file, u64& offset,
224 u64& size) override;
226 225
227private: 226private:
228
229 /** 227 /**
230 * Reads an application ExeFS section of an NCCH file into AppLoader (e.g. .code, .logo, etc.) 228 * 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 229 * @param name Name of section to read out of NCCH file
@@ -246,24 +244,24 @@ private:
246 */ 244 */
247 ResultStatus LoadExeFS(); 245 ResultStatus LoadExeFS();
248 246
249 bool is_exefs_loaded = false; 247 bool is_exefs_loaded = false;
250 bool is_compressed = false; 248 bool is_compressed = false;
251 249
252 u32 entry_point = 0; 250 u32 entry_point = 0;
253 u32 code_size = 0; 251 u32 code_size = 0;
254 u32 stack_size = 0; 252 u32 stack_size = 0;
255 u32 bss_size = 0; 253 u32 bss_size = 0;
256 u32 core_version = 0; 254 u32 core_version = 0;
257 u8 priority = 0; 255 u8 priority = 0;
258 u8 resource_limit_category = 0; 256 u8 resource_limit_category = 0;
259 u32 ncch_offset = 0; // Offset to NCCH header, can be 0 or after NCSD header 257 u32 ncch_offset = 0; // Offset to NCCH header, can be 0 or after NCSD header
260 u32 exefs_offset = 0; 258 u32 exefs_offset = 0;
261 259
262 NCCH_Header ncch_header; 260 NCCH_Header ncch_header;
263 ExeFs_Header exefs_header; 261 ExeFs_Header exefs_header;
264 ExHeader_Header exheader_header; 262 ExHeader_Header exheader_header;
265 263
266 std::string filepath; 264 std::string filepath;
267}; 265};
268 266
269} // namespace Loader 267} // namespace Loader
diff --git a/src/core/loader/smdh.cpp b/src/core/loader/smdh.cpp
index 2d014054a..ccbeb7961 100644
--- a/src/core/loader/smdh.cpp
+++ b/src/core/loader/smdh.cpp
@@ -4,12 +4,9 @@
4 4
5#include <cstring> 5#include <cstring>
6#include <vector> 6#include <vector>
7
8#include "common/common_types.h" 7#include "common/common_types.h"
9
10#include "core/loader/loader.h" 8#include "core/loader/loader.h"
11#include "core/loader/smdh.h" 9#include "core/loader/smdh.h"
12
13#include "video_core/utils.h" 10#include "video_core/utils.h"
14 11
15namespace Loader { 12namespace Loader {
diff --git a/src/core/loader/smdh.h b/src/core/loader/smdh.h
index 2011abda2..ac7726c8f 100644
--- a/src/core/loader/smdh.h
+++ b/src/core/loader/smdh.h
@@ -6,7 +6,6 @@
6 6
7#include <array> 7#include <array>
8#include <vector> 8#include <vector>
9
10#include "common/common_funcs.h" 9#include "common/common_funcs.h"
11#include "common/common_types.h" 10#include "common/common_types.h"
12#include "common/swap.h" 11#include "common/swap.h"
@@ -56,7 +55,7 @@ struct SMDH {
56 Italian = 4, 55 Italian = 4,
57 Spanish = 5, 56 Spanish = 5,
58 SimplifiedChinese = 6, 57 SimplifiedChinese = 6,
59 Korean= 7, 58 Korean = 7,
60 Dutch = 8, 59 Dutch = 8,
61 Portuguese = 9, 60 Portuguese = 9,
62 Russian = 10, 61 Russian = 10,
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 9aa8c4e5a..df029d655 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -4,17 +4,14 @@
4 4
5#include <array> 5#include <array>
6#include <cstring> 6#include <cstring>
7
8#include "common/assert.h" 7#include "common/assert.h"
9#include "common/common_types.h" 8#include "common/common_types.h"
10#include "common/logging/log.h" 9#include "common/logging/log.h"
11#include "common/swap.h" 10#include "common/swap.h"
12
13#include "core/hle/kernel/process.h" 11#include "core/hle/kernel/process.h"
14#include "core/memory.h" 12#include "core/memory.h"
15#include "core/memory_setup.h" 13#include "core/memory_setup.h"
16#include "core/mmio.h" 14#include "core/mmio.h"
17
18#include "video_core/renderer_base.h" 15#include "video_core/renderer_base.h"
19#include "video_core/video_core.h" 16#include "video_core/video_core.h"
20 17
@@ -25,11 +22,13 @@ enum class PageType {
25 Unmapped, 22 Unmapped,
26 /// Page is mapped to regular memory. This is the only type you can get pointers to. 23 /// Page is mapped to regular memory. This is the only type you can get pointers to.
27 Memory, 24 Memory,
28 /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and invalidation 25 /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and
26 /// invalidation
29 RasterizerCachedMemory, 27 RasterizerCachedMemory,
30 /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions. 28 /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions.
31 Special, 29 Special,
32 /// Page is mapped to a I/O region, but also needs to check for rasterizer cache flushing and invalidation 30 /// Page is mapped to a I/O region, but also needs to check for rasterizer cache flushing and
31 /// invalidation
33 RasterizerCachedSpecial, 32 RasterizerCachedSpecial,
34}; 33};
35 34
@@ -55,7 +54,8 @@ struct PageTable {
55 std::array<u8*, NUM_ENTRIES> pointers; 54 std::array<u8*, NUM_ENTRIES> pointers;
56 55
57 /** 56 /**
58 * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of type `Special`. 57 * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of
58 * type `Special`.
59 */ 59 */
60 std::vector<SpecialRegion> special_regions; 60 std::vector<SpecialRegion> special_regions;
61 61
@@ -78,17 +78,20 @@ static PageTable main_page_table;
78static PageTable* current_page_table = &main_page_table; 78static PageTable* current_page_table = &main_page_table;
79 79
80static void MapPages(u32 base, u32 size, u8* memory, PageType type) { 80static 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); 81 LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE,
82 (base + size) * PAGE_SIZE);
82 83
83 u32 end = base + size; 84 u32 end = base + size;
84 85
85 while (base != end) { 86 while (base != end) {
86 ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base); 87 ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base);
87 88
88 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be null here 89 // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be
90 // null here
89 if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory || 91 if (current_page_table->attributes[base] == PageType::RasterizerCachedMemory ||
90 current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) { 92 current_page_table->attributes[base] == PageType::RasterizerCachedSpecial) {
91 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS), PAGE_SIZE); 93 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(base << PAGE_BITS),
94 PAGE_SIZE);
92 } 95 }
93 96
94 current_page_table->attributes[base] = type; 97 current_page_table->attributes[base] = type;
@@ -162,7 +165,7 @@ static MMIORegionPointer GetMMIOHandler(VAddr vaddr) {
162 return nullptr; // Should never happen 165 return nullptr; // Should never happen
163} 166}
164 167
165template<typename T> 168template <typename T>
166T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr); 169T ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr);
167 170
168template <typename T> 171template <typename T>
@@ -183,8 +186,7 @@ T Read(const VAddr vaddr) {
183 case PageType::Memory: 186 case PageType::Memory:
184 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 187 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
185 break; 188 break;
186 case PageType::RasterizerCachedMemory: 189 case PageType::RasterizerCachedMemory: {
187 {
188 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 190 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
189 191
190 T value; 192 T value;
@@ -193,8 +195,7 @@ T Read(const VAddr vaddr) {
193 } 195 }
194 case PageType::Special: 196 case PageType::Special:
195 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 197 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
196 case PageType::RasterizerCachedSpecial: 198 case PageType::RasterizerCachedSpecial: {
197 {
198 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 199 RasterizerFlushRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
199 200
200 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr); 201 return ReadMMIO<T>(GetMMIOHandler(vaddr), vaddr);
@@ -204,7 +205,7 @@ T Read(const VAddr vaddr) {
204 } 205 }
205} 206}
206 207
207template<typename T> 208template <typename T>
208void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data); 209void WriteMMIO(MMIORegionPointer mmio_handler, VAddr addr, const T data);
209 210
210template <typename T> 211template <typename T>
@@ -219,13 +220,13 @@ void Write(const VAddr vaddr, const T data) {
219 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS]; 220 PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
220 switch (type) { 221 switch (type) {
221 case PageType::Unmapped: 222 case PageType::Unmapped:
222 LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32) data, vaddr); 223 LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data,
224 vaddr);
223 return; 225 return;
224 case PageType::Memory: 226 case PageType::Memory:
225 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr); 227 ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
226 break; 228 break;
227 case PageType::RasterizerCachedMemory: 229 case PageType::RasterizerCachedMemory: {
228 {
229 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 230 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
230 231
231 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T)); 232 std::memcpy(GetPointerFromVMA(vaddr), &data, sizeof(T));
@@ -234,8 +235,7 @@ void Write(const VAddr vaddr, const T data) {
234 case PageType::Special: 235 case PageType::Special:
235 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 236 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
236 break; 237 break;
237 case PageType::RasterizerCachedSpecial: 238 case PageType::RasterizerCachedSpecial: {
238 {
239 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T)); 239 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(vaddr), sizeof(T));
240 240
241 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data); 241 WriteMMIO<T>(GetMMIOHandler(vaddr), vaddr, data);
@@ -310,7 +310,8 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
310 for (unsigned i = 0; i < num_pages; ++i) { 310 for (unsigned i = 0; i < num_pages; ++i) {
311 VAddr vaddr = PhysicalToVirtualAddress(paddr); 311 VAddr vaddr = PhysicalToVirtualAddress(paddr);
312 u8& res_count = current_page_table->cached_res_count[vaddr >> PAGE_BITS]; 312 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!"); 313 ASSERT_MSG(count_delta <= UINT8_MAX - res_count,
314 "Rasterizer resource cache counter overflow!");
314 ASSERT_MSG(count_delta >= -res_count, "Rasterizer resource cache counter underflow!"); 315 ASSERT_MSG(count_delta >= -res_count, "Rasterizer resource cache counter underflow!");
315 316
316 // Switch page type to cached if now cached 317 // Switch page type to cached if now cached
@@ -337,7 +338,8 @@ void RasterizerMarkRegionCached(PAddr start, u32 size, int count_delta) {
337 switch (page_type) { 338 switch (page_type) {
338 case PageType::RasterizerCachedMemory: 339 case PageType::RasterizerCachedMemory:
339 page_type = PageType::Memory; 340 page_type = PageType::Memory;
340 current_page_table->pointers[vaddr >> PAGE_BITS] = GetPointerFromVMA(vaddr & ~PAGE_MASK); 341 current_page_table->pointers[vaddr >> PAGE_BITS] =
342 GetPointerFromVMA(vaddr & ~PAGE_MASK);
341 break; 343 break;
342 case PageType::RasterizerCachedSpecial: 344 case PageType::RasterizerCachedSpecial:
343 page_type = PageType::Special; 345 page_type = PageType::Special;
@@ -389,7 +391,8 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) {
389 391
390 switch (current_page_table->attributes[page_index]) { 392 switch (current_page_table->attributes[page_index]) {
391 case PageType::Unmapped: { 393 case PageType::Unmapped: {
392 LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); 394 LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
395 current_vaddr, src_addr, size);
393 std::memset(dest_buffer, 0, copy_amount); 396 std::memset(dest_buffer, 0, copy_amount);
394 break; 397 break;
395 } 398 }
@@ -458,7 +461,9 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
458 461
459 switch (current_page_table->attributes[page_index]) { 462 switch (current_page_table->attributes[page_index]) {
460 case PageType::Unmapped: { 463 case PageType::Unmapped: {
461 LOG_ERROR(HW_Memory, "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); 464 LOG_ERROR(HW_Memory,
465 "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
466 current_vaddr, dest_addr, size);
462 break; 467 break;
463 } 468 }
464 case PageType::Memory: { 469 case PageType::Memory: {
@@ -475,7 +480,8 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
475 break; 480 break;
476 } 481 }
477 case PageType::RasterizerCachedMemory: { 482 case PageType::RasterizerCachedMemory: {
478 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 483 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
484 copy_amount);
479 485
480 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); 486 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount);
481 break; 487 break;
@@ -483,7 +489,8 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size
483 case PageType::RasterizerCachedSpecial: { 489 case PageType::RasterizerCachedSpecial: {
484 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 490 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
485 491
486 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 492 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
493 copy_amount);
487 494
488 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); 495 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount);
489 break; 496 break;
@@ -512,7 +519,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
512 519
513 switch (current_page_table->attributes[page_index]) { 520 switch (current_page_table->attributes[page_index]) {
514 case PageType::Unmapped: { 521 case PageType::Unmapped: {
515 LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); 522 LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
523 current_vaddr, dest_addr, size);
516 break; 524 break;
517 } 525 }
518 case PageType::Memory: { 526 case PageType::Memory: {
@@ -529,7 +537,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
529 break; 537 break;
530 } 538 }
531 case PageType::RasterizerCachedMemory: { 539 case PageType::RasterizerCachedMemory: {
532 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 540 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
541 copy_amount);
533 542
534 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); 543 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount);
535 break; 544 break;
@@ -537,7 +546,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) {
537 case PageType::RasterizerCachedSpecial: { 546 case PageType::RasterizerCachedSpecial: {
538 DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); 547 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
539 548
540 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); 549 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr),
550 copy_amount);
541 551
542 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); 552 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount);
543 break; 553 break;
@@ -563,7 +573,8 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
563 573
564 switch (current_page_table->attributes[page_index]) { 574 switch (current_page_table->attributes[page_index]) {
565 case PageType::Unmapped: { 575 case PageType::Unmapped: {
566 LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); 576 LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)",
577 current_vaddr, src_addr, size);
567 ZeroBlock(dest_addr, copy_amount); 578 ZeroBlock(dest_addr, copy_amount);
568 break; 579 break;
569 } 580 }
@@ -609,42 +620,42 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
609 } 620 }
610} 621}
611 622
612template<> 623template <>
613u8 ReadMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr) { 624u8 ReadMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr) {
614 return mmio_handler->Read8(addr); 625 return mmio_handler->Read8(addr);
615} 626}
616 627
617template<> 628template <>
618u16 ReadMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr) { 629u16 ReadMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr) {
619 return mmio_handler->Read16(addr); 630 return mmio_handler->Read16(addr);
620} 631}
621 632
622template<> 633template <>
623u32 ReadMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr) { 634u32 ReadMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr) {
624 return mmio_handler->Read32(addr); 635 return mmio_handler->Read32(addr);
625} 636}
626 637
627template<> 638template <>
628u64 ReadMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr) { 639u64 ReadMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr) {
629 return mmio_handler->Read64(addr); 640 return mmio_handler->Read64(addr);
630} 641}
631 642
632template<> 643template <>
633void WriteMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr, const u8 data) { 644void WriteMMIO<u8>(MMIORegionPointer mmio_handler, VAddr addr, const u8 data) {
634 mmio_handler->Write8(addr, data); 645 mmio_handler->Write8(addr, data);
635} 646}
636 647
637template<> 648template <>
638void WriteMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr, const u16 data) { 649void WriteMMIO<u16>(MMIORegionPointer mmio_handler, VAddr addr, const u16 data) {
639 mmio_handler->Write16(addr, data); 650 mmio_handler->Write16(addr, data);
640} 651}
641 652
642template<> 653template <>
643void WriteMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr, const u32 data) { 654void WriteMMIO<u32>(MMIORegionPointer mmio_handler, VAddr addr, const u32 data) {
644 mmio_handler->Write32(addr, data); 655 mmio_handler->Write32(addr, data);
645} 656}
646 657
647template<> 658template <>
648void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) { 659void WriteMMIO<u64>(MMIORegionPointer mmio_handler, VAddr addr, const u64 data) {
649 mmio_handler->Write64(addr, data); 660 mmio_handler->Write64(addr, data);
650} 661}
diff --git a/src/core/memory.h b/src/core/memory.h
index cad845385..8fd3080ff 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -6,7 +6,6 @@
6 6
7#include <cstddef> 7#include <cstddef>
8#include <string> 8#include <string>
9
10#include "common/common_types.h" 9#include "common/common_types.h"
11 10
12namespace Memory { 11namespace Memory {
@@ -22,92 +21,93 @@ const int PAGE_BITS = 12;
22/// Physical memory regions as seen from the ARM11 21/// Physical memory regions as seen from the ARM11
23enum : PAddr { 22enum : PAddr {
24 /// IO register area 23 /// IO register area
25 IO_AREA_PADDR = 0x10100000, 24 IO_AREA_PADDR = 0x10100000,
26 IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB) 25 IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB)
27 IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE, 26 IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE,
28 27
29 /// MPCore internal memory region 28 /// MPCore internal memory region
30 MPCORE_RAM_PADDR = 0x17E00000, 29 MPCORE_RAM_PADDR = 0x17E00000,
31 MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB) 30 MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB)
32 MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE, 31 MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE,
33 32
34 /// Video memory 33 /// Video memory
35 VRAM_PADDR = 0x18000000, 34 VRAM_PADDR = 0x18000000,
36 VRAM_SIZE = 0x00600000, ///< VRAM size (6MB) 35 VRAM_SIZE = 0x00600000, ///< VRAM size (6MB)
37 VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, 36 VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE,
38 37
39 /// DSP memory 38 /// DSP memory
40 DSP_RAM_PADDR = 0x1FF00000, 39 DSP_RAM_PADDR = 0x1FF00000,
41 DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB) 40 DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB)
42 DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE, 41 DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE,
43 42
44 /// AXI WRAM 43 /// AXI WRAM
45 AXI_WRAM_PADDR = 0x1FF80000, 44 AXI_WRAM_PADDR = 0x1FF80000,
46 AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB) 45 AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB)
47 AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE, 46 AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE,
48 47
49 /// Main FCRAM 48 /// Main FCRAM
50 FCRAM_PADDR = 0x20000000, 49 FCRAM_PADDR = 0x20000000,
51 FCRAM_SIZE = 0x08000000, ///< FCRAM size (128MB) 50 FCRAM_SIZE = 0x08000000, ///< FCRAM size (128MB)
52 FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE, 51 FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE,
53}; 52};
54 53
55/// Virtual user-space memory regions 54/// Virtual user-space memory regions
56enum : VAddr { 55enum : VAddr {
57 /// Where the application text, data and bss reside. 56 /// Where the application text, data and bss reside.
58 PROCESS_IMAGE_VADDR = 0x00100000, 57 PROCESS_IMAGE_VADDR = 0x00100000,
59 PROCESS_IMAGE_MAX_SIZE = 0x03F00000, 58 PROCESS_IMAGE_MAX_SIZE = 0x03F00000,
60 PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE, 59 PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE,
61 60
62 /// Area where IPC buffers are mapped onto. 61 /// Area where IPC buffers are mapped onto.
63 IPC_MAPPING_VADDR = 0x04000000, 62 IPC_MAPPING_VADDR = 0x04000000,
64 IPC_MAPPING_SIZE = 0x04000000, 63 IPC_MAPPING_SIZE = 0x04000000,
65 IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE, 64 IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE,
66 65
67 /// Application heap (includes stack). 66 /// Application heap (includes stack).
68 HEAP_VADDR = 0x08000000, 67 HEAP_VADDR = 0x08000000,
69 HEAP_SIZE = 0x08000000, 68 HEAP_SIZE = 0x08000000,
70 HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE, 69 HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE,
71 70
72 /// Area where shared memory buffers are mapped onto. 71 /// Area where shared memory buffers are mapped onto.
73 SHARED_MEMORY_VADDR = 0x10000000, 72 SHARED_MEMORY_VADDR = 0x10000000,
74 SHARED_MEMORY_SIZE = 0x04000000, 73 SHARED_MEMORY_SIZE = 0x04000000,
75 SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE, 74 SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE,
76 75
77 /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical memory. 76 /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical
78 LINEAR_HEAP_VADDR = 0x14000000, 77 /// memory.
79 LINEAR_HEAP_SIZE = 0x08000000, 78 LINEAR_HEAP_VADDR = 0x14000000,
79 LINEAR_HEAP_SIZE = 0x08000000,
80 LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, 80 LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE,
81 81
82 /// Maps 1:1 to the IO register area. 82 /// Maps 1:1 to the IO register area.
83 IO_AREA_VADDR = 0x1EC00000, 83 IO_AREA_VADDR = 0x1EC00000,
84 IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, 84 IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE,
85 85
86 /// Maps 1:1 to VRAM. 86 /// Maps 1:1 to VRAM.
87 VRAM_VADDR = 0x1F000000, 87 VRAM_VADDR = 0x1F000000,
88 VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE, 88 VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE,
89 89
90 /// Maps 1:1 to DSP memory. 90 /// Maps 1:1 to DSP memory.
91 DSP_RAM_VADDR = 0x1FF00000, 91 DSP_RAM_VADDR = 0x1FF00000,
92 DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE, 92 DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE,
93 93
94 /// Read-only page containing kernel and system configuration values. 94 /// Read-only page containing kernel and system configuration values.
95 CONFIG_MEMORY_VADDR = 0x1FF80000, 95 CONFIG_MEMORY_VADDR = 0x1FF80000,
96 CONFIG_MEMORY_SIZE = 0x00001000, 96 CONFIG_MEMORY_SIZE = 0x00001000,
97 CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE, 97 CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE,
98 98
99 /// Usually read-only page containing mostly values read from hardware. 99 /// Usually read-only page containing mostly values read from hardware.
100 SHARED_PAGE_VADDR = 0x1FF81000, 100 SHARED_PAGE_VADDR = 0x1FF81000,
101 SHARED_PAGE_SIZE = 0x00001000, 101 SHARED_PAGE_SIZE = 0x00001000,
102 SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, 102 SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE,
103 103
104 /// Area where TLS (Thread-Local Storage) buffers are allocated. 104 /// Area where TLS (Thread-Local Storage) buffers are allocated.
105 TLS_AREA_VADDR = 0x1FF82000, 105 TLS_AREA_VADDR = 0x1FF82000,
106 TLS_ENTRY_SIZE = 0x200, 106 TLS_ENTRY_SIZE = 0x200,
107 107
108 /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. 108 /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS.
109 NEW_LINEAR_HEAP_VADDR = 0x30000000, 109 NEW_LINEAR_HEAP_VADDR = 0x30000000,
110 NEW_LINEAR_HEAP_SIZE = 0x10000000, 110 NEW_LINEAR_HEAP_SIZE = 0x10000000,
111 NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, 111 NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE,
112}; 112};
113 113
@@ -166,5 +166,4 @@ void RasterizerFlushRegion(PAddr start, u32 size);
166 * Flushes and invalidates any externally cached rasterizer resources touching the given region. 166 * Flushes and invalidates any externally cached rasterizer resources touching the given region.
167 */ 167 */
168void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size); 168void RasterizerFlushAndInvalidateRegion(PAddr start, u32 size);
169
170} 169}
diff --git a/src/core/memory_setup.h b/src/core/memory_setup.h
index ee8ea7857..3fdf3a87d 100644
--- a/src/core/memory_setup.h
+++ b/src/core/memory_setup.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8
9#include "core/mmio.h" 8#include "core/mmio.h"
10 9
11namespace Memory { 10namespace Memory {
@@ -30,5 +29,4 @@ void MapMemoryRegion(VAddr base, u32 size, u8* target);
30void MapIoRegion(VAddr base, u32 size, MMIORegionPointer mmio_handler); 29void MapIoRegion(VAddr base, u32 size, MMIORegionPointer mmio_handler);
31 30
32void UnmapRegion(VAddr base, u32 size); 31void UnmapRegion(VAddr base, u32 size);
33
34} 32}
diff --git a/src/core/mmio.h b/src/core/mmio.h
index d76f005d8..f45126da8 100644
--- a/src/core/mmio.h
+++ b/src/core/mmio.h
@@ -5,7 +5,6 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8
9#include "common/common_types.h" 8#include "common/common_types.h"
10 9
11namespace Memory { 10namespace Memory {
@@ -36,5 +35,4 @@ public:
36}; 35};
37 36
38using MMIORegionPointer = std::shared_ptr<MMIORegion>; 37using MMIORegionPointer = std::shared_ptr<MMIORegion>;
39
40}; 38};
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 1b6733a79..4a0969b00 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -2,12 +2,9 @@
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 "settings.h"
6
7#include "audio_core/audio_core.h" 5#include "audio_core/audio_core.h"
8
9#include "core/gdbstub/gdbstub.h" 6#include "core/gdbstub/gdbstub.h"
10 7#include "settings.h"
11#include "video_core/video_core.h" 8#include "video_core/video_core.h"
12 9
13namespace Settings { 10namespace Settings {
@@ -25,7 +22,6 @@ void Apply() {
25 22
26 AudioCore::SelectSink(values.sink_id); 23 AudioCore::SelectSink(values.sink_id);
27 AudioCore::EnableStretching(values.enable_audio_stretching); 24 AudioCore::EnableStretching(values.enable_audio_stretching);
28
29} 25}
30 26
31} // namespace 27} // namespace
diff --git a/src/core/settings.h b/src/core/settings.h
index fcd14c6f3..5a64f8018 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -4,9 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <string>
8#include <array> 7#include <array>
9 8#include <string>
10#include "common/common_types.h" 9#include "common/common_types.h"
11 10
12namespace Settings { 11namespace Settings {
@@ -14,14 +13,31 @@ namespace Settings {
14namespace NativeInput { 13namespace NativeInput {
15enum Values { 14enum Values {
16 // directly mapped keys 15 // directly mapped keys
17 A, B, X, Y, 16 A,
18 L, R, ZL, ZR, 17 B,
19 START, SELECT, HOME, 18 X,
20 DUP, DDOWN, DLEFT, DRIGHT, 19 Y,
21 CUP, CDOWN, CLEFT, CRIGHT, 20 L,
21 R,
22 ZL,
23 ZR,
24 START,
25 SELECT,
26 HOME,
27 DUP,
28 DDOWN,
29 DLEFT,
30 DRIGHT,
31 CUP,
32 CDOWN,
33 CLEFT,
34 CRIGHT,
22 35
23 // indirectly mapped keys 36 // indirectly mapped keys
24 CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, 37 CIRCLE_UP,
38 CIRCLE_DOWN,
39 CIRCLE_LEFT,
40 CIRCLE_RIGHT,
25 CIRCLE_MODIFIER, 41 CIRCLE_MODIFIER,
26 42
27 NUM_INPUTS 43 NUM_INPUTS
@@ -29,28 +45,21 @@ enum Values {
29 45
30static const std::array<const char*, NUM_INPUTS> Mapping = {{ 46static const std::array<const char*, NUM_INPUTS> Mapping = {{
31 // directly mapped keys 47 // directly mapped keys
32 "pad_a", "pad_b", "pad_x", "pad_y", 48 "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", 49 "pad_select", "pad_home", "pad_dup", "pad_ddown", "pad_dleft", "pad_dright", "pad_cup",
34 "pad_start", "pad_select", "pad_home", 50 "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 51
38 // indirectly mapped keys 52 // indirectly mapped keys
39 "pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right", 53 "pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right",
40 "pad_circle_modifier", 54 "pad_circle_modifier",
41}}; 55}};
42static const std::array<Values, NUM_INPUTS> All = {{ 56static const std::array<Values, NUM_INPUTS> All = {{
43 A, B, X, Y, 57 A, B, X, Y, L, R, ZL, ZR,
44 L, R, ZL, ZR, 58 START, SELECT, HOME, DUP, DDOWN, DLEFT, DRIGHT, CUP,
45 START, SELECT, HOME, 59 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}}; 60}};
51} 61}
52 62
53
54struct Values { 63struct Values {
55 // CheckNew3DS 64 // CheckNew3DS
56 bool is_new_3ds; 65 bool is_new_3ds;
@@ -91,5 +100,4 @@ struct Values {
91} extern values; 100} extern values;
92 101
93void Apply(); 102void Apply();
94
95} 103}
diff --git a/src/core/system.cpp b/src/core/system.cpp
index 4fc266cb0..7d54811a0 100644
--- a/src/core/system.cpp
+++ b/src/core/system.cpp
@@ -3,21 +3,19 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "audio_core/audio_core.h" 5#include "audio_core/audio_core.h"
6
7#include "core/core.h" 6#include "core/core.h"
8#include "core/core_timing.h" 7#include "core/core_timing.h"
9#include "core/system.h"
10#include "core/gdbstub/gdbstub.h" 8#include "core/gdbstub/gdbstub.h"
11#include "core/hw/hw.h"
12#include "core/hle/hle.h" 9#include "core/hle/hle.h"
13#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/memory.h" 11#include "core/hle/kernel/memory.h"
15 12#include "core/hw/hw.h"
13#include "core/system.h"
16#include "video_core/video_core.h" 14#include "video_core/video_core.h"
17 15
18namespace System { 16namespace System {
19 17
20static bool is_powered_on{ false }; 18static bool is_powered_on{false};
21 19
22Result Init(EmuWindow* emu_window) { 20Result Init(EmuWindow* emu_window) {
23 Core::Init(); 21 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..215f86359 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
@@ -77,10 +77,10 @@ struct CTRegisterWrite {
77 u32 physical_address; 77 u32 physical_address;
78 78
79 enum : u32 { 79 enum : u32 {
80 SIZE_8 = 0xD1, 80 SIZE_8 = 0xD1,
81 SIZE_16 = 0xD2, 81 SIZE_16 = 0xD2,
82 SIZE_32 = 0xD3, 82 SIZE_32 = 0xD3,
83 SIZE_64 = 0xD4 83 SIZE_64 = 0xD4,
84 } size; 84 } size;
85 85
86 // TODO: Make it clearer which bits of this member are used for sizes other than 32 bits 86 // TODO: Make it clearer which bits of this member are used for sizes other than 32 bits
@@ -97,5 +97,4 @@ struct CTStreamElement {
97}; 97};
98 98
99#pragma pack() 99#pragma pack()
100
101} 100}
diff --git a/src/core/tracer/recorder.cpp b/src/core/tracer/recorder.cpp
index 7abaacf70..276a5b288 100644
--- a/src/core/tracer/recorder.cpp
+++ b/src/core/tracer/recorder.cpp
@@ -3,18 +3,14 @@
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
7#include "common/assert.h" 6#include "common/assert.h"
8#include "common/file_util.h" 7#include "common/file_util.h"
9#include "common/logging/log.h" 8#include "common/logging/log.h"
10
11#include "recorder.h" 9#include "recorder.h"
12 10
13namespace CiTrace { 11namespace CiTrace {
14 12
15Recorder::Recorder(const InitialState& initial_state) : initial_state(initial_state) { 13Recorder::Recorder(const InitialState& initial_state) : initial_state(initial_state) {}
16
17}
18 14
19void Recorder::Finish(const std::string& filename) { 15void Recorder::Finish(const std::string& filename) {
20 // Setup CiTrace header 16 // Setup CiTrace header
@@ -26,35 +22,41 @@ void Recorder::Finish(const std::string& filename) {
26 // Calculate file offsets 22 // Calculate file offsets
27 auto& initial = header.initial_state_offsets; 23 auto& initial = header.initial_state_offsets;
28 24
29 initial.gpu_registers_size = static_cast<u32>(initial_state.gpu_registers.size()); 25 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()); 26 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()); 27 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()); 28 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()); 29 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()); 30 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()); 31 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()); 32 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()); 33 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()); 34 initial.gs_float_uniforms_size = static_cast<u32>(initial_state.gs_float_uniforms.size());
39 header.stream_size = static_cast<u32>(stream.size()); 35 header.stream_size = static_cast<u32>(stream.size());
40 36
41 initial.gpu_registers = sizeof(header); 37 initial.gpu_registers = sizeof(header);
42 initial.lcd_registers = initial.gpu_registers + initial.gpu_registers_size * sizeof(u32); 38 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);; 39 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); 40 ;
45 initial.vs_program_binary = initial.default_attributes + initial.default_attributes_size * sizeof(u32); 41 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); 42 initial.vs_program_binary =
47 initial.vs_float_uniforms = initial.vs_swizzle_data + initial.vs_swizzle_data_size * sizeof(u32); 43 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); 44 initial.vs_swizzle_data =
49 initial.gs_swizzle_data = initial.gs_program_binary + initial.gs_program_binary_size * sizeof(u32); 45 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); 46 initial.vs_float_uniforms =
51 header.stream_offset = initial.gs_float_uniforms + initial.gs_float_uniforms_size * sizeof(u32); 47 initial.vs_swizzle_data + initial.vs_swizzle_data_size * sizeof(u32);
48 initial.gs_program_binary =
49 initial.vs_float_uniforms + initial.vs_float_uniforms_size * sizeof(u32);
50 initial.gs_swizzle_data =
51 initial.gs_program_binary + initial.gs_program_binary_size * sizeof(u32);
52 initial.gs_float_uniforms =
53 initial.gs_swizzle_data + initial.gs_swizzle_data_size * sizeof(u32);
54 header.stream_offset = initial.gs_float_uniforms + initial.gs_float_uniforms_size * sizeof(u32);
52 55
53 // Iterate through stream elements, update relevant stream element data 56 // Iterate through stream elements, update relevant stream element data
54 for (auto& stream_element : stream) { 57 for (auto& stream_element : stream) {
55 switch (stream_element.data.type) { 58 switch (stream_element.data.type) {
56 case MemoryLoad: 59 case MemoryLoad: {
57 {
58 auto& file_offset = memory_regions[stream_element.hash]; 60 auto& file_offset = memory_regions[stream_element.hash];
59 if (!stream_element.uses_existing_data) { 61 if (!stream_element.uses_existing_data) {
60 file_offset = header.stream_offset; 62 file_offset = header.stream_offset;
@@ -79,44 +81,62 @@ void Recorder::Finish(const std::string& filename) {
79 throw "Failed to write header"; 81 throw "Failed to write header";
80 82
81 // Write initial state 83 // Write initial state
82 written = file.WriteArray(initial_state.gpu_registers.data(), initial_state.gpu_registers.size()); 84 written =
85 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) 86 if (written != initial_state.gpu_registers.size() || file.Tell() != initial.lcd_registers)
84 throw "Failed to write GPU registers"; 87 throw "Failed to write GPU registers";
85 88
86 written = file.WriteArray(initial_state.lcd_registers.data(), initial_state.lcd_registers.size()); 89 written =
90 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) 91 if (written != initial_state.lcd_registers.size() || file.Tell() != initial.pica_registers)
88 throw "Failed to write LCD registers"; 92 throw "Failed to write LCD registers";
89 93
90 written = file.WriteArray(initial_state.pica_registers.data(), initial_state.pica_registers.size()); 94 written = file.WriteArray(initial_state.pica_registers.data(),
91 if (written != initial_state.pica_registers.size() || file.Tell() != initial.default_attributes) 95 initial_state.pica_registers.size());
96 if (written != initial_state.pica_registers.size() ||
97 file.Tell() != initial.default_attributes)
92 throw "Failed to write Pica registers"; 98 throw "Failed to write Pica registers";
93 99
94 written = file.WriteArray(initial_state.default_attributes.data(), initial_state.default_attributes.size()); 100 written = file.WriteArray(initial_state.default_attributes.data(),
95 if (written != initial_state.default_attributes.size() || file.Tell() != initial.vs_program_binary) 101 initial_state.default_attributes.size());
102 if (written != initial_state.default_attributes.size() ||
103 file.Tell() != initial.vs_program_binary)
96 throw "Failed to write default vertex attributes"; 104 throw "Failed to write default vertex attributes";
97 105
98 written = file.WriteArray(initial_state.vs_program_binary.data(), initial_state.vs_program_binary.size()); 106 written = file.WriteArray(initial_state.vs_program_binary.data(),
99 if (written != initial_state.vs_program_binary.size() || file.Tell() != initial.vs_swizzle_data) 107 initial_state.vs_program_binary.size());
108 if (written != initial_state.vs_program_binary.size() ||
109 file.Tell() != initial.vs_swizzle_data)
100 throw "Failed to write vertex shader program binary"; 110 throw "Failed to write vertex shader program binary";
101 111
102 written = file.WriteArray(initial_state.vs_swizzle_data.data(), initial_state.vs_swizzle_data.size()); 112 written = file.WriteArray(initial_state.vs_swizzle_data.data(),
103 if (written != initial_state.vs_swizzle_data.size() || file.Tell() != initial.vs_float_uniforms) 113 initial_state.vs_swizzle_data.size());
114 if (written != initial_state.vs_swizzle_data.size() ||
115 file.Tell() != initial.vs_float_uniforms)
104 throw "Failed to write vertex shader swizzle data"; 116 throw "Failed to write vertex shader swizzle data";
105 117
106 written = file.WriteArray(initial_state.vs_float_uniforms.data(), initial_state.vs_float_uniforms.size()); 118 written = file.WriteArray(initial_state.vs_float_uniforms.data(),
107 if (written != initial_state.vs_float_uniforms.size() || file.Tell() != initial.gs_program_binary) 119 initial_state.vs_float_uniforms.size());
120 if (written != initial_state.vs_float_uniforms.size() ||
121 file.Tell() != initial.gs_program_binary)
108 throw "Failed to write vertex shader float uniforms"; 122 throw "Failed to write vertex shader float uniforms";
109 123
110 written = file.WriteArray(initial_state.gs_program_binary.data(), initial_state.gs_program_binary.size()); 124 written = file.WriteArray(initial_state.gs_program_binary.data(),
111 if (written != initial_state.gs_program_binary.size() || file.Tell() != initial.gs_swizzle_data) 125 initial_state.gs_program_binary.size());
126 if (written != initial_state.gs_program_binary.size() ||
127 file.Tell() != initial.gs_swizzle_data)
112 throw "Failed to write geomtry shader program binary"; 128 throw "Failed to write geomtry shader program binary";
113 129
114 written = file.WriteArray(initial_state.gs_swizzle_data.data(), initial_state.gs_swizzle_data.size()); 130 written = file.WriteArray(initial_state.gs_swizzle_data.data(),
115 if (written != initial_state.gs_swizzle_data.size() || file.Tell() != initial.gs_float_uniforms) 131 initial_state.gs_swizzle_data.size());
132 if (written != initial_state.gs_swizzle_data.size() ||
133 file.Tell() != initial.gs_float_uniforms)
116 throw "Failed to write geometry shader swizzle data"; 134 throw "Failed to write geometry shader swizzle data";
117 135
118 written = file.WriteArray(initial_state.gs_float_uniforms.data(), initial_state.gs_float_uniforms.size()); 136 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) 137 initial_state.gs_float_uniforms.size());
138 if (written != initial_state.gs_float_uniforms.size() ||
139 file.Tell() != initial.gs_float_uniforms + sizeof(u32) * initial.gs_float_uniforms_size)
120 throw "Failed to write geometry shader float uniforms"; 140 throw "Failed to write geometry shader float uniforms";
121 141
122 // Iterate through stream elements, write "extra data" 142 // Iterate through stream elements, write "extra data"
@@ -124,7 +144,8 @@ void Recorder::Finish(const std::string& filename) {
124 if (stream_element.extra_data.size() == 0) 144 if (stream_element.extra_data.size() == 0)
125 continue; 145 continue;
126 146
127 written = file.WriteBytes(stream_element.extra_data.data(), stream_element.extra_data.size()); 147 written =
148 file.WriteBytes(stream_element.extra_data.data(), stream_element.extra_data.size());
128 if (written != stream_element.extra_data.size()) 149 if (written != stream_element.extra_data.size())
129 throw "Failed to write extra data"; 150 throw "Failed to write extra data";
130 } 151 }
@@ -137,17 +158,17 @@ void Recorder::Finish(const std::string& filename) {
137 if (1 != file.WriteObject(stream_element.data)) 158 if (1 != file.WriteObject(stream_element.data))
138 throw "Failed to write stream element"; 159 throw "Failed to write stream element";
139 } 160 }
140 } catch(const char* str) { 161 } catch (const char* str) {
141 LOG_ERROR(HW_GPU, "Writing CiTrace file failed: %s", str); 162 LOG_ERROR(HW_GPU, "Writing CiTrace file failed: %s", str);
142 } 163 }
143} 164}
144 165
145void Recorder::FrameFinished() { 166void Recorder::FrameFinished() {
146 stream.push_back( { { FrameMarker } } ); 167 stream.push_back({{FrameMarker}});
147} 168}
148 169
149void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) { 170void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) {
150 StreamElement element = { { MemoryLoad } }; 171 StreamElement element = {{MemoryLoad}};
151 element.data.memory_load.size = size; 172 element.data.memory_load.size = size;
152 element.data.memory_load.physical_address = physical_address; 173 element.data.memory_load.physical_address = physical_address;
153 174
@@ -166,22 +187,22 @@ void Recorder::MemoryAccessed(const u8* data, u32 size, u32 physical_address) {
166 stream.push_back(element); 187 stream.push_back(element);
167} 188}
168 189
169template<typename T> 190template <typename T>
170void Recorder::RegisterWritten(u32 physical_address, T value) { 191void Recorder::RegisterWritten(u32 physical_address, T value) {
171 StreamElement element = { { RegisterWrite } }; 192 StreamElement element = {{RegisterWrite}};
172 element.data.register_write.size = (sizeof(T) == 1) ? CTRegisterWrite::SIZE_8 193 element.data.register_write.size =
173 : (sizeof(T) == 2) ? CTRegisterWrite::SIZE_16 194 (sizeof(T) == 1) ? CTRegisterWrite::SIZE_8
174 : (sizeof(T) == 4) ? CTRegisterWrite::SIZE_32 195 : (sizeof(T) == 2) ? CTRegisterWrite::SIZE_16
175 : CTRegisterWrite::SIZE_64; 196 : (sizeof(T) == 4) ? CTRegisterWrite::SIZE_32
197 : CTRegisterWrite::SIZE_64;
176 element.data.register_write.physical_address = physical_address; 198 element.data.register_write.physical_address = physical_address;
177 element.data.register_write.value = value; 199 element.data.register_write.value = value;
178 200
179 stream.push_back(element); 201 stream.push_back(element);
180} 202}
181 203
182template void Recorder::RegisterWritten(u32,u8); 204template void Recorder::RegisterWritten(u32, u8);
183template void Recorder::RegisterWritten(u32,u16); 205template void Recorder::RegisterWritten(u32, u16);
184template void Recorder::RegisterWritten(u32,u32); 206template void Recorder::RegisterWritten(u32, u32);
185template void Recorder::RegisterWritten(u32,u64); 207template void Recorder::RegisterWritten(u32, u64);
186
187} 208}
diff --git a/src/core/tracer/recorder.h b/src/core/tracer/recorder.h
index febf883c8..aea363b95 100644
--- a/src/core/tracer/recorder.h
+++ b/src/core/tracer/recorder.h
@@ -7,12 +7,9 @@
7#include <string> 7#include <string>
8#include <unordered_map> 8#include <unordered_map>
9#include <vector> 9#include <vector>
10
11#include <boost/crc.hpp> 10#include <boost/crc.hpp>
12
13#include "common/common_types.h"
14
15#include "citrace.h" 11#include "citrace.h"
12#include "common/common_types.h"
16 13
17namespace CiTrace { 14namespace CiTrace {
18 15
@@ -54,7 +51,7 @@ public:
54 * Record a register write. 51 * Record a register write.
55 * @note Use this whenever a GPU-related MMIO register has been written to. 52 * @note Use this whenever a GPU-related MMIO register has been written to.
56 */ 53 */
57 template<typename T> 54 template <typename T>
58 void RegisterWritten(u32 physical_address, T value); 55 void RegisterWritten(u32 physical_address, T value);
59 56
60private: 57private: