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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [arm/] [armemu.c] - Blame information for rev 26

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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