summaryrefslogtreecommitdiff
path: root/src/core/arm/skyeye_common
diff options
context:
space:
mode:
authorGravatar bunnei2015-07-25 23:12:34 -0400
committerGravatar bunnei2015-07-25 23:12:34 -0400
commit392c7feba0cd152e46ffbe6089def35082fa2692 (patch)
treed959d1751d99a6f5307b45d04e46c19c53d5efc2 /src/core/arm/skyeye_common
parentMerge pull request #989 from lioncash/extern (diff)
parentdyncom: Remove unnecessary initialization code. (diff)
downloadyuzu-392c7feba0cd152e46ffbe6089def35082fa2692.tar.gz
yuzu-392c7feba0cd152e46ffbe6089def35082fa2692.tar.xz
yuzu-392c7feba0cd152e46ffbe6089def35082fa2692.zip
Merge pull request #990 from lioncash/arm
dyncom: General cleanup
Diffstat (limited to 'src/core/arm/skyeye_common')
-rw-r--r--src/core/arm/skyeye_common/armdefs.h318
-rw-r--r--src/core/arm/skyeye_common/arminit.cpp100
-rw-r--r--src/core/arm/skyeye_common/armmmu.h3
-rw-r--r--src/core/arm/skyeye_common/armstate.h215
-rw-r--r--src/core/arm/skyeye_common/armsupp.cpp638
-rw-r--r--src/core/arm/skyeye_common/armsupp.h40
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp12
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h10
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp_helper.h4
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp12
10 files changed, 1014 insertions, 338 deletions
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
deleted file mode 100644
index a0ec108c7..000000000
--- a/src/core/arm/skyeye_common/armdefs.h
+++ /dev/null
@@ -1,318 +0,0 @@
1/* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18#pragma once
19
20#include <unordered_map>
21
22#include "common/common_types.h"
23#include "core/arm/skyeye_common/arm_regformat.h"
24
25#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
26#define BIT(s, n) ((s >> (n)) & 1)
27
28// Signal levels
29enum {
30 LOW = 0,
31 HIGH = 1,
32 LOWHIGH = 1,
33 HIGHLOW = 2
34};
35
36// Cache types
37enum {
38 NONCACHE = 0,
39 DATACACHE = 1,
40 INSTCACHE = 2,
41};
42
43// Abort models
44enum {
45 ABORT_BASE_RESTORED = 0,
46 ABORT_EARLY = 1,
47 ABORT_BASE_UPDATED = 2
48};
49
50#define POS(i) ( (~(i)) >> 31 )
51#define NEG(i) ( (i) >> 31 )
52
53typedef u64 ARMdword; // must be 64 bits wide
54typedef u32 ARMword; // must be 32 bits wide
55typedef u16 ARMhword; // must be 16 bits wide
56typedef u8 ARMbyte; // must be 8 bits wide
57
58#define VFP_REG_NUM 64
59struct ARMul_State
60{
61 ARMword Emulate; // To start and stop emulation
62
63 // Order of the following register should not be modified
64 ARMword Reg[16]; // The current register file
65 ARMword Cpsr; // The current PSR
66 ARMword Spsr_copy;
67 ARMword phys_pc;
68 ARMword Reg_usr[2];
69 ARMword Reg_svc[2]; // R13_SVC R14_SVC
70 ARMword Reg_abort[2]; // R13_ABORT R14_ABORT
71 ARMword Reg_undef[2]; // R13 UNDEF R14 UNDEF
72 ARMword Reg_irq[2]; // R13_IRQ R14_IRQ
73 ARMword Reg_firq[7]; // R8---R14 FIRQ
74 ARMword Spsr[7]; // The exception psr's
75 ARMword Mode; // The current mode
76 ARMword Bank; // The current register bank
77 ARMword exclusive_tag; // The address for which the local monitor is in exclusive access mode
78 ARMword exclusive_state;
79 ARMword exclusive_result;
80 ARMword CP15[CP15_REGISTER_COUNT];
81
82 // FPSID, FPSCR, and FPEXC
83 ARMword VFP[VFP_SYSTEM_REGISTER_COUNT];
84 // VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31).
85 // VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31),
86 // and only 32 singleword registers are accessible (S0-S31).
87 ARMword ExtReg[VFP_REG_NUM];
88 /* ---- End of the ordered registers ---- */
89
90 ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
91 unsigned int shifter_carry_out;
92
93 // Add armv6 flags dyf:2010-08-09
94 ARMword GEFlag, EFlag, AFlag, QFlag;
95
96 ARMword TFlag; // Thumb state
97
98 unsigned long long NumInstrs; // The number of instructions executed
99 unsigned NumInstrsToExecute;
100
101 unsigned NresetSig; // Reset the processor
102 unsigned NfiqSig;
103 unsigned NirqSig;
104
105 unsigned abortSig;
106 unsigned NtransSig;
107 unsigned bigendSig;
108 unsigned syscallSig;
109
110/* 2004-05-09 chy
111----------------------------------------------------------
112read ARM Architecture Reference Manual
1132.6.5 Data Abort
114There are three Abort Model in ARM arch.
115
116Early Abort Model: used in some ARMv3 and earlier implementations. In this
117model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and
118the base register was unchanged for all other instructions. (oldest)
119
120Base Restored Abort Model: If a Data Abort occurs in an instruction which
121specifies base register writeback, the value in the base register is
122unchanged. (strongarm, xscale)
123
124Base Updated Abort Model: If a Data Abort occurs in an instruction which
125specifies base register writeback, the base register writeback still occurs.
126(arm720T)
127
128read PART B
129chap2 The System Control Coprocessor CP15
1302.4 Register1:control register
131L(bit 6): in some ARMv3 and earlier implementations, the abort model of the
132processor could be configured:
1330=early Abort Model Selected(now obsolete)
1341=Late Abort Model selceted(same as Base Updated Abort Model)
135
136on later processors, this bit reads as 1 and ignores writes.
137-------------------------------------------------------------
138So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
139 if lateabtSig=0, then it means Base Restored Abort Model
140*/
141 unsigned lateabtSig;
142
143 // For differentiating ARM core emulaiton.
144 bool is_v4; // Are we emulating a v4 architecture (or higher)?
145 bool is_v5; // Are we emulating a v5 architecture?
146 bool is_v5e; // Are we emulating a v5e architecture?
147 bool is_v6; // Are we emulating a v6 architecture?
148 bool is_v7; // Are we emulating a v7 architecture?
149
150 // ARM_ARM A2-18
151 // 0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model
152 int abort_model;
153
154 // TODO(bunnei): Move this cache to a better place - it should be per codeset (likely per
155 // process for our purposes), not per ARMul_State (which tracks CPU core state).
156 std::unordered_map<u32, int> instruction_cache;
157};
158
159/***************************************************************************\
160* Types of ARM we know about *
161\***************************************************************************/
162
163enum {
164 ARM_v4_Prop = 0x01,
165 ARM_v5_Prop = 0x02,
166 ARM_v5e_Prop = 0x04,
167 ARM_v6_Prop = 0x08,
168 ARM_v7_Prop = 0x10,
169};
170
171/***************************************************************************\
172* The hardware vector addresses *
173\***************************************************************************/
174
175enum {
176 ARMResetV = 0,
177 ARMUndefinedInstrV = 4,
178 ARMSWIV = 8,
179 ARMPrefetchAbortV = 12,
180 ARMDataAbortV = 16,
181 ARMAddrExceptnV = 20,
182 ARMIRQV = 24,
183 ARMFIQV = 28,
184 ARMErrorV = 32, // This is an offset, not an address!
185
186 ARMul_ResetV = ARMResetV,
187 ARMul_UndefinedInstrV = ARMUndefinedInstrV,
188 ARMul_SWIV = ARMSWIV,
189 ARMul_PrefetchAbortV = ARMPrefetchAbortV,
190 ARMul_DataAbortV = ARMDataAbortV,
191 ARMul_AddrExceptnV = ARMAddrExceptnV,
192 ARMul_IRQV = ARMIRQV,
193 ARMul_FIQV = ARMFIQV
194};
195
196/***************************************************************************\
197* Mode and Bank Constants *
198\***************************************************************************/
199
200enum PrivilegeMode {
201 USER32MODE = 16,
202 FIQ32MODE = 17,
203 IRQ32MODE = 18,
204 SVC32MODE = 19,
205 ABORT32MODE = 23,
206 UNDEF32MODE = 27,
207 SYSTEM32MODE = 31
208};
209
210enum {
211 USERBANK = 0,
212 FIQBANK = 1,
213 IRQBANK = 2,
214 SVCBANK = 3,
215 ABORTBANK = 4,
216 UNDEFBANK = 5,
217 DUMMYBANK = 6,
218 SYSTEMBANK = 7
219};
220
221/***************************************************************************\
222* Definitions of things in the emulator *
223\***************************************************************************/
224void ARMul_Reset(ARMul_State* state);
225ARMul_State* ARMul_NewState(ARMul_State* state);
226
227/***************************************************************************\
228* Definitions of things in the co-processor interface *
229\***************************************************************************/
230
231enum {
232 ARMul_FIRST = 0,
233 ARMul_TRANSFER = 1,
234 ARMul_BUSY = 2,
235 ARMul_DATA = 3,
236 ARMul_INTERRUPT = 4,
237 ARMul_DONE = 0,
238 ARMul_CANT = 1,
239 ARMul_INC = 3
240};
241
242/***************************************************************************\
243* Definitions of things in the host environment *
244\***************************************************************************/
245
246enum ConditionCode {
247 EQ = 0,
248 NE = 1,
249 CS = 2,
250 CC = 3,
251 MI = 4,
252 PL = 5,
253 VS = 6,
254 VC = 7,
255 HI = 8,
256 LS = 9,
257 GE = 10,
258 LT = 11,
259 GT = 12,
260 LE = 13,
261 AL = 14,
262 NV = 15,
263};
264
265// Flags for use with the APSR.
266enum : u32 {
267 NBIT = (1U << 31U),
268 ZBIT = (1 << 30),
269 CBIT = (1 << 29),
270 VBIT = (1 << 28),
271 QBIT = (1 << 27),
272 JBIT = (1 << 24),
273 EBIT = (1 << 9),
274 ABIT = (1 << 8),
275 IBIT = (1 << 7),
276 FBIT = (1 << 6),
277 TBIT = (1 << 5),
278
279 // Masks for groups of bits in the APSR.
280 MODEBITS = 0x1F,
281 INTBITS = 0x1C0,
282};
283
284// Values for Emulate.
285enum {
286 STOP = 0, // Stop
287 CHANGEMODE = 1, // Change mode
288 ONCE = 2, // Execute just one iteration
289 RUN = 3 // Continuous execution
290};
291
292
293bool AddOverflow(ARMword, ARMword, ARMword);
294bool SubOverflow(ARMword, ARMword, ARMword);
295
296void ARMul_SelectProcessor(ARMul_State*, unsigned);
297
298u32 AddWithCarry(u32, u32, u32, bool*, bool*);
299bool ARMul_AddOverflowQ(ARMword, ARMword);
300
301u8 ARMul_SignedSaturatedAdd8(u8, u8);
302u8 ARMul_SignedSaturatedSub8(u8, u8);
303u16 ARMul_SignedSaturatedAdd16(u16, u16);
304u16 ARMul_SignedSaturatedSub16(u16, u16);
305
306u8 ARMul_UnsignedSaturatedAdd8(u8, u8);
307u16 ARMul_UnsignedSaturatedAdd16(u16, u16);
308u8 ARMul_UnsignedSaturatedSub8(u8, u8);
309u16 ARMul_UnsignedSaturatedSub16(u16, u16);
310u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
311u32 ARMul_SignedSatQ(s32, u8, bool*);
312u32 ARMul_UnsignedSatQ(s32, u8, bool*);
313
314bool InBigEndianMode(ARMul_State*);
315bool InAPrivilegedMode(ARMul_State*);
316
317u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
318void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
diff --git a/src/core/arm/skyeye_common/arminit.cpp b/src/core/arm/skyeye_common/arminit.cpp
new file mode 100644
index 000000000..b7c508d75
--- /dev/null
+++ b/src/core/arm/skyeye_common/arminit.cpp
@@ -0,0 +1,100 @@
1/* arminit.c -- ARMulator initialization: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18#include <cstring>
19#include "core/arm/skyeye_common/armstate.h"
20#include "core/arm/skyeye_common/vfp/vfp.h"
21
22// Resets certain MPCore CP15 values to their ARM-defined reset values.
23static void ResetMPCoreCP15Registers(ARMul_State* cpu)
24{
25 // c0
26 cpu->CP15[CP15_MAIN_ID] = 0x410FB024;
27 cpu->CP15[CP15_TLB_TYPE] = 0x00000800;
28 cpu->CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111;
29 cpu->CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001;
30 cpu->CP15[CP15_DEBUG_FEATURE_0] = 0x00000002;
31 cpu->CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103;
32 cpu->CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302;
33 cpu->CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000;
34 cpu->CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000;
35 cpu->CP15[CP15_ISA_FEATURE_0] = 0x00100011;
36 cpu->CP15[CP15_ISA_FEATURE_1] = 0x12002111;
37 cpu->CP15[CP15_ISA_FEATURE_2] = 0x11221011;
38 cpu->CP15[CP15_ISA_FEATURE_3] = 0x01102131;
39 cpu->CP15[CP15_ISA_FEATURE_4] = 0x00000141;
40
41 // c1
42 cpu->CP15[CP15_CONTROL] = 0x00054078;
43 cpu->CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F;
44 cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000;
45
46 // c2
47 cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000;
48 cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000;
49 cpu->CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000;
50
51 // c3
52 cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000;
53
54 // c7
55 cpu->CP15[CP15_PHYS_ADDRESS] = 0x00000000;
56
57 // c9
58 cpu->CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0;
59
60 // c10
61 cpu->CP15[CP15_TLB_LOCKDOWN] = 0x00000000;
62 cpu->CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4;
63 cpu->CP15[CP15_NORMAL_REGION_REMAP] = 0x44E048E0;
64
65 // c13
66 cpu->CP15[CP15_PID] = 0x00000000;
67 cpu->CP15[CP15_CONTEXT_ID] = 0x00000000;
68 cpu->CP15[CP15_THREAD_UPRW] = 0x00000000;
69 cpu->CP15[CP15_THREAD_URO] = 0x00000000;
70 cpu->CP15[CP15_THREAD_PRW] = 0x00000000;
71
72 // c15
73 cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = 0x00000000;
74 cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000;
75 cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000;
76 cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000;
77 cpu->CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000;
78}
79
80// Performs a reset
81void ARMul_Reset(ARMul_State* state)
82{
83 VFPInit(state);
84
85 state->Reg[15] = 0;
86 state->Cpsr = INTBITS | SVC32MODE;
87 state->Mode = SVC32MODE;
88 state->Bank = SVCBANK;
89
90 ResetMPCoreCP15Registers(state);
91
92 state->NresetSig = HIGH;
93 state->NfiqSig = HIGH;
94 state->NirqSig = HIGH;
95 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
96 state->abortSig = LOW;
97
98 state->NumInstrs = 0;
99 state->Emulate = RUN;
100}
diff --git a/src/core/arm/skyeye_common/armmmu.h b/src/core/arm/skyeye_common/armmmu.h
index c67d7209b..5423588c0 100644
--- a/src/core/arm/skyeye_common/armmmu.h
+++ b/src/core/arm/skyeye_common/armmmu.h
@@ -23,7 +23,8 @@
23#include "common/swap.h" 23#include "common/swap.h"
24 24
25#include "core/memory.h" 25#include "core/memory.h"
26#include "core/arm/skyeye_common/armdefs.h" 26#include "core/arm/skyeye_common/armstate.h"
27#include "core/arm/skyeye_common/armsupp.h"
27 28
28// Register numbers in the MMU 29// Register numbers in the MMU
29enum 30enum
diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h
new file mode 100644
index 000000000..3ba0ba5cd
--- /dev/null
+++ b/src/core/arm/skyeye_common/armstate.h
@@ -0,0 +1,215 @@
1/* armdefs.h -- ARMulator common definitions: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18#pragma once
19
20#include <unordered_map>
21
22#include "common/common_types.h"
23#include "core/arm/skyeye_common/arm_regformat.h"
24
25// Signal levels
26enum {
27 LOW = 0,
28 HIGH = 1,
29 LOWHIGH = 1,
30 HIGHLOW = 2
31};
32
33// Cache types
34enum {
35 NONCACHE = 0,
36 DATACACHE = 1,
37 INSTCACHE = 2,
38};
39
40#define VFP_REG_NUM 64
41struct ARMul_State
42{
43 u32 Emulate; // To start and stop emulation
44
45 // Order of the following register should not be modified
46 u32 Reg[16]; // The current register file
47 u32 Cpsr; // The current PSR
48 u32 Spsr_copy;
49 u32 phys_pc;
50 u32 Reg_usr[2];
51 u32 Reg_svc[2]; // R13_SVC R14_SVC
52 u32 Reg_abort[2]; // R13_ABORT R14_ABORT
53 u32 Reg_undef[2]; // R13 UNDEF R14 UNDEF
54 u32 Reg_irq[2]; // R13_IRQ R14_IRQ
55 u32 Reg_firq[7]; // R8---R14 FIRQ
56 u32 Spsr[7]; // The exception psr's
57 u32 Mode; // The current mode
58 u32 Bank; // The current register bank
59 u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
60 u32 exclusive_state;
61 u32 exclusive_result;
62 u32 CP15[CP15_REGISTER_COUNT];
63
64 // FPSID, FPSCR, and FPEXC
65 u32 VFP[VFP_SYSTEM_REGISTER_COUNT];
66 // VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31).
67 // VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31),
68 // and only 32 singleword registers are accessible (S0-S31).
69 u32 ExtReg[VFP_REG_NUM];
70 /* ---- End of the ordered registers ---- */
71
72 u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
73 unsigned int shifter_carry_out;
74
75 // Add armv6 flags dyf:2010-08-09
76 u32 GEFlag, EFlag, AFlag, QFlag;
77
78 u32 TFlag; // Thumb state
79
80 unsigned long long NumInstrs; // The number of instructions executed
81 unsigned NumInstrsToExecute;
82
83 unsigned NresetSig; // Reset the processor
84 unsigned NfiqSig;
85 unsigned NirqSig;
86
87 unsigned abortSig;
88 unsigned NtransSig;
89 unsigned bigendSig;
90 unsigned syscallSig;
91
92 // TODO(bunnei): Move this cache to a better place - it should be per codeset (likely per
93 // process for our purposes), not per ARMul_State (which tracks CPU core state).
94 std::unordered_map<u32, int> instruction_cache;
95};
96
97/***************************************************************************\
98* The hardware vector addresses *
99\***************************************************************************/
100
101enum {
102 ARMResetV = 0,
103 ARMUndefinedInstrV = 4,
104 ARMSWIV = 8,
105 ARMPrefetchAbortV = 12,
106 ARMDataAbortV = 16,
107 ARMAddrExceptnV = 20,
108 ARMIRQV = 24,
109 ARMFIQV = 28,
110 ARMErrorV = 32, // This is an offset, not an address!
111
112 ARMul_ResetV = ARMResetV,
113 ARMul_UndefinedInstrV = ARMUndefinedInstrV,
114 ARMul_SWIV = ARMSWIV,
115 ARMul_PrefetchAbortV = ARMPrefetchAbortV,
116 ARMul_DataAbortV = ARMDataAbortV,
117 ARMul_AddrExceptnV = ARMAddrExceptnV,
118 ARMul_IRQV = ARMIRQV,
119 ARMul_FIQV = ARMFIQV
120};
121
122/***************************************************************************\
123* Mode and Bank Constants *
124\***************************************************************************/
125
126enum PrivilegeMode {
127 USER32MODE = 16,
128 FIQ32MODE = 17,
129 IRQ32MODE = 18,
130 SVC32MODE = 19,
131 ABORT32MODE = 23,
132 UNDEF32MODE = 27,
133 SYSTEM32MODE = 31
134};
135
136enum {
137 USERBANK = 0,
138 FIQBANK = 1,
139 IRQBANK = 2,
140 SVCBANK = 3,
141 ABORTBANK = 4,
142 UNDEFBANK = 5,
143 DUMMYBANK = 6,
144 SYSTEMBANK = 7
145};
146
147/***************************************************************************\
148* Definitions of things in the emulator *
149\***************************************************************************/
150void ARMul_Reset(ARMul_State* state);
151
152/***************************************************************************\
153* Definitions of things in the co-processor interface *
154\***************************************************************************/
155
156enum {
157 ARMul_FIRST = 0,
158 ARMul_TRANSFER = 1,
159 ARMul_BUSY = 2,
160 ARMul_DATA = 3,
161 ARMul_INTERRUPT = 4,
162 ARMul_DONE = 0,
163 ARMul_CANT = 1,
164 ARMul_INC = 3
165};
166
167/***************************************************************************\
168* Definitions of things in the host environment *
169\***************************************************************************/
170
171enum ConditionCode {
172 EQ = 0,
173 NE = 1,
174 CS = 2,
175 CC = 3,
176 MI = 4,
177 PL = 5,
178 VS = 6,
179 VC = 7,
180 HI = 8,
181 LS = 9,
182 GE = 10,
183 LT = 11,
184 GT = 12,
185 LE = 13,
186 AL = 14,
187 NV = 15,
188};
189
190// Flags for use with the APSR.
191enum : u32 {
192 NBIT = (1U << 31U),
193 ZBIT = (1 << 30),
194 CBIT = (1 << 29),
195 VBIT = (1 << 28),
196 QBIT = (1 << 27),
197 JBIT = (1 << 24),
198 EBIT = (1 << 9),
199 ABIT = (1 << 8),
200 IBIT = (1 << 7),
201 FBIT = (1 << 6),
202 TBIT = (1 << 5),
203
204 // Masks for groups of bits in the APSR.
205 MODEBITS = 0x1F,
206 INTBITS = 0x1C0,
207};
208
209// Values for Emulate.
210enum {
211 STOP = 0, // Stop
212 CHANGEMODE = 1, // Change mode
213 ONCE = 2, // Execute just one iteration
214 RUN = 3 // Continuous execution
215};
diff --git a/src/core/arm/skyeye_common/armsupp.cpp b/src/core/arm/skyeye_common/armsupp.cpp
new file mode 100644
index 000000000..affbf193a
--- /dev/null
+++ b/src/core/arm/skyeye_common/armsupp.cpp
@@ -0,0 +1,638 @@
1/* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18#include "common/logging/log.h"
19
20#include "core/mem_map.h"
21#include "core/arm/skyeye_common/arm_regformat.h"
22#include "core/arm/skyeye_common/armstate.h"
23#include "core/arm/skyeye_common/armsupp.h"
24
25// Unsigned sum of absolute difference
26u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
27{
28 if (left > right)
29 return left - right;
30
31 return right - left;
32}
33
34// Add with carry, indicates if a carry-out or signed overflow occurred.
35u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred)
36{
37 u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in;
38 s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in;
39 u64 result = (unsigned_sum & 0xFFFFFFFF);
40
41 if (carry_out_occurred)
42 *carry_out_occurred = (result != unsigned_sum);
43
44 if (overflow_occurred)
45 *overflow_occurred = ((s64)(s32)result != signed_sum);
46
47 return (u32)result;
48}
49
50// Compute whether an addition of A and B, giving RESULT, overflowed.
51bool AddOverflow(u32 a, u32 b, u32 result)
52{
53 return ((NEG(a) && NEG(b) && POS(result)) ||
54 (POS(a) && POS(b) && NEG(result)));
55}
56
57// Compute whether a subtraction of A and B, giving RESULT, overflowed.
58bool SubOverflow(u32 a, u32 b, u32 result)
59{
60 return ((NEG(a) && POS(b) && POS(result)) ||
61 (POS(a) && NEG(b) && NEG(result)));
62}
63
64// Returns true if the Q flag should be set as a result of overflow.
65bool ARMul_AddOverflowQ(u32 a, u32 b)
66{
67 u32 result = a + b;
68 if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0)
69 return true;
70
71 return false;
72}
73
74// 8-bit signed saturated addition
75u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
76{
77 u8 result = left + right;
78
79 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) {
80 if (left & 0x80)
81 result = 0x80;
82 else
83 result = 0x7F;
84 }
85
86 return result;
87}
88
89// 8-bit signed saturated subtraction
90u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
91{
92 u8 result = left - right;
93
94 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) {
95 if (left & 0x80)
96 result = 0x80;
97 else
98 result = 0x7F;
99 }
100
101 return result;
102}
103
104// 16-bit signed saturated addition
105u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
106{
107 u16 result = left + right;
108
109 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) {
110 if (left & 0x8000)
111 result = 0x8000;
112 else
113 result = 0x7FFF;
114 }
115
116 return result;
117}
118
119// 16-bit signed saturated subtraction
120u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
121{
122 u16 result = left - right;
123
124 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) {
125 if (left & 0x8000)
126 result = 0x8000;
127 else
128 result = 0x7FFF;
129 }
130
131 return result;
132}
133
134// 8-bit unsigned saturated addition
135u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
136{
137 u8 result = left + right;
138
139 if (result < left)
140 result = 0xFF;
141
142 return result;
143}
144
145// 16-bit unsigned saturated addition
146u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
147{
148 u16 result = left + right;
149
150 if (result < left)
151 result = 0xFFFF;
152
153 return result;
154}
155
156// 8-bit unsigned saturated subtraction
157u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
158{
159 if (left <= right)
160 return 0;
161
162 return left - right;
163}
164
165// 16-bit unsigned saturated subtraction
166u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
167{
168 if (left <= right)
169 return 0;
170
171 return left - right;
172}
173
174// Signed saturation.
175u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
176{
177 const u32 max = (1 << shift) - 1;
178 const s32 top = (value >> shift);
179
180 if (top > 0) {
181 *saturation_occurred = true;
182 return max;
183 }
184 else if (top < -1) {
185 *saturation_occurred = true;
186 return ~max;
187 }
188
189 *saturation_occurred = false;
190 return (u32)value;
191}
192
193// Unsigned saturation
194u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred)
195{
196 const u32 max = (1 << shift) - 1;
197
198 if (value < 0) {
199 *saturation_occurred = true;
200 return 0;
201 } else if ((u32)value > max) {
202 *saturation_occurred = true;
203 return max;
204 }
205
206 *saturation_occurred = false;
207 return (u32)value;
208}
209
210// Whether or not the given CPU is in big endian mode (E bit is set)
211bool InBigEndianMode(ARMul_State* cpu)
212{
213 return (cpu->Cpsr & (1 << 9)) != 0;
214}
215
216// Whether or not the given CPU is in a mode other than user mode.
217bool InAPrivilegedMode(ARMul_State* cpu)
218{
219 return (cpu->Mode != USER32MODE);
220}
221
222// Reads from the CP15 registers. Used with implementation of the MRC instruction.
223// Note that since the 3DS does not have the hypervisor extensions, these registers
224// are not implemented.
225u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
226{
227 // Unprivileged registers
228 if (crn == 13 && opcode_1 == 0 && crm == 0)
229 {
230 if (opcode_2 == 2)
231 return cpu->CP15[CP15_THREAD_UPRW];
232
233 if (opcode_2 == 3)
234 return cpu->CP15[CP15_THREAD_URO];
235 }
236
237 if (InAPrivilegedMode(cpu))
238 {
239 if (crn == 0 && opcode_1 == 0)
240 {
241 if (crm == 0)
242 {
243 if (opcode_2 == 0)
244 return cpu->CP15[CP15_MAIN_ID];
245
246 if (opcode_2 == 1)
247 return cpu->CP15[CP15_CACHE_TYPE];
248
249 if (opcode_2 == 3)
250 return cpu->CP15[CP15_TLB_TYPE];
251
252 if (opcode_2 == 5)
253 return cpu->CP15[CP15_CPU_ID];
254 }
255 else if (crm == 1)
256 {
257 if (opcode_2 == 0)
258 return cpu->CP15[CP15_PROCESSOR_FEATURE_0];
259
260 if (opcode_2 == 1)
261 return cpu->CP15[CP15_PROCESSOR_FEATURE_1];
262
263 if (opcode_2 == 2)
264 return cpu->CP15[CP15_DEBUG_FEATURE_0];
265
266 if (opcode_2 == 4)
267 return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_0];
268
269 if (opcode_2 == 5)
270 return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_1];
271
272 if (opcode_2 == 6)
273 return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_2];
274
275 if (opcode_2 == 7)
276 return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_3];
277 }
278 else if (crm == 2)
279 {
280 if (opcode_2 == 0)
281 return cpu->CP15[CP15_ISA_FEATURE_0];
282
283 if (opcode_2 == 1)
284 return cpu->CP15[CP15_ISA_FEATURE_1];
285
286 if (opcode_2 == 2)
287 return cpu->CP15[CP15_ISA_FEATURE_2];
288
289 if (opcode_2 == 3)
290 return cpu->CP15[CP15_ISA_FEATURE_3];
291
292 if (opcode_2 == 4)
293 return cpu->CP15[CP15_ISA_FEATURE_4];
294 }
295 }
296
297 if (crn == 1 && opcode_1 == 0 && crm == 0)
298 {
299 if (opcode_2 == 0)
300 return cpu->CP15[CP15_CONTROL];
301
302 if (opcode_2 == 1)
303 return cpu->CP15[CP15_AUXILIARY_CONTROL];
304
305 if (opcode_2 == 2)
306 return cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL];
307 }
308
309 if (crn == 2 && opcode_1 == 0 && crm == 0)
310 {
311 if (opcode_2 == 0)
312 return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0];
313
314 if (opcode_2 == 1)
315 return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1];
316
317 if (opcode_2 == 2)
318 return cpu->CP15[CP15_TRANSLATION_BASE_CONTROL];
319 }
320
321 if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
322 return cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL];
323
324 if (crn == 5 && opcode_1 == 0 && crm == 0)
325 {
326 if (opcode_2 == 0)
327 return cpu->CP15[CP15_FAULT_STATUS];
328
329 if (opcode_2 == 1)
330 return cpu->CP15[CP15_INSTR_FAULT_STATUS];
331 }
332
333 if (crn == 6 && opcode_1 == 0 && crm == 0)
334 {
335 if (opcode_2 == 0)
336 return cpu->CP15[CP15_FAULT_ADDRESS];
337
338 if (opcode_2 == 1)
339 return cpu->CP15[CP15_WFAR];
340 }
341
342 if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0)
343 return cpu->CP15[CP15_PHYS_ADDRESS];
344
345 if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
346 return cpu->CP15[CP15_DATA_CACHE_LOCKDOWN];
347
348 if (crn == 10 && opcode_1 == 0)
349 {
350 if (crm == 0 && opcode_2 == 0)
351 return cpu->CP15[CP15_TLB_LOCKDOWN];
352
353 if (crm == 2)
354 {
355 if (opcode_2 == 0)
356 return cpu->CP15[CP15_PRIMARY_REGION_REMAP];
357
358 if (opcode_2 == 1)
359 return cpu->CP15[CP15_NORMAL_REGION_REMAP];
360 }
361 }
362
363 if (crn == 13 && crm == 0)
364 {
365 if (opcode_2 == 0)
366 return cpu->CP15[CP15_PID];
367
368 if (opcode_2 == 1)
369 return cpu->CP15[CP15_CONTEXT_ID];
370
371 if (opcode_2 == 4)
372 return cpu->CP15[CP15_THREAD_PRW];
373 }
374
375 if (crn == 15)
376 {
377 if (opcode_1 == 0 && crm == 12)
378 {
379 if (opcode_2 == 0)
380 return cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL];
381
382 if (opcode_2 == 1)
383 return cpu->CP15[CP15_CYCLE_COUNTER];
384
385 if (opcode_2 == 2)
386 return cpu->CP15[CP15_COUNT_0];
387
388 if (opcode_2 == 3)
389 return cpu->CP15[CP15_COUNT_1];
390 }
391
392 if (opcode_1 == 5 && opcode_2 == 2)
393 {
394 if (crm == 5)
395 return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS];
396
397 if (crm == 6)
398 return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS];
399
400 if (crm == 7)
401 return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE];
402 }
403
404 if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
405 return cpu->CP15[CP15_TLB_DEBUG_CONTROL];
406 }
407 }
408
409 LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2);
410 return 0;
411}
412
413// Write to the CP15 registers. Used with implementation of the MCR instruction.
414// Note that since the 3DS does not have the hypervisor extensions, these registers
415// are not implemented.
416void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2)
417{
418 if (InAPrivilegedMode(cpu))
419 {
420 if (crn == 1 && opcode_1 == 0 && crm == 0)
421 {
422 if (opcode_2 == 0)
423 cpu->CP15[CP15_CONTROL] = value;
424 else if (opcode_2 == 1)
425 cpu->CP15[CP15_AUXILIARY_CONTROL] = value;
426 else if (opcode_2 == 2)
427 cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value;
428 }
429 else if (crn == 2 && opcode_1 == 0 && crm == 0)
430 {
431 if (opcode_2 == 0)
432 cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0] = value;
433 else if (opcode_2 == 1)
434 cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1] = value;
435 else if (opcode_2 == 2)
436 cpu->CP15[CP15_TRANSLATION_BASE_CONTROL] = value;
437 }
438 else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
439 {
440 cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL] = value;
441 }
442 else if (crn == 5 && opcode_1 == 0 && crm == 0)
443 {
444 if (opcode_2 == 0)
445 cpu->CP15[CP15_FAULT_STATUS] = value;
446 else if (opcode_2 == 1)
447 cpu->CP15[CP15_INSTR_FAULT_STATUS] = value;
448 }
449 else if (crn == 6 && opcode_1 == 0 && crm == 0)
450 {
451 if (opcode_2 == 0)
452 cpu->CP15[CP15_FAULT_ADDRESS] = value;
453 else if (opcode_2 == 1)
454 cpu->CP15[CP15_WFAR] = value;
455 }
456 else if (crn == 7 && opcode_1 == 0)
457 {
458 if (crm == 0 && opcode_2 == 4)
459 {
460 cpu->CP15[CP15_WAIT_FOR_INTERRUPT] = value;
461 }
462 else if (crm == 4 && opcode_2 == 0)
463 {
464 // NOTE: Not entirely accurate. This should do permission checks.
465 cpu->CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value);
466 }
467 else if (crm == 5)
468 {
469 if (opcode_2 == 0)
470 cpu->CP15[CP15_INVALIDATE_INSTR_CACHE] = value;
471 else if (opcode_2 == 1)
472 cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value;
473 else if (opcode_2 == 2)
474 cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value;
475 else if (opcode_2 == 6)
476 cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value;
477 else if (opcode_2 == 7)
478 cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value;
479 }
480 else if (crm == 6)
481 {
482 if (opcode_2 == 0)
483 cpu->CP15[CP15_INVALIDATE_DATA_CACHE] = value;
484 else if (opcode_2 == 1)
485 cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
486 else if (opcode_2 == 2)
487 cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
488 }
489 else if (crm == 7 && opcode_2 == 0)
490 {
491 cpu->CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value;
492 }
493 else if (crm == 10)
494 {
495 if (opcode_2 == 0)
496 cpu->CP15[CP15_CLEAN_DATA_CACHE] = value;
497 else if (opcode_2 == 1)
498 cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value;
499 else if (opcode_2 == 2)
500 cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value;
501 }
502 else if (crm == 14)
503 {
504 if (opcode_2 == 0)
505 cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value;
506 else if (opcode_2 == 1)
507 cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value;
508 else if (opcode_2 == 2)
509 cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value;
510 }
511 }
512 else if (crn == 8 && opcode_1 == 0)
513 {
514 LOG_WARNING(Core_ARM11, "TLB operations not fully implemented.");
515
516 if (crm == 5)
517 {
518 if (opcode_2 == 0)
519 cpu->CP15[CP15_INVALIDATE_ITLB] = value;
520 else if (opcode_2 == 1)
521 cpu->CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value;
522 else if (opcode_2 == 2)
523 cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value;
524 else if (opcode_2 == 3)
525 cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value;
526 }
527 else if (crm == 6)
528 {
529 if (opcode_2 == 0)
530 cpu->CP15[CP15_INVALIDATE_DTLB] = value;
531 else if (opcode_2 == 1)
532 cpu->CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value;
533 else if (opcode_2 == 2)
534 cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value;
535 else if (opcode_2 == 3)
536 cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value;
537 }
538 else if (crm == 7)
539 {
540 if (opcode_2 == 0)
541 cpu->CP15[CP15_INVALIDATE_UTLB] = value;
542 else if (opcode_2 == 1)
543 cpu->CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value;
544 else if (opcode_2 == 2)
545 cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value;
546 else if (opcode_2 == 3)
547 cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value;
548 }
549 }
550 else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0)
551 {
552 cpu->CP15[CP15_DATA_CACHE_LOCKDOWN] = value;
553 }
554 else if (crn == 10 && opcode_1 == 0)
555 {
556 if (crm == 0 && opcode_2 == 0)
557 {
558 cpu->CP15[CP15_TLB_LOCKDOWN] = value;
559 }
560 else if (crm == 2)
561 {
562 if (opcode_2 == 0)
563 cpu->CP15[CP15_PRIMARY_REGION_REMAP] = value;
564 else if (opcode_2 == 1)
565 cpu->CP15[CP15_NORMAL_REGION_REMAP] = value;
566 }
567 }
568 else if (crn == 13 && opcode_1 == 0 && crm == 0)
569 {
570 if (opcode_2 == 0)
571 cpu->CP15[CP15_PID] = value;
572 else if (opcode_2 == 1)
573 cpu->CP15[CP15_CONTEXT_ID] = value;
574 else if (opcode_2 == 3)
575 cpu->CP15[CP15_THREAD_URO] = value;
576 else if (opcode_2 == 4)
577 cpu->CP15[CP15_THREAD_PRW] = value;
578 }
579 else if (crn == 15)
580 {
581 if (opcode_1 == 0 && crm == 12)
582 {
583 if (opcode_2 == 0)
584 cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value;
585 else if (opcode_2 == 1)
586 cpu->CP15[CP15_CYCLE_COUNTER] = value;
587 else if (opcode_2 == 2)
588 cpu->CP15[CP15_COUNT_0] = value;
589 else if (opcode_2 == 3)
590 cpu->CP15[CP15_COUNT_1] = value;
591 }
592 else if (opcode_1 == 5)
593 {
594 if (crm == 4)
595 {
596 if (opcode_2 == 2)
597 cpu->CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value;
598 else if (opcode_2 == 4)
599 cpu->CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value;
600 }
601 else if (crm == 5 && opcode_2 == 2)
602 {
603 cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value;
604 }
605 else if (crm == 6 && opcode_2 == 2)
606 {
607 cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value;
608 }
609 else if (crm == 7 && opcode_2 == 2)
610 {
611 cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value;
612 }
613 }
614 else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0)
615 {
616 cpu->CP15[CP15_TLB_DEBUG_CONTROL] = value;
617 }
618 }
619 }
620
621 // Unprivileged registers
622 if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4)
623 {
624 cpu->CP15[CP15_FLUSH_PREFETCH_BUFFER] = value;
625 }
626 else if (crn == 7 && opcode_1 == 0 && crm == 10)
627 {
628 if (opcode_2 == 4)
629 cpu->CP15[CP15_DATA_SYNC_BARRIER] = value;
630 else if (opcode_2 == 5)
631 cpu->CP15[CP15_DATA_MEMORY_BARRIER] = value;
632
633 }
634 else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2)
635 {
636 cpu->CP15[CP15_THREAD_UPRW] = value;
637 }
638}
diff --git a/src/core/arm/skyeye_common/armsupp.h b/src/core/arm/skyeye_common/armsupp.h
new file mode 100644
index 000000000..5cf1cd1d3
--- /dev/null
+++ b/src/core/arm/skyeye_common/armsupp.h
@@ -0,0 +1,40 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9struct ARMul_State;
10
11#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
12#define BIT(s, n) ((s >> (n)) & 1)
13
14#define POS(i) ( (~(i)) >> 31 )
15#define NEG(i) ( (i) >> 31 )
16
17bool AddOverflow(u32, u32, u32);
18bool SubOverflow(u32, u32, u32);
19
20u32 AddWithCarry(u32, u32, u32, bool*, bool*);
21bool ARMul_AddOverflowQ(u32, u32);
22
23u8 ARMul_SignedSaturatedAdd8(u8, u8);
24u8 ARMul_SignedSaturatedSub8(u8, u8);
25u16 ARMul_SignedSaturatedAdd16(u16, u16);
26u16 ARMul_SignedSaturatedSub16(u16, u16);
27
28u8 ARMul_UnsignedSaturatedAdd8(u8, u8);
29u16 ARMul_UnsignedSaturatedAdd16(u16, u16);
30u8 ARMul_UnsignedSaturatedSub8(u8, u8);
31u16 ARMul_UnsignedSaturatedSub16(u16, u16);
32u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
33u32 ARMul_SignedSatQ(s32, u8, bool*);
34u32 ARMul_UnsignedSatQ(s32, u8, bool*);
35
36bool InBigEndianMode(ARMul_State*);
37bool InAPrivilegedMode(ARMul_State*);
38
39u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
40void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index 1ffc1f9af..26f303de4 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -23,7 +23,7 @@
23#include "common/common_funcs.h" 23#include "common/common_funcs.h"
24#include "common/logging/log.h" 24#include "common/logging/log.h"
25 25
26#include "core/arm/skyeye_common/armdefs.h" 26#include "core/arm/skyeye_common/armstate.h"
27#include "core/arm/skyeye_common/vfp/asm_vfp.h" 27#include "core/arm/skyeye_common/vfp/asm_vfp.h"
28#include "core/arm/skyeye_common/vfp/vfp.h" 28#include "core/arm/skyeye_common/vfp/vfp.h"
29 29
@@ -43,7 +43,7 @@ void VFPInit(ARMul_State* state)
43 state->VFP[VFP_MVFR1] = 0; 43 state->VFP[VFP_MVFR1] = 0;
44} 44}
45 45
46void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value) 46void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value)
47{ 47{
48 if (to_arm) 48 if (to_arm)
49 { 49 {
@@ -55,7 +55,7 @@ void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword*
55 } 55 }
56} 56}
57 57
58void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) 58void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2)
59{ 59{
60 if (to_arm) 60 if (to_arm)
61 { 61 {
@@ -68,7 +68,7 @@ void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword
68 state->ExtReg[n*2] = *value1; 68 state->ExtReg[n*2] = *value1;
69 } 69 }
70} 70}
71void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) 71void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2)
72{ 72{
73 if (to_arm) 73 if (to_arm)
74 { 74 {
@@ -82,7 +82,7 @@ void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMwor
82 } 82 }
83} 83}
84 84
85void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm) 85void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm)
86{ 86{
87 if (single) 87 if (single)
88 { 88 {
@@ -95,7 +95,7 @@ void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm)
95 state->ExtReg[d*2] = 0; 95 state->ExtReg[d*2] = 0;
96 } 96 }
97} 97}
98void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword m) 98void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m)
99{ 99{
100 if (single) 100 if (single)
101 { 101 {
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index 80ca93ccd..88908da9f 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -36,8 +36,8 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc
36u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); 36u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
37u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); 37u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr);
38 38
39void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value); 39void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value);
40void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); 40void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2);
41void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); 41void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2);
42void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm); 42void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm);
43void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm); 43void VMOVR(ARMul_State* state, u32 single, u32 d, u32 imm);
diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h
index 2007d6dc4..91a8d4d57 100644
--- a/src/core/arm/skyeye_common/vfp/vfp_helper.h
+++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h
@@ -34,7 +34,7 @@
34 34
35#include <cstdio> 35#include <cstdio>
36#include "common/common_types.h" 36#include "common/common_types.h"
37#include "core/arm/skyeye_common/armdefs.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) {n/=base;}
@@ -415,7 +415,7 @@ struct op {
415 u32 flags; 415 u32 flags;
416}; 416};
417 417
418static inline u32 fls(ARMword x) 418static inline u32 fls(u32 x)
419{ 419{
420 int r = 32; 420 int r = 32;
421 421
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
index f91049585..1d844a66e 100644
--- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
@@ -70,9 +70,9 @@ static void vfp_double_dump(const char *str, struct vfp_double *d)
70 70
71static void vfp_double_normalise_denormal(struct vfp_double *vd) 71static void vfp_double_normalise_denormal(struct vfp_double *vd)
72{ 72{
73 int bits = 31 - fls((ARMword)(vd->significand >> 32)); 73 int bits = 31 - fls((u32)(vd->significand >> 32));
74 if (bits == 31) 74 if (bits == 31)
75 bits = 63 - fls((ARMword)vd->significand); 75 bits = 63 - fls((u32)vd->significand);
76 76
77 vfp_double_dump("normalise_denormal: in", vd); 77 vfp_double_dump("normalise_denormal: in", vd);
78 78
@@ -109,9 +109,9 @@ u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd,
109 exponent = vd->exponent; 109 exponent = vd->exponent;
110 significand = vd->significand; 110 significand = vd->significand;
111 111
112 shift = 32 - fls((ARMword)(significand >> 32)); 112 shift = 32 - fls((u32)(significand >> 32));
113 if (shift == 32) 113 if (shift == 32)
114 shift = 64 - fls((ARMword)significand); 114 shift = 64 - fls((u32)significand);
115 if (shift) { 115 if (shift) {
116 exponent -= shift; 116 exponent -= shift;
117 significand <<= shift; 117 significand <<= shift;
@@ -566,7 +566,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32
566 /* 566 /*
567 * 2^0 <= m < 2^32-2^8 567 * 2^0 <= m < 2^32-2^8
568 */ 568 */
569 d = (ARMword)((vdm.significand << 1) >> shift); 569 d = (u32)((vdm.significand << 1) >> shift);
570 rem = vdm.significand << (65 - shift); 570 rem = vdm.significand << (65 - shift);
571 571
572 if (rmode == FPSCR_ROUND_NEAREST) { 572 if (rmode == FPSCR_ROUND_NEAREST) {
@@ -647,7 +647,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32
647 int shift = 1023 + 63 - vdm.exponent; /* 58 */ 647 int shift = 1023 + 63 - vdm.exponent; /* 58 */
648 u64 rem, incr = 0; 648 u64 rem, incr = 0;
649 649
650 d = (ARMword)((vdm.significand << 1) >> shift); 650 d = (u32)((vdm.significand << 1) >> shift);
651 rem = vdm.significand << (65 - shift); 651 rem = vdm.significand << (65 - shift);
652 652
653 if (rmode == FPSCR_ROUND_NEAREST) { 653 if (rmode == FPSCR_ROUND_NEAREST) {