OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [arm/] [armemu.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.