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

Subversion Repositories or1k

[/] [or1k/] [tags/] [tn_m001/] [gdb-5.0/] [sim/] [arm/] [armemu.c] - Blame information for rev 106

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

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

powered by: WebSVN 2.1.0

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