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