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