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