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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [sim/] [arm/] [armemu.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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