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