Add checks to catch invaliud XScale MIA, MIAPH and MIAxy instructions.
[deliverable/binutils-gdb.git] / sim / arm / armemu.c
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 "armdefs.h"
20 #include "armemu.h"
21 #include "armos.h"
22
23 static ARMword GetDPRegRHS (ARMul_State *, ARMword);
24 static ARMword GetDPSRegRHS (ARMul_State *, ARMword);
25 static void WriteR15 (ARMul_State *, ARMword);
26 static void WriteSR15 (ARMul_State *, ARMword);
27 static void WriteR15Branch (ARMul_State *, ARMword);
28 static ARMword GetLSRegRHS (ARMul_State *, ARMword);
29 static ARMword GetLS7RHS (ARMul_State *, ARMword);
30 static unsigned LoadWord (ARMul_State *, ARMword, ARMword);
31 static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int);
32 static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int);
33 static unsigned StoreWord (ARMul_State *, ARMword, ARMword);
34 static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword);
35 static unsigned StoreByte (ARMul_State *, ARMword, ARMword);
36 static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword);
37 static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword);
38 static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword);
39 static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword);
40 static unsigned Multiply64 (ARMul_State *, ARMword, int, int);
41 static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int);
42 static void Handle_Load_Double (ARMul_State *, ARMword);
43 static void Handle_Store_Double (ARMul_State *, ARMword);
44
45 #define LUNSIGNED (0) /* unsigned operation */
46 #define LSIGNED (1) /* signed operation */
47 #define LDEFAULT (0) /* default : do nothing */
48 #define LSCC (1) /* set condition codes on result */
49
50 #ifdef NEED_UI_LOOP_HOOK
51 /* How often to run the ui_loop update, when in use. */
52 #define UI_LOOP_POLL_INTERVAL 0x32000
53
54 /* Counter for the ui_loop_hook update. */
55 static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
56
57 /* Actual hook to call to run through gdb's gui event loop. */
58 extern int (*ui_loop_hook) (int);
59 #endif /* NEED_UI_LOOP_HOOK */
60
61 extern int stop_simulator;
62
63 /* Short-hand macros for LDR/STR. */
64
65 /* Store post decrement writeback. */
66 #define SHDOWNWB() \
67 lhs = LHS ; \
68 if (StoreHalfWord (state, instr, lhs)) \
69 LSBase = lhs - GetLS7RHS (state, instr);
70
71 /* Store post increment writeback. */
72 #define SHUPWB() \
73 lhs = LHS ; \
74 if (StoreHalfWord (state, instr, lhs)) \
75 LSBase = lhs + GetLS7RHS (state, instr);
76
77 /* Store pre decrement. */
78 #define SHPREDOWN() \
79 (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
80
81 /* Store pre decrement writeback. */
82 #define SHPREDOWNWB() \
83 temp = LHS - GetLS7RHS (state, instr); \
84 if (StoreHalfWord (state, instr, temp)) \
85 LSBase = temp;
86
87 /* Store pre increment. */
88 #define SHPREUP() \
89 (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
90
91 /* Store pre increment writeback. */
92 #define SHPREUPWB() \
93 temp = LHS + GetLS7RHS (state, instr); \
94 if (StoreHalfWord (state, instr, temp)) \
95 LSBase = temp;
96
97 /* Load post decrement writeback. */
98 #define LHPOSTDOWN() \
99 { \
100 int done = 1; \
101 lhs = LHS; \
102 temp = lhs - GetLS7RHS (state, instr); \
103 \
104 switch (BITS (5, 6)) \
105 { \
106 case 1: /* H */ \
107 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
108 LSBase = temp; \
109 break; \
110 case 2: /* SB */ \
111 if (LoadByte (state, instr, lhs, LSIGNED)) \
112 LSBase = temp; \
113 break; \
114 case 3: /* SH */ \
115 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
116 LSBase = temp; \
117 break; \
118 case 0: /* SWP handled elsewhere. */ \
119 default: \
120 done = 0; \
121 break; \
122 } \
123 if (done) \
124 break; \
125 }
126
127 /* Load post increment writeback. */
128 #define LHPOSTUP() \
129 { \
130 int done = 1; \
131 lhs = LHS; \
132 temp = lhs + GetLS7RHS (state, instr); \
133 \
134 switch (BITS (5, 6)) \
135 { \
136 case 1: /* H */ \
137 if (LoadHalfWord (state, instr, lhs, LUNSIGNED)) \
138 LSBase = temp; \
139 break; \
140 case 2: /* SB */ \
141 if (LoadByte (state, instr, lhs, LSIGNED)) \
142 LSBase = temp; \
143 break; \
144 case 3: /* SH */ \
145 if (LoadHalfWord (state, instr, lhs, LSIGNED)) \
146 LSBase = temp; \
147 break; \
148 case 0: /* SWP handled elsewhere. */ \
149 default: \
150 done = 0; \
151 break; \
152 } \
153 if (done) \
154 break; \
155 }
156
157 /* Load pre decrement. */
158 #define LHPREDOWN() \
159 { \
160 int done = 1; \
161 \
162 temp = LHS - GetLS7RHS (state, instr); \
163 switch (BITS (5, 6)) \
164 { \
165 case 1: /* H */ \
166 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
167 break; \
168 case 2: /* SB */ \
169 (void) LoadByte (state, instr, temp, LSIGNED); \
170 break; \
171 case 3: /* SH */ \
172 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
173 break; \
174 case 0: \
175 /* SWP handled elsewhere. */ \
176 default: \
177 done = 0; \
178 break; \
179 } \
180 if (done) \
181 break; \
182 }
183
184 /* Load pre decrement writeback. */
185 #define LHPREDOWNWB() \
186 { \
187 int done = 1; \
188 \
189 temp = LHS - GetLS7RHS (state, instr); \
190 switch (BITS (5, 6)) \
191 { \
192 case 1: /* H */ \
193 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
194 LSBase = temp; \
195 break; \
196 case 2: /* SB */ \
197 if (LoadByte (state, instr, temp, LSIGNED)) \
198 LSBase = temp; \
199 break; \
200 case 3: /* SH */ \
201 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
202 LSBase = temp; \
203 break; \
204 case 0: \
205 /* SWP handled elsewhere. */ \
206 default: \
207 done = 0; \
208 break; \
209 } \
210 if (done) \
211 break; \
212 }
213
214 /* Load pre increment. */
215 #define LHPREUP() \
216 { \
217 int done = 1; \
218 \
219 temp = LHS + GetLS7RHS (state, instr); \
220 switch (BITS (5, 6)) \
221 { \
222 case 1: /* H */ \
223 (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \
224 break; \
225 case 2: /* SB */ \
226 (void) LoadByte (state, instr, temp, LSIGNED); \
227 break; \
228 case 3: /* SH */ \
229 (void) LoadHalfWord (state, instr, temp, LSIGNED); \
230 break; \
231 case 0: \
232 /* SWP handled elsewhere. */ \
233 default: \
234 done = 0; \
235 break; \
236 } \
237 if (done) \
238 break; \
239 }
240
241 /* Load pre increment writeback. */
242 #define LHPREUPWB() \
243 { \
244 int done = 1; \
245 \
246 temp = LHS + GetLS7RHS (state, instr); \
247 switch (BITS (5, 6)) \
248 { \
249 case 1: /* H */ \
250 if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \
251 LSBase = temp; \
252 break; \
253 case 2: /* SB */ \
254 if (LoadByte (state, instr, temp, LSIGNED)) \
255 LSBase = temp; \
256 break; \
257 case 3: /* SH */ \
258 if (LoadHalfWord (state, instr, temp, LSIGNED)) \
259 LSBase = temp; \
260 break; \
261 case 0: \
262 /* SWP handled elsewhere. */ \
263 default: \
264 done = 0; \
265 break; \
266 } \
267 if (done) \
268 break; \
269 }
270
271 /* EMULATION of ARM6. */
272
273 /* The PC pipeline value depends on whether ARM
274 or Thumb instructions are being executed. */
275 ARMword isize;
276
277 ARMword
278 #ifdef MODE32
279 ARMul_Emulate32 (ARMul_State * state)
280 #else
281 ARMul_Emulate26 (ARMul_State * state)
282 #endif
283 {
284 ARMword instr; /* The current instruction. */
285 ARMword dest = 0; /* Almost the DestBus. */
286 ARMword temp; /* Ubiquitous third hand. */
287 ARMword pc = 0; /* The address of the current instruction. */
288 ARMword lhs; /* Almost the ABus and BBus. */
289 ARMword rhs;
290 ARMword decoded = 0; /* Instruction pipeline. */
291 ARMword loaded = 0;
292
293 /* Execute the next instruction. */
294
295 if (state->NextInstr < PRIMEPIPE)
296 {
297 decoded = state->decoded;
298 loaded = state->loaded;
299 pc = state->pc;
300 }
301
302 do
303 {
304 /* Just keep going. */
305 isize = INSN_SIZE;
306
307 switch (state->NextInstr)
308 {
309 case SEQ:
310 /* Advance the pipeline, and an S cycle. */
311 state->Reg[15] += isize;
312 pc += isize;
313 instr = decoded;
314 decoded = loaded;
315 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
316 break;
317
318 case NONSEQ:
319 /* Advance the pipeline, and an N cycle. */
320 state->Reg[15] += isize;
321 pc += isize;
322 instr = decoded;
323 decoded = loaded;
324 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
325 NORMALCYCLE;
326 break;
327
328 case PCINCEDSEQ:
329 /* Program counter advanced, and an S cycle. */
330 pc += isize;
331 instr = decoded;
332 decoded = loaded;
333 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
334 NORMALCYCLE;
335 break;
336
337 case PCINCEDNONSEQ:
338 /* Program counter advanced, and an N cycle. */
339 pc += isize;
340 instr = decoded;
341 decoded = loaded;
342 loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
343 NORMALCYCLE;
344 break;
345
346 case RESUME:
347 /* The program counter has been changed. */
348 pc = state->Reg[15];
349 #ifndef MODE32
350 pc = pc & R15PCBITS;
351 #endif
352 state->Reg[15] = pc + (isize * 2);
353 state->Aborted = 0;
354 instr = ARMul_ReLoadInstr (state, pc, isize);
355 decoded = ARMul_ReLoadInstr (state, pc + isize, isize);
356 loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize);
357 NORMALCYCLE;
358 break;
359
360 default:
361 /* The program counter has been changed. */
362 pc = state->Reg[15];
363 #ifndef MODE32
364 pc = pc & R15PCBITS;
365 #endif
366 state->Reg[15] = pc + (isize * 2);
367 state->Aborted = 0;
368 instr = ARMul_LoadInstrN (state, pc, isize);
369 decoded = ARMul_LoadInstrS (state, pc + (isize), isize);
370 loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
371 NORMALCYCLE;
372 break;
373 }
374
375 if (state->EventSet)
376 ARMul_EnvokeEvent (state);
377 #if 0
378 /* Enable this for a helpful bit of debugging when tracing is needed. */
379 fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr);
380 if (instr == 0)
381 abort ();
382 #endif
383
384 if (state->Exception)
385 {
386 /* Any exceptions ? */
387 if (state->NresetSig == LOW)
388 {
389 ARMul_Abort (state, ARMul_ResetV);
390 break;
391 }
392 else if (!state->NfiqSig && !FFLAG)
393 {
394 ARMul_Abort (state, ARMul_FIQV);
395 break;
396 }
397 else if (!state->NirqSig && !IFLAG)
398 {
399 ARMul_Abort (state, ARMul_IRQV);
400 break;
401 }
402 }
403
404 if (state->CallDebug > 0)
405 {
406 instr = ARMul_Debug (state, pc, instr);
407 if (state->Emulate < ONCE)
408 {
409 state->NextInstr = RESUME;
410 break;
411 }
412 if (state->Debug)
413 {
414 fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n", pc, instr,
415 state->Mode);
416 (void) fgetc (stdin);
417 }
418 }
419 else if (state->Emulate < ONCE)
420 {
421 state->NextInstr = RESUME;
422 break;
423 }
424
425 state->NumInstrs++;
426
427 #ifdef MODET
428 /* Provide Thumb instruction decoding. If the processor is in Thumb
429 mode, then we can simply decode the Thumb instruction, and map it
430 to the corresponding ARM instruction (by directly loading the
431 instr variable, and letting the normal ARM simulator
432 execute). There are some caveats to ensure that the correct
433 pipelined PC value is used when executing Thumb code, and also for
434 dealing with the BL instruction. */
435 if (TFLAG)
436 {
437 ARMword new;
438
439 /* Check if in Thumb mode. */
440 switch (ARMul_ThumbDecode (state, pc, instr, &new))
441 {
442 case t_undefined:
443 /* This is a Thumb instruction. */
444 ARMul_UndefInstr (state, instr);
445 goto donext;
446
447 case t_branch:
448 /* Already processed. */
449 goto donext;
450
451 case t_decoded:
452 /* ARM instruction available. */
453 instr = new;
454 /* So continue instruction decoding. */
455 break;
456 default:
457 break;
458 }
459 }
460 #endif
461
462 /* Check the condition codes. */
463 if ((temp = TOPBITS (28)) == AL)
464 /* Vile deed in the need for speed. */
465 goto mainswitch;
466
467 /* Check the condition code. */
468 switch ((int) TOPBITS (28))
469 {
470 case AL:
471 temp = TRUE;
472 break;
473 case NV:
474 if (state->is_v5)
475 {
476 if (BITS (25, 27) == 5) /* BLX(1) */
477 {
478 ARMword dest;
479
480 state->Reg[14] = pc + 4;
481
482 /* Force entry into Thumb mode. */
483 dest = pc + 8 + 1;
484 if (BIT (23))
485 dest += (NEGBRANCH + (BIT (24) << 1));
486 else
487 dest += POSBRANCH + (BIT (24) << 1);
488
489 WriteR15Branch (state, dest);
490 goto donext;
491 }
492 else if ((instr & 0xFC70F000) == 0xF450F000)
493 /* The PLD instruction. Ignored. */
494 goto donext;
495 else
496 /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2. */
497 ARMul_UndefInstr (state, instr);
498 }
499 temp = FALSE;
500 break;
501 case EQ:
502 temp = ZFLAG;
503 break;
504 case NE:
505 temp = !ZFLAG;
506 break;
507 case VS:
508 temp = VFLAG;
509 break;
510 case VC:
511 temp = !VFLAG;
512 break;
513 case MI:
514 temp = NFLAG;
515 break;
516 case PL:
517 temp = !NFLAG;
518 break;
519 case CS:
520 temp = CFLAG;
521 break;
522 case CC:
523 temp = !CFLAG;
524 break;
525 case HI:
526 temp = (CFLAG && !ZFLAG);
527 break;
528 case LS:
529 temp = (!CFLAG || ZFLAG);
530 break;
531 case GE:
532 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
533 break;
534 case LT:
535 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
536 break;
537 case GT:
538 temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
539 break;
540 case LE:
541 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
542 break;
543 } /* cc check */
544
545 /* Handle the Clock counter here. */
546 if (state->is_XScale)
547 {
548 ARMword cp14r0;
549 int ok;
550
551 ok = state->CPRead[14] (state, 0, & cp14r0);
552
553 if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE))
554 {
555 unsigned long newcycles, nowtime = ARMul_Time (state);
556
557 newcycles = nowtime - state->LastTime;
558 state->LastTime = nowtime;
559
560 if (cp14r0 & ARMul_CP14_R0_CCD)
561 {
562 if (state->CP14R0_CCD == -1)
563 state->CP14R0_CCD = newcycles;
564 else
565 state->CP14R0_CCD += newcycles;
566
567 if (state->CP14R0_CCD >= 64)
568 {
569 newcycles = 0;
570
571 while (state->CP14R0_CCD >= 64)
572 state->CP14R0_CCD -= 64, newcycles++;
573
574 goto check_PMUintr;
575 }
576 }
577 else
578 {
579 ARMword cp14r1;
580 int do_int = 0;
581
582 state->CP14R0_CCD = -1;
583 check_PMUintr:
584 cp14r0 |= ARMul_CP14_R0_FLAG2;
585 (void) state->CPWrite[14] (state, 0, cp14r0);
586
587 ok = state->CPRead[14] (state, 1, & cp14r1);
588
589 /* Coded like this for portability. */
590 while (ok && newcycles)
591 {
592 if (cp14r1 == 0xffffffff)
593 {
594 cp14r1 = 0;
595 do_int = 1;
596 }
597 else
598 cp14r1 ++;
599
600 newcycles --;
601 }
602
603 (void) state->CPWrite[14] (state, 1, cp14r1);
604
605 if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2))
606 {
607 ARMword temp;
608
609 if (state->CPRead[13] (state, 8, & temp)
610 && (temp & ARMul_CP13_R8_PMUS))
611 ARMul_Abort (state, ARMul_FIQV);
612 else
613 ARMul_Abort (state, ARMul_IRQV);
614 }
615 }
616 }
617 }
618
619 /* Handle hardware instructions breakpoints here. */
620 if (state->is_XScale)
621 {
622 if ( (pc | 3) == (read_cp15_reg (14, 0, 8) | 2)
623 || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2))
624 {
625 if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB))
626 ARMul_OSHandleSWI (state, SWI_Breakpoint);
627 }
628 }
629
630 /* Actual execution of instructions begins here. */
631 /* If the condition codes don't match, stop here. */
632 if (temp)
633 {
634 mainswitch:
635
636 if (state->is_XScale)
637 {
638 if (BIT (20) == 0 && BITS (25, 27) == 0)
639 {
640 if (BITS (4, 7) == 0xD)
641 {
642 /* XScale Load Consecutive insn. */
643 ARMword temp = GetLS7RHS (state, instr);
644 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
645 ARMword addr = BIT (24) ? temp2 : LHS;
646
647 if (BIT (12))
648 ARMul_UndefInstr (state, instr);
649 else if (addr & 7)
650 /* Alignment violation. */
651 ARMul_Abort (state, ARMul_DataAbortV);
652 else
653 {
654 int wb = BIT (21) || (! BIT (24));
655
656 state->Reg[BITS (12, 15)] =
657 ARMul_LoadWordN (state, addr);
658 state->Reg[BITS (12, 15) + 1] =
659 ARMul_LoadWordN (state, addr + 4);
660 if (wb)
661 LSBase = temp2;
662 }
663
664 goto donext;
665 }
666 else if (BITS (4, 7) == 0xF)
667 {
668 /* XScale Store Consecutive insn. */
669 ARMword temp = GetLS7RHS (state, instr);
670 ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
671 ARMword addr = BIT (24) ? temp2 : LHS;
672
673 if (BIT (12))
674 ARMul_UndefInstr (state, instr);
675 else if (addr & 7)
676 /* Alignment violation. */
677 ARMul_Abort (state, ARMul_DataAbortV);
678 else
679 {
680 ARMul_StoreWordN (state, addr,
681 state->Reg[BITS (12, 15)]);
682 ARMul_StoreWordN (state, addr + 4,
683 state->Reg[BITS (12, 15) + 1]);
684
685 if (BIT (21)|| ! BIT (24))
686 LSBase = temp2;
687 }
688
689 goto donext;
690 }
691 }
692 }
693
694 switch ((int) BITS (20, 27))
695 {
696 /* Data Processing Register RHS Instructions. */
697
698 case 0x00: /* AND reg and MUL */
699 #ifdef MODET
700 if (BITS (4, 11) == 0xB)
701 {
702 /* STRH register offset, no write-back, down, post indexed. */
703 SHDOWNWB ();
704 break;
705 }
706 if (BITS (4, 7) == 0xD)
707 {
708 Handle_Load_Double (state, instr);
709 break;
710 }
711 if (BITS (4, 7) == 0xF)
712 {
713 Handle_Store_Double (state, instr);
714 break;
715 }
716 #endif
717 if (BITS (4, 7) == 9)
718 {
719 /* MUL */
720 rhs = state->Reg[MULRHSReg];
721 if (MULLHSReg == MULDESTReg)
722 {
723 UNDEF_MULDestEQOp1;
724 state->Reg[MULDESTReg] = 0;
725 }
726 else if (MULDESTReg != 15)
727 state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
728 else
729 UNDEF_MULPCDest;
730
731 for (dest = 0, temp = 0; dest < 32; dest ++)
732 if (rhs & (1L << dest))
733 temp = dest;
734
735 /* Mult takes this many/2 I cycles. */
736 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
737 }
738 else
739 {
740 /* AND reg. */
741 rhs = DPRegRHS;
742 dest = LHS & rhs;
743 WRITEDEST (dest);
744 }
745 break;
746
747 case 0x01: /* ANDS reg and MULS */
748 #ifdef MODET
749 if ((BITS (4, 11) & 0xF9) == 0x9)
750 /* LDR register offset, no write-back, down, post indexed. */
751 LHPOSTDOWN ();
752 /* Fall through to rest of decoding. */
753 #endif
754 if (BITS (4, 7) == 9)
755 {
756 /* MULS */
757 rhs = state->Reg[MULRHSReg];
758
759 if (MULLHSReg == MULDESTReg)
760 {
761 UNDEF_MULDestEQOp1;
762 state->Reg[MULDESTReg] = 0;
763 CLEARN;
764 SETZ;
765 }
766 else if (MULDESTReg != 15)
767 {
768 dest = state->Reg[MULLHSReg] * rhs;
769 ARMul_NegZero (state, dest);
770 state->Reg[MULDESTReg] = dest;
771 }
772 else
773 UNDEF_MULPCDest;
774
775 for (dest = 0, temp = 0; dest < 32; dest ++)
776 if (rhs & (1L << dest))
777 temp = dest;
778
779 /* Mult takes this many/2 I cycles. */
780 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
781 }
782 else
783 {
784 /* ANDS reg. */
785 rhs = DPSRegRHS;
786 dest = LHS & rhs;
787 WRITESDEST (dest);
788 }
789 break;
790
791 case 0x02: /* EOR reg and MLA */
792 #ifdef MODET
793 if (BITS (4, 11) == 0xB)
794 {
795 /* STRH register offset, write-back, down, post indexed. */
796 SHDOWNWB ();
797 break;
798 }
799 #endif
800 if (BITS (4, 7) == 9)
801 { /* MLA */
802 rhs = state->Reg[MULRHSReg];
803 if (MULLHSReg == MULDESTReg)
804 {
805 UNDEF_MULDestEQOp1;
806 state->Reg[MULDESTReg] = state->Reg[MULACCReg];
807 }
808 else if (MULDESTReg != 15)
809 state->Reg[MULDESTReg] =
810 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
811 else
812 UNDEF_MULPCDest;
813
814 for (dest = 0, temp = 0; dest < 32; dest ++)
815 if (rhs & (1L << dest))
816 temp = dest;
817
818 /* Mult takes this many/2 I cycles. */
819 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
820 }
821 else
822 {
823 rhs = DPRegRHS;
824 dest = LHS ^ rhs;
825 WRITEDEST (dest);
826 }
827 break;
828
829 case 0x03: /* EORS reg and MLAS */
830 #ifdef MODET
831 if ((BITS (4, 11) & 0xF9) == 0x9)
832 /* LDR register offset, write-back, down, post-indexed. */
833 LHPOSTDOWN ();
834 /* Fall through to rest of the decoding. */
835 #endif
836 if (BITS (4, 7) == 9)
837 {
838 /* MLAS */
839 rhs = state->Reg[MULRHSReg];
840
841 if (MULLHSReg == MULDESTReg)
842 {
843 UNDEF_MULDestEQOp1;
844 dest = state->Reg[MULACCReg];
845 ARMul_NegZero (state, dest);
846 state->Reg[MULDESTReg] = dest;
847 }
848 else if (MULDESTReg != 15)
849 {
850 dest =
851 state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
852 ARMul_NegZero (state, dest);
853 state->Reg[MULDESTReg] = dest;
854 }
855 else
856 UNDEF_MULPCDest;
857
858 for (dest = 0, temp = 0; dest < 32; dest ++)
859 if (rhs & (1L << dest))
860 temp = dest;
861
862 /* Mult takes this many/2 I cycles. */
863 ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
864 }
865 else
866 {
867 /* EORS Reg. */
868 rhs = DPSRegRHS;
869 dest = LHS ^ rhs;
870 WRITESDEST (dest);
871 }
872 break;
873
874 case 0x04: /* SUB reg */
875 #ifdef MODET
876 if (BITS (4, 7) == 0xB)
877 {
878 /* STRH immediate offset, no write-back, down, post indexed. */
879 SHDOWNWB ();
880 break;
881 }
882 if (BITS (4, 7) == 0xD)
883 {
884 Handle_Load_Double (state, instr);
885 break;
886 }
887 if (BITS (4, 7) == 0xF)
888 {
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 {
911 ARMul_SubCarry (state, lhs, rhs, dest);
912 ARMul_SubOverflow (state, lhs, rhs, dest);
913 }
914 else
915 {
916 CLEARC;
917 CLEARV;
918 }
919 WRITESDEST (dest);
920 break;
921
922 case 0x06: /* RSB reg */
923 #ifdef MODET
924 if (BITS (4, 7) == 0xB)
925 {
926 /* STRH immediate offset, write-back, down, post indexed. */
927 SHDOWNWB ();
928 break;
929 }
930 #endif
931 rhs = DPRegRHS;
932 dest = rhs - LHS;
933 WRITEDEST (dest);
934 break;
935
936 case 0x07: /* RSBS reg */
937 #ifdef MODET
938 if ((BITS (4, 7) & 0x9) == 0x9)
939 /* LDR immediate offset, write-back, down, post indexed. */
940 LHPOSTDOWN ();
941 /* Fall through to remainder of instruction decoding. */
942 #endif
943 lhs = LHS;
944 rhs = DPRegRHS;
945 dest = rhs - lhs;
946
947 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
948 {
949 ARMul_SubCarry (state, rhs, lhs, dest);
950 ARMul_SubOverflow (state, rhs, lhs, dest);
951 }
952 else
953 {
954 CLEARC;
955 CLEARV;
956 }
957 WRITESDEST (dest);
958 break;
959
960 case 0x08: /* ADD reg */
961 #ifdef MODET
962 if (BITS (4, 11) == 0xB)
963 {
964 /* STRH register offset, no write-back, up, post indexed. */
965 SHUPWB ();
966 break;
967 }
968 if (BITS (4, 7) == 0xD)
969 {
970 Handle_Load_Double (state, instr);
971 break;
972 }
973 if (BITS (4, 7) == 0xF)
974 {
975 Handle_Store_Double (state, instr);
976 break;
977 }
978 #endif
979 #ifdef MODET
980 if (BITS (4, 7) == 0x9)
981 {
982 /* MULL */
983 /* 32x32 = 64 */
984 ARMul_Icycles (state,
985 Multiply64 (state, instr, LUNSIGNED,
986 LDEFAULT), 0L);
987 break;
988 }
989 #endif
990 rhs = DPRegRHS;
991 dest = LHS + rhs;
992 WRITEDEST (dest);
993 break;
994
995 case 0x09: /* ADDS reg */
996 #ifdef MODET
997 if ((BITS (4, 11) & 0xF9) == 0x9)
998 /* LDR register offset, no write-back, up, post indexed. */
999 LHPOSTUP ();
1000 /* Fall through to remaining instruction decoding. */
1001 #endif
1002 #ifdef MODET
1003 if (BITS (4, 7) == 0x9)
1004 {
1005 /* MULL */
1006 /* 32x32=64 */
1007 ARMul_Icycles (state,
1008 Multiply64 (state, instr, LUNSIGNED, LSCC),
1009 0L);
1010 break;
1011 }
1012 #endif
1013 lhs = LHS;
1014 rhs = DPRegRHS;
1015 dest = lhs + rhs;
1016 ASSIGNZ (dest == 0);
1017 if ((lhs | rhs) >> 30)
1018 {
1019 /* Possible C,V,N to set. */
1020 ASSIGNN (NEG (dest));
1021 ARMul_AddCarry (state, lhs, rhs, dest);
1022 ARMul_AddOverflow (state, lhs, rhs, dest);
1023 }
1024 else
1025 {
1026 CLEARN;
1027 CLEARC;
1028 CLEARV;
1029 }
1030 WRITESDEST (dest);
1031 break;
1032
1033 case 0x0a: /* ADC reg */
1034 #ifdef MODET
1035 if (BITS (4, 11) == 0xB)
1036 {
1037 /* STRH register offset, write-back, up, post-indexed. */
1038 SHUPWB ();
1039 break;
1040 }
1041 if (BITS (4, 7) == 0x9)
1042 {
1043 /* MULL */
1044 /* 32x32=64 */
1045 ARMul_Icycles (state,
1046 MultiplyAdd64 (state, instr, LUNSIGNED,
1047 LDEFAULT), 0L);
1048 break;
1049 }
1050 #endif
1051 rhs = DPRegRHS;
1052 dest = LHS + rhs + CFLAG;
1053 WRITEDEST (dest);
1054 break;
1055
1056 case 0x0b: /* ADCS reg */
1057 #ifdef MODET
1058 if ((BITS (4, 11) & 0xF9) == 0x9)
1059 /* LDR register offset, write-back, up, post indexed. */
1060 LHPOSTUP ();
1061 /* Fall through to remaining instruction decoding. */
1062 if (BITS (4, 7) == 0x9)
1063 {
1064 /* MULL */
1065 /* 32x32=64 */
1066 ARMul_Icycles (state,
1067 MultiplyAdd64 (state, instr, LUNSIGNED,
1068 LSCC), 0L);
1069 break;
1070 }
1071 #endif
1072 lhs = LHS;
1073 rhs = DPRegRHS;
1074 dest = lhs + rhs + CFLAG;
1075 ASSIGNZ (dest == 0);
1076 if ((lhs | rhs) >> 30)
1077 {
1078 /* Possible C,V,N to set. */
1079 ASSIGNN (NEG (dest));
1080 ARMul_AddCarry (state, lhs, rhs, dest);
1081 ARMul_AddOverflow (state, lhs, rhs, dest);
1082 }
1083 else
1084 {
1085 CLEARN;
1086 CLEARC;
1087 CLEARV;
1088 }
1089 WRITESDEST (dest);
1090 break;
1091
1092 case 0x0c: /* SBC reg */
1093 #ifdef MODET
1094 if (BITS (4, 7) == 0xB)
1095 {
1096 /* STRH immediate offset, no write-back, up post indexed. */
1097 SHUPWB ();
1098 break;
1099 }
1100 if (BITS (4, 7) == 0xD)
1101 {
1102 Handle_Load_Double (state, instr);
1103 break;
1104 }
1105 if (BITS (4, 7) == 0xF)
1106 {
1107 Handle_Store_Double (state, instr);
1108 break;
1109 }
1110 if (BITS (4, 7) == 0x9)
1111 {
1112 /* MULL */
1113 /* 32x32=64 */
1114 ARMul_Icycles (state,
1115 Multiply64 (state, instr, LSIGNED, LDEFAULT),
1116 0L);
1117 break;
1118 }
1119 #endif
1120 rhs = DPRegRHS;
1121 dest = LHS - rhs - !CFLAG;
1122 WRITEDEST (dest);
1123 break;
1124
1125 case 0x0d: /* SBCS reg */
1126 #ifdef MODET
1127 if ((BITS (4, 7) & 0x9) == 0x9)
1128 /* LDR immediate offset, no write-back, up, post indexed. */
1129 LHPOSTUP ();
1130
1131 if (BITS (4, 7) == 0x9)
1132 {
1133 /* MULL */
1134 /* 32x32=64 */
1135 ARMul_Icycles (state,
1136 Multiply64 (state, instr, LSIGNED, LSCC),
1137 0L);
1138 break;
1139 }
1140 #endif
1141 lhs = LHS;
1142 rhs = DPRegRHS;
1143 dest = lhs - rhs - !CFLAG;
1144 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1145 {
1146 ARMul_SubCarry (state, lhs, rhs, dest);
1147 ARMul_SubOverflow (state, lhs, rhs, dest);
1148 }
1149 else
1150 {
1151 CLEARC;
1152 CLEARV;
1153 }
1154 WRITESDEST (dest);
1155 break;
1156
1157 case 0x0e: /* RSC reg */
1158 #ifdef MODET
1159 if (BITS (4, 7) == 0xB)
1160 {
1161 /* STRH immediate offset, write-back, up, post indexed. */
1162 SHUPWB ();
1163 break;
1164 }
1165
1166 if (BITS (4, 7) == 0x9)
1167 {
1168 /* MULL */
1169 /* 32x32=64 */
1170 ARMul_Icycles (state,
1171 MultiplyAdd64 (state, instr, LSIGNED,
1172 LDEFAULT), 0L);
1173 break;
1174 }
1175 #endif
1176 rhs = DPRegRHS;
1177 dest = rhs - LHS - !CFLAG;
1178 WRITEDEST (dest);
1179 break;
1180
1181 case 0x0f: /* RSCS reg */
1182 #ifdef MODET
1183 if ((BITS (4, 7) & 0x9) == 0x9)
1184 /* LDR immediate offset, write-back, up, post indexed. */
1185 LHPOSTUP ();
1186 /* Fall through to remaining instruction decoding. */
1187
1188 if (BITS (4, 7) == 0x9)
1189 {
1190 /* MULL */
1191 /* 32x32=64 */
1192 ARMul_Icycles (state,
1193 MultiplyAdd64 (state, instr, LSIGNED, LSCC),
1194 0L);
1195 break;
1196 }
1197 #endif
1198 lhs = LHS;
1199 rhs = DPRegRHS;
1200 dest = rhs - lhs - !CFLAG;
1201
1202 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1203 {
1204 ARMul_SubCarry (state, rhs, lhs, dest);
1205 ARMul_SubOverflow (state, rhs, lhs, dest);
1206 }
1207 else
1208 {
1209 CLEARC;
1210 CLEARV;
1211 }
1212 WRITESDEST (dest);
1213 break;
1214
1215 case 0x10: /* TST reg and MRS CPSR and SWP word. */
1216 if (state->is_v5e)
1217 {
1218 if (BIT (4) == 0 && BIT (7) == 1)
1219 {
1220 /* ElSegundo SMLAxy insn. */
1221 ARMword op1 = state->Reg[BITS (0, 3)];
1222 ARMword op2 = state->Reg[BITS (8, 11)];
1223 ARMword Rn = state->Reg[BITS (12, 15)];
1224
1225 if (BIT (5))
1226 op1 >>= 16;
1227 if (BIT (6))
1228 op2 >>= 16;
1229 op1 &= 0xFFFF;
1230 op2 &= 0xFFFF;
1231 if (op1 & 0x8000)
1232 op1 -= 65536;
1233 if (op2 & 0x8000)
1234 op2 -= 65536;
1235 op1 *= op2;
1236
1237 if (AddOverflow (op1, Rn, op1 + Rn))
1238 SETS;
1239 state->Reg[BITS (16, 19)] = op1 + Rn;
1240 break;
1241 }
1242
1243 if (BITS (4, 11) == 5)
1244 {
1245 /* ElSegundo QADD insn. */
1246 ARMword op1 = state->Reg[BITS (0, 3)];
1247 ARMword op2 = state->Reg[BITS (16, 19)];
1248 ARMword result = op1 + op2;
1249 if (AddOverflow (op1, op2, result))
1250 {
1251 result = POS (result) ? 0x80000000 : 0x7fffffff;
1252 SETS;
1253 }
1254 state->Reg[BITS (12, 15)] = result;
1255 break;
1256 }
1257 }
1258 #ifdef MODET
1259 if (BITS (4, 11) == 0xB)
1260 {
1261 /* STRH register offset, no write-back, down, pre indexed. */
1262 SHPREDOWN ();
1263 break;
1264 }
1265 if (BITS (4, 7) == 0xD)
1266 {
1267 Handle_Load_Double (state, instr);
1268 break;
1269 }
1270 if (BITS (4, 7) == 0xF)
1271 {
1272 Handle_Store_Double (state, instr);
1273 break;
1274 }
1275 #endif
1276 if (BITS (4, 11) == 9)
1277 {
1278 /* SWP */
1279 UNDEF_SWPPC;
1280 temp = LHS;
1281 BUSUSEDINCPCS;
1282 #ifndef MODE32
1283 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
1284 {
1285 INTERNALABORT (temp);
1286 (void) ARMul_LoadWordN (state, temp);
1287 (void) ARMul_LoadWordN (state, temp);
1288 }
1289 else
1290 #endif
1291 dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
1292 if (temp & 3)
1293 DEST = ARMul_Align (state, temp, dest);
1294 else
1295 DEST = dest;
1296 if (state->abortSig || state->Aborted)
1297 TAKEABORT;
1298 }
1299 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
1300 { /* MRS CPSR */
1301 UNDEF_MRSPC;
1302 DEST = ECC | EINT | EMODE;
1303 }
1304 else
1305 {
1306 UNDEF_Test;
1307 }
1308 break;
1309
1310 case 0x11: /* TSTP reg */
1311 #ifdef MODET
1312 if ((BITS (4, 11) & 0xF9) == 0x9)
1313 /* LDR register offset, no write-back, down, pre indexed. */
1314 LHPREDOWN ();
1315 /* Continue with remaining instruction decode. */
1316 #endif
1317 if (DESTReg == 15)
1318 {
1319 /* TSTP reg */
1320 #ifdef MODE32
1321 state->Cpsr = GETSPSR (state->Bank);
1322 ARMul_CPSRAltered (state);
1323 #else
1324 rhs = DPRegRHS;
1325 temp = LHS & rhs;
1326 SETR15PSR (temp);
1327 #endif
1328 }
1329 else
1330 {
1331 /* TST reg */
1332 rhs = DPSRegRHS;
1333 dest = LHS & rhs;
1334 ARMul_NegZero (state, dest);
1335 }
1336 break;
1337
1338 case 0x12: /* TEQ reg and MSR reg to CPSR (ARM6). */
1339 if (state->is_v5)
1340 {
1341 if (BITS (4, 7) == 3)
1342 {
1343 /* BLX(2) */
1344 ARMword temp;
1345
1346 if (TFLAG)
1347 temp = (pc + 2) | 1;
1348 else
1349 temp = pc + 4;
1350
1351 WriteR15Branch (state, state->Reg[RHSReg]);
1352 state->Reg[14] = temp;
1353 break;
1354 }
1355 }
1356
1357 if (state->is_v5e)
1358 {
1359 if (BIT (4) == 0 && BIT (7) == 1
1360 && (BIT (5) == 0 || BITS (12, 15) == 0))
1361 {
1362 /* ElSegundo SMLAWy/SMULWy insn. */
1363 unsigned long long op1 = state->Reg[BITS (0, 3)];
1364 unsigned long long op2 = state->Reg[BITS (8, 11)];
1365 unsigned long long result;
1366
1367 if (BIT (6))
1368 op2 >>= 16;
1369 if (op1 & 0x80000000)
1370 op1 -= 1ULL << 32;
1371 op2 &= 0xFFFF;
1372 if (op2 & 0x8000)
1373 op2 -= 65536;
1374 result = (op1 * op2) >> 16;
1375
1376 if (BIT (5) == 0)
1377 {
1378 ARMword Rn = state->Reg[BITS (12, 15)];
1379
1380 if (AddOverflow (result, Rn, result + Rn))
1381 SETS;
1382 result += Rn;
1383 }
1384 state->Reg[BITS (16, 19)] = result;
1385 break;
1386 }
1387
1388 if (BITS (4, 11) == 5)
1389 {
1390 /* ElSegundo QSUB insn. */
1391 ARMword op1 = state->Reg[BITS (0, 3)];
1392 ARMword op2 = state->Reg[BITS (16, 19)];
1393 ARMword result = op1 - op2;
1394
1395 if (SubOverflow (op1, op2, result))
1396 {
1397 result = POS (result) ? 0x80000000 : 0x7fffffff;
1398 SETS;
1399 }
1400
1401 state->Reg[BITS (12, 15)] = result;
1402 break;
1403 }
1404 }
1405 #ifdef MODET
1406 if (BITS (4, 11) == 0xB)
1407 {
1408 /* STRH register offset, write-back, down, pre indexed. */
1409 SHPREDOWNWB ();
1410 break;
1411 }
1412 if (BITS (4, 27) == 0x12FFF1)
1413 {
1414 /* BX */
1415 WriteR15Branch (state, state->Reg[RHSReg]);
1416 break;
1417 }
1418 if (BITS (4, 7) == 0xD)
1419 {
1420 Handle_Load_Double (state, instr);
1421 break;
1422 }
1423 if (BITS (4, 7) == 0xF)
1424 {
1425 Handle_Store_Double (state, instr);
1426 break;
1427 }
1428 #endif
1429 if (state->is_v5)
1430 {
1431 if (BITS (4, 7) == 0x7)
1432 {
1433 ARMword value;
1434 extern int SWI_vector_installed;
1435
1436 /* Hardware is allowed to optionally override this
1437 instruction and treat it as a breakpoint. Since
1438 this is a simulator not hardware, we take the position
1439 that if a SWI vector was not installed, then an Abort
1440 vector was probably not installed either, and so
1441 normally this instruction would be ignored, even if an
1442 Abort is generated. This is a bad thing, since GDB
1443 uses this instruction for its breakpoints (at least in
1444 Thumb mode it does). So intercept the instruction here
1445 and generate a breakpoint SWI instead. */
1446 if (! SWI_vector_installed)
1447 ARMul_OSHandleSWI (state, SWI_Breakpoint);
1448 else
1449 {
1450 /* BKPT - normally this will cause an abort, but on the
1451 XScale we must check the DCSR. */
1452 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
1453 if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT))
1454 break;
1455 }
1456
1457 /* Force the next instruction to be refetched. */
1458 state->NextInstr = RESUME;
1459 break;
1460 }
1461 }
1462 if (DESTReg == 15)
1463 {
1464 /* MSR reg to CPSR. */
1465 UNDEF_MSRPC;
1466 temp = DPRegRHS;
1467 #ifdef MODET
1468 /* Don't allow TBIT to be set by MSR. */
1469 temp &= ~ TBIT;
1470 #endif
1471 ARMul_FixCPSR (state, instr, temp);
1472 }
1473 else
1474 UNDEF_Test;
1475
1476 break;
1477
1478 case 0x13: /* TEQP reg */
1479 #ifdef MODET
1480 if ((BITS (4, 11) & 0xF9) == 0x9)
1481 /* LDR register offset, write-back, down, pre indexed. */
1482 LHPREDOWNWB ();
1483 /* Continue with remaining instruction decode. */
1484 #endif
1485 if (DESTReg == 15)
1486 {
1487 /* TEQP reg */
1488 #ifdef MODE32
1489 state->Cpsr = GETSPSR (state->Bank);
1490 ARMul_CPSRAltered (state);
1491 #else
1492 rhs = DPRegRHS;
1493 temp = LHS ^ rhs;
1494 SETR15PSR (temp);
1495 #endif
1496 }
1497 else
1498 {
1499 /* TEQ Reg. */
1500 rhs = DPSRegRHS;
1501 dest = LHS ^ rhs;
1502 ARMul_NegZero (state, dest);
1503 }
1504 break;
1505
1506 case 0x14: /* CMP reg and MRS SPSR and SWP byte. */
1507 if (state->is_v5e)
1508 {
1509 if (BIT (4) == 0 && BIT (7) == 1)
1510 {
1511 /* ElSegundo SMLALxy insn. */
1512 unsigned long long op1 = state->Reg[BITS (0, 3)];
1513 unsigned long long op2 = state->Reg[BITS (8, 11)];
1514 unsigned long long dest;
1515 unsigned long long result;
1516
1517 if (BIT (5))
1518 op1 >>= 16;
1519 if (BIT (6))
1520 op2 >>= 16;
1521 op1 &= 0xFFFF;
1522 if (op1 & 0x8000)
1523 op1 -= 65536;
1524 op2 &= 0xFFFF;
1525 if (op2 & 0x8000)
1526 op2 -= 65536;
1527
1528 dest = (unsigned long long) state->Reg[BITS (16, 19)] << 32;
1529 dest |= state->Reg[BITS (12, 15)];
1530 dest += op1 * op2;
1531 state->Reg[BITS (12, 15)] = dest;
1532 state->Reg[BITS (16, 19)] = dest >> 32;
1533 break;
1534 }
1535
1536 if (BITS (4, 11) == 5)
1537 {
1538 /* ElSegundo QDADD insn. */
1539 ARMword op1 = state->Reg[BITS (0, 3)];
1540 ARMword op2 = state->Reg[BITS (16, 19)];
1541 ARMword op2d = op2 + op2;
1542 ARMword result;
1543
1544 if (AddOverflow (op2, op2, op2d))
1545 {
1546 SETS;
1547 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1548 }
1549
1550 result = op1 + op2d;
1551 if (AddOverflow (op1, op2d, result))
1552 {
1553 SETS;
1554 result = POS (result) ? 0x80000000 : 0x7fffffff;
1555 }
1556
1557 state->Reg[BITS (12, 15)] = result;
1558 break;
1559 }
1560 }
1561 #ifdef MODET
1562 if (BITS (4, 7) == 0xB)
1563 {
1564 /* STRH immediate offset, no write-back, down, pre indexed. */
1565 SHPREDOWN ();
1566 break;
1567 }
1568 if (BITS (4, 7) == 0xD)
1569 {
1570 Handle_Load_Double (state, instr);
1571 break;
1572 }
1573 if (BITS (4, 7) == 0xF)
1574 {
1575 Handle_Store_Double (state, instr);
1576 break;
1577 }
1578 #endif
1579 if (BITS (4, 11) == 9)
1580 {
1581 /* SWP */
1582 UNDEF_SWPPC;
1583 temp = LHS;
1584 BUSUSEDINCPCS;
1585 #ifndef MODE32
1586 if (VECTORACCESS (temp) || ADDREXCEPT (temp))
1587 {
1588 INTERNALABORT (temp);
1589 (void) ARMul_LoadByte (state, temp);
1590 (void) ARMul_LoadByte (state, temp);
1591 }
1592 else
1593 #endif
1594 DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
1595 if (state->abortSig || state->Aborted)
1596 TAKEABORT;
1597 }
1598 else if ((BITS (0, 11) == 0) && (LHSReg == 15))
1599 {
1600 /* MRS SPSR */
1601 UNDEF_MRSPC;
1602 DEST = GETSPSR (state->Bank);
1603 }
1604 else
1605 UNDEF_Test;
1606
1607 break;
1608
1609 case 0x15: /* CMPP reg. */
1610 #ifdef MODET
1611 if ((BITS (4, 7) & 0x9) == 0x9)
1612 /* LDR immediate offset, no write-back, down, pre indexed. */
1613 LHPREDOWN ();
1614 /* Continue with remaining instruction decode. */
1615 #endif
1616 if (DESTReg == 15)
1617 {
1618 /* CMPP reg. */
1619 #ifdef MODE32
1620 state->Cpsr = GETSPSR (state->Bank);
1621 ARMul_CPSRAltered (state);
1622 #else
1623 rhs = DPRegRHS;
1624 temp = LHS - rhs;
1625 SETR15PSR (temp);
1626 #endif
1627 }
1628 else
1629 {
1630 /* CMP reg. */
1631 lhs = LHS;
1632 rhs = DPRegRHS;
1633 dest = lhs - rhs;
1634 ARMul_NegZero (state, dest);
1635 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1636 {
1637 ARMul_SubCarry (state, lhs, rhs, dest);
1638 ARMul_SubOverflow (state, lhs, rhs, dest);
1639 }
1640 else
1641 {
1642 CLEARC;
1643 CLEARV;
1644 }
1645 }
1646 break;
1647
1648 case 0x16: /* CMN reg and MSR reg to SPSR */
1649 if (state->is_v5e)
1650 {
1651 if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
1652 {
1653 /* ElSegundo SMULxy insn. */
1654 ARMword op1 = state->Reg[BITS (0, 3)];
1655 ARMword op2 = state->Reg[BITS (8, 11)];
1656 ARMword Rn = state->Reg[BITS (12, 15)];
1657
1658 if (BIT (5))
1659 op1 >>= 16;
1660 if (BIT (6))
1661 op2 >>= 16;
1662 op1 &= 0xFFFF;
1663 op2 &= 0xFFFF;
1664 if (op1 & 0x8000)
1665 op1 -= 65536;
1666 if (op2 & 0x8000)
1667 op2 -= 65536;
1668
1669 state->Reg[BITS (16, 19)] = op1 * op2;
1670 break;
1671 }
1672
1673 if (BITS (4, 11) == 5)
1674 {
1675 /* ElSegundo QDSUB insn. */
1676 ARMword op1 = state->Reg[BITS (0, 3)];
1677 ARMword op2 = state->Reg[BITS (16, 19)];
1678 ARMword op2d = op2 + op2;
1679 ARMword result;
1680
1681 if (AddOverflow (op2, op2, op2d))
1682 {
1683 SETS;
1684 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1685 }
1686
1687 result = op1 - op2d;
1688 if (SubOverflow (op1, op2d, result))
1689 {
1690 SETS;
1691 result = POS (result) ? 0x80000000 : 0x7fffffff;
1692 }
1693
1694 state->Reg[BITS (12, 15)] = result;
1695 break;
1696 }
1697 }
1698
1699 if (state->is_v5)
1700 {
1701 if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
1702 {
1703 /* ARM5 CLZ insn. */
1704 ARMword op1 = state->Reg[BITS (0, 3)];
1705 int result = 32;
1706
1707 if (op1)
1708 for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
1709 result++;
1710
1711 state->Reg[BITS (12, 15)] = result;
1712 break;
1713 }
1714 }
1715 #ifdef MODET
1716 if (BITS (4, 7) == 0xB)
1717 {
1718 /* STRH immediate offset, write-back, down, pre indexed. */
1719 SHPREDOWNWB ();
1720 break;
1721 }
1722 if (BITS (4, 7) == 0xD)
1723 {
1724 Handle_Load_Double (state, instr);
1725 break;
1726 }
1727 if (BITS (4, 7) == 0xF)
1728 {
1729 Handle_Store_Double (state, instr);
1730 break;
1731 }
1732 #endif
1733 if (DESTReg == 15)
1734 {
1735 /* MSR */
1736 UNDEF_MSRPC;
1737 ARMul_FixSPSR (state, instr, DPRegRHS);
1738 }
1739 else
1740 {
1741 UNDEF_Test;
1742 }
1743 break;
1744
1745 case 0x17: /* CMNP reg */
1746 #ifdef MODET
1747 if ((BITS (4, 7) & 0x9) == 0x9)
1748 /* LDR immediate offset, write-back, down, pre indexed. */
1749 LHPREDOWNWB ();
1750 /* Continue with remaining instruction decoding. */
1751 #endif
1752 if (DESTReg == 15)
1753 {
1754 #ifdef MODE32
1755 state->Cpsr = GETSPSR (state->Bank);
1756 ARMul_CPSRAltered (state);
1757 #else
1758 rhs = DPRegRHS;
1759 temp = LHS + rhs;
1760 SETR15PSR (temp);
1761 #endif
1762 break;
1763 }
1764 else
1765 {
1766 /* CMN reg. */
1767 lhs = LHS;
1768 rhs = DPRegRHS;
1769 dest = lhs + rhs;
1770 ASSIGNZ (dest == 0);
1771 if ((lhs | rhs) >> 30)
1772 {
1773 /* Possible C,V,N to set. */
1774 ASSIGNN (NEG (dest));
1775 ARMul_AddCarry (state, lhs, rhs, dest);
1776 ARMul_AddOverflow (state, lhs, rhs, dest);
1777 }
1778 else
1779 {
1780 CLEARN;
1781 CLEARC;
1782 CLEARV;
1783 }
1784 }
1785 break;
1786
1787 case 0x18: /* ORR reg */
1788 #ifdef MODET
1789 if (BITS (4, 11) == 0xB)
1790 {
1791 /* STRH register offset, no write-back, up, pre indexed. */
1792 SHPREUP ();
1793 break;
1794 }
1795 if (BITS (4, 7) == 0xD)
1796 {
1797 Handle_Load_Double (state, instr);
1798 break;
1799 }
1800 if (BITS (4, 7) == 0xF)
1801 {
1802 Handle_Store_Double (state, instr);
1803 break;
1804 }
1805 #endif
1806 rhs = DPRegRHS;
1807 dest = LHS | rhs;
1808 WRITEDEST (dest);
1809 break;
1810
1811 case 0x19: /* ORRS reg */
1812 #ifdef MODET
1813 if ((BITS (4, 11) & 0xF9) == 0x9)
1814 /* LDR register offset, no write-back, up, pre indexed. */
1815 LHPREUP ();
1816 /* Continue with remaining instruction decoding. */
1817 #endif
1818 rhs = DPSRegRHS;
1819 dest = LHS | rhs;
1820 WRITESDEST (dest);
1821 break;
1822
1823 case 0x1a: /* MOV reg */
1824 #ifdef MODET
1825 if (BITS (4, 11) == 0xB)
1826 {
1827 /* STRH register offset, write-back, up, pre indexed. */
1828 SHPREUPWB ();
1829 break;
1830 }
1831 if (BITS (4, 7) == 0xD)
1832 {
1833 Handle_Load_Double (state, instr);
1834 break;
1835 }
1836 if (BITS (4, 7) == 0xF)
1837 {
1838 Handle_Store_Double (state, instr);
1839 break;
1840 }
1841 #endif
1842 dest = DPRegRHS;
1843 WRITEDEST (dest);
1844 break;
1845
1846 case 0x1b: /* MOVS reg */
1847 #ifdef MODET
1848 if ((BITS (4, 11) & 0xF9) == 0x9)
1849 /* LDR register offset, write-back, up, pre indexed. */
1850 LHPREUPWB ();
1851 /* Continue with remaining instruction decoding. */
1852 #endif
1853 dest = DPSRegRHS;
1854 WRITESDEST (dest);
1855 break;
1856
1857 case 0x1c: /* BIC reg */
1858 #ifdef MODET
1859 if (BITS (4, 7) == 0xB)
1860 {
1861 /* STRH immediate offset, no write-back, up, pre indexed. */
1862 SHPREUP ();
1863 break;
1864 }
1865 if (BITS (4, 7) == 0xD)
1866 {
1867 Handle_Load_Double (state, instr);
1868 break;
1869 }
1870 else if (BITS (4, 7) == 0xF)
1871 {
1872 Handle_Store_Double (state, instr);
1873 break;
1874 }
1875 #endif
1876 rhs = DPRegRHS;
1877 dest = LHS & ~rhs;
1878 WRITEDEST (dest);
1879 break;
1880
1881 case 0x1d: /* BICS reg */
1882 #ifdef MODET
1883 if ((BITS (4, 7) & 0x9) == 0x9)
1884 /* LDR immediate offset, no write-back, up, pre indexed. */
1885 LHPREUP ();
1886 /* Continue with instruction decoding. */
1887 #endif
1888 rhs = DPSRegRHS;
1889 dest = LHS & ~rhs;
1890 WRITESDEST (dest);
1891 break;
1892
1893 case 0x1e: /* MVN reg */
1894 #ifdef MODET
1895 if (BITS (4, 7) == 0xB)
1896 {
1897 /* STRH immediate offset, write-back, up, pre indexed. */
1898 SHPREUPWB ();
1899 break;
1900 }
1901 if (BITS (4, 7) == 0xD)
1902 {
1903 Handle_Load_Double (state, instr);
1904 break;
1905 }
1906 if (BITS (4, 7) == 0xF)
1907 {
1908 Handle_Store_Double (state, instr);
1909 break;
1910 }
1911 #endif
1912 dest = ~DPRegRHS;
1913 WRITEDEST (dest);
1914 break;
1915
1916 case 0x1f: /* MVNS reg */
1917 #ifdef MODET
1918 if ((BITS (4, 7) & 0x9) == 0x9)
1919 /* LDR immediate offset, write-back, up, pre indexed. */
1920 LHPREUPWB ();
1921 /* Continue instruction decoding. */
1922 #endif
1923 dest = ~DPSRegRHS;
1924 WRITESDEST (dest);
1925 break;
1926
1927
1928 /* Data Processing Immediate RHS Instructions. */
1929
1930 case 0x20: /* AND immed */
1931 dest = LHS & DPImmRHS;
1932 WRITEDEST (dest);
1933 break;
1934
1935 case 0x21: /* ANDS immed */
1936 DPSImmRHS;
1937 dest = LHS & rhs;
1938 WRITESDEST (dest);
1939 break;
1940
1941 case 0x22: /* EOR immed */
1942 dest = LHS ^ DPImmRHS;
1943 WRITEDEST (dest);
1944 break;
1945
1946 case 0x23: /* EORS immed */
1947 DPSImmRHS;
1948 dest = LHS ^ rhs;
1949 WRITESDEST (dest);
1950 break;
1951
1952 case 0x24: /* SUB immed */
1953 dest = LHS - DPImmRHS;
1954 WRITEDEST (dest);
1955 break;
1956
1957 case 0x25: /* SUBS immed */
1958 lhs = LHS;
1959 rhs = DPImmRHS;
1960 dest = lhs - rhs;
1961
1962 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
1963 {
1964 ARMul_SubCarry (state, lhs, rhs, dest);
1965 ARMul_SubOverflow (state, lhs, rhs, dest);
1966 }
1967 else
1968 {
1969 CLEARC;
1970 CLEARV;
1971 }
1972 WRITESDEST (dest);
1973 break;
1974
1975 case 0x26: /* RSB immed */
1976 dest = DPImmRHS - LHS;
1977 WRITEDEST (dest);
1978 break;
1979
1980 case 0x27: /* RSBS immed */
1981 lhs = LHS;
1982 rhs = DPImmRHS;
1983 dest = rhs - lhs;
1984
1985 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
1986 {
1987 ARMul_SubCarry (state, rhs, lhs, dest);
1988 ARMul_SubOverflow (state, rhs, lhs, dest);
1989 }
1990 else
1991 {
1992 CLEARC;
1993 CLEARV;
1994 }
1995 WRITESDEST (dest);
1996 break;
1997
1998 case 0x28: /* ADD immed */
1999 dest = LHS + DPImmRHS;
2000 WRITEDEST (dest);
2001 break;
2002
2003 case 0x29: /* ADDS immed */
2004 lhs = LHS;
2005 rhs = DPImmRHS;
2006 dest = lhs + rhs;
2007 ASSIGNZ (dest == 0);
2008
2009 if ((lhs | rhs) >> 30)
2010 {
2011 /* Possible C,V,N to set. */
2012 ASSIGNN (NEG (dest));
2013 ARMul_AddCarry (state, lhs, rhs, dest);
2014 ARMul_AddOverflow (state, lhs, rhs, dest);
2015 }
2016 else
2017 {
2018 CLEARN;
2019 CLEARC;
2020 CLEARV;
2021 }
2022 WRITESDEST (dest);
2023 break;
2024
2025 case 0x2a: /* ADC immed */
2026 dest = LHS + DPImmRHS + CFLAG;
2027 WRITEDEST (dest);
2028 break;
2029
2030 case 0x2b: /* ADCS immed */
2031 lhs = LHS;
2032 rhs = DPImmRHS;
2033 dest = lhs + rhs + CFLAG;
2034 ASSIGNZ (dest == 0);
2035 if ((lhs | rhs) >> 30)
2036 {
2037 /* Possible C,V,N to set. */
2038 ASSIGNN (NEG (dest));
2039 ARMul_AddCarry (state, lhs, rhs, dest);
2040 ARMul_AddOverflow (state, lhs, rhs, dest);
2041 }
2042 else
2043 {
2044 CLEARN;
2045 CLEARC;
2046 CLEARV;
2047 }
2048 WRITESDEST (dest);
2049 break;
2050
2051 case 0x2c: /* SBC immed */
2052 dest = LHS - DPImmRHS - !CFLAG;
2053 WRITEDEST (dest);
2054 break;
2055
2056 case 0x2d: /* SBCS immed */
2057 lhs = LHS;
2058 rhs = DPImmRHS;
2059 dest = lhs - rhs - !CFLAG;
2060 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2061 {
2062 ARMul_SubCarry (state, lhs, rhs, dest);
2063 ARMul_SubOverflow (state, lhs, rhs, dest);
2064 }
2065 else
2066 {
2067 CLEARC;
2068 CLEARV;
2069 }
2070 WRITESDEST (dest);
2071 break;
2072
2073 case 0x2e: /* RSC immed */
2074 dest = DPImmRHS - LHS - !CFLAG;
2075 WRITEDEST (dest);
2076 break;
2077
2078 case 0x2f: /* RSCS immed */
2079 lhs = LHS;
2080 rhs = DPImmRHS;
2081 dest = rhs - lhs - !CFLAG;
2082 if ((rhs >= lhs) || ((rhs | lhs) >> 31))
2083 {
2084 ARMul_SubCarry (state, rhs, lhs, dest);
2085 ARMul_SubOverflow (state, rhs, lhs, dest);
2086 }
2087 else
2088 {
2089 CLEARC;
2090 CLEARV;
2091 }
2092 WRITESDEST (dest);
2093 break;
2094
2095 case 0x30: /* TST immed */
2096 UNDEF_Test;
2097 break;
2098
2099 case 0x31: /* TSTP immed */
2100 if (DESTReg == 15)
2101 {
2102 /* TSTP immed. */
2103 #ifdef MODE32
2104 state->Cpsr = GETSPSR (state->Bank);
2105 ARMul_CPSRAltered (state);
2106 #else
2107 temp = LHS & DPImmRHS;
2108 SETR15PSR (temp);
2109 #endif
2110 }
2111 else
2112 {
2113 /* TST immed. */
2114 DPSImmRHS;
2115 dest = LHS & rhs;
2116 ARMul_NegZero (state, dest);
2117 }
2118 break;
2119
2120 case 0x32: /* TEQ immed and MSR immed to CPSR */
2121 if (DESTReg == 15)
2122 /* MSR immed to CPSR. */
2123 ARMul_FixCPSR (state, instr, DPImmRHS);
2124 else
2125 UNDEF_Test;
2126 break;
2127
2128 case 0x33: /* TEQP immed */
2129 if (DESTReg == 15)
2130 {
2131 /* TEQP immed. */
2132 #ifdef MODE32
2133 state->Cpsr = GETSPSR (state->Bank);
2134 ARMul_CPSRAltered (state);
2135 #else
2136 temp = LHS ^ DPImmRHS;
2137 SETR15PSR (temp);
2138 #endif
2139 }
2140 else
2141 {
2142 DPSImmRHS; /* TEQ immed */
2143 dest = LHS ^ rhs;
2144 ARMul_NegZero (state, dest);
2145 }
2146 break;
2147
2148 case 0x34: /* CMP immed */
2149 UNDEF_Test;
2150 break;
2151
2152 case 0x35: /* CMPP immed */
2153 if (DESTReg == 15)
2154 {
2155 /* CMPP immed. */
2156 #ifdef MODE32
2157 state->Cpsr = GETSPSR (state->Bank);
2158 ARMul_CPSRAltered (state);
2159 #else
2160 temp = LHS - DPImmRHS;
2161 SETR15PSR (temp);
2162 #endif
2163 break;
2164 }
2165 else
2166 {
2167 /* CMP immed. */
2168 lhs = LHS;
2169 rhs = DPImmRHS;
2170 dest = lhs - rhs;
2171 ARMul_NegZero (state, dest);
2172
2173 if ((lhs >= rhs) || ((rhs | lhs) >> 31))
2174 {
2175 ARMul_SubCarry (state, lhs, rhs, dest);
2176 ARMul_SubOverflow (state, lhs, rhs, dest);
2177 }
2178 else
2179 {
2180 CLEARC;
2181 CLEARV;
2182 }
2183 }
2184 break;
2185
2186 case 0x36: /* CMN immed and MSR immed to SPSR */
2187 if (DESTReg == 15)
2188 ARMul_FixSPSR (state, instr, DPImmRHS);
2189 else
2190 UNDEF_Test;
2191 break;
2192
2193 case 0x37: /* CMNP immed. */
2194 if (DESTReg == 15)
2195 {
2196 /* CMNP immed. */
2197 #ifdef MODE32
2198 state->Cpsr = GETSPSR (state->Bank);
2199 ARMul_CPSRAltered (state);
2200 #else
2201 temp = LHS + DPImmRHS;
2202 SETR15PSR (temp);
2203 #endif
2204 break;
2205 }
2206 else
2207 {
2208 /* CMN immed. */
2209 lhs = LHS;
2210 rhs = DPImmRHS;
2211 dest = lhs + rhs;
2212 ASSIGNZ (dest == 0);
2213 if ((lhs | rhs) >> 30)
2214 {
2215 /* Possible C,V,N to set. */
2216 ASSIGNN (NEG (dest));
2217 ARMul_AddCarry (state, lhs, rhs, dest);
2218 ARMul_AddOverflow (state, lhs, rhs, dest);
2219 }
2220 else
2221 {
2222 CLEARN;
2223 CLEARC;
2224 CLEARV;
2225 }
2226 }
2227 break;
2228
2229 case 0x38: /* ORR immed. */
2230 dest = LHS | DPImmRHS;
2231 WRITEDEST (dest);
2232 break;
2233
2234 case 0x39: /* ORRS immed. */
2235 DPSImmRHS;
2236 dest = LHS | rhs;
2237 WRITESDEST (dest);
2238 break;
2239
2240 case 0x3a: /* MOV immed. */
2241 dest = DPImmRHS;
2242 WRITEDEST (dest);
2243 break;
2244
2245 case 0x3b: /* MOVS immed. */
2246 DPSImmRHS;
2247 WRITESDEST (rhs);
2248 break;
2249
2250 case 0x3c: /* BIC immed. */
2251 dest = LHS & ~DPImmRHS;
2252 WRITEDEST (dest);
2253 break;
2254
2255 case 0x3d: /* BICS immed. */
2256 DPSImmRHS;
2257 dest = LHS & ~rhs;
2258 WRITESDEST (dest);
2259 break;
2260
2261 case 0x3e: /* MVN immed. */
2262 dest = ~DPImmRHS;
2263 WRITEDEST (dest);
2264 break;
2265
2266 case 0x3f: /* MVNS immed. */
2267 DPSImmRHS;
2268 WRITESDEST (~rhs);
2269 break;
2270
2271
2272 /* Single Data Transfer Immediate RHS Instructions. */
2273
2274 case 0x40: /* Store Word, No WriteBack, Post Dec, Immed. */
2275 lhs = LHS;
2276 if (StoreWord (state, instr, lhs))
2277 LSBase = lhs - LSImmRHS;
2278 break;
2279
2280 case 0x41: /* Load Word, No WriteBack, Post Dec, Immed. */
2281 lhs = LHS;
2282 if (LoadWord (state, instr, lhs))
2283 LSBase = lhs - LSImmRHS;
2284 break;
2285
2286 case 0x42: /* Store Word, WriteBack, Post Dec, Immed. */
2287 UNDEF_LSRBaseEQDestWb;
2288 UNDEF_LSRPCBaseWb;
2289 lhs = LHS;
2290 temp = lhs - LSImmRHS;
2291 state->NtransSig = LOW;
2292 if (StoreWord (state, instr, lhs))
2293 LSBase = temp;
2294 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2295 break;
2296
2297 case 0x43: /* Load Word, WriteBack, Post Dec, Immed. */
2298 UNDEF_LSRBaseEQDestWb;
2299 UNDEF_LSRPCBaseWb;
2300 lhs = LHS;
2301 state->NtransSig = LOW;
2302 if (LoadWord (state, instr, lhs))
2303 LSBase = lhs - LSImmRHS;
2304 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2305 break;
2306
2307 case 0x44: /* Store Byte, No WriteBack, Post Dec, Immed. */
2308 lhs = LHS;
2309 if (StoreByte (state, instr, lhs))
2310 LSBase = lhs - LSImmRHS;
2311 break;
2312
2313 case 0x45: /* Load Byte, No WriteBack, Post Dec, Immed. */
2314 lhs = LHS;
2315 if (LoadByte (state, instr, lhs, LUNSIGNED))
2316 LSBase = lhs - LSImmRHS;
2317 break;
2318
2319 case 0x46: /* Store Byte, WriteBack, Post Dec, Immed. */
2320 UNDEF_LSRBaseEQDestWb;
2321 UNDEF_LSRPCBaseWb;
2322 lhs = LHS;
2323 state->NtransSig = LOW;
2324 if (StoreByte (state, instr, lhs))
2325 LSBase = lhs - LSImmRHS;
2326 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2327 break;
2328
2329 case 0x47: /* Load Byte, WriteBack, Post Dec, Immed. */
2330 UNDEF_LSRBaseEQDestWb;
2331 UNDEF_LSRPCBaseWb;
2332 lhs = LHS;
2333 state->NtransSig = LOW;
2334 if (LoadByte (state, instr, lhs, LUNSIGNED))
2335 LSBase = lhs - LSImmRHS;
2336 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2337 break;
2338
2339 case 0x48: /* Store Word, No WriteBack, Post Inc, Immed. */
2340 lhs = LHS;
2341 if (StoreWord (state, instr, lhs))
2342 LSBase = lhs + LSImmRHS;
2343 break;
2344
2345 case 0x49: /* Load Word, No WriteBack, Post Inc, Immed. */
2346 lhs = LHS;
2347 if (LoadWord (state, instr, lhs))
2348 LSBase = lhs + LSImmRHS;
2349 break;
2350
2351 case 0x4a: /* Store Word, WriteBack, Post Inc, Immed. */
2352 UNDEF_LSRBaseEQDestWb;
2353 UNDEF_LSRPCBaseWb;
2354 lhs = LHS;
2355 state->NtransSig = LOW;
2356 if (StoreWord (state, instr, lhs))
2357 LSBase = lhs + LSImmRHS;
2358 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2359 break;
2360
2361 case 0x4b: /* Load Word, WriteBack, Post Inc, Immed. */
2362 UNDEF_LSRBaseEQDestWb;
2363 UNDEF_LSRPCBaseWb;
2364 lhs = LHS;
2365 state->NtransSig = LOW;
2366 if (LoadWord (state, instr, lhs))
2367 LSBase = lhs + LSImmRHS;
2368 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2369 break;
2370
2371 case 0x4c: /* Store Byte, No WriteBack, Post Inc, Immed. */
2372 lhs = LHS;
2373 if (StoreByte (state, instr, lhs))
2374 LSBase = lhs + LSImmRHS;
2375 break;
2376
2377 case 0x4d: /* Load Byte, No WriteBack, Post Inc, Immed. */
2378 lhs = LHS;
2379 if (LoadByte (state, instr, lhs, LUNSIGNED))
2380 LSBase = lhs + LSImmRHS;
2381 break;
2382
2383 case 0x4e: /* Store Byte, WriteBack, Post Inc, Immed. */
2384 UNDEF_LSRBaseEQDestWb;
2385 UNDEF_LSRPCBaseWb;
2386 lhs = LHS;
2387 state->NtransSig = LOW;
2388 if (StoreByte (state, instr, lhs))
2389 LSBase = lhs + LSImmRHS;
2390 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2391 break;
2392
2393 case 0x4f: /* Load Byte, WriteBack, Post Inc, Immed. */
2394 UNDEF_LSRBaseEQDestWb;
2395 UNDEF_LSRPCBaseWb;
2396 lhs = LHS;
2397 state->NtransSig = LOW;
2398 if (LoadByte (state, instr, lhs, LUNSIGNED))
2399 LSBase = lhs + LSImmRHS;
2400 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2401 break;
2402
2403
2404 case 0x50: /* Store Word, No WriteBack, Pre Dec, Immed. */
2405 (void) StoreWord (state, instr, LHS - LSImmRHS);
2406 break;
2407
2408 case 0x51: /* Load Word, No WriteBack, Pre Dec, Immed. */
2409 (void) LoadWord (state, instr, LHS - LSImmRHS);
2410 break;
2411
2412 case 0x52: /* Store Word, WriteBack, Pre Dec, Immed. */
2413 UNDEF_LSRBaseEQDestWb;
2414 UNDEF_LSRPCBaseWb;
2415 temp = LHS - LSImmRHS;
2416 if (StoreWord (state, instr, temp))
2417 LSBase = temp;
2418 break;
2419
2420 case 0x53: /* Load Word, WriteBack, Pre Dec, Immed. */
2421 UNDEF_LSRBaseEQDestWb;
2422 UNDEF_LSRPCBaseWb;
2423 temp = LHS - LSImmRHS;
2424 if (LoadWord (state, instr, temp))
2425 LSBase = temp;
2426 break;
2427
2428 case 0x54: /* Store Byte, No WriteBack, Pre Dec, Immed. */
2429 (void) StoreByte (state, instr, LHS - LSImmRHS);
2430 break;
2431
2432 case 0x55: /* Load Byte, No WriteBack, Pre Dec, Immed. */
2433 (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
2434 break;
2435
2436 case 0x56: /* Store Byte, WriteBack, Pre Dec, Immed. */
2437 UNDEF_LSRBaseEQDestWb;
2438 UNDEF_LSRPCBaseWb;
2439 temp = LHS - LSImmRHS;
2440 if (StoreByte (state, instr, temp))
2441 LSBase = temp;
2442 break;
2443
2444 case 0x57: /* Load Byte, WriteBack, Pre Dec, Immed. */
2445 UNDEF_LSRBaseEQDestWb;
2446 UNDEF_LSRPCBaseWb;
2447 temp = LHS - LSImmRHS;
2448 if (LoadByte (state, instr, temp, LUNSIGNED))
2449 LSBase = temp;
2450 break;
2451
2452 case 0x58: /* Store Word, No WriteBack, Pre Inc, Immed. */
2453 (void) StoreWord (state, instr, LHS + LSImmRHS);
2454 break;
2455
2456 case 0x59: /* Load Word, No WriteBack, Pre Inc, Immed. */
2457 (void) LoadWord (state, instr, LHS + LSImmRHS);
2458 break;
2459
2460 case 0x5a: /* Store Word, WriteBack, Pre Inc, Immed. */
2461 UNDEF_LSRBaseEQDestWb;
2462 UNDEF_LSRPCBaseWb;
2463 temp = LHS + LSImmRHS;
2464 if (StoreWord (state, instr, temp))
2465 LSBase = temp;
2466 break;
2467
2468 case 0x5b: /* Load Word, WriteBack, Pre Inc, Immed. */
2469 UNDEF_LSRBaseEQDestWb;
2470 UNDEF_LSRPCBaseWb;
2471 temp = LHS + LSImmRHS;
2472 if (LoadWord (state, instr, temp))
2473 LSBase = temp;
2474 break;
2475
2476 case 0x5c: /* Store Byte, No WriteBack, Pre Inc, Immed. */
2477 (void) StoreByte (state, instr, LHS + LSImmRHS);
2478 break;
2479
2480 case 0x5d: /* Load Byte, No WriteBack, Pre Inc, Immed. */
2481 (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
2482 break;
2483
2484 case 0x5e: /* Store Byte, WriteBack, Pre Inc, Immed. */
2485 UNDEF_LSRBaseEQDestWb;
2486 UNDEF_LSRPCBaseWb;
2487 temp = LHS + LSImmRHS;
2488 if (StoreByte (state, instr, temp))
2489 LSBase = temp;
2490 break;
2491
2492 case 0x5f: /* Load Byte, WriteBack, Pre Inc, Immed. */
2493 UNDEF_LSRBaseEQDestWb;
2494 UNDEF_LSRPCBaseWb;
2495 temp = LHS + LSImmRHS;
2496 if (LoadByte (state, instr, temp, LUNSIGNED))
2497 LSBase = temp;
2498 break;
2499
2500
2501 /* Single Data Transfer Register RHS Instructions. */
2502
2503 case 0x60: /* Store Word, No WriteBack, Post Dec, Reg. */
2504 if (BIT (4))
2505 {
2506 ARMul_UndefInstr (state, instr);
2507 break;
2508 }
2509 UNDEF_LSRBaseEQOffWb;
2510 UNDEF_LSRBaseEQDestWb;
2511 UNDEF_LSRPCBaseWb;
2512 UNDEF_LSRPCOffWb;
2513 lhs = LHS;
2514 if (StoreWord (state, instr, lhs))
2515 LSBase = lhs - LSRegRHS;
2516 break;
2517
2518 case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
2519 if (BIT (4))
2520 {
2521 ARMul_UndefInstr (state, instr);
2522 break;
2523 }
2524 UNDEF_LSRBaseEQOffWb;
2525 UNDEF_LSRBaseEQDestWb;
2526 UNDEF_LSRPCBaseWb;
2527 UNDEF_LSRPCOffWb;
2528 lhs = LHS;
2529 temp = lhs - LSRegRHS;
2530 if (LoadWord (state, instr, lhs))
2531 LSBase = temp;
2532 break;
2533
2534 case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
2535 if (BIT (4))
2536 {
2537 ARMul_UndefInstr (state, instr);
2538 break;
2539 }
2540 UNDEF_LSRBaseEQOffWb;
2541 UNDEF_LSRBaseEQDestWb;
2542 UNDEF_LSRPCBaseWb;
2543 UNDEF_LSRPCOffWb;
2544 lhs = LHS;
2545 state->NtransSig = LOW;
2546 if (StoreWord (state, instr, lhs))
2547 LSBase = lhs - LSRegRHS;
2548 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2549 break;
2550
2551 case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
2552 if (BIT (4))
2553 {
2554 ARMul_UndefInstr (state, instr);
2555 break;
2556 }
2557 UNDEF_LSRBaseEQOffWb;
2558 UNDEF_LSRBaseEQDestWb;
2559 UNDEF_LSRPCBaseWb;
2560 UNDEF_LSRPCOffWb;
2561 lhs = LHS;
2562 temp = lhs - LSRegRHS;
2563 state->NtransSig = LOW;
2564 if (LoadWord (state, instr, lhs))
2565 LSBase = temp;
2566 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2567 break;
2568
2569 case 0x64: /* Store Byte, No WriteBack, Post Dec, Reg. */
2570 if (BIT (4))
2571 {
2572 ARMul_UndefInstr (state, instr);
2573 break;
2574 }
2575 UNDEF_LSRBaseEQOffWb;
2576 UNDEF_LSRBaseEQDestWb;
2577 UNDEF_LSRPCBaseWb;
2578 UNDEF_LSRPCOffWb;
2579 lhs = LHS;
2580 if (StoreByte (state, instr, lhs))
2581 LSBase = lhs - LSRegRHS;
2582 break;
2583
2584 case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
2585 if (BIT (4))
2586 {
2587 ARMul_UndefInstr (state, instr);
2588 break;
2589 }
2590 UNDEF_LSRBaseEQOffWb;
2591 UNDEF_LSRBaseEQDestWb;
2592 UNDEF_LSRPCBaseWb;
2593 UNDEF_LSRPCOffWb;
2594 lhs = LHS;
2595 temp = lhs - LSRegRHS;
2596 if (LoadByte (state, instr, lhs, LUNSIGNED))
2597 LSBase = temp;
2598 break;
2599
2600 case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
2601 if (BIT (4))
2602 {
2603 ARMul_UndefInstr (state, instr);
2604 break;
2605 }
2606 UNDEF_LSRBaseEQOffWb;
2607 UNDEF_LSRBaseEQDestWb;
2608 UNDEF_LSRPCBaseWb;
2609 UNDEF_LSRPCOffWb;
2610 lhs = LHS;
2611 state->NtransSig = LOW;
2612 if (StoreByte (state, instr, lhs))
2613 LSBase = lhs - LSRegRHS;
2614 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2615 break;
2616
2617 case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
2618 if (BIT (4))
2619 {
2620 ARMul_UndefInstr (state, instr);
2621 break;
2622 }
2623 UNDEF_LSRBaseEQOffWb;
2624 UNDEF_LSRBaseEQDestWb;
2625 UNDEF_LSRPCBaseWb;
2626 UNDEF_LSRPCOffWb;
2627 lhs = LHS;
2628 temp = lhs - LSRegRHS;
2629 state->NtransSig = LOW;
2630 if (LoadByte (state, instr, lhs, LUNSIGNED))
2631 LSBase = temp;
2632 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2633 break;
2634
2635 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
2636 if (BIT (4))
2637 {
2638 ARMul_UndefInstr (state, instr);
2639 break;
2640 }
2641 UNDEF_LSRBaseEQOffWb;
2642 UNDEF_LSRBaseEQDestWb;
2643 UNDEF_LSRPCBaseWb;
2644 UNDEF_LSRPCOffWb;
2645 lhs = LHS;
2646 if (StoreWord (state, instr, lhs))
2647 LSBase = lhs + LSRegRHS;
2648 break;
2649
2650 case 0x69: /* Load Word, No WriteBack, Post Inc, Reg. */
2651 if (BIT (4))
2652 {
2653 ARMul_UndefInstr (state, instr);
2654 break;
2655 }
2656 UNDEF_LSRBaseEQOffWb;
2657 UNDEF_LSRBaseEQDestWb;
2658 UNDEF_LSRPCBaseWb;
2659 UNDEF_LSRPCOffWb;
2660 lhs = LHS;
2661 temp = lhs + LSRegRHS;
2662 if (LoadWord (state, instr, lhs))
2663 LSBase = temp;
2664 break;
2665
2666 case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
2667 if (BIT (4))
2668 {
2669 ARMul_UndefInstr (state, instr);
2670 break;
2671 }
2672 UNDEF_LSRBaseEQOffWb;
2673 UNDEF_LSRBaseEQDestWb;
2674 UNDEF_LSRPCBaseWb;
2675 UNDEF_LSRPCOffWb;
2676 lhs = LHS;
2677 state->NtransSig = LOW;
2678 if (StoreWord (state, instr, lhs))
2679 LSBase = lhs + LSRegRHS;
2680 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2681 break;
2682
2683 case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
2684 if (BIT (4))
2685 {
2686 ARMul_UndefInstr (state, instr);
2687 break;
2688 }
2689 UNDEF_LSRBaseEQOffWb;
2690 UNDEF_LSRBaseEQDestWb;
2691 UNDEF_LSRPCBaseWb;
2692 UNDEF_LSRPCOffWb;
2693 lhs = LHS;
2694 temp = lhs + LSRegRHS;
2695 state->NtransSig = LOW;
2696 if (LoadWord (state, instr, lhs))
2697 LSBase = temp;
2698 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2699 break;
2700
2701 case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
2702 if (BIT (4))
2703 {
2704 ARMul_UndefInstr (state, instr);
2705 break;
2706 }
2707 UNDEF_LSRBaseEQOffWb;
2708 UNDEF_LSRBaseEQDestWb;
2709 UNDEF_LSRPCBaseWb;
2710 UNDEF_LSRPCOffWb;
2711 lhs = LHS;
2712 if (StoreByte (state, instr, lhs))
2713 LSBase = lhs + LSRegRHS;
2714 break;
2715
2716 case 0x6d: /* Load Byte, No WriteBack, Post Inc, Reg. */
2717 if (BIT (4))
2718 {
2719 ARMul_UndefInstr (state, instr);
2720 break;
2721 }
2722 UNDEF_LSRBaseEQOffWb;
2723 UNDEF_LSRBaseEQDestWb;
2724 UNDEF_LSRPCBaseWb;
2725 UNDEF_LSRPCOffWb;
2726 lhs = LHS;
2727 temp = lhs + LSRegRHS;
2728 if (LoadByte (state, instr, lhs, LUNSIGNED))
2729 LSBase = temp;
2730 break;
2731
2732 case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
2733 if (BIT (4))
2734 {
2735 ARMul_UndefInstr (state, instr);
2736 break;
2737 }
2738 UNDEF_LSRBaseEQOffWb;
2739 UNDEF_LSRBaseEQDestWb;
2740 UNDEF_LSRPCBaseWb;
2741 UNDEF_LSRPCOffWb;
2742 lhs = LHS;
2743 state->NtransSig = LOW;
2744 if (StoreByte (state, instr, lhs))
2745 LSBase = lhs + LSRegRHS;
2746 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2747 break;
2748
2749 case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
2750 if (BIT (4))
2751 {
2752 ARMul_UndefInstr (state, instr);
2753 break;
2754 }
2755 UNDEF_LSRBaseEQOffWb;
2756 UNDEF_LSRBaseEQDestWb;
2757 UNDEF_LSRPCBaseWb;
2758 UNDEF_LSRPCOffWb;
2759 lhs = LHS;
2760 temp = lhs + LSRegRHS;
2761 state->NtransSig = LOW;
2762 if (LoadByte (state, instr, lhs, LUNSIGNED))
2763 LSBase = temp;
2764 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
2765 break;
2766
2767
2768 case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
2769 if (BIT (4))
2770 {
2771 ARMul_UndefInstr (state, instr);
2772 break;
2773 }
2774 (void) StoreWord (state, instr, LHS - LSRegRHS);
2775 break;
2776
2777 case 0x71: /* Load Word, No WriteBack, Pre Dec, Reg. */
2778 if (BIT (4))
2779 {
2780 ARMul_UndefInstr (state, instr);
2781 break;
2782 }
2783 (void) LoadWord (state, instr, LHS - LSRegRHS);
2784 break;
2785
2786 case 0x72: /* Store Word, WriteBack, Pre Dec, Reg. */
2787 if (BIT (4))
2788 {
2789 ARMul_UndefInstr (state, instr);
2790 break;
2791 }
2792 UNDEF_LSRBaseEQOffWb;
2793 UNDEF_LSRBaseEQDestWb;
2794 UNDEF_LSRPCBaseWb;
2795 UNDEF_LSRPCOffWb;
2796 temp = LHS - LSRegRHS;
2797 if (StoreWord (state, instr, temp))
2798 LSBase = temp;
2799 break;
2800
2801 case 0x73: /* Load Word, WriteBack, Pre Dec, Reg. */
2802 if (BIT (4))
2803 {
2804 ARMul_UndefInstr (state, instr);
2805 break;
2806 }
2807 UNDEF_LSRBaseEQOffWb;
2808 UNDEF_LSRBaseEQDestWb;
2809 UNDEF_LSRPCBaseWb;
2810 UNDEF_LSRPCOffWb;
2811 temp = LHS - LSRegRHS;
2812 if (LoadWord (state, instr, temp))
2813 LSBase = temp;
2814 break;
2815
2816 case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
2817 if (BIT (4))
2818 {
2819 ARMul_UndefInstr (state, instr);
2820 break;
2821 }
2822 (void) StoreByte (state, instr, LHS - LSRegRHS);
2823 break;
2824
2825 case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
2826 if (BIT (4))
2827 {
2828 ARMul_UndefInstr (state, instr);
2829 break;
2830 }
2831 (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
2832 break;
2833
2834 case 0x76: /* Store Byte, WriteBack, Pre Dec, Reg. */
2835 if (BIT (4))
2836 {
2837 ARMul_UndefInstr (state, instr);
2838 break;
2839 }
2840 UNDEF_LSRBaseEQOffWb;
2841 UNDEF_LSRBaseEQDestWb;
2842 UNDEF_LSRPCBaseWb;
2843 UNDEF_LSRPCOffWb;
2844 temp = LHS - LSRegRHS;
2845 if (StoreByte (state, instr, temp))
2846 LSBase = temp;
2847 break;
2848
2849 case 0x77: /* Load Byte, WriteBack, Pre Dec, Reg. */
2850 if (BIT (4))
2851 {
2852 ARMul_UndefInstr (state, instr);
2853 break;
2854 }
2855 UNDEF_LSRBaseEQOffWb;
2856 UNDEF_LSRBaseEQDestWb;
2857 UNDEF_LSRPCBaseWb;
2858 UNDEF_LSRPCOffWb;
2859 temp = LHS - LSRegRHS;
2860 if (LoadByte (state, instr, temp, LUNSIGNED))
2861 LSBase = temp;
2862 break;
2863
2864 case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
2865 if (BIT (4))
2866 {
2867 ARMul_UndefInstr (state, instr);
2868 break;
2869 }
2870 (void) StoreWord (state, instr, LHS + LSRegRHS);
2871 break;
2872
2873 case 0x79: /* Load Word, No WriteBack, Pre Inc, Reg. */
2874 if (BIT (4))
2875 {
2876 ARMul_UndefInstr (state, instr);
2877 break;
2878 }
2879 (void) LoadWord (state, instr, LHS + LSRegRHS);
2880 break;
2881
2882 case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
2883 if (BIT (4))
2884 {
2885 ARMul_UndefInstr (state, instr);
2886 break;
2887 }
2888 UNDEF_LSRBaseEQOffWb;
2889 UNDEF_LSRBaseEQDestWb;
2890 UNDEF_LSRPCBaseWb;
2891 UNDEF_LSRPCOffWb;
2892 temp = LHS + LSRegRHS;
2893 if (StoreWord (state, instr, temp))
2894 LSBase = temp;
2895 break;
2896
2897 case 0x7b: /* Load Word, WriteBack, Pre Inc, Reg. */
2898 if (BIT (4))
2899 {
2900 ARMul_UndefInstr (state, instr);
2901 break;
2902 }
2903 UNDEF_LSRBaseEQOffWb;
2904 UNDEF_LSRBaseEQDestWb;
2905 UNDEF_LSRPCBaseWb;
2906 UNDEF_LSRPCOffWb;
2907 temp = LHS + LSRegRHS;
2908 if (LoadWord (state, instr, temp))
2909 LSBase = temp;
2910 break;
2911
2912 case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
2913 if (BIT (4))
2914 {
2915 ARMul_UndefInstr (state, instr);
2916 break;
2917 }
2918 (void) StoreByte (state, instr, LHS + LSRegRHS);
2919 break;
2920
2921 case 0x7d: /* Load Byte, No WriteBack, Pre Inc, Reg. */
2922 if (BIT (4))
2923 {
2924 ARMul_UndefInstr (state, instr);
2925 break;
2926 }
2927 (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
2928 break;
2929
2930 case 0x7e: /* Store Byte, WriteBack, Pre Inc, Reg. */
2931 if (BIT (4))
2932 {
2933 ARMul_UndefInstr (state, instr);
2934 break;
2935 }
2936 UNDEF_LSRBaseEQOffWb;
2937 UNDEF_LSRBaseEQDestWb;
2938 UNDEF_LSRPCBaseWb;
2939 UNDEF_LSRPCOffWb;
2940 temp = LHS + LSRegRHS;
2941 if (StoreByte (state, instr, temp))
2942 LSBase = temp;
2943 break;
2944
2945 case 0x7f: /* Load Byte, WriteBack, Pre Inc, Reg. */
2946 if (BIT (4))
2947 {
2948 /* Check for the special breakpoint opcode.
2949 This value should correspond to the value defined
2950 as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h. */
2951 if (BITS (0, 19) == 0xfdefe)
2952 {
2953 if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
2954 ARMul_Abort (state, ARMul_SWIV);
2955 }
2956 else
2957 ARMul_UndefInstr (state, instr);
2958 break;
2959 }
2960 UNDEF_LSRBaseEQOffWb;
2961 UNDEF_LSRBaseEQDestWb;
2962 UNDEF_LSRPCBaseWb;
2963 UNDEF_LSRPCOffWb;
2964 temp = LHS + LSRegRHS;
2965 if (LoadByte (state, instr, temp, LUNSIGNED))
2966 LSBase = temp;
2967 break;
2968
2969
2970 /* Multiple Data Transfer Instructions. */
2971
2972 case 0x80: /* Store, No WriteBack, Post Dec. */
2973 STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2974 break;
2975
2976 case 0x81: /* Load, No WriteBack, Post Dec. */
2977 LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2978 break;
2979
2980 case 0x82: /* Store, WriteBack, Post Dec. */
2981 temp = LSBase - LSMNumRegs;
2982 STOREMULT (instr, temp + 4L, temp);
2983 break;
2984
2985 case 0x83: /* Load, WriteBack, Post Dec. */
2986 temp = LSBase - LSMNumRegs;
2987 LOADMULT (instr, temp + 4L, temp);
2988 break;
2989
2990 case 0x84: /* Store, Flags, No WriteBack, Post Dec. */
2991 STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2992 break;
2993
2994 case 0x85: /* Load, Flags, No WriteBack, Post Dec. */
2995 LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
2996 break;
2997
2998 case 0x86: /* Store, Flags, WriteBack, Post Dec. */
2999 temp = LSBase - LSMNumRegs;
3000 STORESMULT (instr, temp + 4L, temp);
3001 break;
3002
3003 case 0x87: /* Load, Flags, WriteBack, Post Dec. */
3004 temp = LSBase - LSMNumRegs;
3005 LOADSMULT (instr, temp + 4L, temp);
3006 break;
3007
3008 case 0x88: /* Store, No WriteBack, Post Inc. */
3009 STOREMULT (instr, LSBase, 0L);
3010 break;
3011
3012 case 0x89: /* Load, No WriteBack, Post Inc. */
3013 LOADMULT (instr, LSBase, 0L);
3014 break;
3015
3016 case 0x8a: /* Store, WriteBack, Post Inc. */
3017 temp = LSBase;
3018 STOREMULT (instr, temp, temp + LSMNumRegs);
3019 break;
3020
3021 case 0x8b: /* Load, WriteBack, Post Inc. */
3022 temp = LSBase;
3023 LOADMULT (instr, temp, temp + LSMNumRegs);
3024 break;
3025
3026 case 0x8c: /* Store, Flags, No WriteBack, Post Inc. */
3027 STORESMULT (instr, LSBase, 0L);
3028 break;
3029
3030 case 0x8d: /* Load, Flags, No WriteBack, Post Inc. */
3031 LOADSMULT (instr, LSBase, 0L);
3032 break;
3033
3034 case 0x8e: /* Store, Flags, WriteBack, Post Inc. */
3035 temp = LSBase;
3036 STORESMULT (instr, temp, temp + LSMNumRegs);
3037 break;
3038
3039 case 0x8f: /* Load, Flags, WriteBack, Post Inc. */
3040 temp = LSBase;
3041 LOADSMULT (instr, temp, temp + LSMNumRegs);
3042 break;
3043
3044 case 0x90: /* Store, No WriteBack, Pre Dec. */
3045 STOREMULT (instr, LSBase - LSMNumRegs, 0L);
3046 break;
3047
3048 case 0x91: /* Load, No WriteBack, Pre Dec. */
3049 LOADMULT (instr, LSBase - LSMNumRegs, 0L);
3050 break;
3051
3052 case 0x92: /* Store, WriteBack, Pre Dec. */
3053 temp = LSBase - LSMNumRegs;
3054 STOREMULT (instr, temp, temp);
3055 break;
3056
3057 case 0x93: /* Load, WriteBack, Pre Dec. */
3058 temp = LSBase - LSMNumRegs;
3059 LOADMULT (instr, temp, temp);
3060 break;
3061
3062 case 0x94: /* Store, Flags, No WriteBack, Pre Dec. */
3063 STORESMULT (instr, LSBase - LSMNumRegs, 0L);
3064 break;
3065
3066 case 0x95: /* Load, Flags, No WriteBack, Pre Dec. */
3067 LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
3068 break;
3069
3070 case 0x96: /* Store, Flags, WriteBack, Pre Dec. */
3071 temp = LSBase - LSMNumRegs;
3072 STORESMULT (instr, temp, temp);
3073 break;
3074
3075 case 0x97: /* Load, Flags, WriteBack, Pre Dec. */
3076 temp = LSBase - LSMNumRegs;
3077 LOADSMULT (instr, temp, temp);
3078 break;
3079
3080 case 0x98: /* Store, No WriteBack, Pre Inc. */
3081 STOREMULT (instr, LSBase + 4L, 0L);
3082 break;
3083
3084 case 0x99: /* Load, No WriteBack, Pre Inc. */
3085 LOADMULT (instr, LSBase + 4L, 0L);
3086 break;
3087
3088 case 0x9a: /* Store, WriteBack, Pre Inc. */
3089 temp = LSBase;
3090 STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
3091 break;
3092
3093 case 0x9b: /* Load, WriteBack, Pre Inc. */
3094 temp = LSBase;
3095 LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
3096 break;
3097
3098 case 0x9c: /* Store, Flags, No WriteBack, Pre Inc. */
3099 STORESMULT (instr, LSBase + 4L, 0L);
3100 break;
3101
3102 case 0x9d: /* Load, Flags, No WriteBack, Pre Inc. */
3103 LOADSMULT (instr, LSBase + 4L, 0L);
3104 break;
3105
3106 case 0x9e: /* Store, Flags, WriteBack, Pre Inc. */
3107 temp = LSBase;
3108 STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
3109 break;
3110
3111 case 0x9f: /* Load, Flags, WriteBack, Pre Inc. */
3112 temp = LSBase;
3113 LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
3114 break;
3115
3116
3117 /* Branch forward. */
3118 case 0xa0:
3119 case 0xa1:
3120 case 0xa2:
3121 case 0xa3:
3122 case 0xa4:
3123 case 0xa5:
3124 case 0xa6:
3125 case 0xa7:
3126 state->Reg[15] = pc + 8 + POSBRANCH;
3127 FLUSHPIPE;
3128 break;
3129
3130
3131 /* Branch backward. */
3132 case 0xa8:
3133 case 0xa9:
3134 case 0xaa:
3135 case 0xab:
3136 case 0xac:
3137 case 0xad:
3138 case 0xae:
3139 case 0xaf:
3140 state->Reg[15] = pc + 8 + NEGBRANCH;
3141 FLUSHPIPE;
3142 break;
3143
3144
3145 /* Branch and Link forward. */
3146 case 0xb0:
3147 case 0xb1:
3148 case 0xb2:
3149 case 0xb3:
3150 case 0xb4:
3151 case 0xb5:
3152 case 0xb6:
3153 case 0xb7:
3154 /* Put PC into Link. */
3155 #ifdef MODE32
3156 state->Reg[14] = pc + 4;
3157 #else
3158 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3159 #endif
3160 state->Reg[15] = pc + 8 + POSBRANCH;
3161 FLUSHPIPE;
3162 break;
3163
3164
3165 /* Branch and Link backward. */
3166 case 0xb8:
3167 case 0xb9:
3168 case 0xba:
3169 case 0xbb:
3170 case 0xbc:
3171 case 0xbd:
3172 case 0xbe:
3173 case 0xbf:
3174 /* Put PC into Link. */
3175 #ifdef MODE32
3176 state->Reg[14] = pc + 4;
3177 #else
3178 state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
3179 #endif
3180 state->Reg[15] = pc + 8 + NEGBRANCH;
3181 FLUSHPIPE;
3182 break;
3183
3184
3185 /* Co-Processor Data Transfers. */
3186 case 0xc4:
3187 if (state->is_v5)
3188 {
3189 /* Reading from R15 is UNPREDICTABLE. */
3190 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3191 ARMul_UndefInstr (state, instr);
3192 /* Is access to coprocessor 0 allowed ? */
3193 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3194 ARMul_UndefInstr (state, instr);
3195 /* Special treatment for XScale coprocessors. */
3196 else if (state->is_XScale)
3197 {
3198 /* Only opcode 0 is supported. */
3199 if (BITS (4, 7) != 0x00)
3200 ARMul_UndefInstr (state, instr);
3201 /* Only coporcessor 0 is supported. */
3202 else if (CPNum != 0x00)
3203 ARMul_UndefInstr (state, instr);
3204 /* Only accumulator 0 is supported. */
3205 else if (BITS (0, 3) != 0x00)
3206 ARMul_UndefInstr (state, instr);
3207 else
3208 {
3209 /* XScale MAR insn. Move two registers into accumulator. */
3210 state->Accumulator = state->Reg[BITS (12, 15)];
3211 state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
3212 }
3213 }
3214 else
3215 /* FIXME: Not sure what to do for other v5 processors. */
3216 ARMul_UndefInstr (state, instr);
3217 break;
3218 }
3219 /* Drop through. */
3220
3221 case 0xc0: /* Store , No WriteBack , Post Dec. */
3222 ARMul_STC (state, instr, LHS);
3223 break;
3224
3225 case 0xc5:
3226 if (state->is_v5)
3227 {
3228 /* Writes to R15 are UNPREDICATABLE. */
3229 if (DESTReg == 15 || LHSReg == 15)
3230 ARMul_UndefInstr (state, instr);
3231 /* Is access to the coprocessor allowed ? */
3232 else if (! CP_ACCESS_ALLOWED (state, CPNum))
3233 ARMul_UndefInstr (state, instr);
3234 /* Special handling for XScale coprcoessors. */
3235 else if (state->is_XScale)
3236 {
3237 /* Only opcode 0 is supported. */
3238 if (BITS (4, 7) != 0x00)
3239 ARMul_UndefInstr (state, instr);
3240 /* Only coprocessor 0 is supported. */
3241 else if (CPNum != 0x00)
3242 ARMul_UndefInstr (state, instr);
3243 /* Only accumulator 0 is supported. */
3244 else if (BITS (0, 3) != 0x00)
3245 ARMul_UndefInstr (state, instr);
3246 else
3247 {
3248 /* XScale MRA insn. Move accumulator into two registers. */
3249 ARMword t1 = (state->Accumulator >> 32) & 255;
3250
3251 if (t1 & 128)
3252 t1 -= 256;
3253
3254 state->Reg[BITS (12, 15)] = state->Accumulator;
3255 state->Reg[BITS (16, 19)] = t1;
3256 break;
3257 }
3258 }
3259 else
3260 /* FIXME: Not sure what to do for other v5 processors. */
3261 ARMul_UndefInstr (state, instr);
3262 break;
3263 }
3264 /* Drop through. */
3265
3266 case 0xc1: /* Load , No WriteBack , Post Dec. */
3267 ARMul_LDC (state, instr, LHS);
3268 break;
3269
3270 case 0xc2:
3271 case 0xc6: /* Store , WriteBack , Post Dec. */
3272 lhs = LHS;
3273 state->Base = lhs - LSCOff;
3274 ARMul_STC (state, instr, lhs);
3275 break;
3276
3277 case 0xc3:
3278 case 0xc7: /* Load , WriteBack , Post Dec. */
3279 lhs = LHS;
3280 state->Base = lhs - LSCOff;
3281 ARMul_LDC (state, instr, lhs);
3282 break;
3283
3284 case 0xc8:
3285 case 0xcc: /* Store , No WriteBack , Post Inc. */
3286 ARMul_STC (state, instr, LHS);
3287 break;
3288
3289 case 0xc9:
3290 case 0xcd: /* Load , No WriteBack , Post Inc. */
3291 ARMul_LDC (state, instr, LHS);
3292 break;
3293
3294 case 0xca:
3295 case 0xce: /* Store , WriteBack , Post Inc. */
3296 lhs = LHS;
3297 state->Base = lhs + LSCOff;
3298 ARMul_STC (state, instr, LHS);
3299 break;
3300
3301 case 0xcb:
3302 case 0xcf: /* Load , WriteBack , Post Inc. */
3303 lhs = LHS;
3304 state->Base = lhs + LSCOff;
3305 ARMul_LDC (state, instr, LHS);
3306 break;
3307
3308 case 0xd0:
3309 case 0xd4: /* Store , No WriteBack , Pre Dec. */
3310 ARMul_STC (state, instr, LHS - LSCOff);
3311 break;
3312
3313 case 0xd1:
3314 case 0xd5: /* Load , No WriteBack , Pre Dec. */
3315 ARMul_LDC (state, instr, LHS - LSCOff);
3316 break;
3317
3318 case 0xd2:
3319 case 0xd6: /* Store , WriteBack , Pre Dec. */
3320 lhs = LHS - LSCOff;
3321 state->Base = lhs;
3322 ARMul_STC (state, instr, lhs);
3323 break;
3324
3325 case 0xd3:
3326 case 0xd7: /* Load , WriteBack , Pre Dec. */
3327 lhs = LHS - LSCOff;
3328 state->Base = lhs;
3329 ARMul_LDC (state, instr, lhs);
3330 break;
3331
3332 case 0xd8:
3333 case 0xdc: /* Store , No WriteBack , Pre Inc. */
3334 ARMul_STC (state, instr, LHS + LSCOff);
3335 break;
3336
3337 case 0xd9:
3338 case 0xdd: /* Load , No WriteBack , Pre Inc. */
3339 ARMul_LDC (state, instr, LHS + LSCOff);
3340 break;
3341
3342 case 0xda:
3343 case 0xde: /* Store , WriteBack , Pre Inc. */
3344 lhs = LHS + LSCOff;
3345 state->Base = lhs;
3346 ARMul_STC (state, instr, lhs);
3347 break;
3348
3349 case 0xdb:
3350 case 0xdf: /* Load , WriteBack , Pre Inc. */
3351 lhs = LHS + LSCOff;
3352 state->Base = lhs;
3353 ARMul_LDC (state, instr, lhs);
3354 break;
3355
3356
3357 /* Co-Processor Register Transfers (MCR) and Data Ops. */
3358
3359 case 0xe2:
3360 if (! CP_ACCESS_ALLOWED (state, CPNum))
3361 {
3362 ARMul_UndefInstr (state, instr);
3363 break;
3364 }
3365 if (state->is_XScale)
3366 switch (BITS (18, 19))
3367 {
3368 case 0x0:
3369 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3370 {
3371 /* XScale MIA instruction. Signed multiplication of
3372 two 32 bit values and addition to 40 bit accumulator. */
3373 long long Rm = state->Reg[MULLHSReg];
3374 long long Rs = state->Reg[MULACCReg];
3375
3376 if (Rm & (1 << 31))
3377 Rm -= 1ULL << 32;
3378 if (Rs & (1 << 31))
3379 Rs -= 1ULL << 32;
3380 state->Accumulator += Rm * Rs;
3381 goto donext;
3382 }
3383 break;
3384
3385 case 0x2:
3386 if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
3387 {
3388 /* XScale MIAPH instruction. */
3389 ARMword t1 = state->Reg[MULLHSReg] >> 16;
3390 ARMword t2 = state->Reg[MULACCReg] >> 16;
3391 ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
3392 ARMword t4 = state->Reg[MULACCReg] & 0xffff;
3393 long long t5;
3394
3395 if (t1 & (1 << 15))
3396 t1 -= 1 << 16;
3397 if (t2 & (1 << 15))
3398 t2 -= 1 << 16;
3399 if (t3 & (1 << 15))
3400 t3 -= 1 << 16;
3401 if (t4 & (1 << 15))
3402 t4 -= 1 << 16;
3403 t1 *= t2;
3404 t5 = t1;
3405 if (t5 & (1 << 31))
3406 t5 -= 1ULL << 32;
3407 state->Accumulator += t5;
3408 t3 *= t4;
3409 t5 = t3;
3410 if (t5 & (1 << 31))
3411 t5 -= 1ULL << 32;
3412 state->Accumulator += t5;
3413 goto donext;
3414 }
3415 break;
3416
3417 case 0x3:
3418 if (BITS (4, 11) == 1)
3419 {
3420 /* XScale MIAxy instruction. */
3421 ARMword t1;
3422 ARMword t2;
3423 long long t5;
3424
3425 if (BIT (17))
3426 t1 = state->Reg[MULLHSReg] >> 16;
3427 else
3428 t1 = state->Reg[MULLHSReg] & 0xffff;
3429
3430 if (BIT (16))
3431 t2 = state->Reg[MULACCReg] >> 16;
3432 else
3433 t2 = state->Reg[MULACCReg] & 0xffff;
3434
3435 if (t1 & (1 << 15))
3436 t1 -= 1 << 16;
3437 if (t2 & (1 << 15))
3438 t2 -= 1 << 16;
3439 t1 *= t2;
3440 t5 = t1;
3441 if (t5 & (1 << 31))
3442 t5 -= 1ULL << 32;
3443 state->Accumulator += t5;
3444 goto donext;
3445 }
3446 break;
3447
3448 default:
3449 break;
3450 }
3451 /* Drop through. */
3452
3453 case 0xe0:
3454 case 0xe4:
3455 case 0xe6:
3456 case 0xe8:
3457 case 0xea:
3458 case 0xec:
3459 case 0xee:
3460 if (BIT (4))
3461 {
3462 /* MCR. */
3463 if (DESTReg == 15)
3464 {
3465 UNDEF_MCRPC;
3466 #ifdef MODE32
3467 ARMul_MCR (state, instr, state->Reg[15] + isize);
3468 #else
3469 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
3470 ((state->Reg[15] + isize) & R15PCBITS));
3471 #endif
3472 }
3473 else
3474 ARMul_MCR (state, instr, DEST);
3475 }
3476 else
3477 /* CDP Part 1. */
3478 ARMul_CDP (state, instr);
3479 break;
3480
3481
3482 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3483 case 0xe1:
3484 case 0xe3:
3485 case 0xe5:
3486 case 0xe7:
3487 case 0xe9:
3488 case 0xeb:
3489 case 0xed:
3490 case 0xef:
3491 if (BIT (4))
3492 {
3493 /* MRC */
3494 temp = ARMul_MRC (state, instr);
3495 if (DESTReg == 15)
3496 {
3497 ASSIGNN ((temp & NBIT) != 0);
3498 ASSIGNZ ((temp & ZBIT) != 0);
3499 ASSIGNC ((temp & CBIT) != 0);
3500 ASSIGNV ((temp & VBIT) != 0);
3501 }
3502 else
3503 DEST = temp;
3504 }
3505 else
3506 /* CDP Part 2. */
3507 ARMul_CDP (state, instr);
3508 break;
3509
3510
3511 /* SWI instruction. */
3512 case 0xf0:
3513 case 0xf1:
3514 case 0xf2:
3515 case 0xf3:
3516 case 0xf4:
3517 case 0xf5:
3518 case 0xf6:
3519 case 0xf7:
3520 case 0xf8:
3521 case 0xf9:
3522 case 0xfa:
3523 case 0xfb:
3524 case 0xfc:
3525 case 0xfd:
3526 case 0xfe:
3527 case 0xff:
3528 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
3529 {
3530 /* A prefetch abort. */
3531 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
3532 ARMul_Abort (state, ARMul_PrefetchAbortV);
3533 break;
3534 }
3535
3536 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
3537 ARMul_Abort (state, ARMul_SWIV);
3538
3539 break;
3540 }
3541 }
3542
3543 #ifdef MODET
3544 donext:
3545 #endif
3546
3547 #ifdef NEED_UI_LOOP_HOOK
3548 if (ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
3549 {
3550 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
3551 ui_loop_hook (0);
3552 }
3553 #endif /* NEED_UI_LOOP_HOOK */
3554
3555 if (state->Emulate == ONCE)
3556 state->Emulate = STOP;
3557 /* If we have changed mode, allow the PC to advance before stopping. */
3558 else if (state->Emulate == CHANGEMODE)
3559 continue;
3560 else if (state->Emulate != RUN)
3561 break;
3562 }
3563 while (!stop_simulator);
3564
3565 state->decoded = decoded;
3566 state->loaded = loaded;
3567 state->pc = pc;
3568
3569 return pc;
3570 }
3571
3572 /* This routine evaluates most Data Processing register RHS's with the S
3573 bit clear. It is intended to be called from the macro DPRegRHS, which
3574 filters the common case of an unshifted register with in line code. */
3575
3576 static ARMword
3577 GetDPRegRHS (ARMul_State * state, ARMword instr)
3578 {
3579 ARMword shamt, base;
3580
3581 base = RHSReg;
3582 if (BIT (4))
3583 {
3584 /* Shift amount in a register. */
3585 UNDEF_Shift;
3586 INCPC;
3587 #ifndef MODE32
3588 if (base == 15)
3589 base = ECC | ER15INT | R15PC | EMODE;
3590 else
3591 #endif
3592 base = state->Reg[base];
3593 ARMul_Icycles (state, 1, 0L);
3594 shamt = state->Reg[BITS (8, 11)] & 0xff;
3595 switch ((int) BITS (5, 6))
3596 {
3597 case LSL:
3598 if (shamt == 0)
3599 return (base);
3600 else if (shamt >= 32)
3601 return (0);
3602 else
3603 return (base << shamt);
3604 case LSR:
3605 if (shamt == 0)
3606 return (base);
3607 else if (shamt >= 32)
3608 return (0);
3609 else
3610 return (base >> shamt);
3611 case ASR:
3612 if (shamt == 0)
3613 return (base);
3614 else if (shamt >= 32)
3615 return ((ARMword) ((long int) base >> 31L));
3616 else
3617 return ((ARMword) ((long int) base >> (int) shamt));
3618 case ROR:
3619 shamt &= 0x1f;
3620 if (shamt == 0)
3621 return (base);
3622 else
3623 return ((base << (32 - shamt)) | (base >> shamt));
3624 }
3625 }
3626 else
3627 {
3628 /* Shift amount is a constant. */
3629 #ifndef MODE32
3630 if (base == 15)
3631 base = ECC | ER15INT | R15PC | EMODE;
3632 else
3633 #endif
3634 base = state->Reg[base];
3635 shamt = BITS (7, 11);
3636 switch ((int) BITS (5, 6))
3637 {
3638 case LSL:
3639 return (base << shamt);
3640 case LSR:
3641 if (shamt == 0)
3642 return (0);
3643 else
3644 return (base >> shamt);
3645 case ASR:
3646 if (shamt == 0)
3647 return ((ARMword) ((long int) base >> 31L));
3648 else
3649 return ((ARMword) ((long int) base >> (int) shamt));
3650 case ROR:
3651 if (shamt == 0)
3652 /* It's an RRX. */
3653 return ((base >> 1) | (CFLAG << 31));
3654 else
3655 return ((base << (32 - shamt)) | (base >> shamt));
3656 }
3657 }
3658
3659 return 0;
3660 }
3661
3662 /* This routine evaluates most Logical Data Processing register RHS's
3663 with the S bit set. It is intended to be called from the macro
3664 DPSRegRHS, which filters the common case of an unshifted register
3665 with in line code. */
3666
3667 static ARMword
3668 GetDPSRegRHS (ARMul_State * state, ARMword instr)
3669 {
3670 ARMword shamt, base;
3671
3672 base = RHSReg;
3673 if (BIT (4))
3674 {
3675 /* Shift amount in a register. */
3676 UNDEF_Shift;
3677 INCPC;
3678 #ifndef MODE32
3679 if (base == 15)
3680 base = ECC | ER15INT | R15PC | EMODE;
3681 else
3682 #endif
3683 base = state->Reg[base];
3684 ARMul_Icycles (state, 1, 0L);
3685 shamt = state->Reg[BITS (8, 11)] & 0xff;
3686 switch ((int) BITS (5, 6))
3687 {
3688 case LSL:
3689 if (shamt == 0)
3690 return (base);
3691 else if (shamt == 32)
3692 {
3693 ASSIGNC (base & 1);
3694 return (0);
3695 }
3696 else if (shamt > 32)
3697 {
3698 CLEARC;
3699 return (0);
3700 }
3701 else
3702 {
3703 ASSIGNC ((base >> (32 - shamt)) & 1);
3704 return (base << shamt);
3705 }
3706 case LSR:
3707 if (shamt == 0)
3708 return (base);
3709 else if (shamt == 32)
3710 {
3711 ASSIGNC (base >> 31);
3712 return (0);
3713 }
3714 else if (shamt > 32)
3715 {
3716 CLEARC;
3717 return (0);
3718 }
3719 else
3720 {
3721 ASSIGNC ((base >> (shamt - 1)) & 1);
3722 return (base >> shamt);
3723 }
3724 case ASR:
3725 if (shamt == 0)
3726 return (base);
3727 else if (shamt >= 32)
3728 {
3729 ASSIGNC (base >> 31L);
3730 return ((ARMword) ((long int) base >> 31L));
3731 }
3732 else
3733 {
3734 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3735 return ((ARMword) ((long int) base >> (int) shamt));
3736 }
3737 case ROR:
3738 if (shamt == 0)
3739 return (base);
3740 shamt &= 0x1f;
3741 if (shamt == 0)
3742 {
3743 ASSIGNC (base >> 31);
3744 return (base);
3745 }
3746 else
3747 {
3748 ASSIGNC ((base >> (shamt - 1)) & 1);
3749 return ((base << (32 - shamt)) | (base >> shamt));
3750 }
3751 }
3752 }
3753 else
3754 {
3755 /* Shift amount is a constant. */
3756 #ifndef MODE32
3757 if (base == 15)
3758 base = ECC | ER15INT | R15PC | EMODE;
3759 else
3760 #endif
3761 base = state->Reg[base];
3762 shamt = BITS (7, 11);
3763
3764 switch ((int) BITS (5, 6))
3765 {
3766 case LSL:
3767 ASSIGNC ((base >> (32 - shamt)) & 1);
3768 return (base << shamt);
3769 case LSR:
3770 if (shamt == 0)
3771 {
3772 ASSIGNC (base >> 31);
3773 return (0);
3774 }
3775 else
3776 {
3777 ASSIGNC ((base >> (shamt - 1)) & 1);
3778 return (base >> shamt);
3779 }
3780 case ASR:
3781 if (shamt == 0)
3782 {
3783 ASSIGNC (base >> 31L);
3784 return ((ARMword) ((long int) base >> 31L));
3785 }
3786 else
3787 {
3788 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3789 return ((ARMword) ((long int) base >> (int) shamt));
3790 }
3791 case ROR:
3792 if (shamt == 0)
3793 {
3794 /* It's an RRX. */
3795 shamt = CFLAG;
3796 ASSIGNC (base & 1);
3797 return ((base >> 1) | (shamt << 31));
3798 }
3799 else
3800 {
3801 ASSIGNC ((base >> (shamt - 1)) & 1);
3802 return ((base << (32 - shamt)) | (base >> shamt));
3803 }
3804 }
3805 }
3806
3807 return 0;
3808 }
3809
3810 /* This routine handles writes to register 15 when the S bit is not set. */
3811
3812 static void
3813 WriteR15 (ARMul_State * state, ARMword src)
3814 {
3815 /* The ARM documentation states that the two least significant bits
3816 are discarded when setting PC, except in the cases handled by
3817 WriteR15Branch() below. It's probably an oversight: in THUMB
3818 mode, the second least significant bit should probably not be
3819 discarded. */
3820 #ifdef MODET
3821 if (TFLAG)
3822 src &= 0xfffffffe;
3823 else
3824 #endif
3825 src &= 0xfffffffc;
3826
3827 #ifdef MODE32
3828 state->Reg[15] = src & PCBITS;
3829 #else
3830 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
3831 ARMul_R15Altered (state);
3832 #endif
3833
3834 FLUSHPIPE;
3835 }
3836
3837 /* This routine handles writes to register 15 when the S bit is set. */
3838
3839 static void
3840 WriteSR15 (ARMul_State * state, ARMword src)
3841 {
3842 #ifdef MODE32
3843 if (state->Bank > 0)
3844 {
3845 state->Cpsr = state->Spsr[state->Bank];
3846 ARMul_CPSRAltered (state);
3847 }
3848 #ifdef MODET
3849 if (TFLAG)
3850 src &= 0xfffffffe;
3851 else
3852 #endif
3853 src &= 0xfffffffc;
3854 state->Reg[15] = src & PCBITS;
3855 #else
3856 #ifdef MODET
3857 if (TFLAG)
3858 /* ARMul_R15Altered would have to support it. */
3859 abort ();
3860 else
3861 #endif
3862 src &= 0xfffffffc;
3863
3864 if (state->Bank == USERBANK)
3865 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
3866 else
3867 state->Reg[15] = src;
3868
3869 ARMul_R15Altered (state);
3870 #endif
3871 FLUSHPIPE;
3872 }
3873
3874 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3875 will switch to Thumb mode if the least significant bit is set. */
3876
3877 static void
3878 WriteR15Branch (ARMul_State * state, ARMword src)
3879 {
3880 #ifdef MODET
3881 if (src & 1)
3882 {
3883 /* Thumb bit. */
3884 SETT;
3885 state->Reg[15] = src & 0xfffffffe;
3886 }
3887 else
3888 {
3889 CLEART;
3890 state->Reg[15] = src & 0xfffffffc;
3891 }
3892 FLUSHPIPE;
3893 #else
3894 WriteR15 (state, src);
3895 #endif
3896 }
3897
3898 /* This routine evaluates most Load and Store register RHS's. It is
3899 intended to be called from the macro LSRegRHS, which filters the
3900 common case of an unshifted register with in line code. */
3901
3902 static ARMword
3903 GetLSRegRHS (ARMul_State * state, ARMword instr)
3904 {
3905 ARMword shamt, base;
3906
3907 base = RHSReg;
3908 #ifndef MODE32
3909 if (base == 15)
3910 /* Now forbidden, but ... */
3911 base = ECC | ER15INT | R15PC | EMODE;
3912 else
3913 #endif
3914 base = state->Reg[base];
3915
3916 shamt = BITS (7, 11);
3917 switch ((int) BITS (5, 6))
3918 {
3919 case LSL:
3920 return (base << shamt);
3921 case LSR:
3922 if (shamt == 0)
3923 return (0);
3924 else
3925 return (base >> shamt);
3926 case ASR:
3927 if (shamt == 0)
3928 return ((ARMword) ((long int) base >> 31L));
3929 else
3930 return ((ARMword) ((long int) base >> (int) shamt));
3931 case ROR:
3932 if (shamt == 0)
3933 /* It's an RRX. */
3934 return ((base >> 1) | (CFLAG << 31));
3935 else
3936 return ((base << (32 - shamt)) | (base >> shamt));
3937 default:
3938 break;
3939 }
3940 return 0;
3941 }
3942
3943 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
3944
3945 static ARMword
3946 GetLS7RHS (ARMul_State * state, ARMword instr)
3947 {
3948 if (BIT (22) == 0)
3949 {
3950 /* Register. */
3951 #ifndef MODE32
3952 if (RHSReg == 15)
3953 /* Now forbidden, but ... */
3954 return ECC | ER15INT | R15PC | EMODE;
3955 #endif
3956 return state->Reg[RHSReg];
3957 }
3958
3959 /* Immediate. */
3960 return BITS (0, 3) | (BITS (8, 11) << 4);
3961 }
3962
3963 /* This function does the work of loading a word for a LDR instruction. */
3964
3965 static unsigned
3966 LoadWord (ARMul_State * state, ARMword instr, ARMword address)
3967 {
3968 ARMword dest;
3969
3970 BUSUSEDINCPCS;
3971 #ifndef MODE32
3972 if (ADDREXCEPT (address))
3973 INTERNALABORT (address);
3974 #endif
3975
3976 dest = ARMul_LoadWordN (state, address);
3977
3978 if (state->Aborted)
3979 {
3980 TAKEABORT;
3981 return state->lateabtSig;
3982 }
3983 if (address & 3)
3984 dest = ARMul_Align (state, address, dest);
3985 WRITEDESTB (dest);
3986 ARMul_Icycles (state, 1, 0L);
3987
3988 return (DESTReg != LHSReg);
3989 }
3990
3991 #ifdef MODET
3992 /* This function does the work of loading a halfword. */
3993
3994 static unsigned
3995 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
3996 int signextend)
3997 {
3998 ARMword dest;
3999
4000 BUSUSEDINCPCS;
4001 #ifndef MODE32
4002 if (ADDREXCEPT (address))
4003 INTERNALABORT (address);
4004 #endif
4005 dest = ARMul_LoadHalfWord (state, address);
4006 if (state->Aborted)
4007 {
4008 TAKEABORT;
4009 return state->lateabtSig;
4010 }
4011 UNDEF_LSRBPC;
4012 if (signextend)
4013 if (dest & 1 << (16 - 1))
4014 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
4015
4016 WRITEDEST (dest);
4017 ARMul_Icycles (state, 1, 0L);
4018 return (DESTReg != LHSReg);
4019 }
4020
4021 #endif /* MODET */
4022
4023 /* This function does the work of loading a byte for a LDRB instruction. */
4024
4025 static unsigned
4026 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
4027 {
4028 ARMword dest;
4029
4030 BUSUSEDINCPCS;
4031 #ifndef MODE32
4032 if (ADDREXCEPT (address))
4033 INTERNALABORT (address);
4034 #endif
4035 dest = ARMul_LoadByte (state, address);
4036 if (state->Aborted)
4037 {
4038 TAKEABORT;
4039 return state->lateabtSig;
4040 }
4041 UNDEF_LSRBPC;
4042 if (signextend)
4043 if (dest & 1 << (8 - 1))
4044 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
4045
4046 WRITEDEST (dest);
4047 ARMul_Icycles (state, 1, 0L);
4048
4049 return (DESTReg != LHSReg);
4050 }
4051
4052 /* This function does the work of loading two words for a LDRD instruction. */
4053
4054 static void
4055 Handle_Load_Double (ARMul_State * state, ARMword instr)
4056 {
4057 ARMword dest_reg;
4058 ARMword addr_reg;
4059 ARMword write_back = BIT (21);
4060 ARMword immediate = BIT (22);
4061 ARMword add_to_base = BIT (23);
4062 ARMword pre_indexed = BIT (24);
4063 ARMword offset;
4064 ARMword addr;
4065 ARMword sum;
4066 ARMword base;
4067 ARMword value1;
4068 ARMword value2;
4069
4070 BUSUSEDINCPCS;
4071
4072 /* If the writeback bit is set, the pre-index bit must be clear. */
4073 if (write_back && ! pre_indexed)
4074 {
4075 ARMul_UndefInstr (state, instr);
4076 return;
4077 }
4078
4079 /* Extract the base address register. */
4080 addr_reg = LHSReg;
4081
4082 /* Extract the destination register and check it. */
4083 dest_reg = DESTReg;
4084
4085 /* Destination register must be even. */
4086 if ((dest_reg & 1)
4087 /* Destination register cannot be LR. */
4088 || (dest_reg == 14))
4089 {
4090 ARMul_UndefInstr (state, instr);
4091 return;
4092 }
4093
4094 /* Compute the base address. */
4095 base = state->Reg[addr_reg];
4096
4097 /* Compute the offset. */
4098 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4099
4100 /* Compute the sum of the two. */
4101 if (add_to_base)
4102 sum = base + offset;
4103 else
4104 sum = base - offset;
4105
4106 /* If this is a pre-indexed mode use the sum. */
4107 if (pre_indexed)
4108 addr = sum;
4109 else
4110 addr = base;
4111
4112 /* The address must be aligned on a 8 byte boundary. */
4113 if (addr & 0x7)
4114 {
4115 #ifdef ABORTS
4116 ARMul_DATAABORT (addr);
4117 #else
4118 ARMul_UndefInstr (state, instr);
4119 #endif
4120 return;
4121 }
4122
4123 /* For pre indexed or post indexed addressing modes,
4124 check that the destination registers do not overlap
4125 the address registers. */
4126 if ((! pre_indexed || write_back)
4127 && ( addr_reg == dest_reg
4128 || addr_reg == dest_reg + 1))
4129 {
4130 ARMul_UndefInstr (state, instr);
4131 return;
4132 }
4133
4134 /* Load the words. */
4135 value1 = ARMul_LoadWordN (state, addr);
4136 value2 = ARMul_LoadWordN (state, addr + 4);
4137
4138 /* Check for data aborts. */
4139 if (state->Aborted)
4140 {
4141 TAKEABORT;
4142 return;
4143 }
4144
4145 ARMul_Icycles (state, 2, 0L);
4146
4147 /* Store the values. */
4148 state->Reg[dest_reg] = value1;
4149 state->Reg[dest_reg + 1] = value2;
4150
4151 /* Do the post addressing and writeback. */
4152 if (! pre_indexed)
4153 addr = sum;
4154
4155 if (! pre_indexed || write_back)
4156 state->Reg[addr_reg] = addr;
4157 }
4158
4159 /* This function does the work of storing two words for a STRD instruction. */
4160
4161 static void
4162 Handle_Store_Double (ARMul_State * state, ARMword instr)
4163 {
4164 ARMword src_reg;
4165 ARMword addr_reg;
4166 ARMword write_back = BIT (21);
4167 ARMword immediate = BIT (22);
4168 ARMword add_to_base = BIT (23);
4169 ARMword pre_indexed = BIT (24);
4170 ARMword offset;
4171 ARMword addr;
4172 ARMword sum;
4173 ARMword base;
4174
4175 BUSUSEDINCPCS;
4176
4177 /* If the writeback bit is set, the pre-index bit must be clear. */
4178 if (write_back && ! pre_indexed)
4179 {
4180 ARMul_UndefInstr (state, instr);
4181 return;
4182 }
4183
4184 /* Extract the base address register. */
4185 addr_reg = LHSReg;
4186
4187 /* Base register cannot be PC. */
4188 if (addr_reg == 15)
4189 {
4190 ARMul_UndefInstr (state, instr);
4191 return;
4192 }
4193
4194 /* Extract the source register. */
4195 src_reg = DESTReg;
4196
4197 /* Source register must be even. */
4198 if (src_reg & 1)
4199 {
4200 ARMul_UndefInstr (state, instr);
4201 return;
4202 }
4203
4204 /* Compute the base address. */
4205 base = state->Reg[addr_reg];
4206
4207 /* Compute the offset. */
4208 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4209
4210 /* Compute the sum of the two. */
4211 if (add_to_base)
4212 sum = base + offset;
4213 else
4214 sum = base - offset;
4215
4216 /* If this is a pre-indexed mode use the sum. */
4217 if (pre_indexed)
4218 addr = sum;
4219 else
4220 addr = base;
4221
4222 /* The address must be aligned on a 8 byte boundary. */
4223 if (addr & 0x7)
4224 {
4225 #ifdef ABORTS
4226 ARMul_DATAABORT (addr);
4227 #else
4228 ARMul_UndefInstr (state, instr);
4229 #endif
4230 return;
4231 }
4232
4233 /* For pre indexed or post indexed addressing modes,
4234 check that the destination registers do not overlap
4235 the address registers. */
4236 if ((! pre_indexed || write_back)
4237 && ( addr_reg == src_reg
4238 || addr_reg == src_reg + 1))
4239 {
4240 ARMul_UndefInstr (state, instr);
4241 return;
4242 }
4243
4244 /* Load the words. */
4245 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
4246 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
4247
4248 if (state->Aborted)
4249 {
4250 TAKEABORT;
4251 return;
4252 }
4253
4254 /* Do the post addressing and writeback. */
4255 if (! pre_indexed)
4256 addr = sum;
4257
4258 if (! pre_indexed || write_back)
4259 state->Reg[addr_reg] = addr;
4260 }
4261
4262 /* This function does the work of storing a word from a STR instruction. */
4263
4264 static unsigned
4265 StoreWord (ARMul_State * state, ARMword instr, ARMword address)
4266 {
4267 BUSUSEDINCPCN;
4268 #ifndef MODE32
4269 if (DESTReg == 15)
4270 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4271 #endif
4272 #ifdef MODE32
4273 ARMul_StoreWordN (state, address, DEST);
4274 #else
4275 if (VECTORACCESS (address) || ADDREXCEPT (address))
4276 {
4277 INTERNALABORT (address);
4278 (void) ARMul_LoadWordN (state, address);
4279 }
4280 else
4281 ARMul_StoreWordN (state, address, DEST);
4282 #endif
4283 if (state->Aborted)
4284 {
4285 TAKEABORT;
4286 return state->lateabtSig;
4287 }
4288 return TRUE;
4289 }
4290
4291 #ifdef MODET
4292 /* This function does the work of storing a byte for a STRH instruction. */
4293
4294 static unsigned
4295 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
4296 {
4297 BUSUSEDINCPCN;
4298
4299 #ifndef MODE32
4300 if (DESTReg == 15)
4301 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4302 #endif
4303
4304 #ifdef MODE32
4305 ARMul_StoreHalfWord (state, address, DEST);
4306 #else
4307 if (VECTORACCESS (address) || ADDREXCEPT (address))
4308 {
4309 INTERNALABORT (address);
4310 (void) ARMul_LoadHalfWord (state, address);
4311 }
4312 else
4313 ARMul_StoreHalfWord (state, address, DEST);
4314 #endif
4315
4316 if (state->Aborted)
4317 {
4318 TAKEABORT;
4319 return state->lateabtSig;
4320 }
4321 return TRUE;
4322 }
4323
4324 #endif /* MODET */
4325
4326 /* This function does the work of storing a byte for a STRB instruction. */
4327
4328 static unsigned
4329 StoreByte (ARMul_State * state, ARMword instr, ARMword address)
4330 {
4331 BUSUSEDINCPCN;
4332 #ifndef MODE32
4333 if (DESTReg == 15)
4334 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4335 #endif
4336 #ifdef MODE32
4337 ARMul_StoreByte (state, address, DEST);
4338 #else
4339 if (VECTORACCESS (address) || ADDREXCEPT (address))
4340 {
4341 INTERNALABORT (address);
4342 (void) ARMul_LoadByte (state, address);
4343 }
4344 else
4345 ARMul_StoreByte (state, address, DEST);
4346 #endif
4347 if (state->Aborted)
4348 {
4349 TAKEABORT;
4350 return state->lateabtSig;
4351 }
4352 UNDEF_LSRBPC;
4353 return TRUE;
4354 }
4355
4356 /* This function does the work of loading the registers listed in an LDM
4357 instruction, when the S bit is clear. The code here is always increment
4358 after, it's up to the caller to get the input address correct and to
4359 handle base register modification. */
4360
4361 static void
4362 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
4363 {
4364 ARMword dest, temp;
4365
4366 UNDEF_LSMNoRegs;
4367 UNDEF_LSMPCBase;
4368 UNDEF_LSMBaseInListWb;
4369 BUSUSEDINCPCS;
4370 #ifndef MODE32
4371 if (ADDREXCEPT (address))
4372 INTERNALABORT (address);
4373 #endif
4374 if (BIT (21) && LHSReg != 15)
4375 LSBase = WBBase;
4376
4377 /* N cycle first. */
4378 for (temp = 0; !BIT (temp); temp++)
4379 ;
4380
4381 dest = ARMul_LoadWordN (state, address);
4382
4383 if (!state->abortSig && !state->Aborted)
4384 state->Reg[temp++] = dest;
4385 else if (!state->Aborted)
4386 {
4387 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4388 state->Aborted = ARMul_DataAbortV;
4389 }
4390
4391 /* S cycles from here on. */
4392 for (; temp < 16; temp ++)
4393 if (BIT (temp))
4394 {
4395 /* Load this register. */
4396 address += 4;
4397 dest = ARMul_LoadWordS (state, address);
4398
4399 if (!state->abortSig && !state->Aborted)
4400 state->Reg[temp] = dest;
4401 else if (!state->Aborted)
4402 {
4403 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4404 state->Aborted = ARMul_DataAbortV;
4405 }
4406 }
4407
4408 if (BIT (15) && !state->Aborted)
4409 /* PC is in the reg list. */
4410 WriteR15Branch (state, PC);
4411
4412 /* To write back the final register. */
4413 ARMul_Icycles (state, 1, 0L);
4414
4415 if (state->Aborted)
4416 {
4417 if (BIT (21) && LHSReg != 15)
4418 LSBase = WBBase;
4419 TAKEABORT;
4420 }
4421 }
4422
4423 /* This function does the work of loading the registers listed in an LDM
4424 instruction, when the S bit is set. The code here is always increment
4425 after, it's up to the caller to get the input address correct and to
4426 handle base register modification. */
4427
4428 static void
4429 LoadSMult (ARMul_State * state,
4430 ARMword instr,
4431 ARMword address,
4432 ARMword WBBase)
4433 {
4434 ARMword dest, temp;
4435
4436 UNDEF_LSMNoRegs;
4437 UNDEF_LSMPCBase;
4438 UNDEF_LSMBaseInListWb;
4439
4440 BUSUSEDINCPCS;
4441
4442 #ifndef MODE32
4443 if (ADDREXCEPT (address))
4444 INTERNALABORT (address);
4445 #endif
4446
4447 if (BIT (21) && LHSReg != 15)
4448 LSBase = WBBase;
4449
4450 if (!BIT (15) && state->Bank != USERBANK)
4451 {
4452 /* Temporary reg bank switch. */
4453 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4454 UNDEF_LSMUserBankWb;
4455 }
4456
4457 /* N cycle first. */
4458 for (temp = 0; !BIT (temp); temp ++)
4459 ;
4460
4461 dest = ARMul_LoadWordN (state, address);
4462
4463 if (!state->abortSig)
4464 state->Reg[temp++] = dest;
4465 else if (!state->Aborted)
4466 {
4467 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4468 state->Aborted = ARMul_DataAbortV;
4469 }
4470
4471 /* S cycles from here on. */
4472 for (; temp < 16; temp++)
4473 if (BIT (temp))
4474 {
4475 /* Load this register. */
4476 address += 4;
4477 dest = ARMul_LoadWordS (state, address);
4478
4479 if (!state->abortSig && !state->Aborted)
4480 state->Reg[temp] = dest;
4481 else if (!state->Aborted)
4482 {
4483 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4484 state->Aborted = ARMul_DataAbortV;
4485 }
4486 }
4487
4488 if (BIT (15) && !state->Aborted)
4489 {
4490 /* PC is in the reg list. */
4491 #ifdef MODE32
4492 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4493 {
4494 state->Cpsr = GETSPSR (state->Bank);
4495 ARMul_CPSRAltered (state);
4496 }
4497
4498 WriteR15 (state, PC);
4499 #else
4500 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
4501 {
4502 /* Protect bits in user mode. */
4503 ASSIGNN ((state->Reg[15] & NBIT) != 0);
4504 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
4505 ASSIGNC ((state->Reg[15] & CBIT) != 0);
4506 ASSIGNV ((state->Reg[15] & VBIT) != 0);
4507 }
4508 else
4509 ARMul_R15Altered (state);
4510
4511 FLUSHPIPE;
4512 #endif
4513 }
4514
4515 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
4516 /* Restore the correct bank. */
4517 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4518
4519 /* To write back the final register. */
4520 ARMul_Icycles (state, 1, 0L);
4521
4522 if (state->Aborted)
4523 {
4524 if (BIT (21) && LHSReg != 15)
4525 LSBase = WBBase;
4526
4527 TAKEABORT;
4528 }
4529 }
4530
4531 /* This function does the work of storing the registers listed in an STM
4532 instruction, when the S bit is clear. The code here is always increment
4533 after, it's up to the caller to get the input address correct and to
4534 handle base register modification. */
4535
4536 static void
4537 StoreMult (ARMul_State * state,
4538 ARMword instr,
4539 ARMword address,
4540 ARMword WBBase)
4541 {
4542 ARMword temp;
4543
4544 UNDEF_LSMNoRegs;
4545 UNDEF_LSMPCBase;
4546 UNDEF_LSMBaseInListWb;
4547
4548 if (!TFLAG)
4549 /* N-cycle, increment the PC and update the NextInstr state. */
4550 BUSUSEDINCPCN;
4551
4552 #ifndef MODE32
4553 if (VECTORACCESS (address) || ADDREXCEPT (address))
4554 INTERNALABORT (address);
4555
4556 if (BIT (15))
4557 PATCHR15;
4558 #endif
4559
4560 /* N cycle first. */
4561 for (temp = 0; !BIT (temp); temp ++)
4562 ;
4563
4564 #ifdef MODE32
4565 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4566 #else
4567 if (state->Aborted)
4568 {
4569 (void) ARMul_LoadWordN (state, address);
4570
4571 /* Fake the Stores as Loads. */
4572 for (; temp < 16; temp++)
4573 if (BIT (temp))
4574 {
4575 /* Save this register. */
4576 address += 4;
4577 (void) ARMul_LoadWordS (state, address);
4578 }
4579
4580 if (BIT (21) && LHSReg != 15)
4581 LSBase = WBBase;
4582 TAKEABORT;
4583 return;
4584 }
4585 else
4586 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4587 #endif
4588
4589 if (state->abortSig && !state->Aborted)
4590 {
4591 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4592 state->Aborted = ARMul_DataAbortV;
4593 }
4594
4595 if (BIT (21) && LHSReg != 15)
4596 LSBase = WBBase;
4597
4598 /* S cycles from here on. */
4599 for (; temp < 16; temp ++)
4600 if (BIT (temp))
4601 {
4602 /* Save this register. */
4603 address += 4;
4604
4605 ARMul_StoreWordS (state, address, state->Reg[temp]);
4606
4607 if (state->abortSig && !state->Aborted)
4608 {
4609 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4610 state->Aborted = ARMul_DataAbortV;
4611 }
4612 }
4613
4614 if (state->Aborted)
4615 TAKEABORT;
4616 }
4617
4618 /* This function does the work of storing the registers listed in an STM
4619 instruction when the S bit is set. The code here is always increment
4620 after, it's up to the caller to get the input address correct and to
4621 handle base register modification. */
4622
4623 static void
4624 StoreSMult (ARMul_State * state,
4625 ARMword instr,
4626 ARMword address,
4627 ARMword WBBase)
4628 {
4629 ARMword temp;
4630
4631 UNDEF_LSMNoRegs;
4632 UNDEF_LSMPCBase;
4633 UNDEF_LSMBaseInListWb;
4634
4635 BUSUSEDINCPCN;
4636
4637 #ifndef MODE32
4638 if (VECTORACCESS (address) || ADDREXCEPT (address))
4639 INTERNALABORT (address);
4640
4641 if (BIT (15))
4642 PATCHR15;
4643 #endif
4644
4645 if (state->Bank != USERBANK)
4646 {
4647 /* Force User Bank. */
4648 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4649 UNDEF_LSMUserBankWb;
4650 }
4651
4652 for (temp = 0; !BIT (temp); temp++)
4653 ; /* N cycle first. */
4654
4655 #ifdef MODE32
4656 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4657 #else
4658 if (state->Aborted)
4659 {
4660 (void) ARMul_LoadWordN (state, address);
4661
4662 for (; temp < 16; temp++)
4663 /* Fake the Stores as Loads. */
4664 if (BIT (temp))
4665 {
4666 /* Save this register. */
4667 address += 4;
4668
4669 (void) ARMul_LoadWordS (state, address);
4670 }
4671
4672 if (BIT (21) && LHSReg != 15)
4673 LSBase = WBBase;
4674
4675 TAKEABORT;
4676 return;
4677 }
4678 else
4679 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4680 #endif
4681
4682 if (state->abortSig && !state->Aborted)
4683 {
4684 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4685 state->Aborted = ARMul_DataAbortV;
4686 }
4687
4688 /* S cycles from here on. */
4689 for (; temp < 16; temp++)
4690 if (BIT (temp))
4691 {
4692 /* Save this register. */
4693 address += 4;
4694
4695 ARMul_StoreWordS (state, address, state->Reg[temp]);
4696
4697 if (state->abortSig && !state->Aborted)
4698 {
4699 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4700 state->Aborted = ARMul_DataAbortV;
4701 }
4702 }
4703
4704 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4705 /* Restore the correct bank. */
4706 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4707
4708 if (BIT (21) && LHSReg != 15)
4709 LSBase = WBBase;
4710
4711 if (state->Aborted)
4712 TAKEABORT;
4713 }
4714
4715 /* This function does the work of adding two 32bit values
4716 together, and calculating if a carry has occurred. */
4717
4718 static ARMword
4719 Add32 (ARMword a1, ARMword a2, int *carry)
4720 {
4721 ARMword result = (a1 + a2);
4722 unsigned int uresult = (unsigned int) result;
4723 unsigned int ua1 = (unsigned int) a1;
4724
4725 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4726 or (result > RdLo) then we have no carry. */
4727 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
4728 *carry = 1;
4729 else
4730 *carry = 0;
4731
4732 return result;
4733 }
4734
4735 /* This function does the work of multiplying
4736 two 32bit values to give a 64bit result. */
4737
4738 static unsigned
4739 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
4740 {
4741 /* Operand register numbers. */
4742 int nRdHi, nRdLo, nRs, nRm;
4743 ARMword RdHi = 0, RdLo = 0, Rm;
4744 /* Cycle count. */
4745 int scount;
4746
4747 nRdHi = BITS (16, 19);
4748 nRdLo = BITS (12, 15);
4749 nRs = BITS (8, 11);
4750 nRm = BITS (0, 3);
4751
4752 /* Needed to calculate the cycle count. */
4753 Rm = state->Reg[nRm];
4754
4755 /* Check for illegal operand combinations first. */
4756 if ( nRdHi != 15
4757 && nRdLo != 15
4758 && nRs != 15
4759 && nRm != 15
4760 && nRdHi != nRdLo
4761 && nRdHi != nRm
4762 && nRdLo != nRm)
4763 {
4764 /* Intermediate results. */
4765 ARMword lo, mid1, mid2, hi;
4766 int carry;
4767 ARMword Rs = state->Reg[nRs];
4768 int sign = 0;
4769
4770 if (msigned)
4771 {
4772 /* Compute sign of result and adjust operands if necessary. */
4773 sign = (Rm ^ Rs) & 0x80000000;
4774
4775 if (((signed long) Rm) < 0)
4776 Rm = -Rm;
4777
4778 if (((signed long) Rs) < 0)
4779 Rs = -Rs;
4780 }
4781
4782 /* We can split the 32x32 into four 16x16 operations. This
4783 ensures that we do not lose precision on 32bit only hosts. */
4784 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
4785 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4786 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
4787 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4788
4789 /* We now need to add all of these results together, taking
4790 care to propogate the carries from the additions. */
4791 RdLo = Add32 (lo, (mid1 << 16), &carry);
4792 RdHi = carry;
4793 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
4794 RdHi +=
4795 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
4796
4797 if (sign)
4798 {
4799 /* Negate result if necessary. */
4800 RdLo = ~RdLo;
4801 RdHi = ~RdHi;
4802 if (RdLo == 0xFFFFFFFF)
4803 {
4804 RdLo = 0;
4805 RdHi += 1;
4806 }
4807 else
4808 RdLo += 1;
4809 }
4810
4811 state->Reg[nRdLo] = RdLo;
4812 state->Reg[nRdHi] = RdHi;
4813 }
4814 else
4815 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4816
4817 if (scc)
4818 /* Ensure that both RdHi and RdLo are used to compute Z,
4819 but don't let RdLo's sign bit make it to N. */
4820 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4821
4822 /* The cycle count depends on whether the instruction is a signed or
4823 unsigned multiply, and what bits are clear in the multiplier. */
4824 if (msigned && (Rm & ((unsigned) 1 << 31)))
4825 /* Invert the bits to make the check against zero. */
4826 Rm = ~Rm;
4827
4828 if ((Rm & 0xFFFFFF00) == 0)
4829 scount = 1;
4830 else if ((Rm & 0xFFFF0000) == 0)
4831 scount = 2;
4832 else if ((Rm & 0xFF000000) == 0)
4833 scount = 3;
4834 else
4835 scount = 4;
4836
4837 return 2 + scount;
4838 }
4839
4840 /* This function does the work of multiplying two 32bit
4841 values and adding a 64bit value to give a 64bit result. */
4842
4843 static unsigned
4844 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
4845 {
4846 unsigned scount;
4847 ARMword RdLo, RdHi;
4848 int nRdHi, nRdLo;
4849 int carry = 0;
4850
4851 nRdHi = BITS (16, 19);
4852 nRdLo = BITS (12, 15);
4853
4854 RdHi = state->Reg[nRdHi];
4855 RdLo = state->Reg[nRdLo];
4856
4857 scount = Multiply64 (state, instr, msigned, LDEFAULT);
4858
4859 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
4860 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
4861
4862 state->Reg[nRdLo] = RdLo;
4863 state->Reg[nRdHi] = RdHi;
4864
4865 if (scc)
4866 /* Ensure that both RdHi and RdLo are used to compute Z,
4867 but don't let RdLo's sign bit make it to N. */
4868 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4869
4870 /* Extra cycle for addition. */
4871 return scount + 1;
4872 }
This page took 0.135111 seconds and 5 git commands to generate.