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