summaryrefslogtreecommitdiff
path: root/src/core/arm/interpreter/armemu.cpp
diff options
context:
space:
mode:
authorGravatar Lioncash2015-01-31 20:34:26 -0500
committerGravatar Lioncash2015-01-31 20:43:03 -0500
commitf44781fd7b0c5f99573e917ccdd92716a99a9b0d (patch)
treead31575f5653316488371cd654d961ce803e2c01 /src/core/arm/interpreter/armemu.cpp
parentMerge pull request #512 from lioncash/assignment (diff)
downloadyuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar.gz
yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar.xz
yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.zip
arm: Adios armemu
Diffstat (limited to 'src/core/arm/interpreter/armemu.cpp')
-rw-r--r--src/core/arm/interpreter/armemu.cpp5648
1 files changed, 0 insertions, 5648 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
deleted file mode 100644
index 7114313d6..000000000
--- a/src/core/arm/interpreter/armemu.cpp
+++ /dev/null
@@ -1,5648 +0,0 @@
1/* armemu.c -- Main instruction emulation: ARM7 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
3 Modifications to add arch. v4 support by <jsmith@cygnus.com>.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19#include "core/arm/skyeye_common/arm_regformat.h"
20#include "core/arm/skyeye_common/armdefs.h"
21#include "core/arm/skyeye_common/armemu.h"
22#include "core/hle/hle.h"
23
24static ARMword GetDPRegRHS (ARMul_State *, ARMword);
25static ARMword GetDPSRegRHS (ARMul_State *, ARMword);
26static void WriteR15 (ARMul_State *, ARMword);
27static void WriteSR15 (ARMul_State *, ARMword);
28static void WriteR15Branch (ARMul_State *, ARMword);
29static ARMword GetLSRegRHS (ARMul_State *, ARMword);
30static ARMword GetLS7RHS (ARMul_State *, ARMword);
31static unsigned LoadWord (ARMul_State *, ARMword, ARMword);
32static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int);
33static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int);
34static unsigned StoreWord (ARMul_State *, ARMword, ARMword);
35static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword);
36static unsigned StoreByte (ARMul_State *, ARMword, ARMword);
37static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword);
38static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword);
39static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword);
40static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword);
41static unsigned Multiply64 (ARMul_State *, ARMword, int, int);
42static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int);
43static void Handle_Load_Double (ARMul_State *, ARMword);
44static void Handle_Store_Double (ARMul_State *, ARMword);
45
46static int handle_v6_insn (ARMul_State * state, ARMword instr);
47
48#define LUNSIGNED (0) /* unsigned operation */
49#define LSIGNED (1) /* signed operation */
50#define LDEFAULT (0) /* default : do nothing */
51#define LSCC (1) /* set condition codes on result */
52
53/* Short-hand macros for LDR/STR. */
54
55/* Store post decrement writeback. */
56#define SHDOWNWB() \
57 lhs = LHS ; \
58 if (StoreHalfWord (state, instr, lhs)) \
59 LSBase = lhs - GetLS7RHS (state, instr);
60
61/* Store post increment writeback. */
62#define SHUPWB() \
63 lhs = LHS ; \
64 if (StoreHalfWord (state, instr, lhs)) \
65 LSBase = lhs + GetLS7RHS (state, instr);
66
67/* Store pre decrement. */
68#define SHPREDOWN() \
69 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
70
71/* Store pre decrement writeback. */
72#define SHPREDOWNWB() \
73 temp = LHS - GetLS7RHS (state, instr); \
74 if (StoreHalfWord (state, instr, temp)) \
75 LSBase = temp;
76
77/* Store pre increment. */
78#define SHPREUP() \
79 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
80
81/* Store pre increment writeback. */
82#define SHPREUPWB() \
83 temp = LHS + GetLS7RHS (state, instr); \
84 if (StoreHalfWord (state, instr, temp)) \
85 LSBase = temp;
86
87/* Load post decrement writeback. */
88#define LHPOSTDOWN() \
89{ \
90 int done = 1; \
91 lhs = LHS; \
92 temp = lhs - GetLS7RHS (state, instr); \
93 \
94 switch (BITS (5, 6)) \
95 { \
96 case 1: /* H */ \
97 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
98 LSBase = temp; \
99 break; \
100 case 2: /* SB */ \
101 if (LoadByte (state, instr, lhs, LSIGNED)) \
102 LSBase = temp; \
103 break; \
104 case 3: /* SH */ \
105 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
106 LSBase = temp; \
107 break; \
108 case 0: /* SWP handled elsewhere. */ \
109 default: \
110 done = 0; \
111 break; \
112 } \
113 if (done) \
114 break; \
115}
116
117/* Load post increment writeback. */
118#define LHPOSTUP() \
119{ \
120 int done = 1; \
121 lhs = LHS; \
122 temp = lhs + GetLS7RHS (state, instr); \
123 \
124 switch (BITS (5, 6)) \
125 { \
126 case 1: /* H */ \
127 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
128 LSBase = temp; \
129 break; \
130 case 2: /* SB */ \
131 if (LoadByte (state, instr, lhs, LSIGNED)) \
132 LSBase = temp; \
133 break; \
134 case 3: /* SH */ \
135 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
136 LSBase = temp; \
137 break; \
138 case 0: /* SWP handled elsewhere. */ \
139 default: \
140 done = 0; \
141 break; \
142 } \
143 if (done) \
144 break; \
145}
146
147/* Load pre decrement. */
148#define LHPREDOWN() \
149{ \
150 int done = 1; \
151 \
152 temp = LHS - GetLS7RHS (state, instr); \
153 switch (BITS (5, 6)) \
154 { \
155 case 1: /* H */ \
156 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
157 break; \
158 case 2: /* SB */ \
159 (void) LoadByte (state, instr, temp, LSIGNED); \
160 break; \
161 case 3: /* SH */ \
162 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
163 break; \
164 case 0: \
165 /* SWP handled elsewhere. */ \
166 default: \
167 done = 0; \
168 break; \
169 } \
170 if (done) \
171 break; \
172}
173
174/* Load pre decrement writeback. */
175#define LHPREDOWNWB() \
176{ \
177 int done = 1; \
178 \
179 temp = LHS - GetLS7RHS (state, instr); \
180 switch (BITS (5, 6)) \
181 { \
182 case 1: /* H */ \
183 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
184 LSBase = temp; \
185 break; \
186 case 2: /* SB */ \
187 if (LoadByte (state, instr, temp, LSIGNED)) \
188 LSBase = temp; \
189 break; \
190 case 3: /* SH */ \
191 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
192 LSBase = temp; \
193 break; \
194 case 0: \
195 /* SWP handled elsewhere. */ \
196 default: \
197 done = 0; \
198 break; \
199 } \
200 if (done) \
201 break; \
202}
203
204/* Load pre increment. */
205#define LHPREUP() \
206{ \
207 int done = 1; \
208 \
209 temp = LHS + GetLS7RHS (state, instr); \
210 switch (BITS (5, 6)) \
211 { \
212 case 1: /* H */ \
213 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
214 break; \
215 case 2: /* SB */ \
216 (void) LoadByte (state, instr, temp, LSIGNED); \
217 break; \
218 case 3: /* SH */ \
219 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
220 break; \
221 case 0: \
222 /* SWP handled elsewhere. */ \
223 default: \
224 done = 0; \
225 break; \
226 } \
227 if (done) \
228 break; \
229}
230
231/* Load pre increment writeback. */
232#define LHPREUPWB() \
233{ \
234 int done = 1; \
235 \
236 temp = LHS + GetLS7RHS (state, instr); \
237 switch (BITS (5, 6)) \
238 { \
239 case 1: /* H */ \
240 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
241 LSBase = temp; \
242 break; \
243 case 2: /* SB */ \
244 if (LoadByte (state, instr, temp, LSIGNED)) \
245 LSBase = temp; \
246 break; \
247 case 3: /* SH */ \
248 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
249 LSBase = temp; \
250 break; \
251 case 0: \
252 /* SWP handled elsewhere. */ \
253 default: \
254 done = 0; \
255 break; \
256 } \
257 if (done) \
258 break; \
259}
260
261/* EMULATION of ARM6. */
262
263int ARMul_ICE_debug(ARMul_State *state,ARMword instr,ARMword addr);
264#ifdef MODE32
265//chy 2006-04-12, for ICE debug
266int ARMul_ICE_debug(ARMul_State *state,ARMword instr,ARMword addr)
267{
268 return 0;
269}
270
271ARMword ARMul_Debug(ARMul_State * state, ARMword pc, ARMword instr)
272{
273 return 0;
274}
275
276ARMword ARMul_Emulate32(ARMul_State* state)
277#else
278ARMword ARMul_Emulate26(ARMul_State* state)
279#endif
280{
281 /* The PC pipeline value depends on whether ARM
282 or Thumb instructions are being
283 d. */
284 ARMword isize;
285 ARMword instr; /* The current instruction. */
286 ARMword dest = 0; /* Almost the DestBus. */
287 ARMword temp; /* Ubiquitous third hand. */
288 ARMword pc = 0; /* The address of the current instruction. */
289 ARMword lhs; /* Almost the ABus and BBus. */
290 ARMword rhs;
291 ARMword decoded = 0; /* Instruction pipeline. */
292 ARMword loaded = 0;
293 ARMword decoded_addr=0;
294 ARMword loaded_addr=0;
295 ARMword have_bp=0;
296
297 /* Execute the next instruction. */
298 if (state->NextInstr < PRIMEPIPE) {
299 decoded = state->decoded;
300 loaded = state->loaded;
301 pc = state->pc;
302 //chy 2006-04-12, for ICE debug
303 decoded_addr=state->decoded_addr;
304 loaded_addr=state->loaded_addr;
305 }
306
307 do {
308 //print_func_name(state->pc);
309 /* Just keep going. */
310 isize = INSN_SIZE;
311
312 switch (state->NextInstr) {
313 case SEQ:
314 /* Advance the pipeline, and an S cycle. */
315 state->Reg[15] += isize;
316 pc += isize;
317 instr = decoded;
318 //chy 2006-04-12, for ICE debug
319 have_bp = ARMul_ICE_debug(state,instr,decoded_addr);
320 decoded = loaded;
321 decoded_addr=loaded_addr;
322 //loaded = ARMul_LoadInstrS (state, pc + (isize * 2),
323 // isize);
324 loaded_addr=pc + (isize * 2);
325 if (have_bp) goto TEST_EMULATE;
326 break;
327
328 case NONSEQ:
329 /* Advance the pipeline, and an N cycle. */
330 state->Reg[15] += isize;
331 pc += isize;
332 instr = decoded;
333 //chy 2006-04-12, for ICE debug
334 have_bp=ARMul_ICE_debug(state,instr,decoded_addr);
335 decoded = loaded;
336 decoded_addr=loaded_addr;
337 //loaded = ARMul_LoadInstrN (state, pc + (isize * 2),
338 // isize);
339 loaded_addr=pc + (isize * 2);
340 NORMALCYCLE;
341 if (have_bp) goto TEST_EMULATE;
342 break;
343
344 case PCINCEDSEQ:
345 /* Program counter advanced, and an S cycle. */
346 pc += isize;
347 instr = decoded;
348 //chy 2006-04-12, for ICE debug
349 have_bp=ARMul_ICE_debug(state,instr,decoded_addr);
350 decoded = loaded;
351 decoded_addr=loaded_addr;
352 //loaded = ARMul_LoadInstrS (state, pc + (isize * 2),
353 // isize);
354 loaded_addr=pc + (isize * 2);
355 NORMALCYCLE;
356 if (have_bp) goto TEST_EMULATE;
357 break;
358
359 case PCINCEDNONSEQ:
360 /* Program counter advanced, and an N cycle. */
361 pc += isize;
362 instr = decoded;
363 //chy 2006-04-12, for ICE debug
364 have_bp=ARMul_ICE_debug(state,instr,decoded_addr);
365 decoded = loaded;
366 decoded_addr=loaded_addr;
367 //loaded = ARMul_LoadInstrN (state, pc + (isize * 2),
368 // isize);
369 loaded_addr=pc + (isize * 2);
370 NORMALCYCLE;
371 if (have_bp) goto TEST_EMULATE;
372 break;
373
374 case RESUME:
375 /* The program counter has been changed. */
376 pc = state->Reg[15];
377#ifndef MODE32
378 pc = pc & R15PCBITS;
379#endif
380 state->Reg[15] = pc + (isize * 2);
381 state->Aborted = 0;
382 //chy 2004-05-25, fix bug provided by Carl van Schaik<cvansch@cse.unsw.EDU.AU>
383 state->AbortAddr = 1;
384
385 instr = ARMul_LoadInstrN (state, pc, isize);
386 //instr = ARMul_ReLoadInstr (state, pc, isize);
387 //chy 2006-04-12, for ICE debug
388 have_bp=ARMul_ICE_debug(state,instr,pc);
389 //decoded =
390 // ARMul_ReLoadInstr (state, pc + isize, isize);
391 decoded_addr=pc+isize;
392 //loaded = ARMul_ReLoadInstr (state, pc + isize * 2,
393 // isize);
394 loaded_addr=pc + isize * 2;
395 NORMALCYCLE;
396 if (have_bp) goto TEST_EMULATE;
397 break;
398
399 default:
400 /* The program counter has been changed. */
401 pc = state->Reg[15];
402#ifndef MODE32
403 pc = pc & R15PCBITS;
404#endif
405 state->Reg[15] = pc + (isize * 2);
406 state->Aborted = 0;
407 //chy 2004-05-25, fix bug provided by Carl van Schaik<cvansch@cse.unsw.EDU.AU>
408 state->AbortAddr = 1;
409
410 instr = ARMul_LoadInstrN (state, pc, isize);
411
412 //chy 2006-04-12, for ICE debug
413 have_bp=ARMul_ICE_debug(state,instr,pc);
414
415 decoded_addr=pc+isize;
416
417 loaded_addr=pc + isize * 2;
418 NORMALCYCLE;
419 if (have_bp) goto TEST_EMULATE;
420 break;
421 }
422
423 instr = ARMul_LoadInstrN (state, pc, isize);
424 state->last_instr = state->CurrInstr;
425 state->CurrInstr = instr;
426 ARMul_Debug(state, pc, instr);
427
428 /* Any exceptions ? */
429 if (state->NresetSig == LOW) {
430 ARMul_Abort (state, ARMul_ResetV);
431 break;
432 } else if (!state->NfiqSig && !FFLAG) {
433 ARMul_Abort (state, ARMul_FIQV);
434 break;
435 } else if (!state->NirqSig && !IFLAG) {
436 ARMul_Abort (state, ARMul_IRQV);
437 break;
438 }
439
440 if (state->Emulate < ONCE) {
441 state->NextInstr = RESUME;
442 break;
443 }
444
445 state->NumInstrs++;
446
447#ifdef MODET
448 /* Provide Thumb instruction decoding. If the processor is in Thumb
449 mode, then we can simply decode the Thumb instruction, and map it
450 to the corresponding ARM instruction (by directly loading the
451 instr variable, and letting the normal ARM simulator
452 execute). There are some caveats to ensure that the correct
453 pipelined PC value is used when executing Thumb code, and also for
454 dealing with the BL instruction. */
455 if (TFLAG) {
456 ARMword armOp = 0;
457 /* Check if in Thumb mode. */
458 switch (ARMul_ThumbDecode(state, pc, instr, &armOp)) {
459 case t_undefined:
460 /* This is a Thumb instruction. */
461 ARMul_UndefInstr (state, instr);
462 goto donext;
463
464 case t_branch:
465 /* Already processed. */
466 //pc = state->Reg[15] - 2;
467 //state->pc = state->Reg[15] - 2; //ichfly why do I need that
468 goto donext;
469
470 case t_decoded:
471 /* ARM instruction available. */
472 //printf("t decode %04lx -> %08lx\n", instr & 0xffff, armOp);
473
474 if (armOp == 0xDEADC0DE) {
475 LOG_ERROR(Core_ARM11, "Failed to decode thumb opcode %04X at %08X", instr, pc);
476 }
477
478 instr = armOp;
479
480 /* So continue instruction decoding. */
481 break;
482 default:
483 break;
484 }
485 }
486#endif
487 /* Check the condition codes. */
488 if ((temp = TOPBITS (28)) == AL) {
489 /* Vile deed in the need for speed. */
490 goto mainswitch;
491 }
492
493 /* Check the condition code. */
494 switch ((int) TOPBITS (28)) {
495 case AL:
496 temp = TRUE;
497 break;
498 case NV:
499
500 /* shenoubang add for armv7 instr dmb 2012-3-11 */
501 if (state->is_v7) {
502 if ((instr & 0x0fffff00) == 0x057ff000) {
503 switch((instr >> 4) & 0xf) {
504 case 4: /* dsb */
505 case 5: /* dmb */
506 case 6: /* isb */
507 // TODO: do no implemented thes instr
508 goto donext;
509 }
510 }
511 }
512 /* dyf add for armv6 instruct CPS 2010.9.17 */
513 if (state->is_v6) {
514 /* clrex do nothing here temporary */
515 if (instr == 0xf57ff01f) {
516 //printf("clrex \n");
517 /* shenoubang 2012-3-14 refer the dyncom_interpreter */
518 state->exclusive_tag_array[0] = 0xFFFFFFFF;
519 state->exclusive_access_state = 0;
520 goto donext;
521 }
522
523 if (BITS(20, 27) == 0x10) {
524 if (BIT(19)) {
525 if (BIT(8)) {
526 if (BIT(18))
527 state->Cpsr |= 1<<8;
528 else
529 state->Cpsr &= ~(1<<8);
530 }
531 if (BIT(7)) {
532 if (BIT(18))
533 state->Cpsr |= 1<<7;
534 else
535 state->Cpsr &= ~(1<<7);
536 ASSIGNINT (state->Cpsr & INTBITS);
537 }
538 if (BIT(6)) {
539 if (BIT(18))
540 state->Cpsr |= 1<<6;
541 else
542 state->Cpsr &= ~(1<<6);
543 ASSIGNINT (state->Cpsr & INTBITS);
544 }
545 }
546 if (BIT(17)) {
547 state->Cpsr |= BITS(0, 4);
548 printf("skyeye test state->Mode\n");
549 if (state->Mode != (state->Cpsr & MODEBITS)) {
550 state->Mode = ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
551 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
552 }
553 }
554 goto donext;
555 }
556 }
557 if (state->is_v5) {
558 if (BITS (25, 27) == 5) { /* BLX(1) */
559 ARMword dest;
560
561 state->Reg[14] = pc + 4;
562
563 /* Force entry into Thumb mode. */
564 dest = pc + 8 + 1;
565 if (BIT (23))
566 dest += (NEGBRANCH +
567 (BIT (24) << 1));
568 else
569 dest += POSBRANCH +
570 (BIT (24) << 1);
571
572 WriteR15Branch (state, dest);
573 goto donext;
574 } else if ((instr & 0xFC70F000) == 0xF450F000) {
575 /* The PLD instruction. Ignored. */
576 goto donext;
577 } else if (((instr & 0xfe500f00) == 0xfc100100)
578 || ((instr & 0xfe500f00) ==
579 0xfc000100)) {
580 /* wldrw and wstrw are unconditional. */
581 goto mainswitch;
582 } else {
583 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
584 ARMul_UndefInstr (state, instr);
585 }
586 }
587 temp = FALSE;
588 break;
589 case EQ:
590 temp = ZFLAG;
591 break;
592 case NE:
593 temp = !ZFLAG;
594 break;
595 case VS:
596 temp = VFLAG;
597 break;
598 case VC:
599 temp = !VFLAG;
600 break;
601 case MI:
602 temp = NFLAG;
603 break;
604 case PL:
605 temp = !NFLAG;
606 break;
607 case CS:
608 temp = CFLAG;
609 break;
610 case CC:
611 temp = !CFLAG;
612 break;
613 case HI:
614 temp = (CFLAG && !ZFLAG);
615 break;
616 case LS:
617 temp = (!CFLAG || ZFLAG);
618 break;
619 case GE:
620 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
621 break;
622 case LT:
623 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
624 break;
625 case GT:
626 temp = ((!NFLAG && !VFLAG && !ZFLAG)
627 || (NFLAG && VFLAG && !ZFLAG));
628 break;
629 case LE:
630 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG))
631 || ZFLAG;
632 break;
633 } /* cc check */
634
635//chy 2003-08-24 now #if 0 .... #endif process cp14, cp15.reg14, I disable it...
636
637 /* Actual execution of instructions begins here. */
638 /* If the condition codes don't match, stop here. */
639 if (temp) {
640mainswitch:
641
642 /* shenoubang sbfx and ubfx instr 2012-3-16 */
643 if (state->is_v6) {
644 unsigned int m, lsb, width, Rd, Rn, data;
645 Rd = Rn = lsb = width = data = m = 0;
646
647 //printf("helloworld\n");
648 if ((((int) BITS (21, 27)) == 0x3f) && (((int) BITS (4, 6)) == 0x5)) {
649 m = (unsigned)BITS(7, 11);
650 width = (unsigned)BITS(16, 20);
651 Rd = (unsigned)BITS(12, 15);
652 Rn = (unsigned)BITS(0, 3);
653 if ((Rd == 15) || (Rn == 15)) {
654 ARMul_UndefInstr (state, instr);
655 } else if ((m + width) < 32) {
656 data = state->Reg[Rn];
657 state->Reg[Rd] ^= state->Reg[Rd];
658 state->Reg[Rd] = ((ARMword)(data << (31 -(m + width))) >> ((31 - (m + width)) + (m)));
659 //SKYEYE_LOG_IN_CLR(RED, "UBFX: In %s, line = %d, Reg_src[%d] = 0x%x, Reg_d[%d] = 0x%x, m = %d, width = %d, Rd = %d, Rn = %d\n",
660 // __FUNCTION__, __LINE__, Rn, data, Rd, state->Reg[Rd], m, width + 1, Rd, Rn);
661 goto donext;
662 }
663 } // ubfx instr
664 else if ((((int) BITS (21, 27)) == 0x3d) && (((int) BITS (4, 6)) == 0x5)) {
665 int tmp = 0;
666 Rd = BITS(12, 15);
667 Rn = BITS(0, 3);
668 lsb = BITS(7, 11);
669 width = BITS(16, 20);
670 if ((Rd == 15) || (Rn == 15)) {
671 ARMul_UndefInstr (state, instr);
672 } else if ((lsb + width) < 32) {
673 state->Reg[Rd] ^= state->Reg[Rd];
674 data = state->Reg[Rn];
675 tmp = (data << (32 - (lsb + width + 1)));
676 state->Reg[Rd] = (tmp >> (32 - (lsb + width + 1)));
677 //SKYEYE_LOG_IN_CLR(RED, "sbfx: In %s, line = %d, pc = 0x%x, instr = 0x%x,Rd = 0x%x, Rn = 0x%x, lsb = %d, width = %d, Rs[%d] = 0x%x, Rd[%d] = 0x%x\n",
678 // __func__, __LINE__, pc, instr, Rd, Rn, lsb, width + 1, Rn, state->Reg[Rn], Rd, state->Reg[Rd]);
679 goto donext;
680 }
681 } // sbfx instr
682 else if ((((int)BITS(21, 27)) == 0x3e) && ((int)BITS(4, 6) == 0x1)) {
683 //(ARMword)(instr<<(31-(n))) >> ((31-(n))+(m))
684 unsigned msb ,tmp_rn, tmp_rd, dst;
685 tmp_rd = tmp_rn = dst = 0;
686 Rd = BITS(12, 15);
687 Rn = BITS(0, 3);
688 lsb = BITS(7, 11);
689 msb = BITS(16, 20); //-V519
690 if (Rd == 15) {
691 ARMul_UndefInstr (state, instr);
692 } else if (Rn == 15) {
693 data = state->Reg[Rd];
694 tmp_rd = ((ARMword)(data << (31 - lsb)) >> (31 - lsb));
695 dst = ((data >> msb) << (msb - lsb));
696 dst = (dst << lsb) | tmp_rd;
697 goto donext;
698 } // bfc instr
699 else if (((msb >= lsb) && (msb < 32))) {
700 data = state->Reg[Rn];
701 tmp_rn = ((ARMword)(data << (31 - (msb - lsb))) >> (31 - (msb - lsb)));
702 data = state->Reg[Rd];
703 tmp_rd = ((ARMword)(data << (31 - lsb)) >> (31 - lsb));
704 dst = ((data >> msb) << (msb - lsb)) | tmp_rn;
705 dst = (dst << lsb) | tmp_rd;
706 goto donext;
707 } // bfi instr
708 }
709 }
710
711 switch ((int) BITS (20, 27)) {
712 /* Data Processing Register RHS Instructions. */
713
714 case 0x00: /* AND reg and MUL */
715#ifdef MODET
716 if (BITS (4, 11) == 0xB) {
717 /* STRH register offset, no write-back, down, post indexed. */
718 SHDOWNWB ();
719 break;
720 }
721 if (BITS (4, 7) == 0xD) {
722 Handle_Load_Double (state, instr);
723 break;
724 }
725 if (BITS (4, 7) == 0xF) {
726 Handle_Store_Double (state, instr);
727 break;
728 }
729#endif
730 if (BITS (4, 7) == 9) {
731 /* MUL */
732 rhs = state->Reg[MULRHSReg];
733 //if (MULLHSReg == MULDESTReg) {
734 if(0) { /* For armv6, the restriction is removed */
735 UNDEF_MULDestEQOp1;
736 state->Reg[MULDESTReg] = 0;
737 } else if (MULDESTReg != 15)
738 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
739 else
740 UNDEF_MULPCDest;
741
742 for (dest = 0, temp = 0; dest < 32;
743 dest++)
744 if (rhs & (1L << dest))
745 temp = dest;
746
747 /* Mult takes this many/2 I cycles. */
748 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
749 } else {
750 /* AND reg. */
751 rhs = DPRegRHS;
752 dest = LHS & rhs;
753 WRITEDEST (dest);
754 }
755 break;
756
757 case 0x01: /* ANDS reg and MULS */
758#ifdef MODET
759 if ((BITS (4, 11) & 0xF9) == 0x9)
760 /* LDR register offset, no write-back, down, post indexed. */
761 LHPOSTDOWN ();
762 /* Fall through to rest of decoding. */
763#endif
764 if (BITS (4, 7) == 9) {
765 /* MULS */
766 rhs = state->Reg[MULRHSReg];
767
768 //if (MULLHSReg == MULDESTReg) {
769 if(0) {
770 printf("Something in %d line\n", __LINE__);
771 UNDEF_WARNING;
772 UNDEF_MULDestEQOp1;
773 state->Reg[MULDESTReg] = 0;
774 CLEARN;
775 SETZ;
776 } else if (MULDESTReg != 15) {
777 dest = state->Reg[MULLHSReg] * rhs;
778 ARMul_NegZero (state, dest);
779 state->Reg[MULDESTReg] = dest;
780 } else
781 UNDEF_MULPCDest;
782
783 for (dest = 0, temp = 0; dest < 32;
784 dest++)
785 if (rhs & (1L << dest))
786 temp = dest;
787
788 /* Mult takes this many/2 I cycles. */
789 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
790 } else {
791 /* ANDS reg. */
792 rhs = DPSRegRHS;
793 dest = LHS & rhs;
794 WRITESDEST (dest);
795 }
796 break;
797
798 case 0x02: /* EOR reg and MLA */
799#ifdef MODET
800 if (BITS (4, 11) == 0xB) {
801 /* STRH register offset, write-back, down, post indexed. */
802 SHDOWNWB ();
803 break;
804 }
805#endif
806 if (BITS (4, 7) == 9) { /* MLA */
807 rhs = state->Reg[MULRHSReg];
808#if 0
809 if (MULLHSReg == MULDESTReg) {
810 UNDEF_MULDestEQOp1;
811 state->Reg[MULDESTReg] = state->Reg[MULACCReg];
812 } else if (MULDESTReg != 15) {
813#endif
814 if (MULDESTReg != 15) {
815 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
816 } else
817 UNDEF_MULPCDest;
818
819 for (dest = 0, temp = 0; dest < 32;
820 dest++)
821 if (rhs & (1L << dest))
822 temp = dest;
823
824 /* Mult takes this many/2 I cycles. */
825 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
826 } else {
827 rhs = DPRegRHS;
828 dest = LHS ^ rhs;
829 WRITEDEST (dest);
830 }
831 break;
832
833 case 0x03: /* EORS reg and MLAS */
834#ifdef MODET
835 if ((BITS (4, 11) & 0xF9) == 0x9)
836 /* LDR register offset, write-back, down, post-indexed. */
837 LHPOSTDOWN ();
838 /* Fall through to rest of the decoding. */
839#endif
840 if (BITS (4, 7) == 9) {
841 /* MLAS */
842 rhs = state->Reg[MULRHSReg];
843 //if (MULLHSReg == MULDESTReg) {
844 if (0) {
845 UNDEF_MULDestEQOp1;
846 dest = state->Reg[MULACCReg];
847 ARMul_NegZero (state, dest);
848 state->Reg[MULDESTReg] = dest;
849 } else if (MULDESTReg != 15) {
850 dest = state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
851 ARMul_NegZero (state, dest);
852 state->Reg[MULDESTReg] = dest;
853 } else
854 UNDEF_MULPCDest;
855
856 for (dest = 0, temp = 0; dest < 32;
857 dest++)
858 if (rhs & (1L << dest))
859 temp = dest;
860
861 /* Mult takes this many/2 I cycles. */
862 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
863 } else {
864 /* EORS Reg. */
865 rhs = DPSRegRHS;
866 dest = LHS ^ rhs;
867 WRITESDEST (dest);
868 }
869 break;
870
871 case 0x04: /* SUB reg */
872 // Signifies UMAAL
873 if (state->is_v6 && BITS(4, 7) == 0x09) {
874 if (handle_v6_insn(state, instr))
875 break;
876 }
877
878#ifdef MODET
879 if (BITS (4, 7) == 0xB) {
880 /* STRH immediate offset, no write-back, down, post indexed. */
881 SHDOWNWB ();
882 break;
883 }
884 if (BITS (4, 7) == 0xD) {
885 Handle_Load_Double (state, instr);
886 break;
887 }
888 if (BITS (4, 7) == 0xF) {
889 Handle_Store_Double (state, instr);
890 break;
891 }
892#endif
893 rhs = DPRegRHS;
894 dest = LHS - rhs;
895 WRITEDEST (dest);
896 break;
897
898 case 0x05: /* SUBS reg */
899#ifdef MODET
900 if ((BITS (4, 7) & 0x9) == 0x9)
901 /* LDR immediate offset, no write-back, down, post indexed. */
902 LHPOSTDOWN ();
903 /* Fall through to the rest of the instruction decoding. */
904#endif
905 lhs = LHS;
906 rhs = DPRegRHS;
907 dest = lhs - rhs;
908
909 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
910 ARMul_SubCarry (state, lhs, rhs, dest);
911 ARMul_SubOverflow (state, lhs, rhs, dest);
912 } else {
913 CLEARC;
914 CLEARV;
915 }
916 WRITESDEST (dest);
917 break;
918
919 case 0x06: /* RSB reg */
920#ifdef MODET
921 if (BITS (4, 7) == 0xB) {
922 /* STRH immediate offset, write-back, down, post indexed. */
923 SHDOWNWB ();
924 break;
925 }
926#endif
927 rhs = DPRegRHS;
928 dest = rhs - LHS;
929 WRITEDEST (dest);
930 break;
931
932 case 0x07: /* RSBS reg */
933#ifdef MODET
934 if ((BITS (4, 7) & 0x9) == 0x9)
935 /* LDR immediate offset, write-back, down, post indexed. */
936 LHPOSTDOWN ();
937 /* Fall through to remainder of instruction decoding. */
938#endif
939 lhs = LHS;
940 rhs = DPRegRHS;
941 dest = rhs - lhs;
942
943 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
944 ARMul_SubCarry (state, rhs, lhs, dest);
945 ARMul_SubOverflow (state, rhs, lhs, dest);
946 } else {
947 CLEARC;
948 CLEARV;
949 }
950 WRITESDEST (dest);
951 break;
952
953 case 0x08: /* ADD reg */
954#ifdef MODET
955 if (BITS (4, 11) == 0xB) {
956 /* STRH register offset, no write-back, up, post indexed. */
957 SHUPWB ();
958 break;
959 }
960 if (BITS (4, 7) == 0xD) {
961 Handle_Load_Double (state, instr);
962 break;
963 }
964 if (BITS (4, 7) == 0xF) {
965 Handle_Store_Double (state, instr);
966 break;
967 }
968#endif
969#ifdef MODET
970 if (BITS (4, 7) == 0x9) {
971 /* MULL */
972 /* 32x32 = 64 */
973 ARMul_Icycles (state, Multiply64 (state, instr, LUNSIGNED, LDEFAULT), 0L);
974 break;
975 }
976#endif
977 rhs = DPRegRHS;
978 dest = LHS + rhs;
979 WRITEDEST (dest);
980 break;
981
982 case 0x09: /* ADDS reg */
983#ifdef MODET
984 if ((BITS (4, 11) & 0xF9) == 0x9)
985 /* LDR register offset, no write-back, up, post indexed. */
986 LHPOSTUP ();
987 /* Fall through to remaining instruction decoding. */
988#endif
989#ifdef MODET
990 if (BITS (4, 7) == 0x9) {
991 /* MULL */
992 /* 32x32=64 */
993 ARMul_Icycles (state, Multiply64 (state, instr, LUNSIGNED, LSCC), 0L);
994 break;
995 }
996#endif
997 lhs = LHS;
998 rhs = DPRegRHS;
999 dest = lhs + rhs;
1000 ASSIGNZ (dest == 0);
1001 if ((lhs | rhs) >> 30) {
1002 /* Possible C,V,N to set. */
1003 ASSIGNN (NEG (dest));
1004 ARMul_AddCarry (state, lhs, rhs, dest);
1005 ARMul_AddOverflow (state, lhs, rhs, dest);
1006 } else {
1007 CLEARN;
1008 CLEARC;
1009 CLEARV;
1010 }
1011 WRITESDEST (dest);
1012 break;
1013
1014 case 0x0a: /* ADC reg */
1015#ifdef MODET
1016 if (BITS (4, 11) == 0xB) {
1017 /* STRH register offset, write-back, up, post-indexed. */
1018 SHUPWB ();
1019 break;
1020 }
1021 if (BITS (4, 7) == 0x9) {
1022 /* MULL */
1023 /* 32x32=64 */
1024 ARMul_Icycles (state, MultiplyAdd64 (state, instr, LUNSIGNED, LDEFAULT), 0L);
1025 break;
1026 }
1027#endif
1028 rhs = DPRegRHS;
1029 dest = LHS + rhs + CFLAG;
1030 WRITEDEST (dest);
1031 break;
1032
1033 case 0x0b: /* ADCS reg */
1034#ifdef MODET
1035 if ((BITS (4, 11) & 0xF9) == 0x9)
1036 /* LDR register offset, write-back, up, post indexed. */
1037 LHPOSTUP ();
1038 /* Fall through to remaining instruction decoding. */
1039 if (BITS (4, 7) == 0x9) {
1040 /* MULL */
1041 /* 32x32=64 */
1042 ARMul_Icycles (state, MultiplyAdd64 (state, instr, LUNSIGNED, LSCC), 0L);
1043 break;
1044 }
1045#endif
1046 lhs = LHS;
1047 rhs = DPRegRHS;
1048 dest = lhs + rhs + CFLAG;
1049 ASSIGNZ (dest == 0);
1050 if ((lhs | rhs) >> 30) {
1051 /* Possible C,V,N to set. */
1052 ASSIGNN (NEG (dest));
1053 ARMul_AddCarry (state, lhs, rhs, dest);
1054 ARMul_AddOverflow (state, lhs, rhs, dest);
1055 } else {
1056 CLEARN;
1057 CLEARC;
1058 CLEARV;
1059 }
1060 WRITESDEST (dest);
1061 break;
1062
1063 case 0x0c: /* SBC reg */
1064#ifdef MODET
1065 if (BITS (4, 7) == 0xB) {
1066 /* STRH immediate offset, no write-back, up post indexed. */
1067 SHUPWB ();
1068 break;
1069 }
1070 if (BITS (4, 7) == 0xD) {
1071 Handle_Load_Double (state, instr);
1072 break;
1073 }
1074 if (BITS (4, 7) == 0xF) {
1075 Handle_Store_Double (state, instr);
1076 break;
1077 }
1078 if (BITS (4, 7) == 0x9) {
1079 /* MULL */
1080 /* 32x32=64 */
1081 ARMul_Icycles (state, Multiply64 (state, instr, LSIGNED, LDEFAULT), 0L);
1082 break;
1083 }
1084#endif
1085 rhs = DPRegRHS;
1086 dest = LHS - rhs - !CFLAG;
1087 WRITEDEST (dest);
1088 break;
1089
1090 case 0x0d: /* SBCS reg */
1091#ifdef MODET
1092 if ((BITS (4, 7) & 0x9) == 0x9)
1093 /* LDR immediate offset, no write-back, up, post indexed. */
1094 LHPOSTUP ();
1095
1096 if (BITS (4, 7) == 0x9) {
1097 /* MULL */
1098 /* 32x32=64 */
1099 ARMul_Icycles (state, Multiply64 (state, instr, LSIGNED, LSCC), 0L);
1100 break;
1101 }
1102#endif
1103 lhs = LHS;
1104 rhs = DPRegRHS;
1105 dest = lhs - rhs - !CFLAG;
1106 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1107 ARMul_SubCarry (state, lhs, rhs, dest);
1108 ARMul_SubOverflow (state, lhs, rhs, dest);
1109 } else {
1110 CLEARC;
1111 CLEARV;
1112 }
1113 WRITESDEST (dest);
1114 break;
1115
1116 case 0x0e: /* RSC reg */
1117#ifdef MODET
1118 if (BITS (4, 7) == 0xB) {
1119 /* STRH immediate offset, write-back, up, post indexed. */
1120 SHUPWB ();
1121 break;
1122 }
1123
1124 if (BITS (4, 7) == 0x9) {
1125 /* MULL */
1126 /* 32x32=64 */
1127 ARMul_Icycles (state, MultiplyAdd64 (state, instr, LSIGNED, LDEFAULT), 0L);
1128 break;
1129 }
1130#endif
1131 rhs = DPRegRHS;
1132 dest = rhs - LHS - !CFLAG;
1133 WRITEDEST (dest);
1134 break;
1135
1136 case 0x0f: /* RSCS reg */
1137#ifdef MODET
1138 if ((BITS (4, 7) & 0x9) == 0x9)
1139 /* LDR immediate offset, write-back, up, post indexed. */
1140 LHPOSTUP ();
1141 /* Fall through to remaining instruction decoding. */
1142
1143 if (BITS (4, 7) == 0x9) {
1144 /* MULL */
1145 /* 32x32=64 */
1146 ARMul_Icycles (state, MultiplyAdd64 (state, instr, LSIGNED, LSCC), 0L);
1147 break;
1148 }
1149#endif
1150 lhs = LHS;
1151 rhs = DPRegRHS;
1152 dest = rhs - lhs - !CFLAG;
1153
1154 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
1155 ARMul_SubCarry (state, rhs, lhs, dest);
1156 ARMul_SubOverflow (state, rhs, lhs, dest);
1157 } else {
1158 CLEARC;
1159 CLEARV;
1160 }
1161 WRITESDEST (dest);
1162 break;
1163
1164 case 0x10: /* TST reg and MRS CPSR and SWP word. */
1165 if (state->is_v5e) {
1166 if (BIT (4) == 0 && BIT (7) == 1) {
1167 /* ElSegundo SMLAxy insn. */
1168 ARMword op1 = state->Reg[BITS (0, 3)];
1169 ARMword op2 = state->Reg[BITS (8, 11)];
1170 ARMword Rn = state->Reg[BITS (12, 15)];
1171
1172 if (BIT (5))
1173 op1 >>= 16;
1174 if (BIT (6))
1175 op2 >>= 16;
1176 op1 &= 0xFFFF;
1177 op2 &= 0xFFFF;
1178 if (op1 & 0x8000)
1179 op1 -= 65536;
1180 if (op2 & 0x8000)
1181 op2 -= 65536;
1182 op1 *= op2;
1183 //printf("SMLA_INST:BB,op1=0x%x, op2=0x%x. Rn=0x%x\n", op1, op2, Rn);
1184 if (AddOverflow(op1, Rn, op1 + Rn))
1185 SETQ;
1186 state->Reg[BITS (16, 19)] = op1 + Rn;
1187 break;
1188 }
1189
1190 if (BITS (4, 11) == 5) {
1191 /* ElSegundo QADD insn. */
1192 ARMword op1 = state->Reg[BITS (0, 3)];
1193 ARMword op2 = state->Reg[BITS (16, 19)];
1194 ARMword result = op1 + op2;
1195 if (AddOverflow(op1, op2, result)) {
1196 result = POS (result) ? 0x80000000 : 0x7fffffff;
1197 SETQ;
1198 }
1199 state->Reg[BITS (12, 15)] = result;
1200 break;
1201 }
1202 }
1203#ifdef MODET
1204 if (BITS (4, 11) == 0xB) {
1205 /* STRH register offset, no write-back, down, pre indexed. */
1206 SHPREDOWN ();
1207 break;
1208 }
1209 if (BITS (4, 7) == 0xD) {
1210 Handle_Load_Double (state, instr);
1211 break;
1212 }
1213 if (BITS (4, 7) == 0xF) {
1214 Handle_Store_Double (state, instr);
1215 break;
1216 }
1217#endif
1218 if (BITS (4, 11) == 9) {
1219 /* SWP */
1220 UNDEF_SWPPC;
1221 temp = LHS;
1222 BUSUSEDINCPCS;
1223#ifndef MODE32
1224 if (VECTORACCESS (temp) || ADDREXCEPT (temp)) {
1225 INTERNALABORT (temp);
1226 (void) ARMul_LoadWordN (state, temp);
1227 (void) ARMul_LoadWordN (state, temp);
1228 } else
1229#endif
1230 dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
1231 if (temp & 3)
1232 DEST = ARMul_Align (state, temp, dest);
1233 else
1234 DEST = dest;
1235 if (state->abortSig || state->Aborted)
1236 TAKEABORT;
1237 } else if ((BITS (0, 11) == 0) && (LHSReg == 15)) { /* MRS CPSR */
1238 UNDEF_MRSPC;
1239 DEST = ARMul_GetCPSR(state);
1240 } else {
1241 UNDEF_Test;
1242 }
1243 break;
1244
1245 case 0x11: /* TSTP reg */
1246#ifdef MODET
1247 if ((BITS (4, 11) & 0xF9) == 0x9)
1248 /* LDR register offset, no write-back, down, pre indexed. */
1249 LHPREDOWN ();
1250 /* Continue with remaining instruction decode. */
1251#endif
1252 if (DESTReg == 15) {
1253 /* TSTP reg */
1254#ifdef MODE32
1255 //chy 2006-02-15 if in user mode, can not set cpsr 0:23
1256 //from p165 of ARMARM book
1257 state->Cpsr = GETSPSR (state->Bank);
1258 ARMul_CPSRAltered (state);
1259#else
1260 rhs = DPRegRHS;
1261 temp = LHS & rhs;
1262 SETR15PSR (temp);
1263#endif
1264 } else {
1265 /* TST reg */
1266 rhs = DPSRegRHS;
1267 dest = LHS & rhs;
1268 ARMul_NegZero (state, dest);
1269 }
1270 break;
1271
1272 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
1273
1274 if (state->is_v5) {
1275 if (BITS (4, 7) == 3) {
1276 /* BLX(2) */
1277 ARMword temp;
1278
1279 if (TFLAG)
1280 temp = (pc + 2) | 1;
1281 else
1282 temp = pc + 4;
1283
1284 WriteR15Branch (state, state->Reg[RHSReg]);
1285 state->Reg[14] = temp;
1286 break;
1287 }
1288 }
1289
1290 if (state->is_v5e) {
1291 if (BIT (4) == 0 && BIT (7) == 1 && (BIT (5) == 0 || BITS (12, 15) == 0)) {
1292 /* ElSegundo SMLAWy/SMULWy insn. */
1293 unsigned long long op1 = state->Reg[BITS (0, 3)];
1294 unsigned long long op2 = state->Reg[BITS (8, 11)];
1295 unsigned long long result;
1296
1297 if (BIT (6))
1298 op2 >>= 16;
1299 if (op1 & 0x80000000)
1300 op1 -= 1ULL << 32;
1301 op2 &= 0xFFFF;
1302 if (op2 & 0x8000)
1303 op2 -= 65536;
1304 result = (op1 * op2) >> 16;
1305
1306 if (BIT (5) == 0) {
1307 ARMword Rn = state->Reg[BITS(12, 15)];
1308
1309 if (AddOverflow((ARMword)result, Rn, (ARMword)(result + Rn)))
1310 SETQ;
1311 result += Rn;
1312 }
1313 state->Reg[BITS (16, 19)] = (ARMword)result;
1314 break;
1315 }
1316
1317 if (BITS (4, 11) == 5) {
1318 /* ElSegundo QSUB insn. */
1319 ARMword op1 = state->Reg[BITS (0, 3)];
1320 ARMword op2 = state->Reg[BITS (16, 19)];
1321 ARMword result = op1 - op2;
1322
1323 if (SubOverflow
1324 (op1, op2, result)) {
1325 result = POS (result) ? 0x80000000 : 0x7fffffff;
1326 SETQ;
1327 }
1328
1329 state->Reg[BITS (12, 15)] = result;
1330 break;
1331 }
1332 }
1333#ifdef MODET
1334 if (BITS (4, 11) == 0xB) {
1335 /* STRH register offset, write-back, down, pre indexed. */
1336 SHPREDOWNWB ();
1337 break;
1338 }
1339 if (BITS (4, 27) == 0x12FFF1) {
1340 /* BX */
1341 WriteR15Branch (state, state->Reg[RHSReg]);
1342 break;
1343 }
1344 if (BITS (4, 7) == 0xD) {
1345 Handle_Load_Double (state, instr);
1346 break;
1347 }
1348 if (BITS (4, 7) == 0xF) {
1349 Handle_Store_Double (state, instr);
1350 break;
1351 }
1352#endif
1353 if (state->is_v5) {
1354 if (BITS (4, 7) == 0x7) {
1355 //ARMword value;
1356 //extern int SWI_vector_installed;
1357
1358 /* Hardware is allowed to optionally override this
1359 instruction and treat it as a breakpoint. Since
1360 this is a simulator not hardware, we take the position
1361 that if a SWI vector was not installed, then an Abort
1362 vector was probably not installed either, and so
1363 normally this instruction would be ignored, even if an
1364 Abort is generated. This is a bad thing, since GDB
1365 uses this instruction for its breakpoints (at least in
1366 Thumb mode it does). So intercept the instruction here
1367 and generate a breakpoint SWI instead. */
1368 /* Force the next instruction to be refetched. */
1369 state->NextInstr = RESUME;
1370 break;
1371 }
1372 }
1373 if (DESTReg == 15) {
1374 /* MSR reg to CPSR. */
1375 UNDEF_MSRPC;
1376 temp = DPRegRHS;
1377#ifdef MODET
1378 /* Don't allow TBIT to be set by MSR. */
1379 temp &= ~TBIT;
1380#endif
1381 ARMul_FixCPSR (state, instr, temp);
1382 } else
1383 UNDEF_Test;
1384
1385 break;
1386
1387 case 0x13: /* TEQP reg */
1388#ifdef MODET
1389 if ((BITS (4, 11) & 0xF9) == 0x9)
1390 /* LDR register offset, write-back, down, pre indexed. */
1391 LHPREDOWNWB ();
1392 /* Continue with remaining instruction decode. */
1393#endif
1394 if (DESTReg == 15) {
1395 /* TEQP reg */
1396#ifdef MODE32
1397 state->Cpsr = GETSPSR (state->Bank);
1398 ARMul_CPSRAltered (state);
1399#else
1400 rhs = DPRegRHS;
1401 temp = LHS ^ rhs;
1402 SETR15PSR (temp);
1403#endif
1404 } else {
1405 /* TEQ Reg. */
1406 rhs = DPSRegRHS;
1407 dest = LHS ^ rhs;
1408 ARMul_NegZero (state, dest);
1409 }
1410 break;
1411
1412 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
1413 if (state->is_v5e) {
1414 if (BIT (4) == 0 && BIT (7) == 1) {
1415 /* ElSegundo SMLALxy insn. */
1416 unsigned long long op1 = state->Reg[BITS (0, 3)];
1417 unsigned long long op2 = state->Reg[BITS (8, 11)];
1418 unsigned long long dest;
1419 //unsigned long long result;
1420
1421 if (BIT (5))
1422 op1 >>= 16;
1423 if (BIT (6))
1424 op2 >>= 16;
1425 op1 &= 0xFFFF;
1426 if (op1 & 0x8000)
1427 op1 -= 65536;
1428 op2 &= 0xFFFF;
1429 if (op2 & 0x8000)
1430 op2 -= 65536;
1431
1432 dest = (unsigned long long) state->Reg[BITS (16, 19)] << 32;
1433 dest |= state->Reg[BITS (12, 15)];
1434 dest += op1 * op2;
1435 state->Reg[BITS(12, 15)] = (ARMword)dest;
1436 state->Reg[BITS(16, 19)] = (ARMword)(dest >> 32);
1437 break;
1438 }
1439
1440 if (BITS (4, 11) == 5) {
1441 /* ElSegundo QDADD insn. */
1442 ARMword op1 = state->Reg[BITS (0, 3)];
1443 ARMword op2 = state->Reg[BITS (16, 19)];
1444 ARMword op2d = op2 + op2;
1445 ARMword result;
1446
1447 if (AddOverflow
1448 (op2, op2, op2d)) {
1449 SETQ;
1450 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1451 }
1452
1453 result = op1 + op2d;
1454 if (AddOverflow(op1, op2d, result)) {
1455 SETQ;
1456 result = POS (result) ? 0x80000000 : 0x7fffffff;
1457 }
1458
1459 state->Reg[BITS (12, 15)] = result;
1460 break;
1461 }
1462 }
1463#ifdef MODET
1464 if (BITS (4, 7) == 0xB) {
1465 /* STRH immediate offset, no write-back, down, pre indexed. */
1466 SHPREDOWN ();
1467 break;
1468 }
1469 if (BITS (4, 7) == 0xD) {
1470 Handle_Load_Double (state, instr);
1471 break;
1472 }
1473 if (BITS (4, 7) == 0xF) {
1474 Handle_Store_Double (state, instr);
1475 break;
1476 }
1477#endif
1478 if (BITS (4, 11) == 9) {
1479 /* SWP */
1480 UNDEF_SWPPC;
1481 temp = LHS;
1482 BUSUSEDINCPCS;
1483#ifndef MODE32
1484 if (VECTORACCESS (temp) || ADDREXCEPT (temp)) {
1485 INTERNALABORT (temp);
1486 (void) ARMul_LoadByte (state, temp);
1487 (void) ARMul_LoadByte (state, temp);
1488 } else
1489#endif
1490 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
1491 if (state->abortSig || state->Aborted)
1492 TAKEABORT;
1493 } else if ((BITS (0, 11) == 0)
1494 && (LHSReg == 15)) {
1495 /* MRS SPSR */
1496 UNDEF_MRSPC;
1497 DEST = GETSPSR (state->Bank);
1498 } else
1499 UNDEF_Test;
1500
1501 break;
1502
1503 case 0x15: /* CMPP reg. */
1504#ifdef MODET
1505 if ((BITS (4, 7) & 0x9) == 0x9)
1506 /* LDR immediate offset, no write-back, down, pre indexed. */
1507 LHPREDOWN ();
1508 /* Continue with remaining instruction decode. */
1509#endif
1510 if (DESTReg == 15) {
1511 /* CMPP reg. */
1512#ifdef MODE32
1513 state->Cpsr = GETSPSR (state->Bank);
1514 ARMul_CPSRAltered (state);
1515#else
1516 rhs = DPRegRHS;
1517 temp = LHS - rhs;
1518 SETR15PSR (temp);
1519#endif
1520 } else {
1521 /* CMP reg. */
1522 lhs = LHS;
1523 rhs = DPRegRHS;
1524 dest = lhs - rhs;
1525 ARMul_NegZero (state, dest);
1526 if ((lhs >= rhs)
1527 || ((rhs | lhs) >> 31)) {
1528 ARMul_SubCarry (state, lhs, rhs, dest);
1529 ARMul_SubOverflow (state, lhs, rhs, dest);
1530 } else {
1531 CLEARC;
1532 CLEARV;
1533 }
1534 }
1535 break;
1536
1537 case 0x16: /* CMN reg and MSR reg to SPSR */
1538 if (state->is_v5e) {
1539 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0) {
1540 /* ElSegundo SMULxy insn. */
1541 ARMword op1 = state->Reg[BITS (0, 3)];
1542 ARMword op2 = state->Reg[BITS (8, 11)];
1543 ARMword Rn = state->Reg[BITS (12, 15)];
1544
1545 if (BIT (5))
1546 op1 >>= 16;
1547 if (BIT (6))
1548 op2 >>= 16;
1549 op1 &= 0xFFFF;
1550 op2 &= 0xFFFF;
1551 if (op1 & 0x8000)
1552 op1 -= 65536;
1553 if (op2 & 0x8000)
1554 op2 -= 65536;
1555
1556 state->Reg[BITS (16, 19)] = op1 * op2;
1557 break;
1558 }
1559
1560 if (BITS (4, 11) == 5) {
1561 /* ElSegundo QDSUB insn. */
1562 ARMword op1 = state->Reg[BITS (0, 3)];
1563 ARMword op2 = state->Reg[BITS (16, 19)];
1564 ARMword op2d = op2 + op2;
1565 ARMword result;
1566
1567 if (AddOverflow(op2, op2, op2d)) {
1568 SETQ;
1569 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1570 }
1571
1572 result = op1 - op2d;
1573 if (SubOverflow(op1, op2d, result)) {
1574 SETQ;
1575 result = POS (result) ? 0x80000000 : 0x7fffffff;
1576 }
1577
1578 state->Reg[BITS (12, 15)] = result;
1579 break;
1580 }
1581 }
1582
1583 if (state->is_v5) {
1584 if (BITS (4, 11) == 0xF1
1585 && BITS (16, 19) == 0xF) {
1586 /* ARM5 CLZ insn. */
1587 ARMword op1 = state->Reg[BITS (0, 3)];
1588 int result = 32;
1589
1590 if (op1)
1591 for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
1592 result++;
1593 state->Reg[BITS (12, 15)] = result;
1594 break;
1595 }
1596 }
1597
1598#ifdef MODET
1599 if (BITS (4, 7) == 0xB) {
1600 /* STRH immediate offset, write-back, down, pre indexed. */
1601 SHPREDOWNWB ();
1602 break;
1603 }
1604 if (BITS (4, 7) == 0xD) {
1605 Handle_Load_Double (state, instr);
1606 break;
1607 }
1608 if (BITS (4, 7) == 0xF) {
1609 Handle_Store_Double (state, instr);
1610 break;
1611 }
1612#endif
1613 if (DESTReg == 15) {
1614 /* MSR */
1615 UNDEF_MSRPC;
1616 /*ARMul_FixSPSR (state, instr,
1617 DPRegRHS);*/
1618 } else {
1619 UNDEF_Test;
1620 }
1621 break;
1622
1623 case 0x17: /* CMNP reg */
1624#ifdef MODET
1625 if ((BITS (4, 7) & 0x9) == 0x9)
1626 /* LDR immediate offset, write-back, down, pre indexed. */
1627 LHPREDOWNWB ();
1628 /* Continue with remaining instruction decoding. */
1629#endif
1630 if (DESTReg == 15) {
1631#ifdef MODE32
1632 state->Cpsr = GETSPSR (state->Bank);
1633 ARMul_CPSRAltered (state);
1634#else
1635 rhs = DPRegRHS;
1636 temp = LHS + rhs;
1637 SETR15PSR (temp);
1638#endif
1639 break;
1640 } else {
1641 /* CMN reg. */
1642 lhs = LHS;
1643 rhs = DPRegRHS;
1644 dest = lhs + rhs;
1645 ASSIGNZ (dest == 0);
1646 if ((lhs | rhs) >> 30) {
1647 /* Possible C,V,N to set. */
1648 ASSIGNN (NEG (dest));
1649 ARMul_AddCarry (state, lhs, rhs, dest);
1650 ARMul_AddOverflow (state, lhs, rhs, dest);
1651 } else {
1652 CLEARN;
1653 CLEARC;
1654 CLEARV;
1655 }
1656 }
1657 break;
1658
1659 case 0x18: /* ORR reg */
1660#ifdef MODET
1661 /* dyf add armv6 instr strex 2010.9.17 */
1662 if (state->is_v6) {
1663 if (BITS (4, 7) == 0x9)
1664 if (handle_v6_insn (state, instr))
1665 break;
1666 }
1667
1668 if (BITS (4, 11) == 0xB) {
1669 /* STRH register offset, no write-back, up, pre indexed. */
1670 SHPREUP ();
1671 break;
1672 }
1673 if (BITS (4, 7) == 0xD) {
1674 Handle_Load_Double (state, instr);
1675 break;
1676 }
1677 if (BITS (4, 7) == 0xF) {
1678 Handle_Store_Double (state, instr);
1679 break;
1680 }
1681#endif
1682 rhs = DPRegRHS;
1683 dest = LHS | rhs;
1684 WRITEDEST (dest);
1685 break;
1686
1687 case 0x19: /* ORRS reg */
1688#ifdef MODET
1689 /* dyf add armv6 instr ldrex */
1690 if (state->is_v6) {
1691 if (BITS (4, 7) == 0x9) {
1692 if (handle_v6_insn (state, instr))
1693 break;
1694 }
1695 }
1696 if ((BITS (4, 11) & 0xF9) == 0x9)
1697 /* LDR register offset, no write-back, up, pre indexed. */
1698 LHPREUP ();
1699 /* Continue with remaining instruction decoding. */
1700#endif
1701 rhs = DPSRegRHS;
1702 dest = LHS | rhs;
1703 WRITESDEST (dest);
1704 break;
1705
1706 case 0x1a: /* MOV reg */
1707#ifdef MODET
1708 if (BITS (4, 11) == 0xB) {
1709 /* STRH register offset, write-back, up, pre indexed. */
1710 SHPREUPWB ();
1711 break;
1712 }
1713 if (BITS (4, 7) == 0xD) {
1714 Handle_Load_Double (state, instr);
1715 break;
1716 }
1717 if (BITS (4, 7) == 0xF) {
1718 Handle_Store_Double (state, instr);
1719 break;
1720 }
1721 if (BITS(4, 11) == 0xF9) { //strexd
1722 u32 l = LHSReg;
1723
1724 bool enter = false;
1725
1726 if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr)&&
1727 state->currentexvald == (u32)ARMul_ReadWord(state, state->currentexaddr + 4))
1728 enter = true;
1729
1730 //todo bug this and STREXD and LDREXD http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0360e/CHDGJGGC.html
1731
1732 if (enter) {
1733 ARMul_StoreWordN(state, LHS, state->Reg[RHSReg]);
1734 ARMul_StoreWordN(state,LHS + 4 , state->Reg[RHSReg + 1]);
1735 state->Reg[DESTReg] = 0;
1736 } else {
1737 state->Reg[DESTReg] = 1;
1738 }
1739
1740 break;
1741 }
1742#endif
1743 dest = DPRegRHS;
1744 WRITEDEST (dest);
1745 break;
1746
1747 case 0x1B: /* MOVS reg */
1748#ifdef MODET
1749 /* ldrexd ichfly */
1750 if (BITS(0, 11) == 0xF9F) { //strexd
1751 lhs = LHS;
1752
1753 state->currentexaddr = lhs;
1754 state->currentexval = (u32)ARMul_ReadWord(state, lhs);
1755 state->currentexvald = (u32)ARMul_ReadWord(state, lhs + 4);
1756
1757 state->Reg[DESTReg] = ARMul_LoadWordN(state, lhs);
1758 state->Reg[DESTReg] = ARMul_LoadWordN(state, lhs + 4);
1759 break;
1760 }
1761
1762 if ((BITS (4, 11) & 0xF9) == 0x9)
1763 /* LDR register offset, write-back, up, pre indexed. */
1764 LHPREUPWB ();
1765 /* Continue with remaining instruction decoding. */
1766
1767#endif
1768 dest = DPSRegRHS;
1769 WRITESDEST (dest);
1770 break;
1771
1772 case 0x1c: /* BIC reg */
1773#ifdef MODET
1774 /* dyf add for STREXB */
1775 if (state->is_v6) {
1776 if (BITS (4, 7) == 0x9) {
1777 if (handle_v6_insn (state, instr))
1778 break;
1779 }
1780 }
1781 if (BITS (4, 7) == 0xB) {
1782 /* STRH immediate offset, no write-back, up, pre indexed. */
1783 SHPREUP ();
1784 break;
1785 }
1786 if (BITS (4, 7) == 0xD) {
1787 Handle_Load_Double (state, instr);
1788 break;
1789 } else if (BITS (4, 7) == 0xF) {
1790 Handle_Store_Double (state, instr);
1791 break;
1792 }
1793#endif
1794 rhs = DPRegRHS;
1795 dest = LHS & ~rhs;
1796 WRITEDEST (dest);
1797 break;
1798
1799 case 0x1d: /* BICS reg */
1800#ifdef MODET
1801 /* ladsh P=1 U=1 W=0 L=1 S=1 H=1 */
1802 if (BITS(4, 7) == 0xF) {
1803 temp = LHS + GetLS7RHS (state, instr);
1804 LoadHalfWord (state, instr, temp, LSIGNED);
1805 break;
1806 }
1807 if (BITS (4, 7) == 0xb) {
1808 /* LDRH immediate offset, no write-back, up, pre indexed. */
1809 temp = LHS + GetLS7RHS (state, instr);
1810 LoadHalfWord (state, instr, temp, LUNSIGNED);
1811 break;
1812 }
1813 if (BITS (4, 7) == 0xd) {
1814 // alex-ykl fix: 2011-07-20 missing ldrsb instruction
1815 temp = LHS + GetLS7RHS (state, instr);
1816 LoadByte (state, instr, temp, LSIGNED);
1817 break;
1818 }
1819
1820 /* Continue with instruction decoding. */
1821 /*if ((BITS (4, 7) & 0x9) == 0x9) */
1822 if ((BITS (4, 7)) == 0x9) {
1823 /* ldrexb */
1824 if (state->is_v6) {
1825 if (handle_v6_insn (state, instr))
1826 break;
1827 }
1828 /* LDR immediate offset, no write-back, up, pre indexed. */
1829 LHPREUP ();
1830 }
1831
1832#endif
1833 rhs = DPSRegRHS;
1834 dest = LHS & ~rhs;
1835 WRITESDEST (dest);
1836 break;
1837
1838 case 0x1e: /* MVN reg */
1839#ifdef MODET
1840 if ((instr & 0x00000FF0) == 0x00000F90) { //if ((instr & 0x0FF00FF0) == 0x01e00f90) { //todo make that better ichfly
1841 /* strexh ichfly */
1842 u32 l = LHSReg;
1843 u32 r = RHSReg;
1844 lhs = LHS;
1845
1846 bool enter = false;
1847
1848 if (state->currentexval == (u32)ARMul_LoadHalfWord(state, state->currentexaddr))enter = true;
1849
1850 //StoreWord(state, lhs, RHS)
1851 if (state->Aborted) {
1852 TAKEABORT;
1853 }
1854 if (enter) {
1855 ARMul_StoreHalfWord(state, lhs, RHS);
1856 state->Reg[DESTReg] = 0;
1857 } else {
1858 state->Reg[DESTReg] = 1;
1859 }
1860 break;
1861 }
1862 if (BITS (4, 7) == 0xB) {
1863 /* STRH immediate offset, write-back, up, pre indexed. */
1864 SHPREUPWB ();
1865 break;
1866 }
1867 if (BITS (4, 7) == 0xD) {
1868 Handle_Load_Double (state, instr);
1869 break;
1870 }
1871 if (BITS (4, 7) == 0xF) {
1872 Handle_Store_Double (state, instr);
1873 break;
1874 }
1875#endif
1876 dest = ~DPRegRHS;
1877 WRITEDEST (dest);
1878 break;
1879
1880 case 0x1f: /* MVNS reg */
1881#ifdef MODET
1882
1883 if ((instr & 0x00000FF0) == 0x00000F90) { //(instr & 0x0FF00FF0) == 0x01f00f90)//if ((instr & 0x0FF00FF0) == 0x01f00f90) {
1884 /* ldrexh ichfly */
1885 lhs = LHS;
1886
1887 state->currentexaddr = lhs;
1888 state->currentexval = (u32)ARMul_LoadHalfWord(state, lhs);
1889
1890 LoadHalfWord(state, instr, lhs,0);
1891 break;
1892 }
1893
1894 if ((BITS (4, 7) & 0x9) == 0x9)
1895 /* LDR immediate offset, write-back, up, pre indexed. */
1896 LHPREUPWB ();
1897 /* Continue instruction decoding. */
1898#endif
1899 dest = ~DPSRegRHS;
1900 WRITESDEST (dest);
1901 break;
1902
1903 /* Data Processing Immediate RHS Instructions. */
1904
1905 case 0x20: /* AND immed */
1906 dest = LHS & DPImmRHS;
1907 WRITEDEST (dest);
1908 break;
1909
1910 case 0x21: /* ANDS immed */
1911 DPSImmRHS;
1912 dest = LHS & rhs;
1913 WRITESDEST (dest);
1914 break;
1915
1916 case 0x22: /* EOR immed */
1917 dest = LHS ^ DPImmRHS;
1918 WRITEDEST (dest);
1919 break;
1920
1921 case 0x23: /* EORS immed */
1922 DPSImmRHS;
1923 dest = LHS ^ rhs;
1924 WRITESDEST (dest);
1925 break;
1926
1927 case 0x24: /* SUB immed */
1928 dest = LHS - DPImmRHS;
1929 WRITEDEST (dest);
1930 break;
1931
1932 case 0x25: /* SUBS immed */
1933 lhs = LHS;
1934 rhs = DPImmRHS;
1935 dest = lhs - rhs;
1936
1937 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
1938 ARMul_SubCarry (state, lhs, rhs, dest);
1939 ARMul_SubOverflow (state, lhs, rhs, dest);
1940 } else {
1941 CLEARC;
1942 CLEARV;
1943 }
1944 WRITESDEST (dest);
1945 break;
1946
1947 case 0x26: /* RSB immed */
1948 dest = DPImmRHS - LHS;
1949 WRITEDEST (dest);
1950 break;
1951
1952 case 0x27: /* RSBS immed */
1953 lhs = LHS;
1954 rhs = DPImmRHS;
1955 dest = rhs - lhs;
1956
1957 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
1958 ARMul_SubCarry (state, rhs, lhs, dest);
1959 ARMul_SubOverflow (state, rhs, lhs, dest);
1960 } else {
1961 CLEARC;
1962 CLEARV;
1963 }
1964 WRITESDEST (dest);
1965 break;
1966
1967 case 0x28: /* ADD immed */
1968 dest = LHS + DPImmRHS;
1969 WRITEDEST (dest);
1970 break;
1971
1972 case 0x29: /* ADDS immed */
1973 lhs = LHS;
1974 rhs = DPImmRHS;
1975 dest = lhs + rhs;
1976 ASSIGNZ (dest == 0);
1977
1978 if ((lhs | rhs) >> 30) {
1979 /* Possible C,V,N to set. */
1980 ASSIGNN (NEG (dest));
1981 ARMul_AddCarry (state, lhs, rhs, dest);
1982 ARMul_AddOverflow (state, lhs, rhs, dest);
1983 } else {
1984 CLEARN;
1985 CLEARC;
1986 CLEARV;
1987 }
1988 WRITESDEST (dest);
1989 break;
1990
1991 case 0x2a: /* ADC immed */
1992 dest = LHS + DPImmRHS + CFLAG;
1993 WRITEDEST (dest);
1994 break;
1995
1996 case 0x2b: /* ADCS immed */
1997 lhs = LHS;
1998 rhs = DPImmRHS;
1999 dest = lhs + rhs + CFLAG;
2000 ASSIGNZ (dest == 0);
2001 if ((lhs | rhs) >> 30) {
2002 /* Possible C,V,N to set. */
2003 ASSIGNN (NEG (dest));
2004 ARMul_AddCarry (state, lhs, rhs, dest);
2005 ARMul_AddOverflow (state, lhs, rhs, dest);
2006 } else {
2007 CLEARN;
2008 CLEARC;
2009 CLEARV;
2010 }
2011 WRITESDEST (dest);
2012 break;
2013
2014 case 0x2c: /* SBC immed */
2015 dest = LHS - DPImmRHS - !CFLAG;
2016 WRITEDEST (dest);
2017 break;
2018
2019 case 0x2d: /* SBCS immed */
2020 lhs = LHS;
2021 rhs = DPImmRHS;
2022 dest = lhs - rhs - !CFLAG;
2023 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
2024 ARMul_SubCarry (state, lhs, rhs, dest);
2025 ARMul_SubOverflow (state, lhs, rhs, dest);
2026 } else {
2027 CLEARC;
2028 CLEARV;
2029 }
2030 WRITESDEST (dest);
2031 break;
2032
2033 case 0x2e: /* RSC immed */
2034 dest = DPImmRHS - LHS - !CFLAG;
2035 WRITEDEST (dest);
2036 break;
2037
2038 case 0x2f: /* RSCS immed */
2039 lhs = LHS;
2040 rhs = DPImmRHS;
2041 dest = rhs - lhs - !CFLAG;
2042 if ((rhs >= lhs) || ((rhs | lhs) >> 31)) {
2043 ARMul_SubCarry (state, rhs, lhs, dest);
2044 ARMul_SubOverflow (state, rhs, lhs, dest);
2045 } else {
2046 CLEARC;
2047 CLEARV;
2048 }
2049 WRITESDEST (dest);
2050 break;
2051
2052 case 0x30: /* TST immed */
2053 /* shenoubang 2012-3-14*/
2054 if (state->is_v6) { /* movw, ARMV6, ARMv7 */
2055 dest ^= dest;
2056 dest = BITS(16, 19);
2057 dest = ((dest<<12) | BITS(0, 11));
2058 WRITEDEST(dest);
2059 break;
2060 } else {
2061 UNDEF_Test;
2062 break;
2063 }
2064
2065 case 0x31: /* TSTP immed */
2066 if (DESTReg == 15) {
2067 /* TSTP immed. */
2068#ifdef MODE32
2069 state->Cpsr = GETSPSR (state->Bank);
2070 ARMul_CPSRAltered (state);
2071#else
2072 temp = LHS & DPImmRHS;
2073 SETR15PSR (temp);
2074#endif
2075 } else {
2076 /* TST immed. */
2077 DPSImmRHS;
2078 dest = LHS & rhs;
2079 ARMul_NegZero (state, dest);
2080 }
2081 break;
2082
2083 case 0x32: /* TEQ immed and MSR immed to CPSR */
2084 if (DESTReg == 15)
2085 /* MSR immed to CPSR. */
2086 ARMul_FixCPSR (state, instr,
2087 DPImmRHS);
2088 else
2089 UNDEF_Test;
2090 break;
2091
2092 case 0x33: /* TEQP immed */
2093 if (DESTReg == 15) {
2094 /* TEQP immed. */
2095#ifdef MODE32
2096 state->Cpsr = GETSPSR (state->Bank);
2097 ARMul_CPSRAltered (state);
2098#else
2099 temp = LHS ^ DPImmRHS;
2100 SETR15PSR (temp);
2101#endif
2102 } else {
2103 DPSImmRHS; /* TEQ immed */
2104 dest = LHS ^ rhs;
2105 ARMul_NegZero (state, dest);
2106 }
2107 break;
2108
2109 case 0x34: /* CMP immed */
2110 UNDEF_Test;
2111 break;
2112
2113 case 0x35: /* CMPP immed */
2114 if (DESTReg == 15) {
2115 /* CMPP immed. */
2116#ifdef MODE32
2117 state->Cpsr = GETSPSR (state->Bank);
2118 ARMul_CPSRAltered (state);
2119#else
2120 temp = LHS - DPImmRHS;
2121 SETR15PSR (temp);
2122#endif
2123 break;
2124 } else {
2125 /* CMP immed. */
2126 lhs = LHS;
2127 rhs = DPImmRHS;
2128 dest = lhs - rhs;
2129 ARMul_NegZero (state, dest);
2130
2131 if ((lhs >= rhs) || ((rhs | lhs) >> 31)) {
2132 ARMul_SubCarry (state, lhs, rhs, dest);
2133 ARMul_SubOverflow (state, lhs, rhs, dest);
2134 } else {
2135 CLEARC;
2136 CLEARV;
2137 }
2138 }
2139 break;
2140
2141 case 0x36: /* CMN immed and MSR immed to SPSR */
2142 //if (DESTReg == 15)
2143 /*ARMul0_FixSPSR (state, instr,
2144 DPImmRHS);*/
2145 //else
2146 UNDEF_Test;
2147 break;
2148
2149 case 0x37: /* CMNP immed. */
2150 if (DESTReg == 15) {
2151 /* CMNP immed. */
2152#ifdef MODE32
2153 state->Cpsr = GETSPSR (state->Bank);
2154 ARMul_CPSRAltered (state);
2155#else
2156 temp = LHS + DPImmRHS;
2157 SETR15PSR (temp);
2158#endif
2159 break;
2160 } else {
2161 /* CMN immed. */
2162 lhs = LHS;
2163 rhs = DPImmRHS;
2164 dest = lhs + rhs;
2165 ASSIGNZ (dest == 0);
2166 if ((lhs | rhs) >> 30) {
2167 /* Possible C,V,N to set. */
2168 ASSIGNN (NEG (dest));
2169 ARMul_AddCarry (state, lhs, rhs, dest);
2170 ARMul_AddOverflow (state, lhs, rhs, dest);
2171 } else {
2172 CLEARN;
2173 CLEARC;
2174 CLEARV;
2175 }
2176 }
2177 break;
2178
2179 case 0x38: /* ORR immed. */
2180 dest = LHS | DPImmRHS;
2181 WRITEDEST (dest);
2182 break;
2183
2184 case 0x39: /* ORRS immed. */
2185 DPSImmRHS;
2186 dest = LHS | rhs;
2187 WRITESDEST (dest);
2188 break;
2189
2190 case 0x3a: /* MOV immed. */
2191 dest = DPImmRHS;
2192 WRITEDEST (dest);
2193 break;
2194
2195 case 0x3b: /* MOVS immed. */
2196 DPSImmRHS;
2197 WRITESDEST (rhs);
2198 break;
2199
2200 case 0x3c: /* BIC immed. */
2201 dest = LHS & ~DPImmRHS;
2202 WRITEDEST (dest);
2203 break;
2204
2205 case 0x3d: /* BICS immed. */
2206 DPSImmRHS;
2207 dest = LHS & ~rhs;
2208 WRITESDEST (dest);
2209 break;
2210
2211 case 0x3e: /* MVN immed. */
2212 dest = ~DPImmRHS;
2213 WRITEDEST (dest);
2214 break;
2215
2216 case 0x3f: /* MVNS immed. */
2217 DPSImmRHS;
2218 WRITESDEST (~rhs);
2219 break;
2220
2221 /* Single Data Transfer Immediate RHS Instructions. */
2222
2223 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2224 lhs = LHS;
2225 if (StoreWord (state, instr, lhs))
2226 LSBase = lhs - LSImmRHS;
2227 break;
2228
2229 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2230 lhs = LHS;
2231 if (LoadWord (state, instr, lhs))
2232 LSBase = lhs - LSImmRHS;
2233 break;
2234
2235 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2236 UNDEF_LSRBaseEQDestWb;
2237 UNDEF_LSRPCBaseWb;
2238 lhs = LHS;
2239 temp = lhs - LSImmRHS;
2240 state->NtransSig = LOW;
2241 if (StoreWord (state, instr, lhs))
2242 LSBase = temp;
2243 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2244 break;
2245
2246 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2247 UNDEF_LSRBaseEQDestWb;
2248 UNDEF_LSRPCBaseWb;
2249 lhs = LHS;
2250 state->NtransSig = LOW;
2251 if (LoadWord (state, instr, lhs))
2252 LSBase = lhs - LSImmRHS;
2253 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2254 break;
2255
2256 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2257 lhs = LHS;
2258 if (StoreByte (state, instr, lhs))
2259 LSBase = lhs - LSImmRHS;
2260 break;
2261
2262 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2263 lhs = LHS;
2264 if (LoadByte (state, instr, lhs, LUNSIGNED))
2265 LSBase = lhs - LSImmRHS;
2266 break;
2267
2268 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2269 UNDEF_LSRBaseEQDestWb;
2270 UNDEF_LSRPCBaseWb;
2271 lhs = LHS;
2272 state->NtransSig = LOW;
2273 if (StoreByte (state, instr, lhs))
2274 LSBase = lhs - LSImmRHS;
2275 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2276 break;
2277
2278 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2279 UNDEF_LSRBaseEQDestWb;
2280 UNDEF_LSRPCBaseWb;
2281 lhs = LHS;
2282 state->NtransSig = LOW;
2283 if (LoadByte (state, instr, lhs, LUNSIGNED))
2284 LSBase = lhs - LSImmRHS;
2285 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2286 break;
2287
2288 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2289 lhs = LHS;
2290 if (StoreWord (state, instr, lhs))
2291 LSBase = lhs + LSImmRHS;
2292 break;
2293
2294 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2295 lhs = LHS;
2296 if (LoadWord (state, instr, lhs))
2297 LSBase = lhs + LSImmRHS;
2298 break;
2299
2300 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2301 UNDEF_LSRBaseEQDestWb;
2302 UNDEF_LSRPCBaseWb;
2303 lhs = LHS;
2304 state->NtransSig = LOW;
2305 if (StoreWord (state, instr, lhs))
2306 LSBase = lhs + LSImmRHS;
2307 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2308 break;
2309
2310 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2311 UNDEF_LSRBaseEQDestWb;
2312 UNDEF_LSRPCBaseWb;
2313 lhs = LHS;
2314 state->NtransSig = LOW;
2315 if (LoadWord (state, instr, lhs))
2316 LSBase = lhs + LSImmRHS;
2317 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2318 break;
2319
2320 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2321 lhs = LHS;
2322 if (StoreByte (state, instr, lhs))
2323 LSBase = lhs + LSImmRHS;
2324 break;
2325
2326 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2327 lhs = LHS;
2328 if (LoadByte (state, instr, lhs, LUNSIGNED))
2329 LSBase = lhs + LSImmRHS;
2330 break;
2331
2332 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2333 UNDEF_LSRBaseEQDestWb;
2334 UNDEF_LSRPCBaseWb;
2335 lhs = LHS;
2336 state->NtransSig = LOW;
2337 if (StoreByte (state, instr, lhs))
2338 LSBase = lhs + LSImmRHS;
2339 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2340 break;
2341
2342 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2343 UNDEF_LSRBaseEQDestWb;
2344 UNDEF_LSRPCBaseWb;
2345 lhs = LHS;
2346 state->NtransSig = LOW;
2347 if (LoadByte (state, instr, lhs, LUNSIGNED))
2348 LSBase = lhs + LSImmRHS;
2349 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2350 break;
2351
2352 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2353 (void) StoreWord (state, instr, LHS - LSImmRHS);
2354 break;
2355
2356 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2357 (void) LoadWord (state, instr, LHS - LSImmRHS);
2358 break;
2359
2360 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2361 UNDEF_LSRBaseEQDestWb;
2362 UNDEF_LSRPCBaseWb;
2363 temp = LHS - LSImmRHS;
2364 if (StoreWord (state, instr, temp))
2365 LSBase = temp;
2366 break;
2367
2368 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2369 UNDEF_LSRBaseEQDestWb;
2370 UNDEF_LSRPCBaseWb;
2371 temp = LHS - LSImmRHS;
2372 if (LoadWord (state, instr, temp))
2373 LSBase = temp;
2374 break;
2375
2376 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2377 (void) StoreByte (state, instr, LHS - LSImmRHS);
2378 break;
2379
2380 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2381 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
2382 break;
2383
2384 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2385 UNDEF_LSRBaseEQDestWb;
2386 UNDEF_LSRPCBaseWb;
2387 temp = LHS - LSImmRHS;
2388 if (StoreByte (state, instr, temp))
2389 LSBase = temp;
2390 break;
2391
2392 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2393 UNDEF_LSRBaseEQDestWb;
2394 UNDEF_LSRPCBaseWb;
2395 temp = LHS - LSImmRHS;
2396 if (LoadByte (state, instr, temp, LUNSIGNED))
2397 LSBase = temp;
2398 break;
2399
2400 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2401 (void) StoreWord (state, instr, LHS + LSImmRHS);
2402 break;
2403
2404 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2405 (void) LoadWord (state, instr, LHS + LSImmRHS);
2406 break;
2407
2408 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2409 UNDEF_LSRBaseEQDestWb;
2410 UNDEF_LSRPCBaseWb;
2411 temp = LHS + LSImmRHS;
2412 if (StoreWord (state, instr, temp))
2413 LSBase = temp;
2414 break;
2415
2416 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2417 UNDEF_LSRBaseEQDestWb;
2418 UNDEF_LSRPCBaseWb;
2419 temp = LHS + LSImmRHS;
2420 if (LoadWord (state, instr, temp))
2421 LSBase = temp;
2422 break;
2423
2424 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2425 (void) StoreByte (state, instr, LHS + LSImmRHS);
2426 break;
2427
2428 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2429 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
2430 break;
2431
2432 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2433 UNDEF_LSRBaseEQDestWb;
2434 UNDEF_LSRPCBaseWb;
2435 temp = LHS + LSImmRHS;
2436 if (StoreByte (state, instr, temp))
2437 LSBase = temp;
2438 break;
2439
2440 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2441 UNDEF_LSRBaseEQDestWb;
2442 UNDEF_LSRPCBaseWb;
2443 temp = LHS + LSImmRHS;
2444 if (LoadByte (state, instr, temp, LUNSIGNED))
2445 LSBase = temp;
2446 break;
2447
2448 /* Single Data Transfer Register RHS Instructions. */
2449
2450 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2451 if (BIT (4)) {
2452 ARMul_UndefInstr (state, instr);
2453 break;
2454 }
2455 UNDEF_LSRBaseEQOffWb;
2456 UNDEF_LSRBaseEQDestWb;
2457 UNDEF_LSRPCBaseWb;
2458 UNDEF_LSRPCOffWb;
2459 lhs = LHS;
2460 if (StoreWord (state, instr, lhs))
2461 LSBase = lhs - LSRegRHS;
2462 break;
2463
2464 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2465 if (BIT (4)) {
2466#ifdef MODE32
2467 if (state->is_v6 && handle_v6_insn (state, instr))
2468 break;
2469#endif
2470 ARMul_UndefInstr (state, instr);
2471 break;
2472 }
2473 UNDEF_LSRBaseEQOffWb;
2474 UNDEF_LSRBaseEQDestWb;
2475 UNDEF_LSRPCBaseWb;
2476 UNDEF_LSRPCOffWb;
2477 lhs = LHS;
2478 temp = lhs - LSRegRHS;
2479 if (LoadWord (state, instr, lhs))
2480 LSBase = temp;
2481 break;
2482
2483 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2484 if (BIT (4)) {
2485#ifdef MODE32
2486 if (state->is_v6 && handle_v6_insn (state, instr))
2487 break;
2488#endif
2489 ARMul_UndefInstr (state, instr);
2490 break;
2491 }
2492 UNDEF_LSRBaseEQOffWb;
2493 UNDEF_LSRBaseEQDestWb;
2494 UNDEF_LSRPCBaseWb;
2495 UNDEF_LSRPCOffWb;
2496 lhs = LHS;
2497 state->NtransSig = LOW;
2498 if (StoreWord (state, instr, lhs))
2499 LSBase = lhs - LSRegRHS;
2500 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2501 break;
2502
2503 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2504 if (BIT (4)) {
2505#ifdef MODE32
2506 if (state->is_v6 && handle_v6_insn (state, instr))
2507 break;
2508#endif
2509 ARMul_UndefInstr (state, instr);
2510 break;
2511 }
2512 UNDEF_LSRBaseEQOffWb;
2513 UNDEF_LSRBaseEQDestWb;
2514 UNDEF_LSRPCBaseWb;
2515 UNDEF_LSRPCOffWb;
2516 lhs = LHS;
2517 temp = lhs - LSRegRHS;
2518 state->NtransSig = LOW;
2519 if (LoadWord (state, instr, lhs))
2520 LSBase = temp;
2521 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2522 break;
2523
2524 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2525 if (BIT (4)) {
2526 ARMul_UndefInstr (state, instr);
2527 break;
2528 }
2529 UNDEF_LSRBaseEQOffWb;
2530 UNDEF_LSRBaseEQDestWb;
2531 UNDEF_LSRPCBaseWb;
2532 UNDEF_LSRPCOffWb;
2533 lhs = LHS;
2534 if (StoreByte (state, instr, lhs))
2535 LSBase = lhs - LSRegRHS;
2536 break;
2537
2538 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2539 if (BIT (4)) {
2540#ifdef MODE32
2541 if (state->is_v6 && handle_v6_insn (state, instr))
2542 break;
2543#endif
2544 ARMul_UndefInstr (state, instr);
2545 break;
2546 }
2547 UNDEF_LSRBaseEQOffWb;
2548 UNDEF_LSRBaseEQDestWb;
2549 UNDEF_LSRPCBaseWb;
2550 UNDEF_LSRPCOffWb;
2551 lhs = LHS;
2552 temp = lhs - LSRegRHS;
2553 if (LoadByte (state, instr, lhs, LUNSIGNED))
2554 LSBase = temp;
2555 break;
2556
2557 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2558 if (BIT (4)) {
2559#ifdef MODE32
2560 if (state->is_v6 && handle_v6_insn (state, instr))
2561 break;
2562#endif
2563 ARMul_UndefInstr (state, instr);
2564 break;
2565 }
2566 UNDEF_LSRBaseEQOffWb;
2567 UNDEF_LSRBaseEQDestWb;
2568 UNDEF_LSRPCBaseWb;
2569 UNDEF_LSRPCOffWb;
2570 lhs = LHS;
2571 state->NtransSig = LOW;
2572 if (StoreByte (state, instr, lhs))
2573 LSBase = lhs - LSRegRHS;
2574 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2575 break;
2576
2577 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2578 if (BIT (4)) {
2579#ifdef MODE32
2580 if (state->is_v6
2581 && handle_v6_insn (state, instr))
2582 break;
2583#endif
2584
2585 ARMul_UndefInstr (state, instr);
2586 break;
2587 }
2588 UNDEF_LSRBaseEQOffWb;
2589 UNDEF_LSRBaseEQDestWb;
2590 UNDEF_LSRPCBaseWb;
2591 UNDEF_LSRPCOffWb;
2592 lhs = LHS;
2593 temp = lhs - LSRegRHS;
2594 state->NtransSig = LOW;
2595 if (LoadByte (state, instr, lhs, LUNSIGNED))
2596 LSBase = temp;
2597 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2598 break;
2599
2600 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2601 if ((instr & 0x70) == 0x10) { //pkhbt
2602 u8 idest = BITS(12, 15);
2603 u8 rfis = BITS(16, 19);
2604 u8 rlast = BITS(0, 3);
2605 u8 ishi = BITS(7,11);
2606 state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000);
2607 break;
2608 } else if ((instr & 0x70) == 0x50) { //pkhtb
2609 u8 rd_idx = BITS(12, 15);
2610 u8 rn_idx = BITS(16, 19);
2611 u8 rm_idx = BITS(0, 3);
2612 u8 imm5 = BITS(7, 11) ? BITS(7, 11) : 31;
2613 state->Reg[rd_idx] = ((static_cast<s32>(state->Reg[rm_idx]) >> imm5) & 0xFFFF) | ((state->Reg[rn_idx]) & 0xFFFF0000);
2614 break;
2615 } else if (BIT (4)) {
2616#ifdef MODE32
2617 if (state->is_v6
2618 && handle_v6_insn (state, instr))
2619 break;
2620#endif
2621
2622 ARMul_UndefInstr (state, instr);
2623 break;
2624 }
2625 UNDEF_LSRBaseEQOffWb;
2626 UNDEF_LSRBaseEQDestWb;
2627 UNDEF_LSRPCBaseWb;
2628 UNDEF_LSRPCOffWb;
2629 lhs = LHS;
2630 if (StoreWord (state, instr, lhs))
2631 LSBase = lhs + LSRegRHS;
2632 break;
2633
2634 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2635 if (BIT (4)) {
2636 ARMul_UndefInstr (state, instr);
2637 break;
2638 }
2639 UNDEF_LSRBaseEQOffWb;
2640 UNDEF_LSRBaseEQDestWb;
2641 UNDEF_LSRPCBaseWb;
2642 UNDEF_LSRPCOffWb;
2643 lhs = LHS;
2644 temp = lhs + LSRegRHS;
2645 if (LoadWord (state, instr, lhs))
2646 LSBase = temp;
2647 break;
2648
2649 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2650 if (BIT (4)) {
2651#ifdef MODE32
2652 if (state->is_v6
2653 && handle_v6_insn (state, instr))
2654 break;
2655#endif
2656
2657 ARMul_UndefInstr (state, instr);
2658 break;
2659 }
2660 UNDEF_LSRBaseEQOffWb;
2661 UNDEF_LSRBaseEQDestWb;
2662 UNDEF_LSRPCBaseWb;
2663 UNDEF_LSRPCOffWb;
2664 lhs = LHS;
2665 state->NtransSig = LOW;
2666 if (StoreWord (state, instr, lhs))
2667 LSBase = lhs + LSRegRHS;
2668 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2669 break;
2670
2671 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2672 if (BIT (4)) {
2673#ifdef MODE32
2674 if (state->is_v6
2675 && handle_v6_insn (state, instr))
2676 break;
2677#endif
2678
2679 ARMul_UndefInstr (state, instr);
2680 break;
2681 }
2682 UNDEF_LSRBaseEQOffWb;
2683 UNDEF_LSRBaseEQDestWb;
2684 UNDEF_LSRPCBaseWb;
2685 UNDEF_LSRPCOffWb;
2686 lhs = LHS;
2687 temp = lhs + LSRegRHS;
2688 state->NtransSig = LOW;
2689 if (LoadWord (state, instr, lhs))
2690 LSBase = temp;
2691 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2692 break;
2693
2694 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2695 if (BIT (4)) {
2696#ifdef MODE32
2697 if (state->is_v6
2698 && handle_v6_insn (state, instr))
2699 break;
2700#endif
2701
2702 ARMul_UndefInstr (state, instr);
2703 break;
2704 }
2705 UNDEF_LSRBaseEQOffWb;
2706 UNDEF_LSRBaseEQDestWb;
2707 UNDEF_LSRPCBaseWb;
2708 UNDEF_LSRPCOffWb;
2709 lhs = LHS;
2710 if (StoreByte (state, instr, lhs))
2711 LSBase = lhs + LSRegRHS;
2712 break;
2713
2714 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
2715 if (BIT (4)) {
2716 ARMul_UndefInstr (state, instr);
2717 break;
2718 }
2719 UNDEF_LSRBaseEQOffWb;
2720 UNDEF_LSRBaseEQDestWb;
2721 UNDEF_LSRPCBaseWb;
2722 UNDEF_LSRPCOffWb;
2723 lhs = LHS;
2724 temp = lhs + LSRegRHS;
2725 if (LoadByte (state, instr, lhs, LUNSIGNED))
2726 LSBase = temp;
2727 break;
2728
2729 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
2730 if (BIT (4)) {
2731#ifdef MODE32
2732 if (state->is_v6
2733 && handle_v6_insn (state, instr))
2734 break;
2735#endif
2736
2737 ARMul_UndefInstr (state, instr);
2738 break;
2739 }
2740 UNDEF_LSRBaseEQOffWb;
2741 UNDEF_LSRBaseEQDestWb;
2742 UNDEF_LSRPCBaseWb;
2743 UNDEF_LSRPCOffWb;
2744 lhs = LHS;
2745 state->NtransSig = LOW;
2746 if (StoreByte (state, instr, lhs))
2747 LSBase = lhs + LSRegRHS;
2748 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2749 break;
2750
2751 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
2752 if (BIT (4)) {
2753#ifdef MODE32
2754 if (state->is_v6
2755 && handle_v6_insn (state, instr))
2756 break;
2757#endif
2758
2759 ARMul_UndefInstr (state, instr);
2760 break;
2761 }
2762 UNDEF_LSRBaseEQOffWb;
2763 UNDEF_LSRBaseEQDestWb;
2764 UNDEF_LSRPCBaseWb;
2765 UNDEF_LSRPCOffWb;
2766 lhs = LHS;
2767 temp = lhs + LSRegRHS;
2768 state->NtransSig = LOW;
2769 if (LoadByte (state, instr, lhs, LUNSIGNED))
2770 LSBase = temp;
2771 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2772 break;
2773
2774 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
2775 if (BIT (4)) {
2776#ifdef MODE32
2777 if (state->is_v6 && handle_v6_insn (state, instr))
2778 break;
2779#endif
2780 ARMul_UndefInstr (state, instr);
2781 break;
2782 }
2783 (void) StoreWord (state, instr, LHS - LSRegRHS);
2784 break;
2785
2786 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
2787 if (BIT (4)) {
2788 ARMul_UndefInstr (state, instr);
2789 break;
2790 }
2791 (void) LoadWord (state, instr, LHS - LSRegRHS);
2792 break;
2793
2794 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
2795 if (BIT (4)) {
2796 ARMul_UndefInstr (state, instr);
2797 break;
2798 }
2799 UNDEF_LSRBaseEQOffWb;
2800 UNDEF_LSRBaseEQDestWb;
2801 UNDEF_LSRPCBaseWb;
2802 UNDEF_LSRPCOffWb;
2803 temp = LHS - LSRegRHS;
2804 if (StoreWord (state, instr, temp))
2805 LSBase = temp;
2806 break;
2807
2808 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
2809 if (BIT (4)) {
2810 ARMul_UndefInstr (state, instr);
2811 break;
2812 }
2813 UNDEF_LSRBaseEQOffWb;
2814 UNDEF_LSRBaseEQDestWb;
2815 UNDEF_LSRPCBaseWb;
2816 UNDEF_LSRPCOffWb;
2817 temp = LHS - LSRegRHS;
2818 if (LoadWord (state, instr, temp))
2819 LSBase = temp;
2820 break;
2821
2822 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
2823 if (BIT (4)) {
2824#ifdef MODE32
2825 if (state->is_v6 && handle_v6_insn (state, instr))
2826 break;
2827#endif
2828 ARMul_UndefInstr (state, instr);
2829 break;
2830 }
2831 (void) StoreByte (state, instr, LHS - LSRegRHS);
2832 break;
2833
2834 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
2835 if (BIT (4)) {
2836#ifdef MODE32
2837 if (state->is_v6 && handle_v6_insn (state, instr))
2838 break;
2839#endif
2840 ARMul_UndefInstr (state, instr);
2841 break;
2842 }
2843 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
2844 break;
2845
2846 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
2847 if (BIT (4)) {
2848 ARMul_UndefInstr (state, instr);
2849 break;
2850 }
2851 UNDEF_LSRBaseEQOffWb;
2852 UNDEF_LSRBaseEQDestWb;
2853 UNDEF_LSRPCBaseWb;
2854 UNDEF_LSRPCOffWb;
2855 temp = LHS - LSRegRHS;
2856 if (StoreByte (state, instr, temp))
2857 LSBase = temp;
2858 break;
2859
2860 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
2861 if (BIT (4)) {
2862 ARMul_UndefInstr (state, instr);
2863 break;
2864 }
2865 UNDEF_LSRBaseEQOffWb;
2866 UNDEF_LSRBaseEQDestWb;
2867 UNDEF_LSRPCBaseWb;
2868 UNDEF_LSRPCOffWb;
2869 temp = LHS - LSRegRHS;
2870 if (LoadByte (state, instr, temp, LUNSIGNED))
2871 LSBase = temp;
2872 break;
2873
2874 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
2875 if (BIT (4)) {
2876#ifdef MODE32
2877 if (state->is_v6 && handle_v6_insn (state, instr))
2878 break;
2879#endif
2880
2881 ARMul_UndefInstr (state, instr);
2882 break;
2883 }
2884 (void) StoreWord (state, instr, LHS + LSRegRHS);
2885 break;
2886
2887 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
2888 if (BIT (4)) {
2889 ARMul_UndefInstr (state, instr);
2890 break;
2891 }
2892 (void) LoadWord (state, instr, LHS + LSRegRHS);
2893 break;
2894
2895 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
2896 if (BIT (4)) {
2897#ifdef MODE32
2898 if (state->is_v6 && handle_v6_insn (state, instr))
2899 break;
2900#endif
2901
2902 ARMul_UndefInstr (state, instr);
2903 break;
2904 }
2905 UNDEF_LSRBaseEQOffWb;
2906 UNDEF_LSRBaseEQDestWb;
2907 UNDEF_LSRPCBaseWb;
2908 UNDEF_LSRPCOffWb;
2909 temp = LHS + LSRegRHS;
2910 if (StoreWord (state, instr, temp))
2911 LSBase = temp;
2912 break;
2913
2914 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
2915 if (BIT (4)) {
2916 ARMul_UndefInstr (state, instr);
2917 break;
2918 }
2919 UNDEF_LSRBaseEQOffWb;
2920 UNDEF_LSRBaseEQDestWb;
2921 UNDEF_LSRPCBaseWb;
2922 UNDEF_LSRPCOffWb;
2923 temp = LHS + LSRegRHS;
2924 if (LoadWord (state, instr, temp))
2925 LSBase = temp;
2926 break;
2927
2928 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
2929 if (BIT (4)) {
2930#ifdef MODE32
2931 if (state->is_v6 && handle_v6_insn (state, instr))
2932 break;
2933#endif
2934
2935 ARMul_UndefInstr (state, instr);
2936 break;
2937 }
2938 (void) StoreByte (state, instr, LHS + LSRegRHS);
2939 break;
2940
2941 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
2942 if (BIT (4)) {
2943 ARMul_UndefInstr (state, instr);
2944 break;
2945 }
2946 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
2947 break;
2948
2949 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
2950 if (BIT (4)) {
2951 ARMul_UndefInstr (state, instr);
2952 break;
2953 }
2954 UNDEF_LSRBaseEQOffWb;
2955 UNDEF_LSRBaseEQDestWb;
2956 UNDEF_LSRPCBaseWb;
2957 UNDEF_LSRPCOffWb;
2958 temp = LHS + LSRegRHS;
2959 if (StoreByte (state, instr, temp))
2960 LSBase = temp;
2961 break;
2962
2963 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
2964 if (BIT (4)) {
2965 LOG_DEBUG(Core_ARM11, "got unhandled special breakpoint");
2966 return 1;
2967 }
2968 UNDEF_LSRBaseEQOffWb;
2969 UNDEF_LSRBaseEQDestWb;
2970 UNDEF_LSRPCBaseWb;
2971 UNDEF_LSRPCOffWb;
2972 temp = LHS + LSRegRHS;
2973 if (LoadByte (state, instr, temp, LUNSIGNED))
2974 LSBase = temp;
2975 break;
2976
2977 /* Multiple Data Transfer Instructions. */
2978
2979 case 0x80: /* Store, No WriteBack, Post Dec. */
2980 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2981 break;
2982
2983 case 0x81: /* Load, No WriteBack, Post Dec. */
2984 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2985 break;
2986
2987 case 0x82: /* Store, WriteBack, Post Dec. */
2988 temp = LSBase - LSMNumRegs;
2989 STOREMULT (instr, temp + 4L, temp);
2990 break;
2991
2992 case 0x83: /* Load, WriteBack, Post Dec. */
2993 temp = LSBase - LSMNumRegs;
2994 LOADMULT (instr, temp + 4L, temp);
2995 break;
2996
2997 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
2998 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2999 break;
3000
3001 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
3002 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
3003 break;
3004
3005 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
3006 temp = LSBase - LSMNumRegs;
3007 STORESMULT (instr, temp + 4L, temp);
3008 break;
3009
3010 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3011 temp = LSBase - LSMNumRegs;
3012 LOADSMULT (instr, temp + 4L, temp);
3013 break;
3014
3015 case 0x88: /* Store, No WriteBack, Post Inc. */
3016 STOREMULT (instr, LSBase, 0L);
3017 break;
3018
3019 case 0x89: /* Load, No WriteBack, Post Inc. */
3020 LOADMULT (instr, LSBase, 0L);
3021 break;
3022
3023 case 0x8a: /* Store, WriteBack, Post Inc. */
3024 temp = LSBase;
3025 STOREMULT (instr, temp, temp + LSMNumRegs);
3026 break;
3027
3028 case 0x8b: /* Load, WriteBack, Post Inc. */
3029 temp = LSBase;
3030 LOADMULT (instr, temp, temp + LSMNumRegs);
3031 break;
3032
3033 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3034 STORESMULT (instr, LSBase, 0L);
3035 break;
3036
3037 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3038 LOADSMULT (instr, LSBase, 0L);
3039 break;
3040
3041 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3042 temp = LSBase;
3043 STORESMULT (instr, temp, temp + LSMNumRegs);
3044 break;
3045
3046 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3047 temp = LSBase;
3048 LOADSMULT (instr, temp, temp + LSMNumRegs);
3049 break;
3050
3051 case 0x90: /* Store, No WriteBack, Pre Dec. */
3052 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
3053 break;
3054
3055 case 0x91: /* Load, No WriteBack, Pre Dec. */
3056 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
3057 break;
3058
3059 case 0x92: /* Store, WriteBack, Pre Dec. */
3060 temp = LSBase - LSMNumRegs;
3061 STOREMULT (instr, temp, temp);
3062 break;
3063
3064 case 0x93: /* Load, WriteBack, Pre Dec. */
3065 temp = LSBase - LSMNumRegs;
3066 LOADMULT (instr, temp, temp);
3067 break;
3068
3069 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3070 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
3071 break;
3072
3073 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3074 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
3075 break;
3076
3077 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3078 temp = LSBase - LSMNumRegs;
3079 STORESMULT (instr, temp, temp);
3080 break;
3081
3082 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3083 temp = LSBase - LSMNumRegs;
3084 LOADSMULT (instr, temp, temp);
3085 break;
3086
3087 case 0x98: /* Store, No WriteBack, Pre Inc. */
3088 STOREMULT (instr, LSBase + 4L, 0L);
3089 break;
3090
3091 case 0x99: /* Load, No WriteBack, Pre Inc. */
3092 LOADMULT (instr, LSBase + 4L, 0L);
3093 break;
3094
3095 case 0x9a: /* Store, WriteBack, Pre Inc. */
3096 temp = LSBase;
3097 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
3098 break;
3099
3100 case 0x9b: /* Load, WriteBack, Pre Inc. */
3101 temp = LSBase;
3102 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
3103 break;
3104
3105 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3106 STORESMULT (instr, LSBase + 4L, 0L);
3107 break;
3108
3109 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3110 LOADSMULT (instr, LSBase + 4L, 0L);
3111 break;
3112
3113 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3114 temp = LSBase;
3115 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
3116 break;
3117
3118 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3119 temp = LSBase;
3120 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
3121 break;
3122
3123 /* Branch forward. */
3124 case 0xa0:
3125 case 0xa1:
3126 case 0xa2:
3127 case 0xa3:
3128 case 0xa4:
3129 case 0xa5:
3130 case 0xa6:
3131 case 0xa7:
3132 state->Reg[15] = pc + 8 + POSBRANCH;
3133 FLUSHPIPE;
3134 break;
3135
3136 /* Branch backward. */
3137 case 0xa8:
3138 case 0xa9:
3139 case 0xaa:
3140 case 0xab:
3141 case 0xac:
3142 case 0xad:
3143 case 0xae:
3144 case 0xaf:
3145 state->Reg[15] = pc + 8 + NEGBRANCH;
3146 FLUSHPIPE;
3147 break;
3148
3149 /* Branch and Link forward. */
3150 case 0xb0:
3151 case 0xb1:
3152 case 0xb2:
3153 case 0xb3:
3154 case 0xb4:
3155 case 0xb5:
3156 case 0xb6:
3157 case 0xb7:
3158
3159 /* Put PC into Link. */
3160#ifdef MODE32
3161 state->Reg[14] = pc + 4;
3162#else
3163 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3164#endif
3165 state->Reg[15] = pc + 8 + POSBRANCH;
3166 FLUSHPIPE;
3167 break;
3168
3169 /* Branch and Link backward. */
3170 case 0xb8:
3171 case 0xb9:
3172 case 0xba:
3173 case 0xbb:
3174 case 0xbc:
3175 case 0xbd:
3176 case 0xbe:
3177 case 0xbf:
3178 /* Put PC into Link. */
3179#ifdef MODE32
3180 state->Reg[14] = pc + 4;
3181#else
3182 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3183#endif
3184 state->Reg[15] = pc + 8 + NEGBRANCH;
3185 FLUSHPIPE;
3186 break;
3187
3188 /* Co-Processor Data Transfers. */
3189 case 0xc4:
3190 if ((instr & 0x0FF00FF0) == 0xC400B10) { //vmov BIT(0-3), BIT(12-15), BIT(16-20), vmov d0, r0, r0
3191 state->ExtReg[BITS(0, 3) << 1] = state->Reg[BITS(12, 15)];
3192 state->ExtReg[(BITS(0, 3) << 1) + 1] = state->Reg[BITS(16, 20)];
3193 break;
3194 } else if (state->is_v5) {
3195 /* Reading from R15 is UNPREDICTABLE. */
3196 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3197 ARMul_UndefInstr (state, instr);
3198 /* Is access to coprocessor 0 allowed ? */
3199 else if (!CP_ACCESS_ALLOWED(state, CPNum))
3200 ARMul_UndefInstr (state, instr);
3201 else {
3202 /* MCRR, ARMv5TE and up */
3203 ARMul_MCRR (state, instr, DEST, state->Reg[LHSReg]);
3204 break;
3205 }
3206 }
3207 /* Drop through. */
3208
3209 case 0xc0: /* Store , No WriteBack , Post Dec. */
3210 ARMul_STC (state, instr, LHS);
3211 break;
3212
3213 case 0xc5:
3214 if ((instr & 0x00000FF0) == 0xB10) { //vmov BIT(12-15), BIT(16-20), BIT(0-3) vmov r0, r0, d0
3215 state->Reg[BITS(12, 15)] = state->ExtReg[BITS(0, 3) << 1];
3216 state->Reg[BITS(16, 19)] = state->ExtReg[(BITS(0, 3) << 1) + 1];
3217 break;
3218 } else if (state->is_v5) {
3219 /* Writes to R15 are UNPREDICATABLE. */
3220 if (DESTReg == 15 || LHSReg == 15)
3221 ARMul_UndefInstr (state, instr);
3222 /* Is access to the coprocessor allowed ? */
3223 else if (!CP_ACCESS_ALLOWED(state, CPNum)) {
3224 ARMul_UndefInstr(state, instr);
3225 } else {
3226 /* MRRC, ARMv5TE and up */
3227 ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg]));
3228 break;
3229 }
3230 }
3231 /* Drop through. */
3232
3233 case 0xc1: /* Load , No WriteBack , Post Dec. */
3234 ARMul_LDC (state, instr, LHS);
3235 break;
3236
3237 case 0xc2:
3238 case 0xc6: /* Store , WriteBack , Post Dec. */
3239 lhs = LHS;
3240 state->Base = lhs - LSCOff;
3241 ARMul_STC (state, instr, lhs);
3242 break;
3243
3244 case 0xc3:
3245 case 0xc7: /* Load , WriteBack , Post Dec. */
3246 lhs = LHS;
3247 state->Base = lhs - LSCOff;
3248 ARMul_LDC (state, instr, lhs);
3249 break;
3250
3251 case 0xc8:
3252 case 0xcc: /* Store , No WriteBack , Post Inc. */
3253 ARMul_STC (state, instr, LHS);
3254 break;
3255
3256 case 0xc9:
3257 case 0xcd: /* Load , No WriteBack , Post Inc. */
3258 ARMul_LDC (state, instr, LHS);
3259 break;
3260
3261 case 0xca:
3262 case 0xce: /* Store , WriteBack , Post Inc. */
3263 lhs = LHS;
3264 state->Base = lhs + LSCOff;
3265 ARMul_STC (state, instr, LHS);
3266 break;
3267
3268 case 0xcb:
3269 case 0xcf: /* Load , WriteBack , Post Inc. */
3270 lhs = LHS;
3271 state->Base = lhs + LSCOff;
3272 ARMul_LDC (state, instr, LHS);
3273 break;
3274
3275 case 0xd0:
3276 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3277 ARMul_STC (state, instr, LHS - LSCOff);
3278 break;
3279
3280 case 0xd1:
3281 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3282 ARMul_LDC (state, instr, LHS - LSCOff);
3283 break;
3284
3285 case 0xd2:
3286 case 0xd6: /* Store , WriteBack , Pre Dec. */
3287 lhs = LHS - LSCOff;
3288 state->Base = lhs;
3289 ARMul_STC (state, instr, lhs);
3290 break;
3291
3292 case 0xd3:
3293 case 0xd7: /* Load , WriteBack , Pre Dec. */
3294 lhs = LHS - LSCOff;
3295 state->Base = lhs;
3296 ARMul_LDC (state, instr, lhs);
3297 break;
3298
3299 case 0xd8:
3300 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3301 ARMul_STC (state, instr, LHS + LSCOff);
3302 break;
3303
3304 case 0xd9:
3305 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3306 ARMul_LDC (state, instr, LHS + LSCOff);
3307 break;
3308
3309 case 0xda:
3310 case 0xde: /* Store , WriteBack , Pre Inc. */
3311 lhs = LHS + LSCOff;
3312 state->Base = lhs;
3313 ARMul_STC (state, instr, lhs);
3314 break;
3315
3316 case 0xdb:
3317 case 0xdf: /* Load , WriteBack , Pre Inc. */
3318 lhs = LHS + LSCOff;
3319 state->Base = lhs;
3320 ARMul_LDC (state, instr, lhs);
3321 break;
3322
3323 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3324
3325 case 0xe2:
3326 /*if (!CP_ACCESS_ALLOWED (state, CPNum)) {
3327 ARMul_UndefInstr (state, instr);
3328 break;
3329 }*/
3330
3331 case 0xe0:
3332 case 0xe4:
3333 case 0xe6:
3334 case 0xe8:
3335 case 0xea:
3336 case 0xec:
3337 case 0xee:
3338 if (BIT (4)) {
3339 /* MCR. */
3340 if (DESTReg == 15) {
3341 UNDEF_MCRPC;
3342#ifdef MODE32
3343 ARMul_MCR (state, instr, state->Reg[15] + isize);
3344#else
3345 ARMul_MCR (state, instr, ECC | ER15INT | EMODE | ((state->Reg[15] + isize) & R15PCBITS));
3346#endif
3347 } else
3348 ARMul_MCR (state, instr, DEST);
3349 } else
3350 /* CDP Part 1. */
3351 ARMul_CDP (state, instr);
3352 break;
3353
3354 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3355 case 0xe1:
3356 case 0xe3:
3357 case 0xe5:
3358 case 0xe7:
3359 case 0xe9:
3360 case 0xeb:
3361 case 0xed:
3362 case 0xef:
3363 if (BIT (4)) {
3364 /* MRC */
3365 temp = ARMul_MRC (state, instr);
3366 if (DESTReg == 15) {
3367 ASSIGNN ((temp & NBIT) != 0);
3368 ASSIGNZ ((temp & ZBIT) != 0);
3369 ASSIGNC ((temp & CBIT) != 0);
3370 ASSIGNV ((temp & VBIT) != 0);
3371 } else
3372 DEST = temp;
3373 } else
3374 /* CDP Part 2. */
3375 ARMul_CDP (state, instr);
3376 break;
3377
3378 /* SWI instruction. */
3379 case 0xf0:
3380 case 0xf1:
3381 case 0xf2:
3382 case 0xf3:
3383 case 0xf4:
3384 case 0xf5:
3385 case 0xf6:
3386 case 0xf7:
3387 case 0xf8:
3388 case 0xf9:
3389 case 0xfa:
3390 case 0xfb:
3391 case 0xfc:
3392 case 0xfd:
3393 case 0xfe:
3394 case 0xff:
3395 //svc_Execute(state, BITS(0, 23));
3396 HLE::CallSVC(instr);
3397
3398 break;
3399 }
3400 }
3401
3402#ifdef MODET
3403donext:
3404#endif
3405 state->pc = pc;
3406
3407 /* jump out every time */
3408 //state->EndCondition = 0;
3409 //state->Emulate = STOP;
3410//chy 2006-04-12 for ICE debug
3411TEST_EMULATE:
3412 if (state->Emulate == ONCE)
3413 state->Emulate = STOP;
3414 else if (state->Emulate != RUN)
3415 break;
3416 }
3417
3418 while (state->NumInstrsToExecute);
3419exit:
3420 state->decoded = decoded;
3421 state->loaded = loaded;
3422 state->pc = pc;
3423 //chy 2006-04-12, for ICE debug
3424 state->decoded_addr=decoded_addr;
3425 state->loaded_addr=loaded_addr;
3426
3427 return pc;
3428 }
3429
3430 static volatile void (*gen_func) (void);
3431
3432 static volatile uint32_t tmp_st;
3433 static volatile uint32_t save_st;
3434 static volatile uint32_t save_T0;
3435 static volatile uint32_t save_T1;
3436 static volatile uint32_t save_T2;
3437
3438 /* This routine evaluates most Data Processing register RHS's with the S
3439 bit clear. It is intended to be called from the macro DPRegRHS, which
3440 filters the common case of an unshifted register with in line code. */
3441
3442 static ARMword
3443 GetDPRegRHS (ARMul_State * state, ARMword instr) {
3444 ARMword shamt, base;
3445
3446 base = RHSReg;
3447 if (BIT (4)) {
3448 /* Shift amount in a register. */
3449 UNDEF_Shift;
3450 INCPC;
3451#ifndef MODE32
3452 if (base == 15)
3453 base = ECC | ER15INT | R15PC | EMODE;
3454 else
3455#endif
3456 base = state->Reg[base];
3457 ARMul_Icycles (state, 1, 0L);
3458 shamt = state->Reg[BITS (8, 11)] & 0xff;
3459 switch ((int) BITS (5, 6)) {
3460 case LSL:
3461 if (shamt == 0)
3462 return (base);
3463 else if (shamt >= 32)
3464 return (0);
3465 else
3466 return (base << shamt);
3467 case LSR:
3468 if (shamt == 0)
3469 return (base);
3470 else if (shamt >= 32)
3471 return (0);
3472 else
3473 return (base >> shamt);
3474 case ASR:
3475 if (shamt == 0)
3476 return (base);
3477 else if (shamt >= 32)
3478 return ((ARMword) ((int) base >> 31L));
3479 else
3480 return ((ARMword)
3481 (( int) base >> (int) shamt));
3482 case ROR:
3483 shamt &= 0x1f;
3484 if (shamt == 0)
3485 return (base);
3486 else
3487 return ((base << (32 - shamt)) |
3488 (base >> shamt));
3489 }
3490 } else {
3491 /* Shift amount is a constant. */
3492#ifndef MODE32
3493 if (base == 15)
3494 base = ECC | ER15INT | R15PC | EMODE;
3495 else
3496#endif
3497 base = state->Reg[base];
3498 shamt = BITS (7, 11);
3499 switch ((int) BITS (5, 6)) {
3500 case LSL:
3501 return (base << shamt);
3502 case LSR:
3503 if (shamt == 0)
3504 return (0);
3505 else
3506 return (base >> shamt);
3507 case ASR:
3508 if (shamt == 0)
3509 return ((ARMword) (( int) base >> 31L));
3510 else
3511 return ((ARMword)
3512 (( int) base >> (int) shamt));
3513 case ROR:
3514 if (shamt == 0)
3515 /* It's an RRX. */
3516 return ((base >> 1) | (CFLAG << 31));
3517 else
3518 return ((base << (32 - shamt)) |
3519 (base >> shamt));
3520 }
3521 }
3522
3523 return 0;
3524 }
3525
3526 /* This routine evaluates most Logical Data Processing register RHS's
3527 with the S bit set. It is intended to be called from the macro
3528 DPSRegRHS, which filters the common case of an unshifted register
3529 with in line code. */
3530
3531 static ARMword
3532 GetDPSRegRHS (ARMul_State * state, ARMword instr) {
3533 ARMword shamt, base;
3534
3535 base = RHSReg;
3536 if (BIT (4)) {
3537 /* Shift amount in a register. */
3538 UNDEF_Shift;
3539 INCPC;
3540#ifndef MODE32
3541 if (base == 15)
3542 base = ECC | ER15INT | R15PC | EMODE;
3543 else
3544#endif
3545 base = state->Reg[base];
3546 ARMul_Icycles (state, 1, 0L);
3547 shamt = state->Reg[BITS (8, 11)] & 0xff;
3548 switch ((int) BITS (5, 6)) {
3549 case LSL:
3550 if (shamt == 0)
3551 return (base);
3552 else if (shamt == 32) {
3553 ASSIGNC (base & 1);
3554 return (0);
3555 } else if (shamt > 32) {
3556 CLEARC;
3557 return (0);
3558 } else {
3559 ASSIGNC ((base >> (32 - shamt)) & 1);
3560 return (base << shamt);
3561 }
3562 case LSR:
3563 if (shamt == 0)
3564 return (base);
3565 else if (shamt == 32) {
3566 ASSIGNC (base >> 31);
3567 return (0);
3568 } else if (shamt > 32) {
3569 CLEARC;
3570 return (0);
3571 } else {
3572 ASSIGNC ((base >> (shamt - 1)) & 1);
3573 return (base >> shamt);
3574 }
3575 case ASR:
3576 if (shamt == 0)
3577 return (base);
3578 else if (shamt >= 32) {
3579 ASSIGNC (base >> 31L);
3580 return ((ARMword) (( int) base >> 31L));
3581 } else {
3582 ASSIGNC ((ARMword)
3583 (( int) base >>
3584 (int) (shamt - 1)) & 1);
3585 return ((ARMword)
3586 ((int) base >> (int) shamt));
3587 }
3588 case ROR:
3589 if (shamt == 0)
3590 return (base);
3591 shamt &= 0x1f;
3592 if (shamt == 0) {
3593 ASSIGNC (base >> 31);
3594 return (base);
3595 } else {
3596 ASSIGNC ((base >> (shamt - 1)) & 1);
3597 return ((base << (32 - shamt)) |
3598 (base >> shamt));
3599 }
3600 }
3601 } else {
3602 /* Shift amount is a constant. */
3603#ifndef MODE32
3604 if (base == 15)
3605 base = ECC | ER15INT | R15PC | EMODE;
3606 else
3607#endif
3608 base = state->Reg[base];
3609 shamt = BITS (7, 11);
3610
3611 switch ((int) BITS (5, 6)) {
3612 case LSL:
3613 ASSIGNC ((base >> (32 - shamt)) & 1);
3614 return (base << shamt);
3615 case LSR:
3616 if (shamt == 0) {
3617 ASSIGNC (base >> 31);
3618 return (0);
3619 } else {
3620 ASSIGNC ((base >> (shamt - 1)) & 1);
3621 return (base >> shamt);
3622 }
3623 case ASR:
3624 if (shamt == 0) {
3625 ASSIGNC (base >> 31L);
3626 return ((ARMword) ((int) base >> 31L));
3627 } else {
3628 ASSIGNC ((ARMword)
3629 ((int) base >>
3630 (int) (shamt - 1)) & 1);
3631 return ((ARMword)
3632 (( int) base >> (int) shamt));
3633 }
3634 case ROR:
3635 if (shamt == 0) {
3636 /* It's an RRX. */
3637 shamt = CFLAG;
3638 ASSIGNC (base & 1);
3639 return ((base >> 1) | (shamt << 31));
3640 } else {
3641 ASSIGNC ((base >> (shamt - 1)) & 1);
3642 return ((base << (32 - shamt)) |
3643 (base >> shamt));
3644 }
3645 }
3646 }
3647
3648 return 0;
3649 }
3650
3651 /* This routine handles writes to register 15 when the S bit is not set. */
3652
3653 static void
3654 WriteR15 (ARMul_State * state, ARMword src) {
3655 /* The ARM documentation states that the two least significant bits
3656 are discarded when setting PC, except in the cases handled by
3657 WriteR15Branch() below. It's probably an oversight: in THUMB
3658 mode, the second least significant bit should probably not be
3659 discarded. */
3660#ifdef MODET
3661 if (TFLAG)
3662 src &= 0xfffffffe;
3663 else
3664#endif
3665 src &= 0xfffffffc;
3666
3667#ifdef MODE32
3668 state->Reg[15] = src & PCBITS;
3669#else
3670 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
3671 ARMul_R15Altered (state);
3672#endif
3673
3674 FLUSHPIPE;
3675 }
3676
3677 /* This routine handles writes to register 15 when the S bit is set. */
3678
3679 static void
3680 WriteSR15 (ARMul_State * state, ARMword src) {
3681#ifdef MODE32
3682 if (state->Bank > 0) {
3683 state->Cpsr = state->Spsr[state->Bank];
3684 ARMul_CPSRAltered (state);
3685 }
3686#ifdef MODET
3687 if (TFLAG)
3688 src &= 0xfffffffe;
3689 else
3690#endif
3691 src &= 0xfffffffc;
3692 state->Reg[15] = src & PCBITS;
3693#else
3694#ifdef MODET
3695 if (TFLAG)
3696 /* ARMul_R15Altered would have to support it. */
3697 abort ();
3698 else
3699#endif
3700 src &= 0xfffffffc;
3701
3702 if (state->Bank == USERBANK)
3703 state->Reg[15] =
3704 (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
3705 else
3706 state->Reg[15] = src;
3707
3708 ARMul_R15Altered (state);
3709#endif
3710 FLUSHPIPE;
3711 }
3712
3713 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3714 will switch to Thumb mode if the least significant bit is set. */
3715
3716 static void
3717 WriteR15Branch (ARMul_State * state, ARMword src) {
3718#ifdef MODET
3719 if (src & 1) {
3720 /* Thumb bit. */
3721 SETT;
3722 state->Reg[15] = src & 0xfffffffe;
3723 } else {
3724 CLEART;
3725 state->Reg[15] = src & 0xfffffffc;
3726 }
3727 state->Cpsr = ARMul_GetCPSR (state);
3728 FLUSHPIPE;
3729#else
3730 WriteR15 (state, src);
3731#endif
3732 }
3733
3734 /* This routine evaluates most Load and Store register RHS's. It is
3735 intended to be called from the macro LSRegRHS, which filters the
3736 common case of an unshifted register with in line code. */
3737
3738 static ARMword
3739 GetLSRegRHS (ARMul_State * state, ARMword instr) {
3740 ARMword shamt, base;
3741
3742 base = RHSReg;
3743#ifndef MODE32
3744 if (base == 15)
3745 /* Now forbidden, but ... */
3746 base = ECC | ER15INT | R15PC | EMODE;
3747 else
3748#endif
3749 base = state->Reg[base];
3750
3751 shamt = BITS (7, 11);
3752 switch ((int) BITS (5, 6)) {
3753 case LSL:
3754 return (base << shamt);
3755 case LSR:
3756 if (shamt == 0)
3757 return (0);
3758 else
3759 return (base >> shamt);
3760 case ASR:
3761 if (shamt == 0)
3762 return ((ARMword) (( int) base >> 31L));
3763 else
3764 return ((ARMword) (( int) base >> (int) shamt));
3765 case ROR:
3766 if (shamt == 0)
3767 /* It's an RRX. */
3768 return ((base >> 1) | (CFLAG << 31));
3769 else
3770 return ((base << (32 - shamt)) | (base >> shamt));
3771 default:
3772 break;
3773 }
3774 return 0;
3775 }
3776
3777 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
3778
3779 static ARMword
3780 GetLS7RHS (ARMul_State * state, ARMword instr) {
3781 if (BIT (22) == 0) {
3782 /* Register. */
3783#ifndef MODE32
3784 if (RHSReg == 15)
3785 /* Now forbidden, but ... */
3786 return ECC | ER15INT | R15PC | EMODE;
3787#endif
3788 return state->Reg[RHSReg];
3789 }
3790
3791 /* Immediate. */
3792 return BITS (0, 3) | (BITS (8, 11) << 4);
3793 }
3794
3795 static unsigned
3796 LoadWord (ARMul_State * state, ARMword instr, ARMword address) {
3797 ARMword dest;
3798
3799 BUSUSEDINCPCS;
3800#ifndef MODE32
3801 if (ADDREXCEPT (address))
3802 INTERNALABORT (address);
3803#endif
3804
3805 dest = ARMul_LoadWordN (state, address);
3806
3807 if (state->Aborted) {
3808 TAKEABORT;
3809 return state->lateabtSig;
3810 }
3811 if (address & 3)
3812 dest = ARMul_Align (state, address, dest);
3813 WRITEDESTB (dest);
3814 ARMul_Icycles (state, 1, 0L);
3815
3816 return (DESTReg != LHSReg);
3817 }
3818
3819#ifdef MODET
3820 /* This function does the work of loading a halfword. */
3821
3822 static unsigned
3823 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
3824 int signextend) {
3825 ARMword dest;
3826
3827 BUSUSEDINCPCS;
3828#ifndef MODE32
3829 if (ADDREXCEPT (address))
3830 INTERNALABORT (address);
3831#endif
3832 dest = ARMul_LoadHalfWord (state, address);
3833 if (state->Aborted) {
3834 TAKEABORT;
3835 return state->lateabtSig;
3836 }
3837 UNDEF_LSRBPC;
3838 if (signextend)
3839 if (dest & 1 << (16 - 1))
3840 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
3841
3842 WRITEDEST (dest);
3843 ARMul_Icycles (state, 1, 0L);
3844
3845 return (DESTReg != LHSReg);
3846 }
3847
3848#endif /* MODET */
3849
3850 /* This function does the work of loading a byte for a LDRB instruction. */
3851
3852 static unsigned
3853 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend) {
3854 ARMword dest;
3855
3856 BUSUSEDINCPCS;
3857#ifndef MODE32
3858 if (ADDREXCEPT (address))
3859 INTERNALABORT (address);
3860#endif
3861 dest = ARMul_LoadByte (state, address);
3862 if (state->Aborted) {
3863 TAKEABORT;
3864 return state->lateabtSig;
3865 }
3866 UNDEF_LSRBPC;
3867 if (signextend)
3868 if (dest & 1 << (8 - 1))
3869 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
3870
3871 WRITEDEST (dest);
3872 ARMul_Icycles (state, 1, 0L);
3873
3874 return (DESTReg != LHSReg);
3875 }
3876
3877 /* This function does the work of loading two words for a LDRD instruction. */
3878
3879 static void
3880 Handle_Load_Double (ARMul_State * state, ARMword instr) {
3881 ARMword dest_reg;
3882 ARMword addr_reg;
3883 ARMword write_back = BIT (21);
3884 ARMword immediate = BIT (22);
3885 ARMword add_to_base = BIT (23);
3886 ARMword pre_indexed = BIT (24);
3887 ARMword offset;
3888 ARMword addr;
3889 ARMword sum;
3890 ARMword base;
3891 ARMword value1;
3892 ARMword value2;
3893
3894 BUSUSEDINCPCS;
3895
3896 /* If the writeback bit is set, the pre-index bit must be clear. */
3897 if (write_back && !pre_indexed) {
3898 ARMul_UndefInstr (state, instr);
3899 return;
3900 }
3901
3902 /* Extract the base address register. */
3903 addr_reg = LHSReg;
3904
3905 /* Extract the destination register and check it. */
3906 dest_reg = DESTReg;
3907
3908 /* Destination register must be even. */
3909 if ((dest_reg & 1)
3910 /* Destination register cannot be LR. */
3911 || (dest_reg == 14)) {
3912 ARMul_UndefInstr (state, instr);
3913 return;
3914 }
3915
3916 /* Compute the base address. */
3917 base = state->Reg[addr_reg];
3918
3919 /* Compute the offset. */
3920 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->
3921 Reg[RHSReg];
3922
3923 /* Compute the sum of the two. */
3924 if (add_to_base)
3925 sum = base + offset;
3926 else
3927 sum = base - offset;
3928
3929 /* If this is a pre-indexed mode use the sum. */
3930 if (pre_indexed)
3931 addr = sum;
3932 else
3933 addr = base;
3934
3935 /* The address must be aligned on a 8 byte boundary. */
3936 /*if (addr & 0x7) {
3937 #ifdef ABORTS
3938 ARMul_DATAABORT (addr);
3939 #else
3940 ARMul_UndefInstr (state, instr);
3941 #endif
3942 return;
3943 }*/
3944 /* Lets just forcibly align it for now */
3945 //addr = (addr + 7) & ~7;
3946
3947 /* For pre indexed or post indexed addressing modes,
3948 check that the destination registers do not overlap
3949 the address registers. */
3950 if ((!pre_indexed || write_back)
3951 && (addr_reg == dest_reg || addr_reg == dest_reg + 1)) {
3952 ARMul_UndefInstr (state, instr);
3953 return;
3954 }
3955
3956 /* Load the words. */
3957 value1 = ARMul_LoadWordN (state, addr);
3958 value2 = ARMul_LoadWordN (state, addr + 4);
3959
3960 /* Check for data aborts. */
3961 if (state->Aborted) {
3962 TAKEABORT;
3963 return;
3964 }
3965
3966 ARMul_Icycles (state, 2, 0L);
3967
3968 /* Store the values. */
3969 state->Reg[dest_reg] = value1;
3970 state->Reg[dest_reg + 1] = value2;
3971
3972 /* Do the post addressing and writeback. */
3973 if (!pre_indexed)
3974 addr = sum;
3975
3976 if (!pre_indexed || write_back)
3977 state->Reg[addr_reg] = addr;
3978 }
3979
3980 /* This function does the work of storing two words for a STRD instruction. */
3981
3982 static void
3983 Handle_Store_Double (ARMul_State * state, ARMword instr) {
3984 ARMword src_reg;
3985 ARMword addr_reg;
3986 ARMword write_back = BIT (21);
3987 ARMword immediate = BIT (22);
3988 ARMword add_to_base = BIT (23);
3989 ARMword pre_indexed = BIT (24);
3990 ARMword offset;
3991 ARMword addr;
3992 ARMword sum;
3993 ARMword base;
3994
3995 BUSUSEDINCPCS;
3996
3997 /* If the writeback bit is set, the pre-index bit must be clear. */
3998 if (write_back && !pre_indexed) {
3999 ARMul_UndefInstr (state, instr);
4000 return;
4001 }
4002
4003 /* Extract the base address register. */
4004 addr_reg = LHSReg;
4005
4006 /* Base register cannot be PC. */
4007 if (addr_reg == 15) {
4008 ARMul_UndefInstr (state, instr);
4009 return;
4010 }
4011
4012 /* Extract the source register. */
4013 src_reg = DESTReg;
4014
4015 /* Source register must be even. */
4016 if (src_reg & 1) {
4017 ARMul_UndefInstr (state, instr);
4018 return;
4019 }
4020
4021 /* Compute the base address. */
4022 base = state->Reg[addr_reg];
4023
4024 /* Compute the offset. */
4025 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->
4026 Reg[RHSReg];
4027
4028 /* Compute the sum of the two. */
4029 if (add_to_base)
4030 sum = base + offset;
4031 else
4032 sum = base - offset;
4033
4034 /* If this is a pre-indexed mode use the sum. */
4035 if (pre_indexed)
4036 addr = sum;
4037 else
4038 addr = base;
4039
4040 /* The address must be aligned on a 8 byte boundary. */
4041 /*if (addr & 0x7) {
4042 #ifdef ABORTS
4043 ARMul_DATAABORT (addr);
4044 #else
4045 ARMul_UndefInstr (state, instr);
4046 #endif
4047 return;
4048 }*/
4049 /* Lets just forcibly align it for now */
4050 //addr = (addr + 7) & ~7;
4051
4052 /* For pre indexed or post indexed addressing modes,
4053 check that the destination registers do not overlap
4054 the address registers. */
4055 if ((!pre_indexed || write_back)
4056 && (addr_reg == src_reg || addr_reg == src_reg + 1)) {
4057 ARMul_UndefInstr (state, instr);
4058 return;
4059 }
4060
4061 /* Load the words. */
4062 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
4063 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
4064
4065 if (state->Aborted) {
4066 TAKEABORT;
4067 return;
4068 }
4069
4070 /* Do the post addressing and writeback. */
4071 if (!pre_indexed)
4072 addr = sum;
4073
4074 if (!pre_indexed || write_back)
4075 state->Reg[addr_reg] = addr;
4076 }
4077
4078 /* This function does the work of storing a word from a STR instruction. */
4079
4080 static unsigned
4081 StoreWord (ARMul_State * state, ARMword instr, ARMword address) {
4082 BUSUSEDINCPCN;
4083#ifndef MODE32
4084 if (DESTReg == 15)
4085 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4086#endif
4087#ifdef MODE32
4088 ARMul_StoreWordN (state, address, DEST);
4089#else
4090 if (VECTORACCESS (address) || ADDREXCEPT (address)) {
4091 INTERNALABORT (address);
4092 (void) ARMul_LoadWordN (state, address);
4093 } else
4094 ARMul_StoreWordN (state, address, DEST);
4095#endif
4096 if (state->Aborted) {
4097 TAKEABORT;
4098 return state->lateabtSig;
4099 }
4100
4101 return TRUE;
4102 }
4103
4104#ifdef MODET
4105 /* This function does the work of storing a byte for a STRH instruction. */
4106
4107 static unsigned
4108 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address) {
4109 BUSUSEDINCPCN;
4110
4111#ifndef MODE32
4112 if (DESTReg == 15)
4113 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4114#endif
4115
4116#ifdef MODE32
4117 ARMul_StoreHalfWord (state, address, DEST);
4118#else
4119 if (VECTORACCESS (address) || ADDREXCEPT (address)) {
4120 INTERNALABORT (address);
4121 (void) ARMul_LoadHalfWord (state, address);
4122 } else
4123 ARMul_StoreHalfWord (state, address, DEST);
4124#endif
4125
4126 if (state->Aborted) {
4127 TAKEABORT;
4128 return state->lateabtSig;
4129 }
4130 return TRUE;
4131 }
4132
4133#endif /* MODET */
4134
4135 /* This function does the work of storing a byte for a STRB instruction. */
4136
4137 static unsigned
4138 StoreByte (ARMul_State * state, ARMword instr, ARMword address) {
4139 BUSUSEDINCPCN;
4140#ifndef MODE32
4141 if (DESTReg == 15)
4142 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4143#endif
4144#ifdef MODE32
4145 ARMul_StoreByte (state, address, DEST);
4146#else
4147 if (VECTORACCESS (address) || ADDREXCEPT (address)) {
4148 INTERNALABORT (address);
4149 (void) ARMul_LoadByte (state, address);
4150 } else
4151 ARMul_StoreByte (state, address, DEST);
4152#endif
4153 if (state->Aborted) {
4154 TAKEABORT;
4155 return state->lateabtSig;
4156 }
4157 //UNDEF_LSRBPC;
4158 return TRUE;
4159 }
4160
4161 /* This function does the work of loading the registers listed in an LDM
4162 instruction, when the S bit is clear. The code here is always increment
4163 after, it's up to the caller to get the input address correct and to
4164 handle base register modification. */
4165
4166 static void
4167 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) {
4168 ARMword dest, temp;
4169
4170 //UNDEF_LSMNoRegs;
4171 //UNDEF_LSMPCBase;
4172 //UNDEF_LSMBaseInListWb;
4173 BUSUSEDINCPCS;
4174#ifndef MODE32
4175 if (ADDREXCEPT (address))
4176 INTERNALABORT (address);
4177#endif
4178 /*chy 2004-05-23 may write twice
4179 if (BIT (21) && LHSReg != 15)
4180 LSBase = WBBase;
4181 */
4182 /* N cycle first. */
4183 for (temp = 0; !BIT (temp); temp++);
4184
4185 dest = ARMul_LoadWordN (state, address);
4186
4187 if (!state->abortSig && !state->Aborted)
4188 state->Reg[temp++] = dest;
4189 else if (!state->Aborted) {
4190 //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4191 state->Aborted = ARMul_DataAbortV;
4192 }
4193 /*chy 2004-05-23 chy goto end*/
4194 if (state->Aborted)
4195 goto L_ldm_makeabort;
4196 /* S cycles from here on. */
4197 for (; temp < 16; temp++)
4198 if (BIT (temp)) {
4199 /* Load this register. */
4200 address += 4;
4201 dest = ARMul_LoadWordS (state, address);
4202
4203 if (!state->abortSig && !state->Aborted)
4204 state->Reg[temp] = dest;
4205 else if (!state->Aborted) {
4206 /*XScale_set_fsr_far (state,
4207 ARMul_CP15_R5_ST_ALIGN,
4208 address);*/
4209 state->Aborted = ARMul_DataAbortV;
4210 }
4211 /*chy 2004-05-23 chy goto end */
4212 if (state->Aborted)
4213 goto L_ldm_makeabort;
4214 }
4215
4216 if (BIT (15) && !state->Aborted)
4217 /* PC is in the reg list. */
4218 WriteR15Branch (state, PC);
4219
4220 /* To write back the final register. */
4221 /* ARMul_Icycles (state, 1, 0L);*/
4222 /*chy 2004-05-23, see below
4223 if (state->Aborted)
4224 {
4225 if (BIT (21) && LHSReg != 15)
4226 LSBase = WBBase;
4227
4228 TAKEABORT;
4229 }
4230 */
4231 /*chy 2004-05-23 should compare the Abort Models*/
4232L_ldm_makeabort:
4233 /* To write back the final register. */
4234 ARMul_Icycles (state, 1, 0L);
4235
4236 /* chy 2005-11-24, bug found by benjl@cse.unsw.edu.au, etc */
4237 /*
4238 if (state->Aborted)
4239 {
4240 if (BIT (21) && LHSReg != 15)
4241 if (!(state->abortSig && state->Aborted && state->lateabtSig == LOW))
4242 LSBase = WBBase;
4243 TAKEABORT;
4244 }else if (BIT (21) && LHSReg != 15)
4245 LSBase = WBBase;
4246 */
4247 if (state->Aborted) {
4248 if (BIT (21) && LHSReg != 15) {
4249 if (!(state->abortSig)) {
4250 }
4251 }
4252 TAKEABORT;
4253 } else if (BIT (21) && LHSReg != 15) {
4254 LSBase = WBBase;
4255 }
4256 /* chy 2005-11-24, over */
4257 }
4258
4259 /* This function does the work of loading the registers listed in an LDM
4260 instruction, when the S bit is set. The code here is always increment
4261 after, it's up to the caller to get the input address correct and to
4262 handle base register modification. */
4263
4264 static void
4265 LoadSMult (ARMul_State * state,
4266 ARMword instr, ARMword address, ARMword WBBase) {
4267 ARMword dest, temp;
4268
4269 //UNDEF_LSMNoRegs;
4270 //UNDEF_LSMPCBase;
4271 //UNDEF_LSMBaseInListWb;
4272
4273 BUSUSEDINCPCS;
4274
4275#ifndef MODE32
4276 if (ADDREXCEPT (address))
4277 INTERNALABORT (address);
4278#endif
4279 /* chy 2004-05-23, may write twice
4280 if (BIT (21) && LHSReg != 15)
4281 LSBase = WBBase;
4282 */
4283 if (!BIT (15) && state->Bank != USERBANK) {
4284 /* Temporary reg bank switch. */
4285 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4286 UNDEF_LSMUserBankWb;
4287 }
4288
4289 /* N cycle first. */
4290 for (temp = 0; !BIT (temp); temp++);
4291
4292 dest = ARMul_LoadWordN (state, address);
4293
4294 if (!state->abortSig)
4295 state->Reg[temp++] = dest;
4296 else if (!state->Aborted) {
4297 //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4298 state->Aborted = ARMul_DataAbortV;
4299 }
4300
4301 /*chy 2004-05-23 chy goto end*/
4302 if (state->Aborted)
4303 goto L_ldm_s_makeabort;
4304 /* S cycles from here on. */
4305 for (; temp < 16; temp++)
4306 if (BIT (temp)) {
4307 /* Load this register. */
4308 address += 4;
4309 dest = ARMul_LoadWordS (state, address);
4310
4311 if (!state->abortSig && !state->Aborted)
4312 state->Reg[temp] = dest;
4313 else if (!state->Aborted) {
4314 /*XScale_set_fsr_far (state,
4315 ARMul_CP15_R5_ST_ALIGN,
4316 address);*/
4317 state->Aborted = ARMul_DataAbortV;
4318 }
4319 /*chy 2004-05-23 chy goto end */
4320 if (state->Aborted)
4321 goto L_ldm_s_makeabort;
4322 }
4323
4324 /*chy 2004-05-23 label of ldm_s_makeabort*/
4325L_ldm_s_makeabort:
4326 /*chy 2004-06-06 LSBase process should be here, not in the end of this function. Because ARMul_CPSRAltered maybe change R13(SP) R14(lr). If not, simulate INSTR ldmia sp!,[....pc]^ error.*/
4327 /*chy 2004-05-23 should compare the Abort Models*/
4328 if (state->Aborted) {
4329 if (BIT (21) && LHSReg != 15)
4330 if (!
4331 (state->abortSig && state->Aborted
4332 && state->lateabtSig == LOW))
4333 LSBase = WBBase;
4334 TAKEABORT;
4335 } else if (BIT (21) && LHSReg != 15)
4336 LSBase = WBBase;
4337
4338 if (BIT (15) && !state->Aborted) {
4339 /* PC is in the reg list. */
4340#ifdef MODE32
4341 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
4342 if (state->Mode != USER26MODE && state->Mode != USER32MODE ) {
4343 state->Cpsr = GETSPSR (state->Bank);
4344 ARMul_CPSRAltered (state);
4345 }
4346
4347 WriteR15 (state, PC);
4348#else
4349 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
4350 if (state->Mode == USER26MODE || state->Mode == USER32MODE ) {
4351 /* Protect bits in user mode. */
4352 ASSIGNN ((state->Reg[15] & NBIT) != 0);
4353 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
4354 ASSIGNC ((state->Reg[15] & CBIT) != 0);
4355 ASSIGNV ((state->Reg[15] & VBIT) != 0);
4356 } else
4357 ARMul_R15Altered (state);
4358
4359 FLUSHPIPE;
4360#endif
4361 }
4362
4363 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
4364 if (!BIT (15) && state->Mode != USER26MODE
4365 && state->Mode != USER32MODE )
4366 /* Restore the correct bank. */
4367 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4368
4369 /* To write back the final register. */
4370 ARMul_Icycles (state, 1, 0L);
4371 /* chy 2004-05-23, see below
4372 if (state->Aborted)
4373 {
4374 if (BIT (21) && LHSReg != 15)
4375 LSBase = WBBase;
4376
4377 TAKEABORT;
4378 }
4379 */
4380 }
4381
4382 /* This function does the work of storing the registers listed in an STM
4383 instruction, when the S bit is clear. The code here is always increment
4384 after, it's up to the caller to get the input address correct and to
4385 handle base register modification. */
4386
4387 static void
4388 StoreMult (ARMul_State * state,
4389 ARMword instr, ARMword address, ARMword WBBase) {
4390 ARMword temp;
4391
4392 UNDEF_LSMNoRegs;
4393 UNDEF_LSMPCBase;
4394 UNDEF_LSMBaseInListWb;
4395
4396 if (!TFLAG)
4397 /* N-cycle, increment the PC and update the NextInstr state. */
4398 BUSUSEDINCPCN;
4399
4400#ifndef MODE32
4401 if (VECTORACCESS (address) || ADDREXCEPT (address))
4402 INTERNALABORT (address);
4403
4404 if (BIT (15))
4405 PATCHR15;
4406#endif
4407
4408 /* N cycle first. */
4409 for (temp = 0; !BIT (temp); temp++);
4410
4411#ifdef MODE32
4412 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4413#else
4414 if (state->Aborted) {
4415 (void) ARMul_LoadWordN (state, address);
4416
4417 /* Fake the Stores as Loads. */
4418 for (; temp < 16; temp++)
4419 if (BIT (temp)) {
4420 /* Save this register. */
4421 address += 4;
4422 (void) ARMul_LoadWordS (state, address);
4423 }
4424
4425 if (BIT (21) && LHSReg != 15)
4426 LSBase = WBBase;
4427 TAKEABORT;
4428 return;
4429 } else
4430 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4431#endif
4432
4433 if (state->abortSig && !state->Aborted) {
4434 //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4435 state->Aborted = ARMul_DataAbortV;
4436 }
4437
4438//chy 2004-05-23, needn't store other when aborted
4439 if (state->Aborted)
4440 goto L_stm_takeabort;
4441
4442 /* S cycles from here on. */
4443 for (; temp < 16; temp++)
4444 if (BIT (temp)) {
4445 /* Save this register. */
4446 address += 4;
4447
4448 ARMul_StoreWordS (state, address, state->Reg[temp]);
4449
4450 if (state->abortSig && !state->Aborted) {
4451 /*XScale_set_fsr_far (state,
4452 ARMul_CP15_R5_ST_ALIGN,
4453 address);*/
4454 state->Aborted = ARMul_DataAbortV;
4455 }
4456 //chy 2004-05-23, needn't store other when aborted
4457 if (state->Aborted)
4458 goto L_stm_takeabort;
4459 }
4460
4461//chy 2004-05-23,should compare the Abort Models
4462L_stm_takeabort:
4463 if (BIT (21) && LHSReg != 15) {
4464 if (!
4465 (state->abortSig && state->Aborted
4466 && state->lateabtSig == LOW))
4467 LSBase = WBBase;
4468 }
4469 if (state->Aborted)
4470 TAKEABORT;
4471 }
4472
4473 /* This function does the work of storing the registers listed in an STM
4474 instruction when the S bit is set. The code here is always increment
4475 after, it's up to the caller to get the input address correct and to
4476 handle base register modification. */
4477
4478 static void
4479 StoreSMult (ARMul_State * state,
4480 ARMword instr, ARMword address, ARMword WBBase) {
4481 ARMword temp;
4482
4483 UNDEF_LSMNoRegs;
4484 UNDEF_LSMPCBase;
4485 UNDEF_LSMBaseInListWb;
4486
4487 BUSUSEDINCPCN;
4488
4489#ifndef MODE32
4490 if (VECTORACCESS (address) || ADDREXCEPT (address))
4491 INTERNALABORT (address);
4492
4493 if (BIT (15))
4494 PATCHR15;
4495#endif
4496
4497 if (state->Bank != USERBANK) {
4498 /* Force User Bank. */
4499 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4500 UNDEF_LSMUserBankWb;
4501 }
4502
4503 for (temp = 0; !BIT (temp); temp++); /* N cycle first. */
4504
4505#ifdef MODE32
4506 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4507#else
4508 if (state->Aborted) {
4509 (void) ARMul_LoadWordN (state, address);
4510
4511 for (; temp < 16; temp++)
4512 /* Fake the Stores as Loads. */
4513 if (BIT (temp)) {
4514 /* Save this register. */
4515 address += 4;
4516
4517 (void) ARMul_LoadWordS (state, address);
4518 }
4519
4520 if (BIT (21) && LHSReg != 15)
4521 LSBase = WBBase;
4522
4523 TAKEABORT;
4524 return;
4525 } else
4526 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4527#endif
4528
4529 if (state->abortSig && !state->Aborted) {
4530 //XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4531 state->Aborted = ARMul_DataAbortV;
4532 }
4533
4534//chy 2004-05-23, needn't store other when aborted
4535 if (state->Aborted)
4536 goto L_stm_s_takeabort;
4537 /* S cycles from here on. */
4538 for (; temp < 16; temp++)
4539 if (BIT (temp)) {
4540 /* Save this register. */
4541 address += 4;
4542
4543 ARMul_StoreWordS (state, address, state->Reg[temp]);
4544
4545 if (state->abortSig && !state->Aborted) {
4546 /*XScale_set_fsr_far (state,
4547 ARMul_CP15_R5_ST_ALIGN,
4548 address);*/
4549 state->Aborted = ARMul_DataAbortV;
4550 }
4551 //chy 2004-05-23, needn't store other when aborted
4552 if (state->Aborted)
4553 goto L_stm_s_takeabort;
4554 }
4555
4556 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
4557 if (state->Mode != USER26MODE && state->Mode != USER32MODE )
4558 /* Restore the correct bank. */
4559 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4560
4561//chy 2004-05-23,should compare the Abort Models
4562L_stm_s_takeabort:
4563 if (BIT (21) && LHSReg != 15) {
4564 if (!
4565 (state->abortSig && state->Aborted
4566 && state->lateabtSig == LOW))
4567 LSBase = WBBase;
4568 }
4569
4570 if (state->Aborted)
4571 TAKEABORT;
4572 }
4573
4574 /* This function does the work of adding two 32bit values
4575 together, and calculating if a carry has occurred. */
4576
4577 static ARMword
4578 Add32 (ARMword a1, ARMword a2, int *carry) {
4579 ARMword result = (a1 + a2);
4580 unsigned int uresult = (unsigned int) result;
4581 unsigned int ua1 = (unsigned int) a1;
4582
4583 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4584 or (result > RdLo) then we have no carry. */
4585 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
4586 *carry = 1;
4587 else
4588 *carry = 0;
4589
4590 return result;
4591 }
4592
4593 /* This function does the work of multiplying
4594 two 32bit values to give a 64bit result. */
4595
4596 static unsigned
4597 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc) {
4598 /* Operand register numbers. */
4599 int nRdHi, nRdLo, nRs, nRm;
4600 ARMword RdHi = 0, RdLo = 0, Rm;
4601 /* Cycle count. */
4602 int scount;
4603
4604 nRdHi = BITS (16, 19);
4605 nRdLo = BITS (12, 15);
4606 nRs = BITS (8, 11);
4607 nRm = BITS (0, 3);
4608
4609 /* Needed to calculate the cycle count. */
4610 Rm = state->Reg[nRm];
4611
4612 /* Check for illegal operand combinations first. */
4613 if (nRdHi != 15
4614 && nRdLo != 15
4615 && nRs != 15
4616 //&& nRm != 15 && nRdHi != nRdLo && nRdHi != nRm && nRdLo != nRm) {
4617 && nRm != 15 && nRdHi != nRdLo ) {
4618 /* Intermediate results. */
4619 ARMword lo, mid1, mid2, hi;
4620 int carry;
4621 ARMword Rs = state->Reg[nRs];
4622 int sign = 0;
4623
4624 if (msigned) {
4625 /* Compute sign of result and adjust operands if necessary. */
4626 sign = (Rm ^ Rs) & 0x80000000;
4627
4628 if (((signed int) Rm) < 0)
4629 Rm = -Rm;
4630
4631 if (((signed int) Rs) < 0)
4632 Rs = -Rs;
4633 }
4634
4635 /* We can split the 32x32 into four 16x16 operations. This
4636 ensures that we do not lose precision on 32bit only hosts. */
4637 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
4638 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4639 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
4640 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4641
4642 /* We now need to add all of these results together, taking
4643 care to propogate the carries from the additions. */
4644 RdLo = Add32 (lo, (mid1 << 16), &carry);
4645 RdHi = carry;
4646 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
4647 RdHi += (carry + ((mid1 >> 16) & 0xFFFF) +
4648 ((mid2 >> 16) & 0xFFFF) + hi);
4649
4650 if (sign) {
4651 /* Negate result if necessary. */
4652 RdLo = ~RdLo;
4653 RdHi = ~RdHi;
4654 if (RdLo == 0xFFFFFFFF) {
4655 RdLo = 0;
4656 RdHi += 1;
4657 } else
4658 RdLo += 1;
4659 }
4660
4661 state->Reg[nRdLo] = RdLo;
4662 state->Reg[nRdHi] = RdHi;
4663 } else {
4664 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS, instr=0x%x\n", instr);
4665 }
4666 if (scc)
4667 /* Ensure that both RdHi and RdLo are used to compute Z,
4668 but don't let RdLo's sign bit make it to N. */
4669 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4670
4671 /* The cycle count depends on whether the instruction is a signed or
4672 unsigned multiply, and what bits are clear in the multiplier. */
4673 if (msigned && (Rm & ((unsigned) 1 << 31)))
4674 /* Invert the bits to make the check against zero. */
4675 Rm = ~Rm;
4676
4677 if ((Rm & 0xFFFFFF00) == 0)
4678 scount = 1;
4679 else if ((Rm & 0xFFFF0000) == 0)
4680 scount = 2;
4681 else if ((Rm & 0xFF000000) == 0)
4682 scount = 3;
4683 else
4684 scount = 4;
4685
4686 return 2 + scount;
4687 }
4688
4689 /* This function does the work of multiplying two 32bit
4690 values and adding a 64bit value to give a 64bit result. */
4691
4692 static unsigned
4693 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc) {
4694 unsigned scount;
4695 ARMword RdLo, RdHi;
4696 int nRdHi, nRdLo;
4697 int carry = 0;
4698
4699 nRdHi = BITS (16, 19);
4700 nRdLo = BITS (12, 15);
4701
4702 RdHi = state->Reg[nRdHi];
4703 RdLo = state->Reg[nRdLo];
4704
4705 scount = Multiply64 (state, instr, msigned, LDEFAULT);
4706
4707 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
4708 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
4709
4710 state->Reg[nRdLo] = RdLo;
4711 state->Reg[nRdHi] = RdHi;
4712
4713 if (scc)
4714 /* Ensure that both RdHi and RdLo are used to compute Z,
4715 but don't let RdLo's sign bit make it to N. */
4716 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4717
4718 /* Extra cycle for addition. */
4719 return scount + 1;
4720 }
4721
4722 /* Attempt to emulate an ARMv6 instruction.
4723 Returns non-zero upon success. */
4724
4725 static int handle_v6_insn(ARMul_State* state, ARMword instr) {
4726 switch (BITS(20, 27)) {
4727 case 0x03:
4728 printf ("Unhandled v6 insn: ldr\n");
4729 break;
4730 case 0x04: // UMAAL
4731 {
4732 const u8 rm_idx = BITS(8, 11);
4733 const u8 rn_idx = BITS(0, 3);
4734 const u8 rd_lo_idx = BITS(12, 15);
4735 const u8 rd_hi_idx = BITS(16, 19);
4736
4737 const u32 rm_val = state->Reg[rm_idx];
4738 const u32 rn_val = state->Reg[rn_idx];
4739 const u32 rd_lo_val = state->Reg[rd_lo_idx];
4740 const u32 rd_hi_val = state->Reg[rd_hi_idx];
4741
4742 const u64 result = (rn_val * rm_val) + rd_lo_val + rd_hi_val;
4743
4744 state->Reg[rd_lo_idx] = (result & 0xFFFFFFFF);
4745 state->Reg[rd_hi_idx] = ((result >> 32) & 0xFFFFFFFF);
4746 return 1;
4747 }
4748 break;
4749 case 0x06:
4750 printf ("Unhandled v6 insn: mls/str\n");
4751 break;
4752 case 0x16:
4753 printf ("Unhandled v6 insn: smi\n");
4754 break;
4755 case 0x18:
4756 if (BITS(4, 7) == 0x9) {
4757 /* strex */
4758 u32 l = LHSReg;
4759 u32 r = RHSReg;
4760 u32 lhs = LHS;
4761
4762 bool enter = false;
4763
4764 if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr))enter = true;
4765 //StoreWord(state, lhs, RHS)
4766 if (state->Aborted) {
4767 TAKEABORT;
4768 }
4769
4770 if (enter) {
4771 ARMul_StoreWordS(state, lhs, RHS);
4772 state->Reg[DESTReg] = 0;
4773 }
4774 else {
4775 state->Reg[DESTReg] = 1;
4776 }
4777
4778 return 1;
4779 }
4780 printf ("Unhandled v6 insn: strex\n");
4781 break;
4782 case 0x19:
4783 /* ldrex */
4784 if (BITS(4, 7) == 0x9) {
4785 u32 lhs = LHS;
4786
4787 state->currentexaddr = lhs;
4788 state->currentexval = ARMul_ReadWord(state, lhs);
4789
4790 LoadWord(state, instr, lhs);
4791 return 1;
4792 }
4793 printf ("Unhandled v6 insn: ldrex\n");
4794 break;
4795 case 0x1a:
4796 printf ("Unhandled v6 insn: strexd\n");
4797 break;
4798 case 0x1b:
4799 printf ("Unhandled v6 insn: ldrexd\n");
4800 break;
4801 case 0x1c:
4802 if (BITS(4, 7) == 0x9) {
4803 /* strexb */
4804 u32 lhs = LHS;
4805
4806 bool enter = false;
4807
4808 if (state->currentexval == (u32)ARMul_ReadByte(state, state->currentexaddr))enter = true;
4809
4810 BUSUSEDINCPCN;
4811 if (state->Aborted) {
4812 TAKEABORT;
4813 }
4814
4815 if (enter) {
4816 ARMul_StoreByte(state, lhs, RHS);
4817 state->Reg[DESTReg] = 0;
4818 }
4819 else {
4820 state->Reg[DESTReg] = 1;
4821 }
4822
4823 //printf("In %s, strexb not implemented\n", __FUNCTION__);
4824 UNDEF_LSRBPC;
4825 /* WRITESDEST (dest); */
4826 return 1;
4827 }
4828 printf ("Unhandled v6 insn: strexb\n");
4829 break;
4830 case 0x1d:
4831 if ((BITS(4, 7)) == 0x9) {
4832 /* ldrexb */
4833 u32 lhs = LHS;
4834 LoadByte(state, instr, lhs, LUNSIGNED);
4835
4836 state->currentexaddr = lhs;
4837 state->currentexval = (u32)ARMul_ReadByte(state, lhs);
4838
4839 //state->Reg[BITS(12, 15)] = ARMul_LoadByte(state, state->Reg[BITS(16, 19)]);
4840 //printf("ldrexb\n");
4841 //printf("instr is %x rm is %d\n", instr, BITS(16, 19));
4842 //exit(-1);
4843
4844 //printf("In %s, ldrexb not implemented\n", __FUNCTION__);
4845 return 1;
4846 }
4847 printf ("Unhandled v6 insn: ldrexb\n");
4848 break;
4849 case 0x1e:
4850 printf ("Unhandled v6 insn: strexh\n");
4851 break;
4852 case 0x1f:
4853 printf ("Unhandled v6 insn: ldrexh\n");
4854 break;
4855 case 0x30:
4856 printf ("Unhandled v6 insn: movw\n");
4857 break;
4858 case 0x32:
4859 printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n");
4860 break;
4861 case 0x34:
4862 printf ("Unhandled v6 insn: movt\n");
4863 break;
4864 case 0x3f:
4865 printf ("Unhandled v6 insn: rbit\n");
4866 break;
4867 case 0x61: // SADD16, SASX, SSAX, and SSUB16
4868 if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 ||
4869 (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70)
4870 {
4871 const u8 rd_idx = BITS(12, 15);
4872 const u8 rm_idx = BITS(0, 3);
4873 const u8 rn_idx = BITS(16, 19);
4874 const s16 rn_lo = (state->Reg[rn_idx] & 0xFFFF);
4875 const s16 rn_hi = ((state->Reg[rn_idx] >> 16) & 0xFFFF);
4876 const s16 rm_lo = (state->Reg[rm_idx] & 0xFFFF);
4877 const s16 rm_hi = ((state->Reg[rm_idx] >> 16) & 0xFFFF);
4878
4879 s32 lo_result;
4880 s32 hi_result;
4881
4882 // SADD16
4883 if ((instr & 0xFF0) == 0xf10) {
4884 lo_result = (rn_lo + rm_lo);
4885 hi_result = (rn_hi + rm_hi);
4886 }
4887 // SASX
4888 else if ((instr & 0xFF0) == 0xf30) {
4889 lo_result = (rn_lo - rm_hi);
4890 hi_result = (rn_hi + rm_lo);
4891 }
4892 // SSAX
4893 else if ((instr & 0xFF0) == 0xf50) {
4894 lo_result = (rn_lo + rm_hi);
4895 hi_result = (rn_hi - rm_lo);
4896 }
4897 // SSUB16
4898 else {
4899 lo_result = (rn_lo - rm_lo);
4900 hi_result = (rn_hi - rm_hi);
4901 }
4902
4903 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
4904
4905 if (lo_result >= 0) {
4906 state->GEFlag |= (1 << 16);
4907 state->GEFlag |= (1 << 17);
4908 } else {
4909 state->GEFlag &= ~(1 << 16);
4910 state->GEFlag &= ~(1 << 17);
4911 }
4912
4913 if (hi_result >= 0) {
4914 state->GEFlag |= (1 << 18);
4915 state->GEFlag |= (1 << 19);
4916 } else {
4917 state->GEFlag &= ~(1 << 18);
4918 state->GEFlag &= ~(1 << 19);
4919 }
4920
4921 return 1;
4922 }
4923 // SADD8/SSUB8
4924 else if ((instr & 0xFF0) == 0xf90 || (instr & 0xFF0) == 0xff0)
4925 {
4926 const u8 rd_idx = BITS(12, 15);
4927 const u8 rm_idx = BITS(0, 3);
4928 const u8 rn_idx = BITS(16, 19);
4929 const u32 rm_val = state->Reg[rm_idx];
4930 const u32 rn_val = state->Reg[rn_idx];
4931
4932 s32 lo_val1, lo_val2;
4933 s32 hi_val1, hi_val2;
4934
4935 // SADD8
4936 if ((instr & 0xFF0) == 0xf90) {
4937 lo_val1 = (s32)(s8)(rn_val & 0xFF) + (s32)(s8)(rm_val & 0xFF);
4938 lo_val2 = (s32)(s8)((rn_val >> 8) & 0xFF) + (s32)(s8)((rm_val >> 8) & 0xFF);
4939 hi_val1 = (s32)(s8)((rn_val >> 16) & 0xFF) + (s32)(s8)((rm_val >> 16) & 0xFF);
4940 hi_val2 = (s32)(s8)((rn_val >> 24) & 0xFF) + (s32)(s8)((rm_val >> 24) & 0xFF);
4941 }
4942 // SSUB8
4943 else {
4944 lo_val1 = (s32)(s8)(rn_val & 0xFF) - (s32)(s8)(rm_val & 0xFF);
4945 lo_val2 = (s32)(s8)((rn_val >> 8) & 0xFF) - (s32)(s8)((rm_val >> 8) & 0xFF);
4946 hi_val1 = (s32)(s8)((rn_val >> 16) & 0xFF) - (s32)(s8)((rm_val >> 16) & 0xFF);
4947 hi_val2 = (s32)(s8)((rn_val >> 24) & 0xFF) - (s32)(s8)((rm_val >> 24) & 0xFF);
4948 }
4949
4950 if (lo_val1 >= 0)
4951 state->GEFlag |= (1 << 16);
4952 else
4953 state->GEFlag &= ~(1 << 16);
4954
4955 if (lo_val2 >= 0)
4956 state->GEFlag |= (1 << 17);
4957 else
4958 state->GEFlag &= ~(1 << 17);
4959
4960 if (hi_val1 >= 0)
4961 state->GEFlag |= (1 << 18);
4962 else
4963 state->GEFlag &= ~(1 << 18);
4964
4965 if (hi_val2 >= 0)
4966 state->GEFlag |= (1 << 19);
4967 else
4968 state->GEFlag &= ~(1 << 19);
4969
4970 state->Reg[rd_idx] = ((lo_val1 & 0xFF) | ((lo_val2 & 0xFF) << 8) | ((hi_val1 & 0xFF) << 16) | ((hi_val2 & 0xFF) << 24));
4971 return 1;
4972 }
4973 else {
4974 printf("Unhandled v6 insn: %08x", instr);
4975 }
4976 break;
4977 case 0x62: // QADD16, QASX, QSAX, QSUB16, QADD8, and QSUB8
4978 {
4979 const u8 op2 = BITS(5, 7);
4980
4981 const u8 rd_idx = BITS(12, 15);
4982 const u8 rn_idx = BITS(16, 19);
4983 const u8 rm_idx = BITS(0, 3);
4984 const u16 rm_lo = (state->Reg[rm_idx] & 0xFFFF);
4985 const u16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF);
4986 const u16 rn_lo = (state->Reg[rn_idx] & 0xFFFF);
4987 const u16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF);
4988
4989 u16 lo_result = 0;
4990 u16 hi_result = 0;
4991
4992 // QADD16
4993 if (op2 == 0x00) {
4994 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
4995 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
4996 }
4997 // QASX
4998 else if (op2 == 0x01) {
4999 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
5000 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
5001 }
5002 // QSAX
5003 else if (op2 == 0x02) {
5004 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
5005 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
5006 }
5007 // QSUB16
5008 else if (op2 == 0x03) {
5009 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
5010 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
5011 }
5012 // QADD8
5013 else if (op2 == 0x04) {
5014 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
5015 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
5016 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
5017 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
5018 }
5019 // QSUB8
5020 else if (op2 == 0x07) {
5021 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
5022 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
5023 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
5024 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
5025 }
5026
5027 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
5028 return 1;
5029 }
5030 break;
5031 case 0x63:
5032 printf ("Unhandled v6 insn: shadd/shsub\n");
5033 break;
5034 case 0x65:
5035 {
5036 u32 rd = (instr >> 12) & 0xF;
5037 u32 rn = (instr >> 16) & 0xF;
5038 u32 rm = (instr >> 0) & 0xF;
5039 u32 from = state->Reg[rn];
5040 u32 to = state->Reg[rm];
5041
5042 if ((instr & 0xFF0) == 0xF10 || (instr & 0xFF0) == 0xF70) { // UADD16/USUB16
5043 u32 h1, h2;
5044 state->Cpsr &= 0xfff0ffff;
5045 if ((instr & 0x0F0) == 0x070) { // USUB16
5046 h1 = ((u16)from - (u16)to);
5047 h2 = ((u16)(from >> 16) - (u16)(to >> 16));
5048
5049 if (!(h1 & 0xffff0000))
5050 state->GEFlag |= (3 << 16);
5051 else
5052 state->GEFlag &= ~(3 << 16);
5053
5054 if (!(h2 & 0xffff0000))
5055 state->GEFlag |= (3 << 18);
5056 else
5057 state->GEFlag &= ~(3 << 18);
5058 }
5059 else { // UADD16
5060 h1 = ((u16)from + (u16)to);
5061 h2 = ((u16)(from >> 16) + (u16)(to >> 16));
5062
5063 if (h1 & 0xffff0000)
5064 state->GEFlag |= (3 << 16);
5065 else
5066 state->GEFlag &= ~(3 << 16);
5067
5068 if (h2 & 0xffff0000)
5069 state->GEFlag |= (3 << 18);
5070 else
5071 state->GEFlag &= ~(3 << 18);
5072 }
5073
5074 state->Reg[rd] = (u32)((h1 & 0xffff) | ((h2 & 0xffff) << 16));
5075 return 1;
5076 }
5077 else
5078 if ((instr & 0xFF0) == 0xF90 || (instr & 0xFF0) == 0xFF0) { // UADD8/USUB8
5079 u32 b1, b2, b3, b4;
5080 state->Cpsr &= 0xfff0ffff;
5081 if ((instr & 0x0F0) == 0x0F0) { // USUB8
5082 b1 = ((u8)from - (u8)to);
5083 b2 = ((u8)(from >> 8) - (u8)(to >> 8));
5084 b3 = ((u8)(from >> 16) - (u8)(to >> 16));
5085 b4 = ((u8)(from >> 24) - (u8)(to >> 24));
5086
5087 if (!(b1 & 0xffffff00))
5088 state->GEFlag |= (1 << 16);
5089 else
5090 state->GEFlag &= ~(1 << 16);
5091
5092 if (!(b2 & 0xffffff00))
5093 state->GEFlag |= (1 << 17);
5094 else
5095 state->GEFlag &= ~(1 << 17);
5096
5097 if (!(b3 & 0xffffff00))
5098 state->GEFlag |= (1 << 18);
5099 else
5100 state->GEFlag &= ~(1 << 18);
5101
5102 if (!(b4 & 0xffffff00))
5103 state->GEFlag |= (1 << 19);
5104 else
5105 state->GEFlag &= ~(1 << 19);
5106 }
5107 else { // UADD8
5108 b1 = ((u8)from + (u8)to);
5109 b2 = ((u8)(from >> 8) + (u8)(to >> 8));
5110 b3 = ((u8)(from >> 16) + (u8)(to >> 16));
5111 b4 = ((u8)(from >> 24) + (u8)(to >> 24));
5112
5113 if (b1 & 0xffffff00)
5114 state->GEFlag |= (1 << 16);
5115 else
5116 state->GEFlag &= ~(1 << 16);
5117
5118 if (b2 & 0xffffff00)
5119 state->GEFlag |= (1 << 17);
5120 else
5121 state->GEFlag &= ~(1 << 17);
5122
5123 if (b3 & 0xffffff00)
5124 state->GEFlag |= (1 << 18);
5125 else
5126 state->GEFlag &= ~(1 << 18);
5127
5128 if (b4 & 0xffffff00)
5129 state->GEFlag |= (1 << 19);
5130 else
5131 state->GEFlag &= ~(1 << 19);
5132 }
5133
5134 state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24);
5135 return 1;
5136 }
5137 }
5138 printf("Unhandled v6 insn: uasx/usax\n");
5139 break;
5140 case 0x66: // UQADD16, UQASX, UQSAX, UQSUB16, UQADD8, and UQSUB8
5141 {
5142 const u8 rd_idx = BITS(12, 15);
5143 const u8 rm_idx = BITS(0, 3);
5144 const u8 rn_idx = BITS(16, 19);
5145 const u8 op2 = BITS(5, 7);
5146 const u32 rm_val = state->Reg[rm_idx];
5147 const u32 rn_val = state->Reg[rn_idx];
5148
5149 u16 lo_val = 0;
5150 u16 hi_val = 0;
5151
5152 // UQADD16
5153 if (op2 == 0x00) {
5154 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
5155 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
5156 }
5157 // UQASX
5158 else if (op2 == 0x01) {
5159 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
5160 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
5161 }
5162 // UQSAX
5163 else if (op2 == 0x02) {
5164 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
5165 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
5166 }
5167 // UQSUB16
5168 else if (op2 == 0x03) {
5169 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF);
5170 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
5171 }
5172 // UQADD8
5173 else if (op2 == 0x04) {
5174 lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) |
5175 ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8;
5176 hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) |
5177 ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8;
5178 }
5179 // UQSUB8
5180 else {
5181 lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) |
5182 ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8;
5183 hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) |
5184 ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8;
5185 }
5186
5187 state->Reg[rd_idx] = ((lo_val & 0xFFFF) | hi_val << 16);
5188 return 1;
5189 }
5190 break;
5191 case 0x67: // UHADD16, UHASX, UHSAX, UHSUB16, UHADD8, and UHSUB8.
5192 {
5193 const u8 op2 = BITS(5, 7);
5194
5195 const u8 rm_idx = BITS(0, 3);
5196 const u8 rn_idx = BITS(16, 19);
5197 const u8 rd_idx = BITS(12, 15);
5198
5199 const u32 rm_val = state->Reg[rm_idx];
5200 const u32 rn_val = state->Reg[rn_idx];
5201
5202 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03)
5203 {
5204 u32 lo_val = 0;
5205 u32 hi_val = 0;
5206
5207 // UHADD16
5208 if (op2 == 0x00) {
5209 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
5210 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
5211 }
5212 // UHASX
5213 else if (op2 == 0x01) {
5214 lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
5215 hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
5216 }
5217 // UHSAX
5218 else if (op2 == 0x02) {
5219 lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
5220 hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
5221 }
5222 // UHSUB16
5223 else if (op2 == 0x03) {
5224 lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
5225 hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
5226 }
5227
5228 lo_val >>= 1;
5229 hi_val >>= 1;
5230
5231 state->Reg[rd_idx] = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
5232 return 1;
5233 }
5234 else if (op2 == 0x04 || op2 == 0x07) {
5235 u32 sum1;
5236 u32 sum2;
5237 u32 sum3;
5238 u32 sum4;
5239
5240 // UHADD8
5241 if (op2 == 0x04) {
5242 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
5243 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
5244 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
5245 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
5246 }
5247 // UHSUB8
5248 else {
5249 sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
5250 sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
5251 sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
5252 sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
5253 }
5254
5255 sum1 >>= 1;
5256 sum2 >>= 1;
5257 sum3 >>= 1;
5258 sum4 >>= 1;
5259
5260 state->Reg[rd_idx] = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24);
5261 return 1;
5262 }
5263 }
5264 break;
5265 case 0x68:
5266 {
5267 u32 rd = (instr >> 12) & 0xF;
5268 u32 rn = (instr >> 16) & 0xF;
5269 u32 rm = (instr >> 0) & 0xF;
5270 u32 from = state->Reg[rn];
5271 u32 to = state->Reg[rm];
5272 u32 cpsr = ARMul_GetCPSR(state);
5273 if ((instr & 0xFF0) == 0xFB0) { // SEL
5274 u32 result;
5275 if (cpsr & (1 << 16))
5276 result = from & 0xff;
5277 else
5278 result = to & 0xff;
5279 if (cpsr & (1 << 17))
5280 result |= from & 0x0000ff00;
5281 else
5282 result |= to & 0x0000ff00;
5283 if (cpsr & (1 << 18))
5284 result |= from & 0x00ff0000;
5285 else
5286 result |= to & 0x00ff0000;
5287 if (cpsr & (1 << 19))
5288 result |= from & 0xff000000;
5289 else
5290 result |= to & 0xff000000;
5291 state->Reg[rd] = result;
5292 return 1;
5293 }
5294 }
5295 printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n");
5296 break;
5297
5298 case 0x6a: // SSAT, SSAT16, SXTB, and SXTAB
5299 {
5300 const u8 op2 = BITS(5, 7);
5301
5302 // SSAT16
5303 if (op2 == 0x01) {
5304 const u8 rd_idx = BITS(12, 15);
5305 const u8 rn_idx = BITS(0, 3);
5306 const u8 num_bits = BITS(16, 19) + 1;
5307 const s16 min = -(0x8000 >> (16 - num_bits));
5308 const s16 max = (0x7FFF >> (16 - num_bits));
5309 s16 rn_lo = (state->Reg[rn_idx]);
5310 s16 rn_hi = (state->Reg[rn_idx] >> 16);
5311
5312 if (rn_lo > max) {
5313 rn_lo = max;
5314 SETQ;
5315 } else if (rn_lo < min) {
5316 rn_lo = min;
5317 SETQ;
5318 }
5319
5320 if (rn_hi > max) {
5321 rn_hi = max;
5322 SETQ;
5323 } else if (rn_hi < min) {
5324 rn_hi = min;
5325 SETQ;
5326 }
5327
5328 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16);
5329 return 1;
5330 }
5331 else if (op2 == 0x03) {
5332 const u8 rotation = BITS(10, 11) * 8;
5333 u32 rm = ((state->Reg[BITS(0, 3)] >> rotation) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotation)) & 0xFF) & 0xFF);
5334 if (rm & 0x80)
5335 rm |= 0xffffff00;
5336
5337 // SXTB, otherwise SXTAB
5338 if (BITS(16, 19) == 0xf)
5339 state->Reg[BITS(12, 15)] = rm;
5340 else
5341 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
5342
5343 return 1;
5344 }
5345 else {
5346 printf("Unimplemented op: SSAT");
5347 }
5348 }
5349 break;
5350
5351 case 0x6b: // REV, REV16, SXTH, and SXTAH
5352 {
5353 const u8 op2 = BITS(5, 7);
5354
5355 // REV
5356 if (op2 == 0x01) {
5357 DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24);
5358 return 1;
5359 }
5360 // REV16
5361 else if (op2 == 0x05) {
5362 DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8);
5363 return 1;
5364 }
5365 else if (op2 == 0x03) {
5366 const u8 rotate = BITS(10, 11) * 8;
5367
5368 u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF);
5369 if (rm & 0x8000)
5370 rm |= 0xffff0000;
5371
5372 // SXTH, otherwise SXTAH
5373 if (BITS(16, 19) == 15)
5374 state->Reg[BITS(12, 15)] = rm;
5375 else
5376 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
5377
5378 return 1;
5379 }
5380 }
5381 break;
5382
5383 case 0x6c: // UXTB16 and UXTAB16
5384 {
5385 const u8 rm_idx = BITS(0, 3);
5386 const u8 rn_idx = BITS(16, 19);
5387 const u8 rd_idx = BITS(12, 15);
5388 const u32 rm_val = state->Reg[rm_idx];
5389 const u32 rn_val = state->Reg[rn_idx];
5390 const u32 rotation = BITS(10, 11) * 8;
5391 const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
5392
5393 // UXTB16
5394 if ((instr & 0xf03f0) == 0xf0070) {
5395 state->Reg[rd_idx] = rotated_rm & 0x00FF00FF;
5396 }
5397 else { // UXTAB16
5398 const u8 lo_rotated = (rotated_rm & 0xFF);
5399 const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
5400
5401 const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
5402 const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
5403
5404 state->Reg[rd_idx] = ((hi_result << 16) | (lo_result & 0xFFFF));
5405 }
5406
5407 return 1;
5408 }
5409 break;
5410 case 0x6e: // USAT, USAT16, UXTB, and UXTAB
5411 {
5412 const u8 op2 = BITS(5, 7);
5413
5414 // USAT16
5415 if (op2 == 0x01) {
5416 const u8 rd_idx = BITS(12, 15);
5417 const u8 rn_idx = BITS(0, 3);
5418 const u8 num_bits = BITS(16, 19);
5419 const s16 max = 0xFFFF >> (16 - num_bits);
5420 s16 rn_lo = (state->Reg[rn_idx]);
5421 s16 rn_hi = (state->Reg[rn_idx] >> 16);
5422
5423 if (max < rn_lo) {
5424 rn_lo = max;
5425 SETQ;
5426 } else if (rn_lo < 0) {
5427 rn_lo = 0;
5428 SETQ;
5429 }
5430
5431 if (max < rn_hi) {
5432 rn_hi = max;
5433 SETQ;
5434 } else if (rn_hi < 0) {
5435 rn_hi = 0;
5436 SETQ;
5437 }
5438
5439 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF);
5440 return 1;
5441 }
5442 else if (op2 == 0x03) {
5443 const u8 rotate = BITS(10, 11) * 8;
5444 const u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFF) & 0xFF);
5445
5446 if (BITS(16, 19) == 0xf)
5447 /* UXTB */
5448 state->Reg[BITS(12, 15)] = rm;
5449 else
5450 /* UXTAB */
5451 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
5452
5453 return 1;
5454 }
5455 else {
5456 printf("Unimplemented op: USAT");
5457 }
5458 }
5459 break;
5460
5461 case 0x6f: // UXTH, UXTAH, and REVSH.
5462 {
5463 const u8 op2 = BITS(5, 7);
5464
5465 // REVSH
5466 if (op2 == 0x05) {
5467 DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8);
5468 if (DEST & 0x8000)
5469 DEST |= 0xffff0000;
5470 return 1;
5471 }
5472 // UXTH and UXTAH
5473 else if (op2 == 0x03) {
5474 const u8 rotate = BITS(10, 11) * 8;
5475 const ARMword rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF);
5476
5477 // UXTH
5478 if (BITS(16, 19) == 0xf) {
5479 state->Reg[BITS(12, 15)] = rm;
5480 }
5481 // UXTAH
5482 else {
5483 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
5484 }
5485
5486 return 1;
5487 }
5488 }
5489 case 0x70:
5490 // ichfly
5491 // SMUAD, SMUSD, SMLAD, and SMLSD
5492 if ((instr & 0xf0d0) == 0xf010 || (instr & 0xf0d0) == 0xf050 ||
5493 (instr & 0xd0) == 0x10 || (instr & 0xd0) == 0x50)
5494 {
5495 const u8 rd_idx = BITS(16, 19);
5496 const u8 rn_idx = BITS(0, 3);
5497 const u8 rm_idx = BITS(8, 11);
5498 const u8 ra_idx = BITS(12, 15);
5499 const bool do_swap = (BIT(5) == 1);
5500
5501 u32 rm_val = state->Reg[rm_idx];
5502 const u32 rn_val = state->Reg[rn_idx];
5503
5504 if (do_swap)
5505 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
5506
5507 const s16 rm_lo = (rm_val & 0xFFFF);
5508 const s16 rm_hi = ((rm_val >> 16) & 0xFFFF);
5509 const s16 rn_lo = (rn_val & 0xFFFF);
5510 const s16 rn_hi = ((rn_val >> 16) & 0xFFFF);
5511
5512 const u32 product1 = (rn_lo * rm_lo);
5513 const u32 product2 = (rn_hi * rm_hi);
5514
5515 // SMUAD and SMLAD
5516 if (BIT(6) == 0) {
5517 state->Reg[rd_idx] = product1 + product2;
5518
5519 if (BITS(12, 15) != 15) {
5520 state->Reg[rd_idx] += state->Reg[ra_idx];
5521 if (ARMul_AddOverflowQ(product1 + product2, state->Reg[ra_idx]))
5522 SETQ;
5523 }
5524
5525 if (ARMul_AddOverflowQ(product1, product2))
5526 SETQ;
5527 }
5528 // SMUSD and SMLSD
5529 else {
5530 state->Reg[rd_idx] = product1 - product2;
5531
5532 if (BITS(12, 15) != 15) {
5533 state->Reg[rd_idx] += state->Reg[ra_idx];
5534
5535 if (ARMul_AddOverflowQ(product1 - product2, state->Reg[ra_idx]))
5536 SETQ;
5537 }
5538 }
5539
5540 return 1;
5541 }
5542 break;
5543 case 0x74: // SMLALD and SMLSLD
5544 {
5545 const u8 rm_idx = BITS(8, 11);
5546 const u8 rn_idx = BITS(0, 3);
5547 const u8 rdlo_idx = BITS(12, 15);
5548 const u8 rdhi_idx = BITS(16, 19);
5549 const bool do_swap = (BIT(5) == 1);
5550
5551 const u32 rdlo_val = state->Reg[rdlo_idx];
5552 const u32 rdhi_val = state->Reg[rdhi_idx];
5553 const u32 rn_val = state->Reg[rn_idx];
5554 u32 rm_val = state->Reg[rm_idx];
5555
5556 if (do_swap)
5557 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
5558
5559 const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF);
5560 const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF);
5561 s64 result;
5562
5563 // SMLALD
5564 if (BIT(6) == 0) {
5565 result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
5566 }
5567 // SMLSLD
5568 else {
5569 result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
5570 }
5571
5572 state->Reg[rdlo_idx] = (result & 0xFFFFFFFF);
5573 state->Reg[rdhi_idx] = ((result >> 32) & 0xFFFFFFFF);
5574 return 1;
5575 }
5576 break;
5577 case 0x75: // SMMLA, SMMUL, and SMMLS
5578 {
5579 const u8 rm_idx = BITS(8, 11);
5580 const u8 rn_idx = BITS(0, 3);
5581 const u8 ra_idx = BITS(12, 15);
5582 const u8 rd_idx = BITS(16, 19);
5583 const bool do_round = (BIT(5) == 1);
5584
5585 const u32 rm_val = state->Reg[rm_idx];
5586 const u32 rn_val = state->Reg[rn_idx];
5587
5588 // Assume SMMUL by default.
5589 s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val;
5590
5591 if (ra_idx != 15) {
5592 const u32 ra_val = state->Reg[ra_idx];
5593
5594 // SMMLA, otherwise SMMLS
5595 if (BIT(6) == 0)
5596 result += ((s64)ra_val << 32);
5597 else
5598 result = ((s64)ra_val << 32) - result;
5599 }
5600
5601 if (do_round)
5602 result += 0x80000000;
5603
5604 state->Reg[rd_idx] = ((result >> 32) & 0xFFFFFFFF);
5605 return 1;
5606 }
5607 break;
5608 case 0x78:
5609 if (BITS(20, 24) == 0x18)
5610 {
5611 const u8 rm_idx = BITS(8, 11);
5612 const u8 rn_idx = BITS(0, 3);
5613 const u8 rd_idx = BITS(16, 19);
5614
5615 const u32 rm_val = state->Reg[rm_idx];
5616 const u32 rn_val = state->Reg[rn_idx];
5617
5618 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
5619 const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
5620 const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
5621 const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
5622
5623 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
5624
5625 // Op is USADA8 if true.
5626 const u8 ra_idx = BITS(12, 15);
5627 if (ra_idx != 15)
5628 finalDif += state->Reg[ra_idx];
5629
5630 state->Reg[rd_idx] = finalDif;
5631 return 1;
5632 }
5633 break;
5634 case 0x7a:
5635 printf ("Unhandled v6 insn: usbfx\n");
5636 break;
5637 case 0x7c:
5638 printf ("Unhandled v6 insn: bfc/bfi\n");
5639 break;
5640 case 0x84:
5641 printf ("Unhandled v6 insn: srs\n");
5642 break;
5643 default:
5644 break;
5645 }
5646 printf("Unhandled v6 insn: UNKNOWN: %08x %08X\n", instr, BITS(20, 27));
5647 return 0;
5648 } \ No newline at end of file