Add support for target specific command line switches to old-style simualtors.
[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 {
3370 /* XScale MIA instruction. Signed multiplication of two 32 bit
3371 values and addition to 40 bit accumulator. */
3372 long long Rm = state->Reg[MULLHSReg];
3373 long long Rs = state->Reg[MULACCReg];
3374
3375 if (Rm & (1 << 31))
3376 Rm -= 1ULL << 32;
3377 if (Rs & (1 << 31))
3378 Rs -= 1ULL << 32;
3379 state->Accumulator += Rm * Rs;
3380 }
3381 goto donext;
3382
3383 case 0x2:
3384 {
3385 /* XScale MIAPH instruction. */
3386 ARMword t1 = state->Reg[MULLHSReg] >> 16;
3387 ARMword t2 = state->Reg[MULACCReg] >> 16;
3388 ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
3389 ARMword t4 = state->Reg[MULACCReg] & 0xffff;
3390 long long t5;
3391
3392 if (t1 & (1 << 15))
3393 t1 -= 1 << 16;
3394 if (t2 & (1 << 15))
3395 t2 -= 1 << 16;
3396 if (t3 & (1 << 15))
3397 t3 -= 1 << 16;
3398 if (t4 & (1 << 15))
3399 t4 -= 1 << 16;
3400 t1 *= t2;
3401 t5 = t1;
3402 if (t5 & (1 << 31))
3403 t5 -= 1ULL << 32;
3404 state->Accumulator += t5;
3405 t3 *= t4;
3406 t5 = t3;
3407 if (t5 & (1 << 31))
3408 t5 -= 1ULL << 32;
3409 state->Accumulator += t5;
3410 }
3411 goto donext;
3412
3413 case 0x3:
3414 {
3415 /* XScale MIAxy instruction. */
3416 ARMword t1;
3417 ARMword t2;
3418 long long t5;
3419
3420 if (BIT (17))
3421 t1 = state->Reg[MULLHSReg] >> 16;
3422 else
3423 t1 = state->Reg[MULLHSReg] & 0xffff;
3424
3425 if (BIT (16))
3426 t2 = state->Reg[MULACCReg] >> 16;
3427 else
3428 t2 = state->Reg[MULACCReg] & 0xffff;
3429
3430 if (t1 & (1 << 15))
3431 t1 -= 1 << 16;
3432 if (t2 & (1 << 15))
3433 t2 -= 1 << 16;
3434 t1 *= t2;
3435 t5 = t1;
3436 if (t5 & (1 << 31))
3437 t5 -= 1ULL << 32;
3438 state->Accumulator += t5;
3439 }
3440 goto donext;
3441
3442 default:
3443 break;
3444 }
3445 /* Drop through. */
3446
3447 case 0xe0:
3448 case 0xe4:
3449 case 0xe6:
3450 case 0xe8:
3451 case 0xea:
3452 case 0xec:
3453 case 0xee:
3454 if (BIT (4))
3455 {
3456 /* MCR. */
3457 if (DESTReg == 15)
3458 {
3459 UNDEF_MCRPC;
3460 #ifdef MODE32
3461 ARMul_MCR (state, instr, state->Reg[15] + isize);
3462 #else
3463 ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
3464 ((state->Reg[15] + isize) & R15PCBITS));
3465 #endif
3466 }
3467 else
3468 ARMul_MCR (state, instr, DEST);
3469 }
3470 else
3471 /* CDP Part 1. */
3472 ARMul_CDP (state, instr);
3473 break;
3474
3475
3476 /* Co-Processor Register Transfers (MRC) and Data Ops. */
3477 case 0xe1:
3478 case 0xe3:
3479 case 0xe5:
3480 case 0xe7:
3481 case 0xe9:
3482 case 0xeb:
3483 case 0xed:
3484 case 0xef:
3485 if (BIT (4))
3486 {
3487 /* MRC */
3488 temp = ARMul_MRC (state, instr);
3489 if (DESTReg == 15)
3490 {
3491 ASSIGNN ((temp & NBIT) != 0);
3492 ASSIGNZ ((temp & ZBIT) != 0);
3493 ASSIGNC ((temp & CBIT) != 0);
3494 ASSIGNV ((temp & VBIT) != 0);
3495 }
3496 else
3497 DEST = temp;
3498 }
3499 else
3500 /* CDP Part 2. */
3501 ARMul_CDP (state, instr);
3502 break;
3503
3504
3505 /* SWI instruction. */
3506 case 0xf0:
3507 case 0xf1:
3508 case 0xf2:
3509 case 0xf3:
3510 case 0xf4:
3511 case 0xf5:
3512 case 0xf6:
3513 case 0xf7:
3514 case 0xf8:
3515 case 0xf9:
3516 case 0xfa:
3517 case 0xfb:
3518 case 0xfc:
3519 case 0xfd:
3520 case 0xfe:
3521 case 0xff:
3522 if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
3523 {
3524 /* A prefetch abort. */
3525 XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
3526 ARMul_Abort (state, ARMul_PrefetchAbortV);
3527 break;
3528 }
3529
3530 if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
3531 ARMul_Abort (state, ARMul_SWIV);
3532
3533 break;
3534 }
3535 }
3536
3537 #ifdef MODET
3538 donext:
3539 #endif
3540
3541 #ifdef NEED_UI_LOOP_HOOK
3542 if (ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
3543 {
3544 ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
3545 ui_loop_hook (0);
3546 }
3547 #endif /* NEED_UI_LOOP_HOOK */
3548
3549 if (state->Emulate == ONCE)
3550 state->Emulate = STOP;
3551 /* If we have changed mode, allow the PC to advance before stopping. */
3552 else if (state->Emulate == CHANGEMODE)
3553 continue;
3554 else if (state->Emulate != RUN)
3555 break;
3556 }
3557 while (!stop_simulator);
3558
3559 state->decoded = decoded;
3560 state->loaded = loaded;
3561 state->pc = pc;
3562
3563 return pc;
3564 }
3565
3566 /* This routine evaluates most Data Processing register RHS's with the S
3567 bit clear. It is intended to be called from the macro DPRegRHS, which
3568 filters the common case of an unshifted register with in line code. */
3569
3570 static ARMword
3571 GetDPRegRHS (ARMul_State * state, ARMword instr)
3572 {
3573 ARMword shamt, base;
3574
3575 base = RHSReg;
3576 if (BIT (4))
3577 {
3578 /* Shift amount in a register. */
3579 UNDEF_Shift;
3580 INCPC;
3581 #ifndef MODE32
3582 if (base == 15)
3583 base = ECC | ER15INT | R15PC | EMODE;
3584 else
3585 #endif
3586 base = state->Reg[base];
3587 ARMul_Icycles (state, 1, 0L);
3588 shamt = state->Reg[BITS (8, 11)] & 0xff;
3589 switch ((int) BITS (5, 6))
3590 {
3591 case LSL:
3592 if (shamt == 0)
3593 return (base);
3594 else if (shamt >= 32)
3595 return (0);
3596 else
3597 return (base << shamt);
3598 case LSR:
3599 if (shamt == 0)
3600 return (base);
3601 else if (shamt >= 32)
3602 return (0);
3603 else
3604 return (base >> shamt);
3605 case ASR:
3606 if (shamt == 0)
3607 return (base);
3608 else if (shamt >= 32)
3609 return ((ARMword) ((long int) base >> 31L));
3610 else
3611 return ((ARMword) ((long int) base >> (int) shamt));
3612 case ROR:
3613 shamt &= 0x1f;
3614 if (shamt == 0)
3615 return (base);
3616 else
3617 return ((base << (32 - shamt)) | (base >> shamt));
3618 }
3619 }
3620 else
3621 {
3622 /* Shift amount is a constant. */
3623 #ifndef MODE32
3624 if (base == 15)
3625 base = ECC | ER15INT | R15PC | EMODE;
3626 else
3627 #endif
3628 base = state->Reg[base];
3629 shamt = BITS (7, 11);
3630 switch ((int) BITS (5, 6))
3631 {
3632 case LSL:
3633 return (base << shamt);
3634 case LSR:
3635 if (shamt == 0)
3636 return (0);
3637 else
3638 return (base >> shamt);
3639 case ASR:
3640 if (shamt == 0)
3641 return ((ARMword) ((long int) base >> 31L));
3642 else
3643 return ((ARMword) ((long int) base >> (int) shamt));
3644 case ROR:
3645 if (shamt == 0)
3646 /* It's an RRX. */
3647 return ((base >> 1) | (CFLAG << 31));
3648 else
3649 return ((base << (32 - shamt)) | (base >> shamt));
3650 }
3651 }
3652
3653 return 0;
3654 }
3655
3656 /* This routine evaluates most Logical Data Processing register RHS's
3657 with the S bit set. It is intended to be called from the macro
3658 DPSRegRHS, which filters the common case of an unshifted register
3659 with in line code. */
3660
3661 static ARMword
3662 GetDPSRegRHS (ARMul_State * state, ARMword instr)
3663 {
3664 ARMword shamt, base;
3665
3666 base = RHSReg;
3667 if (BIT (4))
3668 {
3669 /* Shift amount in a register. */
3670 UNDEF_Shift;
3671 INCPC;
3672 #ifndef MODE32
3673 if (base == 15)
3674 base = ECC | ER15INT | R15PC | EMODE;
3675 else
3676 #endif
3677 base = state->Reg[base];
3678 ARMul_Icycles (state, 1, 0L);
3679 shamt = state->Reg[BITS (8, 11)] & 0xff;
3680 switch ((int) BITS (5, 6))
3681 {
3682 case LSL:
3683 if (shamt == 0)
3684 return (base);
3685 else if (shamt == 32)
3686 {
3687 ASSIGNC (base & 1);
3688 return (0);
3689 }
3690 else if (shamt > 32)
3691 {
3692 CLEARC;
3693 return (0);
3694 }
3695 else
3696 {
3697 ASSIGNC ((base >> (32 - shamt)) & 1);
3698 return (base << shamt);
3699 }
3700 case LSR:
3701 if (shamt == 0)
3702 return (base);
3703 else if (shamt == 32)
3704 {
3705 ASSIGNC (base >> 31);
3706 return (0);
3707 }
3708 else if (shamt > 32)
3709 {
3710 CLEARC;
3711 return (0);
3712 }
3713 else
3714 {
3715 ASSIGNC ((base >> (shamt - 1)) & 1);
3716 return (base >> shamt);
3717 }
3718 case ASR:
3719 if (shamt == 0)
3720 return (base);
3721 else if (shamt >= 32)
3722 {
3723 ASSIGNC (base >> 31L);
3724 return ((ARMword) ((long int) base >> 31L));
3725 }
3726 else
3727 {
3728 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3729 return ((ARMword) ((long int) base >> (int) shamt));
3730 }
3731 case ROR:
3732 if (shamt == 0)
3733 return (base);
3734 shamt &= 0x1f;
3735 if (shamt == 0)
3736 {
3737 ASSIGNC (base >> 31);
3738 return (base);
3739 }
3740 else
3741 {
3742 ASSIGNC ((base >> (shamt - 1)) & 1);
3743 return ((base << (32 - shamt)) | (base >> shamt));
3744 }
3745 }
3746 }
3747 else
3748 {
3749 /* Shift amount is a constant. */
3750 #ifndef MODE32
3751 if (base == 15)
3752 base = ECC | ER15INT | R15PC | EMODE;
3753 else
3754 #endif
3755 base = state->Reg[base];
3756 shamt = BITS (7, 11);
3757
3758 switch ((int) BITS (5, 6))
3759 {
3760 case LSL:
3761 ASSIGNC ((base >> (32 - shamt)) & 1);
3762 return (base << shamt);
3763 case LSR:
3764 if (shamt == 0)
3765 {
3766 ASSIGNC (base >> 31);
3767 return (0);
3768 }
3769 else
3770 {
3771 ASSIGNC ((base >> (shamt - 1)) & 1);
3772 return (base >> shamt);
3773 }
3774 case ASR:
3775 if (shamt == 0)
3776 {
3777 ASSIGNC (base >> 31L);
3778 return ((ARMword) ((long int) base >> 31L));
3779 }
3780 else
3781 {
3782 ASSIGNC ((ARMword) ((long int) base >> (int) (shamt - 1)) & 1);
3783 return ((ARMword) ((long int) base >> (int) shamt));
3784 }
3785 case ROR:
3786 if (shamt == 0)
3787 {
3788 /* It's an RRX. */
3789 shamt = CFLAG;
3790 ASSIGNC (base & 1);
3791 return ((base >> 1) | (shamt << 31));
3792 }
3793 else
3794 {
3795 ASSIGNC ((base >> (shamt - 1)) & 1);
3796 return ((base << (32 - shamt)) | (base >> shamt));
3797 }
3798 }
3799 }
3800
3801 return 0;
3802 }
3803
3804 /* This routine handles writes to register 15 when the S bit is not set. */
3805
3806 static void
3807 WriteR15 (ARMul_State * state, ARMword src)
3808 {
3809 /* The ARM documentation states that the two least significant bits
3810 are discarded when setting PC, except in the cases handled by
3811 WriteR15Branch() below. It's probably an oversight: in THUMB
3812 mode, the second least significant bit should probably not be
3813 discarded. */
3814 #ifdef MODET
3815 if (TFLAG)
3816 src &= 0xfffffffe;
3817 else
3818 #endif
3819 src &= 0xfffffffc;
3820
3821 #ifdef MODE32
3822 state->Reg[15] = src & PCBITS;
3823 #else
3824 state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
3825 ARMul_R15Altered (state);
3826 #endif
3827
3828 FLUSHPIPE;
3829 }
3830
3831 /* This routine handles writes to register 15 when the S bit is set. */
3832
3833 static void
3834 WriteSR15 (ARMul_State * state, ARMword src)
3835 {
3836 #ifdef MODE32
3837 if (state->Bank > 0)
3838 {
3839 state->Cpsr = state->Spsr[state->Bank];
3840 ARMul_CPSRAltered (state);
3841 }
3842 #ifdef MODET
3843 if (TFLAG)
3844 src &= 0xfffffffe;
3845 else
3846 #endif
3847 src &= 0xfffffffc;
3848 state->Reg[15] = src & PCBITS;
3849 #else
3850 #ifdef MODET
3851 if (TFLAG)
3852 /* ARMul_R15Altered would have to support it. */
3853 abort ();
3854 else
3855 #endif
3856 src &= 0xfffffffc;
3857
3858 if (state->Bank == USERBANK)
3859 state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
3860 else
3861 state->Reg[15] = src;
3862
3863 ARMul_R15Altered (state);
3864 #endif
3865 FLUSHPIPE;
3866 }
3867
3868 /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
3869 will switch to Thumb mode if the least significant bit is set. */
3870
3871 static void
3872 WriteR15Branch (ARMul_State * state, ARMword src)
3873 {
3874 #ifdef MODET
3875 if (src & 1)
3876 {
3877 /* Thumb bit. */
3878 SETT;
3879 state->Reg[15] = src & 0xfffffffe;
3880 }
3881 else
3882 {
3883 CLEART;
3884 state->Reg[15] = src & 0xfffffffc;
3885 }
3886 FLUSHPIPE;
3887 #else
3888 WriteR15 (state, src);
3889 #endif
3890 }
3891
3892 /* This routine evaluates most Load and Store register RHS's. It is
3893 intended to be called from the macro LSRegRHS, which filters the
3894 common case of an unshifted register with in line code. */
3895
3896 static ARMword
3897 GetLSRegRHS (ARMul_State * state, ARMword instr)
3898 {
3899 ARMword shamt, base;
3900
3901 base = RHSReg;
3902 #ifndef MODE32
3903 if (base == 15)
3904 /* Now forbidden, but ... */
3905 base = ECC | ER15INT | R15PC | EMODE;
3906 else
3907 #endif
3908 base = state->Reg[base];
3909
3910 shamt = BITS (7, 11);
3911 switch ((int) BITS (5, 6))
3912 {
3913 case LSL:
3914 return (base << shamt);
3915 case LSR:
3916 if (shamt == 0)
3917 return (0);
3918 else
3919 return (base >> shamt);
3920 case ASR:
3921 if (shamt == 0)
3922 return ((ARMword) ((long int) base >> 31L));
3923 else
3924 return ((ARMword) ((long int) base >> (int) shamt));
3925 case ROR:
3926 if (shamt == 0)
3927 /* It's an RRX. */
3928 return ((base >> 1) | (CFLAG << 31));
3929 else
3930 return ((base << (32 - shamt)) | (base >> shamt));
3931 default:
3932 break;
3933 }
3934 return 0;
3935 }
3936
3937 /* This routine evaluates the ARM7T halfword and signed transfer RHS's. */
3938
3939 static ARMword
3940 GetLS7RHS (ARMul_State * state, ARMword instr)
3941 {
3942 if (BIT (22) == 0)
3943 {
3944 /* Register. */
3945 #ifndef MODE32
3946 if (RHSReg == 15)
3947 /* Now forbidden, but ... */
3948 return ECC | ER15INT | R15PC | EMODE;
3949 #endif
3950 return state->Reg[RHSReg];
3951 }
3952
3953 /* Immediate. */
3954 return BITS (0, 3) | (BITS (8, 11) << 4);
3955 }
3956
3957 /* This function does the work of loading a word for a LDR instruction. */
3958
3959 static unsigned
3960 LoadWord (ARMul_State * state, ARMword instr, ARMword address)
3961 {
3962 ARMword dest;
3963
3964 BUSUSEDINCPCS;
3965 #ifndef MODE32
3966 if (ADDREXCEPT (address))
3967 INTERNALABORT (address);
3968 #endif
3969
3970 dest = ARMul_LoadWordN (state, address);
3971
3972 if (state->Aborted)
3973 {
3974 TAKEABORT;
3975 return state->lateabtSig;
3976 }
3977 if (address & 3)
3978 dest = ARMul_Align (state, address, dest);
3979 WRITEDESTB (dest);
3980 ARMul_Icycles (state, 1, 0L);
3981
3982 return (DESTReg != LHSReg);
3983 }
3984
3985 #ifdef MODET
3986 /* This function does the work of loading a halfword. */
3987
3988 static unsigned
3989 LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
3990 int signextend)
3991 {
3992 ARMword dest;
3993
3994 BUSUSEDINCPCS;
3995 #ifndef MODE32
3996 if (ADDREXCEPT (address))
3997 INTERNALABORT (address);
3998 #endif
3999 dest = ARMul_LoadHalfWord (state, address);
4000 if (state->Aborted)
4001 {
4002 TAKEABORT;
4003 return state->lateabtSig;
4004 }
4005 UNDEF_LSRBPC;
4006 if (signextend)
4007 if (dest & 1 << (16 - 1))
4008 dest = (dest & ((1 << 16) - 1)) - (1 << 16);
4009
4010 WRITEDEST (dest);
4011 ARMul_Icycles (state, 1, 0L);
4012 return (DESTReg != LHSReg);
4013 }
4014
4015 #endif /* MODET */
4016
4017 /* This function does the work of loading a byte for a LDRB instruction. */
4018
4019 static unsigned
4020 LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
4021 {
4022 ARMword dest;
4023
4024 BUSUSEDINCPCS;
4025 #ifndef MODE32
4026 if (ADDREXCEPT (address))
4027 INTERNALABORT (address);
4028 #endif
4029 dest = ARMul_LoadByte (state, address);
4030 if (state->Aborted)
4031 {
4032 TAKEABORT;
4033 return state->lateabtSig;
4034 }
4035 UNDEF_LSRBPC;
4036 if (signextend)
4037 if (dest & 1 << (8 - 1))
4038 dest = (dest & ((1 << 8) - 1)) - (1 << 8);
4039
4040 WRITEDEST (dest);
4041 ARMul_Icycles (state, 1, 0L);
4042
4043 return (DESTReg != LHSReg);
4044 }
4045
4046 /* This function does the work of loading two words for a LDRD instruction. */
4047
4048 static void
4049 Handle_Load_Double (ARMul_State * state, ARMword instr)
4050 {
4051 ARMword dest_reg;
4052 ARMword addr_reg;
4053 ARMword write_back = BIT (21);
4054 ARMword immediate = BIT (22);
4055 ARMword add_to_base = BIT (23);
4056 ARMword pre_indexed = BIT (24);
4057 ARMword offset;
4058 ARMword addr;
4059 ARMword sum;
4060 ARMword base;
4061 ARMword value1;
4062 ARMword value2;
4063
4064 BUSUSEDINCPCS;
4065
4066 /* If the writeback bit is set, the pre-index bit must be clear. */
4067 if (write_back && ! pre_indexed)
4068 {
4069 ARMul_UndefInstr (state, instr);
4070 return;
4071 }
4072
4073 /* Extract the base address register. */
4074 addr_reg = LHSReg;
4075
4076 /* Extract the destination register and check it. */
4077 dest_reg = DESTReg;
4078
4079 /* Destination register must be even. */
4080 if ((dest_reg & 1)
4081 /* Destination register cannot be LR. */
4082 || (dest_reg == 14))
4083 {
4084 ARMul_UndefInstr (state, instr);
4085 return;
4086 }
4087
4088 /* Compute the base address. */
4089 base = state->Reg[addr_reg];
4090
4091 /* Compute the offset. */
4092 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4093
4094 /* Compute the sum of the two. */
4095 if (add_to_base)
4096 sum = base + offset;
4097 else
4098 sum = base - offset;
4099
4100 /* If this is a pre-indexed mode use the sum. */
4101 if (pre_indexed)
4102 addr = sum;
4103 else
4104 addr = base;
4105
4106 /* The address must be aligned on a 8 byte boundary. */
4107 if (addr & 0x7)
4108 {
4109 #ifdef ABORTS
4110 ARMul_DATAABORT (addr);
4111 #else
4112 ARMul_UndefInstr (state, instr);
4113 #endif
4114 return;
4115 }
4116
4117 /* For pre indexed or post indexed addressing modes,
4118 check that the destination registers do not overlap
4119 the address registers. */
4120 if ((! pre_indexed || write_back)
4121 && ( addr_reg == dest_reg
4122 || addr_reg == dest_reg + 1))
4123 {
4124 ARMul_UndefInstr (state, instr);
4125 return;
4126 }
4127
4128 /* Load the words. */
4129 value1 = ARMul_LoadWordN (state, addr);
4130 value2 = ARMul_LoadWordN (state, addr + 4);
4131
4132 /* Check for data aborts. */
4133 if (state->Aborted)
4134 {
4135 TAKEABORT;
4136 return;
4137 }
4138
4139 ARMul_Icycles (state, 2, 0L);
4140
4141 /* Store the values. */
4142 state->Reg[dest_reg] = value1;
4143 state->Reg[dest_reg + 1] = value2;
4144
4145 /* Do the post addressing and writeback. */
4146 if (! pre_indexed)
4147 addr = sum;
4148
4149 if (! pre_indexed || write_back)
4150 state->Reg[addr_reg] = addr;
4151 }
4152
4153 /* This function does the work of storing two words for a STRD instruction. */
4154
4155 static void
4156 Handle_Store_Double (ARMul_State * state, ARMword instr)
4157 {
4158 ARMword src_reg;
4159 ARMword addr_reg;
4160 ARMword write_back = BIT (21);
4161 ARMword immediate = BIT (22);
4162 ARMword add_to_base = BIT (23);
4163 ARMword pre_indexed = BIT (24);
4164 ARMword offset;
4165 ARMword addr;
4166 ARMword sum;
4167 ARMword base;
4168
4169 BUSUSEDINCPCS;
4170
4171 /* If the writeback bit is set, the pre-index bit must be clear. */
4172 if (write_back && ! pre_indexed)
4173 {
4174 ARMul_UndefInstr (state, instr);
4175 return;
4176 }
4177
4178 /* Extract the base address register. */
4179 addr_reg = LHSReg;
4180
4181 /* Base register cannot be PC. */
4182 if (addr_reg == 15)
4183 {
4184 ARMul_UndefInstr (state, instr);
4185 return;
4186 }
4187
4188 /* Extract the source register. */
4189 src_reg = DESTReg;
4190
4191 /* Source register must be even. */
4192 if (src_reg & 1)
4193 {
4194 ARMul_UndefInstr (state, instr);
4195 return;
4196 }
4197
4198 /* Compute the base address. */
4199 base = state->Reg[addr_reg];
4200
4201 /* Compute the offset. */
4202 offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
4203
4204 /* Compute the sum of the two. */
4205 if (add_to_base)
4206 sum = base + offset;
4207 else
4208 sum = base - offset;
4209
4210 /* If this is a pre-indexed mode use the sum. */
4211 if (pre_indexed)
4212 addr = sum;
4213 else
4214 addr = base;
4215
4216 /* The address must be aligned on a 8 byte boundary. */
4217 if (addr & 0x7)
4218 {
4219 #ifdef ABORTS
4220 ARMul_DATAABORT (addr);
4221 #else
4222 ARMul_UndefInstr (state, instr);
4223 #endif
4224 return;
4225 }
4226
4227 /* For pre indexed or post indexed addressing modes,
4228 check that the destination registers do not overlap
4229 the address registers. */
4230 if ((! pre_indexed || write_back)
4231 && ( addr_reg == src_reg
4232 || addr_reg == src_reg + 1))
4233 {
4234 ARMul_UndefInstr (state, instr);
4235 return;
4236 }
4237
4238 /* Load the words. */
4239 ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
4240 ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
4241
4242 if (state->Aborted)
4243 {
4244 TAKEABORT;
4245 return;
4246 }
4247
4248 /* Do the post addressing and writeback. */
4249 if (! pre_indexed)
4250 addr = sum;
4251
4252 if (! pre_indexed || write_back)
4253 state->Reg[addr_reg] = addr;
4254 }
4255
4256 /* This function does the work of storing a word from a STR instruction. */
4257
4258 static unsigned
4259 StoreWord (ARMul_State * state, ARMword instr, ARMword address)
4260 {
4261 BUSUSEDINCPCN;
4262 #ifndef MODE32
4263 if (DESTReg == 15)
4264 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4265 #endif
4266 #ifdef MODE32
4267 ARMul_StoreWordN (state, address, DEST);
4268 #else
4269 if (VECTORACCESS (address) || ADDREXCEPT (address))
4270 {
4271 INTERNALABORT (address);
4272 (void) ARMul_LoadWordN (state, address);
4273 }
4274 else
4275 ARMul_StoreWordN (state, address, DEST);
4276 #endif
4277 if (state->Aborted)
4278 {
4279 TAKEABORT;
4280 return state->lateabtSig;
4281 }
4282 return TRUE;
4283 }
4284
4285 #ifdef MODET
4286 /* This function does the work of storing a byte for a STRH instruction. */
4287
4288 static unsigned
4289 StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
4290 {
4291 BUSUSEDINCPCN;
4292
4293 #ifndef MODE32
4294 if (DESTReg == 15)
4295 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4296 #endif
4297
4298 #ifdef MODE32
4299 ARMul_StoreHalfWord (state, address, DEST);
4300 #else
4301 if (VECTORACCESS (address) || ADDREXCEPT (address))
4302 {
4303 INTERNALABORT (address);
4304 (void) ARMul_LoadHalfWord (state, address);
4305 }
4306 else
4307 ARMul_StoreHalfWord (state, address, DEST);
4308 #endif
4309
4310 if (state->Aborted)
4311 {
4312 TAKEABORT;
4313 return state->lateabtSig;
4314 }
4315 return TRUE;
4316 }
4317
4318 #endif /* MODET */
4319
4320 /* This function does the work of storing a byte for a STRB instruction. */
4321
4322 static unsigned
4323 StoreByte (ARMul_State * state, ARMword instr, ARMword address)
4324 {
4325 BUSUSEDINCPCN;
4326 #ifndef MODE32
4327 if (DESTReg == 15)
4328 state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
4329 #endif
4330 #ifdef MODE32
4331 ARMul_StoreByte (state, address, DEST);
4332 #else
4333 if (VECTORACCESS (address) || ADDREXCEPT (address))
4334 {
4335 INTERNALABORT (address);
4336 (void) ARMul_LoadByte (state, address);
4337 }
4338 else
4339 ARMul_StoreByte (state, address, DEST);
4340 #endif
4341 if (state->Aborted)
4342 {
4343 TAKEABORT;
4344 return state->lateabtSig;
4345 }
4346 UNDEF_LSRBPC;
4347 return TRUE;
4348 }
4349
4350 /* This function does the work of loading the registers listed in an LDM
4351 instruction, when the S bit is clear. The code here is always increment
4352 after, it's up to the caller to get the input address correct and to
4353 handle base register modification. */
4354
4355 static void
4356 LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
4357 {
4358 ARMword dest, temp;
4359
4360 UNDEF_LSMNoRegs;
4361 UNDEF_LSMPCBase;
4362 UNDEF_LSMBaseInListWb;
4363 BUSUSEDINCPCS;
4364 #ifndef MODE32
4365 if (ADDREXCEPT (address))
4366 INTERNALABORT (address);
4367 #endif
4368 if (BIT (21) && LHSReg != 15)
4369 LSBase = WBBase;
4370
4371 /* N cycle first. */
4372 for (temp = 0; !BIT (temp); temp++)
4373 ;
4374
4375 dest = ARMul_LoadWordN (state, address);
4376
4377 if (!state->abortSig && !state->Aborted)
4378 state->Reg[temp++] = dest;
4379 else if (!state->Aborted)
4380 {
4381 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4382 state->Aborted = ARMul_DataAbortV;
4383 }
4384
4385 /* S cycles from here on. */
4386 for (; temp < 16; temp ++)
4387 if (BIT (temp))
4388 {
4389 /* Load this register. */
4390 address += 4;
4391 dest = ARMul_LoadWordS (state, address);
4392
4393 if (!state->abortSig && !state->Aborted)
4394 state->Reg[temp] = dest;
4395 else if (!state->Aborted)
4396 {
4397 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4398 state->Aborted = ARMul_DataAbortV;
4399 }
4400 }
4401
4402 if (BIT (15) && !state->Aborted)
4403 /* PC is in the reg list. */
4404 WriteR15Branch (state, PC);
4405
4406 /* To write back the final register. */
4407 ARMul_Icycles (state, 1, 0L);
4408
4409 if (state->Aborted)
4410 {
4411 if (BIT (21) && LHSReg != 15)
4412 LSBase = WBBase;
4413 TAKEABORT;
4414 }
4415 }
4416
4417 /* This function does the work of loading the registers listed in an LDM
4418 instruction, when the S bit is set. The code here is always increment
4419 after, it's up to the caller to get the input address correct and to
4420 handle base register modification. */
4421
4422 static void
4423 LoadSMult (ARMul_State * state,
4424 ARMword instr,
4425 ARMword address,
4426 ARMword WBBase)
4427 {
4428 ARMword dest, temp;
4429
4430 UNDEF_LSMNoRegs;
4431 UNDEF_LSMPCBase;
4432 UNDEF_LSMBaseInListWb;
4433
4434 BUSUSEDINCPCS;
4435
4436 #ifndef MODE32
4437 if (ADDREXCEPT (address))
4438 INTERNALABORT (address);
4439 #endif
4440
4441 if (BIT (21) && LHSReg != 15)
4442 LSBase = WBBase;
4443
4444 if (!BIT (15) && state->Bank != USERBANK)
4445 {
4446 /* Temporary reg bank switch. */
4447 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4448 UNDEF_LSMUserBankWb;
4449 }
4450
4451 /* N cycle first. */
4452 for (temp = 0; !BIT (temp); temp ++)
4453 ;
4454
4455 dest = ARMul_LoadWordN (state, address);
4456
4457 if (!state->abortSig)
4458 state->Reg[temp++] = dest;
4459 else if (!state->Aborted)
4460 {
4461 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4462 state->Aborted = ARMul_DataAbortV;
4463 }
4464
4465 /* S cycles from here on. */
4466 for (; temp < 16; temp++)
4467 if (BIT (temp))
4468 {
4469 /* Load this register. */
4470 address += 4;
4471 dest = ARMul_LoadWordS (state, address);
4472
4473 if (!state->abortSig && !state->Aborted)
4474 state->Reg[temp] = dest;
4475 else if (!state->Aborted)
4476 {
4477 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4478 state->Aborted = ARMul_DataAbortV;
4479 }
4480 }
4481
4482 if (BIT (15) && !state->Aborted)
4483 {
4484 /* PC is in the reg list. */
4485 #ifdef MODE32
4486 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4487 {
4488 state->Cpsr = GETSPSR (state->Bank);
4489 ARMul_CPSRAltered (state);
4490 }
4491
4492 WriteR15 (state, PC);
4493 #else
4494 if (state->Mode == USER26MODE || state->Mode == USER32MODE)
4495 {
4496 /* Protect bits in user mode. */
4497 ASSIGNN ((state->Reg[15] & NBIT) != 0);
4498 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
4499 ASSIGNC ((state->Reg[15] & CBIT) != 0);
4500 ASSIGNV ((state->Reg[15] & VBIT) != 0);
4501 }
4502 else
4503 ARMul_R15Altered (state);
4504
4505 FLUSHPIPE;
4506 #endif
4507 }
4508
4509 if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
4510 /* Restore the correct bank. */
4511 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4512
4513 /* To write back the final register. */
4514 ARMul_Icycles (state, 1, 0L);
4515
4516 if (state->Aborted)
4517 {
4518 if (BIT (21) && LHSReg != 15)
4519 LSBase = WBBase;
4520
4521 TAKEABORT;
4522 }
4523 }
4524
4525 /* This function does the work of storing the registers listed in an STM
4526 instruction, when the S bit is clear. The code here is always increment
4527 after, it's up to the caller to get the input address correct and to
4528 handle base register modification. */
4529
4530 static void
4531 StoreMult (ARMul_State * state,
4532 ARMword instr,
4533 ARMword address,
4534 ARMword WBBase)
4535 {
4536 ARMword temp;
4537
4538 UNDEF_LSMNoRegs;
4539 UNDEF_LSMPCBase;
4540 UNDEF_LSMBaseInListWb;
4541
4542 if (!TFLAG)
4543 /* N-cycle, increment the PC and update the NextInstr state. */
4544 BUSUSEDINCPCN;
4545
4546 #ifndef MODE32
4547 if (VECTORACCESS (address) || ADDREXCEPT (address))
4548 INTERNALABORT (address);
4549
4550 if (BIT (15))
4551 PATCHR15;
4552 #endif
4553
4554 /* N cycle first. */
4555 for (temp = 0; !BIT (temp); temp ++)
4556 ;
4557
4558 #ifdef MODE32
4559 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4560 #else
4561 if (state->Aborted)
4562 {
4563 (void) ARMul_LoadWordN (state, address);
4564
4565 /* Fake the Stores as Loads. */
4566 for (; temp < 16; temp++)
4567 if (BIT (temp))
4568 {
4569 /* Save this register. */
4570 address += 4;
4571 (void) ARMul_LoadWordS (state, address);
4572 }
4573
4574 if (BIT (21) && LHSReg != 15)
4575 LSBase = WBBase;
4576 TAKEABORT;
4577 return;
4578 }
4579 else
4580 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4581 #endif
4582
4583 if (state->abortSig && !state->Aborted)
4584 {
4585 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4586 state->Aborted = ARMul_DataAbortV;
4587 }
4588
4589 if (BIT (21) && LHSReg != 15)
4590 LSBase = WBBase;
4591
4592 /* S cycles from here on. */
4593 for (; temp < 16; temp ++)
4594 if (BIT (temp))
4595 {
4596 /* Save this register. */
4597 address += 4;
4598
4599 ARMul_StoreWordS (state, address, state->Reg[temp]);
4600
4601 if (state->abortSig && !state->Aborted)
4602 {
4603 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4604 state->Aborted = ARMul_DataAbortV;
4605 }
4606 }
4607
4608 if (state->Aborted)
4609 TAKEABORT;
4610 }
4611
4612 /* This function does the work of storing the registers listed in an STM
4613 instruction when the S bit is set. The code here is always increment
4614 after, it's up to the caller to get the input address correct and to
4615 handle base register modification. */
4616
4617 static void
4618 StoreSMult (ARMul_State * state,
4619 ARMword instr,
4620 ARMword address,
4621 ARMword WBBase)
4622 {
4623 ARMword temp;
4624
4625 UNDEF_LSMNoRegs;
4626 UNDEF_LSMPCBase;
4627 UNDEF_LSMBaseInListWb;
4628
4629 BUSUSEDINCPCN;
4630
4631 #ifndef MODE32
4632 if (VECTORACCESS (address) || ADDREXCEPT (address))
4633 INTERNALABORT (address);
4634
4635 if (BIT (15))
4636 PATCHR15;
4637 #endif
4638
4639 if (state->Bank != USERBANK)
4640 {
4641 /* Force User Bank. */
4642 (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
4643 UNDEF_LSMUserBankWb;
4644 }
4645
4646 for (temp = 0; !BIT (temp); temp++)
4647 ; /* N cycle first. */
4648
4649 #ifdef MODE32
4650 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4651 #else
4652 if (state->Aborted)
4653 {
4654 (void) ARMul_LoadWordN (state, address);
4655
4656 for (; temp < 16; temp++)
4657 /* Fake the Stores as Loads. */
4658 if (BIT (temp))
4659 {
4660 /* Save this register. */
4661 address += 4;
4662
4663 (void) ARMul_LoadWordS (state, address);
4664 }
4665
4666 if (BIT (21) && LHSReg != 15)
4667 LSBase = WBBase;
4668
4669 TAKEABORT;
4670 return;
4671 }
4672 else
4673 ARMul_StoreWordN (state, address, state->Reg[temp++]);
4674 #endif
4675
4676 if (state->abortSig && !state->Aborted)
4677 {
4678 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4679 state->Aborted = ARMul_DataAbortV;
4680 }
4681
4682 /* S cycles from here on. */
4683 for (; temp < 16; temp++)
4684 if (BIT (temp))
4685 {
4686 /* Save this register. */
4687 address += 4;
4688
4689 ARMul_StoreWordS (state, address, state->Reg[temp]);
4690
4691 if (state->abortSig && !state->Aborted)
4692 {
4693 XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
4694 state->Aborted = ARMul_DataAbortV;
4695 }
4696 }
4697
4698 if (state->Mode != USER26MODE && state->Mode != USER32MODE)
4699 /* Restore the correct bank. */
4700 (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
4701
4702 if (BIT (21) && LHSReg != 15)
4703 LSBase = WBBase;
4704
4705 if (state->Aborted)
4706 TAKEABORT;
4707 }
4708
4709 /* This function does the work of adding two 32bit values
4710 together, and calculating if a carry has occurred. */
4711
4712 static ARMword
4713 Add32 (ARMword a1, ARMword a2, int *carry)
4714 {
4715 ARMword result = (a1 + a2);
4716 unsigned int uresult = (unsigned int) result;
4717 unsigned int ua1 = (unsigned int) a1;
4718
4719 /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
4720 or (result > RdLo) then we have no carry. */
4721 if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
4722 *carry = 1;
4723 else
4724 *carry = 0;
4725
4726 return result;
4727 }
4728
4729 /* This function does the work of multiplying
4730 two 32bit values to give a 64bit result. */
4731
4732 static unsigned
4733 Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
4734 {
4735 /* Operand register numbers. */
4736 int nRdHi, nRdLo, nRs, nRm;
4737 ARMword RdHi = 0, RdLo = 0, Rm;
4738 /* Cycle count. */
4739 int scount;
4740
4741 nRdHi = BITS (16, 19);
4742 nRdLo = BITS (12, 15);
4743 nRs = BITS (8, 11);
4744 nRm = BITS (0, 3);
4745
4746 /* Needed to calculate the cycle count. */
4747 Rm = state->Reg[nRm];
4748
4749 /* Check for illegal operand combinations first. */
4750 if ( nRdHi != 15
4751 && nRdLo != 15
4752 && nRs != 15
4753 && nRm != 15
4754 && nRdHi != nRdLo
4755 && nRdHi != nRm
4756 && nRdLo != nRm)
4757 {
4758 /* Intermediate results. */
4759 ARMword lo, mid1, mid2, hi;
4760 int carry;
4761 ARMword Rs = state->Reg[nRs];
4762 int sign = 0;
4763
4764 if (msigned)
4765 {
4766 /* Compute sign of result and adjust operands if necessary. */
4767 sign = (Rm ^ Rs) & 0x80000000;
4768
4769 if (((signed long) Rm) < 0)
4770 Rm = -Rm;
4771
4772 if (((signed long) Rs) < 0)
4773 Rs = -Rs;
4774 }
4775
4776 /* We can split the 32x32 into four 16x16 operations. This
4777 ensures that we do not lose precision on 32bit only hosts. */
4778 lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
4779 mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4780 mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
4781 hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
4782
4783 /* We now need to add all of these results together, taking
4784 care to propogate the carries from the additions. */
4785 RdLo = Add32 (lo, (mid1 << 16), &carry);
4786 RdHi = carry;
4787 RdLo = Add32 (RdLo, (mid2 << 16), &carry);
4788 RdHi +=
4789 (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
4790
4791 if (sign)
4792 {
4793 /* Negate result if necessary. */
4794 RdLo = ~RdLo;
4795 RdHi = ~RdHi;
4796 if (RdLo == 0xFFFFFFFF)
4797 {
4798 RdLo = 0;
4799 RdHi += 1;
4800 }
4801 else
4802 RdLo += 1;
4803 }
4804
4805 state->Reg[nRdLo] = RdLo;
4806 state->Reg[nRdHi] = RdHi;
4807 }
4808 else
4809 fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
4810
4811 if (scc)
4812 /* Ensure that both RdHi and RdLo are used to compute Z,
4813 but don't let RdLo's sign bit make it to N. */
4814 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4815
4816 /* The cycle count depends on whether the instruction is a signed or
4817 unsigned multiply, and what bits are clear in the multiplier. */
4818 if (msigned && (Rm & ((unsigned) 1 << 31)))
4819 /* Invert the bits to make the check against zero. */
4820 Rm = ~Rm;
4821
4822 if ((Rm & 0xFFFFFF00) == 0)
4823 scount = 1;
4824 else if ((Rm & 0xFFFF0000) == 0)
4825 scount = 2;
4826 else if ((Rm & 0xFF000000) == 0)
4827 scount = 3;
4828 else
4829 scount = 4;
4830
4831 return 2 + scount;
4832 }
4833
4834 /* This function does the work of multiplying two 32bit
4835 values and adding a 64bit value to give a 64bit result. */
4836
4837 static unsigned
4838 MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
4839 {
4840 unsigned scount;
4841 ARMword RdLo, RdHi;
4842 int nRdHi, nRdLo;
4843 int carry = 0;
4844
4845 nRdHi = BITS (16, 19);
4846 nRdLo = BITS (12, 15);
4847
4848 RdHi = state->Reg[nRdHi];
4849 RdLo = state->Reg[nRdLo];
4850
4851 scount = Multiply64 (state, instr, msigned, LDEFAULT);
4852
4853 RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
4854 RdHi = (RdHi + state->Reg[nRdHi]) + carry;
4855
4856 state->Reg[nRdLo] = RdLo;
4857 state->Reg[nRdHi] = RdHi;
4858
4859 if (scc)
4860 /* Ensure that both RdHi and RdLo are used to compute Z,
4861 but don't let RdLo's sign bit make it to N. */
4862 ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
4863
4864 /* Extra cycle for addition. */
4865 return scount + 1;
4866 }
This page took 0.133089 seconds and 4 git commands to generate.