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