OSDN Git Service

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