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