1 // Copyright 2012 Michael Kang, 2014 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4
5 #define CITRA_IGNORE_EXIT(x)
6
7 #include <algorithm>
8 #include <cinttypes>
9 #include <cstdio>
10 #include "common/common_types.h"
11 #include "common/logging/log.h"
12 #include "common/microprofile.h"
13 #include "core/arm/dyncom/arm_dyncom_dec.h"
14 #include "core/arm/dyncom/arm_dyncom_interpreter.h"
15 #include "core/arm/dyncom/arm_dyncom_run.h"
16 #include "core/arm/dyncom/arm_dyncom_thumb.h"
17 #include "core/arm/dyncom/arm_dyncom_trans.h"
18 #include "core/arm/skyeye_common/armstate.h"
19 #include "core/arm/skyeye_common/armsupp.h"
20 #include "core/arm/skyeye_common/vfp/vfp.h"
21 #include "core/core.h"
22 #include "core/core_timing.h"
23 #include "core/gdbstub/gdbstub.h"
24 #include "core/hle/kernel/svc.h"
25 #include "core/memory.h"
26
27 #define RM BITS(sht_oper, 0, 3)
28 #define RS BITS(sht_oper, 8, 11)
29
30 #define glue(x, y) x##y
31 #define DPO(s) glue(DataProcessingOperands, s)
32 #define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i))
33 #define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i))
34 #define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32)
35 #define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32)
36
CondPassed(const ARMul_State * cpu,unsigned int cond)37 static bool CondPassed(const ARMul_State* cpu, unsigned int cond) {
38 const bool n_flag = cpu->NFlag != 0;
39 const bool z_flag = cpu->ZFlag != 0;
40 const bool c_flag = cpu->CFlag != 0;
41 const bool v_flag = cpu->VFlag != 0;
42
43 switch (cond) {
44 case ConditionCode::EQ:
45 return z_flag;
46 case ConditionCode::NE:
47 return !z_flag;
48 case ConditionCode::CS:
49 return c_flag;
50 case ConditionCode::CC:
51 return !c_flag;
52 case ConditionCode::MI:
53 return n_flag;
54 case ConditionCode::PL:
55 return !n_flag;
56 case ConditionCode::VS:
57 return v_flag;
58 case ConditionCode::VC:
59 return !v_flag;
60 case ConditionCode::HI:
61 return (c_flag && !z_flag);
62 case ConditionCode::LS:
63 return (!c_flag || z_flag);
64 case ConditionCode::GE:
65 return (n_flag == v_flag);
66 case ConditionCode::LT:
67 return (n_flag != v_flag);
68 case ConditionCode::GT:
69 return (!z_flag && (n_flag == v_flag));
70 case ConditionCode::LE:
71 return (z_flag || (n_flag != v_flag));
72 case ConditionCode::AL:
73 case ConditionCode::NV: // Unconditional
74 return true;
75 }
76
77 return false;
78 }
79
DPO(Immediate)80 static unsigned int DPO(Immediate)(ARMul_State* cpu, unsigned int sht_oper) {
81 unsigned int immed_8 = BITS(sht_oper, 0, 7);
82 unsigned int rotate_imm = BITS(sht_oper, 8, 11);
83 unsigned int shifter_operand = ROTATE_RIGHT_32(immed_8, rotate_imm * 2);
84 if (rotate_imm == 0)
85 cpu->shifter_carry_out = cpu->CFlag;
86 else
87 cpu->shifter_carry_out = BIT(shifter_operand, 31);
88 return shifter_operand;
89 }
90
DPO(Register)91 static unsigned int DPO(Register)(ARMul_State* cpu, unsigned int sht_oper) {
92 unsigned int rm = CHECK_READ_REG15(cpu, RM);
93 unsigned int shifter_operand = rm;
94 cpu->shifter_carry_out = cpu->CFlag;
95 return shifter_operand;
96 }
97
DPO(LogicalShiftLeftByImmediate)98 static unsigned int DPO(LogicalShiftLeftByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
99 int shift_imm = BITS(sht_oper, 7, 11);
100 unsigned int rm = CHECK_READ_REG15(cpu, RM);
101 unsigned int shifter_operand;
102 if (shift_imm == 0) {
103 shifter_operand = rm;
104 cpu->shifter_carry_out = cpu->CFlag;
105 } else {
106 shifter_operand = rm << shift_imm;
107 cpu->shifter_carry_out = BIT(rm, 32 - shift_imm);
108 }
109 return shifter_operand;
110 }
111
DPO(LogicalShiftLeftByRegister)112 static unsigned int DPO(LogicalShiftLeftByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
113 int shifter_operand;
114 unsigned int rm = CHECK_READ_REG15(cpu, RM);
115 unsigned int rs = CHECK_READ_REG15(cpu, RS);
116 if (BITS(rs, 0, 7) == 0) {
117 shifter_operand = rm;
118 cpu->shifter_carry_out = cpu->CFlag;
119 } else if (BITS(rs, 0, 7) < 32) {
120 shifter_operand = rm << BITS(rs, 0, 7);
121 cpu->shifter_carry_out = BIT(rm, 32 - BITS(rs, 0, 7));
122 } else if (BITS(rs, 0, 7) == 32) {
123 shifter_operand = 0;
124 cpu->shifter_carry_out = BIT(rm, 0);
125 } else {
126 shifter_operand = 0;
127 cpu->shifter_carry_out = 0;
128 }
129 return shifter_operand;
130 }
131
DPO(LogicalShiftRightByImmediate)132 static unsigned int DPO(LogicalShiftRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
133 unsigned int rm = CHECK_READ_REG15(cpu, RM);
134 unsigned int shifter_operand;
135 int shift_imm = BITS(sht_oper, 7, 11);
136 if (shift_imm == 0) {
137 shifter_operand = 0;
138 cpu->shifter_carry_out = BIT(rm, 31);
139 } else {
140 shifter_operand = rm >> shift_imm;
141 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
142 }
143 return shifter_operand;
144 }
145
DPO(LogicalShiftRightByRegister)146 static unsigned int DPO(LogicalShiftRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
147 unsigned int rs = CHECK_READ_REG15(cpu, RS);
148 unsigned int rm = CHECK_READ_REG15(cpu, RM);
149 unsigned int shifter_operand;
150 if (BITS(rs, 0, 7) == 0) {
151 shifter_operand = rm;
152 cpu->shifter_carry_out = cpu->CFlag;
153 } else if (BITS(rs, 0, 7) < 32) {
154 shifter_operand = rm >> BITS(rs, 0, 7);
155 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
156 } else if (BITS(rs, 0, 7) == 32) {
157 shifter_operand = 0;
158 cpu->shifter_carry_out = BIT(rm, 31);
159 } else {
160 shifter_operand = 0;
161 cpu->shifter_carry_out = 0;
162 }
163 return shifter_operand;
164 }
165
DPO(ArithmeticShiftRightByImmediate)166 static unsigned int DPO(ArithmeticShiftRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
167 unsigned int rm = CHECK_READ_REG15(cpu, RM);
168 unsigned int shifter_operand;
169 int shift_imm = BITS(sht_oper, 7, 11);
170 if (shift_imm == 0) {
171 if (BIT(rm, 31) == 0)
172 shifter_operand = 0;
173 else
174 shifter_operand = 0xFFFFFFFF;
175 cpu->shifter_carry_out = BIT(rm, 31);
176 } else {
177 shifter_operand = static_cast<int>(rm) >> shift_imm;
178 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
179 }
180 return shifter_operand;
181 }
182
DPO(ArithmeticShiftRightByRegister)183 static unsigned int DPO(ArithmeticShiftRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
184 unsigned int rs = CHECK_READ_REG15(cpu, RS);
185 unsigned int rm = CHECK_READ_REG15(cpu, RM);
186 unsigned int shifter_operand;
187 if (BITS(rs, 0, 7) == 0) {
188 shifter_operand = rm;
189 cpu->shifter_carry_out = cpu->CFlag;
190 } else if (BITS(rs, 0, 7) < 32) {
191 shifter_operand = static_cast<int>(rm) >> BITS(rs, 0, 7);
192 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
193 } else {
194 if (BIT(rm, 31) == 0)
195 shifter_operand = 0;
196 else
197 shifter_operand = 0xffffffff;
198 cpu->shifter_carry_out = BIT(rm, 31);
199 }
200 return shifter_operand;
201 }
202
DPO(RotateRightByImmediate)203 static unsigned int DPO(RotateRightByImmediate)(ARMul_State* cpu, unsigned int sht_oper) {
204 unsigned int shifter_operand;
205 unsigned int rm = CHECK_READ_REG15(cpu, RM);
206 int shift_imm = BITS(sht_oper, 7, 11);
207 if (shift_imm == 0) {
208 shifter_operand = (cpu->CFlag << 31) | (rm >> 1);
209 cpu->shifter_carry_out = BIT(rm, 0);
210 } else {
211 shifter_operand = ROTATE_RIGHT_32(rm, shift_imm);
212 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
213 }
214 return shifter_operand;
215 }
216
DPO(RotateRightByRegister)217 static unsigned int DPO(RotateRightByRegister)(ARMul_State* cpu, unsigned int sht_oper) {
218 unsigned int rm = CHECK_READ_REG15(cpu, RM);
219 unsigned int rs = CHECK_READ_REG15(cpu, RS);
220 unsigned int shifter_operand;
221 if (BITS(rs, 0, 7) == 0) {
222 shifter_operand = rm;
223 cpu->shifter_carry_out = cpu->CFlag;
224 } else if (BITS(rs, 0, 4) == 0) {
225 shifter_operand = rm;
226 cpu->shifter_carry_out = BIT(rm, 31);
227 } else {
228 shifter_operand = ROTATE_RIGHT_32(rm, BITS(rs, 0, 4));
229 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 4) - 1);
230 }
231 return shifter_operand;
232 }
233
234 #define DEBUG_MSG \
235 LOG_DEBUG(Core_ARM11, "inst is {:x}", inst); \
236 CITRA_IGNORE_EXIT(0)
237
238 #define LnSWoUB(s) glue(LnSWoUB, s)
239 #define MLnS(s) glue(MLnS, s)
240 #define LdnStM(s) glue(LdnStM, s)
241
242 #define W_BIT BIT(inst, 21)
243 #define U_BIT BIT(inst, 23)
244 #define I_BIT BIT(inst, 25)
245 #define P_BIT BIT(inst, 24)
246 #define OFFSET_12 BITS(inst, 0, 11)
247
LnSWoUB(ImmediateOffset)248 static void LnSWoUB(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
249 unsigned int Rn = BITS(inst, 16, 19);
250 unsigned int addr;
251
252 if (U_BIT)
253 addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12;
254 else
255 addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12;
256
257 virt_addr = addr;
258 }
259
LnSWoUB(RegisterOffset)260 static void LnSWoUB(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
261 unsigned int Rn = BITS(inst, 16, 19);
262 unsigned int Rm = BITS(inst, 0, 3);
263 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
264 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
265 unsigned int addr;
266
267 if (U_BIT)
268 addr = rn + rm;
269 else
270 addr = rn - rm;
271
272 virt_addr = addr;
273 }
274
LnSWoUB(ImmediatePostIndexed)275 static void LnSWoUB(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst,
276 unsigned int& virt_addr) {
277 unsigned int Rn = BITS(inst, 16, 19);
278 unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn);
279
280 if (U_BIT)
281 cpu->Reg[Rn] += OFFSET_12;
282 else
283 cpu->Reg[Rn] -= OFFSET_12;
284
285 virt_addr = addr;
286 }
287
LnSWoUB(ImmediatePreIndexed)288 static void LnSWoUB(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst,
289 unsigned int& virt_addr) {
290 unsigned int Rn = BITS(inst, 16, 19);
291 unsigned int addr;
292
293 if (U_BIT)
294 addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12;
295 else
296 addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12;
297
298 virt_addr = addr;
299
300 if (CondPassed(cpu, BITS(inst, 28, 31)))
301 cpu->Reg[Rn] = addr;
302 }
303
MLnS(RegisterPreIndexed)304 static void MLnS(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
305 unsigned int addr;
306 unsigned int Rn = BITS(inst, 16, 19);
307 unsigned int Rm = BITS(inst, 0, 3);
308 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
309 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
310
311 if (U_BIT)
312 addr = rn + rm;
313 else
314 addr = rn - rm;
315
316 virt_addr = addr;
317
318 if (CondPassed(cpu, BITS(inst, 28, 31)))
319 cpu->Reg[Rn] = addr;
320 }
321
LnSWoUB(RegisterPreIndexed)322 static void LnSWoUB(RegisterPreIndexed)(ARMul_State* cpu, unsigned int inst,
323 unsigned int& virt_addr) {
324 unsigned int Rn = BITS(inst, 16, 19);
325 unsigned int Rm = BITS(inst, 0, 3);
326 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
327 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
328 unsigned int addr;
329
330 if (U_BIT)
331 addr = rn + rm;
332 else
333 addr = rn - rm;
334
335 virt_addr = addr;
336
337 if (CondPassed(cpu, BITS(inst, 28, 31))) {
338 cpu->Reg[Rn] = addr;
339 }
340 }
341
LnSWoUB(ScaledRegisterPreIndexed)342 static void LnSWoUB(ScaledRegisterPreIndexed)(ARMul_State* cpu, unsigned int inst,
343 unsigned int& virt_addr) {
344 unsigned int shift = BITS(inst, 5, 6);
345 unsigned int shift_imm = BITS(inst, 7, 11);
346 unsigned int Rn = BITS(inst, 16, 19);
347 unsigned int Rm = BITS(inst, 0, 3);
348 unsigned int index = 0;
349 unsigned int addr;
350 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
351 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
352
353 switch (shift) {
354 case 0:
355 index = rm << shift_imm;
356 break;
357 case 1:
358 if (shift_imm == 0) {
359 index = 0;
360 } else {
361 index = rm >> shift_imm;
362 }
363 break;
364 case 2:
365 if (shift_imm == 0) { // ASR #32
366 if (BIT(rm, 31) == 1)
367 index = 0xFFFFFFFF;
368 else
369 index = 0;
370 } else {
371 index = static_cast<int>(rm) >> shift_imm;
372 }
373 break;
374 case 3:
375 if (shift_imm == 0) {
376 index = (cpu->CFlag << 31) | (rm >> 1);
377 } else {
378 index = ROTATE_RIGHT_32(rm, shift_imm);
379 }
380 break;
381 }
382
383 if (U_BIT)
384 addr = rn + index;
385 else
386 addr = rn - index;
387
388 virt_addr = addr;
389
390 if (CondPassed(cpu, BITS(inst, 28, 31)))
391 cpu->Reg[Rn] = addr;
392 }
393
LnSWoUB(ScaledRegisterPostIndexed)394 static void LnSWoUB(ScaledRegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
395 unsigned int& virt_addr) {
396 unsigned int shift = BITS(inst, 5, 6);
397 unsigned int shift_imm = BITS(inst, 7, 11);
398 unsigned int Rn = BITS(inst, 16, 19);
399 unsigned int Rm = BITS(inst, 0, 3);
400 unsigned int index = 0;
401 unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn);
402 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
403
404 switch (shift) {
405 case 0:
406 index = rm << shift_imm;
407 break;
408 case 1:
409 if (shift_imm == 0) {
410 index = 0;
411 } else {
412 index = rm >> shift_imm;
413 }
414 break;
415 case 2:
416 if (shift_imm == 0) { // ASR #32
417 if (BIT(rm, 31) == 1)
418 index = 0xFFFFFFFF;
419 else
420 index = 0;
421 } else {
422 index = static_cast<int>(rm) >> shift_imm;
423 }
424 break;
425 case 3:
426 if (shift_imm == 0) {
427 index = (cpu->CFlag << 31) | (rm >> 1);
428 } else {
429 index = ROTATE_RIGHT_32(rm, shift_imm);
430 }
431 break;
432 }
433
434 virt_addr = addr;
435
436 if (CondPassed(cpu, BITS(inst, 28, 31))) {
437 if (U_BIT)
438 cpu->Reg[Rn] += index;
439 else
440 cpu->Reg[Rn] -= index;
441 }
442 }
443
LnSWoUB(RegisterPostIndexed)444 static void LnSWoUB(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
445 unsigned int& virt_addr) {
446 unsigned int Rn = BITS(inst, 16, 19);
447 unsigned int Rm = BITS(inst, 0, 3);
448 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
449
450 virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
451
452 if (CondPassed(cpu, BITS(inst, 28, 31))) {
453 if (U_BIT) {
454 cpu->Reg[Rn] += rm;
455 } else {
456 cpu->Reg[Rn] -= rm;
457 }
458 }
459 }
460
MLnS(ImmediateOffset)461 static void MLnS(ImmediateOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
462 unsigned int immedL = BITS(inst, 0, 3);
463 unsigned int immedH = BITS(inst, 8, 11);
464 unsigned int Rn = BITS(inst, 16, 19);
465 unsigned int addr;
466
467 unsigned int offset_8 = (immedH << 4) | immedL;
468
469 if (U_BIT)
470 addr = CHECK_READ_REG15_WA(cpu, Rn) + offset_8;
471 else
472 addr = CHECK_READ_REG15_WA(cpu, Rn) - offset_8;
473
474 virt_addr = addr;
475 }
476
MLnS(RegisterOffset)477 static void MLnS(RegisterOffset)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
478 unsigned int addr;
479 unsigned int Rn = BITS(inst, 16, 19);
480 unsigned int Rm = BITS(inst, 0, 3);
481 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
482 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
483
484 if (U_BIT)
485 addr = rn + rm;
486 else
487 addr = rn - rm;
488
489 virt_addr = addr;
490 }
491
MLnS(ImmediatePreIndexed)492 static void MLnS(ImmediatePreIndexed)(ARMul_State* cpu, unsigned int inst,
493 unsigned int& virt_addr) {
494 unsigned int Rn = BITS(inst, 16, 19);
495 unsigned int immedH = BITS(inst, 8, 11);
496 unsigned int immedL = BITS(inst, 0, 3);
497 unsigned int addr;
498 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
499 unsigned int offset_8 = (immedH << 4) | immedL;
500
501 if (U_BIT)
502 addr = rn + offset_8;
503 else
504 addr = rn - offset_8;
505
506 virt_addr = addr;
507
508 if (CondPassed(cpu, BITS(inst, 28, 31)))
509 cpu->Reg[Rn] = addr;
510 }
511
MLnS(ImmediatePostIndexed)512 static void MLnS(ImmediatePostIndexed)(ARMul_State* cpu, unsigned int inst,
513 unsigned int& virt_addr) {
514 unsigned int Rn = BITS(inst, 16, 19);
515 unsigned int immedH = BITS(inst, 8, 11);
516 unsigned int immedL = BITS(inst, 0, 3);
517 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
518
519 virt_addr = rn;
520
521 if (CondPassed(cpu, BITS(inst, 28, 31))) {
522 unsigned int offset_8 = (immedH << 4) | immedL;
523 if (U_BIT)
524 rn += offset_8;
525 else
526 rn -= offset_8;
527
528 cpu->Reg[Rn] = rn;
529 }
530 }
531
MLnS(RegisterPostIndexed)532 static void MLnS(RegisterPostIndexed)(ARMul_State* cpu, unsigned int inst,
533 unsigned int& virt_addr) {
534 unsigned int Rn = BITS(inst, 16, 19);
535 unsigned int Rm = BITS(inst, 0, 3);
536 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
537
538 virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
539
540 if (CondPassed(cpu, BITS(inst, 28, 31))) {
541 if (U_BIT)
542 cpu->Reg[Rn] += rm;
543 else
544 cpu->Reg[Rn] -= rm;
545 }
546 }
547
LdnStM(DecrementBefore)548 static void LdnStM(DecrementBefore)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
549 unsigned int Rn = BITS(inst, 16, 19);
550 unsigned int i = BITS(inst, 0, 15);
551 int count = 0;
552
553 while (i) {
554 if (i & 1)
555 count++;
556 i = i >> 1;
557 }
558
559 virt_addr = CHECK_READ_REG15_WA(cpu, Rn) - count * 4;
560
561 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21))
562 cpu->Reg[Rn] -= count * 4;
563 }
564
LdnStM(IncrementBefore)565 static void LdnStM(IncrementBefore)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
566 unsigned int Rn = BITS(inst, 16, 19);
567 unsigned int i = BITS(inst, 0, 15);
568 int count = 0;
569
570 while (i) {
571 if (i & 1)
572 count++;
573 i = i >> 1;
574 }
575
576 virt_addr = CHECK_READ_REG15_WA(cpu, Rn) + 4;
577
578 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21))
579 cpu->Reg[Rn] += count * 4;
580 }
581
LdnStM(IncrementAfter)582 static void LdnStM(IncrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
583 unsigned int Rn = BITS(inst, 16, 19);
584 unsigned int i = BITS(inst, 0, 15);
585 int count = 0;
586
587 while (i) {
588 if (i & 1)
589 count++;
590 i = i >> 1;
591 }
592
593 virt_addr = CHECK_READ_REG15_WA(cpu, Rn);
594
595 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21))
596 cpu->Reg[Rn] += count * 4;
597 }
598
LdnStM(DecrementAfter)599 static void LdnStM(DecrementAfter)(ARMul_State* cpu, unsigned int inst, unsigned int& virt_addr) {
600 unsigned int Rn = BITS(inst, 16, 19);
601 unsigned int i = BITS(inst, 0, 15);
602 int count = 0;
603 while (i) {
604 if (i & 1)
605 count++;
606 i = i >> 1;
607 }
608 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
609 unsigned int start_addr = rn - count * 4 + 4;
610
611 virt_addr = start_addr;
612
613 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
614 cpu->Reg[Rn] -= count * 4;
615 }
616 }
617
LnSWoUB(ScaledRegisterOffset)618 static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst,
619 unsigned int& virt_addr) {
620 unsigned int shift = BITS(inst, 5, 6);
621 unsigned int shift_imm = BITS(inst, 7, 11);
622 unsigned int Rn = BITS(inst, 16, 19);
623 unsigned int Rm = BITS(inst, 0, 3);
624 unsigned int index = 0;
625 unsigned int addr;
626 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
627 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
628
629 switch (shift) {
630 case 0:
631 index = rm << shift_imm;
632 break;
633 case 1:
634 if (shift_imm == 0) {
635 index = 0;
636 } else {
637 index = rm >> shift_imm;
638 }
639 break;
640 case 2:
641 if (shift_imm == 0) { // ASR #32
642 if (BIT(rm, 31) == 1)
643 index = 0xFFFFFFFF;
644 else
645 index = 0;
646 } else {
647 index = static_cast<int>(rm) >> shift_imm;
648 }
649 break;
650 case 3:
651 if (shift_imm == 0) {
652 index = (cpu->CFlag << 31) | (rm >> 1);
653 } else {
654 index = ROTATE_RIGHT_32(rm, shift_imm);
655 }
656 break;
657 }
658
659 if (U_BIT) {
660 addr = rn + index;
661 } else
662 addr = rn - index;
663
664 virt_addr = addr;
665 }
666
GetShifterOp(unsigned int inst)667 shtop_fp_t GetShifterOp(unsigned int inst) {
668 if (BIT(inst, 25)) {
669 return DPO(Immediate);
670 } else if (BITS(inst, 4, 11) == 0) {
671 return DPO(Register);
672 } else if (BITS(inst, 4, 6) == 0) {
673 return DPO(LogicalShiftLeftByImmediate);
674 } else if (BITS(inst, 4, 7) == 1) {
675 return DPO(LogicalShiftLeftByRegister);
676 } else if (BITS(inst, 4, 6) == 2) {
677 return DPO(LogicalShiftRightByImmediate);
678 } else if (BITS(inst, 4, 7) == 3) {
679 return DPO(LogicalShiftRightByRegister);
680 } else if (BITS(inst, 4, 6) == 4) {
681 return DPO(ArithmeticShiftRightByImmediate);
682 } else if (BITS(inst, 4, 7) == 5) {
683 return DPO(ArithmeticShiftRightByRegister);
684 } else if (BITS(inst, 4, 6) == 6) {
685 return DPO(RotateRightByImmediate);
686 } else if (BITS(inst, 4, 7) == 7) {
687 return DPO(RotateRightByRegister);
688 }
689 return nullptr;
690 }
691
GetAddressingOp(unsigned int inst)692 get_addr_fp_t GetAddressingOp(unsigned int inst) {
693 if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 0) {
694 return LnSWoUB(ImmediateOffset);
695 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) {
696 return LnSWoUB(RegisterOffset);
697 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
698 return LnSWoUB(ScaledRegisterOffset);
699 } else if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 1) {
700 return LnSWoUB(ImmediatePreIndexed);
701 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BITS(inst, 4, 11) == 0) {
702 return LnSWoUB(RegisterPreIndexed);
703 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BIT(inst, 4) == 0) {
704 return LnSWoUB(ScaledRegisterPreIndexed);
705 } else if (BITS(inst, 24, 27) == 4 && BIT(inst, 21) == 0) {
706 return LnSWoUB(ImmediatePostIndexed);
707 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) {
708 return LnSWoUB(RegisterPostIndexed);
709 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
710 return LnSWoUB(ScaledRegisterPostIndexed);
711 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 &&
712 BIT(inst, 4) == 1) {
713 return MLnS(ImmediateOffset);
714 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 &&
715 BIT(inst, 4) == 1) {
716 return MLnS(RegisterOffset);
717 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 &&
718 BIT(inst, 4) == 1) {
719 return MLnS(ImmediatePreIndexed);
720 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 &&
721 BIT(inst, 4) == 1) {
722 return MLnS(RegisterPreIndexed);
723 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 &&
724 BIT(inst, 4) == 1) {
725 return MLnS(ImmediatePostIndexed);
726 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 &&
727 BIT(inst, 4) == 1) {
728 return MLnS(RegisterPostIndexed);
729 } else if (BITS(inst, 23, 27) == 0x11) {
730 return LdnStM(IncrementAfter);
731 } else if (BITS(inst, 23, 27) == 0x13) {
732 return LdnStM(IncrementBefore);
733 } else if (BITS(inst, 23, 27) == 0x10) {
734 return LdnStM(DecrementAfter);
735 } else if (BITS(inst, 23, 27) == 0x12) {
736 return LdnStM(DecrementBefore);
737 }
738 return nullptr;
739 }
740
741 // Specialized for LDRT, LDRBT, STRT, and STRBT, which have specific addressing mode requirements
GetAddressingOpLoadStoreT(unsigned int inst)742 get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst) {
743 if (BITS(inst, 25, 27) == 2) {
744 return LnSWoUB(ImmediatePostIndexed);
745 } else if (BITS(inst, 25, 27) == 3) {
746 return LnSWoUB(ScaledRegisterPostIndexed);
747 }
748 // Reaching this would indicate the thumb version
749 // of this instruction, however the 3DS CPU doesn't
750 // support this variant (the 3DS CPU is only ARMv6K,
751 // while this variant is added in ARMv6T2).
752 // So it's sufficient for citra to not implement this.
753 return nullptr;
754 }
755
756 enum { FETCH_SUCCESS, FETCH_FAILURE };
757
DecodeThumbInstruction(u32 inst,u32 addr,u32 * arm_inst,u32 * inst_size,ARM_INST_PTR * ptr_inst_base)758 static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_inst, u32* inst_size,
759 ARM_INST_PTR* ptr_inst_base) {
760 // Check if in Thumb mode
761 ThumbDecodeStatus ret = TranslateThumbInstruction(addr, inst, arm_inst, inst_size);
762 if (ret == ThumbDecodeStatus::BRANCH) {
763 int inst_index;
764 int table_length = static_cast<int>(arm_instruction_trans_len);
765 u32 tinstr = GetThumbInstruction(inst, addr);
766
767 switch ((tinstr & 0xF800) >> 11) {
768 case 26:
769 case 27:
770 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)) {
771 inst_index = table_length - 4;
772 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
773 } else {
774 LOG_ERROR(Core_ARM11, "thumb decoder error");
775 }
776 break;
777 case 28:
778 // Branch 2, unconditional branch
779 inst_index = table_length - 5;
780 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
781 break;
782
783 case 8:
784 case 29:
785 // For BLX 1 thumb instruction
786 inst_index = table_length - 1;
787 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
788 break;
789 case 30:
790 // For BL 1 thumb instruction
791 inst_index = table_length - 3;
792 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
793 break;
794 case 31:
795 // For BL 2 thumb instruction
796 inst_index = table_length - 2;
797 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
798 break;
799 default:
800 ret = ThumbDecodeStatus::UNDEFINED;
801 break;
802 }
803 }
804 return ret;
805 }
806
807 enum { KEEP_GOING, FETCH_EXCEPTION };
808
809 MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64));
810
InterpreterTranslateInstruction(const ARMul_State * cpu,const u32 phys_addr,ARM_INST_PTR & inst_base)811 static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr,
812 ARM_INST_PTR& inst_base) {
813 u32 inst_size = 4;
814 u32 inst = cpu->memory.Read32(phys_addr & 0xFFFFFFFC);
815
816 // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM
817 // instruction
818 if (cpu->TFlag) {
819 u32 arm_inst;
820 ThumbDecodeStatus state =
821 DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
822
823 // We have translated the Thumb branch instruction in the Thumb decoder
824 if (state == ThumbDecodeStatus::BRANCH) {
825 return inst_size;
826 }
827 inst = arm_inst;
828 }
829
830 int idx;
831 if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
832 LOG_ERROR(Core_ARM11, "Decode failure.\tPC: [{:#010X}]\tInstruction: {:08X}", phys_addr,
833 inst);
834 LOG_ERROR(Core_ARM11, "cpsr={:#X}, cpu->TFlag={}, r15={:#010X}", cpu->Cpsr, cpu->TFlag,
835 cpu->Reg[15]);
836 CITRA_IGNORE_EXIT(-1);
837 }
838 inst_base = arm_instruction_trans[idx](inst, idx);
839
840 return inst_size;
841 }
842
InterpreterTranslateBlock(ARMul_State * cpu,std::size_t & bb_start,u32 addr)843 static int InterpreterTranslateBlock(ARMul_State* cpu, std::size_t& bb_start, u32 addr) {
844 MICROPROFILE_SCOPE(DynCom_Decode);
845
846 // Decode instruction, get index
847 // Allocate memory and init InsCream
848 // Go on next, until terminal instruction
849 // Save start addr of basicblock in CreamCache
850 ARM_INST_PTR inst_base = nullptr;
851 TransExtData ret = TransExtData::NON_BRANCH;
852 int size = 0; // instruction size of basic block
853 bb_start = trans_cache_buf_top;
854
855 u32 phys_addr = addr;
856 u32 pc_start = cpu->Reg[15];
857
858 while (ret == TransExtData::NON_BRANCH) {
859 unsigned int inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
860
861 size++;
862
863 phys_addr += inst_size;
864
865 if ((phys_addr & 0xfff) == 0) {
866 inst_base->br = TransExtData::END_OF_PAGE;
867 }
868 ret = inst_base->br;
869 };
870
871 cpu->instruction_cache[pc_start] = bb_start;
872
873 return KEEP_GOING;
874 }
875
InterpreterTranslateSingle(ARMul_State * cpu,std::size_t & bb_start,u32 addr)876 static int InterpreterTranslateSingle(ARMul_State* cpu, std::size_t& bb_start, u32 addr) {
877 MICROPROFILE_SCOPE(DynCom_Decode);
878
879 ARM_INST_PTR inst_base = nullptr;
880 bb_start = trans_cache_buf_top;
881
882 u32 phys_addr = addr;
883 u32 pc_start = cpu->Reg[15];
884
885 InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
886
887 if (inst_base->br == TransExtData::NON_BRANCH) {
888 inst_base->br = TransExtData::SINGLE_STEP;
889 }
890
891 cpu->instruction_cache[pc_start] = bb_start;
892
893 return KEEP_GOING;
894 }
895
clz(unsigned int x)896 static int clz(unsigned int x) {
897 int n;
898 if (x == 0)
899 return (32);
900 n = 1;
901 if ((x >> 16) == 0) {
902 n = n + 16;
903 x = x << 16;
904 }
905 if ((x >> 24) == 0) {
906 n = n + 8;
907 x = x << 8;
908 }
909 if ((x >> 28) == 0) {
910 n = n + 4;
911 x = x << 4;
912 }
913 if ((x >> 30) == 0) {
914 n = n + 2;
915 x = x << 2;
916 }
917 n = n - (x >> 31);
918 return n;
919 }
920
921 MICROPROFILE_DEFINE(DynCom_Execute, "DynCom", "Execute", MP_RGB(255, 0, 0));
922
InterpreterMainLoop(ARMul_State * cpu)923 unsigned InterpreterMainLoop(ARMul_State* cpu) {
924 MICROPROFILE_SCOPE(DynCom_Execute);
925
926 /// Nearest upcoming GDB code execution breakpoint, relative to the last dispatch's address.
927 GDBStub::BreakpointAddress breakpoint_data;
928 breakpoint_data.type = GDBStub::BreakpointType::None;
929
930 #undef RM
931 #undef RS
932
933 #define CRn inst_cream->crn
934 #define OPCODE_1 inst_cream->opcode_1
935 #define OPCODE_2 inst_cream->opcode_2
936 #define CRm inst_cream->crm
937 #define RD cpu->Reg[inst_cream->Rd]
938 #define RD2 cpu->Reg[inst_cream->Rd + 1]
939 #define RN cpu->Reg[inst_cream->Rn]
940 #define RM cpu->Reg[inst_cream->Rm]
941 #define RS cpu->Reg[inst_cream->Rs]
942 #define RDHI cpu->Reg[inst_cream->RdHi]
943 #define RDLO cpu->Reg[inst_cream->RdLo]
944 #define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4)
945 #define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24)
946 #define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand)
947
948 #define FETCH_INST \
949 if (inst_base->br != TransExtData::NON_BRANCH) \
950 goto DISPATCH; \
951 inst_base = (arm_inst*)&trans_cache_buf[ptr]
952
953 #define INC_PC(l) ptr += sizeof(arm_inst) + l
954 #define INC_PC_STUB ptr += sizeof(arm_inst)
955
956 #ifdef ANDROID
957 #define GDB_BP_CHECK
958 #else
959 #define GDB_BP_CHECK \
960 cpu->Cpsr &= ~(1 << 5); \
961 cpu->Cpsr |= cpu->TFlag << 5; \
962 if (GDBStub::IsServerEnabled()) { \
963 if (GDBStub::IsMemoryBreak()) { \
964 goto END; \
965 } else if (breakpoint_data.type != GDBStub::BreakpointType::None && \
966 PC == breakpoint_data.address) { \
967 cpu->RecordBreak(breakpoint_data); \
968 goto END; \
969 } \
970 }
971 #endif
972
973 // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a
974 // clunky switch statement.
975 #if defined __GNUC__ || defined __clang__
976 #define GOTO_NEXT_INST \
977 GDB_BP_CHECK; \
978 if (num_instrs >= cpu->NumInstrsToExecute) \
979 goto END; \
980 num_instrs++; \
981 goto* InstLabel[inst_base->idx]
982 #else
983 #define GOTO_NEXT_INST \
984 GDB_BP_CHECK; \
985 if (num_instrs >= cpu->NumInstrsToExecute) \
986 goto END; \
987 num_instrs++; \
988 switch (inst_base->idx) { \
989 case 0: \
990 goto VMLA_INST; \
991 case 1: \
992 goto VMLS_INST; \
993 case 2: \
994 goto VNMLA_INST; \
995 case 3: \
996 goto VNMLS_INST; \
997 case 4: \
998 goto VNMUL_INST; \
999 case 5: \
1000 goto VMUL_INST; \
1001 case 6: \
1002 goto VADD_INST; \
1003 case 7: \
1004 goto VSUB_INST; \
1005 case 8: \
1006 goto VDIV_INST; \
1007 case 9: \
1008 goto VMOVI_INST; \
1009 case 10: \
1010 goto VMOVR_INST; \
1011 case 11: \
1012 goto VABS_INST; \
1013 case 12: \
1014 goto VNEG_INST; \
1015 case 13: \
1016 goto VSQRT_INST; \
1017 case 14: \
1018 goto VCMP_INST; \
1019 case 15: \
1020 goto VCMP2_INST; \
1021 case 16: \
1022 goto VCVTBDS_INST; \
1023 case 17: \
1024 goto VCVTBFF_INST; \
1025 case 18: \
1026 goto VCVTBFI_INST; \
1027 case 19: \
1028 goto VMOVBRS_INST; \
1029 case 20: \
1030 goto VMSR_INST; \
1031 case 21: \
1032 goto VMOVBRC_INST; \
1033 case 22: \
1034 goto VMRS_INST; \
1035 case 23: \
1036 goto VMOVBCR_INST; \
1037 case 24: \
1038 goto VMOVBRRSS_INST; \
1039 case 25: \
1040 goto VMOVBRRD_INST; \
1041 case 26: \
1042 goto VSTR_INST; \
1043 case 27: \
1044 goto VPUSH_INST; \
1045 case 28: \
1046 goto VSTM_INST; \
1047 case 29: \
1048 goto VPOP_INST; \
1049 case 30: \
1050 goto VLDR_INST; \
1051 case 31: \
1052 goto VLDM_INST; \
1053 case 32: \
1054 goto SRS_INST; \
1055 case 33: \
1056 goto RFE_INST; \
1057 case 34: \
1058 goto BKPT_INST; \
1059 case 35: \
1060 goto BLX_INST; \
1061 case 36: \
1062 goto CPS_INST; \
1063 case 37: \
1064 goto PLD_INST; \
1065 case 38: \
1066 goto SETEND_INST; \
1067 case 39: \
1068 goto CLREX_INST; \
1069 case 40: \
1070 goto REV16_INST; \
1071 case 41: \
1072 goto USAD8_INST; \
1073 case 42: \
1074 goto SXTB_INST; \
1075 case 43: \
1076 goto UXTB_INST; \
1077 case 44: \
1078 goto SXTH_INST; \
1079 case 45: \
1080 goto SXTB16_INST; \
1081 case 46: \
1082 goto UXTH_INST; \
1083 case 47: \
1084 goto UXTB16_INST; \
1085 case 48: \
1086 goto CPY_INST; \
1087 case 49: \
1088 goto UXTAB_INST; \
1089 case 50: \
1090 goto SSUB8_INST; \
1091 case 51: \
1092 goto SHSUB8_INST; \
1093 case 52: \
1094 goto SSUBADDX_INST; \
1095 case 53: \
1096 goto STREX_INST; \
1097 case 54: \
1098 goto STREXB_INST; \
1099 case 55: \
1100 goto SWP_INST; \
1101 case 56: \
1102 goto SWPB_INST; \
1103 case 57: \
1104 goto SSUB16_INST; \
1105 case 58: \
1106 goto SSAT16_INST; \
1107 case 59: \
1108 goto SHSUBADDX_INST; \
1109 case 60: \
1110 goto QSUBADDX_INST; \
1111 case 61: \
1112 goto SHADDSUBX_INST; \
1113 case 62: \
1114 goto SHADD8_INST; \
1115 case 63: \
1116 goto SHADD16_INST; \
1117 case 64: \
1118 goto SEL_INST; \
1119 case 65: \
1120 goto SADDSUBX_INST; \
1121 case 66: \
1122 goto SADD8_INST; \
1123 case 67: \
1124 goto SADD16_INST; \
1125 case 68: \
1126 goto SHSUB16_INST; \
1127 case 69: \
1128 goto UMAAL_INST; \
1129 case 70: \
1130 goto UXTAB16_INST; \
1131 case 71: \
1132 goto USUBADDX_INST; \
1133 case 72: \
1134 goto USUB8_INST; \
1135 case 73: \
1136 goto USUB16_INST; \
1137 case 74: \
1138 goto USAT16_INST; \
1139 case 75: \
1140 goto USADA8_INST; \
1141 case 76: \
1142 goto UQSUBADDX_INST; \
1143 case 77: \
1144 goto UQSUB8_INST; \
1145 case 78: \
1146 goto UQSUB16_INST; \
1147 case 79: \
1148 goto UQADDSUBX_INST; \
1149 case 80: \
1150 goto UQADD8_INST; \
1151 case 81: \
1152 goto UQADD16_INST; \
1153 case 82: \
1154 goto SXTAB_INST; \
1155 case 83: \
1156 goto UHSUBADDX_INST; \
1157 case 84: \
1158 goto UHSUB8_INST; \
1159 case 85: \
1160 goto UHSUB16_INST; \
1161 case 86: \
1162 goto UHADDSUBX_INST; \
1163 case 87: \
1164 goto UHADD8_INST; \
1165 case 88: \
1166 goto UHADD16_INST; \
1167 case 89: \
1168 goto UADDSUBX_INST; \
1169 case 90: \
1170 goto UADD8_INST; \
1171 case 91: \
1172 goto UADD16_INST; \
1173 case 92: \
1174 goto SXTAH_INST; \
1175 case 93: \
1176 goto SXTAB16_INST; \
1177 case 94: \
1178 goto QADD8_INST; \
1179 case 95: \
1180 goto BXJ_INST; \
1181 case 96: \
1182 goto CLZ_INST; \
1183 case 97: \
1184 goto UXTAH_INST; \
1185 case 98: \
1186 goto BX_INST; \
1187 case 99: \
1188 goto REV_INST; \
1189 case 100: \
1190 goto BLX_INST; \
1191 case 101: \
1192 goto REVSH_INST; \
1193 case 102: \
1194 goto QADD_INST; \
1195 case 103: \
1196 goto QADD16_INST; \
1197 case 104: \
1198 goto QADDSUBX_INST; \
1199 case 105: \
1200 goto LDREX_INST; \
1201 case 106: \
1202 goto QDADD_INST; \
1203 case 107: \
1204 goto QDSUB_INST; \
1205 case 108: \
1206 goto QSUB_INST; \
1207 case 109: \
1208 goto LDREXB_INST; \
1209 case 110: \
1210 goto QSUB8_INST; \
1211 case 111: \
1212 goto QSUB16_INST; \
1213 case 112: \
1214 goto SMUAD_INST; \
1215 case 113: \
1216 goto SMMUL_INST; \
1217 case 114: \
1218 goto SMUSD_INST; \
1219 case 115: \
1220 goto SMLSD_INST; \
1221 case 116: \
1222 goto SMLSLD_INST; \
1223 case 117: \
1224 goto SMMLA_INST; \
1225 case 118: \
1226 goto SMMLS_INST; \
1227 case 119: \
1228 goto SMLALD_INST; \
1229 case 120: \
1230 goto SMLAD_INST; \
1231 case 121: \
1232 goto SMLAW_INST; \
1233 case 122: \
1234 goto SMULW_INST; \
1235 case 123: \
1236 goto PKHTB_INST; \
1237 case 124: \
1238 goto PKHBT_INST; \
1239 case 125: \
1240 goto SMUL_INST; \
1241 case 126: \
1242 goto SMLALXY_INST; \
1243 case 127: \
1244 goto SMLA_INST; \
1245 case 128: \
1246 goto MCRR_INST; \
1247 case 129: \
1248 goto MRRC_INST; \
1249 case 130: \
1250 goto CMP_INST; \
1251 case 131: \
1252 goto TST_INST; \
1253 case 132: \
1254 goto TEQ_INST; \
1255 case 133: \
1256 goto CMN_INST; \
1257 case 134: \
1258 goto SMULL_INST; \
1259 case 135: \
1260 goto UMULL_INST; \
1261 case 136: \
1262 goto UMLAL_INST; \
1263 case 137: \
1264 goto SMLAL_INST; \
1265 case 138: \
1266 goto MUL_INST; \
1267 case 139: \
1268 goto MLA_INST; \
1269 case 140: \
1270 goto SSAT_INST; \
1271 case 141: \
1272 goto USAT_INST; \
1273 case 142: \
1274 goto MRS_INST; \
1275 case 143: \
1276 goto MSR_INST; \
1277 case 144: \
1278 goto AND_INST; \
1279 case 145: \
1280 goto BIC_INST; \
1281 case 146: \
1282 goto LDM_INST; \
1283 case 147: \
1284 goto EOR_INST; \
1285 case 148: \
1286 goto ADD_INST; \
1287 case 149: \
1288 goto RSB_INST; \
1289 case 150: \
1290 goto RSC_INST; \
1291 case 151: \
1292 goto SBC_INST; \
1293 case 152: \
1294 goto ADC_INST; \
1295 case 153: \
1296 goto SUB_INST; \
1297 case 154: \
1298 goto ORR_INST; \
1299 case 155: \
1300 goto MVN_INST; \
1301 case 156: \
1302 goto MOV_INST; \
1303 case 157: \
1304 goto STM_INST; \
1305 case 158: \
1306 goto LDM_INST; \
1307 case 159: \
1308 goto LDRSH_INST; \
1309 case 160: \
1310 goto STM_INST; \
1311 case 161: \
1312 goto LDM_INST; \
1313 case 162: \
1314 goto LDRSB_INST; \
1315 case 163: \
1316 goto STRD_INST; \
1317 case 164: \
1318 goto LDRH_INST; \
1319 case 165: \
1320 goto STRH_INST; \
1321 case 166: \
1322 goto LDRD_INST; \
1323 case 167: \
1324 goto STRT_INST; \
1325 case 168: \
1326 goto STRBT_INST; \
1327 case 169: \
1328 goto LDRBT_INST; \
1329 case 170: \
1330 goto LDRT_INST; \
1331 case 171: \
1332 goto MRC_INST; \
1333 case 172: \
1334 goto MCR_INST; \
1335 case 173: \
1336 goto MSR_INST; \
1337 case 174: \
1338 goto MSR_INST; \
1339 case 175: \
1340 goto MSR_INST; \
1341 case 176: \
1342 goto MSR_INST; \
1343 case 177: \
1344 goto MSR_INST; \
1345 case 178: \
1346 goto LDRB_INST; \
1347 case 179: \
1348 goto STRB_INST; \
1349 case 180: \
1350 goto LDR_INST; \
1351 case 181: \
1352 goto LDRCOND_INST; \
1353 case 182: \
1354 goto STR_INST; \
1355 case 183: \
1356 goto CDP_INST; \
1357 case 184: \
1358 goto STC_INST; \
1359 case 185: \
1360 goto LDC_INST; \
1361 case 186: \
1362 goto LDREXD_INST; \
1363 case 187: \
1364 goto STREXD_INST; \
1365 case 188: \
1366 goto LDREXH_INST; \
1367 case 189: \
1368 goto STREXH_INST; \
1369 case 190: \
1370 goto NOP_INST; \
1371 case 191: \
1372 goto YIELD_INST; \
1373 case 192: \
1374 goto WFE_INST; \
1375 case 193: \
1376 goto WFI_INST; \
1377 case 194: \
1378 goto SEV_INST; \
1379 case 195: \
1380 goto SWI_INST; \
1381 case 196: \
1382 goto BBL_INST; \
1383 case 197: \
1384 goto B_2_THUMB; \
1385 case 198: \
1386 goto B_COND_THUMB; \
1387 case 199: \
1388 goto BL_1_THUMB; \
1389 case 200: \
1390 goto BL_2_THUMB; \
1391 case 201: \
1392 goto BLX_1_THUMB; \
1393 case 202: \
1394 goto DISPATCH; \
1395 case 203: \
1396 goto INIT_INST_LENGTH; \
1397 case 204: \
1398 goto END; \
1399 }
1400 #endif
1401
1402 #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0)
1403 #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1)
1404 #define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out)
1405
1406 #define SAVE_NZCVT \
1407 cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | (cpu->NFlag << 31) | (cpu->ZFlag << 30) | \
1408 (cpu->CFlag << 29) | (cpu->VFlag << 28) | (cpu->TFlag << 5)
1409 #define LOAD_NZCVT \
1410 cpu->NFlag = (cpu->Cpsr >> 31); \
1411 cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \
1412 cpu->CFlag = (cpu->Cpsr >> 29) & 1; \
1413 cpu->VFlag = (cpu->Cpsr >> 28) & 1; \
1414 cpu->TFlag = (cpu->Cpsr >> 5) & 1;
1415
1416 #define PC (cpu->Reg[15])
1417
1418 // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback
1419 // to a clunky switch statement.
1420 #if defined __GNUC__ || defined __clang__
1421 void* InstLabel[] = {&&VMLA_INST,
1422 &&VMLS_INST,
1423 &&VNMLA_INST,
1424 &&VNMLS_INST,
1425 &&VNMUL_INST,
1426 &&VMUL_INST,
1427 &&VADD_INST,
1428 &&VSUB_INST,
1429 &&VDIV_INST,
1430 &&VMOVI_INST,
1431 &&VMOVR_INST,
1432 &&VABS_INST,
1433 &&VNEG_INST,
1434 &&VSQRT_INST,
1435 &&VCMP_INST,
1436 &&VCMP2_INST,
1437 &&VCVTBDS_INST,
1438 &&VCVTBFF_INST,
1439 &&VCVTBFI_INST,
1440 &&VMOVBRS_INST,
1441 &&VMSR_INST,
1442 &&VMOVBRC_INST,
1443 &&VMRS_INST,
1444 &&VMOVBCR_INST,
1445 &&VMOVBRRSS_INST,
1446 &&VMOVBRRD_INST,
1447 &&VSTR_INST,
1448 &&VPUSH_INST,
1449 &&VSTM_INST,
1450 &&VPOP_INST,
1451 &&VLDR_INST,
1452 &&VLDM_INST,
1453
1454 &&SRS_INST,
1455 &&RFE_INST,
1456 &&BKPT_INST,
1457 &&BLX_INST,
1458 &&CPS_INST,
1459 &&PLD_INST,
1460 &&SETEND_INST,
1461 &&CLREX_INST,
1462 &&REV16_INST,
1463 &&USAD8_INST,
1464 &&SXTB_INST,
1465 &&UXTB_INST,
1466 &&SXTH_INST,
1467 &&SXTB16_INST,
1468 &&UXTH_INST,
1469 &&UXTB16_INST,
1470 &&CPY_INST,
1471 &&UXTAB_INST,
1472 &&SSUB8_INST,
1473 &&SHSUB8_INST,
1474 &&SSUBADDX_INST,
1475 &&STREX_INST,
1476 &&STREXB_INST,
1477 &&SWP_INST,
1478 &&SWPB_INST,
1479 &&SSUB16_INST,
1480 &&SSAT16_INST,
1481 &&SHSUBADDX_INST,
1482 &&QSUBADDX_INST,
1483 &&SHADDSUBX_INST,
1484 &&SHADD8_INST,
1485 &&SHADD16_INST,
1486 &&SEL_INST,
1487 &&SADDSUBX_INST,
1488 &&SADD8_INST,
1489 &&SADD16_INST,
1490 &&SHSUB16_INST,
1491 &&UMAAL_INST,
1492 &&UXTAB16_INST,
1493 &&USUBADDX_INST,
1494 &&USUB8_INST,
1495 &&USUB16_INST,
1496 &&USAT16_INST,
1497 &&USADA8_INST,
1498 &&UQSUBADDX_INST,
1499 &&UQSUB8_INST,
1500 &&UQSUB16_INST,
1501 &&UQADDSUBX_INST,
1502 &&UQADD8_INST,
1503 &&UQADD16_INST,
1504 &&SXTAB_INST,
1505 &&UHSUBADDX_INST,
1506 &&UHSUB8_INST,
1507 &&UHSUB16_INST,
1508 &&UHADDSUBX_INST,
1509 &&UHADD8_INST,
1510 &&UHADD16_INST,
1511 &&UADDSUBX_INST,
1512 &&UADD8_INST,
1513 &&UADD16_INST,
1514 &&SXTAH_INST,
1515 &&SXTAB16_INST,
1516 &&QADD8_INST,
1517 &&BXJ_INST,
1518 &&CLZ_INST,
1519 &&UXTAH_INST,
1520 &&BX_INST,
1521 &&REV_INST,
1522 &&BLX_INST,
1523 &&REVSH_INST,
1524 &&QADD_INST,
1525 &&QADD16_INST,
1526 &&QADDSUBX_INST,
1527 &&LDREX_INST,
1528 &&QDADD_INST,
1529 &&QDSUB_INST,
1530 &&QSUB_INST,
1531 &&LDREXB_INST,
1532 &&QSUB8_INST,
1533 &&QSUB16_INST,
1534 &&SMUAD_INST,
1535 &&SMMUL_INST,
1536 &&SMUSD_INST,
1537 &&SMLSD_INST,
1538 &&SMLSLD_INST,
1539 &&SMMLA_INST,
1540 &&SMMLS_INST,
1541 &&SMLALD_INST,
1542 &&SMLAD_INST,
1543 &&SMLAW_INST,
1544 &&SMULW_INST,
1545 &&PKHTB_INST,
1546 &&PKHBT_INST,
1547 &&SMUL_INST,
1548 &&SMLALXY_INST,
1549 &&SMLA_INST,
1550 &&MCRR_INST,
1551 &&MRRC_INST,
1552 &&CMP_INST,
1553 &&TST_INST,
1554 &&TEQ_INST,
1555 &&CMN_INST,
1556 &&SMULL_INST,
1557 &&UMULL_INST,
1558 &&UMLAL_INST,
1559 &&SMLAL_INST,
1560 &&MUL_INST,
1561 &&MLA_INST,
1562 &&SSAT_INST,
1563 &&USAT_INST,
1564 &&MRS_INST,
1565 &&MSR_INST,
1566 &&AND_INST,
1567 &&BIC_INST,
1568 &&LDM_INST,
1569 &&EOR_INST,
1570 &&ADD_INST,
1571 &&RSB_INST,
1572 &&RSC_INST,
1573 &&SBC_INST,
1574 &&ADC_INST,
1575 &&SUB_INST,
1576 &&ORR_INST,
1577 &&MVN_INST,
1578 &&MOV_INST,
1579 &&STM_INST,
1580 &&LDM_INST,
1581 &&LDRSH_INST,
1582 &&STM_INST,
1583 &&LDM_INST,
1584 &&LDRSB_INST,
1585 &&STRD_INST,
1586 &&LDRH_INST,
1587 &&STRH_INST,
1588 &&LDRD_INST,
1589 &&STRT_INST,
1590 &&STRBT_INST,
1591 &&LDRBT_INST,
1592 &&LDRT_INST,
1593 &&MRC_INST,
1594 &&MCR_INST,
1595 &&MSR_INST,
1596 &&MSR_INST,
1597 &&MSR_INST,
1598 &&MSR_INST,
1599 &&MSR_INST,
1600 &&LDRB_INST,
1601 &&STRB_INST,
1602 &&LDR_INST,
1603 &&LDRCOND_INST,
1604 &&STR_INST,
1605 &&CDP_INST,
1606 &&STC_INST,
1607 &&LDC_INST,
1608 &&LDREXD_INST,
1609 &&STREXD_INST,
1610 &&LDREXH_INST,
1611 &&STREXH_INST,
1612 &&NOP_INST,
1613 &&YIELD_INST,
1614 &&WFE_INST,
1615 &&WFI_INST,
1616 &&SEV_INST,
1617 &&SWI_INST,
1618 &&BBL_INST,
1619 &&B_2_THUMB,
1620 &&B_COND_THUMB,
1621 &&BL_1_THUMB,
1622 &&BL_2_THUMB,
1623 &&BLX_1_THUMB,
1624 &&DISPATCH,
1625 &&INIT_INST_LENGTH,
1626 &&END};
1627 #endif
1628 arm_inst* inst_base;
1629 unsigned int addr;
1630 unsigned int num_instrs = 0;
1631
1632 std::size_t ptr;
1633
1634 LOAD_NZCVT;
1635 DISPATCH : {
1636 if (!cpu->NirqSig) {
1637 if (!(cpu->Cpsr & 0x80)) {
1638 goto END;
1639 }
1640 }
1641
1642 if (cpu->TFlag)
1643 cpu->Reg[15] &= 0xfffffffe;
1644 else
1645 cpu->Reg[15] &= 0xfffffffc;
1646
1647 // Find the cached instruction cream, otherwise translate it...
1648 auto itr = cpu->instruction_cache.find(cpu->Reg[15]);
1649 if (itr != cpu->instruction_cache.end()) {
1650 ptr = itr->second;
1651 } else if (cpu->NumInstrsToExecute != 1) {
1652 if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
1653 goto END;
1654 } else {
1655 if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
1656 goto END;
1657 }
1658
1659 #ifndef ANDROID
1660 // Find breakpoint if one exists within the block
1661 if (GDBStub::IsConnected()) {
1662 breakpoint_data =
1663 GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute);
1664 }
1665 #endif
1666
1667 inst_base = (arm_inst*)&trans_cache_buf[ptr];
1668 GOTO_NEXT_INST;
1669 }
1670 ADC_INST : {
1671 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1672 adc_inst* const inst_cream = (adc_inst*)inst_base->component;
1673
1674 u32 rn_val = RN;
1675 if (inst_cream->Rn == 15)
1676 rn_val += 2 * cpu->GetInstructionSize();
1677
1678 bool carry;
1679 bool overflow;
1680 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
1681
1682 if (inst_cream->S && (inst_cream->Rd == 15)) {
1683 if (cpu->CurrentModeHasSPSR()) {
1684 cpu->Cpsr = cpu->Spsr_copy;
1685 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1686 LOAD_NZCVT;
1687 }
1688 } else if (inst_cream->S) {
1689 UPDATE_NFLAG(RD);
1690 UPDATE_ZFLAG(RD);
1691 cpu->CFlag = carry;
1692 cpu->VFlag = overflow;
1693 }
1694 if (inst_cream->Rd == 15) {
1695 INC_PC(sizeof(adc_inst));
1696 goto DISPATCH;
1697 }
1698 }
1699 cpu->Reg[15] += cpu->GetInstructionSize();
1700 INC_PC(sizeof(adc_inst));
1701 FETCH_INST;
1702 GOTO_NEXT_INST;
1703 }
1704 ADD_INST : {
1705 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1706 add_inst* const inst_cream = (add_inst*)inst_base->component;
1707
1708 u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
1709
1710 bool carry;
1711 bool overflow;
1712 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
1713
1714 if (inst_cream->S && (inst_cream->Rd == 15)) {
1715 if (cpu->CurrentModeHasSPSR()) {
1716 cpu->Cpsr = cpu->Spsr_copy;
1717 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
1718 LOAD_NZCVT;
1719 }
1720 } else if (inst_cream->S) {
1721 UPDATE_NFLAG(RD);
1722 UPDATE_ZFLAG(RD);
1723 cpu->CFlag = carry;
1724 cpu->VFlag = overflow;
1725 }
1726 if (inst_cream->Rd == 15) {
1727 INC_PC(sizeof(add_inst));
1728 goto DISPATCH;
1729 }
1730 }
1731 cpu->Reg[15] += cpu->GetInstructionSize();
1732 INC_PC(sizeof(add_inst));
1733 FETCH_INST;
1734 GOTO_NEXT_INST;
1735 }
1736 AND_INST : {
1737 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1738 and_inst* const inst_cream = (and_inst*)inst_base->component;
1739
1740 u32 lop = RN;
1741 u32 rop = SHIFTER_OPERAND;
1742
1743 if (inst_cream->Rn == 15)
1744 lop += 2 * cpu->GetInstructionSize();
1745
1746 RD = lop & rop;
1747
1748 if (inst_cream->S && (inst_cream->Rd == 15)) {
1749 if (cpu->CurrentModeHasSPSR()) {
1750 cpu->Cpsr = cpu->Spsr_copy;
1751 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
1752 LOAD_NZCVT;
1753 }
1754 } else if (inst_cream->S) {
1755 UPDATE_NFLAG(RD);
1756 UPDATE_ZFLAG(RD);
1757 UPDATE_CFLAG_WITH_SC;
1758 }
1759 if (inst_cream->Rd == 15) {
1760 INC_PC(sizeof(and_inst));
1761 goto DISPATCH;
1762 }
1763 }
1764 cpu->Reg[15] += cpu->GetInstructionSize();
1765 INC_PC(sizeof(and_inst));
1766 FETCH_INST;
1767 GOTO_NEXT_INST;
1768 }
1769 BBL_INST : {
1770 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1771 bbl_inst* inst_cream = (bbl_inst*)inst_base->component;
1772 if (inst_cream->L) {
1773 LINK_RTN_ADDR;
1774 }
1775 SET_PC;
1776 INC_PC(sizeof(bbl_inst));
1777 goto DISPATCH;
1778 }
1779 cpu->Reg[15] += cpu->GetInstructionSize();
1780 INC_PC(sizeof(bbl_inst));
1781 goto DISPATCH;
1782 }
1783 BIC_INST : {
1784 bic_inst* inst_cream = (bic_inst*)inst_base->component;
1785 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1786 u32 lop = RN;
1787 if (inst_cream->Rn == 15) {
1788 lop += 2 * cpu->GetInstructionSize();
1789 }
1790 u32 rop = SHIFTER_OPERAND;
1791 RD = lop & (~rop);
1792 if ((inst_cream->S) && (inst_cream->Rd == 15)) {
1793 if (cpu->CurrentModeHasSPSR()) {
1794 cpu->Cpsr = cpu->Spsr_copy;
1795 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
1796 LOAD_NZCVT;
1797 }
1798 } else if (inst_cream->S) {
1799 UPDATE_NFLAG(RD);
1800 UPDATE_ZFLAG(RD);
1801 UPDATE_CFLAG_WITH_SC;
1802 }
1803 if (inst_cream->Rd == 15) {
1804 INC_PC(sizeof(bic_inst));
1805 goto DISPATCH;
1806 }
1807 }
1808 cpu->Reg[15] += cpu->GetInstructionSize();
1809 INC_PC(sizeof(bic_inst));
1810 FETCH_INST;
1811 GOTO_NEXT_INST;
1812 }
1813 BKPT_INST : {
1814 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1815 bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
1816 LOG_DEBUG(Core_ARM11, "Breakpoint instruction hit. Immediate: {:#010X}", inst_cream->imm);
1817 }
1818 cpu->Reg[15] += cpu->GetInstructionSize();
1819 INC_PC(sizeof(bkpt_inst));
1820 FETCH_INST;
1821 GOTO_NEXT_INST;
1822 }
1823 BLX_INST : {
1824 blx_inst* inst_cream = (blx_inst*)inst_base->component;
1825 if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
1826 unsigned int inst = inst_cream->inst;
1827 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
1828 const u32 jump_address = cpu->Reg[inst_cream->val.Rm];
1829 cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
1830 if (cpu->TFlag)
1831 cpu->Reg[14] |= 0x1;
1832 cpu->Reg[15] = jump_address & 0xfffffffe;
1833 cpu->TFlag = jump_address & 0x1;
1834 } else {
1835 cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
1836 cpu->TFlag = 0x1;
1837 int signed_int = inst_cream->val.signed_immed_24;
1838 signed_int = (signed_int & 0x800000) ? (0x3F000000 | signed_int) : signed_int;
1839 signed_int = signed_int << 2;
1840 cpu->Reg[15] = cpu->Reg[15] + 8 + signed_int + (BIT(inst, 24) << 1);
1841 }
1842 INC_PC(sizeof(blx_inst));
1843 goto DISPATCH;
1844 }
1845 cpu->Reg[15] += cpu->GetInstructionSize();
1846 INC_PC(sizeof(blx_inst));
1847 goto DISPATCH;
1848 }
1849
1850 BX_INST:
1851 BXJ_INST : {
1852 // Note that only the 'fail' case of BXJ is emulated. This is because
1853 // the facilities for Jazelle emulation are not implemented.
1854 //
1855 // According to the ARM documentation on BXJ, if setting the J bit in the APSR
1856 // fails, then BXJ functions identically like a regular BX instruction.
1857 //
1858 // This is sufficient for citra, as the CPU for the 3DS does not implement Jazelle.
1859
1860 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1861 bx_inst* const inst_cream = (bx_inst*)inst_base->component;
1862
1863 u32 address = RM;
1864
1865 if (inst_cream->Rm == 15)
1866 address += 2 * cpu->GetInstructionSize();
1867
1868 cpu->TFlag = address & 1;
1869 cpu->Reg[15] = address & 0xfffffffe;
1870 INC_PC(sizeof(bx_inst));
1871 goto DISPATCH;
1872 }
1873
1874 cpu->Reg[15] += cpu->GetInstructionSize();
1875 INC_PC(sizeof(bx_inst));
1876 goto DISPATCH;
1877 }
1878
1879 CDP_INST : {
1880 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1881 // Undefined instruction here
1882 cpu->NumInstrsToExecute = 0;
1883 return num_instrs;
1884 }
1885 cpu->Reg[15] += cpu->GetInstructionSize();
1886 INC_PC(sizeof(cdp_inst));
1887 FETCH_INST;
1888 GOTO_NEXT_INST;
1889 }
1890
1891 CLREX_INST : {
1892 cpu->UnsetExclusiveMemoryAddress();
1893 cpu->Reg[15] += cpu->GetInstructionSize();
1894 INC_PC(sizeof(clrex_inst));
1895 FETCH_INST;
1896 GOTO_NEXT_INST;
1897 }
1898 CLZ_INST : {
1899 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1900 clz_inst* inst_cream = (clz_inst*)inst_base->component;
1901 RD = clz(RM);
1902 }
1903 cpu->Reg[15] += cpu->GetInstructionSize();
1904 INC_PC(sizeof(clz_inst));
1905 FETCH_INST;
1906 GOTO_NEXT_INST;
1907 }
1908 CMN_INST : {
1909 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1910 cmn_inst* const inst_cream = (cmn_inst*)inst_base->component;
1911
1912 u32 rn_val = RN;
1913 if (inst_cream->Rn == 15)
1914 rn_val += 2 * cpu->GetInstructionSize();
1915
1916 bool carry;
1917 bool overflow;
1918 u32 result = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
1919
1920 UPDATE_NFLAG(result);
1921 UPDATE_ZFLAG(result);
1922 cpu->CFlag = carry;
1923 cpu->VFlag = overflow;
1924 }
1925 cpu->Reg[15] += cpu->GetInstructionSize();
1926 INC_PC(sizeof(cmn_inst));
1927 FETCH_INST;
1928 GOTO_NEXT_INST;
1929 }
1930 CMP_INST : {
1931 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1932 cmp_inst* const inst_cream = (cmp_inst*)inst_base->component;
1933
1934 u32 rn_val = RN;
1935 if (inst_cream->Rn == 15)
1936 rn_val += 2 * cpu->GetInstructionSize();
1937
1938 bool carry;
1939 bool overflow;
1940 u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
1941
1942 UPDATE_NFLAG(result);
1943 UPDATE_ZFLAG(result);
1944 cpu->CFlag = carry;
1945 cpu->VFlag = overflow;
1946 }
1947 cpu->Reg[15] += cpu->GetInstructionSize();
1948 INC_PC(sizeof(cmp_inst));
1949 FETCH_INST;
1950 GOTO_NEXT_INST;
1951 }
1952 CPS_INST : {
1953 cps_inst* inst_cream = (cps_inst*)inst_base->component;
1954 u32 aif_val = 0;
1955 u32 aif_mask = 0;
1956 if (cpu->InAPrivilegedMode()) {
1957 if (inst_cream->imod1) {
1958 if (inst_cream->A) {
1959 aif_val |= (inst_cream->imod0 << 8);
1960 aif_mask |= 1 << 8;
1961 }
1962 if (inst_cream->I) {
1963 aif_val |= (inst_cream->imod0 << 7);
1964 aif_mask |= 1 << 7;
1965 }
1966 if (inst_cream->F) {
1967 aif_val |= (inst_cream->imod0 << 6);
1968 aif_mask |= 1 << 6;
1969 }
1970 aif_mask = ~aif_mask;
1971 cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val;
1972 }
1973 if (inst_cream->mmod) {
1974 cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode;
1975 cpu->ChangePrivilegeMode(inst_cream->mode);
1976 }
1977 }
1978 cpu->Reg[15] += cpu->GetInstructionSize();
1979 INC_PC(sizeof(cps_inst));
1980 FETCH_INST;
1981 GOTO_NEXT_INST;
1982 }
1983 CPY_INST : {
1984 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
1985 mov_inst* inst_cream = (mov_inst*)inst_base->component;
1986
1987 RD = SHIFTER_OPERAND;
1988 if (inst_cream->Rd == 15) {
1989 INC_PC(sizeof(mov_inst));
1990 goto DISPATCH;
1991 }
1992 }
1993 cpu->Reg[15] += cpu->GetInstructionSize();
1994 INC_PC(sizeof(mov_inst));
1995 FETCH_INST;
1996 GOTO_NEXT_INST;
1997 }
1998 EOR_INST : {
1999 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2000 eor_inst* inst_cream = (eor_inst*)inst_base->component;
2001
2002 u32 lop = RN;
2003 if (inst_cream->Rn == 15) {
2004 lop += 2 * cpu->GetInstructionSize();
2005 }
2006 u32 rop = SHIFTER_OPERAND;
2007 RD = lop ^ rop;
2008 if (inst_cream->S && (inst_cream->Rd == 15)) {
2009 if (cpu->CurrentModeHasSPSR()) {
2010 cpu->Cpsr = cpu->Spsr_copy;
2011 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2012 LOAD_NZCVT;
2013 }
2014 } else if (inst_cream->S) {
2015 UPDATE_NFLAG(RD);
2016 UPDATE_ZFLAG(RD);
2017 UPDATE_CFLAG_WITH_SC;
2018 }
2019 if (inst_cream->Rd == 15) {
2020 INC_PC(sizeof(eor_inst));
2021 goto DISPATCH;
2022 }
2023 }
2024 cpu->Reg[15] += cpu->GetInstructionSize();
2025 INC_PC(sizeof(eor_inst));
2026 FETCH_INST;
2027 GOTO_NEXT_INST;
2028 }
2029 LDC_INST : {
2030 // Instruction not implemented
2031 // LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
2032 cpu->Reg[15] += cpu->GetInstructionSize();
2033 INC_PC(sizeof(ldc_inst));
2034 FETCH_INST;
2035 GOTO_NEXT_INST;
2036 }
2037 LDM_INST : {
2038 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2039 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2040 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2041
2042 unsigned int inst = inst_cream->inst;
2043 if (BIT(inst, 22) && !BIT(inst, 15)) {
2044 for (int i = 0; i < 13; i++) {
2045 if (BIT(inst, i)) {
2046 cpu->Reg[i] = cpu->ReadMemory32(addr);
2047 addr += 4;
2048 }
2049 }
2050 if (BIT(inst, 13)) {
2051 if (cpu->Mode == USER32MODE)
2052 cpu->Reg[13] = cpu->ReadMemory32(addr);
2053 else
2054 cpu->Reg_usr[0] = cpu->ReadMemory32(addr);
2055
2056 addr += 4;
2057 }
2058 if (BIT(inst, 14)) {
2059 if (cpu->Mode == USER32MODE)
2060 cpu->Reg[14] = cpu->ReadMemory32(addr);
2061 else
2062 cpu->Reg_usr[1] = cpu->ReadMemory32(addr);
2063
2064 addr += 4;
2065 }
2066 } else if (!BIT(inst, 22)) {
2067 for (int i = 0; i < 16; i++) {
2068 if (BIT(inst, i)) {
2069 unsigned int ret = cpu->ReadMemory32(addr);
2070
2071 // For armv5t, should enter thumb when bits[0] is non-zero.
2072 if (i == 15) {
2073 cpu->TFlag = ret & 0x1;
2074 ret &= 0xFFFFFFFE;
2075 }
2076
2077 cpu->Reg[i] = ret;
2078 addr += 4;
2079 }
2080 }
2081 } else if (BIT(inst, 22) && BIT(inst, 15)) {
2082 for (int i = 0; i < 15; i++) {
2083 if (BIT(inst, i)) {
2084 cpu->Reg[i] = cpu->ReadMemory32(addr);
2085 addr += 4;
2086 }
2087 }
2088
2089 if (cpu->CurrentModeHasSPSR()) {
2090 cpu->Cpsr = cpu->Spsr_copy;
2091 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
2092 LOAD_NZCVT;
2093 }
2094
2095 cpu->Reg[15] = cpu->ReadMemory32(addr);
2096 }
2097
2098 if (BIT(inst, 15)) {
2099 INC_PC(sizeof(ldst_inst));
2100 goto DISPATCH;
2101 }
2102 }
2103 cpu->Reg[15] += cpu->GetInstructionSize();
2104 INC_PC(sizeof(ldst_inst));
2105 FETCH_INST;
2106 GOTO_NEXT_INST;
2107 }
2108 SXTH_INST : {
2109 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2110 sxth_inst* inst_cream = (sxth_inst*)inst_base->component;
2111
2112 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
2113 if (BIT(operand2, 15)) {
2114 operand2 |= 0xffff0000;
2115 } else {
2116 operand2 &= 0xffff;
2117 }
2118 RD = operand2;
2119 }
2120 cpu->Reg[15] += cpu->GetInstructionSize();
2121 INC_PC(sizeof(sxth_inst));
2122 FETCH_INST;
2123 GOTO_NEXT_INST;
2124 }
2125 LDR_INST : {
2126 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2127 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2128
2129 unsigned int value = cpu->ReadMemory32(addr);
2130 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
2131
2132 if (BITS(inst_cream->inst, 12, 15) == 15) {
2133 // For armv5t, should enter thumb when bits[0] is non-zero.
2134 cpu->TFlag = value & 0x1;
2135 cpu->Reg[15] &= 0xFFFFFFFE;
2136 INC_PC(sizeof(ldst_inst));
2137 goto DISPATCH;
2138 }
2139
2140 cpu->Reg[15] += cpu->GetInstructionSize();
2141 INC_PC(sizeof(ldst_inst));
2142 FETCH_INST;
2143 GOTO_NEXT_INST;
2144 }
2145 LDRCOND_INST : {
2146 if (CondPassed(cpu, inst_base->cond)) {
2147 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2148 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2149
2150 unsigned int value = cpu->ReadMemory32(addr);
2151 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
2152
2153 if (BITS(inst_cream->inst, 12, 15) == 15) {
2154 // For armv5t, should enter thumb when bits[0] is non-zero.
2155 cpu->TFlag = value & 0x1;
2156 cpu->Reg[15] &= 0xFFFFFFFE;
2157 INC_PC(sizeof(ldst_inst));
2158 goto DISPATCH;
2159 }
2160 }
2161 cpu->Reg[15] += cpu->GetInstructionSize();
2162 INC_PC(sizeof(ldst_inst));
2163 FETCH_INST;
2164 GOTO_NEXT_INST;
2165 }
2166 UXTH_INST : {
2167 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2168 uxth_inst* inst_cream = (uxth_inst*)inst_base->component;
2169 RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
2170 }
2171 cpu->Reg[15] += cpu->GetInstructionSize();
2172 INC_PC(sizeof(uxth_inst));
2173 FETCH_INST;
2174 GOTO_NEXT_INST;
2175 }
2176 UXTAH_INST : {
2177 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2178 uxtah_inst* inst_cream = (uxtah_inst*)inst_base->component;
2179 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
2180
2181 RD = RN + operand2;
2182 }
2183 cpu->Reg[15] += cpu->GetInstructionSize();
2184 INC_PC(sizeof(uxtah_inst));
2185 FETCH_INST;
2186 GOTO_NEXT_INST;
2187 }
2188 LDRB_INST : {
2189 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2190 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2191 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2192
2193 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory8(addr);
2194 }
2195 cpu->Reg[15] += cpu->GetInstructionSize();
2196 INC_PC(sizeof(ldst_inst));
2197 FETCH_INST;
2198 GOTO_NEXT_INST;
2199 }
2200 LDRBT_INST : {
2201 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2202 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2203 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2204
2205 const u32 dest_index = BITS(inst_cream->inst, 12, 15);
2206 const u32 previous_mode = cpu->Mode;
2207
2208 cpu->ChangePrivilegeMode(USER32MODE);
2209 const u8 value = cpu->ReadMemory8(addr);
2210 cpu->ChangePrivilegeMode(previous_mode);
2211
2212 cpu->Reg[dest_index] = value;
2213 }
2214 cpu->Reg[15] += cpu->GetInstructionSize();
2215 INC_PC(sizeof(ldst_inst));
2216 FETCH_INST;
2217 GOTO_NEXT_INST;
2218 }
2219 LDRD_INST : {
2220 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2221 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2222 // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 ||
2223 // addr[2] == 0)
2224 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2225
2226 // The 3DS doesn't have LPAE (Large Physical Access Extension), so it
2227 // wouldn't do this as a single read.
2228 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = cpu->ReadMemory32(addr);
2229 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = cpu->ReadMemory32(addr + 4);
2230
2231 // No dispatch since this operation should not modify R15
2232 }
2233 cpu->Reg[15] += 4;
2234 INC_PC(sizeof(ldst_inst));
2235 FETCH_INST;
2236 GOTO_NEXT_INST;
2237 }
2238
2239 LDREX_INST : {
2240 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2241 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2242 unsigned int read_addr = RN;
2243
2244 cpu->SetExclusiveMemoryAddress(read_addr);
2245
2246 RD = cpu->ReadMemory32(read_addr);
2247 }
2248 cpu->Reg[15] += cpu->GetInstructionSize();
2249 INC_PC(sizeof(generic_arm_inst));
2250 FETCH_INST;
2251 GOTO_NEXT_INST;
2252 }
2253 LDREXB_INST : {
2254 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2255 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2256 unsigned int read_addr = RN;
2257
2258 cpu->SetExclusiveMemoryAddress(read_addr);
2259
2260 RD = cpu->ReadMemory8(read_addr);
2261 }
2262 cpu->Reg[15] += cpu->GetInstructionSize();
2263 INC_PC(sizeof(generic_arm_inst));
2264 FETCH_INST;
2265 GOTO_NEXT_INST;
2266 }
2267 LDREXH_INST : {
2268 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2269 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2270 unsigned int read_addr = RN;
2271
2272 cpu->SetExclusiveMemoryAddress(read_addr);
2273
2274 RD = cpu->ReadMemory16(read_addr);
2275 }
2276 cpu->Reg[15] += cpu->GetInstructionSize();
2277 INC_PC(sizeof(generic_arm_inst));
2278 FETCH_INST;
2279 GOTO_NEXT_INST;
2280 }
2281 LDREXD_INST : {
2282 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2283 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
2284 unsigned int read_addr = RN;
2285
2286 cpu->SetExclusiveMemoryAddress(read_addr);
2287
2288 RD = cpu->ReadMemory32(read_addr);
2289 RD2 = cpu->ReadMemory32(read_addr + 4);
2290 }
2291 cpu->Reg[15] += cpu->GetInstructionSize();
2292 INC_PC(sizeof(generic_arm_inst));
2293 FETCH_INST;
2294 GOTO_NEXT_INST;
2295 }
2296 LDRH_INST : {
2297 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2298 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2299 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2300
2301 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = cpu->ReadMemory16(addr);
2302 }
2303 cpu->Reg[15] += cpu->GetInstructionSize();
2304 INC_PC(sizeof(ldst_inst));
2305 FETCH_INST;
2306 GOTO_NEXT_INST;
2307 }
2308 LDRSB_INST : {
2309 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2310 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2311 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2312 unsigned int value = cpu->ReadMemory8(addr);
2313 if (BIT(value, 7)) {
2314 value |= 0xffffff00;
2315 }
2316 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
2317 }
2318 cpu->Reg[15] += cpu->GetInstructionSize();
2319 INC_PC(sizeof(ldst_inst));
2320 FETCH_INST;
2321 GOTO_NEXT_INST;
2322 }
2323 LDRSH_INST : {
2324 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2325 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2326 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2327
2328 unsigned int value = cpu->ReadMemory16(addr);
2329 if (BIT(value, 15)) {
2330 value |= 0xffff0000;
2331 }
2332 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
2333 }
2334 cpu->Reg[15] += cpu->GetInstructionSize();
2335 INC_PC(sizeof(ldst_inst));
2336 FETCH_INST;
2337 GOTO_NEXT_INST;
2338 }
2339 LDRT_INST : {
2340 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2341 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
2342 inst_cream->get_addr(cpu, inst_cream->inst, addr);
2343
2344 const u32 dest_index = BITS(inst_cream->inst, 12, 15);
2345 const u32 previous_mode = cpu->Mode;
2346
2347 cpu->ChangePrivilegeMode(USER32MODE);
2348 const u32 value = cpu->ReadMemory32(addr);
2349 cpu->ChangePrivilegeMode(previous_mode);
2350
2351 cpu->Reg[dest_index] = value;
2352 }
2353 cpu->Reg[15] += cpu->GetInstructionSize();
2354 INC_PC(sizeof(ldst_inst));
2355 FETCH_INST;
2356 GOTO_NEXT_INST;
2357 }
2358 MCR_INST : {
2359 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2360 mcr_inst* inst_cream = (mcr_inst*)inst_base->component;
2361
2362 unsigned int inst = inst_cream->inst;
2363 if (inst_cream->Rd == 15) {
2364 DEBUG_MSG;
2365 } else {
2366 if (inst_cream->cp_num == 15)
2367 cpu->WriteCP15Register(RD, CRn, OPCODE_1, CRm, OPCODE_2);
2368 }
2369 }
2370 cpu->Reg[15] += cpu->GetInstructionSize();
2371 INC_PC(sizeof(mcr_inst));
2372 FETCH_INST;
2373 GOTO_NEXT_INST;
2374 }
2375
2376 MCRR_INST : {
2377 // Stubbed, as the MPCore doesn't have any registers that are accessible
2378 // through this instruction.
2379 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2380 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
2381
2382 LOG_ERROR(Core_ARM11, "MCRR executed | Coprocessor: {}, CRm {}, opc1: {}, Rt: {}, Rt2: {}",
2383 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt,
2384 inst_cream->rt2);
2385 }
2386
2387 cpu->Reg[15] += cpu->GetInstructionSize();
2388 INC_PC(sizeof(mcrr_inst));
2389 FETCH_INST;
2390 GOTO_NEXT_INST;
2391 }
2392
2393 MLA_INST : {
2394 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2395 mla_inst* inst_cream = (mla_inst*)inst_base->component;
2396
2397 u64 rm = RM;
2398 u64 rs = RS;
2399 u64 rn = RN;
2400
2401 RD = static_cast<u32>((rm * rs + rn) & 0xffffffff);
2402 if (inst_cream->S) {
2403 UPDATE_NFLAG(RD);
2404 UPDATE_ZFLAG(RD);
2405 }
2406 }
2407 cpu->Reg[15] += cpu->GetInstructionSize();
2408 INC_PC(sizeof(mla_inst));
2409 FETCH_INST;
2410 GOTO_NEXT_INST;
2411 }
2412 MOV_INST : {
2413 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2414 mov_inst* inst_cream = (mov_inst*)inst_base->component;
2415
2416 RD = SHIFTER_OPERAND;
2417 if (inst_cream->S && (inst_cream->Rd == 15)) {
2418 if (cpu->CurrentModeHasSPSR()) {
2419 cpu->Cpsr = cpu->Spsr_copy;
2420 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2421 LOAD_NZCVT;
2422 }
2423 } else if (inst_cream->S) {
2424 UPDATE_NFLAG(RD);
2425 UPDATE_ZFLAG(RD);
2426 UPDATE_CFLAG_WITH_SC;
2427 }
2428 if (inst_cream->Rd == 15) {
2429 INC_PC(sizeof(mov_inst));
2430 goto DISPATCH;
2431 }
2432 }
2433 cpu->Reg[15] += cpu->GetInstructionSize();
2434 INC_PC(sizeof(mov_inst));
2435 FETCH_INST;
2436 GOTO_NEXT_INST;
2437 }
2438 MRC_INST : {
2439 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2440 mrc_inst* inst_cream = (mrc_inst*)inst_base->component;
2441
2442 if (inst_cream->cp_num == 15) {
2443 const uint32_t value = cpu->ReadCP15Register(CRn, OPCODE_1, CRm, OPCODE_2);
2444
2445 if (inst_cream->Rd == 15) {
2446 cpu->Cpsr = (cpu->Cpsr & ~0xF0000000) | (value & 0xF0000000);
2447 LOAD_NZCVT;
2448 } else {
2449 RD = value;
2450 }
2451 }
2452 }
2453 cpu->Reg[15] += cpu->GetInstructionSize();
2454 INC_PC(sizeof(mrc_inst));
2455 FETCH_INST;
2456 GOTO_NEXT_INST;
2457 }
2458
2459 MRRC_INST : {
2460 // Stubbed, as the MPCore doesn't have any registers that are accessible
2461 // through this instruction.
2462 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2463 mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
2464
2465 LOG_ERROR(Core_ARM11, "MRRC executed | Coprocessor: {}, CRm {}, opc1: {}, Rt: {}, Rt2: {}",
2466 inst_cream->cp_num, inst_cream->crm, inst_cream->opcode_1, inst_cream->rt,
2467 inst_cream->rt2);
2468 }
2469
2470 cpu->Reg[15] += cpu->GetInstructionSize();
2471 INC_PC(sizeof(mcrr_inst));
2472 FETCH_INST;
2473 GOTO_NEXT_INST;
2474 }
2475
2476 MRS_INST : {
2477 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2478 mrs_inst* inst_cream = (mrs_inst*)inst_base->component;
2479
2480 if (inst_cream->R) {
2481 RD = cpu->Spsr_copy;
2482 } else {
2483 SAVE_NZCVT;
2484 RD = cpu->Cpsr;
2485 }
2486 }
2487 cpu->Reg[15] += cpu->GetInstructionSize();
2488 INC_PC(sizeof(mrs_inst));
2489 FETCH_INST;
2490 GOTO_NEXT_INST;
2491 }
2492 MSR_INST : {
2493 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2494 msr_inst* inst_cream = (msr_inst*)inst_base->component;
2495 const u32 UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
2496 unsigned int inst = inst_cream->inst;
2497 unsigned int operand;
2498
2499 if (BIT(inst, 25)) {
2500 int rot_imm = BITS(inst, 8, 11) * 2;
2501 operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
2502 } else {
2503 operand = cpu->Reg[BITS(inst, 0, 3)];
2504 }
2505 u32 byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) |
2506 (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
2507 u32 mask = 0;
2508 if (!inst_cream->R) {
2509 if (cpu->InAPrivilegedMode()) {
2510 if ((operand & StateMask) != 0) {
2511 /// UNPREDICTABLE
2512 DEBUG_MSG;
2513 } else
2514 mask = byte_mask & (UserMask | PrivMask);
2515 } else {
2516 mask = byte_mask & UserMask;
2517 }
2518 SAVE_NZCVT;
2519
2520 cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
2521 cpu->ChangePrivilegeMode(cpu->Cpsr & 0x1F);
2522 LOAD_NZCVT;
2523 } else {
2524 if (cpu->CurrentModeHasSPSR()) {
2525 mask = byte_mask & (UserMask | PrivMask | StateMask);
2526 cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask);
2527 }
2528 }
2529 }
2530 cpu->Reg[15] += cpu->GetInstructionSize();
2531 INC_PC(sizeof(msr_inst));
2532 FETCH_INST;
2533 GOTO_NEXT_INST;
2534 }
2535 MUL_INST : {
2536 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2537 mul_inst* inst_cream = (mul_inst*)inst_base->component;
2538
2539 u64 rm = RM;
2540 u64 rs = RS;
2541 RD = static_cast<u32>((rm * rs) & 0xffffffff);
2542 if (inst_cream->S) {
2543 UPDATE_NFLAG(RD);
2544 UPDATE_ZFLAG(RD);
2545 }
2546 }
2547 cpu->Reg[15] += cpu->GetInstructionSize();
2548 INC_PC(sizeof(mul_inst));
2549 FETCH_INST;
2550 GOTO_NEXT_INST;
2551 }
2552 MVN_INST : {
2553 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2554 mvn_inst* const inst_cream = (mvn_inst*)inst_base->component;
2555
2556 RD = ~SHIFTER_OPERAND;
2557
2558 if (inst_cream->S && (inst_cream->Rd == 15)) {
2559 if (cpu->CurrentModeHasSPSR()) {
2560 cpu->Cpsr = cpu->Spsr_copy;
2561 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2562 LOAD_NZCVT;
2563 }
2564 } else if (inst_cream->S) {
2565 UPDATE_NFLAG(RD);
2566 UPDATE_ZFLAG(RD);
2567 UPDATE_CFLAG_WITH_SC;
2568 }
2569 if (inst_cream->Rd == 15) {
2570 INC_PC(sizeof(mvn_inst));
2571 goto DISPATCH;
2572 }
2573 }
2574 cpu->Reg[15] += cpu->GetInstructionSize();
2575 INC_PC(sizeof(mvn_inst));
2576 FETCH_INST;
2577 GOTO_NEXT_INST;
2578 }
2579 ORR_INST : {
2580 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2581 orr_inst* const inst_cream = (orr_inst*)inst_base->component;
2582
2583 u32 lop = RN;
2584 u32 rop = SHIFTER_OPERAND;
2585
2586 if (inst_cream->Rn == 15)
2587 lop += 2 * cpu->GetInstructionSize();
2588
2589 RD = lop | rop;
2590
2591 if (inst_cream->S && (inst_cream->Rd == 15)) {
2592 if (cpu->CurrentModeHasSPSR()) {
2593 cpu->Cpsr = cpu->Spsr_copy;
2594 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2595 LOAD_NZCVT;
2596 }
2597 } else if (inst_cream->S) {
2598 UPDATE_NFLAG(RD);
2599 UPDATE_ZFLAG(RD);
2600 UPDATE_CFLAG_WITH_SC;
2601 }
2602 if (inst_cream->Rd == 15) {
2603 INC_PC(sizeof(orr_inst));
2604 goto DISPATCH;
2605 }
2606 }
2607 cpu->Reg[15] += cpu->GetInstructionSize();
2608 INC_PC(sizeof(orr_inst));
2609 FETCH_INST;
2610 GOTO_NEXT_INST;
2611 }
2612
2613 NOP_INST : {
2614 cpu->Reg[15] += cpu->GetInstructionSize();
2615 INC_PC_STUB;
2616 FETCH_INST;
2617 GOTO_NEXT_INST;
2618 }
2619
2620 PKHBT_INST : {
2621 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2622 pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
2623 RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000);
2624 }
2625 cpu->Reg[15] += cpu->GetInstructionSize();
2626 INC_PC(sizeof(pkh_inst));
2627 FETCH_INST;
2628 GOTO_NEXT_INST;
2629 }
2630
2631 PKHTB_INST : {
2632 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2633 pkh_inst* inst_cream = (pkh_inst*)inst_base->component;
2634 int shift_imm = inst_cream->imm ? inst_cream->imm : 31;
2635 RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000);
2636 }
2637 cpu->Reg[15] += cpu->GetInstructionSize();
2638 INC_PC(sizeof(pkh_inst));
2639 FETCH_INST;
2640 GOTO_NEXT_INST;
2641 }
2642
2643 PLD_INST : {
2644 // Not implemented. PLD is a hint instruction, so it's optional.
2645
2646 cpu->Reg[15] += cpu->GetInstructionSize();
2647 INC_PC(sizeof(pld_inst));
2648 FETCH_INST;
2649 GOTO_NEXT_INST;
2650 }
2651
2652 QADD_INST:
2653 QDADD_INST:
2654 QDSUB_INST:
2655 QSUB_INST : {
2656 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2657 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2658 const u8 op1 = inst_cream->op1;
2659 const u32 rm_val = RM;
2660 const u32 rn_val = RN;
2661
2662 u32 result = 0;
2663
2664 // QADD
2665 if (op1 == 0x00) {
2666 result = rm_val + rn_val;
2667
2668 if (AddOverflow(rm_val, rn_val, result)) {
2669 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2670 cpu->Cpsr |= (1 << 27);
2671 }
2672 }
2673 // QSUB
2674 else if (op1 == 0x01) {
2675 result = rm_val - rn_val;
2676
2677 if (SubOverflow(rm_val, rn_val, result)) {
2678 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2679 cpu->Cpsr |= (1 << 27);
2680 }
2681 }
2682 // QDADD
2683 else if (op1 == 0x02) {
2684 u32 mul = (rn_val * 2);
2685
2686 if (AddOverflow(rn_val, rn_val, rn_val * 2)) {
2687 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
2688 cpu->Cpsr |= (1 << 27);
2689 }
2690
2691 result = mul + rm_val;
2692
2693 if (AddOverflow(rm_val, mul, result)) {
2694 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2695 cpu->Cpsr |= (1 << 27);
2696 }
2697 }
2698 // QDSUB
2699 else if (op1 == 0x03) {
2700 u32 mul = (rn_val * 2);
2701
2702 if (AddOverflow(rn_val, rn_val, mul)) {
2703 mul = POS(mul) ? 0x80000000 : 0x7FFFFFFF;
2704 cpu->Cpsr |= (1 << 27);
2705 }
2706
2707 result = rm_val - mul;
2708
2709 if (SubOverflow(rm_val, mul, result)) {
2710 result = POS(result) ? 0x80000000 : 0x7FFFFFFF;
2711 cpu->Cpsr |= (1 << 27);
2712 }
2713 }
2714
2715 RD = result;
2716 }
2717
2718 cpu->Reg[15] += cpu->GetInstructionSize();
2719 INC_PC(sizeof(generic_arm_inst));
2720 FETCH_INST;
2721 GOTO_NEXT_INST;
2722 }
2723
2724 QADD8_INST:
2725 QADD16_INST:
2726 QADDSUBX_INST:
2727 QSUB8_INST:
2728 QSUB16_INST:
2729 QSUBADDX_INST : {
2730 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2731 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2732 const u16 rm_lo = (RM & 0xFFFF);
2733 const u16 rm_hi = ((RM >> 16) & 0xFFFF);
2734 const u16 rn_lo = (RN & 0xFFFF);
2735 const u16 rn_hi = ((RN >> 16) & 0xFFFF);
2736 const u8 op2 = inst_cream->op2;
2737
2738 u16 lo_result = 0;
2739 u16 hi_result = 0;
2740
2741 // QADD16
2742 if (op2 == 0x00) {
2743 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
2744 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
2745 }
2746 // QASX
2747 else if (op2 == 0x01) {
2748 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
2749 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
2750 }
2751 // QSAX
2752 else if (op2 == 0x02) {
2753 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
2754 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
2755 }
2756 // QSUB16
2757 else if (op2 == 0x03) {
2758 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
2759 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
2760 }
2761 // QADD8
2762 else if (op2 == 0x04) {
2763 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
2764 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
2765 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
2766 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
2767 }
2768 // QSUB8
2769 else if (op2 == 0x07) {
2770 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
2771 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
2772 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
2773 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
2774 }
2775
2776 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
2777 }
2778
2779 cpu->Reg[15] += cpu->GetInstructionSize();
2780 INC_PC(sizeof(generic_arm_inst));
2781 FETCH_INST;
2782 GOTO_NEXT_INST;
2783 }
2784
2785 REV_INST:
2786 REV16_INST:
2787 REVSH_INST : {
2788
2789 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2790 rev_inst* const inst_cream = (rev_inst*)inst_base->component;
2791
2792 const u8 op1 = inst_cream->op1;
2793 const u8 op2 = inst_cream->op2;
2794
2795 // REV
2796 if (op1 == 0x03 && op2 == 0x01) {
2797 RD = ((RM & 0xFF) << 24) | (((RM >> 8) & 0xFF) << 16) | (((RM >> 16) & 0xFF) << 8) |
2798 ((RM >> 24) & 0xFF);
2799 }
2800 // REV16
2801 else if (op1 == 0x03 && op2 == 0x05) {
2802 RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8) | ((RM & 0xFF0000) << 8) |
2803 ((RM & 0xFF000000) >> 8);
2804 }
2805 // REVSH
2806 else if (op1 == 0x07 && op2 == 0x05) {
2807 RD = ((RM & 0xFF) << 8) | ((RM & 0xFF00) >> 8);
2808 if (RD & 0x8000)
2809 RD |= 0xffff0000;
2810 }
2811 }
2812
2813 cpu->Reg[15] += cpu->GetInstructionSize();
2814 INC_PC(sizeof(rev_inst));
2815 FETCH_INST;
2816 GOTO_NEXT_INST;
2817 }
2818
2819 RFE_INST : {
2820 // RFE is unconditional
2821 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
2822
2823 u32 address = 0;
2824 inst_cream->get_addr(cpu, inst_cream->inst, address);
2825
2826 cpu->Cpsr = cpu->ReadMemory32(address);
2827 cpu->Reg[15] = cpu->ReadMemory32(address + 4);
2828
2829 INC_PC(sizeof(ldst_inst));
2830 goto DISPATCH;
2831 }
2832
2833 RSB_INST : {
2834 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2835 rsb_inst* const inst_cream = (rsb_inst*)inst_base->component;
2836
2837 u32 rn_val = RN;
2838 if (inst_cream->Rn == 15)
2839 rn_val += 2 * cpu->GetInstructionSize();
2840
2841 bool carry;
2842 bool overflow;
2843 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow);
2844
2845 if (inst_cream->S && (inst_cream->Rd == 15)) {
2846 if (cpu->CurrentModeHasSPSR()) {
2847 cpu->Cpsr = cpu->Spsr_copy;
2848 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2849 LOAD_NZCVT;
2850 }
2851 } else if (inst_cream->S) {
2852 UPDATE_NFLAG(RD);
2853 UPDATE_ZFLAG(RD);
2854 cpu->CFlag = carry;
2855 cpu->VFlag = overflow;
2856 }
2857 if (inst_cream->Rd == 15) {
2858 INC_PC(sizeof(rsb_inst));
2859 goto DISPATCH;
2860 }
2861 }
2862 cpu->Reg[15] += cpu->GetInstructionSize();
2863 INC_PC(sizeof(rsb_inst));
2864 FETCH_INST;
2865 GOTO_NEXT_INST;
2866 }
2867 RSC_INST : {
2868 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2869 rsc_inst* const inst_cream = (rsc_inst*)inst_base->component;
2870
2871 u32 rn_val = RN;
2872 if (inst_cream->Rn == 15)
2873 rn_val += 2 * cpu->GetInstructionSize();
2874
2875 bool carry;
2876 bool overflow;
2877 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
2878
2879 if (inst_cream->S && (inst_cream->Rd == 15)) {
2880 if (cpu->CurrentModeHasSPSR()) {
2881 cpu->Cpsr = cpu->Spsr_copy;
2882 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
2883 LOAD_NZCVT;
2884 }
2885 } else if (inst_cream->S) {
2886 UPDATE_NFLAG(RD);
2887 UPDATE_ZFLAG(RD);
2888 cpu->CFlag = carry;
2889 cpu->VFlag = overflow;
2890 }
2891 if (inst_cream->Rd == 15) {
2892 INC_PC(sizeof(rsc_inst));
2893 goto DISPATCH;
2894 }
2895 }
2896 cpu->Reg[15] += cpu->GetInstructionSize();
2897 INC_PC(sizeof(rsc_inst));
2898 FETCH_INST;
2899 GOTO_NEXT_INST;
2900 }
2901
2902 SADD8_INST:
2903 SSUB8_INST:
2904 SADD16_INST:
2905 SADDSUBX_INST:
2906 SSUBADDX_INST:
2907 SSUB16_INST : {
2908 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
2909 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2910 const u8 op2 = inst_cream->op2;
2911
2912 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
2913 const s16 rn_lo = (RN & 0xFFFF);
2914 const s16 rn_hi = ((RN >> 16) & 0xFFFF);
2915 const s16 rm_lo = (RM & 0xFFFF);
2916 const s16 rm_hi = ((RM >> 16) & 0xFFFF);
2917
2918 s32 lo_result = 0;
2919 s32 hi_result = 0;
2920
2921 // SADD16
2922 if (inst_cream->op2 == 0x00) {
2923 lo_result = (rn_lo + rm_lo);
2924 hi_result = (rn_hi + rm_hi);
2925 }
2926 // SASX
2927 else if (op2 == 0x01) {
2928 lo_result = (rn_lo - rm_hi);
2929 hi_result = (rn_hi + rm_lo);
2930 }
2931 // SSAX
2932 else if (op2 == 0x02) {
2933 lo_result = (rn_lo + rm_hi);
2934 hi_result = (rn_hi - rm_lo);
2935 }
2936 // SSUB16
2937 else if (op2 == 0x03) {
2938 lo_result = (rn_lo - rm_lo);
2939 hi_result = (rn_hi - rm_hi);
2940 }
2941
2942 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
2943
2944 if (lo_result >= 0) {
2945 cpu->Cpsr |= (1 << 16);
2946 cpu->Cpsr |= (1 << 17);
2947 } else {
2948 cpu->Cpsr &= ~(1 << 16);
2949 cpu->Cpsr &= ~(1 << 17);
2950 }
2951
2952 if (hi_result >= 0) {
2953 cpu->Cpsr |= (1 << 18);
2954 cpu->Cpsr |= (1 << 19);
2955 } else {
2956 cpu->Cpsr &= ~(1 << 18);
2957 cpu->Cpsr &= ~(1 << 19);
2958 }
2959 } else if (op2 == 0x04 || op2 == 0x07) {
2960 s32 lo_val1, lo_val2;
2961 s32 hi_val1, hi_val2;
2962
2963 // SADD8
2964 if (op2 == 0x04) {
2965 lo_val1 = (s32)(s8)(RN & 0xFF) + (s32)(s8)(RM & 0xFF);
2966 lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) + (s32)(s8)((RM >> 8) & 0xFF);
2967 hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) + (s32)(s8)((RM >> 16) & 0xFF);
2968 hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) + (s32)(s8)((RM >> 24) & 0xFF);
2969 }
2970 // SSUB8
2971 else {
2972 lo_val1 = (s32)(s8)(RN & 0xFF) - (s32)(s8)(RM & 0xFF);
2973 lo_val2 = (s32)(s8)((RN >> 8) & 0xFF) - (s32)(s8)((RM >> 8) & 0xFF);
2974 hi_val1 = (s32)(s8)((RN >> 16) & 0xFF) - (s32)(s8)((RM >> 16) & 0xFF);
2975 hi_val2 = (s32)(s8)((RN >> 24) & 0xFF) - (s32)(s8)((RM >> 24) & 0xFF);
2976 }
2977
2978 RD = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) |
2979 ((hi_val2 & 0xFF) << 24));
2980
2981 if (lo_val1 >= 0)
2982 cpu->Cpsr |= (1 << 16);
2983 else
2984 cpu->Cpsr &= ~(1 << 16);
2985
2986 if (lo_val2 >= 0)
2987 cpu->Cpsr |= (1 << 17);
2988 else
2989 cpu->Cpsr &= ~(1 << 17);
2990
2991 if (hi_val1 >= 0)
2992 cpu->Cpsr |= (1 << 18);
2993 else
2994 cpu->Cpsr &= ~(1 << 18);
2995
2996 if (hi_val2 >= 0)
2997 cpu->Cpsr |= (1 << 19);
2998 else
2999 cpu->Cpsr &= ~(1 << 19);
3000 }
3001 }
3002
3003 cpu->Reg[15] += cpu->GetInstructionSize();
3004 INC_PC(sizeof(generic_arm_inst));
3005 FETCH_INST;
3006 GOTO_NEXT_INST;
3007 }
3008
3009 SBC_INST : {
3010 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3011 sbc_inst* const inst_cream = (sbc_inst*)inst_base->component;
3012
3013 u32 rn_val = RN;
3014 if (inst_cream->Rn == 15)
3015 rn_val += 2 * cpu->GetInstructionSize();
3016
3017 bool carry;
3018 bool overflow;
3019 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
3020
3021 if (inst_cream->S && (inst_cream->Rd == 15)) {
3022 if (cpu->CurrentModeHasSPSR()) {
3023 cpu->Cpsr = cpu->Spsr_copy;
3024 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
3025 LOAD_NZCVT;
3026 }
3027 } else if (inst_cream->S) {
3028 UPDATE_NFLAG(RD);
3029 UPDATE_ZFLAG(RD);
3030 cpu->CFlag = carry;
3031 cpu->VFlag = overflow;
3032 }
3033 if (inst_cream->Rd == 15) {
3034 INC_PC(sizeof(sbc_inst));
3035 goto DISPATCH;
3036 }
3037 }
3038 cpu->Reg[15] += cpu->GetInstructionSize();
3039 INC_PC(sizeof(sbc_inst));
3040 FETCH_INST;
3041 GOTO_NEXT_INST;
3042 }
3043
3044 SEL_INST : {
3045 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3046 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
3047
3048 const u32 to = RM;
3049 const u32 from = RN;
3050 const u32 cpsr = cpu->Cpsr;
3051
3052 u32 result;
3053 if (cpsr & (1 << 16))
3054 result = from & 0xff;
3055 else
3056 result = to & 0xff;
3057
3058 if (cpsr & (1 << 17))
3059 result |= from & 0x0000ff00;
3060 else
3061 result |= to & 0x0000ff00;
3062
3063 if (cpsr & (1 << 18))
3064 result |= from & 0x00ff0000;
3065 else
3066 result |= to & 0x00ff0000;
3067
3068 if (cpsr & (1 << 19))
3069 result |= from & 0xff000000;
3070 else
3071 result |= to & 0xff000000;
3072
3073 RD = result;
3074 }
3075
3076 cpu->Reg[15] += cpu->GetInstructionSize();
3077 INC_PC(sizeof(generic_arm_inst));
3078 FETCH_INST;
3079 GOTO_NEXT_INST;
3080 }
3081
3082 SETEND_INST : {
3083 // SETEND is unconditional
3084 setend_inst* const inst_cream = (setend_inst*)inst_base->component;
3085 const bool big_endian = (inst_cream->set_bigend == 1);
3086
3087 if (big_endian)
3088 cpu->Cpsr |= (1 << 9);
3089 else
3090 cpu->Cpsr &= ~(1 << 9);
3091
3092 LOG_WARNING(Core_ARM11, "SETEND {} executed", big_endian ? "BE" : "LE");
3093
3094 cpu->Reg[15] += cpu->GetInstructionSize();
3095 INC_PC(sizeof(setend_inst));
3096 FETCH_INST;
3097 GOTO_NEXT_INST;
3098 }
3099
3100 SEV_INST : {
3101 // Stubbed, as SEV is a hint instruction.
3102 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3103 LOG_TRACE(Core_ARM11, "SEV executed.");
3104 }
3105
3106 cpu->Reg[15] += cpu->GetInstructionSize();
3107 INC_PC_STUB;
3108 FETCH_INST;
3109 GOTO_NEXT_INST;
3110 }
3111
3112 SHADD8_INST:
3113 SHADD16_INST:
3114 SHADDSUBX_INST:
3115 SHSUB8_INST:
3116 SHSUB16_INST:
3117 SHSUBADDX_INST : {
3118 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3119 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
3120
3121 const u8 op2 = inst_cream->op2;
3122 const u32 rm_val = RM;
3123 const u32 rn_val = RN;
3124
3125 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
3126 s32 lo_result = 0;
3127 s32 hi_result = 0;
3128
3129 // SHADD16
3130 if (op2 == 0x00) {
3131 lo_result = ((s16)(rn_val & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1;
3132 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3133 }
3134 // SHASX
3135 else if (op2 == 0x01) {
3136 lo_result = ((s16)(rn_val & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3137 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) + (s16)(rm_val & 0xFFFF)) >> 1;
3138 }
3139 // SHSAX
3140 else if (op2 == 0x02) {
3141 lo_result = ((s16)(rn_val & 0xFFFF) + (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3142 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
3143 }
3144 // SHSUB16
3145 else if (op2 == 0x03) {
3146 lo_result = ((s16)(rn_val & 0xFFFF) - (s16)(rm_val & 0xFFFF)) >> 1;
3147 hi_result = ((s16)((rn_val >> 16) & 0xFFFF) - (s16)((rm_val >> 16) & 0xFFFF)) >> 1;
3148 }
3149
3150 RD = ((lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16));
3151 } else if (op2 == 0x04 || op2 == 0x07) {
3152 s16 lo_val1, lo_val2;
3153 s16 hi_val1, hi_val2;
3154
3155 // SHADD8
3156 if (op2 == 0x04) {
3157 lo_val1 = ((s8)(rn_val & 0xFF) + (s8)(rm_val & 0xFF)) >> 1;
3158 lo_val2 = ((s8)((rn_val >> 8) & 0xFF) + (s8)((rm_val >> 8) & 0xFF)) >> 1;
3159
3160 hi_val1 = ((s8)((rn_val >> 16) & 0xFF) + (s8)((rm_val >> 16) & 0xFF)) >> 1;
3161 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) + (s8)((rm_val >> 24) & 0xFF)) >> 1;
3162 }
3163 // SHSUB8
3164 else {
3165 lo_val1 = ((s8)(rn_val & 0xFF) - (s8)(rm_val & 0xFF)) >> 1;
3166 lo_val2 = ((s8)((rn_val >> 8) & 0xFF) - (s8)((rm_val >> 8) & 0xFF)) >> 1;
3167
3168 hi_val1 = ((s8)((rn_val >> 16) & 0xFF) - (s8)((rm_val >> 16) & 0xFF)) >> 1;
3169 hi_val2 = ((s8)((rn_val >> 24) & 0xFF) - (s8)((rm_val >> 24) & 0xFF)) >> 1;
3170 }
3171
3172 RD = (lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) |
3173 ((hi_val2 & 0xFF) << 24);
3174 }
3175 }
3176
3177 cpu->Reg[15] += cpu->GetInstructionSize();
3178 INC_PC(sizeof(generic_arm_inst));
3179 FETCH_INST;
3180 GOTO_NEXT_INST;
3181 }
3182
3183 SMLA_INST : {
3184 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3185 smla_inst* inst_cream = (smla_inst*)inst_base->component;
3186 s32 operand1, operand2;
3187 if (inst_cream->x == 0)
3188 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
3189 else
3190 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
3191
3192 if (inst_cream->y == 0)
3193 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
3194 else
3195 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
3196
3197 u32 product = operand1 * operand2;
3198 u32 result = product + RN;
3199 if (AddOverflow(product, RN, result))
3200 cpu->Cpsr |= (1 << 27);
3201 RD = result;
3202 }
3203 cpu->Reg[15] += cpu->GetInstructionSize();
3204 INC_PC(sizeof(smla_inst));
3205 FETCH_INST;
3206 GOTO_NEXT_INST;
3207 }
3208
3209 SMLAD_INST:
3210 SMLSD_INST:
3211 SMUAD_INST:
3212 SMUSD_INST : {
3213 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3214 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3215 const u8 op2 = inst_cream->op2;
3216
3217 u32 rm_val = cpu->Reg[inst_cream->Rm];
3218 const u32 rn_val = cpu->Reg[inst_cream->Rn];
3219
3220 if (inst_cream->m)
3221 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
3222
3223 const s16 rm_lo = (rm_val & 0xFFFF);
3224 const s16 rm_hi = ((rm_val >> 16) & 0xFFFF);
3225 const s16 rn_lo = (rn_val & 0xFFFF);
3226 const s16 rn_hi = ((rn_val >> 16) & 0xFFFF);
3227
3228 const u32 product1 = (rn_lo * rm_lo);
3229 const u32 product2 = (rn_hi * rm_hi);
3230
3231 // SMUAD and SMLAD
3232 if (BIT(op2, 1) == 0) {
3233 u32 rd_val = (product1 + product2);
3234
3235 if (inst_cream->Ra != 15) {
3236 rd_val += cpu->Reg[inst_cream->Ra];
3237
3238 if (ARMul_AddOverflowQ(product1 + product2, cpu->Reg[inst_cream->Ra]))
3239 cpu->Cpsr |= (1 << 27);
3240 }
3241
3242 RD = rd_val;
3243
3244 if (ARMul_AddOverflowQ(product1, product2))
3245 cpu->Cpsr |= (1 << 27);
3246 }
3247 // SMUSD and SMLSD
3248 else {
3249 u32 rd_val = (product1 - product2);
3250
3251 if (inst_cream->Ra != 15) {
3252 rd_val += cpu->Reg[inst_cream->Ra];
3253
3254 if (ARMul_AddOverflowQ(product1 - product2, cpu->Reg[inst_cream->Ra]))
3255 cpu->Cpsr |= (1 << 27);
3256 }
3257
3258 RD = rd_val;
3259 }
3260 }
3261
3262 cpu->Reg[15] += cpu->GetInstructionSize();
3263 INC_PC(sizeof(smlad_inst));
3264 FETCH_INST;
3265 GOTO_NEXT_INST;
3266 }
3267
3268 SMLAL_INST : {
3269 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3270 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
3271 long long int rm = RM;
3272 long long int rs = RS;
3273 if (BIT(rm, 31)) {
3274 rm |= 0xffffffff00000000LL;
3275 }
3276 if (BIT(rs, 31)) {
3277 rs |= 0xffffffff00000000LL;
3278 }
3279 long long int rst = rm * rs;
3280 long long int rdhi32 = RDHI;
3281 long long int hilo = (rdhi32 << 32) + RDLO;
3282 rst += hilo;
3283 RDLO = BITS(rst, 0, 31);
3284 RDHI = BITS(rst, 32, 63);
3285 if (inst_cream->S) {
3286 cpu->NFlag = BIT(RDHI, 31);
3287 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
3288 }
3289 }
3290 cpu->Reg[15] += cpu->GetInstructionSize();
3291 INC_PC(sizeof(umlal_inst));
3292 FETCH_INST;
3293 GOTO_NEXT_INST;
3294 }
3295
3296 SMLALXY_INST : {
3297 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3298 smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component;
3299
3300 u64 operand1 = RN;
3301 u64 operand2 = RM;
3302
3303 if (inst_cream->x != 0)
3304 operand1 >>= 16;
3305 if (inst_cream->y != 0)
3306 operand2 >>= 16;
3307 operand1 &= 0xFFFF;
3308 if (operand1 & 0x8000)
3309 operand1 -= 65536;
3310 operand2 &= 0xFFFF;
3311 if (operand2 & 0x8000)
3312 operand2 -= 65536;
3313
3314 u64 dest = ((u64)RDHI << 32 | RDLO) + (operand1 * operand2);
3315 RDLO = (dest & 0xFFFFFFFF);
3316 RDHI = ((dest >> 32) & 0xFFFFFFFF);
3317 }
3318
3319 cpu->Reg[15] += cpu->GetInstructionSize();
3320 INC_PC(sizeof(smlalxy_inst));
3321 FETCH_INST;
3322 GOTO_NEXT_INST;
3323 }
3324
3325 SMLAW_INST : {
3326 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3327 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3328
3329 const u32 rm_val = RM;
3330 const u32 rn_val = RN;
3331 const u32 ra_val = cpu->Reg[inst_cream->Ra];
3332 const bool high = (inst_cream->m == 1);
3333
3334 const s16 operand2 = (high) ? ((rm_val >> 16) & 0xFFFF) : (rm_val & 0xFFFF);
3335 const s64 result = (s64)(s32)rn_val * (s64)(s32)operand2 + ((s64)(s32)ra_val << 16);
3336
3337 RD = BITS(result, 16, 47);
3338
3339 if ((result >> 16) != (s32)RD)
3340 cpu->Cpsr |= (1 << 27);
3341 }
3342
3343 cpu->Reg[15] += cpu->GetInstructionSize();
3344 INC_PC(sizeof(smlad_inst));
3345 FETCH_INST;
3346 GOTO_NEXT_INST;
3347 }
3348
3349 SMLALD_INST:
3350 SMLSLD_INST : {
3351 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3352 smlald_inst* const inst_cream = (smlald_inst*)inst_base->component;
3353
3354 const bool do_swap = (inst_cream->swap == 1);
3355 const u32 rdlo_val = RDLO;
3356 const u32 rdhi_val = RDHI;
3357 const u32 rn_val = RN;
3358 u32 rm_val = RM;
3359
3360 if (do_swap)
3361 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
3362
3363 const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF);
3364 const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF);
3365 s64 result;
3366
3367 // SMLALD
3368 if (BIT(inst_cream->op2, 1) == 0) {
3369 result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
3370 }
3371 // SMLSLD
3372 else {
3373 result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
3374 }
3375
3376 RDLO = (result & 0xFFFFFFFF);
3377 RDHI = ((result >> 32) & 0xFFFFFFFF);
3378 }
3379
3380 cpu->Reg[15] += cpu->GetInstructionSize();
3381 INC_PC(sizeof(smlald_inst));
3382 FETCH_INST;
3383 GOTO_NEXT_INST;
3384 }
3385
3386 SMMLA_INST:
3387 SMMLS_INST:
3388 SMMUL_INST : {
3389 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3390 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3391
3392 const u32 rm_val = RM;
3393 const u32 rn_val = RN;
3394 const bool do_round = (inst_cream->m == 1);
3395
3396 // Assume SMMUL by default.
3397 s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val;
3398
3399 if (inst_cream->Ra != 15) {
3400 const u32 ra_val = cpu->Reg[inst_cream->Ra];
3401
3402 // SMMLA, otherwise SMMLS
3403 if (BIT(inst_cream->op2, 1) == 0)
3404 result += ((s64)ra_val << 32);
3405 else
3406 result = ((s64)ra_val << 32) - result;
3407 }
3408
3409 if (do_round)
3410 result += 0x80000000;
3411
3412 RD = ((result >> 32) & 0xFFFFFFFF);
3413 }
3414
3415 cpu->Reg[15] += cpu->GetInstructionSize();
3416 INC_PC(sizeof(smlad_inst));
3417 FETCH_INST;
3418 GOTO_NEXT_INST;
3419 }
3420
3421 SMUL_INST : {
3422 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3423 smul_inst* inst_cream = (smul_inst*)inst_base->component;
3424 u32 operand1, operand2;
3425 if (inst_cream->x == 0)
3426 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
3427 else
3428 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
3429
3430 if (inst_cream->y == 0)
3431 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
3432 else
3433 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
3434 RD = operand1 * operand2;
3435 }
3436 cpu->Reg[15] += cpu->GetInstructionSize();
3437 INC_PC(sizeof(smul_inst));
3438 FETCH_INST;
3439 GOTO_NEXT_INST;
3440 }
3441 SMULL_INST : {
3442 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3443 umull_inst* inst_cream = (umull_inst*)inst_base->component;
3444 s64 rm = RM;
3445 s64 rs = RS;
3446 if (BIT(rm, 31)) {
3447 rm |= 0xffffffff00000000LL;
3448 }
3449 if (BIT(rs, 31)) {
3450 rs |= 0xffffffff00000000LL;
3451 }
3452 s64 rst = rm * rs;
3453 RDHI = BITS(rst, 32, 63);
3454 RDLO = BITS(rst, 0, 31);
3455
3456 if (inst_cream->S) {
3457 cpu->NFlag = BIT(RDHI, 31);
3458 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
3459 }
3460 }
3461 cpu->Reg[15] += cpu->GetInstructionSize();
3462 INC_PC(sizeof(umull_inst));
3463 FETCH_INST;
3464 GOTO_NEXT_INST;
3465 }
3466
3467 SMULW_INST : {
3468 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3469 smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
3470
3471 s16 rm = (inst_cream->m == 1) ? ((RM >> 16) & 0xFFFF) : (RM & 0xFFFF);
3472
3473 s64 result = (s64)rm * (s64)(s32)RN;
3474 RD = BITS(result, 16, 47);
3475 }
3476 cpu->Reg[15] += cpu->GetInstructionSize();
3477 INC_PC(sizeof(smlad_inst));
3478 FETCH_INST;
3479 GOTO_NEXT_INST;
3480 }
3481
3482 SRS_INST : {
3483 // SRS is unconditional
3484 ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
3485
3486 u32 address = 0;
3487 inst_cream->get_addr(cpu, inst_cream->inst, address);
3488
3489 cpu->WriteMemory32(address + 0, cpu->Reg[14]);
3490 cpu->WriteMemory32(address + 4, cpu->Spsr_copy);
3491
3492 cpu->Reg[15] += cpu->GetInstructionSize();
3493 INC_PC(sizeof(ldst_inst));
3494 FETCH_INST;
3495 GOTO_NEXT_INST;
3496 }
3497
3498 SSAT_INST : {
3499 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3500 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
3501
3502 u8 shift_type = inst_cream->shift_type;
3503 u8 shift_amount = inst_cream->imm5;
3504 u32 rn_val = RN;
3505
3506 // 32-bit ASR is encoded as an amount of 0.
3507 if (shift_type == 1 && shift_amount == 0)
3508 shift_amount = 31;
3509
3510 if (shift_type == 0)
3511 rn_val <<= shift_amount;
3512 else if (shift_type == 1)
3513 rn_val = ((s32)rn_val >> shift_amount);
3514
3515 bool saturated = false;
3516 rn_val = ARMul_SignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
3517
3518 if (saturated)
3519 cpu->Cpsr |= (1 << 27);
3520
3521 RD = rn_val;
3522 }
3523
3524 cpu->Reg[15] += cpu->GetInstructionSize();
3525 INC_PC(sizeof(ssat_inst));
3526 FETCH_INST;
3527 GOTO_NEXT_INST;
3528 }
3529
3530 SSAT16_INST : {
3531 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3532 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
3533 const u8 saturate_to = inst_cream->sat_imm;
3534
3535 bool sat1 = false;
3536 bool sat2 = false;
3537
3538 RD = (ARMul_SignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) |
3539 ARMul_SignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16;
3540
3541 if (sat1 || sat2)
3542 cpu->Cpsr |= (1 << 27);
3543 }
3544
3545 cpu->Reg[15] += cpu->GetInstructionSize();
3546 INC_PC(sizeof(ssat_inst));
3547 FETCH_INST;
3548 GOTO_NEXT_INST;
3549 }
3550
3551 STC_INST : {
3552 // Instruction not implemented
3553 // LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
3554 cpu->Reg[15] += cpu->GetInstructionSize();
3555 INC_PC(sizeof(stc_inst));
3556 FETCH_INST;
3557 GOTO_NEXT_INST;
3558 }
3559 STM_INST : {
3560 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3561 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3562 unsigned int inst = inst_cream->inst;
3563
3564 unsigned int Rn = BITS(inst, 16, 19);
3565 unsigned int old_RN = cpu->Reg[Rn];
3566
3567 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3568 if (BIT(inst_cream->inst, 22) == 1) {
3569 for (int i = 0; i < 13; i++) {
3570 if (BIT(inst_cream->inst, i)) {
3571 cpu->WriteMemory32(addr, cpu->Reg[i]);
3572 addr += 4;
3573 }
3574 }
3575 if (BIT(inst_cream->inst, 13)) {
3576 if (cpu->Mode == USER32MODE)
3577 cpu->WriteMemory32(addr, cpu->Reg[13]);
3578 else
3579 cpu->WriteMemory32(addr, cpu->Reg_usr[0]);
3580
3581 addr += 4;
3582 }
3583 if (BIT(inst_cream->inst, 14)) {
3584 if (cpu->Mode == USER32MODE)
3585 cpu->WriteMemory32(addr, cpu->Reg[14]);
3586 else
3587 cpu->WriteMemory32(addr, cpu->Reg_usr[1]);
3588
3589 addr += 4;
3590 }
3591 if (BIT(inst_cream->inst, 15)) {
3592 cpu->WriteMemory32(addr, cpu->Reg[15] + 8);
3593 }
3594 } else {
3595 for (unsigned int i = 0; i < 15; i++) {
3596 if (BIT(inst_cream->inst, i)) {
3597 if (i == Rn)
3598 cpu->WriteMemory32(addr, old_RN);
3599 else
3600 cpu->WriteMemory32(addr, cpu->Reg[i]);
3601
3602 addr += 4;
3603 }
3604 }
3605
3606 // Check PC reg
3607 if (BIT(inst_cream->inst, 15)) {
3608 cpu->WriteMemory32(addr, cpu->Reg[15] + 8);
3609 }
3610 }
3611 }
3612 cpu->Reg[15] += cpu->GetInstructionSize();
3613 INC_PC(sizeof(ldst_inst));
3614 FETCH_INST;
3615 GOTO_NEXT_INST;
3616 }
3617 SXTB_INST : {
3618 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3619 sxtb_inst* inst_cream = (sxtb_inst*)inst_base->component;
3620
3621 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
3622 if (BIT(operand2, 7)) {
3623 operand2 |= 0xffffff00;
3624 } else {
3625 operand2 &= 0xff;
3626 }
3627 RD = operand2;
3628 }
3629 cpu->Reg[15] += cpu->GetInstructionSize();
3630 INC_PC(sizeof(sxtb_inst));
3631 FETCH_INST;
3632 GOTO_NEXT_INST;
3633 }
3634 STR_INST : {
3635 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3636 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3637 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3638
3639 unsigned int reg = BITS(inst_cream->inst, 12, 15);
3640 unsigned int value = cpu->Reg[reg];
3641
3642 if (reg == 15)
3643 value += 2 * cpu->GetInstructionSize();
3644
3645 cpu->WriteMemory32(addr, value);
3646 }
3647 cpu->Reg[15] += cpu->GetInstructionSize();
3648 INC_PC(sizeof(ldst_inst));
3649 FETCH_INST;
3650 GOTO_NEXT_INST;
3651 }
3652 UXTB_INST : {
3653 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3654 uxtb_inst* inst_cream = (uxtb_inst*)inst_base->component;
3655 RD = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3656 }
3657 cpu->Reg[15] += cpu->GetInstructionSize();
3658 INC_PC(sizeof(uxtb_inst));
3659 FETCH_INST;
3660 GOTO_NEXT_INST;
3661 }
3662 UXTAB_INST : {
3663 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3664 uxtab_inst* inst_cream = (uxtab_inst*)inst_base->component;
3665
3666 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3667 RD = RN + operand2;
3668 }
3669 cpu->Reg[15] += cpu->GetInstructionSize();
3670 INC_PC(sizeof(uxtab_inst));
3671 FETCH_INST;
3672 GOTO_NEXT_INST;
3673 }
3674 STRB_INST : {
3675 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3676 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3677 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3678 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
3679 cpu->WriteMemory8(addr, value);
3680 }
3681 cpu->Reg[15] += cpu->GetInstructionSize();
3682 INC_PC(sizeof(ldst_inst));
3683 FETCH_INST;
3684 GOTO_NEXT_INST;
3685 }
3686 STRBT_INST : {
3687 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3688 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3689 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3690
3691 const u32 previous_mode = cpu->Mode;
3692 const u32 value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
3693
3694 cpu->ChangePrivilegeMode(USER32MODE);
3695 cpu->WriteMemory8(addr, value);
3696 cpu->ChangePrivilegeMode(previous_mode);
3697 }
3698 cpu->Reg[15] += cpu->GetInstructionSize();
3699 INC_PC(sizeof(ldst_inst));
3700 FETCH_INST;
3701 GOTO_NEXT_INST;
3702 }
3703 STRD_INST : {
3704 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3705 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3706 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3707
3708 // The 3DS doesn't have the Large Physical Access Extension (LPAE)
3709 // so STRD wouldn't store these as a single write.
3710 cpu->WriteMemory32(addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]);
3711 cpu->WriteMemory32(addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]);
3712 }
3713 cpu->Reg[15] += cpu->GetInstructionSize();
3714 INC_PC(sizeof(ldst_inst));
3715 FETCH_INST;
3716 GOTO_NEXT_INST;
3717 }
3718 STREX_INST : {
3719 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3720 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3721 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3722
3723 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3724 cpu->UnsetExclusiveMemoryAddress();
3725 cpu->WriteMemory32(write_addr, RM);
3726 RD = 0;
3727 } else {
3728 // Failed to write due to mutex access
3729 RD = 1;
3730 }
3731 }
3732 cpu->Reg[15] += cpu->GetInstructionSize();
3733 INC_PC(sizeof(generic_arm_inst));
3734 FETCH_INST;
3735 GOTO_NEXT_INST;
3736 }
3737 STREXB_INST : {
3738 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3739 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3740 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3741
3742 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3743 cpu->UnsetExclusiveMemoryAddress();
3744 cpu->WriteMemory8(write_addr, cpu->Reg[inst_cream->Rm]);
3745 RD = 0;
3746 } else {
3747 // Failed to write due to mutex access
3748 RD = 1;
3749 }
3750 }
3751 cpu->Reg[15] += cpu->GetInstructionSize();
3752 INC_PC(sizeof(generic_arm_inst));
3753 FETCH_INST;
3754 GOTO_NEXT_INST;
3755 }
3756 STREXD_INST : {
3757 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3758 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3759 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3760
3761 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3762 cpu->UnsetExclusiveMemoryAddress();
3763
3764 const u32 rt = cpu->Reg[inst_cream->Rm + 0];
3765 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
3766 u64 value;
3767
3768 if (cpu->InBigEndianMode())
3769 value = (((u64)rt << 32) | rt2);
3770 else
3771 value = (((u64)rt2 << 32) | rt);
3772
3773 cpu->WriteMemory64(write_addr, value);
3774 RD = 0;
3775 } else {
3776 // Failed to write due to mutex access
3777 RD = 1;
3778 }
3779 }
3780 cpu->Reg[15] += cpu->GetInstructionSize();
3781 INC_PC(sizeof(generic_arm_inst));
3782 FETCH_INST;
3783 GOTO_NEXT_INST;
3784 }
3785 STREXH_INST : {
3786 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3787 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
3788 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
3789
3790 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
3791 cpu->UnsetExclusiveMemoryAddress();
3792 cpu->WriteMemory16(write_addr, RM);
3793 RD = 0;
3794 } else {
3795 // Failed to write due to mutex access
3796 RD = 1;
3797 }
3798 }
3799 cpu->Reg[15] += cpu->GetInstructionSize();
3800 INC_PC(sizeof(generic_arm_inst));
3801 FETCH_INST;
3802 GOTO_NEXT_INST;
3803 }
3804 STRH_INST : {
3805 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3806 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3807 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3808
3809 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
3810 cpu->WriteMemory16(addr, value);
3811 }
3812 cpu->Reg[15] += cpu->GetInstructionSize();
3813 INC_PC(sizeof(ldst_inst));
3814 FETCH_INST;
3815 GOTO_NEXT_INST;
3816 }
3817 STRT_INST : {
3818 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3819 ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
3820 inst_cream->get_addr(cpu, inst_cream->inst, addr);
3821
3822 const u32 previous_mode = cpu->Mode;
3823 const u32 rt_index = BITS(inst_cream->inst, 12, 15);
3824
3825 u32 value = cpu->Reg[rt_index];
3826 if (rt_index == 15)
3827 value += 2 * cpu->GetInstructionSize();
3828
3829 cpu->ChangePrivilegeMode(USER32MODE);
3830 cpu->WriteMemory32(addr, value);
3831 cpu->ChangePrivilegeMode(previous_mode);
3832 }
3833 cpu->Reg[15] += cpu->GetInstructionSize();
3834 INC_PC(sizeof(ldst_inst));
3835 FETCH_INST;
3836 GOTO_NEXT_INST;
3837 }
3838 SUB_INST : {
3839 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3840 sub_inst* const inst_cream = (sub_inst*)inst_base->component;
3841
3842 u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
3843
3844 bool carry;
3845 bool overflow;
3846 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
3847
3848 if (inst_cream->S && (inst_cream->Rd == 15)) {
3849 if (cpu->CurrentModeHasSPSR()) {
3850 cpu->Cpsr = cpu->Spsr_copy;
3851 cpu->ChangePrivilegeMode(cpu->Spsr_copy & 0x1F);
3852 LOAD_NZCVT;
3853 }
3854 } else if (inst_cream->S) {
3855 UPDATE_NFLAG(RD);
3856 UPDATE_ZFLAG(RD);
3857 cpu->CFlag = carry;
3858 cpu->VFlag = overflow;
3859 }
3860 if (inst_cream->Rd == 15) {
3861 INC_PC(sizeof(sub_inst));
3862 goto DISPATCH;
3863 }
3864 }
3865 cpu->Reg[15] += cpu->GetInstructionSize();
3866 INC_PC(sizeof(sub_inst));
3867 FETCH_INST;
3868 GOTO_NEXT_INST;
3869 }
3870 SWI_INST : {
3871 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3872 DEBUG_ASSERT(cpu->system != nullptr);
3873 swi_inst* const inst_cream = (swi_inst*)inst_base->component;
3874 cpu->system->GetRunningCore().GetTimer().AddTicks(num_instrs);
3875 cpu->NumInstrsToExecute =
3876 num_instrs >= cpu->NumInstrsToExecute ? 0 : cpu->NumInstrsToExecute - num_instrs;
3877 num_instrs = 0;
3878 Kernel::SVCContext{*cpu->system}.CallSVC(inst_cream->num & 0xFFFF);
3879 // The kernel would call ERET to get here, which clears exclusive memory state.
3880 cpu->UnsetExclusiveMemoryAddress();
3881 }
3882
3883 cpu->Reg[15] += cpu->GetInstructionSize();
3884 INC_PC(sizeof(swi_inst));
3885 FETCH_INST;
3886 GOTO_NEXT_INST;
3887 }
3888 SWP_INST : {
3889 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3890 swp_inst* inst_cream = (swp_inst*)inst_base->component;
3891
3892 addr = RN;
3893 unsigned int value = cpu->ReadMemory32(addr);
3894 cpu->WriteMemory32(addr, RM);
3895
3896 RD = value;
3897 }
3898 cpu->Reg[15] += cpu->GetInstructionSize();
3899 INC_PC(sizeof(swp_inst));
3900 FETCH_INST;
3901 GOTO_NEXT_INST;
3902 }
3903 SWPB_INST : {
3904 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3905 swp_inst* inst_cream = (swp_inst*)inst_base->component;
3906 addr = RN;
3907 unsigned int value = cpu->ReadMemory8(addr);
3908 cpu->WriteMemory8(addr, (RM & 0xFF));
3909 RD = value;
3910 }
3911 cpu->Reg[15] += cpu->GetInstructionSize();
3912 INC_PC(sizeof(swp_inst));
3913 FETCH_INST;
3914 GOTO_NEXT_INST;
3915 }
3916 SXTAB_INST : {
3917 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3918 sxtab_inst* inst_cream = (sxtab_inst*)inst_base->component;
3919
3920 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
3921
3922 // Sign extend for byte
3923 operand2 = (0x80 & operand2) ? (0xFFFFFF00 | operand2) : operand2;
3924 RD = RN + operand2;
3925 }
3926 cpu->Reg[15] += cpu->GetInstructionSize();
3927 INC_PC(sizeof(uxtab_inst));
3928 FETCH_INST;
3929 GOTO_NEXT_INST;
3930 }
3931
3932 SXTAB16_INST:
3933 SXTB16_INST : {
3934 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3935 sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component;
3936
3937 const u8 rotation = inst_cream->rotate * 8;
3938 u32 rm_val = RM;
3939 u32 rn_val = RN;
3940
3941 if (rotation)
3942 rm_val = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
3943
3944 // SXTB16
3945 if (inst_cream->Rn == 15) {
3946 u32 lo = (u32)(s8)rm_val;
3947 u32 hi = (u32)(s8)(rm_val >> 16);
3948 RD = (lo & 0xFFFF) | (hi << 16);
3949 }
3950 // SXTAB16
3951 else {
3952 u32 lo = rn_val + (u32)(s8)(rm_val & 0xFF);
3953 u32 hi = (rn_val >> 16) + (u32)(s8)((rm_val >> 16) & 0xFF);
3954 RD = (lo & 0xFFFF) | (hi << 16);
3955 }
3956 }
3957
3958 cpu->Reg[15] += cpu->GetInstructionSize();
3959 INC_PC(sizeof(sxtab_inst));
3960 FETCH_INST;
3961 GOTO_NEXT_INST;
3962 }
3963
3964 SXTAH_INST : {
3965 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3966 sxtah_inst* inst_cream = (sxtah_inst*)inst_base->component;
3967
3968 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
3969 // Sign extend for half
3970 operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2;
3971 RD = RN + operand2;
3972 }
3973 cpu->Reg[15] += cpu->GetInstructionSize();
3974 INC_PC(sizeof(sxtah_inst));
3975 FETCH_INST;
3976 GOTO_NEXT_INST;
3977 }
3978
3979 TEQ_INST : {
3980 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
3981 teq_inst* const inst_cream = (teq_inst*)inst_base->component;
3982
3983 u32 lop = RN;
3984 u32 rop = SHIFTER_OPERAND;
3985
3986 if (inst_cream->Rn == 15)
3987 lop += cpu->GetInstructionSize() * 2;
3988
3989 u32 result = lop ^ rop;
3990
3991 UPDATE_NFLAG(result);
3992 UPDATE_ZFLAG(result);
3993 UPDATE_CFLAG_WITH_SC;
3994 }
3995 cpu->Reg[15] += cpu->GetInstructionSize();
3996 INC_PC(sizeof(teq_inst));
3997 FETCH_INST;
3998 GOTO_NEXT_INST;
3999 }
4000 TST_INST : {
4001 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4002 tst_inst* const inst_cream = (tst_inst*)inst_base->component;
4003
4004 u32 lop = RN;
4005 u32 rop = SHIFTER_OPERAND;
4006
4007 if (inst_cream->Rn == 15)
4008 lop += cpu->GetInstructionSize() * 2;
4009
4010 u32 result = lop & rop;
4011
4012 UPDATE_NFLAG(result);
4013 UPDATE_ZFLAG(result);
4014 UPDATE_CFLAG_WITH_SC;
4015 }
4016 cpu->Reg[15] += cpu->GetInstructionSize();
4017 INC_PC(sizeof(tst_inst));
4018 FETCH_INST;
4019 GOTO_NEXT_INST;
4020 }
4021
4022 UADD8_INST:
4023 UADD16_INST:
4024 UADDSUBX_INST:
4025 USUB8_INST:
4026 USUB16_INST:
4027 USUBADDX_INST : {
4028 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4029 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4030
4031 const u8 op2 = inst_cream->op2;
4032 const u32 rm_val = RM;
4033 const u32 rn_val = RN;
4034
4035 s32 lo_result = 0;
4036 s32 hi_result = 0;
4037
4038 // UADD16
4039 if (op2 == 0x00) {
4040 lo_result = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
4041 hi_result = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4042
4043 if (lo_result & 0xFFFF0000) {
4044 cpu->Cpsr |= (1 << 16);
4045 cpu->Cpsr |= (1 << 17);
4046 } else {
4047 cpu->Cpsr &= ~(1 << 16);
4048 cpu->Cpsr &= ~(1 << 17);
4049 }
4050
4051 if (hi_result & 0xFFFF0000) {
4052 cpu->Cpsr |= (1 << 18);
4053 cpu->Cpsr |= (1 << 19);
4054 } else {
4055 cpu->Cpsr &= ~(1 << 18);
4056 cpu->Cpsr &= ~(1 << 19);
4057 }
4058 }
4059 // UASX
4060 else if (op2 == 0x01) {
4061 lo_result = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4062 hi_result = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
4063
4064 if (lo_result >= 0) {
4065 cpu->Cpsr |= (1 << 16);
4066 cpu->Cpsr |= (1 << 17);
4067 } else {
4068 cpu->Cpsr &= ~(1 << 16);
4069 cpu->Cpsr &= ~(1 << 17);
4070 }
4071
4072 if (hi_result >= 0x10000) {
4073 cpu->Cpsr |= (1 << 18);
4074 cpu->Cpsr |= (1 << 19);
4075 } else {
4076 cpu->Cpsr &= ~(1 << 18);
4077 cpu->Cpsr &= ~(1 << 19);
4078 }
4079 }
4080 // USAX
4081 else if (op2 == 0x02) {
4082 lo_result = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4083 hi_result = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
4084
4085 if (lo_result >= 0x10000) {
4086 cpu->Cpsr |= (1 << 16);
4087 cpu->Cpsr |= (1 << 17);
4088 } else {
4089 cpu->Cpsr &= ~(1 << 16);
4090 cpu->Cpsr &= ~(1 << 17);
4091 }
4092
4093 if (hi_result >= 0) {
4094 cpu->Cpsr |= (1 << 18);
4095 cpu->Cpsr |= (1 << 19);
4096 } else {
4097 cpu->Cpsr &= ~(1 << 18);
4098 cpu->Cpsr &= ~(1 << 19);
4099 }
4100 }
4101 // USUB16
4102 else if (op2 == 0x03) {
4103 lo_result = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
4104 hi_result = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4105
4106 if ((lo_result & 0xFFFF0000) == 0) {
4107 cpu->Cpsr |= (1 << 16);
4108 cpu->Cpsr |= (1 << 17);
4109 } else {
4110 cpu->Cpsr &= ~(1 << 16);
4111 cpu->Cpsr &= ~(1 << 17);
4112 }
4113
4114 if ((hi_result & 0xFFFF0000) == 0) {
4115 cpu->Cpsr |= (1 << 18);
4116 cpu->Cpsr |= (1 << 19);
4117 } else {
4118 cpu->Cpsr &= ~(1 << 18);
4119 cpu->Cpsr &= ~(1 << 19);
4120 }
4121 }
4122 // UADD8
4123 else if (op2 == 0x04) {
4124 s16 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
4125 s16 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
4126 s16 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
4127 s16 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
4128
4129 if (sum1 >= 0x100)
4130 cpu->Cpsr |= (1 << 16);
4131 else
4132 cpu->Cpsr &= ~(1 << 16);
4133
4134 if (sum2 >= 0x100)
4135 cpu->Cpsr |= (1 << 17);
4136 else
4137 cpu->Cpsr &= ~(1 << 17);
4138
4139 if (sum3 >= 0x100)
4140 cpu->Cpsr |= (1 << 18);
4141 else
4142 cpu->Cpsr &= ~(1 << 18);
4143
4144 if (sum4 >= 0x100)
4145 cpu->Cpsr |= (1 << 19);
4146 else
4147 cpu->Cpsr &= ~(1 << 19);
4148
4149 lo_result = ((sum1 & 0xFF) | (sum2 & 0xFF) << 8);
4150 hi_result = ((sum3 & 0xFF) | (sum4 & 0xFF) << 8);
4151 }
4152 // USUB8
4153 else if (op2 == 0x07) {
4154 s16 diff1 = (rn_val & 0xFF) - (rm_val & 0xFF);
4155 s16 diff2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
4156 s16 diff3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
4157 s16 diff4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
4158
4159 if (diff1 >= 0)
4160 cpu->Cpsr |= (1 << 16);
4161 else
4162 cpu->Cpsr &= ~(1 << 16);
4163
4164 if (diff2 >= 0)
4165 cpu->Cpsr |= (1 << 17);
4166 else
4167 cpu->Cpsr &= ~(1 << 17);
4168
4169 if (diff3 >= 0)
4170 cpu->Cpsr |= (1 << 18);
4171 else
4172 cpu->Cpsr &= ~(1 << 18);
4173
4174 if (diff4 >= 0)
4175 cpu->Cpsr |= (1 << 19);
4176 else
4177 cpu->Cpsr &= ~(1 << 19);
4178
4179 lo_result = (diff1 & 0xFF) | ((diff2 & 0xFF) << 8);
4180 hi_result = (diff3 & 0xFF) | ((diff4 & 0xFF) << 8);
4181 }
4182
4183 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
4184 }
4185
4186 cpu->Reg[15] += cpu->GetInstructionSize();
4187 INC_PC(sizeof(generic_arm_inst));
4188 FETCH_INST;
4189 GOTO_NEXT_INST;
4190 }
4191
4192 UHADD8_INST:
4193 UHADD16_INST:
4194 UHADDSUBX_INST:
4195 UHSUBADDX_INST:
4196 UHSUB8_INST:
4197 UHSUB16_INST : {
4198 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4199 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4200 const u32 rm_val = RM;
4201 const u32 rn_val = RN;
4202 const u8 op2 = inst_cream->op2;
4203
4204 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03) {
4205 u32 lo_val = 0;
4206 u32 hi_val = 0;
4207
4208 // UHADD16
4209 if (op2 == 0x00) {
4210 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
4211 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4212 }
4213 // UHASX
4214 else if (op2 == 0x01) {
4215 lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4216 hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
4217 }
4218 // UHSAX
4219 else if (op2 == 0x02) {
4220 lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
4221 hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
4222 }
4223 // UHSUB16
4224 else if (op2 == 0x03) {
4225 lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
4226 hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
4227 }
4228
4229 lo_val >>= 1;
4230 hi_val >>= 1;
4231
4232 RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
4233 } else if (op2 == 0x04 || op2 == 0x07) {
4234 u32 sum1;
4235 u32 sum2;
4236 u32 sum3;
4237 u32 sum4;
4238
4239 // UHADD8
4240 if (op2 == 0x04) {
4241 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
4242 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
4243 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
4244 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
4245 }
4246 // UHSUB8
4247 else {
4248 sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
4249 sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
4250 sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
4251 sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
4252 }
4253
4254 sum1 >>= 1;
4255 sum2 >>= 1;
4256 sum3 >>= 1;
4257 sum4 >>= 1;
4258
4259 RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) |
4260 ((sum4 & 0xFF) << 24);
4261 }
4262 }
4263
4264 cpu->Reg[15] += cpu->GetInstructionSize();
4265 INC_PC(sizeof(generic_arm_inst));
4266 FETCH_INST;
4267 GOTO_NEXT_INST;
4268 }
4269
4270 UMAAL_INST : {
4271 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4272 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
4273 const u64 rm = RM;
4274 const u64 rn = RN;
4275 const u64 rd_lo = RDLO;
4276 const u64 rd_hi = RDHI;
4277 const u64 result = (rm * rn) + rd_lo + rd_hi;
4278
4279 RDLO = (result & 0xFFFFFFFF);
4280 RDHI = ((result >> 32) & 0xFFFFFFFF);
4281 }
4282 cpu->Reg[15] += cpu->GetInstructionSize();
4283 INC_PC(sizeof(umaal_inst));
4284 FETCH_INST;
4285 GOTO_NEXT_INST;
4286 }
4287 UMLAL_INST : {
4288 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4289 umlal_inst* inst_cream = (umlal_inst*)inst_base->component;
4290 unsigned long long int rm = RM;
4291 unsigned long long int rs = RS;
4292 unsigned long long int rst = rm * rs;
4293 unsigned long long int add = ((unsigned long long)RDHI) << 32;
4294 add += RDLO;
4295 rst += add;
4296 RDLO = BITS(rst, 0, 31);
4297 RDHI = BITS(rst, 32, 63);
4298
4299 if (inst_cream->S) {
4300 cpu->NFlag = BIT(RDHI, 31);
4301 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
4302 }
4303 }
4304 cpu->Reg[15] += cpu->GetInstructionSize();
4305 INC_PC(sizeof(umlal_inst));
4306 FETCH_INST;
4307 GOTO_NEXT_INST;
4308 }
4309 UMULL_INST : {
4310 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4311 umull_inst* inst_cream = (umull_inst*)inst_base->component;
4312 unsigned long long int rm = RM;
4313 unsigned long long int rs = RS;
4314 unsigned long long int rst = rm * rs;
4315 RDHI = BITS(rst, 32, 63);
4316 RDLO = BITS(rst, 0, 31);
4317
4318 if (inst_cream->S) {
4319 cpu->NFlag = BIT(RDHI, 31);
4320 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
4321 }
4322 }
4323 cpu->Reg[15] += cpu->GetInstructionSize();
4324 INC_PC(sizeof(umull_inst));
4325 FETCH_INST;
4326 GOTO_NEXT_INST;
4327 }
4328 B_2_THUMB : {
4329 b_2_thumb* inst_cream = (b_2_thumb*)inst_base->component;
4330 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
4331 INC_PC(sizeof(b_2_thumb));
4332 goto DISPATCH;
4333 }
4334 B_COND_THUMB : {
4335 b_cond_thumb* inst_cream = (b_cond_thumb*)inst_base->component;
4336
4337 if (CondPassed(cpu, inst_cream->cond))
4338 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
4339 else
4340 cpu->Reg[15] += 2;
4341
4342 INC_PC(sizeof(b_cond_thumb));
4343 goto DISPATCH;
4344 }
4345 BL_1_THUMB : {
4346 bl_1_thumb* inst_cream = (bl_1_thumb*)inst_base->component;
4347 cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm;
4348 cpu->Reg[15] += cpu->GetInstructionSize();
4349 INC_PC(sizeof(bl_1_thumb));
4350 FETCH_INST;
4351 GOTO_NEXT_INST;
4352 }
4353 BL_2_THUMB : {
4354 bl_2_thumb* inst_cream = (bl_2_thumb*)inst_base->component;
4355 int tmp = ((cpu->Reg[15] + 2) | 1);
4356 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm);
4357 cpu->Reg[14] = tmp;
4358 INC_PC(sizeof(bl_2_thumb));
4359 goto DISPATCH;
4360 }
4361 BLX_1_THUMB : {
4362 // BLX 1 for armv5t and above
4363 u32 tmp = cpu->Reg[15];
4364 blx_1_thumb* inst_cream = (blx_1_thumb*)inst_base->component;
4365 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC;
4366 cpu->Reg[14] = ((tmp + 2) | 1);
4367 cpu->TFlag = 0;
4368 INC_PC(sizeof(blx_1_thumb));
4369 goto DISPATCH;
4370 }
4371
4372 UQADD8_INST:
4373 UQADD16_INST:
4374 UQADDSUBX_INST:
4375 UQSUB8_INST:
4376 UQSUB16_INST:
4377 UQSUBADDX_INST : {
4378 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4379 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
4380
4381 const u8 op2 = inst_cream->op2;
4382 const u32 rm_val = RM;
4383 const u32 rn_val = RN;
4384
4385 u16 lo_val = 0;
4386 u16 hi_val = 0;
4387
4388 // UQADD16
4389 if (op2 == 0x00) {
4390 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
4391 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4392 }
4393 // UQASX
4394 else if (op2 == 0x01) {
4395 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4396 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
4397 }
4398 // UQSAX
4399 else if (op2 == 0x02) {
4400 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4401 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
4402 }
4403 // UQSUB16
4404 else if (op2 == 0x03) {
4405 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF);
4406 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
4407 }
4408 // UQADD8
4409 else if (op2 == 0x04) {
4410 lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) |
4411 ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8;
4412 hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) |
4413 ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8;
4414 }
4415 // UQSUB8
4416 else {
4417 lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) |
4418 ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8;
4419 hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) |
4420 ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8;
4421 }
4422
4423 RD = ((lo_val & 0xFFFF) | hi_val << 16);
4424 }
4425
4426 cpu->Reg[15] += cpu->GetInstructionSize();
4427 INC_PC(sizeof(generic_arm_inst));
4428 FETCH_INST;
4429 GOTO_NEXT_INST;
4430 }
4431
4432 USAD8_INST:
4433 USADA8_INST : {
4434 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4435 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4436
4437 const u8 ra_idx = inst_cream->Ra;
4438 const u32 rm_val = RM;
4439 const u32 rn_val = RN;
4440
4441 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
4442 const u8 diff2 =
4443 ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
4444 const u8 diff3 =
4445 ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
4446 const u8 diff4 =
4447 ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
4448
4449 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
4450
4451 // Op is USADA8 if true.
4452 if (ra_idx != 15)
4453 finalDif += cpu->Reg[ra_idx];
4454
4455 RD = finalDif;
4456 }
4457
4458 cpu->Reg[15] += cpu->GetInstructionSize();
4459 INC_PC(sizeof(generic_arm_inst));
4460 FETCH_INST;
4461 GOTO_NEXT_INST;
4462 }
4463
4464 USAT_INST : {
4465 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4466 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
4467
4468 u8 shift_type = inst_cream->shift_type;
4469 u8 shift_amount = inst_cream->imm5;
4470 u32 rn_val = RN;
4471
4472 // 32-bit ASR is encoded as an amount of 0.
4473 if (shift_type == 1 && shift_amount == 0)
4474 shift_amount = 31;
4475
4476 if (shift_type == 0)
4477 rn_val <<= shift_amount;
4478 else if (shift_type == 1)
4479 rn_val = ((s32)rn_val >> shift_amount);
4480
4481 bool saturated = false;
4482 rn_val = ARMul_UnsignedSatQ(rn_val, inst_cream->sat_imm, &saturated);
4483
4484 if (saturated)
4485 cpu->Cpsr |= (1 << 27);
4486
4487 RD = rn_val;
4488 }
4489
4490 cpu->Reg[15] += cpu->GetInstructionSize();
4491 INC_PC(sizeof(ssat_inst));
4492 FETCH_INST;
4493 GOTO_NEXT_INST;
4494 }
4495
4496 USAT16_INST : {
4497 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4498 ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
4499 const u8 saturate_to = inst_cream->sat_imm;
4500
4501 bool sat1 = false;
4502 bool sat2 = false;
4503
4504 RD = (ARMul_UnsignedSatQ((s16)RN, saturate_to, &sat1) & 0xFFFF) |
4505 ARMul_UnsignedSatQ((s32)RN >> 16, saturate_to, &sat2) << 16;
4506
4507 if (sat1 || sat2)
4508 cpu->Cpsr |= (1 << 27);
4509 }
4510
4511 cpu->Reg[15] += cpu->GetInstructionSize();
4512 INC_PC(sizeof(ssat_inst));
4513 FETCH_INST;
4514 GOTO_NEXT_INST;
4515 }
4516
4517 UXTAB16_INST:
4518 UXTB16_INST : {
4519 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4520 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
4521
4522 const u8 rn_idx = inst_cream->Rn;
4523 const u32 rm_val = RM;
4524 const u32 rotation = inst_cream->rotate * 8;
4525 const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
4526
4527 // UXTB16, otherwise UXTAB16
4528 if (rn_idx == 15) {
4529 RD = rotated_rm & 0x00FF00FF;
4530 } else {
4531 const u32 rn_val = RN;
4532 const u8 lo_rotated = (rotated_rm & 0xFF);
4533 const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
4534 const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
4535 const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
4536
4537 RD = ((hi_result << 16) | (lo_result & 0xFFFF));
4538 }
4539 }
4540
4541 cpu->Reg[15] += cpu->GetInstructionSize();
4542 INC_PC(sizeof(uxtab_inst));
4543 FETCH_INST;
4544 GOTO_NEXT_INST;
4545 }
4546
4547 WFE_INST : {
4548 // Stubbed, as WFE is a hint instruction.
4549 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4550 LOG_TRACE(Core_ARM11, "WFE executed.");
4551 }
4552
4553 cpu->Reg[15] += cpu->GetInstructionSize();
4554 INC_PC_STUB;
4555 FETCH_INST;
4556 GOTO_NEXT_INST;
4557 }
4558
4559 WFI_INST : {
4560 // Stubbed, as WFI is a hint instruction.
4561 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4562 LOG_TRACE(Core_ARM11, "WFI executed.");
4563 }
4564
4565 cpu->Reg[15] += cpu->GetInstructionSize();
4566 INC_PC_STUB;
4567 FETCH_INST;
4568 GOTO_NEXT_INST;
4569 }
4570
4571 YIELD_INST : {
4572 // Stubbed, as YIELD is a hint instruction.
4573 if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
4574 LOG_TRACE(Core_ARM11, "YIELD executed.");
4575 }
4576
4577 cpu->Reg[15] += cpu->GetInstructionSize();
4578 INC_PC_STUB;
4579 FETCH_INST;
4580 GOTO_NEXT_INST;
4581 }
4582
4583 #define VFP_INTERPRETER_IMPL
4584 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
4585 #undef VFP_INTERPRETER_IMPL
4586
4587 END : {
4588 SAVE_NZCVT;
4589 cpu->NumInstrsToExecute = 0;
4590 return num_instrs;
4591 }
4592 INIT_INST_LENGTH : {
4593 cpu->NumInstrsToExecute = 0;
4594 return num_instrs;
4595 }
4596 }
4597