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