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