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

Subversion Repositories openrisc_me

[/] [openrisc/] [tags/] [gdb/] [gdb-6.8/] [gdb-6.8.openrisc-2.1/] [sim/] [arm/] [armemu.c] - Diff between revs 24 and 33

Only display areas with differences | Details | Blame | View Log

Rev 24 Rev 33
/*  armemu.c -- Main instruction emulation:  ARM7 Instruction Emulator.
/*  armemu.c -- Main instruction emulation:  ARM7 Instruction Emulator.
    Copyright (C) 1994 Advanced RISC Machines Ltd.
    Copyright (C) 1994 Advanced RISC Machines Ltd.
    Modifications to add arch. v4 support by <jsmith@cygnus.com>.
    Modifications to add arch. v4 support by <jsmith@cygnus.com>.
 
 
    This program is free software; you can redistribute it and/or modify
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    (at your option) any later version.
 
 
    This program is distributed in the hope that it will be useful,
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    GNU General Public License for more details.
 
 
    You should have received a copy of the GNU General Public License
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 
#include "armdefs.h"
#include "armdefs.h"
#include "armemu.h"
#include "armemu.h"
#include "armos.h"
#include "armos.h"
#include "iwmmxt.h"
#include "iwmmxt.h"
 
 
static ARMword  GetDPRegRHS         (ARMul_State *, ARMword);
static ARMword  GetDPRegRHS         (ARMul_State *, ARMword);
static ARMword  GetDPSRegRHS        (ARMul_State *, ARMword);
static ARMword  GetDPSRegRHS        (ARMul_State *, ARMword);
static void     WriteR15            (ARMul_State *, ARMword);
static void     WriteR15            (ARMul_State *, ARMword);
static void     WriteSR15           (ARMul_State *, ARMword);
static void     WriteSR15           (ARMul_State *, ARMword);
static void     WriteR15Branch      (ARMul_State *, ARMword);
static void     WriteR15Branch      (ARMul_State *, ARMword);
static ARMword  GetLSRegRHS         (ARMul_State *, ARMword);
static ARMword  GetLSRegRHS         (ARMul_State *, ARMword);
static ARMword  GetLS7RHS           (ARMul_State *, ARMword);
static ARMword  GetLS7RHS           (ARMul_State *, ARMword);
static unsigned LoadWord            (ARMul_State *, ARMword, ARMword);
static unsigned LoadWord            (ARMul_State *, ARMword, ARMword);
static unsigned LoadHalfWord        (ARMul_State *, ARMword, ARMword, int);
static unsigned LoadHalfWord        (ARMul_State *, ARMword, ARMword, int);
static unsigned LoadByte            (ARMul_State *, ARMword, ARMword, int);
static unsigned LoadByte            (ARMul_State *, ARMword, ARMword, int);
static unsigned StoreWord           (ARMul_State *, ARMword, ARMword);
static unsigned StoreWord           (ARMul_State *, ARMword, ARMword);
static unsigned StoreHalfWord       (ARMul_State *, ARMword, ARMword);
static unsigned StoreHalfWord       (ARMul_State *, ARMword, ARMword);
static unsigned StoreByte           (ARMul_State *, ARMword, ARMword);
static unsigned StoreByte           (ARMul_State *, ARMword, ARMword);
static void     LoadMult            (ARMul_State *, ARMword, ARMword, ARMword);
static void     LoadMult            (ARMul_State *, ARMword, ARMword, ARMword);
static void     StoreMult           (ARMul_State *, ARMword, ARMword, ARMword);
static void     StoreMult           (ARMul_State *, ARMword, ARMword, ARMword);
static void     LoadSMult           (ARMul_State *, ARMword, ARMword, ARMword);
static void     LoadSMult           (ARMul_State *, ARMword, ARMword, ARMword);
static void     StoreSMult          (ARMul_State *, ARMword, ARMword, ARMword);
static void     StoreSMult          (ARMul_State *, ARMword, ARMword, ARMword);
static unsigned Multiply64          (ARMul_State *, ARMword, int, int);
static unsigned Multiply64          (ARMul_State *, ARMword, int, int);
static unsigned MultiplyAdd64       (ARMul_State *, ARMword, int, int);
static unsigned MultiplyAdd64       (ARMul_State *, ARMword, int, int);
static void     Handle_Load_Double  (ARMul_State *, ARMword);
static void     Handle_Load_Double  (ARMul_State *, ARMword);
static void     Handle_Store_Double (ARMul_State *, ARMword);
static void     Handle_Store_Double (ARMul_State *, ARMword);
 
 
#define LUNSIGNED (0)           /* unsigned operation */
#define LUNSIGNED (0)           /* unsigned operation */
#define LSIGNED   (1)           /* signed operation */
#define LSIGNED   (1)           /* signed operation */
#define LDEFAULT  (0)           /* default : do nothing */
#define LDEFAULT  (0)           /* default : do nothing */
#define LSCC      (1)           /* set condition codes on result */
#define LSCC      (1)           /* set condition codes on result */
 
 
#ifdef NEED_UI_LOOP_HOOK
#ifdef NEED_UI_LOOP_HOOK
/* How often to run the ui_loop update, when in use.  */
/* How often to run the ui_loop update, when in use.  */
#define UI_LOOP_POLL_INTERVAL 0x32000
#define UI_LOOP_POLL_INTERVAL 0x32000
 
 
/* Counter for the ui_loop_hook update.  */
/* Counter for the ui_loop_hook update.  */
static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
 
 
/* Actual hook to call to run through gdb's gui event loop.  */
/* Actual hook to call to run through gdb's gui event loop.  */
extern int (*deprecated_ui_loop_hook) (int);
extern int (*deprecated_ui_loop_hook) (int);
#endif /* NEED_UI_LOOP_HOOK */
#endif /* NEED_UI_LOOP_HOOK */
 
 
extern int stop_simulator;
extern int stop_simulator;
 
 
/* Short-hand macros for LDR/STR.  */
/* Short-hand macros for LDR/STR.  */
 
 
/* Store post decrement writeback.  */
/* Store post decrement writeback.  */
#define SHDOWNWB()                                      \
#define SHDOWNWB()                                      \
  lhs = LHS ;                                           \
  lhs = LHS ;                                           \
  if (StoreHalfWord (state, instr, lhs))                \
  if (StoreHalfWord (state, instr, lhs))                \
     LSBase = lhs - GetLS7RHS (state, instr);
     LSBase = lhs - GetLS7RHS (state, instr);
 
 
/* Store post increment writeback.  */
/* Store post increment writeback.  */
#define SHUPWB()                                        \
#define SHUPWB()                                        \
  lhs = LHS ;                                           \
  lhs = LHS ;                                           \
  if (StoreHalfWord (state, instr, lhs))                \
  if (StoreHalfWord (state, instr, lhs))                \
     LSBase = lhs + GetLS7RHS (state, instr);
     LSBase = lhs + GetLS7RHS (state, instr);
 
 
/* Store pre decrement.  */
/* Store pre decrement.  */
#define SHPREDOWN()                                     \
#define SHPREDOWN()                                     \
  (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
  (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr));
 
 
/* Store pre decrement writeback.  */
/* Store pre decrement writeback.  */
#define SHPREDOWNWB()                                   \
#define SHPREDOWNWB()                                   \
  temp = LHS - GetLS7RHS (state, instr);                \
  temp = LHS - GetLS7RHS (state, instr);                \
  if (StoreHalfWord (state, instr, temp))               \
  if (StoreHalfWord (state, instr, temp))               \
     LSBase = temp;
     LSBase = temp;
 
 
/* Store pre increment.  */
/* Store pre increment.  */
#define SHPREUP()                                       \
#define SHPREUP()                                       \
  (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
  (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr));
 
 
/* Store pre increment writeback.  */
/* Store pre increment writeback.  */
#define SHPREUPWB()                                     \
#define SHPREUPWB()                                     \
  temp = LHS + GetLS7RHS (state, instr);                \
  temp = LHS + GetLS7RHS (state, instr);                \
  if (StoreHalfWord (state, instr, temp))               \
  if (StoreHalfWord (state, instr, temp))               \
     LSBase = temp;
     LSBase = temp;
 
 
/* Load post decrement writeback.  */
/* Load post decrement writeback.  */
#define LHPOSTDOWN()                                    \
#define LHPOSTDOWN()                                    \
{                                                       \
{                                                       \
  int done = 1;                                         \
  int done = 1;                                         \
  lhs = LHS;                                            \
  lhs = LHS;                                            \
  temp = lhs - GetLS7RHS (state, instr);                \
  temp = lhs - GetLS7RHS (state, instr);                \
                                                        \
                                                        \
  switch (BITS (5, 6))                                  \
  switch (BITS (5, 6))                                  \
    {                                                   \
    {                                                   \
    case 1: /* H */                                     \
    case 1: /* H */                                     \
      if (LoadHalfWord (state, instr, lhs, LUNSIGNED))  \
      if (LoadHalfWord (state, instr, lhs, LUNSIGNED))  \
         LSBase = temp;                                 \
         LSBase = temp;                                 \
      break;                                            \
      break;                                            \
    case 2: /* SB */                                    \
    case 2: /* SB */                                    \
      if (LoadByte (state, instr, lhs, LSIGNED))        \
      if (LoadByte (state, instr, lhs, LSIGNED))        \
         LSBase = temp;                                 \
         LSBase = temp;                                 \
      break;                                            \
      break;                                            \
    case 3: /* SH */                                    \
    case 3: /* SH */                                    \
      if (LoadHalfWord (state, instr, lhs, LSIGNED))    \
      if (LoadHalfWord (state, instr, lhs, LSIGNED))    \
         LSBase = temp;                                 \
         LSBase = temp;                                 \
      break;                                            \
      break;                                            \
    case 0: /* SWP handled elsewhere.  */               \
    case 0: /* SWP handled elsewhere.  */               \
    default:                                            \
    default:                                            \
      done = 0;                                          \
      done = 0;                                          \
      break;                                            \
      break;                                            \
    }                                                   \
    }                                                   \
  if (done)                                             \
  if (done)                                             \
     break;                                             \
     break;                                             \
}
}
 
 
/* Load post increment writeback.  */
/* Load post increment writeback.  */
#define LHPOSTUP()                                      \
#define LHPOSTUP()                                      \
{                                                       \
{                                                       \
  int done = 1;                                         \
  int done = 1;                                         \
  lhs = LHS;                                            \
  lhs = LHS;                                            \
  temp = lhs + GetLS7RHS (state, instr);                \
  temp = lhs + GetLS7RHS (state, instr);                \
                                                        \
                                                        \
  switch (BITS (5, 6))                                  \
  switch (BITS (5, 6))                                  \
    {                                                   \
    {                                                   \
    case 1: /* H */                                     \
    case 1: /* H */                                     \
      if (LoadHalfWord (state, instr, lhs, LUNSIGNED))  \
      if (LoadHalfWord (state, instr, lhs, LUNSIGNED))  \
         LSBase = temp;                                 \
         LSBase = temp;                                 \
      break;                                            \
      break;                                            \
    case 2: /* SB */                                    \
    case 2: /* SB */                                    \
      if (LoadByte (state, instr, lhs, LSIGNED))        \
      if (LoadByte (state, instr, lhs, LSIGNED))        \
         LSBase = temp;                                 \
         LSBase = temp;                                 \
      break;                                            \
      break;                                            \
    case 3: /* SH */                                    \
    case 3: /* SH */                                    \
      if (LoadHalfWord (state, instr, lhs, LSIGNED))    \
      if (LoadHalfWord (state, instr, lhs, LSIGNED))    \
         LSBase = temp;                                 \
         LSBase = temp;                                 \
      break;                                            \
      break;                                            \
    case 0: /* SWP handled elsewhere.  */               \
    case 0: /* SWP handled elsewhere.  */               \
    default:                                            \
    default:                                            \
      done = 0;                                          \
      done = 0;                                          \
      break;                                            \
      break;                                            \
    }                                                   \
    }                                                   \
  if (done)                                             \
  if (done)                                             \
     break;                                             \
     break;                                             \
}
}
 
 
/* Load pre decrement.  */
/* Load pre decrement.  */
#define LHPREDOWN()                                             \
#define LHPREDOWN()                                             \
{                                                               \
{                                                               \
  int done = 1;                                                 \
  int done = 1;                                                 \
                                                                \
                                                                \
  temp = LHS - GetLS7RHS (state, instr);                        \
  temp = LHS - GetLS7RHS (state, instr);                        \
  switch (BITS (5, 6))                                          \
  switch (BITS (5, 6))                                          \
    {                                                           \
    {                                                           \
    case 1: /* H */                                             \
    case 1: /* H */                                             \
      (void) LoadHalfWord (state, instr, temp, LUNSIGNED);      \
      (void) LoadHalfWord (state, instr, temp, LUNSIGNED);      \
      break;                                                    \
      break;                                                    \
    case 2: /* SB */                                            \
    case 2: /* SB */                                            \
      (void) LoadByte (state, instr, temp, LSIGNED);            \
      (void) LoadByte (state, instr, temp, LSIGNED);            \
      break;                                                    \
      break;                                                    \
    case 3: /* SH */                                            \
    case 3: /* SH */                                            \
      (void) LoadHalfWord (state, instr, temp, LSIGNED);        \
      (void) LoadHalfWord (state, instr, temp, LSIGNED);        \
      break;                                                    \
      break;                                                    \
    case 0:                                                      \
    case 0:                                                      \
      /* SWP handled elsewhere.  */                             \
      /* SWP handled elsewhere.  */                             \
    default:                                                    \
    default:                                                    \
      done = 0;                                                  \
      done = 0;                                                  \
      break;                                                    \
      break;                                                    \
    }                                                           \
    }                                                           \
  if (done)                                                     \
  if (done)                                                     \
     break;                                                     \
     break;                                                     \
}
}
 
 
/* Load pre decrement writeback.  */
/* Load pre decrement writeback.  */
#define LHPREDOWNWB()                                           \
#define LHPREDOWNWB()                                           \
{                                                               \
{                                                               \
  int done = 1;                                                 \
  int done = 1;                                                 \
                                                                \
                                                                \
  temp = LHS - GetLS7RHS (state, instr);                        \
  temp = LHS - GetLS7RHS (state, instr);                        \
  switch (BITS (5, 6))                                          \
  switch (BITS (5, 6))                                          \
    {                                                           \
    {                                                           \
    case 1: /* H */                                             \
    case 1: /* H */                                             \
      if (LoadHalfWord (state, instr, temp, LUNSIGNED))         \
      if (LoadHalfWord (state, instr, temp, LUNSIGNED))         \
         LSBase = temp;                                         \
         LSBase = temp;                                         \
      break;                                                    \
      break;                                                    \
    case 2: /* SB */                                            \
    case 2: /* SB */                                            \
      if (LoadByte (state, instr, temp, LSIGNED))               \
      if (LoadByte (state, instr, temp, LSIGNED))               \
         LSBase = temp;                                         \
         LSBase = temp;                                         \
      break;                                                    \
      break;                                                    \
    case 3: /* SH */                                            \
    case 3: /* SH */                                            \
      if (LoadHalfWord (state, instr, temp, LSIGNED))           \
      if (LoadHalfWord (state, instr, temp, LSIGNED))           \
         LSBase = temp;                                         \
         LSBase = temp;                                         \
      break;                                                    \
      break;                                                    \
    case 0:                                                      \
    case 0:                                                      \
      /* SWP handled elsewhere.  */                             \
      /* SWP handled elsewhere.  */                             \
    default:                                                    \
    default:                                                    \
      done = 0;                                                  \
      done = 0;                                                  \
      break;                                                    \
      break;                                                    \
    }                                                           \
    }                                                           \
  if (done)                                                     \
  if (done)                                                     \
     break;                                                     \
     break;                                                     \
}
}
 
 
/* Load pre increment.  */
/* Load pre increment.  */
#define LHPREUP()                                               \
#define LHPREUP()                                               \
{                                                               \
{                                                               \
  int done = 1;                                                 \
  int done = 1;                                                 \
                                                                \
                                                                \
  temp = LHS + GetLS7RHS (state, instr);                        \
  temp = LHS + GetLS7RHS (state, instr);                        \
  switch (BITS (5, 6))                                          \
  switch (BITS (5, 6))                                          \
    {                                                           \
    {                                                           \
    case 1: /* H */                                             \
    case 1: /* H */                                             \
      (void) LoadHalfWord (state, instr, temp, LUNSIGNED);      \
      (void) LoadHalfWord (state, instr, temp, LUNSIGNED);      \
      break;                                                    \
      break;                                                    \
    case 2: /* SB */                                            \
    case 2: /* SB */                                            \
      (void) LoadByte (state, instr, temp, LSIGNED);            \
      (void) LoadByte (state, instr, temp, LSIGNED);            \
      break;                                                    \
      break;                                                    \
    case 3: /* SH */                                            \
    case 3: /* SH */                                            \
      (void) LoadHalfWord (state, instr, temp, LSIGNED);        \
      (void) LoadHalfWord (state, instr, temp, LSIGNED);        \
      break;                                                    \
      break;                                                    \
    case 0:                                                      \
    case 0:                                                      \
      /* SWP handled elsewhere.  */                             \
      /* SWP handled elsewhere.  */                             \
    default:                                                    \
    default:                                                    \
      done = 0;                                                  \
      done = 0;                                                  \
      break;                                                    \
      break;                                                    \
    }                                                           \
    }                                                           \
  if (done)                                                     \
  if (done)                                                     \
     break;                                                     \
     break;                                                     \
}
}
 
 
/* Load pre increment writeback.  */
/* Load pre increment writeback.  */
#define LHPREUPWB()                                             \
#define LHPREUPWB()                                             \
{                                                               \
{                                                               \
  int done = 1;                                                 \
  int done = 1;                                                 \
                                                                \
                                                                \
  temp = LHS + GetLS7RHS (state, instr);                        \
  temp = LHS + GetLS7RHS (state, instr);                        \
  switch (BITS (5, 6))                                          \
  switch (BITS (5, 6))                                          \
    {                                                           \
    {                                                           \
    case 1: /* H */                                             \
    case 1: /* H */                                             \
      if (LoadHalfWord (state, instr, temp, LUNSIGNED))         \
      if (LoadHalfWord (state, instr, temp, LUNSIGNED))         \
        LSBase = temp;                                          \
        LSBase = temp;                                          \
      break;                                                    \
      break;                                                    \
    case 2: /* SB */                                            \
    case 2: /* SB */                                            \
      if (LoadByte (state, instr, temp, LSIGNED))               \
      if (LoadByte (state, instr, temp, LSIGNED))               \
        LSBase = temp;                                          \
        LSBase = temp;                                          \
      break;                                                    \
      break;                                                    \
    case 3: /* SH */                                            \
    case 3: /* SH */                                            \
      if (LoadHalfWord (state, instr, temp, LSIGNED))           \
      if (LoadHalfWord (state, instr, temp, LSIGNED))           \
        LSBase = temp;                                          \
        LSBase = temp;                                          \
      break;                                                    \
      break;                                                    \
    case 0:                                                      \
    case 0:                                                      \
      /* SWP handled elsewhere.  */                             \
      /* SWP handled elsewhere.  */                             \
    default:                                                    \
    default:                                                    \
      done = 0;                                                  \
      done = 0;                                                  \
      break;                                                    \
      break;                                                    \
    }                                                           \
    }                                                           \
  if (done)                                                     \
  if (done)                                                     \
     break;                                                     \
     break;                                                     \
}
}
 
 
/* Attempt to emulate an ARMv6 instruction.
/* Attempt to emulate an ARMv6 instruction.
   Returns non-zero upon success.  */
   Returns non-zero upon success.  */
 
 
static int
static int
handle_v6_insn (ARMul_State * state, ARMword instr)
handle_v6_insn (ARMul_State * state, ARMword instr)
{
{
  switch (BITS (20, 27))
  switch (BITS (20, 27))
    {
    {
#if 0
#if 0
    case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
    case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
    case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
    case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
    case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
    case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
    case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
    case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
    case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
    case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
    case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
    case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
    case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
    case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
    case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
    case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
    case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
    case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
    case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
    case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
    case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
    case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
    case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
    case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
    case 0x30: printf ("Unhandled v6 insn: movw\n"); break;
    case 0x30: printf ("Unhandled v6 insn: movw\n"); break;
    case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
    case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
    case 0x34: printf ("Unhandled v6 insn: movt\n"); break;
    case 0x34: printf ("Unhandled v6 insn: movt\n"); break;
    case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
    case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
#endif
#endif
    case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
    case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
    case 0x62: printf ("Unhandled v6 insn: qadd/qsub\n"); break;
    case 0x62: printf ("Unhandled v6 insn: qadd/qsub\n"); break;
    case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
    case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
    case 0x65: printf ("Unhandled v6 insn: uadd/usub\n"); break;
    case 0x65: printf ("Unhandled v6 insn: uadd/usub\n"); break;
    case 0x66: printf ("Unhandled v6 insn: uqadd/uqsub\n"); break;
    case 0x66: printf ("Unhandled v6 insn: uqadd/uqsub\n"); break;
    case 0x67: printf ("Unhandled v6 insn: uhadd/uhsub\n"); break;
    case 0x67: printf ("Unhandled v6 insn: uhadd/uhsub\n"); break;
    case 0x68: printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); break;
    case 0x68: printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); break;
    case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
    case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
    case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
    case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
    case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
    case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
    case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
    case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
    case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
    case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
    case 0x7a: printf ("Unhandled v6 insn: usbfx\n"); break;
    case 0x7a: printf ("Unhandled v6 insn: usbfx\n"); break;
    case 0x7c: printf ("Unhandled v6 insn: bfc/bfi\n"); break;
    case 0x7c: printf ("Unhandled v6 insn: bfc/bfi\n"); break;
 
 
    case 0x6a:
    case 0x6a:
      {
      {
        ARMword Rm;
        ARMword Rm;
        int ror = -1;
        int ror = -1;
 
 
        switch (BITS (4, 11))
        switch (BITS (4, 11))
          {
          {
          case 0x07: ror = 0; break;
          case 0x07: ror = 0; break;
          case 0x47: ror = 8; break;
          case 0x47: ror = 8; break;
          case 0x87: ror = 16; break;
          case 0x87: ror = 16; break;
          case 0xc7: ror = 24; break;
          case 0xc7: ror = 24; break;
 
 
          case 0x01:
          case 0x01:
          case 0xf3:
          case 0xf3:
            printf ("Unhandled v6 insn: ssat\n");
            printf ("Unhandled v6 insn: ssat\n");
            return 0;
            return 0;
          default:
          default:
            break;
            break;
          }
          }
 
 
        if (ror == -1)
        if (ror == -1)
          {
          {
            if (BITS (4, 6) == 0x7)
            if (BITS (4, 6) == 0x7)
              {
              {
                printf ("Unhandled v6 insn: ssat\n");
                printf ("Unhandled v6 insn: ssat\n");
                return 0;
                return 0;
              }
              }
            break;
            break;
          }
          }
 
 
        Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
        Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
        if (Rm & 0x80)
        if (Rm & 0x80)
          Rm |= 0xffffff00;
          Rm |= 0xffffff00;
 
 
        if (BITS (16, 19) == 0xf)
        if (BITS (16, 19) == 0xf)
           /* SXTB */
           /* SXTB */
          state->Reg[BITS (12, 15)] = Rm;
          state->Reg[BITS (12, 15)] = Rm;
        else
        else
          /* SXTAB */
          /* SXTAB */
          state->Reg[BITS (12, 15)] += Rm;
          state->Reg[BITS (12, 15)] += Rm;
      }
      }
      return 1;
      return 1;
 
 
    case 0x6b:
    case 0x6b:
      {
      {
        ARMword Rm;
        ARMword Rm;
        int ror = -1;
        int ror = -1;
 
 
        switch (BITS (4, 11))
        switch (BITS (4, 11))
          {
          {
          case 0x07: ror = 0; break;
          case 0x07: ror = 0; break;
          case 0x47: ror = 8; break;
          case 0x47: ror = 8; break;
          case 0x87: ror = 16; break;
          case 0x87: ror = 16; break;
          case 0xc7: ror = 24; break;
          case 0xc7: ror = 24; break;
 
 
          case 0xfb:
          case 0xfb:
            printf ("Unhandled v6 insn: rev\n");
            printf ("Unhandled v6 insn: rev\n");
            return 0;
            return 0;
          default:
          default:
            break;
            break;
          }
          }
 
 
        if (ror == -1)
        if (ror == -1)
          break;
          break;
 
 
        Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
        Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
        if (Rm & 0x8000)
        if (Rm & 0x8000)
          Rm |= 0xffff0000;
          Rm |= 0xffff0000;
 
 
        if (BITS (16, 19) == 0xf)
        if (BITS (16, 19) == 0xf)
          /* SXTH */
          /* SXTH */
          state->Reg[BITS (12, 15)] = Rm;
          state->Reg[BITS (12, 15)] = Rm;
        else
        else
          /* SXTAH */
          /* SXTAH */
          state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
          state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
      }
      }
      return 1;
      return 1;
 
 
    case 0x6e:
    case 0x6e:
      {
      {
        ARMword Rm;
        ARMword Rm;
        int ror = -1;
        int ror = -1;
 
 
        switch (BITS (4, 11))
        switch (BITS (4, 11))
          {
          {
          case 0x07: ror = 0; break;
          case 0x07: ror = 0; break;
          case 0x47: ror = 8; break;
          case 0x47: ror = 8; break;
          case 0x87: ror = 16; break;
          case 0x87: ror = 16; break;
          case 0xc7: ror = 24; break;
          case 0xc7: ror = 24; break;
 
 
          case 0x01:
          case 0x01:
          case 0xf3:
          case 0xf3:
            printf ("Unhandled v6 insn: usat\n");
            printf ("Unhandled v6 insn: usat\n");
            return 0;
            return 0;
          default:
          default:
            break;
            break;
          }
          }
 
 
        if (ror == -1)
        if (ror == -1)
          {
          {
            if (BITS (4, 6) == 0x7)
            if (BITS (4, 6) == 0x7)
              {
              {
                printf ("Unhandled v6 insn: usat\n");
                printf ("Unhandled v6 insn: usat\n");
                return 0;
                return 0;
              }
              }
            break;
            break;
          }
          }
 
 
        Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
        Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
 
 
        if (BITS (16, 19) == 0xf)
        if (BITS (16, 19) == 0xf)
           /* UXTB */
           /* UXTB */
          state->Reg[BITS (12, 15)] = Rm;
          state->Reg[BITS (12, 15)] = Rm;
        else
        else
          /* UXTAB */
          /* UXTAB */
          state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
          state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
      }
      }
      return 1;
      return 1;
 
 
    case 0x6f:
    case 0x6f:
      {
      {
        ARMword Rm;
        ARMword Rm;
        int ror = -1;
        int ror = -1;
 
 
        switch (BITS (4, 11))
        switch (BITS (4, 11))
          {
          {
          case 0x07: ror = 0; break;
          case 0x07: ror = 0; break;
          case 0x47: ror = 8; break;
          case 0x47: ror = 8; break;
          case 0x87: ror = 16; break;
          case 0x87: ror = 16; break;
          case 0xc7: ror = 24; break;
          case 0xc7: ror = 24; break;
 
 
          case 0xfb:
          case 0xfb:
            printf ("Unhandled v6 insn: revsh\n");
            printf ("Unhandled v6 insn: revsh\n");
            return 0;
            return 0;
          default:
          default:
            break;
            break;
          }
          }
 
 
        if (ror == -1)
        if (ror == -1)
          break;
          break;
 
 
        Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
        Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
 
 
        if (BITS (16, 19) == 0xf)
        if (BITS (16, 19) == 0xf)
          /* UXT */
          /* UXT */
          state->Reg[BITS (12, 15)] = Rm;
          state->Reg[BITS (12, 15)] = Rm;
        else
        else
          {
          {
            /* UXTAH */
            /* UXTAH */
            state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm;
            state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm;
          }
          }
        }
        }
      return 1;
      return 1;
 
 
#if 0
#if 0
    case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
    case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
#endif
#endif
    default:
    default:
      break;
      break;
    }
    }
  printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr);
  printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr);
  return 0;
  return 0;
}
}
 
 
/* EMULATION of ARM6.  */
/* EMULATION of ARM6.  */
 
 
/* The PC pipeline value depends on whether ARM
/* The PC pipeline value depends on whether ARM
   or Thumb instructions are being executed.  */
   or Thumb instructions are being executed.  */
ARMword isize;
ARMword isize;
 
 
ARMword
ARMword
#ifdef MODE32
#ifdef MODE32
ARMul_Emulate32 (ARMul_State * state)
ARMul_Emulate32 (ARMul_State * state)
#else
#else
ARMul_Emulate26 (ARMul_State * state)
ARMul_Emulate26 (ARMul_State * state)
#endif
#endif
{
{
  ARMword instr;        /* The current instruction.  */
  ARMword instr;        /* The current instruction.  */
  ARMword dest = 0;      /* Almost the DestBus.  */
  ARMword dest = 0;      /* Almost the DestBus.  */
  ARMword temp;         /* Ubiquitous third hand.  */
  ARMword temp;         /* Ubiquitous third hand.  */
  ARMword pc = 0;        /* The address of the current instruction.  */
  ARMword pc = 0;        /* The address of the current instruction.  */
  ARMword lhs;          /* Almost the ABus and BBus.  */
  ARMword lhs;          /* Almost the ABus and BBus.  */
  ARMword rhs;
  ARMword rhs;
  ARMword decoded = 0;   /* Instruction pipeline.  */
  ARMword decoded = 0;   /* Instruction pipeline.  */
  ARMword loaded = 0;
  ARMword loaded = 0;
 
 
  /* Execute the next instruction.  */
  /* Execute the next instruction.  */
 
 
  if (state->NextInstr < PRIMEPIPE)
  if (state->NextInstr < PRIMEPIPE)
    {
    {
      decoded = state->decoded;
      decoded = state->decoded;
      loaded = state->loaded;
      loaded = state->loaded;
      pc = state->pc;
      pc = state->pc;
    }
    }
 
 
  do
  do
    {
    {
      /* Just keep going.  */
      /* Just keep going.  */
      isize = INSN_SIZE;
      isize = INSN_SIZE;
 
 
      switch (state->NextInstr)
      switch (state->NextInstr)
        {
        {
        case SEQ:
        case SEQ:
          /* Advance the pipeline, and an S cycle.  */
          /* Advance the pipeline, and an S cycle.  */
          state->Reg[15] += isize;
          state->Reg[15] += isize;
          pc += isize;
          pc += isize;
          instr = decoded;
          instr = decoded;
          decoded = loaded;
          decoded = loaded;
          loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
          loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
          break;
          break;
 
 
        case NONSEQ:
        case NONSEQ:
          /* Advance the pipeline, and an N cycle.  */
          /* Advance the pipeline, and an N cycle.  */
          state->Reg[15] += isize;
          state->Reg[15] += isize;
          pc += isize;
          pc += isize;
          instr = decoded;
          instr = decoded;
          decoded = loaded;
          decoded = loaded;
          loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
          loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
          NORMALCYCLE;
          NORMALCYCLE;
          break;
          break;
 
 
        case PCINCEDSEQ:
        case PCINCEDSEQ:
          /* Program counter advanced, and an S cycle.  */
          /* Program counter advanced, and an S cycle.  */
          pc += isize;
          pc += isize;
          instr = decoded;
          instr = decoded;
          decoded = loaded;
          decoded = loaded;
          loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
          loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
          NORMALCYCLE;
          NORMALCYCLE;
          break;
          break;
 
 
        case PCINCEDNONSEQ:
        case PCINCEDNONSEQ:
          /* Program counter advanced, and an N cycle.  */
          /* Program counter advanced, and an N cycle.  */
          pc += isize;
          pc += isize;
          instr = decoded;
          instr = decoded;
          decoded = loaded;
          decoded = loaded;
          loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
          loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize);
          NORMALCYCLE;
          NORMALCYCLE;
          break;
          break;
 
 
        case RESUME:
        case RESUME:
          /* The program counter has been changed.  */
          /* The program counter has been changed.  */
          pc = state->Reg[15];
          pc = state->Reg[15];
#ifndef MODE32
#ifndef MODE32
          pc = pc & R15PCBITS;
          pc = pc & R15PCBITS;
#endif
#endif
          state->Reg[15] = pc + (isize * 2);
          state->Reg[15] = pc + (isize * 2);
          state->Aborted = 0;
          state->Aborted = 0;
          instr   = ARMul_ReLoadInstr (state, pc, isize);
          instr   = ARMul_ReLoadInstr (state, pc, isize);
          decoded = ARMul_ReLoadInstr (state, pc + isize, isize);
          decoded = ARMul_ReLoadInstr (state, pc + isize, isize);
          loaded  = ARMul_ReLoadInstr (state, pc + isize * 2, isize);
          loaded  = ARMul_ReLoadInstr (state, pc + isize * 2, isize);
          NORMALCYCLE;
          NORMALCYCLE;
          break;
          break;
 
 
        default:
        default:
          /* The program counter has been changed.  */
          /* The program counter has been changed.  */
          pc = state->Reg[15];
          pc = state->Reg[15];
#ifndef MODE32
#ifndef MODE32
          pc = pc & R15PCBITS;
          pc = pc & R15PCBITS;
#endif
#endif
          state->Reg[15] = pc + (isize * 2);
          state->Reg[15] = pc + (isize * 2);
          state->Aborted = 0;
          state->Aborted = 0;
          instr   = ARMul_LoadInstrN (state, pc, isize);
          instr   = ARMul_LoadInstrN (state, pc, isize);
          decoded = ARMul_LoadInstrS (state, pc + (isize), isize);
          decoded = ARMul_LoadInstrS (state, pc + (isize), isize);
          loaded  = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
          loaded  = ARMul_LoadInstrS (state, pc + (isize * 2), isize);
          NORMALCYCLE;
          NORMALCYCLE;
          break;
          break;
        }
        }
 
 
      if (state->EventSet)
      if (state->EventSet)
        ARMul_EnvokeEvent (state);
        ARMul_EnvokeEvent (state);
#if 0 /* Enable this for a helpful bit of debugging when tracing is needed.  */
#if 0 /* Enable this for a helpful bit of debugging when tracing is needed.  */
      fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr);
      fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr);
      if (instr == 0)
      if (instr == 0)
        abort ();
        abort ();
#endif
#endif
#if 0 /* Enable this code to help track down stack alignment bugs.  */
#if 0 /* Enable this code to help track down stack alignment bugs.  */
      {
      {
        static ARMword old_sp = -1;
        static ARMword old_sp = -1;
 
 
        if (old_sp != state->Reg[13])
        if (old_sp != state->Reg[13])
          {
          {
            old_sp = state->Reg[13];
            old_sp = state->Reg[13];
            fprintf (stderr, "pc: %08x: SP set to %08x%s\n",
            fprintf (stderr, "pc: %08x: SP set to %08x%s\n",
                     pc & ~1, old_sp, (old_sp % 8) ? " [UNALIGNED!]" : "");
                     pc & ~1, old_sp, (old_sp % 8) ? " [UNALIGNED!]" : "");
          }
          }
      }
      }
#endif
#endif
 
 
      if (state->Exception)
      if (state->Exception)
        {
        {
          /* Any exceptions ?  */
          /* Any exceptions ?  */
          if (state->NresetSig == LOW)
          if (state->NresetSig == LOW)
            {
            {
              ARMul_Abort (state, ARMul_ResetV);
              ARMul_Abort (state, ARMul_ResetV);
              break;
              break;
            }
            }
          else if (!state->NfiqSig && !FFLAG)
          else if (!state->NfiqSig && !FFLAG)
            {
            {
              ARMul_Abort (state, ARMul_FIQV);
              ARMul_Abort (state, ARMul_FIQV);
              break;
              break;
            }
            }
          else if (!state->NirqSig && !IFLAG)
          else if (!state->NirqSig && !IFLAG)
            {
            {
              ARMul_Abort (state, ARMul_IRQV);
              ARMul_Abort (state, ARMul_IRQV);
              break;
              break;
            }
            }
        }
        }
 
 
      if (state->CallDebug > 0)
      if (state->CallDebug > 0)
        {
        {
          instr = ARMul_Debug (state, pc, instr);
          instr = ARMul_Debug (state, pc, instr);
          if (state->Emulate < ONCE)
          if (state->Emulate < ONCE)
            {
            {
              state->NextInstr = RESUME;
              state->NextInstr = RESUME;
              break;
              break;
            }
            }
          if (state->Debug)
          if (state->Debug)
            {
            {
              fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n", pc, instr,
              fprintf (stderr, "sim: At %08lx Instr %08lx Mode %02lx\n", pc, instr,
                       state->Mode);
                       state->Mode);
              (void) fgetc (stdin);
              (void) fgetc (stdin);
            }
            }
        }
        }
      else if (state->Emulate < ONCE)
      else if (state->Emulate < ONCE)
        {
        {
          state->NextInstr = RESUME;
          state->NextInstr = RESUME;
          break;
          break;
        }
        }
 
 
      state->NumInstrs++;
      state->NumInstrs++;
 
 
#ifdef MODET
#ifdef MODET
      /* Provide Thumb instruction decoding. If the processor is in Thumb
      /* Provide Thumb instruction decoding. If the processor is in Thumb
         mode, then we can simply decode the Thumb instruction, and map it
         mode, then we can simply decode the Thumb instruction, and map it
         to the corresponding ARM instruction (by directly loading the
         to the corresponding ARM instruction (by directly loading the
         instr variable, and letting the normal ARM simulator
         instr variable, and letting the normal ARM simulator
         execute). There are some caveats to ensure that the correct
         execute). There are some caveats to ensure that the correct
         pipelined PC value is used when executing Thumb code, and also for
         pipelined PC value is used when executing Thumb code, and also for
         dealing with the BL instruction.  */
         dealing with the BL instruction.  */
      if (TFLAG)
      if (TFLAG)
        {
        {
          ARMword new;
          ARMword new;
 
 
          /* Check if in Thumb mode.  */
          /* Check if in Thumb mode.  */
          switch (ARMul_ThumbDecode (state, pc, instr, &new))
          switch (ARMul_ThumbDecode (state, pc, instr, &new))
            {
            {
            case t_undefined:
            case t_undefined:
              /* This is a Thumb instruction.  */
              /* This is a Thumb instruction.  */
              ARMul_UndefInstr (state, instr);
              ARMul_UndefInstr (state, instr);
              goto donext;
              goto donext;
 
 
            case t_branch:
            case t_branch:
              /* Already processed.  */
              /* Already processed.  */
              goto donext;
              goto donext;
 
 
            case t_decoded:
            case t_decoded:
              /* ARM instruction available.  */
              /* ARM instruction available.  */
              instr = new;
              instr = new;
              /* So continue instruction decoding.  */
              /* So continue instruction decoding.  */
              break;
              break;
            default:
            default:
              break;
              break;
            }
            }
        }
        }
#endif
#endif
 
 
      /* Check the condition codes.  */
      /* Check the condition codes.  */
      if ((temp = TOPBITS (28)) == AL)
      if ((temp = TOPBITS (28)) == AL)
        /* Vile deed in the need for speed.  */
        /* Vile deed in the need for speed.  */
        goto mainswitch;
        goto mainswitch;
 
 
      /* Check the condition code.  */
      /* Check the condition code.  */
      switch ((int) TOPBITS (28))
      switch ((int) TOPBITS (28))
        {
        {
        case AL:
        case AL:
          temp = TRUE;
          temp = TRUE;
          break;
          break;
        case NV:
        case NV:
          if (state->is_v5)
          if (state->is_v5)
            {
            {
              if (BITS (25, 27) == 5) /* BLX(1) */
              if (BITS (25, 27) == 5) /* BLX(1) */
                {
                {
                  ARMword dest;
                  ARMword dest;
 
 
                  state->Reg[14] = pc + 4;
                  state->Reg[14] = pc + 4;
 
 
                  /* Force entry into Thumb mode.  */
                  /* Force entry into Thumb mode.  */
                  dest = pc + 8 + 1;
                  dest = pc + 8 + 1;
                  if (BIT (23))
                  if (BIT (23))
                    dest += (NEGBRANCH + (BIT (24) << 1));
                    dest += (NEGBRANCH + (BIT (24) << 1));
                  else
                  else
                    dest += POSBRANCH + (BIT (24) << 1);
                    dest += POSBRANCH + (BIT (24) << 1);
 
 
                  WriteR15Branch (state, dest);
                  WriteR15Branch (state, dest);
                  goto donext;
                  goto donext;
                }
                }
              else if ((instr & 0xFC70F000) == 0xF450F000)
              else if ((instr & 0xFC70F000) == 0xF450F000)
                /* The PLD instruction.  Ignored.  */
                /* The PLD instruction.  Ignored.  */
                goto donext;
                goto donext;
              else if (   ((instr & 0xfe500f00) == 0xfc100100)
              else if (   ((instr & 0xfe500f00) == 0xfc100100)
                       || ((instr & 0xfe500f00) == 0xfc000100))
                       || ((instr & 0xfe500f00) == 0xfc000100))
                /* wldrw and wstrw are unconditional.  */
                /* wldrw and wstrw are unconditional.  */
                goto mainswitch;
                goto mainswitch;
              else
              else
                /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2.  */
                /* UNDEFINED in v5, UNPREDICTABLE in v3, v4, non executed in v1, v2.  */
                ARMul_UndefInstr (state, instr);
                ARMul_UndefInstr (state, instr);
            }
            }
          temp = FALSE;
          temp = FALSE;
          break;
          break;
        case EQ:
        case EQ:
          temp = ZFLAG;
          temp = ZFLAG;
          break;
          break;
        case NE:
        case NE:
          temp = !ZFLAG;
          temp = !ZFLAG;
          break;
          break;
        case VS:
        case VS:
          temp = VFLAG;
          temp = VFLAG;
          break;
          break;
        case VC:
        case VC:
          temp = !VFLAG;
          temp = !VFLAG;
          break;
          break;
        case MI:
        case MI:
          temp = NFLAG;
          temp = NFLAG;
          break;
          break;
        case PL:
        case PL:
          temp = !NFLAG;
          temp = !NFLAG;
          break;
          break;
        case CS:
        case CS:
          temp = CFLAG;
          temp = CFLAG;
          break;
          break;
        case CC:
        case CC:
          temp = !CFLAG;
          temp = !CFLAG;
          break;
          break;
        case HI:
        case HI:
          temp = (CFLAG && !ZFLAG);
          temp = (CFLAG && !ZFLAG);
          break;
          break;
        case LS:
        case LS:
          temp = (!CFLAG || ZFLAG);
          temp = (!CFLAG || ZFLAG);
          break;
          break;
        case GE:
        case GE:
          temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
          temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
          break;
          break;
        case LT:
        case LT:
          temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
          temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
          break;
          break;
        case GT:
        case GT:
          temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
          temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
          break;
          break;
        case LE:
        case LE:
          temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
          temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
          break;
          break;
        }                       /* cc check */
        }                       /* cc check */
 
 
      /* Handle the Clock counter here.  */
      /* Handle the Clock counter here.  */
      if (state->is_XScale)
      if (state->is_XScale)
        {
        {
          ARMword cp14r0;
          ARMword cp14r0;
          int ok;
          int ok;
 
 
          ok = state->CPRead[14] (state, 0, & cp14r0);
          ok = state->CPRead[14] (state, 0, & cp14r0);
 
 
          if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE))
          if (ok && (cp14r0 & ARMul_CP14_R0_ENABLE))
            {
            {
              unsigned long newcycles, nowtime = ARMul_Time (state);
              unsigned long newcycles, nowtime = ARMul_Time (state);
 
 
              newcycles = nowtime - state->LastTime;
              newcycles = nowtime - state->LastTime;
              state->LastTime = nowtime;
              state->LastTime = nowtime;
 
 
              if (cp14r0 & ARMul_CP14_R0_CCD)
              if (cp14r0 & ARMul_CP14_R0_CCD)
                {
                {
                  if (state->CP14R0_CCD == -1)
                  if (state->CP14R0_CCD == -1)
                    state->CP14R0_CCD = newcycles;
                    state->CP14R0_CCD = newcycles;
                  else
                  else
                    state->CP14R0_CCD += newcycles;
                    state->CP14R0_CCD += newcycles;
 
 
                  if (state->CP14R0_CCD >= 64)
                  if (state->CP14R0_CCD >= 64)
                    {
                    {
                      newcycles = 0;
                      newcycles = 0;
 
 
                      while (state->CP14R0_CCD >= 64)
                      while (state->CP14R0_CCD >= 64)
                        state->CP14R0_CCD -= 64, newcycles++;
                        state->CP14R0_CCD -= 64, newcycles++;
 
 
                      goto check_PMUintr;
                      goto check_PMUintr;
                    }
                    }
                }
                }
              else
              else
                {
                {
                  ARMword cp14r1;
                  ARMword cp14r1;
                  int do_int = 0;
                  int do_int = 0;
 
 
                  state->CP14R0_CCD = -1;
                  state->CP14R0_CCD = -1;
check_PMUintr:
check_PMUintr:
                  cp14r0 |= ARMul_CP14_R0_FLAG2;
                  cp14r0 |= ARMul_CP14_R0_FLAG2;
                  (void) state->CPWrite[14] (state, 0, cp14r0);
                  (void) state->CPWrite[14] (state, 0, cp14r0);
 
 
                  ok = state->CPRead[14] (state, 1, & cp14r1);
                  ok = state->CPRead[14] (state, 1, & cp14r1);
 
 
                  /* Coded like this for portability.  */
                  /* Coded like this for portability.  */
                  while (ok && newcycles)
                  while (ok && newcycles)
                    {
                    {
                      if (cp14r1 == 0xffffffff)
                      if (cp14r1 == 0xffffffff)
                        {
                        {
                          cp14r1 = 0;
                          cp14r1 = 0;
                          do_int = 1;
                          do_int = 1;
                        }
                        }
                      else
                      else
                        cp14r1 ++;
                        cp14r1 ++;
 
 
                      newcycles --;
                      newcycles --;
                    }
                    }
 
 
                  (void) state->CPWrite[14] (state, 1, cp14r1);
                  (void) state->CPWrite[14] (state, 1, cp14r1);
 
 
                  if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2))
                  if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2))
                    {
                    {
                      ARMword temp;
                      ARMword temp;
 
 
                      if (state->CPRead[13] (state, 8, & temp)
                      if (state->CPRead[13] (state, 8, & temp)
                          && (temp & ARMul_CP13_R8_PMUS))
                          && (temp & ARMul_CP13_R8_PMUS))
                        ARMul_Abort (state, ARMul_FIQV);
                        ARMul_Abort (state, ARMul_FIQV);
                      else
                      else
                        ARMul_Abort (state, ARMul_IRQV);
                        ARMul_Abort (state, ARMul_IRQV);
                    }
                    }
                }
                }
            }
            }
        }
        }
 
 
      /* Handle hardware instructions breakpoints here.  */
      /* Handle hardware instructions breakpoints here.  */
      if (state->is_XScale)
      if (state->is_XScale)
        {
        {
          if (   (pc | 3) == (read_cp15_reg (14, 0, 8) | 2)
          if (   (pc | 3) == (read_cp15_reg (14, 0, 8) | 2)
              || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2))
              || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2))
            {
            {
              if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB))
              if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB))
                ARMul_OSHandleSWI (state, SWI_Breakpoint);
                ARMul_OSHandleSWI (state, SWI_Breakpoint);
            }
            }
        }
        }
 
 
      /* Actual execution of instructions begins here.  */
      /* Actual execution of instructions begins here.  */
      /* If the condition codes don't match, stop here.  */
      /* If the condition codes don't match, stop here.  */
      if (temp)
      if (temp)
        {
        {
        mainswitch:
        mainswitch:
 
 
          if (state->is_XScale)
          if (state->is_XScale)
            {
            {
              if (BIT (20) == 0 && BITS (25, 27) == 0)
              if (BIT (20) == 0 && BITS (25, 27) == 0)
                {
                {
                  if (BITS (4, 7) == 0xD)
                  if (BITS (4, 7) == 0xD)
                    {
                    {
                      /* XScale Load Consecutive insn.  */
                      /* XScale Load Consecutive insn.  */
                      ARMword temp = GetLS7RHS (state, instr);
                      ARMword temp = GetLS7RHS (state, instr);
                      ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
                      ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
                      ARMword addr = BIT (24) ? temp2 : LHS;
                      ARMword addr = BIT (24) ? temp2 : LHS;
 
 
                      if (BIT (12))
                      if (BIT (12))
                        ARMul_UndefInstr (state, instr);
                        ARMul_UndefInstr (state, instr);
                      else if (addr & 7)
                      else if (addr & 7)
                        /* Alignment violation.  */
                        /* Alignment violation.  */
                        ARMul_Abort (state, ARMul_DataAbortV);
                        ARMul_Abort (state, ARMul_DataAbortV);
                      else
                      else
                        {
                        {
                          int wb = BIT (21) || (! BIT (24));
                          int wb = BIT (21) || (! BIT (24));
 
 
                          state->Reg[BITS (12, 15)] =
                          state->Reg[BITS (12, 15)] =
                            ARMul_LoadWordN (state, addr);
                            ARMul_LoadWordN (state, addr);
                          state->Reg[BITS (12, 15) + 1] =
                          state->Reg[BITS (12, 15) + 1] =
                            ARMul_LoadWordN (state, addr + 4);
                            ARMul_LoadWordN (state, addr + 4);
                          if (wb)
                          if (wb)
                            LSBase = temp2;
                            LSBase = temp2;
                        }
                        }
 
 
                      goto donext;
                      goto donext;
                    }
                    }
                  else if (BITS (4, 7) == 0xF)
                  else if (BITS (4, 7) == 0xF)
                    {
                    {
                      /* XScale Store Consecutive insn.  */
                      /* XScale Store Consecutive insn.  */
                      ARMword temp = GetLS7RHS (state, instr);
                      ARMword temp = GetLS7RHS (state, instr);
                      ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
                      ARMword temp2 = BIT (23) ? LHS + temp : LHS - temp;
                      ARMword addr = BIT (24) ? temp2 : LHS;
                      ARMword addr = BIT (24) ? temp2 : LHS;
 
 
                      if (BIT (12))
                      if (BIT (12))
                        ARMul_UndefInstr (state, instr);
                        ARMul_UndefInstr (state, instr);
                      else if (addr & 7)
                      else if (addr & 7)
                        /* Alignment violation.  */
                        /* Alignment violation.  */
                        ARMul_Abort (state, ARMul_DataAbortV);
                        ARMul_Abort (state, ARMul_DataAbortV);
                      else
                      else
                        {
                        {
                          ARMul_StoreWordN (state, addr,
                          ARMul_StoreWordN (state, addr,
                                            state->Reg[BITS (12, 15)]);
                                            state->Reg[BITS (12, 15)]);
                          ARMul_StoreWordN (state, addr + 4,
                          ARMul_StoreWordN (state, addr + 4,
                                            state->Reg[BITS (12, 15) + 1]);
                                            state->Reg[BITS (12, 15) + 1]);
 
 
                          if (BIT (21)|| ! BIT (24))
                          if (BIT (21)|| ! BIT (24))
                            LSBase = temp2;
                            LSBase = temp2;
                        }
                        }
 
 
                      goto donext;
                      goto donext;
                    }
                    }
                }
                }
 
 
              if (ARMul_HandleIwmmxt (state, instr))
              if (ARMul_HandleIwmmxt (state, instr))
                goto donext;
                goto donext;
            }
            }
 
 
          switch ((int) BITS (20, 27))
          switch ((int) BITS (20, 27))
            {
            {
              /* Data Processing Register RHS Instructions.  */
              /* Data Processing Register RHS Instructions.  */
 
 
            case 0x00:          /* AND reg and MUL */
            case 0x00:          /* AND reg and MUL */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 11) == 0xB)
              if (BITS (4, 11) == 0xB)
                {
                {
                  /* STRH register offset, no write-back, down, post indexed.  */
                  /* STRH register offset, no write-back, down, post indexed.  */
                  SHDOWNWB ();
                  SHDOWNWB ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xF)
              if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
#endif
#endif
              if (BITS (4, 7) == 9)
              if (BITS (4, 7) == 9)
                {
                {
                  /* MUL */
                  /* MUL */
                  rhs = state->Reg[MULRHSReg];
                  rhs = state->Reg[MULRHSReg];
                  if (MULLHSReg == MULDESTReg)
                  if (MULLHSReg == MULDESTReg)
                    {
                    {
                      UNDEF_MULDestEQOp1;
                      UNDEF_MULDestEQOp1;
                      state->Reg[MULDESTReg] = 0;
                      state->Reg[MULDESTReg] = 0;
                    }
                    }
                  else if (MULDESTReg != 15)
                  else if (MULDESTReg != 15)
                    state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
                    state->Reg[MULDESTReg] = state->Reg[MULLHSReg] * rhs;
                  else
                  else
                    UNDEF_MULPCDest;
                    UNDEF_MULPCDest;
 
 
                  for (dest = 0, temp = 0; dest < 32; dest ++)
                  for (dest = 0, temp = 0; dest < 32; dest ++)
                    if (rhs & (1L << dest))
                    if (rhs & (1L << dest))
                      temp = dest;
                      temp = dest;
 
 
                  /* Mult takes this many/2 I cycles.  */
                  /* Mult takes this many/2 I cycles.  */
                  ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
                  ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
                }
                }
              else
              else
                {
                {
                  /* AND reg.  */
                  /* AND reg.  */
                  rhs = DPRegRHS;
                  rhs = DPRegRHS;
                  dest = LHS & rhs;
                  dest = LHS & rhs;
                  WRITEDEST (dest);
                  WRITEDEST (dest);
                }
                }
              break;
              break;
 
 
            case 0x01:          /* ANDS reg and MULS */
            case 0x01:          /* ANDS reg and MULS */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 11) & 0xF9) == 0x9)
              if ((BITS (4, 11) & 0xF9) == 0x9)
                /* LDR register offset, no write-back, down, post indexed.  */
                /* LDR register offset, no write-back, down, post indexed.  */
                LHPOSTDOWN ();
                LHPOSTDOWN ();
              /* Fall through to rest of decoding.  */
              /* Fall through to rest of decoding.  */
#endif
#endif
              if (BITS (4, 7) == 9)
              if (BITS (4, 7) == 9)
                {
                {
                  /* MULS */
                  /* MULS */
                  rhs = state->Reg[MULRHSReg];
                  rhs = state->Reg[MULRHSReg];
 
 
                  if (MULLHSReg == MULDESTReg)
                  if (MULLHSReg == MULDESTReg)
                    {
                    {
                      UNDEF_MULDestEQOp1;
                      UNDEF_MULDestEQOp1;
                      state->Reg[MULDESTReg] = 0;
                      state->Reg[MULDESTReg] = 0;
                      CLEARN;
                      CLEARN;
                      SETZ;
                      SETZ;
                    }
                    }
                  else if (MULDESTReg != 15)
                  else if (MULDESTReg != 15)
                    {
                    {
                      dest = state->Reg[MULLHSReg] * rhs;
                      dest = state->Reg[MULLHSReg] * rhs;
                      ARMul_NegZero (state, dest);
                      ARMul_NegZero (state, dest);
                      state->Reg[MULDESTReg] = dest;
                      state->Reg[MULDESTReg] = dest;
                    }
                    }
                  else
                  else
                    UNDEF_MULPCDest;
                    UNDEF_MULPCDest;
 
 
                  for (dest = 0, temp = 0; dest < 32; dest ++)
                  for (dest = 0, temp = 0; dest < 32; dest ++)
                    if (rhs & (1L << dest))
                    if (rhs & (1L << dest))
                      temp = dest;
                      temp = dest;
 
 
                  /* Mult takes this many/2 I cycles.  */
                  /* Mult takes this many/2 I cycles.  */
                  ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
                  ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
                }
                }
              else
              else
                {
                {
                  /* ANDS reg.  */
                  /* ANDS reg.  */
                  rhs = DPSRegRHS;
                  rhs = DPSRegRHS;
                  dest = LHS & rhs;
                  dest = LHS & rhs;
                  WRITESDEST (dest);
                  WRITESDEST (dest);
                }
                }
              break;
              break;
 
 
            case 0x02:          /* EOR reg and MLA */
            case 0x02:          /* EOR reg and MLA */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 11) == 0xB)
              if (BITS (4, 11) == 0xB)
                {
                {
                  /* STRH register offset, write-back, down, post indexed.  */
                  /* STRH register offset, write-back, down, post indexed.  */
                  SHDOWNWB ();
                  SHDOWNWB ();
                  break;
                  break;
                }
                }
#endif
#endif
              if (BITS (4, 7) == 9)
              if (BITS (4, 7) == 9)
                {               /* MLA */
                {               /* MLA */
                  rhs = state->Reg[MULRHSReg];
                  rhs = state->Reg[MULRHSReg];
                  if (MULLHSReg == MULDESTReg)
                  if (MULLHSReg == MULDESTReg)
                    {
                    {
                      UNDEF_MULDestEQOp1;
                      UNDEF_MULDestEQOp1;
                      state->Reg[MULDESTReg] = state->Reg[MULACCReg];
                      state->Reg[MULDESTReg] = state->Reg[MULACCReg];
                    }
                    }
                  else if (MULDESTReg != 15)
                  else if (MULDESTReg != 15)
                    state->Reg[MULDESTReg] =
                    state->Reg[MULDESTReg] =
                      state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
                      state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
                  else
                  else
                    UNDEF_MULPCDest;
                    UNDEF_MULPCDest;
 
 
                  for (dest = 0, temp = 0; dest < 32; dest ++)
                  for (dest = 0, temp = 0; dest < 32; dest ++)
                    if (rhs & (1L << dest))
                    if (rhs & (1L << dest))
                      temp = dest;
                      temp = dest;
 
 
                  /* Mult takes this many/2 I cycles.  */
                  /* Mult takes this many/2 I cycles.  */
                  ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
                  ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
                }
                }
              else
              else
                {
                {
                  rhs = DPRegRHS;
                  rhs = DPRegRHS;
                  dest = LHS ^ rhs;
                  dest = LHS ^ rhs;
                  WRITEDEST (dest);
                  WRITEDEST (dest);
                }
                }
              break;
              break;
 
 
            case 0x03:          /* EORS reg and MLAS */
            case 0x03:          /* EORS reg and MLAS */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 11) & 0xF9) == 0x9)
              if ((BITS (4, 11) & 0xF9) == 0x9)
                /* LDR register offset, write-back, down, post-indexed.  */
                /* LDR register offset, write-back, down, post-indexed.  */
                LHPOSTDOWN ();
                LHPOSTDOWN ();
              /* Fall through to rest of the decoding.  */
              /* Fall through to rest of the decoding.  */
#endif
#endif
              if (BITS (4, 7) == 9)
              if (BITS (4, 7) == 9)
                {
                {
                  /* MLAS */
                  /* MLAS */
                  rhs = state->Reg[MULRHSReg];
                  rhs = state->Reg[MULRHSReg];
 
 
                  if (MULLHSReg == MULDESTReg)
                  if (MULLHSReg == MULDESTReg)
                    {
                    {
                      UNDEF_MULDestEQOp1;
                      UNDEF_MULDestEQOp1;
                      dest = state->Reg[MULACCReg];
                      dest = state->Reg[MULACCReg];
                      ARMul_NegZero (state, dest);
                      ARMul_NegZero (state, dest);
                      state->Reg[MULDESTReg] = dest;
                      state->Reg[MULDESTReg] = dest;
                    }
                    }
                  else if (MULDESTReg != 15)
                  else if (MULDESTReg != 15)
                    {
                    {
                      dest =
                      dest =
                        state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
                        state->Reg[MULLHSReg] * rhs + state->Reg[MULACCReg];
                      ARMul_NegZero (state, dest);
                      ARMul_NegZero (state, dest);
                      state->Reg[MULDESTReg] = dest;
                      state->Reg[MULDESTReg] = dest;
                    }
                    }
                  else
                  else
                    UNDEF_MULPCDest;
                    UNDEF_MULPCDest;
 
 
                  for (dest = 0, temp = 0; dest < 32; dest ++)
                  for (dest = 0, temp = 0; dest < 32; dest ++)
                    if (rhs & (1L << dest))
                    if (rhs & (1L << dest))
                      temp = dest;
                      temp = dest;
 
 
                  /* Mult takes this many/2 I cycles.  */
                  /* Mult takes this many/2 I cycles.  */
                  ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
                  ARMul_Icycles (state, ARMul_MultTable[temp], 0L);
                }
                }
              else
              else
                {
                {
                  /* EORS Reg.  */
                  /* EORS Reg.  */
                  rhs = DPSRegRHS;
                  rhs = DPSRegRHS;
                  dest = LHS ^ rhs;
                  dest = LHS ^ rhs;
                  WRITESDEST (dest);
                  WRITESDEST (dest);
                }
                }
              break;
              break;
 
 
            case 0x04:          /* SUB reg */
            case 0x04:          /* SUB reg */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 7) == 0xB)
              if (BITS (4, 7) == 0xB)
                {
                {
                  /* STRH immediate offset, no write-back, down, post indexed.  */
                  /* STRH immediate offset, no write-back, down, post indexed.  */
                  SHDOWNWB ();
                  SHDOWNWB ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xF)
              if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
#endif
#endif
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = LHS - rhs;
              dest = LHS - rhs;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x05:          /* SUBS reg */
            case 0x05:          /* SUBS reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 7) & 0x9) == 0x9)
              if ((BITS (4, 7) & 0x9) == 0x9)
                /* LDR immediate offset, no write-back, down, post indexed.  */
                /* LDR immediate offset, no write-back, down, post indexed.  */
                LHPOSTDOWN ();
                LHPOSTDOWN ();
              /* Fall through to the rest of the instruction decoding.  */
              /* Fall through to the rest of the instruction decoding.  */
#endif
#endif
              lhs = LHS;
              lhs = LHS;
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = lhs - rhs;
              dest = lhs - rhs;
 
 
              if ((lhs >= rhs) || ((rhs | lhs) >> 31))
              if ((lhs >= rhs) || ((rhs | lhs) >> 31))
                {
                {
                  ARMul_SubCarry (state, lhs, rhs, dest);
                  ARMul_SubCarry (state, lhs, rhs, dest);
                  ARMul_SubOverflow (state, lhs, rhs, dest);
                  ARMul_SubOverflow (state, lhs, rhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x06:          /* RSB reg */
            case 0x06:          /* RSB reg */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 7) == 0xB)
              if (BITS (4, 7) == 0xB)
                {
                {
                  /* STRH immediate offset, write-back, down, post indexed.  */
                  /* STRH immediate offset, write-back, down, post indexed.  */
                  SHDOWNWB ();
                  SHDOWNWB ();
                  break;
                  break;
                }
                }
#endif
#endif
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = rhs - LHS;
              dest = rhs - LHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x07:          /* RSBS reg */
            case 0x07:          /* RSBS reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 7) & 0x9) == 0x9)
              if ((BITS (4, 7) & 0x9) == 0x9)
                /* LDR immediate offset, write-back, down, post indexed.  */
                /* LDR immediate offset, write-back, down, post indexed.  */
                LHPOSTDOWN ();
                LHPOSTDOWN ();
              /* Fall through to remainder of instruction decoding.  */
              /* Fall through to remainder of instruction decoding.  */
#endif
#endif
              lhs = LHS;
              lhs = LHS;
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = rhs - lhs;
              dest = rhs - lhs;
 
 
              if ((rhs >= lhs) || ((rhs | lhs) >> 31))
              if ((rhs >= lhs) || ((rhs | lhs) >> 31))
                {
                {
                  ARMul_SubCarry (state, rhs, lhs, dest);
                  ARMul_SubCarry (state, rhs, lhs, dest);
                  ARMul_SubOverflow (state, rhs, lhs, dest);
                  ARMul_SubOverflow (state, rhs, lhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x08:          /* ADD reg */
            case 0x08:          /* ADD reg */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 11) == 0xB)
              if (BITS (4, 11) == 0xB)
                {
                {
                  /* STRH register offset, no write-back, up, post indexed.  */
                  /* STRH register offset, no write-back, up, post indexed.  */
                  SHUPWB ();
                  SHUPWB ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xF)
              if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
#endif
#endif
#ifdef MODET
#ifdef MODET
              if (BITS (4, 7) == 0x9)
              if (BITS (4, 7) == 0x9)
                {
                {
                  /* MULL */
                  /* MULL */
                  /* 32x32 = 64 */
                  /* 32x32 = 64 */
                  ARMul_Icycles (state,
                  ARMul_Icycles (state,
                                 Multiply64 (state, instr, LUNSIGNED,
                                 Multiply64 (state, instr, LUNSIGNED,
                                             LDEFAULT), 0L);
                                             LDEFAULT), 0L);
                  break;
                  break;
                }
                }
#endif
#endif
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = LHS + rhs;
              dest = LHS + rhs;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x09:          /* ADDS reg */
            case 0x09:          /* ADDS reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 11) & 0xF9) == 0x9)
              if ((BITS (4, 11) & 0xF9) == 0x9)
                /* LDR register offset, no write-back, up, post indexed.  */
                /* LDR register offset, no write-back, up, post indexed.  */
                LHPOSTUP ();
                LHPOSTUP ();
              /* Fall through to remaining instruction decoding.  */
              /* Fall through to remaining instruction decoding.  */
#endif
#endif
#ifdef MODET
#ifdef MODET
              if (BITS (4, 7) == 0x9)
              if (BITS (4, 7) == 0x9)
                {
                {
                  /* MULL */
                  /* MULL */
                  /* 32x32=64 */
                  /* 32x32=64 */
                  ARMul_Icycles (state,
                  ARMul_Icycles (state,
                                 Multiply64 (state, instr, LUNSIGNED, LSCC),
                                 Multiply64 (state, instr, LUNSIGNED, LSCC),
                                 0L);
                                 0L);
                  break;
                  break;
                }
                }
#endif
#endif
              lhs = LHS;
              lhs = LHS;
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = lhs + rhs;
              dest = lhs + rhs;
              ASSIGNZ (dest == 0);
              ASSIGNZ (dest == 0);
              if ((lhs | rhs) >> 30)
              if ((lhs | rhs) >> 30)
                {
                {
                  /* Possible C,V,N to set.  */
                  /* Possible C,V,N to set.  */
                  ASSIGNN (NEG (dest));
                  ASSIGNN (NEG (dest));
                  ARMul_AddCarry (state, lhs, rhs, dest);
                  ARMul_AddCarry (state, lhs, rhs, dest);
                  ARMul_AddOverflow (state, lhs, rhs, dest);
                  ARMul_AddOverflow (state, lhs, rhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARN;
                  CLEARN;
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x0a:          /* ADC reg */
            case 0x0a:          /* ADC reg */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 11) == 0xB)
              if (BITS (4, 11) == 0xB)
                {
                {
                  /* STRH register offset, write-back, up, post-indexed.  */
                  /* STRH register offset, write-back, up, post-indexed.  */
                  SHUPWB ();
                  SHUPWB ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0x9)
              if (BITS (4, 7) == 0x9)
                {
                {
                  /* MULL */
                  /* MULL */
                  /* 32x32=64 */
                  /* 32x32=64 */
                  ARMul_Icycles (state,
                  ARMul_Icycles (state,
                                 MultiplyAdd64 (state, instr, LUNSIGNED,
                                 MultiplyAdd64 (state, instr, LUNSIGNED,
                                                LDEFAULT), 0L);
                                                LDEFAULT), 0L);
                  break;
                  break;
                }
                }
#endif
#endif
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = LHS + rhs + CFLAG;
              dest = LHS + rhs + CFLAG;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x0b:          /* ADCS reg */
            case 0x0b:          /* ADCS reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 11) & 0xF9) == 0x9)
              if ((BITS (4, 11) & 0xF9) == 0x9)
                /* LDR register offset, write-back, up, post indexed.  */
                /* LDR register offset, write-back, up, post indexed.  */
                LHPOSTUP ();
                LHPOSTUP ();
              /* Fall through to remaining instruction decoding.  */
              /* Fall through to remaining instruction decoding.  */
              if (BITS (4, 7) == 0x9)
              if (BITS (4, 7) == 0x9)
                {
                {
                  /* MULL */
                  /* MULL */
                  /* 32x32=64 */
                  /* 32x32=64 */
                  ARMul_Icycles (state,
                  ARMul_Icycles (state,
                                 MultiplyAdd64 (state, instr, LUNSIGNED,
                                 MultiplyAdd64 (state, instr, LUNSIGNED,
                                                LSCC), 0L);
                                                LSCC), 0L);
                  break;
                  break;
                }
                }
#endif
#endif
              lhs = LHS;
              lhs = LHS;
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = lhs + rhs + CFLAG;
              dest = lhs + rhs + CFLAG;
              ASSIGNZ (dest == 0);
              ASSIGNZ (dest == 0);
              if ((lhs | rhs) >> 30)
              if ((lhs | rhs) >> 30)
                {
                {
                  /* Possible C,V,N to set.  */
                  /* Possible C,V,N to set.  */
                  ASSIGNN (NEG (dest));
                  ASSIGNN (NEG (dest));
                  ARMul_AddCarry (state, lhs, rhs, dest);
                  ARMul_AddCarry (state, lhs, rhs, dest);
                  ARMul_AddOverflow (state, lhs, rhs, dest);
                  ARMul_AddOverflow (state, lhs, rhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARN;
                  CLEARN;
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x0c:          /* SBC reg */
            case 0x0c:          /* SBC reg */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 7) == 0xB)
              if (BITS (4, 7) == 0xB)
                {
                {
                  /* STRH immediate offset, no write-back, up post indexed.  */
                  /* STRH immediate offset, no write-back, up post indexed.  */
                  SHUPWB ();
                  SHUPWB ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xF)
              if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0x9)
              if (BITS (4, 7) == 0x9)
                {
                {
                  /* MULL */
                  /* MULL */
                  /* 32x32=64 */
                  /* 32x32=64 */
                  ARMul_Icycles (state,
                  ARMul_Icycles (state,
                                 Multiply64 (state, instr, LSIGNED, LDEFAULT),
                                 Multiply64 (state, instr, LSIGNED, LDEFAULT),
                                 0L);
                                 0L);
                  break;
                  break;
                }
                }
#endif
#endif
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = LHS - rhs - !CFLAG;
              dest = LHS - rhs - !CFLAG;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x0d:          /* SBCS reg */
            case 0x0d:          /* SBCS reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 7) & 0x9) == 0x9)
              if ((BITS (4, 7) & 0x9) == 0x9)
                /* LDR immediate offset, no write-back, up, post indexed.  */
                /* LDR immediate offset, no write-back, up, post indexed.  */
                LHPOSTUP ();
                LHPOSTUP ();
 
 
              if (BITS (4, 7) == 0x9)
              if (BITS (4, 7) == 0x9)
                {
                {
                  /* MULL */
                  /* MULL */
                  /* 32x32=64 */
                  /* 32x32=64 */
                  ARMul_Icycles (state,
                  ARMul_Icycles (state,
                                 Multiply64 (state, instr, LSIGNED, LSCC),
                                 Multiply64 (state, instr, LSIGNED, LSCC),
                                 0L);
                                 0L);
                  break;
                  break;
                }
                }
#endif
#endif
              lhs = LHS;
              lhs = LHS;
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = lhs - rhs - !CFLAG;
              dest = lhs - rhs - !CFLAG;
              if ((lhs >= rhs) || ((rhs | lhs) >> 31))
              if ((lhs >= rhs) || ((rhs | lhs) >> 31))
                {
                {
                  ARMul_SubCarry (state, lhs, rhs, dest);
                  ARMul_SubCarry (state, lhs, rhs, dest);
                  ARMul_SubOverflow (state, lhs, rhs, dest);
                  ARMul_SubOverflow (state, lhs, rhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x0e:          /* RSC reg */
            case 0x0e:          /* RSC reg */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 7) == 0xB)
              if (BITS (4, 7) == 0xB)
                {
                {
                  /* STRH immediate offset, write-back, up, post indexed.  */
                  /* STRH immediate offset, write-back, up, post indexed.  */
                  SHUPWB ();
                  SHUPWB ();
                  break;
                  break;
                }
                }
 
 
              if (BITS (4, 7) == 0x9)
              if (BITS (4, 7) == 0x9)
                {
                {
                  /* MULL */
                  /* MULL */
                  /* 32x32=64 */
                  /* 32x32=64 */
                  ARMul_Icycles (state,
                  ARMul_Icycles (state,
                                 MultiplyAdd64 (state, instr, LSIGNED,
                                 MultiplyAdd64 (state, instr, LSIGNED,
                                                LDEFAULT), 0L);
                                                LDEFAULT), 0L);
                  break;
                  break;
                }
                }
#endif
#endif
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = rhs - LHS - !CFLAG;
              dest = rhs - LHS - !CFLAG;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x0f:          /* RSCS reg */
            case 0x0f:          /* RSCS reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 7) & 0x9) == 0x9)
              if ((BITS (4, 7) & 0x9) == 0x9)
                /* LDR immediate offset, write-back, up, post indexed.  */
                /* LDR immediate offset, write-back, up, post indexed.  */
                LHPOSTUP ();
                LHPOSTUP ();
              /* Fall through to remaining instruction decoding.  */
              /* Fall through to remaining instruction decoding.  */
 
 
              if (BITS (4, 7) == 0x9)
              if (BITS (4, 7) == 0x9)
                {
                {
                  /* MULL */
                  /* MULL */
                  /* 32x32=64 */
                  /* 32x32=64 */
                  ARMul_Icycles (state,
                  ARMul_Icycles (state,
                                 MultiplyAdd64 (state, instr, LSIGNED, LSCC),
                                 MultiplyAdd64 (state, instr, LSIGNED, LSCC),
                                 0L);
                                 0L);
                  break;
                  break;
                }
                }
#endif
#endif
              lhs = LHS;
              lhs = LHS;
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = rhs - lhs - !CFLAG;
              dest = rhs - lhs - !CFLAG;
 
 
              if ((rhs >= lhs) || ((rhs | lhs) >> 31))
              if ((rhs >= lhs) || ((rhs | lhs) >> 31))
                {
                {
                  ARMul_SubCarry (state, rhs, lhs, dest);
                  ARMul_SubCarry (state, rhs, lhs, dest);
                  ARMul_SubOverflow (state, rhs, lhs, dest);
                  ARMul_SubOverflow (state, rhs, lhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x10:          /* TST reg and MRS CPSR and SWP word.  */
            case 0x10:          /* TST reg and MRS CPSR and SWP word.  */
              if (state->is_v5e)
              if (state->is_v5e)
                {
                {
                  if (BIT (4) == 0 && BIT (7) == 1)
                  if (BIT (4) == 0 && BIT (7) == 1)
                    {
                    {
                      /* ElSegundo SMLAxy insn.  */
                      /* ElSegundo SMLAxy insn.  */
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op2 = state->Reg[BITS (8, 11)];
                      ARMword op2 = state->Reg[BITS (8, 11)];
                      ARMword Rn = state->Reg[BITS (12, 15)];
                      ARMword Rn = state->Reg[BITS (12, 15)];
 
 
                      if (BIT (5))
                      if (BIT (5))
                        op1 >>= 16;
                        op1 >>= 16;
                      if (BIT (6))
                      if (BIT (6))
                        op2 >>= 16;
                        op2 >>= 16;
                      op1 &= 0xFFFF;
                      op1 &= 0xFFFF;
                      op2 &= 0xFFFF;
                      op2 &= 0xFFFF;
                      if (op1 & 0x8000)
                      if (op1 & 0x8000)
                        op1 -= 65536;
                        op1 -= 65536;
                      if (op2 & 0x8000)
                      if (op2 & 0x8000)
                        op2 -= 65536;
                        op2 -= 65536;
                      op1 *= op2;
                      op1 *= op2;
 
 
                      if (AddOverflow (op1, Rn, op1 + Rn))
                      if (AddOverflow (op1, Rn, op1 + Rn))
                        SETS;
                        SETS;
                      state->Reg[BITS (16, 19)] = op1 + Rn;
                      state->Reg[BITS (16, 19)] = op1 + Rn;
                      break;
                      break;
                    }
                    }
 
 
                  if (BITS (4, 11) == 5)
                  if (BITS (4, 11) == 5)
                    {
                    {
                      /* ElSegundo QADD insn.  */
                      /* ElSegundo QADD insn.  */
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op2 = state->Reg[BITS (16, 19)];
                      ARMword op2 = state->Reg[BITS (16, 19)];
                      ARMword result = op1 + op2;
                      ARMword result = op1 + op2;
                      if (AddOverflow (op1, op2, result))
                      if (AddOverflow (op1, op2, result))
                        {
                        {
                          result = POS (result) ? 0x80000000 : 0x7fffffff;
                          result = POS (result) ? 0x80000000 : 0x7fffffff;
                          SETS;
                          SETS;
                        }
                        }
                      state->Reg[BITS (12, 15)] = result;
                      state->Reg[BITS (12, 15)] = result;
                      break;
                      break;
                    }
                    }
                }
                }
#ifdef MODET
#ifdef MODET
              if (BITS (4, 11) == 0xB)
              if (BITS (4, 11) == 0xB)
                {
                {
                  /* STRH register offset, no write-back, down, pre indexed.  */
                  /* STRH register offset, no write-back, down, pre indexed.  */
                  SHPREDOWN ();
                  SHPREDOWN ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xF)
              if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
#endif
#endif
              if (BITS (4, 11) == 9)
              if (BITS (4, 11) == 9)
                {
                {
                  /* SWP */
                  /* SWP */
                  UNDEF_SWPPC;
                  UNDEF_SWPPC;
                  temp = LHS;
                  temp = LHS;
                  BUSUSEDINCPCS;
                  BUSUSEDINCPCS;
#ifndef MODE32
#ifndef MODE32
                  if (VECTORACCESS (temp) || ADDREXCEPT (temp))
                  if (VECTORACCESS (temp) || ADDREXCEPT (temp))
                    {
                    {
                      INTERNALABORT (temp);
                      INTERNALABORT (temp);
                      (void) ARMul_LoadWordN (state, temp);
                      (void) ARMul_LoadWordN (state, temp);
                      (void) ARMul_LoadWordN (state, temp);
                      (void) ARMul_LoadWordN (state, temp);
                    }
                    }
                  else
                  else
#endif
#endif
                    dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
                    dest = ARMul_SwapWord (state, temp, state->Reg[RHSReg]);
                  if (temp & 3)
                  if (temp & 3)
                    DEST = ARMul_Align (state, temp, dest);
                    DEST = ARMul_Align (state, temp, dest);
                  else
                  else
                    DEST = dest;
                    DEST = dest;
                  if (state->abortSig || state->Aborted)
                  if (state->abortSig || state->Aborted)
                    TAKEABORT;
                    TAKEABORT;
                }
                }
              else if ((BITS (0, 11) == 0) && (LHSReg == 15))
              else if ((BITS (0, 11) == 0) && (LHSReg == 15))
                {               /* MRS CPSR */
                {               /* MRS CPSR */
                  UNDEF_MRSPC;
                  UNDEF_MRSPC;
                  DEST = ECC | EINT | EMODE;
                  DEST = ECC | EINT | EMODE;
                }
                }
              else
              else
                {
                {
                  UNDEF_Test;
                  UNDEF_Test;
                }
                }
              break;
              break;
 
 
            case 0x11:          /* TSTP reg */
            case 0x11:          /* TSTP reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 11) & 0xF9) == 0x9)
              if ((BITS (4, 11) & 0xF9) == 0x9)
                /* LDR register offset, no write-back, down, pre indexed.  */
                /* LDR register offset, no write-back, down, pre indexed.  */
                LHPREDOWN ();
                LHPREDOWN ();
              /* Continue with remaining instruction decode.  */
              /* Continue with remaining instruction decode.  */
#endif
#endif
              if (DESTReg == 15)
              if (DESTReg == 15)
                {
                {
                  /* TSTP reg */
                  /* TSTP reg */
#ifdef MODE32
#ifdef MODE32
                  state->Cpsr = GETSPSR (state->Bank);
                  state->Cpsr = GETSPSR (state->Bank);
                  ARMul_CPSRAltered (state);
                  ARMul_CPSRAltered (state);
#else
#else
                  rhs = DPRegRHS;
                  rhs = DPRegRHS;
                  temp = LHS & rhs;
                  temp = LHS & rhs;
                  SETR15PSR (temp);
                  SETR15PSR (temp);
#endif
#endif
                }
                }
              else
              else
                {
                {
                  /* TST reg */
                  /* TST reg */
                  rhs = DPSRegRHS;
                  rhs = DPSRegRHS;
                  dest = LHS & rhs;
                  dest = LHS & rhs;
                  ARMul_NegZero (state, dest);
                  ARMul_NegZero (state, dest);
                }
                }
              break;
              break;
 
 
            case 0x12:          /* TEQ reg and MSR reg to CPSR (ARM6).  */
            case 0x12:          /* TEQ reg and MSR reg to CPSR (ARM6).  */
              if (state->is_v5)
              if (state->is_v5)
                {
                {
                  if (BITS (4, 7) == 3)
                  if (BITS (4, 7) == 3)
                    {
                    {
                      /* BLX(2) */
                      /* BLX(2) */
                      ARMword temp;
                      ARMword temp;
 
 
                      if (TFLAG)
                      if (TFLAG)
                        temp = (pc + 2) | 1;
                        temp = (pc + 2) | 1;
                      else
                      else
                        temp = pc + 4;
                        temp = pc + 4;
 
 
                      WriteR15Branch (state, state->Reg[RHSReg]);
                      WriteR15Branch (state, state->Reg[RHSReg]);
                      state->Reg[14] = temp;
                      state->Reg[14] = temp;
                      break;
                      break;
                    }
                    }
                }
                }
 
 
              if (state->is_v5e)
              if (state->is_v5e)
                {
                {
                  if (BIT (4) == 0 && BIT (7) == 1
                  if (BIT (4) == 0 && BIT (7) == 1
                      && (BIT (5) == 0 || BITS (12, 15) == 0))
                      && (BIT (5) == 0 || BITS (12, 15) == 0))
                    {
                    {
                      /* ElSegundo SMLAWy/SMULWy insn.  */
                      /* ElSegundo SMLAWy/SMULWy insn.  */
                      ARMdword op1 = state->Reg[BITS (0, 3)];
                      ARMdword op1 = state->Reg[BITS (0, 3)];
                      ARMdword op2 = state->Reg[BITS (8, 11)];
                      ARMdword op2 = state->Reg[BITS (8, 11)];
                      ARMdword result;
                      ARMdword result;
 
 
                      if (BIT (6))
                      if (BIT (6))
                        op2 >>= 16;
                        op2 >>= 16;
                      if (op1 & 0x80000000)
                      if (op1 & 0x80000000)
                        op1 -= 1ULL << 32;
                        op1 -= 1ULL << 32;
                      op2 &= 0xFFFF;
                      op2 &= 0xFFFF;
                      if (op2 & 0x8000)
                      if (op2 & 0x8000)
                        op2 -= 65536;
                        op2 -= 65536;
                      result = (op1 * op2) >> 16;
                      result = (op1 * op2) >> 16;
 
 
                      if (BIT (5) == 0)
                      if (BIT (5) == 0)
                        {
                        {
                          ARMword Rn = state->Reg[BITS (12, 15)];
                          ARMword Rn = state->Reg[BITS (12, 15)];
 
 
                          if (AddOverflow (result, Rn, result + Rn))
                          if (AddOverflow (result, Rn, result + Rn))
                            SETS;
                            SETS;
                          result += Rn;
                          result += Rn;
                        }
                        }
                      state->Reg[BITS (16, 19)] = result;
                      state->Reg[BITS (16, 19)] = result;
                      break;
                      break;
                    }
                    }
 
 
                  if (BITS (4, 11) == 5)
                  if (BITS (4, 11) == 5)
                    {
                    {
                      /* ElSegundo QSUB insn.  */
                      /* ElSegundo QSUB insn.  */
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op2 = state->Reg[BITS (16, 19)];
                      ARMword op2 = state->Reg[BITS (16, 19)];
                      ARMword result = op1 - op2;
                      ARMword result = op1 - op2;
 
 
                      if (SubOverflow (op1, op2, result))
                      if (SubOverflow (op1, op2, result))
                        {
                        {
                          result = POS (result) ? 0x80000000 : 0x7fffffff;
                          result = POS (result) ? 0x80000000 : 0x7fffffff;
                          SETS;
                          SETS;
                        }
                        }
 
 
                      state->Reg[BITS (12, 15)] = result;
                      state->Reg[BITS (12, 15)] = result;
                      break;
                      break;
                    }
                    }
                }
                }
#ifdef MODET
#ifdef MODET
              if (BITS (4, 11) == 0xB)
              if (BITS (4, 11) == 0xB)
                {
                {
                  /* STRH register offset, write-back, down, pre indexed.  */
                  /* STRH register offset, write-back, down, pre indexed.  */
                  SHPREDOWNWB ();
                  SHPREDOWNWB ();
                  break;
                  break;
                }
                }
              if (BITS (4, 27) == 0x12FFF1)
              if (BITS (4, 27) == 0x12FFF1)
                {
                {
                  /* BX */
                  /* BX */
                  WriteR15Branch (state, state->Reg[RHSReg]);
                  WriteR15Branch (state, state->Reg[RHSReg]);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xF)
              if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
#endif
#endif
              if (state->is_v5)
              if (state->is_v5)
                {
                {
                  if (BITS (4, 7) == 0x7)
                  if (BITS (4, 7) == 0x7)
                    {
                    {
                      ARMword value;
                      ARMword value;
                      extern int SWI_vector_installed;
                      extern int SWI_vector_installed;
 
 
                      /* Hardware is allowed to optionally override this
                      /* Hardware is allowed to optionally override this
                         instruction and treat it as a breakpoint.  Since
                         instruction and treat it as a breakpoint.  Since
                         this is a simulator not hardware, we take the position
                         this is a simulator not hardware, we take the position
                         that if a SWI vector was not installed, then an Abort
                         that if a SWI vector was not installed, then an Abort
                         vector was probably not installed either, and so
                         vector was probably not installed either, and so
                         normally this instruction would be ignored, even if an
                         normally this instruction would be ignored, even if an
                         Abort is generated.  This is a bad thing, since GDB
                         Abort is generated.  This is a bad thing, since GDB
                         uses this instruction for its breakpoints (at least in
                         uses this instruction for its breakpoints (at least in
                         Thumb mode it does).  So intercept the instruction here
                         Thumb mode it does).  So intercept the instruction here
                         and generate a breakpoint SWI instead.  */
                         and generate a breakpoint SWI instead.  */
                      if (! SWI_vector_installed)
                      if (! SWI_vector_installed)
                        ARMul_OSHandleSWI (state, SWI_Breakpoint);
                        ARMul_OSHandleSWI (state, SWI_Breakpoint);
                      else
                      else
                        {
                        {
                          /* BKPT - normally this will cause an abort, but on the
                          /* BKPT - normally this will cause an abort, but on the
                             XScale we must check the DCSR.  */
                             XScale we must check the DCSR.  */
                          XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
                          XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
                          if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT))
                          if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT))
                            break;
                            break;
                        }
                        }
 
 
                      /* Force the next instruction to be refetched.  */
                      /* Force the next instruction to be refetched.  */
                      state->NextInstr = RESUME;
                      state->NextInstr = RESUME;
                      break;
                      break;
                    }
                    }
                }
                }
              if (DESTReg == 15)
              if (DESTReg == 15)
                {
                {
                  /* MSR reg to CPSR.  */
                  /* MSR reg to CPSR.  */
                  UNDEF_MSRPC;
                  UNDEF_MSRPC;
                  temp = DPRegRHS;
                  temp = DPRegRHS;
#ifdef MODET
#ifdef MODET
                  /* Don't allow TBIT to be set by MSR.  */
                  /* Don't allow TBIT to be set by MSR.  */
                  temp &= ~ TBIT;
                  temp &= ~ TBIT;
#endif
#endif
                  ARMul_FixCPSR (state, instr, temp);
                  ARMul_FixCPSR (state, instr, temp);
                }
                }
              else
              else
                UNDEF_Test;
                UNDEF_Test;
 
 
              break;
              break;
 
 
            case 0x13:          /* TEQP reg */
            case 0x13:          /* TEQP reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 11) & 0xF9) == 0x9)
              if ((BITS (4, 11) & 0xF9) == 0x9)
                /* LDR register offset, write-back, down, pre indexed.  */
                /* LDR register offset, write-back, down, pre indexed.  */
                LHPREDOWNWB ();
                LHPREDOWNWB ();
              /* Continue with remaining instruction decode.  */
              /* Continue with remaining instruction decode.  */
#endif
#endif
              if (DESTReg == 15)
              if (DESTReg == 15)
                {
                {
                  /* TEQP reg */
                  /* TEQP reg */
#ifdef MODE32
#ifdef MODE32
                  state->Cpsr = GETSPSR (state->Bank);
                  state->Cpsr = GETSPSR (state->Bank);
                  ARMul_CPSRAltered (state);
                  ARMul_CPSRAltered (state);
#else
#else
                  rhs = DPRegRHS;
                  rhs = DPRegRHS;
                  temp = LHS ^ rhs;
                  temp = LHS ^ rhs;
                  SETR15PSR (temp);
                  SETR15PSR (temp);
#endif
#endif
                }
                }
              else
              else
                {
                {
                  /* TEQ Reg.  */
                  /* TEQ Reg.  */
                  rhs = DPSRegRHS;
                  rhs = DPSRegRHS;
                  dest = LHS ^ rhs;
                  dest = LHS ^ rhs;
                  ARMul_NegZero (state, dest);
                  ARMul_NegZero (state, dest);
                }
                }
              break;
              break;
 
 
            case 0x14:          /* CMP reg and MRS SPSR and SWP byte.  */
            case 0x14:          /* CMP reg and MRS SPSR and SWP byte.  */
              if (state->is_v5e)
              if (state->is_v5e)
                {
                {
                  if (BIT (4) == 0 && BIT (7) == 1)
                  if (BIT (4) == 0 && BIT (7) == 1)
                    {
                    {
                      /* ElSegundo SMLALxy insn.  */
                      /* ElSegundo SMLALxy insn.  */
                      ARMdword op1 = state->Reg[BITS (0, 3)];
                      ARMdword op1 = state->Reg[BITS (0, 3)];
                      ARMdword op2 = state->Reg[BITS (8, 11)];
                      ARMdword op2 = state->Reg[BITS (8, 11)];
                      ARMdword dest;
                      ARMdword dest;
                      ARMdword result;
                      ARMdword result;
 
 
                      if (BIT (5))
                      if (BIT (5))
                        op1 >>= 16;
                        op1 >>= 16;
                      if (BIT (6))
                      if (BIT (6))
                        op2 >>= 16;
                        op2 >>= 16;
                      op1 &= 0xFFFF;
                      op1 &= 0xFFFF;
                      if (op1 & 0x8000)
                      if (op1 & 0x8000)
                        op1 -= 65536;
                        op1 -= 65536;
                      op2 &= 0xFFFF;
                      op2 &= 0xFFFF;
                      if (op2 & 0x8000)
                      if (op2 & 0x8000)
                        op2 -= 65536;
                        op2 -= 65536;
 
 
                      dest = (ARMdword) state->Reg[BITS (16, 19)] << 32;
                      dest = (ARMdword) state->Reg[BITS (16, 19)] << 32;
                      dest |= state->Reg[BITS (12, 15)];
                      dest |= state->Reg[BITS (12, 15)];
                      dest += op1 * op2;
                      dest += op1 * op2;
                      state->Reg[BITS (12, 15)] = dest;
                      state->Reg[BITS (12, 15)] = dest;
                      state->Reg[BITS (16, 19)] = dest >> 32;
                      state->Reg[BITS (16, 19)] = dest >> 32;
                      break;
                      break;
                    }
                    }
 
 
                  if (BITS (4, 11) == 5)
                  if (BITS (4, 11) == 5)
                    {
                    {
                      /* ElSegundo QDADD insn.  */
                      /* ElSegundo QDADD insn.  */
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op2 = state->Reg[BITS (16, 19)];
                      ARMword op2 = state->Reg[BITS (16, 19)];
                      ARMword op2d = op2 + op2;
                      ARMword op2d = op2 + op2;
                      ARMword result;
                      ARMword result;
 
 
                      if (AddOverflow (op2, op2, op2d))
                      if (AddOverflow (op2, op2, op2d))
                        {
                        {
                          SETS;
                          SETS;
                          op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
                          op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
                        }
                        }
 
 
                      result = op1 + op2d;
                      result = op1 + op2d;
                      if (AddOverflow (op1, op2d, result))
                      if (AddOverflow (op1, op2d, result))
                        {
                        {
                          SETS;
                          SETS;
                          result = POS (result) ? 0x80000000 : 0x7fffffff;
                          result = POS (result) ? 0x80000000 : 0x7fffffff;
                        }
                        }
 
 
                      state->Reg[BITS (12, 15)] = result;
                      state->Reg[BITS (12, 15)] = result;
                      break;
                      break;
                    }
                    }
                }
                }
#ifdef MODET
#ifdef MODET
              if (BITS (4, 7) == 0xB)
              if (BITS (4, 7) == 0xB)
                {
                {
                  /* STRH immediate offset, no write-back, down, pre indexed.  */
                  /* STRH immediate offset, no write-back, down, pre indexed.  */
                  SHPREDOWN ();
                  SHPREDOWN ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xF)
              if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
#endif
#endif
              if (BITS (4, 11) == 9)
              if (BITS (4, 11) == 9)
                {
                {
                  /* SWP */
                  /* SWP */
                  UNDEF_SWPPC;
                  UNDEF_SWPPC;
                  temp = LHS;
                  temp = LHS;
                  BUSUSEDINCPCS;
                  BUSUSEDINCPCS;
#ifndef MODE32
#ifndef MODE32
                  if (VECTORACCESS (temp) || ADDREXCEPT (temp))
                  if (VECTORACCESS (temp) || ADDREXCEPT (temp))
                    {
                    {
                      INTERNALABORT (temp);
                      INTERNALABORT (temp);
                      (void) ARMul_LoadByte (state, temp);
                      (void) ARMul_LoadByte (state, temp);
                      (void) ARMul_LoadByte (state, temp);
                      (void) ARMul_LoadByte (state, temp);
                    }
                    }
                  else
                  else
#endif
#endif
                    DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
                    DEST = ARMul_SwapByte (state, temp, state->Reg[RHSReg]);
                  if (state->abortSig || state->Aborted)
                  if (state->abortSig || state->Aborted)
                    TAKEABORT;
                    TAKEABORT;
                }
                }
              else if ((BITS (0, 11) == 0) && (LHSReg == 15))
              else if ((BITS (0, 11) == 0) && (LHSReg == 15))
                {
                {
                  /* MRS SPSR */
                  /* MRS SPSR */
                  UNDEF_MRSPC;
                  UNDEF_MRSPC;
                  DEST = GETSPSR (state->Bank);
                  DEST = GETSPSR (state->Bank);
                }
                }
              else
              else
                UNDEF_Test;
                UNDEF_Test;
 
 
              break;
              break;
 
 
            case 0x15:          /* CMPP reg.  */
            case 0x15:          /* CMPP reg.  */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 7) & 0x9) == 0x9)
              if ((BITS (4, 7) & 0x9) == 0x9)
                /* LDR immediate offset, no write-back, down, pre indexed.  */
                /* LDR immediate offset, no write-back, down, pre indexed.  */
                LHPREDOWN ();
                LHPREDOWN ();
              /* Continue with remaining instruction decode.  */
              /* Continue with remaining instruction decode.  */
#endif
#endif
              if (DESTReg == 15)
              if (DESTReg == 15)
                {
                {
                  /* CMPP reg.  */
                  /* CMPP reg.  */
#ifdef MODE32
#ifdef MODE32
                  state->Cpsr = GETSPSR (state->Bank);
                  state->Cpsr = GETSPSR (state->Bank);
                  ARMul_CPSRAltered (state);
                  ARMul_CPSRAltered (state);
#else
#else
                  rhs = DPRegRHS;
                  rhs = DPRegRHS;
                  temp = LHS - rhs;
                  temp = LHS - rhs;
                  SETR15PSR (temp);
                  SETR15PSR (temp);
#endif
#endif
                }
                }
              else
              else
                {
                {
                  /* CMP reg.  */
                  /* CMP reg.  */
                  lhs = LHS;
                  lhs = LHS;
                  rhs = DPRegRHS;
                  rhs = DPRegRHS;
                  dest = lhs - rhs;
                  dest = lhs - rhs;
                  ARMul_NegZero (state, dest);
                  ARMul_NegZero (state, dest);
                  if ((lhs >= rhs) || ((rhs | lhs) >> 31))
                  if ((lhs >= rhs) || ((rhs | lhs) >> 31))
                    {
                    {
                      ARMul_SubCarry (state, lhs, rhs, dest);
                      ARMul_SubCarry (state, lhs, rhs, dest);
                      ARMul_SubOverflow (state, lhs, rhs, dest);
                      ARMul_SubOverflow (state, lhs, rhs, dest);
                    }
                    }
                  else
                  else
                    {
                    {
                      CLEARC;
                      CLEARC;
                      CLEARV;
                      CLEARV;
                    }
                    }
                }
                }
              break;
              break;
 
 
            case 0x16:          /* CMN reg and MSR reg to SPSR */
            case 0x16:          /* CMN reg and MSR reg to SPSR */
              if (state->is_v5e)
              if (state->is_v5e)
                {
                {
                  if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
                  if (BIT (4) == 0 && BIT (7) == 1 && BITS (12, 15) == 0)
                    {
                    {
                      /* ElSegundo SMULxy insn.  */
                      /* ElSegundo SMULxy insn.  */
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op2 = state->Reg[BITS (8, 11)];
                      ARMword op2 = state->Reg[BITS (8, 11)];
                      ARMword Rn = state->Reg[BITS (12, 15)];
                      ARMword Rn = state->Reg[BITS (12, 15)];
 
 
                      if (BIT (5))
                      if (BIT (5))
                        op1 >>= 16;
                        op1 >>= 16;
                      if (BIT (6))
                      if (BIT (6))
                        op2 >>= 16;
                        op2 >>= 16;
                      op1 &= 0xFFFF;
                      op1 &= 0xFFFF;
                      op2 &= 0xFFFF;
                      op2 &= 0xFFFF;
                      if (op1 & 0x8000)
                      if (op1 & 0x8000)
                        op1 -= 65536;
                        op1 -= 65536;
                      if (op2 & 0x8000)
                      if (op2 & 0x8000)
                        op2 -= 65536;
                        op2 -= 65536;
 
 
                      state->Reg[BITS (16, 19)] = op1 * op2;
                      state->Reg[BITS (16, 19)] = op1 * op2;
                      break;
                      break;
                    }
                    }
 
 
                  if (BITS (4, 11) == 5)
                  if (BITS (4, 11) == 5)
                    {
                    {
                      /* ElSegundo QDSUB insn.  */
                      /* ElSegundo QDSUB insn.  */
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op2 = state->Reg[BITS (16, 19)];
                      ARMword op2 = state->Reg[BITS (16, 19)];
                      ARMword op2d = op2 + op2;
                      ARMword op2d = op2 + op2;
                      ARMword result;
                      ARMword result;
 
 
                      if (AddOverflow (op2, op2, op2d))
                      if (AddOverflow (op2, op2, op2d))
                        {
                        {
                          SETS;
                          SETS;
                          op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
                          op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
                        }
                        }
 
 
                      result = op1 - op2d;
                      result = op1 - op2d;
                      if (SubOverflow (op1, op2d, result))
                      if (SubOverflow (op1, op2d, result))
                        {
                        {
                          SETS;
                          SETS;
                          result = POS (result) ? 0x80000000 : 0x7fffffff;
                          result = POS (result) ? 0x80000000 : 0x7fffffff;
                        }
                        }
 
 
                      state->Reg[BITS (12, 15)] = result;
                      state->Reg[BITS (12, 15)] = result;
                      break;
                      break;
                    }
                    }
                }
                }
 
 
              if (state->is_v5)
              if (state->is_v5)
                {
                {
                  if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
                  if (BITS (4, 11) == 0xF1 && BITS (16, 19) == 0xF)
                    {
                    {
                      /* ARM5 CLZ insn.  */
                      /* ARM5 CLZ insn.  */
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      ARMword op1 = state->Reg[BITS (0, 3)];
                      int result = 32;
                      int result = 32;
 
 
                      if (op1)
                      if (op1)
                        for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
                        for (result = 0; (op1 & 0x80000000) == 0; op1 <<= 1)
                          result++;
                          result++;
 
 
                      state->Reg[BITS (12, 15)] = result;
                      state->Reg[BITS (12, 15)] = result;
                      break;
                      break;
                    }
                    }
                }
                }
#ifdef MODET
#ifdef MODET
              if (BITS (4, 7) == 0xB)
              if (BITS (4, 7) == 0xB)
                {
                {
                  /* STRH immediate offset, write-back, down, pre indexed.  */
                  /* STRH immediate offset, write-back, down, pre indexed.  */
                  SHPREDOWNWB ();
                  SHPREDOWNWB ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xF)
              if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
#endif
#endif
              if (DESTReg == 15)
              if (DESTReg == 15)
                {
                {
                  /* MSR */
                  /* MSR */
                  UNDEF_MSRPC;
                  UNDEF_MSRPC;
                  ARMul_FixSPSR (state, instr, DPRegRHS);
                  ARMul_FixSPSR (state, instr, DPRegRHS);
                }
                }
              else
              else
                {
                {
                  UNDEF_Test;
                  UNDEF_Test;
                }
                }
              break;
              break;
 
 
            case 0x17:          /* CMNP reg */
            case 0x17:          /* CMNP reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 7) & 0x9) == 0x9)
              if ((BITS (4, 7) & 0x9) == 0x9)
                /* LDR immediate offset, write-back, down, pre indexed.  */
                /* LDR immediate offset, write-back, down, pre indexed.  */
                LHPREDOWNWB ();
                LHPREDOWNWB ();
              /* Continue with remaining instruction decoding.  */
              /* Continue with remaining instruction decoding.  */
#endif
#endif
              if (DESTReg == 15)
              if (DESTReg == 15)
                {
                {
#ifdef MODE32
#ifdef MODE32
                  state->Cpsr = GETSPSR (state->Bank);
                  state->Cpsr = GETSPSR (state->Bank);
                  ARMul_CPSRAltered (state);
                  ARMul_CPSRAltered (state);
#else
#else
                  rhs = DPRegRHS;
                  rhs = DPRegRHS;
                  temp = LHS + rhs;
                  temp = LHS + rhs;
                  SETR15PSR (temp);
                  SETR15PSR (temp);
#endif
#endif
                  break;
                  break;
                }
                }
              else
              else
                {
                {
                  /* CMN reg.  */
                  /* CMN reg.  */
                  lhs = LHS;
                  lhs = LHS;
                  rhs = DPRegRHS;
                  rhs = DPRegRHS;
                  dest = lhs + rhs;
                  dest = lhs + rhs;
                  ASSIGNZ (dest == 0);
                  ASSIGNZ (dest == 0);
                  if ((lhs | rhs) >> 30)
                  if ((lhs | rhs) >> 30)
                    {
                    {
                      /* Possible C,V,N to set.  */
                      /* Possible C,V,N to set.  */
                      ASSIGNN (NEG (dest));
                      ASSIGNN (NEG (dest));
                      ARMul_AddCarry (state, lhs, rhs, dest);
                      ARMul_AddCarry (state, lhs, rhs, dest);
                      ARMul_AddOverflow (state, lhs, rhs, dest);
                      ARMul_AddOverflow (state, lhs, rhs, dest);
                    }
                    }
                  else
                  else
                    {
                    {
                      CLEARN;
                      CLEARN;
                      CLEARC;
                      CLEARC;
                      CLEARV;
                      CLEARV;
                    }
                    }
                }
                }
              break;
              break;
 
 
            case 0x18:          /* ORR reg */
            case 0x18:          /* ORR reg */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 11) == 0xB)
              if (BITS (4, 11) == 0xB)
                {
                {
                  /* STRH register offset, no write-back, up, pre indexed.  */
                  /* STRH register offset, no write-back, up, pre indexed.  */
                  SHPREUP ();
                  SHPREUP ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xF)
              if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
#endif
#endif
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = LHS | rhs;
              dest = LHS | rhs;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x19:          /* ORRS reg */
            case 0x19:          /* ORRS reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 11) & 0xF9) == 0x9)
              if ((BITS (4, 11) & 0xF9) == 0x9)
                /* LDR register offset, no write-back, up, pre indexed.  */
                /* LDR register offset, no write-back, up, pre indexed.  */
                LHPREUP ();
                LHPREUP ();
              /* Continue with remaining instruction decoding.  */
              /* Continue with remaining instruction decoding.  */
#endif
#endif
              rhs = DPSRegRHS;
              rhs = DPSRegRHS;
              dest = LHS | rhs;
              dest = LHS | rhs;
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x1a:          /* MOV reg */
            case 0x1a:          /* MOV reg */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 11) == 0xB)
              if (BITS (4, 11) == 0xB)
                {
                {
                  /* STRH register offset, write-back, up, pre indexed.  */
                  /* STRH register offset, write-back, up, pre indexed.  */
                  SHPREUPWB ();
                  SHPREUPWB ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xF)
              if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
#endif
#endif
              dest = DPRegRHS;
              dest = DPRegRHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x1b:          /* MOVS reg */
            case 0x1b:          /* MOVS reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 11) & 0xF9) == 0x9)
              if ((BITS (4, 11) & 0xF9) == 0x9)
                /* LDR register offset, write-back, up, pre indexed.  */
                /* LDR register offset, write-back, up, pre indexed.  */
                LHPREUPWB ();
                LHPREUPWB ();
              /* Continue with remaining instruction decoding.  */
              /* Continue with remaining instruction decoding.  */
#endif
#endif
              dest = DPSRegRHS;
              dest = DPSRegRHS;
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x1c:          /* BIC reg */
            case 0x1c:          /* BIC reg */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 7) == 0xB)
              if (BITS (4, 7) == 0xB)
                {
                {
                  /* STRH immediate offset, no write-back, up, pre indexed.  */
                  /* STRH immediate offset, no write-back, up, pre indexed.  */
                  SHPREUP ();
                  SHPREUP ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              else if (BITS (4, 7) == 0xF)
              else if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
#endif
#endif
              rhs = DPRegRHS;
              rhs = DPRegRHS;
              dest = LHS & ~rhs;
              dest = LHS & ~rhs;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x1d:          /* BICS reg */
            case 0x1d:          /* BICS reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 7) & 0x9) == 0x9)
              if ((BITS (4, 7) & 0x9) == 0x9)
                /* LDR immediate offset, no write-back, up, pre indexed.  */
                /* LDR immediate offset, no write-back, up, pre indexed.  */
                LHPREUP ();
                LHPREUP ();
              /* Continue with instruction decoding.  */
              /* Continue with instruction decoding.  */
#endif
#endif
              rhs = DPSRegRHS;
              rhs = DPSRegRHS;
              dest = LHS & ~rhs;
              dest = LHS & ~rhs;
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x1e:          /* MVN reg */
            case 0x1e:          /* MVN reg */
#ifdef MODET
#ifdef MODET
              if (BITS (4, 7) == 0xB)
              if (BITS (4, 7) == 0xB)
                {
                {
                  /* STRH immediate offset, write-back, up, pre indexed.  */
                  /* STRH immediate offset, write-back, up, pre indexed.  */
                  SHPREUPWB ();
                  SHPREUPWB ();
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xD)
              if (BITS (4, 7) == 0xD)
                {
                {
                  Handle_Load_Double (state, instr);
                  Handle_Load_Double (state, instr);
                  break;
                  break;
                }
                }
              if (BITS (4, 7) == 0xF)
              if (BITS (4, 7) == 0xF)
                {
                {
                  Handle_Store_Double (state, instr);
                  Handle_Store_Double (state, instr);
                  break;
                  break;
                }
                }
#endif
#endif
              dest = ~DPRegRHS;
              dest = ~DPRegRHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x1f:          /* MVNS reg */
            case 0x1f:          /* MVNS reg */
#ifdef MODET
#ifdef MODET
              if ((BITS (4, 7) & 0x9) == 0x9)
              if ((BITS (4, 7) & 0x9) == 0x9)
                /* LDR immediate offset, write-back, up, pre indexed.  */
                /* LDR immediate offset, write-back, up, pre indexed.  */
                LHPREUPWB ();
                LHPREUPWB ();
              /* Continue instruction decoding.  */
              /* Continue instruction decoding.  */
#endif
#endif
              dest = ~DPSRegRHS;
              dest = ~DPSRegRHS;
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
 
 
              /* Data Processing Immediate RHS Instructions.  */
              /* Data Processing Immediate RHS Instructions.  */
 
 
            case 0x20:          /* AND immed */
            case 0x20:          /* AND immed */
              dest = LHS & DPImmRHS;
              dest = LHS & DPImmRHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x21:          /* ANDS immed */
            case 0x21:          /* ANDS immed */
              DPSImmRHS;
              DPSImmRHS;
              dest = LHS & rhs;
              dest = LHS & rhs;
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x22:          /* EOR immed */
            case 0x22:          /* EOR immed */
              dest = LHS ^ DPImmRHS;
              dest = LHS ^ DPImmRHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x23:          /* EORS immed */
            case 0x23:          /* EORS immed */
              DPSImmRHS;
              DPSImmRHS;
              dest = LHS ^ rhs;
              dest = LHS ^ rhs;
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x24:          /* SUB immed */
            case 0x24:          /* SUB immed */
              dest = LHS - DPImmRHS;
              dest = LHS - DPImmRHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x25:          /* SUBS immed */
            case 0x25:          /* SUBS immed */
              lhs = LHS;
              lhs = LHS;
              rhs = DPImmRHS;
              rhs = DPImmRHS;
              dest = lhs - rhs;
              dest = lhs - rhs;
 
 
              if ((lhs >= rhs) || ((rhs | lhs) >> 31))
              if ((lhs >= rhs) || ((rhs | lhs) >> 31))
                {
                {
                  ARMul_SubCarry (state, lhs, rhs, dest);
                  ARMul_SubCarry (state, lhs, rhs, dest);
                  ARMul_SubOverflow (state, lhs, rhs, dest);
                  ARMul_SubOverflow (state, lhs, rhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x26:          /* RSB immed */
            case 0x26:          /* RSB immed */
              dest = DPImmRHS - LHS;
              dest = DPImmRHS - LHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x27:          /* RSBS immed */
            case 0x27:          /* RSBS immed */
              lhs = LHS;
              lhs = LHS;
              rhs = DPImmRHS;
              rhs = DPImmRHS;
              dest = rhs - lhs;
              dest = rhs - lhs;
 
 
              if ((rhs >= lhs) || ((rhs | lhs) >> 31))
              if ((rhs >= lhs) || ((rhs | lhs) >> 31))
                {
                {
                  ARMul_SubCarry (state, rhs, lhs, dest);
                  ARMul_SubCarry (state, rhs, lhs, dest);
                  ARMul_SubOverflow (state, rhs, lhs, dest);
                  ARMul_SubOverflow (state, rhs, lhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x28:          /* ADD immed */
            case 0x28:          /* ADD immed */
              dest = LHS + DPImmRHS;
              dest = LHS + DPImmRHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x29:          /* ADDS immed */
            case 0x29:          /* ADDS immed */
              lhs = LHS;
              lhs = LHS;
              rhs = DPImmRHS;
              rhs = DPImmRHS;
              dest = lhs + rhs;
              dest = lhs + rhs;
              ASSIGNZ (dest == 0);
              ASSIGNZ (dest == 0);
 
 
              if ((lhs | rhs) >> 30)
              if ((lhs | rhs) >> 30)
                {
                {
                  /* Possible C,V,N to set.  */
                  /* Possible C,V,N to set.  */
                  ASSIGNN (NEG (dest));
                  ASSIGNN (NEG (dest));
                  ARMul_AddCarry (state, lhs, rhs, dest);
                  ARMul_AddCarry (state, lhs, rhs, dest);
                  ARMul_AddOverflow (state, lhs, rhs, dest);
                  ARMul_AddOverflow (state, lhs, rhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARN;
                  CLEARN;
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x2a:          /* ADC immed */
            case 0x2a:          /* ADC immed */
              dest = LHS + DPImmRHS + CFLAG;
              dest = LHS + DPImmRHS + CFLAG;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x2b:          /* ADCS immed */
            case 0x2b:          /* ADCS immed */
              lhs = LHS;
              lhs = LHS;
              rhs = DPImmRHS;
              rhs = DPImmRHS;
              dest = lhs + rhs + CFLAG;
              dest = lhs + rhs + CFLAG;
              ASSIGNZ (dest == 0);
              ASSIGNZ (dest == 0);
              if ((lhs | rhs) >> 30)
              if ((lhs | rhs) >> 30)
                {
                {
                  /* Possible C,V,N to set.  */
                  /* Possible C,V,N to set.  */
                  ASSIGNN (NEG (dest));
                  ASSIGNN (NEG (dest));
                  ARMul_AddCarry (state, lhs, rhs, dest);
                  ARMul_AddCarry (state, lhs, rhs, dest);
                  ARMul_AddOverflow (state, lhs, rhs, dest);
                  ARMul_AddOverflow (state, lhs, rhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARN;
                  CLEARN;
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x2c:          /* SBC immed */
            case 0x2c:          /* SBC immed */
              dest = LHS - DPImmRHS - !CFLAG;
              dest = LHS - DPImmRHS - !CFLAG;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x2d:          /* SBCS immed */
            case 0x2d:          /* SBCS immed */
              lhs = LHS;
              lhs = LHS;
              rhs = DPImmRHS;
              rhs = DPImmRHS;
              dest = lhs - rhs - !CFLAG;
              dest = lhs - rhs - !CFLAG;
              if ((lhs >= rhs) || ((rhs | lhs) >> 31))
              if ((lhs >= rhs) || ((rhs | lhs) >> 31))
                {
                {
                  ARMul_SubCarry (state, lhs, rhs, dest);
                  ARMul_SubCarry (state, lhs, rhs, dest);
                  ARMul_SubOverflow (state, lhs, rhs, dest);
                  ARMul_SubOverflow (state, lhs, rhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x2e:          /* RSC immed */
            case 0x2e:          /* RSC immed */
              dest = DPImmRHS - LHS - !CFLAG;
              dest = DPImmRHS - LHS - !CFLAG;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x2f:          /* RSCS immed */
            case 0x2f:          /* RSCS immed */
              lhs = LHS;
              lhs = LHS;
              rhs = DPImmRHS;
              rhs = DPImmRHS;
              dest = rhs - lhs - !CFLAG;
              dest = rhs - lhs - !CFLAG;
              if ((rhs >= lhs) || ((rhs | lhs) >> 31))
              if ((rhs >= lhs) || ((rhs | lhs) >> 31))
                {
                {
                  ARMul_SubCarry (state, rhs, lhs, dest);
                  ARMul_SubCarry (state, rhs, lhs, dest);
                  ARMul_SubOverflow (state, rhs, lhs, dest);
                  ARMul_SubOverflow (state, rhs, lhs, dest);
                }
                }
              else
              else
                {
                {
                  CLEARC;
                  CLEARC;
                  CLEARV;
                  CLEARV;
                }
                }
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x30:          /* TST immed */
            case 0x30:          /* TST immed */
              UNDEF_Test;
              UNDEF_Test;
              break;
              break;
 
 
            case 0x31:          /* TSTP immed */
            case 0x31:          /* TSTP immed */
              if (DESTReg == 15)
              if (DESTReg == 15)
                {
                {
                  /* TSTP immed.  */
                  /* TSTP immed.  */
#ifdef MODE32
#ifdef MODE32
                  state->Cpsr = GETSPSR (state->Bank);
                  state->Cpsr = GETSPSR (state->Bank);
                  ARMul_CPSRAltered (state);
                  ARMul_CPSRAltered (state);
#else
#else
                  temp = LHS & DPImmRHS;
                  temp = LHS & DPImmRHS;
                  SETR15PSR (temp);
                  SETR15PSR (temp);
#endif
#endif
                }
                }
              else
              else
                {
                {
                  /* TST immed.  */
                  /* TST immed.  */
                  DPSImmRHS;
                  DPSImmRHS;
                  dest = LHS & rhs;
                  dest = LHS & rhs;
                  ARMul_NegZero (state, dest);
                  ARMul_NegZero (state, dest);
                }
                }
              break;
              break;
 
 
            case 0x32:          /* TEQ immed and MSR immed to CPSR */
            case 0x32:          /* TEQ immed and MSR immed to CPSR */
              if (DESTReg == 15)
              if (DESTReg == 15)
                /* MSR immed to CPSR.  */
                /* MSR immed to CPSR.  */
                ARMul_FixCPSR (state, instr, DPImmRHS);
                ARMul_FixCPSR (state, instr, DPImmRHS);
              else
              else
                UNDEF_Test;
                UNDEF_Test;
              break;
              break;
 
 
            case 0x33:          /* TEQP immed */
            case 0x33:          /* TEQP immed */
              if (DESTReg == 15)
              if (DESTReg == 15)
                {
                {
                  /* TEQP immed.  */
                  /* TEQP immed.  */
#ifdef MODE32
#ifdef MODE32
                  state->Cpsr = GETSPSR (state->Bank);
                  state->Cpsr = GETSPSR (state->Bank);
                  ARMul_CPSRAltered (state);
                  ARMul_CPSRAltered (state);
#else
#else
                  temp = LHS ^ DPImmRHS;
                  temp = LHS ^ DPImmRHS;
                  SETR15PSR (temp);
                  SETR15PSR (temp);
#endif
#endif
                }
                }
              else
              else
                {
                {
                  DPSImmRHS;    /* TEQ immed */
                  DPSImmRHS;    /* TEQ immed */
                  dest = LHS ^ rhs;
                  dest = LHS ^ rhs;
                  ARMul_NegZero (state, dest);
                  ARMul_NegZero (state, dest);
                }
                }
              break;
              break;
 
 
            case 0x34:          /* CMP immed */
            case 0x34:          /* CMP immed */
              UNDEF_Test;
              UNDEF_Test;
              break;
              break;
 
 
            case 0x35:          /* CMPP immed */
            case 0x35:          /* CMPP immed */
              if (DESTReg == 15)
              if (DESTReg == 15)
                {
                {
                  /* CMPP immed.  */
                  /* CMPP immed.  */
#ifdef MODE32
#ifdef MODE32
                  state->Cpsr = GETSPSR (state->Bank);
                  state->Cpsr = GETSPSR (state->Bank);
                  ARMul_CPSRAltered (state);
                  ARMul_CPSRAltered (state);
#else
#else
                  temp = LHS - DPImmRHS;
                  temp = LHS - DPImmRHS;
                  SETR15PSR (temp);
                  SETR15PSR (temp);
#endif
#endif
                  break;
                  break;
                }
                }
              else
              else
                {
                {
                  /* CMP immed.  */
                  /* CMP immed.  */
                  lhs = LHS;
                  lhs = LHS;
                  rhs = DPImmRHS;
                  rhs = DPImmRHS;
                  dest = lhs - rhs;
                  dest = lhs - rhs;
                  ARMul_NegZero (state, dest);
                  ARMul_NegZero (state, dest);
 
 
                  if ((lhs >= rhs) || ((rhs | lhs) >> 31))
                  if ((lhs >= rhs) || ((rhs | lhs) >> 31))
                    {
                    {
                      ARMul_SubCarry (state, lhs, rhs, dest);
                      ARMul_SubCarry (state, lhs, rhs, dest);
                      ARMul_SubOverflow (state, lhs, rhs, dest);
                      ARMul_SubOverflow (state, lhs, rhs, dest);
                    }
                    }
                  else
                  else
                    {
                    {
                      CLEARC;
                      CLEARC;
                      CLEARV;
                      CLEARV;
                    }
                    }
                }
                }
              break;
              break;
 
 
            case 0x36:          /* CMN immed and MSR immed to SPSR */
            case 0x36:          /* CMN immed and MSR immed to SPSR */
              if (DESTReg == 15)
              if (DESTReg == 15)
                ARMul_FixSPSR (state, instr, DPImmRHS);
                ARMul_FixSPSR (state, instr, DPImmRHS);
              else
              else
                UNDEF_Test;
                UNDEF_Test;
              break;
              break;
 
 
            case 0x37:          /* CMNP immed.  */
            case 0x37:          /* CMNP immed.  */
              if (DESTReg == 15)
              if (DESTReg == 15)
                {
                {
                  /* CMNP immed.  */
                  /* CMNP immed.  */
#ifdef MODE32
#ifdef MODE32
                  state->Cpsr = GETSPSR (state->Bank);
                  state->Cpsr = GETSPSR (state->Bank);
                  ARMul_CPSRAltered (state);
                  ARMul_CPSRAltered (state);
#else
#else
                  temp = LHS + DPImmRHS;
                  temp = LHS + DPImmRHS;
                  SETR15PSR (temp);
                  SETR15PSR (temp);
#endif
#endif
                  break;
                  break;
                }
                }
              else
              else
                {
                {
                  /* CMN immed.  */
                  /* CMN immed.  */
                  lhs = LHS;
                  lhs = LHS;
                  rhs = DPImmRHS;
                  rhs = DPImmRHS;
                  dest = lhs + rhs;
                  dest = lhs + rhs;
                  ASSIGNZ (dest == 0);
                  ASSIGNZ (dest == 0);
                  if ((lhs | rhs) >> 30)
                  if ((lhs | rhs) >> 30)
                    {
                    {
                      /* Possible C,V,N to set.  */
                      /* Possible C,V,N to set.  */
                      ASSIGNN (NEG (dest));
                      ASSIGNN (NEG (dest));
                      ARMul_AddCarry (state, lhs, rhs, dest);
                      ARMul_AddCarry (state, lhs, rhs, dest);
                      ARMul_AddOverflow (state, lhs, rhs, dest);
                      ARMul_AddOverflow (state, lhs, rhs, dest);
                    }
                    }
                  else
                  else
                    {
                    {
                      CLEARN;
                      CLEARN;
                      CLEARC;
                      CLEARC;
                      CLEARV;
                      CLEARV;
                    }
                    }
                }
                }
              break;
              break;
 
 
            case 0x38:          /* ORR immed.  */
            case 0x38:          /* ORR immed.  */
              dest = LHS | DPImmRHS;
              dest = LHS | DPImmRHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x39:          /* ORRS immed.  */
            case 0x39:          /* ORRS immed.  */
              DPSImmRHS;
              DPSImmRHS;
              dest = LHS | rhs;
              dest = LHS | rhs;
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x3a:          /* MOV immed.  */
            case 0x3a:          /* MOV immed.  */
              dest = DPImmRHS;
              dest = DPImmRHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x3b:          /* MOVS immed.  */
            case 0x3b:          /* MOVS immed.  */
              DPSImmRHS;
              DPSImmRHS;
              WRITESDEST (rhs);
              WRITESDEST (rhs);
              break;
              break;
 
 
            case 0x3c:          /* BIC immed.  */
            case 0x3c:          /* BIC immed.  */
              dest = LHS & ~DPImmRHS;
              dest = LHS & ~DPImmRHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x3d:          /* BICS immed.  */
            case 0x3d:          /* BICS immed.  */
              DPSImmRHS;
              DPSImmRHS;
              dest = LHS & ~rhs;
              dest = LHS & ~rhs;
              WRITESDEST (dest);
              WRITESDEST (dest);
              break;
              break;
 
 
            case 0x3e:          /* MVN immed.  */
            case 0x3e:          /* MVN immed.  */
              dest = ~DPImmRHS;
              dest = ~DPImmRHS;
              WRITEDEST (dest);
              WRITEDEST (dest);
              break;
              break;
 
 
            case 0x3f:          /* MVNS immed.  */
            case 0x3f:          /* MVNS immed.  */
              DPSImmRHS;
              DPSImmRHS;
              WRITESDEST (~rhs);
              WRITESDEST (~rhs);
              break;
              break;
 
 
 
 
              /* Single Data Transfer Immediate RHS Instructions.  */
              /* Single Data Transfer Immediate RHS Instructions.  */
 
 
            case 0x40:          /* Store Word, No WriteBack, Post Dec, Immed.  */
            case 0x40:          /* Store Word, No WriteBack, Post Dec, Immed.  */
              lhs = LHS;
              lhs = LHS;
              if (StoreWord (state, instr, lhs))
              if (StoreWord (state, instr, lhs))
                LSBase = lhs - LSImmRHS;
                LSBase = lhs - LSImmRHS;
              break;
              break;
 
 
            case 0x41:          /* Load Word, No WriteBack, Post Dec, Immed.  */
            case 0x41:          /* Load Word, No WriteBack, Post Dec, Immed.  */
              lhs = LHS;
              lhs = LHS;
              if (LoadWord (state, instr, lhs))
              if (LoadWord (state, instr, lhs))
                LSBase = lhs - LSImmRHS;
                LSBase = lhs - LSImmRHS;
              break;
              break;
 
 
            case 0x42:          /* Store Word, WriteBack, Post Dec, Immed.  */
            case 0x42:          /* Store Word, WriteBack, Post Dec, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              lhs = LHS;
              lhs = LHS;
              temp = lhs - LSImmRHS;
              temp = lhs - LSImmRHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (StoreWord (state, instr, lhs))
              if (StoreWord (state, instr, lhs))
                LSBase = temp;
                LSBase = temp;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x43:          /* Load Word, WriteBack, Post Dec, Immed.  */
            case 0x43:          /* Load Word, WriteBack, Post Dec, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              lhs = LHS;
              lhs = LHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (LoadWord (state, instr, lhs))
              if (LoadWord (state, instr, lhs))
                LSBase = lhs - LSImmRHS;
                LSBase = lhs - LSImmRHS;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x44:          /* Store Byte, No WriteBack, Post Dec, Immed.  */
            case 0x44:          /* Store Byte, No WriteBack, Post Dec, Immed.  */
              lhs = LHS;
              lhs = LHS;
              if (StoreByte (state, instr, lhs))
              if (StoreByte (state, instr, lhs))
                LSBase = lhs - LSImmRHS;
                LSBase = lhs - LSImmRHS;
              break;
              break;
 
 
            case 0x45:          /* Load Byte, No WriteBack, Post Dec, Immed.  */
            case 0x45:          /* Load Byte, No WriteBack, Post Dec, Immed.  */
              lhs = LHS;
              lhs = LHS;
              if (LoadByte (state, instr, lhs, LUNSIGNED))
              if (LoadByte (state, instr, lhs, LUNSIGNED))
                LSBase = lhs - LSImmRHS;
                LSBase = lhs - LSImmRHS;
              break;
              break;
 
 
            case 0x46:          /* Store Byte, WriteBack, Post Dec, Immed.  */
            case 0x46:          /* Store Byte, WriteBack, Post Dec, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              lhs = LHS;
              lhs = LHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (StoreByte (state, instr, lhs))
              if (StoreByte (state, instr, lhs))
                LSBase = lhs - LSImmRHS;
                LSBase = lhs - LSImmRHS;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x47:          /* Load Byte, WriteBack, Post Dec, Immed.  */
            case 0x47:          /* Load Byte, WriteBack, Post Dec, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              lhs = LHS;
              lhs = LHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (LoadByte (state, instr, lhs, LUNSIGNED))
              if (LoadByte (state, instr, lhs, LUNSIGNED))
                LSBase = lhs - LSImmRHS;
                LSBase = lhs - LSImmRHS;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x48:          /* Store Word, No WriteBack, Post Inc, Immed.  */
            case 0x48:          /* Store Word, No WriteBack, Post Inc, Immed.  */
              lhs = LHS;
              lhs = LHS;
              if (StoreWord (state, instr, lhs))
              if (StoreWord (state, instr, lhs))
                LSBase = lhs + LSImmRHS;
                LSBase = lhs + LSImmRHS;
              break;
              break;
 
 
            case 0x49:          /* Load Word, No WriteBack, Post Inc, Immed.  */
            case 0x49:          /* Load Word, No WriteBack, Post Inc, Immed.  */
              lhs = LHS;
              lhs = LHS;
              if (LoadWord (state, instr, lhs))
              if (LoadWord (state, instr, lhs))
                LSBase = lhs + LSImmRHS;
                LSBase = lhs + LSImmRHS;
              break;
              break;
 
 
            case 0x4a:          /* Store Word, WriteBack, Post Inc, Immed.  */
            case 0x4a:          /* Store Word, WriteBack, Post Inc, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              lhs = LHS;
              lhs = LHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (StoreWord (state, instr, lhs))
              if (StoreWord (state, instr, lhs))
                LSBase = lhs + LSImmRHS;
                LSBase = lhs + LSImmRHS;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x4b:          /* Load Word, WriteBack, Post Inc, Immed.  */
            case 0x4b:          /* Load Word, WriteBack, Post Inc, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              lhs = LHS;
              lhs = LHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (LoadWord (state, instr, lhs))
              if (LoadWord (state, instr, lhs))
                LSBase = lhs + LSImmRHS;
                LSBase = lhs + LSImmRHS;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x4c:          /* Store Byte, No WriteBack, Post Inc, Immed.  */
            case 0x4c:          /* Store Byte, No WriteBack, Post Inc, Immed.  */
              lhs = LHS;
              lhs = LHS;
              if (StoreByte (state, instr, lhs))
              if (StoreByte (state, instr, lhs))
                LSBase = lhs + LSImmRHS;
                LSBase = lhs + LSImmRHS;
              break;
              break;
 
 
            case 0x4d:          /* Load Byte, No WriteBack, Post Inc, Immed.  */
            case 0x4d:          /* Load Byte, No WriteBack, Post Inc, Immed.  */
              lhs = LHS;
              lhs = LHS;
              if (LoadByte (state, instr, lhs, LUNSIGNED))
              if (LoadByte (state, instr, lhs, LUNSIGNED))
                LSBase = lhs + LSImmRHS;
                LSBase = lhs + LSImmRHS;
              break;
              break;
 
 
            case 0x4e:          /* Store Byte, WriteBack, Post Inc, Immed.  */
            case 0x4e:          /* Store Byte, WriteBack, Post Inc, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              lhs = LHS;
              lhs = LHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (StoreByte (state, instr, lhs))
              if (StoreByte (state, instr, lhs))
                LSBase = lhs + LSImmRHS;
                LSBase = lhs + LSImmRHS;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x4f:          /* Load Byte, WriteBack, Post Inc, Immed.  */
            case 0x4f:          /* Load Byte, WriteBack, Post Inc, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              lhs = LHS;
              lhs = LHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (LoadByte (state, instr, lhs, LUNSIGNED))
              if (LoadByte (state, instr, lhs, LUNSIGNED))
                LSBase = lhs + LSImmRHS;
                LSBase = lhs + LSImmRHS;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
 
 
            case 0x50:          /* Store Word, No WriteBack, Pre Dec, Immed.  */
            case 0x50:          /* Store Word, No WriteBack, Pre Dec, Immed.  */
              (void) StoreWord (state, instr, LHS - LSImmRHS);
              (void) StoreWord (state, instr, LHS - LSImmRHS);
              break;
              break;
 
 
            case 0x51:          /* Load Word, No WriteBack, Pre Dec, Immed.  */
            case 0x51:          /* Load Word, No WriteBack, Pre Dec, Immed.  */
              (void) LoadWord (state, instr, LHS - LSImmRHS);
              (void) LoadWord (state, instr, LHS - LSImmRHS);
              break;
              break;
 
 
            case 0x52:          /* Store Word, WriteBack, Pre Dec, Immed.  */
            case 0x52:          /* Store Word, WriteBack, Pre Dec, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              temp = LHS - LSImmRHS;
              temp = LHS - LSImmRHS;
              if (StoreWord (state, instr, temp))
              if (StoreWord (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x53:          /* Load Word, WriteBack, Pre Dec, Immed.  */
            case 0x53:          /* Load Word, WriteBack, Pre Dec, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              temp = LHS - LSImmRHS;
              temp = LHS - LSImmRHS;
              if (LoadWord (state, instr, temp))
              if (LoadWord (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x54:          /* Store Byte, No WriteBack, Pre Dec, Immed.  */
            case 0x54:          /* Store Byte, No WriteBack, Pre Dec, Immed.  */
              (void) StoreByte (state, instr, LHS - LSImmRHS);
              (void) StoreByte (state, instr, LHS - LSImmRHS);
              break;
              break;
 
 
            case 0x55:          /* Load Byte, No WriteBack, Pre Dec, Immed.  */
            case 0x55:          /* Load Byte, No WriteBack, Pre Dec, Immed.  */
              (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
              (void) LoadByte (state, instr, LHS - LSImmRHS, LUNSIGNED);
              break;
              break;
 
 
            case 0x56:          /* Store Byte, WriteBack, Pre Dec, Immed.  */
            case 0x56:          /* Store Byte, WriteBack, Pre Dec, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              temp = LHS - LSImmRHS;
              temp = LHS - LSImmRHS;
              if (StoreByte (state, instr, temp))
              if (StoreByte (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x57:          /* Load Byte, WriteBack, Pre Dec, Immed.  */
            case 0x57:          /* Load Byte, WriteBack, Pre Dec, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              temp = LHS - LSImmRHS;
              temp = LHS - LSImmRHS;
              if (LoadByte (state, instr, temp, LUNSIGNED))
              if (LoadByte (state, instr, temp, LUNSIGNED))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x58:          /* Store Word, No WriteBack, Pre Inc, Immed.  */
            case 0x58:          /* Store Word, No WriteBack, Pre Inc, Immed.  */
              (void) StoreWord (state, instr, LHS + LSImmRHS);
              (void) StoreWord (state, instr, LHS + LSImmRHS);
              break;
              break;
 
 
            case 0x59:          /* Load Word, No WriteBack, Pre Inc, Immed.  */
            case 0x59:          /* Load Word, No WriteBack, Pre Inc, Immed.  */
              (void) LoadWord (state, instr, LHS + LSImmRHS);
              (void) LoadWord (state, instr, LHS + LSImmRHS);
              break;
              break;
 
 
            case 0x5a:          /* Store Word, WriteBack, Pre Inc, Immed.  */
            case 0x5a:          /* Store Word, WriteBack, Pre Inc, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              temp = LHS + LSImmRHS;
              temp = LHS + LSImmRHS;
              if (StoreWord (state, instr, temp))
              if (StoreWord (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x5b:          /* Load Word, WriteBack, Pre Inc, Immed.  */
            case 0x5b:          /* Load Word, WriteBack, Pre Inc, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              temp = LHS + LSImmRHS;
              temp = LHS + LSImmRHS;
              if (LoadWord (state, instr, temp))
              if (LoadWord (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x5c:          /* Store Byte, No WriteBack, Pre Inc, Immed.  */
            case 0x5c:          /* Store Byte, No WriteBack, Pre Inc, Immed.  */
              (void) StoreByte (state, instr, LHS + LSImmRHS);
              (void) StoreByte (state, instr, LHS + LSImmRHS);
              break;
              break;
 
 
            case 0x5d:          /* Load Byte, No WriteBack, Pre Inc, Immed.  */
            case 0x5d:          /* Load Byte, No WriteBack, Pre Inc, Immed.  */
              (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
              (void) LoadByte (state, instr, LHS + LSImmRHS, LUNSIGNED);
              break;
              break;
 
 
            case 0x5e:          /* Store Byte, WriteBack, Pre Inc, Immed.  */
            case 0x5e:          /* Store Byte, WriteBack, Pre Inc, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              temp = LHS + LSImmRHS;
              temp = LHS + LSImmRHS;
              if (StoreByte (state, instr, temp))
              if (StoreByte (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x5f:          /* Load Byte, WriteBack, Pre Inc, Immed.  */
            case 0x5f:          /* Load Byte, WriteBack, Pre Inc, Immed.  */
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              temp = LHS + LSImmRHS;
              temp = LHS + LSImmRHS;
              if (LoadByte (state, instr, temp, LUNSIGNED))
              if (LoadByte (state, instr, temp, LUNSIGNED))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
 
 
              /* Single Data Transfer Register RHS Instructions.  */
              /* Single Data Transfer Register RHS Instructions.  */
 
 
            case 0x60:          /* Store Word, No WriteBack, Post Dec, Reg.  */
            case 0x60:          /* Store Word, No WriteBack, Post Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              if (StoreWord (state, instr, lhs))
              if (StoreWord (state, instr, lhs))
                LSBase = lhs - LSRegRHS;
                LSBase = lhs - LSRegRHS;
              break;
              break;
 
 
            case 0x61:          /* Load Word, No WriteBack, Post Dec, Reg.  */
            case 0x61:          /* Load Word, No WriteBack, Post Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              temp = lhs - LSRegRHS;
              temp = lhs - LSRegRHS;
              if (LoadWord (state, instr, lhs))
              if (LoadWord (state, instr, lhs))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x62:          /* Store Word, WriteBack, Post Dec, Reg.  */
            case 0x62:          /* Store Word, WriteBack, Post Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (StoreWord (state, instr, lhs))
              if (StoreWord (state, instr, lhs))
                LSBase = lhs - LSRegRHS;
                LSBase = lhs - LSRegRHS;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x63:          /* Load Word, WriteBack, Post Dec, Reg.  */
            case 0x63:          /* Load Word, WriteBack, Post Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              temp = lhs - LSRegRHS;
              temp = lhs - LSRegRHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (LoadWord (state, instr, lhs))
              if (LoadWord (state, instr, lhs))
                LSBase = temp;
                LSBase = temp;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x64:          /* Store Byte, No WriteBack, Post Dec, Reg.  */
            case 0x64:          /* Store Byte, No WriteBack, Post Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              if (StoreByte (state, instr, lhs))
              if (StoreByte (state, instr, lhs))
                LSBase = lhs - LSRegRHS;
                LSBase = lhs - LSRegRHS;
              break;
              break;
 
 
            case 0x65:          /* Load Byte, No WriteBack, Post Dec, Reg.  */
            case 0x65:          /* Load Byte, No WriteBack, Post Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              temp = lhs - LSRegRHS;
              temp = lhs - LSRegRHS;
              if (LoadByte (state, instr, lhs, LUNSIGNED))
              if (LoadByte (state, instr, lhs, LUNSIGNED))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x66:          /* Store Byte, WriteBack, Post Dec, Reg.  */
            case 0x66:          /* Store Byte, WriteBack, Post Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (StoreByte (state, instr, lhs))
              if (StoreByte (state, instr, lhs))
                LSBase = lhs - LSRegRHS;
                LSBase = lhs - LSRegRHS;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x67:          /* Load Byte, WriteBack, Post Dec, Reg.  */
            case 0x67:          /* Load Byte, WriteBack, Post Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              temp = lhs - LSRegRHS;
              temp = lhs - LSRegRHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (LoadByte (state, instr, lhs, LUNSIGNED))
              if (LoadByte (state, instr, lhs, LUNSIGNED))
                LSBase = temp;
                LSBase = temp;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x68:          /* Store Word, No WriteBack, Post Inc, Reg.  */
            case 0x68:          /* Store Word, No WriteBack, Post Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              if (StoreWord (state, instr, lhs))
              if (StoreWord (state, instr, lhs))
                LSBase = lhs + LSRegRHS;
                LSBase = lhs + LSRegRHS;
              break;
              break;
 
 
            case 0x69:          /* Load Word, No WriteBack, Post Inc, Reg.  */
            case 0x69:          /* Load Word, No WriteBack, Post Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              temp = lhs + LSRegRHS;
              temp = lhs + LSRegRHS;
              if (LoadWord (state, instr, lhs))
              if (LoadWord (state, instr, lhs))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x6a:          /* Store Word, WriteBack, Post Inc, Reg.  */
            case 0x6a:          /* Store Word, WriteBack, Post Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (StoreWord (state, instr, lhs))
              if (StoreWord (state, instr, lhs))
                LSBase = lhs + LSRegRHS;
                LSBase = lhs + LSRegRHS;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x6b:          /* Load Word, WriteBack, Post Inc, Reg.  */
            case 0x6b:          /* Load Word, WriteBack, Post Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              temp = lhs + LSRegRHS;
              temp = lhs + LSRegRHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (LoadWord (state, instr, lhs))
              if (LoadWord (state, instr, lhs))
                LSBase = temp;
                LSBase = temp;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x6c:          /* Store Byte, No WriteBack, Post Inc, Reg.  */
            case 0x6c:          /* Store Byte, No WriteBack, Post Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              if (StoreByte (state, instr, lhs))
              if (StoreByte (state, instr, lhs))
                LSBase = lhs + LSRegRHS;
                LSBase = lhs + LSRegRHS;
              break;
              break;
 
 
            case 0x6d:          /* Load Byte, No WriteBack, Post Inc, Reg.  */
            case 0x6d:          /* Load Byte, No WriteBack, Post Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              temp = lhs + LSRegRHS;
              temp = lhs + LSRegRHS;
              if (LoadByte (state, instr, lhs, LUNSIGNED))
              if (LoadByte (state, instr, lhs, LUNSIGNED))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x6e:          /* Store Byte, WriteBack, Post Inc, Reg.  */
            case 0x6e:          /* Store Byte, WriteBack, Post Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (StoreByte (state, instr, lhs))
              if (StoreByte (state, instr, lhs))
                LSBase = lhs + LSRegRHS;
                LSBase = lhs + LSRegRHS;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
            case 0x6f:          /* Load Byte, WriteBack, Post Inc, Reg.  */
            case 0x6f:          /* Load Byte, WriteBack, Post Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              lhs = LHS;
              lhs = LHS;
              temp = lhs + LSRegRHS;
              temp = lhs + LSRegRHS;
              state->NtransSig = LOW;
              state->NtransSig = LOW;
              if (LoadByte (state, instr, lhs, LUNSIGNED))
              if (LoadByte (state, instr, lhs, LUNSIGNED))
                LSBase = temp;
                LSBase = temp;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
              break;
              break;
 
 
 
 
            case 0x70:          /* Store Word, No WriteBack, Pre Dec, Reg.  */
            case 0x70:          /* Store Word, No WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              (void) StoreWord (state, instr, LHS - LSRegRHS);
              (void) StoreWord (state, instr, LHS - LSRegRHS);
              break;
              break;
 
 
            case 0x71:          /* Load Word, No WriteBack, Pre Dec, Reg.  */
            case 0x71:          /* Load Word, No WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              (void) LoadWord (state, instr, LHS - LSRegRHS);
              (void) LoadWord (state, instr, LHS - LSRegRHS);
              break;
              break;
 
 
            case 0x72:          /* Store Word, WriteBack, Pre Dec, Reg.  */
            case 0x72:          /* Store Word, WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              temp = LHS - LSRegRHS;
              temp = LHS - LSRegRHS;
              if (StoreWord (state, instr, temp))
              if (StoreWord (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x73:          /* Load Word, WriteBack, Pre Dec, Reg.  */
            case 0x73:          /* Load Word, WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              temp = LHS - LSRegRHS;
              temp = LHS - LSRegRHS;
              if (LoadWord (state, instr, temp))
              if (LoadWord (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x74:          /* Store Byte, No WriteBack, Pre Dec, Reg.  */
            case 0x74:          /* Store Byte, No WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              (void) StoreByte (state, instr, LHS - LSRegRHS);
              (void) StoreByte (state, instr, LHS - LSRegRHS);
              break;
              break;
 
 
            case 0x75:          /* Load Byte, No WriteBack, Pre Dec, Reg.  */
            case 0x75:          /* Load Byte, No WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
              (void) LoadByte (state, instr, LHS - LSRegRHS, LUNSIGNED);
              break;
              break;
 
 
            case 0x76:          /* Store Byte, WriteBack, Pre Dec, Reg.  */
            case 0x76:          /* Store Byte, WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              temp = LHS - LSRegRHS;
              temp = LHS - LSRegRHS;
              if (StoreByte (state, instr, temp))
              if (StoreByte (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x77:          /* Load Byte, WriteBack, Pre Dec, Reg.  */
            case 0x77:          /* Load Byte, WriteBack, Pre Dec, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              temp = LHS - LSRegRHS;
              temp = LHS - LSRegRHS;
              if (LoadByte (state, instr, temp, LUNSIGNED))
              if (LoadByte (state, instr, temp, LUNSIGNED))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x78:          /* Store Word, No WriteBack, Pre Inc, Reg.  */
            case 0x78:          /* Store Word, No WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              (void) StoreWord (state, instr, LHS + LSRegRHS);
              (void) StoreWord (state, instr, LHS + LSRegRHS);
              break;
              break;
 
 
            case 0x79:          /* Load Word, No WriteBack, Pre Inc, Reg.  */
            case 0x79:          /* Load Word, No WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              (void) LoadWord (state, instr, LHS + LSRegRHS);
              (void) LoadWord (state, instr, LHS + LSRegRHS);
              break;
              break;
 
 
            case 0x7a:          /* Store Word, WriteBack, Pre Inc, Reg.  */
            case 0x7a:          /* Store Word, WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              temp = LHS + LSRegRHS;
              temp = LHS + LSRegRHS;
              if (StoreWord (state, instr, temp))
              if (StoreWord (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x7b:          /* Load Word, WriteBack, Pre Inc, Reg.  */
            case 0x7b:          /* Load Word, WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              temp = LHS + LSRegRHS;
              temp = LHS + LSRegRHS;
              if (LoadWord (state, instr, temp))
              if (LoadWord (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x7c:          /* Store Byte, No WriteBack, Pre Inc, Reg.  */
            case 0x7c:          /* Store Byte, No WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
#ifdef MODE32
#ifdef MODE32
                  if (state->is_v6
                  if (state->is_v6
                      && handle_v6_insn (state, instr))
                      && handle_v6_insn (state, instr))
                    break;
                    break;
#endif
#endif
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              (void) StoreByte (state, instr, LHS + LSRegRHS);
              (void) StoreByte (state, instr, LHS + LSRegRHS);
              break;
              break;
 
 
            case 0x7d:          /* Load Byte, No WriteBack, Pre Inc, Reg.  */
            case 0x7d:          /* Load Byte, No WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
              (void) LoadByte (state, instr, LHS + LSRegRHS, LUNSIGNED);
              break;
              break;
 
 
            case 0x7e:          /* Store Byte, WriteBack, Pre Inc, Reg.  */
            case 0x7e:          /* Store Byte, WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              temp = LHS + LSRegRHS;
              temp = LHS + LSRegRHS;
              if (StoreByte (state, instr, temp))
              if (StoreByte (state, instr, temp))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
            case 0x7f:          /* Load Byte, WriteBack, Pre Inc, Reg.  */
            case 0x7f:          /* Load Byte, WriteBack, Pre Inc, Reg.  */
              if (BIT (4))
              if (BIT (4))
                {
                {
                  /* Check for the special breakpoint opcode.
                  /* Check for the special breakpoint opcode.
                     This value should correspond to the value defined
                     This value should correspond to the value defined
                     as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h.  */
                     as ARM_BE_BREAKPOINT in gdb/arm/tm-arm.h.  */
                  if (BITS (0, 19) == 0xfdefe)
                  if (BITS (0, 19) == 0xfdefe)
                    {
                    {
                      if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
                      if (!ARMul_OSHandleSWI (state, SWI_Breakpoint))
                        ARMul_Abort (state, ARMul_SWIV);
                        ARMul_Abort (state, ARMul_SWIV);
                    }
                    }
                  else
                  else
                    ARMul_UndefInstr (state, instr);
                    ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQOffWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRBaseEQDestWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCBaseWb;
              UNDEF_LSRPCOffWb;
              UNDEF_LSRPCOffWb;
              temp = LHS + LSRegRHS;
              temp = LHS + LSRegRHS;
              if (LoadByte (state, instr, temp, LUNSIGNED))
              if (LoadByte (state, instr, temp, LUNSIGNED))
                LSBase = temp;
                LSBase = temp;
              break;
              break;
 
 
 
 
              /* Multiple Data Transfer Instructions.  */
              /* Multiple Data Transfer Instructions.  */
 
 
            case 0x80:          /* Store, No WriteBack, Post Dec.  */
            case 0x80:          /* Store, No WriteBack, Post Dec.  */
              STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
              STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
              break;
              break;
 
 
            case 0x81:          /* Load, No WriteBack, Post Dec.  */
            case 0x81:          /* Load, No WriteBack, Post Dec.  */
              LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
              LOADMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
              break;
              break;
 
 
            case 0x82:          /* Store, WriteBack, Post Dec.  */
            case 0x82:          /* Store, WriteBack, Post Dec.  */
              temp = LSBase - LSMNumRegs;
              temp = LSBase - LSMNumRegs;
              STOREMULT (instr, temp + 4L, temp);
              STOREMULT (instr, temp + 4L, temp);
              break;
              break;
 
 
            case 0x83:          /* Load, WriteBack, Post Dec.  */
            case 0x83:          /* Load, WriteBack, Post Dec.  */
              temp = LSBase - LSMNumRegs;
              temp = LSBase - LSMNumRegs;
              LOADMULT (instr, temp + 4L, temp);
              LOADMULT (instr, temp + 4L, temp);
              break;
              break;
 
 
            case 0x84:          /* Store, Flags, No WriteBack, Post Dec.  */
            case 0x84:          /* Store, Flags, No WriteBack, Post Dec.  */
              STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
              STORESMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
              break;
              break;
 
 
            case 0x85:          /* Load, Flags, No WriteBack, Post Dec.  */
            case 0x85:          /* Load, Flags, No WriteBack, Post Dec.  */
              LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
              LOADSMULT (instr, LSBase - LSMNumRegs + 4L, 0L);
              break;
              break;
 
 
            case 0x86:          /* Store, Flags, WriteBack, Post Dec.  */
            case 0x86:          /* Store, Flags, WriteBack, Post Dec.  */
              temp = LSBase - LSMNumRegs;
              temp = LSBase - LSMNumRegs;
              STORESMULT (instr, temp + 4L, temp);
              STORESMULT (instr, temp + 4L, temp);
              break;
              break;
 
 
            case 0x87:          /* Load, Flags, WriteBack, Post Dec.  */
            case 0x87:          /* Load, Flags, WriteBack, Post Dec.  */
              temp = LSBase - LSMNumRegs;
              temp = LSBase - LSMNumRegs;
              LOADSMULT (instr, temp + 4L, temp);
              LOADSMULT (instr, temp + 4L, temp);
              break;
              break;
 
 
            case 0x88:          /* Store, No WriteBack, Post Inc.  */
            case 0x88:          /* Store, No WriteBack, Post Inc.  */
              STOREMULT (instr, LSBase, 0L);
              STOREMULT (instr, LSBase, 0L);
              break;
              break;
 
 
            case 0x89:          /* Load, No WriteBack, Post Inc.  */
            case 0x89:          /* Load, No WriteBack, Post Inc.  */
              LOADMULT (instr, LSBase, 0L);
              LOADMULT (instr, LSBase, 0L);
              break;
              break;
 
 
            case 0x8a:          /* Store, WriteBack, Post Inc.  */
            case 0x8a:          /* Store, WriteBack, Post Inc.  */
              temp = LSBase;
              temp = LSBase;
              STOREMULT (instr, temp, temp + LSMNumRegs);
              STOREMULT (instr, temp, temp + LSMNumRegs);
              break;
              break;
 
 
            case 0x8b:          /* Load, WriteBack, Post Inc.  */
            case 0x8b:          /* Load, WriteBack, Post Inc.  */
              temp = LSBase;
              temp = LSBase;
              LOADMULT (instr, temp, temp + LSMNumRegs);
              LOADMULT (instr, temp, temp + LSMNumRegs);
              break;
              break;
 
 
            case 0x8c:          /* Store, Flags, No WriteBack, Post Inc.  */
            case 0x8c:          /* Store, Flags, No WriteBack, Post Inc.  */
              STORESMULT (instr, LSBase, 0L);
              STORESMULT (instr, LSBase, 0L);
              break;
              break;
 
 
            case 0x8d:          /* Load, Flags, No WriteBack, Post Inc.  */
            case 0x8d:          /* Load, Flags, No WriteBack, Post Inc.  */
              LOADSMULT (instr, LSBase, 0L);
              LOADSMULT (instr, LSBase, 0L);
              break;
              break;
 
 
            case 0x8e:          /* Store, Flags, WriteBack, Post Inc.  */
            case 0x8e:          /* Store, Flags, WriteBack, Post Inc.  */
              temp = LSBase;
              temp = LSBase;
              STORESMULT (instr, temp, temp + LSMNumRegs);
              STORESMULT (instr, temp, temp + LSMNumRegs);
              break;
              break;
 
 
            case 0x8f:          /* Load, Flags, WriteBack, Post Inc.  */
            case 0x8f:          /* Load, Flags, WriteBack, Post Inc.  */
              temp = LSBase;
              temp = LSBase;
              LOADSMULT (instr, temp, temp + LSMNumRegs);
              LOADSMULT (instr, temp, temp + LSMNumRegs);
              break;
              break;
 
 
            case 0x90:          /* Store, No WriteBack, Pre Dec.  */
            case 0x90:          /* Store, No WriteBack, Pre Dec.  */
              STOREMULT (instr, LSBase - LSMNumRegs, 0L);
              STOREMULT (instr, LSBase - LSMNumRegs, 0L);
              break;
              break;
 
 
            case 0x91:          /* Load, No WriteBack, Pre Dec.  */
            case 0x91:          /* Load, No WriteBack, Pre Dec.  */
              LOADMULT (instr, LSBase - LSMNumRegs, 0L);
              LOADMULT (instr, LSBase - LSMNumRegs, 0L);
              break;
              break;
 
 
            case 0x92:          /* Store, WriteBack, Pre Dec.  */
            case 0x92:          /* Store, WriteBack, Pre Dec.  */
              temp = LSBase - LSMNumRegs;
              temp = LSBase - LSMNumRegs;
              STOREMULT (instr, temp, temp);
              STOREMULT (instr, temp, temp);
              break;
              break;
 
 
            case 0x93:          /* Load, WriteBack, Pre Dec.  */
            case 0x93:          /* Load, WriteBack, Pre Dec.  */
              temp = LSBase - LSMNumRegs;
              temp = LSBase - LSMNumRegs;
              LOADMULT (instr, temp, temp);
              LOADMULT (instr, temp, temp);
              break;
              break;
 
 
            case 0x94:          /* Store, Flags, No WriteBack, Pre Dec.  */
            case 0x94:          /* Store, Flags, No WriteBack, Pre Dec.  */
              STORESMULT (instr, LSBase - LSMNumRegs, 0L);
              STORESMULT (instr, LSBase - LSMNumRegs, 0L);
              break;
              break;
 
 
            case 0x95:          /* Load, Flags, No WriteBack, Pre Dec.  */
            case 0x95:          /* Load, Flags, No WriteBack, Pre Dec.  */
              LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
              LOADSMULT (instr, LSBase - LSMNumRegs, 0L);
              break;
              break;
 
 
            case 0x96:          /* Store, Flags, WriteBack, Pre Dec.  */
            case 0x96:          /* Store, Flags, WriteBack, Pre Dec.  */
              temp = LSBase - LSMNumRegs;
              temp = LSBase - LSMNumRegs;
              STORESMULT (instr, temp, temp);
              STORESMULT (instr, temp, temp);
              break;
              break;
 
 
            case 0x97:          /* Load, Flags, WriteBack, Pre Dec.  */
            case 0x97:          /* Load, Flags, WriteBack, Pre Dec.  */
              temp = LSBase - LSMNumRegs;
              temp = LSBase - LSMNumRegs;
              LOADSMULT (instr, temp, temp);
              LOADSMULT (instr, temp, temp);
              break;
              break;
 
 
            case 0x98:          /* Store, No WriteBack, Pre Inc.  */
            case 0x98:          /* Store, No WriteBack, Pre Inc.  */
              STOREMULT (instr, LSBase + 4L, 0L);
              STOREMULT (instr, LSBase + 4L, 0L);
              break;
              break;
 
 
            case 0x99:          /* Load, No WriteBack, Pre Inc.  */
            case 0x99:          /* Load, No WriteBack, Pre Inc.  */
              LOADMULT (instr, LSBase + 4L, 0L);
              LOADMULT (instr, LSBase + 4L, 0L);
              break;
              break;
 
 
            case 0x9a:          /* Store, WriteBack, Pre Inc.  */
            case 0x9a:          /* Store, WriteBack, Pre Inc.  */
              temp = LSBase;
              temp = LSBase;
              STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
              STOREMULT (instr, temp + 4L, temp + LSMNumRegs);
              break;
              break;
 
 
            case 0x9b:          /* Load, WriteBack, Pre Inc.  */
            case 0x9b:          /* Load, WriteBack, Pre Inc.  */
              temp = LSBase;
              temp = LSBase;
              LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
              LOADMULT (instr, temp + 4L, temp + LSMNumRegs);
              break;
              break;
 
 
            case 0x9c:          /* Store, Flags, No WriteBack, Pre Inc.  */
            case 0x9c:          /* Store, Flags, No WriteBack, Pre Inc.  */
              STORESMULT (instr, LSBase + 4L, 0L);
              STORESMULT (instr, LSBase + 4L, 0L);
              break;
              break;
 
 
            case 0x9d:          /* Load, Flags, No WriteBack, Pre Inc.  */
            case 0x9d:          /* Load, Flags, No WriteBack, Pre Inc.  */
              LOADSMULT (instr, LSBase + 4L, 0L);
              LOADSMULT (instr, LSBase + 4L, 0L);
              break;
              break;
 
 
            case 0x9e:          /* Store, Flags, WriteBack, Pre Inc.  */
            case 0x9e:          /* Store, Flags, WriteBack, Pre Inc.  */
              temp = LSBase;
              temp = LSBase;
              STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
              STORESMULT (instr, temp + 4L, temp + LSMNumRegs);
              break;
              break;
 
 
            case 0x9f:          /* Load, Flags, WriteBack, Pre Inc.  */
            case 0x9f:          /* Load, Flags, WriteBack, Pre Inc.  */
              temp = LSBase;
              temp = LSBase;
              LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
              LOADSMULT (instr, temp + 4L, temp + LSMNumRegs);
              break;
              break;
 
 
 
 
              /* Branch forward.  */
              /* Branch forward.  */
            case 0xa0:
            case 0xa0:
            case 0xa1:
            case 0xa1:
            case 0xa2:
            case 0xa2:
            case 0xa3:
            case 0xa3:
            case 0xa4:
            case 0xa4:
            case 0xa5:
            case 0xa5:
            case 0xa6:
            case 0xa6:
            case 0xa7:
            case 0xa7:
              state->Reg[15] = pc + 8 + POSBRANCH;
              state->Reg[15] = pc + 8 + POSBRANCH;
              FLUSHPIPE;
              FLUSHPIPE;
              break;
              break;
 
 
 
 
              /* Branch backward.  */
              /* Branch backward.  */
            case 0xa8:
            case 0xa8:
            case 0xa9:
            case 0xa9:
            case 0xaa:
            case 0xaa:
            case 0xab:
            case 0xab:
            case 0xac:
            case 0xac:
            case 0xad:
            case 0xad:
            case 0xae:
            case 0xae:
            case 0xaf:
            case 0xaf:
              state->Reg[15] = pc + 8 + NEGBRANCH;
              state->Reg[15] = pc + 8 + NEGBRANCH;
              FLUSHPIPE;
              FLUSHPIPE;
              break;
              break;
 
 
 
 
              /* Branch and Link forward.  */
              /* Branch and Link forward.  */
            case 0xb0:
            case 0xb0:
            case 0xb1:
            case 0xb1:
            case 0xb2:
            case 0xb2:
            case 0xb3:
            case 0xb3:
            case 0xb4:
            case 0xb4:
            case 0xb5:
            case 0xb5:
            case 0xb6:
            case 0xb6:
            case 0xb7:
            case 0xb7:
              /* Put PC into Link.  */
              /* Put PC into Link.  */
#ifdef MODE32
#ifdef MODE32
              state->Reg[14] = pc + 4;
              state->Reg[14] = pc + 4;
#else
#else
              state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
              state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
#endif
#endif
              state->Reg[15] = pc + 8 + POSBRANCH;
              state->Reg[15] = pc + 8 + POSBRANCH;
              FLUSHPIPE;
              FLUSHPIPE;
              break;
              break;
 
 
 
 
              /* Branch and Link backward.  */
              /* Branch and Link backward.  */
            case 0xb8:
            case 0xb8:
            case 0xb9:
            case 0xb9:
            case 0xba:
            case 0xba:
            case 0xbb:
            case 0xbb:
            case 0xbc:
            case 0xbc:
            case 0xbd:
            case 0xbd:
            case 0xbe:
            case 0xbe:
            case 0xbf:
            case 0xbf:
              /* Put PC into Link.  */
              /* Put PC into Link.  */
#ifdef MODE32
#ifdef MODE32
              state->Reg[14] = pc + 4;
              state->Reg[14] = pc + 4;
#else
#else
              state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
              state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE;
#endif
#endif
              state->Reg[15] = pc + 8 + NEGBRANCH;
              state->Reg[15] = pc + 8 + NEGBRANCH;
              FLUSHPIPE;
              FLUSHPIPE;
              break;
              break;
 
 
 
 
              /* Co-Processor Data Transfers.  */
              /* Co-Processor Data Transfers.  */
            case 0xc4:
            case 0xc4:
              if (state->is_v5)
              if (state->is_v5)
                {
                {
                  /* Reading from R15 is UNPREDICTABLE.  */
                  /* Reading from R15 is UNPREDICTABLE.  */
                  if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
                  if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
                    ARMul_UndefInstr (state, instr);
                    ARMul_UndefInstr (state, instr);
                  /* Is access to coprocessor 0 allowed ?  */
                  /* Is access to coprocessor 0 allowed ?  */
                  else if (! CP_ACCESS_ALLOWED (state, CPNum))
                  else if (! CP_ACCESS_ALLOWED (state, CPNum))
                    ARMul_UndefInstr (state, instr);
                    ARMul_UndefInstr (state, instr);
                  /* Special treatment for XScale coprocessors.  */
                  /* Special treatment for XScale coprocessors.  */
                  else if (state->is_XScale)
                  else if (state->is_XScale)
                    {
                    {
                      /* Only opcode 0 is supported.  */
                      /* Only opcode 0 is supported.  */
                      if (BITS (4, 7) != 0x00)
                      if (BITS (4, 7) != 0x00)
                        ARMul_UndefInstr (state, instr);
                        ARMul_UndefInstr (state, instr);
                      /* Only coporcessor 0 is supported.  */
                      /* Only coporcessor 0 is supported.  */
                      else if (CPNum != 0x00)
                      else if (CPNum != 0x00)
                        ARMul_UndefInstr (state, instr);
                        ARMul_UndefInstr (state, instr);
                      /* Only accumulator 0 is supported.  */
                      /* Only accumulator 0 is supported.  */
                      else if (BITS (0, 3) != 0x00)
                      else if (BITS (0, 3) != 0x00)
                        ARMul_UndefInstr (state, instr);
                        ARMul_UndefInstr (state, instr);
                      else
                      else
                        {
                        {
                          /* XScale MAR insn.  Move two registers into accumulator.  */
                          /* XScale MAR insn.  Move two registers into accumulator.  */
                          state->Accumulator = state->Reg[BITS (12, 15)];
                          state->Accumulator = state->Reg[BITS (12, 15)];
                          state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
                          state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32;
                        }
                        }
                    }
                    }
                  else
                  else
                    /* FIXME: Not sure what to do for other v5 processors.  */
                    /* FIXME: Not sure what to do for other v5 processors.  */
                    ARMul_UndefInstr (state, instr);
                    ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              /* Drop through.  */
              /* Drop through.  */
 
 
            case 0xc0:          /* Store , No WriteBack , Post Dec.  */
            case 0xc0:          /* Store , No WriteBack , Post Dec.  */
              ARMul_STC (state, instr, LHS);
              ARMul_STC (state, instr, LHS);
              break;
              break;
 
 
            case 0xc5:
            case 0xc5:
              if (state->is_v5)
              if (state->is_v5)
                {
                {
                  /* Writes to R15 are UNPREDICATABLE.  */
                  /* Writes to R15 are UNPREDICATABLE.  */
                  if (DESTReg == 15 || LHSReg == 15)
                  if (DESTReg == 15 || LHSReg == 15)
                    ARMul_UndefInstr (state, instr);
                    ARMul_UndefInstr (state, instr);
                  /* Is access to the coprocessor allowed ?  */
                  /* Is access to the coprocessor allowed ?  */
                  else if (! CP_ACCESS_ALLOWED (state, CPNum))
                  else if (! CP_ACCESS_ALLOWED (state, CPNum))
                    ARMul_UndefInstr (state, instr);
                    ARMul_UndefInstr (state, instr);
                  /* Special handling for XScale coprcoessors.  */
                  /* Special handling for XScale coprcoessors.  */
                  else if (state->is_XScale)
                  else if (state->is_XScale)
                    {
                    {
                      /* Only opcode 0 is supported.  */
                      /* Only opcode 0 is supported.  */
                      if (BITS (4, 7) != 0x00)
                      if (BITS (4, 7) != 0x00)
                        ARMul_UndefInstr (state, instr);
                        ARMul_UndefInstr (state, instr);
                      /* Only coprocessor 0 is supported.  */
                      /* Only coprocessor 0 is supported.  */
                      else if (CPNum != 0x00)
                      else if (CPNum != 0x00)
                        ARMul_UndefInstr (state, instr);
                        ARMul_UndefInstr (state, instr);
                      /* Only accumulator 0 is supported.  */
                      /* Only accumulator 0 is supported.  */
                      else if (BITS (0, 3) != 0x00)
                      else if (BITS (0, 3) != 0x00)
                        ARMul_UndefInstr (state, instr);
                        ARMul_UndefInstr (state, instr);
                      else
                      else
                        {
                        {
                          /* XScale MRA insn.  Move accumulator into two registers.  */
                          /* XScale MRA insn.  Move accumulator into two registers.  */
                          ARMword t1 = (state->Accumulator >> 32) & 255;
                          ARMword t1 = (state->Accumulator >> 32) & 255;
 
 
                          if (t1 & 128)
                          if (t1 & 128)
                            t1 -= 256;
                            t1 -= 256;
 
 
                          state->Reg[BITS (12, 15)] = state->Accumulator;
                          state->Reg[BITS (12, 15)] = state->Accumulator;
                          state->Reg[BITS (16, 19)] = t1;
                          state->Reg[BITS (16, 19)] = t1;
                          break;
                          break;
                        }
                        }
                    }
                    }
                  else
                  else
                    /* FIXME: Not sure what to do for other v5 processors.  */
                    /* FIXME: Not sure what to do for other v5 processors.  */
                    ARMul_UndefInstr (state, instr);
                    ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              /* Drop through.  */
              /* Drop through.  */
 
 
            case 0xc1:          /* Load , No WriteBack , Post Dec.  */
            case 0xc1:          /* Load , No WriteBack , Post Dec.  */
              ARMul_LDC (state, instr, LHS);
              ARMul_LDC (state, instr, LHS);
              break;
              break;
 
 
            case 0xc2:
            case 0xc2:
            case 0xc6:          /* Store , WriteBack , Post Dec.  */
            case 0xc6:          /* Store , WriteBack , Post Dec.  */
              lhs = LHS;
              lhs = LHS;
              state->Base = lhs - LSCOff;
              state->Base = lhs - LSCOff;
              ARMul_STC (state, instr, lhs);
              ARMul_STC (state, instr, lhs);
              break;
              break;
 
 
            case 0xc3:
            case 0xc3:
            case 0xc7:          /* Load , WriteBack , Post Dec.  */
            case 0xc7:          /* Load , WriteBack , Post Dec.  */
              lhs = LHS;
              lhs = LHS;
              state->Base = lhs - LSCOff;
              state->Base = lhs - LSCOff;
              ARMul_LDC (state, instr, lhs);
              ARMul_LDC (state, instr, lhs);
              break;
              break;
 
 
            case 0xc8:
            case 0xc8:
            case 0xcc:          /* Store , No WriteBack , Post Inc.  */
            case 0xcc:          /* Store , No WriteBack , Post Inc.  */
              ARMul_STC (state, instr, LHS);
              ARMul_STC (state, instr, LHS);
              break;
              break;
 
 
            case 0xc9:
            case 0xc9:
            case 0xcd:          /* Load , No WriteBack , Post Inc.  */
            case 0xcd:          /* Load , No WriteBack , Post Inc.  */
              ARMul_LDC (state, instr, LHS);
              ARMul_LDC (state, instr, LHS);
              break;
              break;
 
 
            case 0xca:
            case 0xca:
            case 0xce:          /* Store , WriteBack , Post Inc.  */
            case 0xce:          /* Store , WriteBack , Post Inc.  */
              lhs = LHS;
              lhs = LHS;
              state->Base = lhs + LSCOff;
              state->Base = lhs + LSCOff;
              ARMul_STC (state, instr, LHS);
              ARMul_STC (state, instr, LHS);
              break;
              break;
 
 
            case 0xcb:
            case 0xcb:
            case 0xcf:          /* Load , WriteBack , Post Inc.  */
            case 0xcf:          /* Load , WriteBack , Post Inc.  */
              lhs = LHS;
              lhs = LHS;
              state->Base = lhs + LSCOff;
              state->Base = lhs + LSCOff;
              ARMul_LDC (state, instr, LHS);
              ARMul_LDC (state, instr, LHS);
              break;
              break;
 
 
            case 0xd0:
            case 0xd0:
            case 0xd4:          /* Store , No WriteBack , Pre Dec.  */
            case 0xd4:          /* Store , No WriteBack , Pre Dec.  */
              ARMul_STC (state, instr, LHS - LSCOff);
              ARMul_STC (state, instr, LHS - LSCOff);
              break;
              break;
 
 
            case 0xd1:
            case 0xd1:
            case 0xd5:          /* Load , No WriteBack , Pre Dec.  */
            case 0xd5:          /* Load , No WriteBack , Pre Dec.  */
              ARMul_LDC (state, instr, LHS - LSCOff);
              ARMul_LDC (state, instr, LHS - LSCOff);
              break;
              break;
 
 
            case 0xd2:
            case 0xd2:
            case 0xd6:          /* Store , WriteBack , Pre Dec.  */
            case 0xd6:          /* Store , WriteBack , Pre Dec.  */
              lhs = LHS - LSCOff;
              lhs = LHS - LSCOff;
              state->Base = lhs;
              state->Base = lhs;
              ARMul_STC (state, instr, lhs);
              ARMul_STC (state, instr, lhs);
              break;
              break;
 
 
            case 0xd3:
            case 0xd3:
            case 0xd7:          /* Load , WriteBack , Pre Dec.  */
            case 0xd7:          /* Load , WriteBack , Pre Dec.  */
              lhs = LHS - LSCOff;
              lhs = LHS - LSCOff;
              state->Base = lhs;
              state->Base = lhs;
              ARMul_LDC (state, instr, lhs);
              ARMul_LDC (state, instr, lhs);
              break;
              break;
 
 
            case 0xd8:
            case 0xd8:
            case 0xdc:          /* Store , No WriteBack , Pre Inc.  */
            case 0xdc:          /* Store , No WriteBack , Pre Inc.  */
              ARMul_STC (state, instr, LHS + LSCOff);
              ARMul_STC (state, instr, LHS + LSCOff);
              break;
              break;
 
 
            case 0xd9:
            case 0xd9:
            case 0xdd:          /* Load , No WriteBack , Pre Inc.  */
            case 0xdd:          /* Load , No WriteBack , Pre Inc.  */
              ARMul_LDC (state, instr, LHS + LSCOff);
              ARMul_LDC (state, instr, LHS + LSCOff);
              break;
              break;
 
 
            case 0xda:
            case 0xda:
            case 0xde:          /* Store , WriteBack , Pre Inc.  */
            case 0xde:          /* Store , WriteBack , Pre Inc.  */
              lhs = LHS + LSCOff;
              lhs = LHS + LSCOff;
              state->Base = lhs;
              state->Base = lhs;
              ARMul_STC (state, instr, lhs);
              ARMul_STC (state, instr, lhs);
              break;
              break;
 
 
            case 0xdb:
            case 0xdb:
            case 0xdf:          /* Load , WriteBack , Pre Inc.  */
            case 0xdf:          /* Load , WriteBack , Pre Inc.  */
              lhs = LHS + LSCOff;
              lhs = LHS + LSCOff;
              state->Base = lhs;
              state->Base = lhs;
              ARMul_LDC (state, instr, lhs);
              ARMul_LDC (state, instr, lhs);
              break;
              break;
 
 
 
 
              /* Co-Processor Register Transfers (MCR) and Data Ops.  */
              /* Co-Processor Register Transfers (MCR) and Data Ops.  */
 
 
            case 0xe2:
            case 0xe2:
              if (! CP_ACCESS_ALLOWED (state, CPNum))
              if (! CP_ACCESS_ALLOWED (state, CPNum))
                {
                {
                  ARMul_UndefInstr (state, instr);
                  ARMul_UndefInstr (state, instr);
                  break;
                  break;
                }
                }
              if (state->is_XScale)
              if (state->is_XScale)
                switch (BITS (18, 19))
                switch (BITS (18, 19))
                  {
                  {
                  case 0x0:
                  case 0x0:
                    if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
                    if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
                      {
                      {
                        /* XScale MIA instruction.  Signed multiplication of
                        /* XScale MIA instruction.  Signed multiplication of
                           two 32 bit values and addition to 40 bit accumulator.  */
                           two 32 bit values and addition to 40 bit accumulator.  */
                        ARMsdword Rm = state->Reg[MULLHSReg];
                        ARMsdword Rm = state->Reg[MULLHSReg];
                        ARMsdword Rs = state->Reg[MULACCReg];
                        ARMsdword Rs = state->Reg[MULACCReg];
 
 
                        if (Rm & (1 << 31))
                        if (Rm & (1 << 31))
                          Rm -= 1ULL << 32;
                          Rm -= 1ULL << 32;
                        if (Rs & (1 << 31))
                        if (Rs & (1 << 31))
                          Rs -= 1ULL << 32;
                          Rs -= 1ULL << 32;
                        state->Accumulator += Rm * Rs;
                        state->Accumulator += Rm * Rs;
                        goto donext;
                        goto donext;
                      }
                      }
                    break;
                    break;
 
 
                  case 0x2:
                  case 0x2:
                    if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
                    if (BITS (4, 11) == 1 && BITS (16, 17) == 0)
                      {
                      {
                        /* XScale MIAPH instruction.  */
                        /* XScale MIAPH instruction.  */
                        ARMword t1 = state->Reg[MULLHSReg] >> 16;
                        ARMword t1 = state->Reg[MULLHSReg] >> 16;
                        ARMword t2 = state->Reg[MULACCReg] >> 16;
                        ARMword t2 = state->Reg[MULACCReg] >> 16;
                        ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
                        ARMword t3 = state->Reg[MULLHSReg] & 0xffff;
                        ARMword t4 = state->Reg[MULACCReg] & 0xffff;
                        ARMword t4 = state->Reg[MULACCReg] & 0xffff;
                        ARMsdword t5;
                        ARMsdword t5;
 
 
                        if (t1 & (1 << 15))
                        if (t1 & (1 << 15))
                          t1 -= 1 << 16;
                          t1 -= 1 << 16;
                        if (t2 & (1 << 15))
                        if (t2 & (1 << 15))
                          t2 -= 1 << 16;
                          t2 -= 1 << 16;
                        if (t3 & (1 << 15))
                        if (t3 & (1 << 15))
                          t3 -= 1 << 16;
                          t3 -= 1 << 16;
                        if (t4 & (1 << 15))
                        if (t4 & (1 << 15))
                          t4 -= 1 << 16;
                          t4 -= 1 << 16;
                        t1 *= t2;
                        t1 *= t2;
                        t5 = t1;
                        t5 = t1;
                        if (t5 & (1 << 31))
                        if (t5 & (1 << 31))
                          t5 -= 1ULL << 32;
                          t5 -= 1ULL << 32;
                        state->Accumulator += t5;
                        state->Accumulator += t5;
                        t3 *= t4;
                        t3 *= t4;
                        t5 = t3;
                        t5 = t3;
                        if (t5 & (1 << 31))
                        if (t5 & (1 << 31))
                          t5 -= 1ULL << 32;
                          t5 -= 1ULL << 32;
                        state->Accumulator += t5;
                        state->Accumulator += t5;
                        goto donext;
                        goto donext;
                      }
                      }
                    break;
                    break;
 
 
                  case 0x3:
                  case 0x3:
                    if (BITS (4, 11) == 1)
                    if (BITS (4, 11) == 1)
                      {
                      {
                        /* XScale MIAxy instruction.  */
                        /* XScale MIAxy instruction.  */
                        ARMword t1;
                        ARMword t1;
                        ARMword t2;
                        ARMword t2;
                        ARMsdword t5;
                        ARMsdword t5;
 
 
                        if (BIT (17))
                        if (BIT (17))
                          t1 = state->Reg[MULLHSReg] >> 16;
                          t1 = state->Reg[MULLHSReg] >> 16;
                        else
                        else
                          t1 = state->Reg[MULLHSReg] & 0xffff;
                          t1 = state->Reg[MULLHSReg] & 0xffff;
 
 
                        if (BIT (16))
                        if (BIT (16))
                          t2 = state->Reg[MULACCReg] >> 16;
                          t2 = state->Reg[MULACCReg] >> 16;
                        else
                        else
                          t2 = state->Reg[MULACCReg] & 0xffff;
                          t2 = state->Reg[MULACCReg] & 0xffff;
 
 
                        if (t1 & (1 << 15))
                        if (t1 & (1 << 15))
                          t1 -= 1 << 16;
                          t1 -= 1 << 16;
                        if (t2 & (1 << 15))
                        if (t2 & (1 << 15))
                          t2 -= 1 << 16;
                          t2 -= 1 << 16;
                        t1 *= t2;
                        t1 *= t2;
                        t5 = t1;
                        t5 = t1;
                        if (t5 & (1 << 31))
                        if (t5 & (1 << 31))
                          t5 -= 1ULL << 32;
                          t5 -= 1ULL << 32;
                        state->Accumulator += t5;
                        state->Accumulator += t5;
                        goto donext;
                        goto donext;
                      }
                      }
                    break;
                    break;
 
 
                  default:
                  default:
                    break;
                    break;
                  }
                  }
              /* Drop through.  */
              /* Drop through.  */
 
 
            case 0xe0:
            case 0xe0:
            case 0xe4:
            case 0xe4:
            case 0xe6:
            case 0xe6:
            case 0xe8:
            case 0xe8:
            case 0xea:
            case 0xea:
            case 0xec:
            case 0xec:
            case 0xee:
            case 0xee:
              if (BIT (4))
              if (BIT (4))
                {
                {
                  /* MCR.  */
                  /* MCR.  */
                  if (DESTReg == 15)
                  if (DESTReg == 15)
                    {
                    {
                      UNDEF_MCRPC;
                      UNDEF_MCRPC;
#ifdef MODE32
#ifdef MODE32
                      ARMul_MCR (state, instr, state->Reg[15] + isize);
                      ARMul_MCR (state, instr, state->Reg[15] + isize);
#else
#else
                      ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
                      ARMul_MCR (state, instr, ECC | ER15INT | EMODE |
                                 ((state->Reg[15] + isize) & R15PCBITS));
                                 ((state->Reg[15] + isize) & R15PCBITS));
#endif
#endif
                    }
                    }
                  else
                  else
                    ARMul_MCR (state, instr, DEST);
                    ARMul_MCR (state, instr, DEST);
                }
                }
              else
              else
                /* CDP Part 1.  */
                /* CDP Part 1.  */
                ARMul_CDP (state, instr);
                ARMul_CDP (state, instr);
              break;
              break;
 
 
 
 
              /* Co-Processor Register Transfers (MRC) and Data Ops.  */
              /* Co-Processor Register Transfers (MRC) and Data Ops.  */
            case 0xe1:
            case 0xe1:
            case 0xe3:
            case 0xe3:
            case 0xe5:
            case 0xe5:
            case 0xe7:
            case 0xe7:
            case 0xe9:
            case 0xe9:
            case 0xeb:
            case 0xeb:
            case 0xed:
            case 0xed:
            case 0xef:
            case 0xef:
              if (BIT (4))
              if (BIT (4))
                {
                {
                  /* MRC */
                  /* MRC */
                  temp = ARMul_MRC (state, instr);
                  temp = ARMul_MRC (state, instr);
                  if (DESTReg == 15)
                  if (DESTReg == 15)
                    {
                    {
                      ASSIGNN ((temp & NBIT) != 0);
                      ASSIGNN ((temp & NBIT) != 0);
                      ASSIGNZ ((temp & ZBIT) != 0);
                      ASSIGNZ ((temp & ZBIT) != 0);
                      ASSIGNC ((temp & CBIT) != 0);
                      ASSIGNC ((temp & CBIT) != 0);
                      ASSIGNV ((temp & VBIT) != 0);
                      ASSIGNV ((temp & VBIT) != 0);
                    }
                    }
                  else
                  else
                    DEST = temp;
                    DEST = temp;
                }
                }
              else
              else
                /* CDP Part 2.  */
                /* CDP Part 2.  */
                ARMul_CDP (state, instr);
                ARMul_CDP (state, instr);
              break;
              break;
 
 
 
 
              /* SWI instruction.  */
              /* SWI instruction.  */
            case 0xf0:
            case 0xf0:
            case 0xf1:
            case 0xf1:
            case 0xf2:
            case 0xf2:
            case 0xf3:
            case 0xf3:
            case 0xf4:
            case 0xf4:
            case 0xf5:
            case 0xf5:
            case 0xf6:
            case 0xf6:
            case 0xf7:
            case 0xf7:
            case 0xf8:
            case 0xf8:
            case 0xf9:
            case 0xf9:
            case 0xfa:
            case 0xfa:
            case 0xfb:
            case 0xfb:
            case 0xfc:
            case 0xfc:
            case 0xfd:
            case 0xfd:
            case 0xfe:
            case 0xfe:
            case 0xff:
            case 0xff:
              if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
              if (instr == ARMul_ABORTWORD && state->AbortAddr == pc)
                {
                {
                  /* A prefetch abort.  */
                  /* A prefetch abort.  */
                  XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
                  XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc);
                  ARMul_Abort (state, ARMul_PrefetchAbortV);
                  ARMul_Abort (state, ARMul_PrefetchAbortV);
                  break;
                  break;
                }
                }
 
 
              if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
              if (!ARMul_OSHandleSWI (state, BITS (0, 23)))
                ARMul_Abort (state, ARMul_SWIV);
                ARMul_Abort (state, ARMul_SWIV);
 
 
              break;
              break;
            }
            }
        }
        }
 
 
#ifdef MODET
#ifdef MODET
    donext:
    donext:
#endif
#endif
 
 
#ifdef NEED_UI_LOOP_HOOK
#ifdef NEED_UI_LOOP_HOOK
      if (deprecated_ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
      if (deprecated_ui_loop_hook != NULL && ui_loop_hook_counter-- < 0)
        {
        {
          ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
          ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL;
          deprecated_ui_loop_hook (0);
          deprecated_ui_loop_hook (0);
        }
        }
#endif /* NEED_UI_LOOP_HOOK */
#endif /* NEED_UI_LOOP_HOOK */
 
 
      if (state->Emulate == ONCE)
      if (state->Emulate == ONCE)
        state->Emulate = STOP;
        state->Emulate = STOP;
      /* If we have changed mode, allow the PC to advance before stopping.  */
      /* If we have changed mode, allow the PC to advance before stopping.  */
      else if (state->Emulate == CHANGEMODE)
      else if (state->Emulate == CHANGEMODE)
        continue;
        continue;
      else if (state->Emulate != RUN)
      else if (state->Emulate != RUN)
        break;
        break;
    }
    }
  while (!stop_simulator);
  while (!stop_simulator);
 
 
  state->decoded = decoded;
  state->decoded = decoded;
  state->loaded = loaded;
  state->loaded = loaded;
  state->pc = pc;
  state->pc = pc;
 
 
  return pc;
  return pc;
}
}
 
 
/* This routine evaluates most Data Processing register RHS's with the S
/* This routine evaluates most Data Processing register RHS's with the S
   bit clear.  It is intended to be called from the macro DPRegRHS, which
   bit clear.  It is intended to be called from the macro DPRegRHS, which
   filters the common case of an unshifted register with in line code.  */
   filters the common case of an unshifted register with in line code.  */
 
 
static ARMword
static ARMword
GetDPRegRHS (ARMul_State * state, ARMword instr)
GetDPRegRHS (ARMul_State * state, ARMword instr)
{
{
  ARMword shamt, base;
  ARMword shamt, base;
 
 
  base = RHSReg;
  base = RHSReg;
  if (BIT (4))
  if (BIT (4))
    {
    {
      /* Shift amount in a register.  */
      /* Shift amount in a register.  */
      UNDEF_Shift;
      UNDEF_Shift;
      INCPC;
      INCPC;
#ifndef MODE32
#ifndef MODE32
      if (base == 15)
      if (base == 15)
        base = ECC | ER15INT | R15PC | EMODE;
        base = ECC | ER15INT | R15PC | EMODE;
      else
      else
#endif
#endif
        base = state->Reg[base];
        base = state->Reg[base];
      ARMul_Icycles (state, 1, 0L);
      ARMul_Icycles (state, 1, 0L);
      shamt = state->Reg[BITS (8, 11)] & 0xff;
      shamt = state->Reg[BITS (8, 11)] & 0xff;
      switch ((int) BITS (5, 6))
      switch ((int) BITS (5, 6))
        {
        {
        case LSL:
        case LSL:
          if (shamt == 0)
          if (shamt == 0)
            return (base);
            return (base);
          else if (shamt >= 32)
          else if (shamt >= 32)
            return (0);
            return (0);
          else
          else
            return (base << shamt);
            return (base << shamt);
        case LSR:
        case LSR:
          if (shamt == 0)
          if (shamt == 0)
            return (base);
            return (base);
          else if (shamt >= 32)
          else if (shamt >= 32)
            return (0);
            return (0);
          else
          else
            return (base >> shamt);
            return (base >> shamt);
        case ASR:
        case ASR:
          if (shamt == 0)
          if (shamt == 0)
            return (base);
            return (base);
          else if (shamt >= 32)
          else if (shamt >= 32)
            return ((ARMword) ((ARMsword) base >> 31L));
            return ((ARMword) ((ARMsword) base >> 31L));
          else
          else
            return ((ARMword) ((ARMsword) base >> (int) shamt));
            return ((ARMword) ((ARMsword) base >> (int) shamt));
        case ROR:
        case ROR:
          shamt &= 0x1f;
          shamt &= 0x1f;
          if (shamt == 0)
          if (shamt == 0)
            return (base);
            return (base);
          else
          else
            return ((base << (32 - shamt)) | (base >> shamt));
            return ((base << (32 - shamt)) | (base >> shamt));
        }
        }
    }
    }
  else
  else
    {
    {
      /* Shift amount is a constant.  */
      /* Shift amount is a constant.  */
#ifndef MODE32
#ifndef MODE32
      if (base == 15)
      if (base == 15)
        base = ECC | ER15INT | R15PC | EMODE;
        base = ECC | ER15INT | R15PC | EMODE;
      else
      else
#endif
#endif
        base = state->Reg[base];
        base = state->Reg[base];
      shamt = BITS (7, 11);
      shamt = BITS (7, 11);
      switch ((int) BITS (5, 6))
      switch ((int) BITS (5, 6))
        {
        {
        case LSL:
        case LSL:
          return (base << shamt);
          return (base << shamt);
        case LSR:
        case LSR:
          if (shamt == 0)
          if (shamt == 0)
            return (0);
            return (0);
          else
          else
            return (base >> shamt);
            return (base >> shamt);
        case ASR:
        case ASR:
          if (shamt == 0)
          if (shamt == 0)
            return ((ARMword) ((ARMsword) base >> 31L));
            return ((ARMword) ((ARMsword) base >> 31L));
          else
          else
            return ((ARMword) ((ARMsword) base >> (int) shamt));
            return ((ARMword) ((ARMsword) base >> (int) shamt));
        case ROR:
        case ROR:
          if (shamt == 0)
          if (shamt == 0)
            /* It's an RRX.  */
            /* It's an RRX.  */
            return ((base >> 1) | (CFLAG << 31));
            return ((base >> 1) | (CFLAG << 31));
          else
          else
            return ((base << (32 - shamt)) | (base >> shamt));
            return ((base << (32 - shamt)) | (base >> shamt));
        }
        }
    }
    }
 
 
  return 0;
  return 0;
}
}
 
 
/* This routine evaluates most Logical Data Processing register RHS's
/* This routine evaluates most Logical Data Processing register RHS's
   with the S bit set.  It is intended to be called from the macro
   with the S bit set.  It is intended to be called from the macro
   DPSRegRHS, which filters the common case of an unshifted register
   DPSRegRHS, which filters the common case of an unshifted register
   with in line code.  */
   with in line code.  */
 
 
static ARMword
static ARMword
GetDPSRegRHS (ARMul_State * state, ARMword instr)
GetDPSRegRHS (ARMul_State * state, ARMword instr)
{
{
  ARMword shamt, base;
  ARMword shamt, base;
 
 
  base = RHSReg;
  base = RHSReg;
  if (BIT (4))
  if (BIT (4))
    {
    {
      /* Shift amount in a register.  */
      /* Shift amount in a register.  */
      UNDEF_Shift;
      UNDEF_Shift;
      INCPC;
      INCPC;
#ifndef MODE32
#ifndef MODE32
      if (base == 15)
      if (base == 15)
        base = ECC | ER15INT | R15PC | EMODE;
        base = ECC | ER15INT | R15PC | EMODE;
      else
      else
#endif
#endif
        base = state->Reg[base];
        base = state->Reg[base];
      ARMul_Icycles (state, 1, 0L);
      ARMul_Icycles (state, 1, 0L);
      shamt = state->Reg[BITS (8, 11)] & 0xff;
      shamt = state->Reg[BITS (8, 11)] & 0xff;
      switch ((int) BITS (5, 6))
      switch ((int) BITS (5, 6))
        {
        {
        case LSL:
        case LSL:
          if (shamt == 0)
          if (shamt == 0)
            return (base);
            return (base);
          else if (shamt == 32)
          else if (shamt == 32)
            {
            {
              ASSIGNC (base & 1);
              ASSIGNC (base & 1);
              return (0);
              return (0);
            }
            }
          else if (shamt > 32)
          else if (shamt > 32)
            {
            {
              CLEARC;
              CLEARC;
              return (0);
              return (0);
            }
            }
          else
          else
            {
            {
              ASSIGNC ((base >> (32 - shamt)) & 1);
              ASSIGNC ((base >> (32 - shamt)) & 1);
              return (base << shamt);
              return (base << shamt);
            }
            }
        case LSR:
        case LSR:
          if (shamt == 0)
          if (shamt == 0)
            return (base);
            return (base);
          else if (shamt == 32)
          else if (shamt == 32)
            {
            {
              ASSIGNC (base >> 31);
              ASSIGNC (base >> 31);
              return (0);
              return (0);
            }
            }
          else if (shamt > 32)
          else if (shamt > 32)
            {
            {
              CLEARC;
              CLEARC;
              return (0);
              return (0);
            }
            }
          else
          else
            {
            {
              ASSIGNC ((base >> (shamt - 1)) & 1);
              ASSIGNC ((base >> (shamt - 1)) & 1);
              return (base >> shamt);
              return (base >> shamt);
            }
            }
        case ASR:
        case ASR:
          if (shamt == 0)
          if (shamt == 0)
            return (base);
            return (base);
          else if (shamt >= 32)
          else if (shamt >= 32)
            {
            {
              ASSIGNC (base >> 31L);
              ASSIGNC (base >> 31L);
              return ((ARMword) ((ARMsword) base >> 31L));
              return ((ARMword) ((ARMsword) base >> 31L));
            }
            }
          else
          else
            {
            {
              ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
              ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
              return ((ARMword) ((ARMsword) base >> (int) shamt));
              return ((ARMword) ((ARMsword) base >> (int) shamt));
            }
            }
        case ROR:
        case ROR:
          if (shamt == 0)
          if (shamt == 0)
            return (base);
            return (base);
          shamt &= 0x1f;
          shamt &= 0x1f;
          if (shamt == 0)
          if (shamt == 0)
            {
            {
              ASSIGNC (base >> 31);
              ASSIGNC (base >> 31);
              return (base);
              return (base);
            }
            }
          else
          else
            {
            {
              ASSIGNC ((base >> (shamt - 1)) & 1);
              ASSIGNC ((base >> (shamt - 1)) & 1);
              return ((base << (32 - shamt)) | (base >> shamt));
              return ((base << (32 - shamt)) | (base >> shamt));
            }
            }
        }
        }
    }
    }
  else
  else
    {
    {
      /* Shift amount is a constant.  */
      /* Shift amount is a constant.  */
#ifndef MODE32
#ifndef MODE32
      if (base == 15)
      if (base == 15)
        base = ECC | ER15INT | R15PC | EMODE;
        base = ECC | ER15INT | R15PC | EMODE;
      else
      else
#endif
#endif
        base = state->Reg[base];
        base = state->Reg[base];
      shamt = BITS (7, 11);
      shamt = BITS (7, 11);
 
 
      switch ((int) BITS (5, 6))
      switch ((int) BITS (5, 6))
        {
        {
        case LSL:
        case LSL:
          ASSIGNC ((base >> (32 - shamt)) & 1);
          ASSIGNC ((base >> (32 - shamt)) & 1);
          return (base << shamt);
          return (base << shamt);
        case LSR:
        case LSR:
          if (shamt == 0)
          if (shamt == 0)
            {
            {
              ASSIGNC (base >> 31);
              ASSIGNC (base >> 31);
              return (0);
              return (0);
            }
            }
          else
          else
            {
            {
              ASSIGNC ((base >> (shamt - 1)) & 1);
              ASSIGNC ((base >> (shamt - 1)) & 1);
              return (base >> shamt);
              return (base >> shamt);
            }
            }
        case ASR:
        case ASR:
          if (shamt == 0)
          if (shamt == 0)
            {
            {
              ASSIGNC (base >> 31L);
              ASSIGNC (base >> 31L);
              return ((ARMword) ((ARMsword) base >> 31L));
              return ((ARMword) ((ARMsword) base >> 31L));
            }
            }
          else
          else
            {
            {
              ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
              ASSIGNC ((ARMword) ((ARMsword) base >> (int) (shamt - 1)) & 1);
              return ((ARMword) ((ARMsword) base >> (int) shamt));
              return ((ARMword) ((ARMsword) base >> (int) shamt));
            }
            }
        case ROR:
        case ROR:
          if (shamt == 0)
          if (shamt == 0)
            {
            {
              /* It's an RRX.  */
              /* It's an RRX.  */
              shamt = CFLAG;
              shamt = CFLAG;
              ASSIGNC (base & 1);
              ASSIGNC (base & 1);
              return ((base >> 1) | (shamt << 31));
              return ((base >> 1) | (shamt << 31));
            }
            }
          else
          else
            {
            {
              ASSIGNC ((base >> (shamt - 1)) & 1);
              ASSIGNC ((base >> (shamt - 1)) & 1);
              return ((base << (32 - shamt)) | (base >> shamt));
              return ((base << (32 - shamt)) | (base >> shamt));
            }
            }
        }
        }
    }
    }
 
 
  return 0;
  return 0;
}
}
 
 
/* This routine handles writes to register 15 when the S bit is not set.  */
/* This routine handles writes to register 15 when the S bit is not set.  */
 
 
static void
static void
WriteR15 (ARMul_State * state, ARMword src)
WriteR15 (ARMul_State * state, ARMword src)
{
{
  /* The ARM documentation states that the two least significant bits
  /* The ARM documentation states that the two least significant bits
     are discarded when setting PC, except in the cases handled by
     are discarded when setting PC, except in the cases handled by
     WriteR15Branch() below.  It's probably an oversight: in THUMB
     WriteR15Branch() below.  It's probably an oversight: in THUMB
     mode, the second least significant bit should probably not be
     mode, the second least significant bit should probably not be
     discarded.  */
     discarded.  */
#ifdef MODET
#ifdef MODET
  if (TFLAG)
  if (TFLAG)
    src &= 0xfffffffe;
    src &= 0xfffffffe;
  else
  else
#endif
#endif
    src &= 0xfffffffc;
    src &= 0xfffffffc;
 
 
#ifdef MODE32
#ifdef MODE32
  state->Reg[15] = src & PCBITS;
  state->Reg[15] = src & PCBITS;
#else
#else
  state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
  state->Reg[15] = (src & R15PCBITS) | ECC | ER15INT | EMODE;
  ARMul_R15Altered (state);
  ARMul_R15Altered (state);
#endif
#endif
 
 
  FLUSHPIPE;
  FLUSHPIPE;
}
}
 
 
/* This routine handles writes to register 15 when the S bit is set.  */
/* This routine handles writes to register 15 when the S bit is set.  */
 
 
static void
static void
WriteSR15 (ARMul_State * state, ARMword src)
WriteSR15 (ARMul_State * state, ARMword src)
{
{
#ifdef MODE32
#ifdef MODE32
  if (state->Bank > 0)
  if (state->Bank > 0)
    {
    {
      state->Cpsr = state->Spsr[state->Bank];
      state->Cpsr = state->Spsr[state->Bank];
      ARMul_CPSRAltered (state);
      ARMul_CPSRAltered (state);
    }
    }
#ifdef MODET
#ifdef MODET
  if (TFLAG)
  if (TFLAG)
    src &= 0xfffffffe;
    src &= 0xfffffffe;
  else
  else
#endif
#endif
    src &= 0xfffffffc;
    src &= 0xfffffffc;
  state->Reg[15] = src & PCBITS;
  state->Reg[15] = src & PCBITS;
#else
#else
#ifdef MODET
#ifdef MODET
  if (TFLAG)
  if (TFLAG)
    /* ARMul_R15Altered would have to support it.  */
    /* ARMul_R15Altered would have to support it.  */
    abort ();
    abort ();
  else
  else
#endif
#endif
    src &= 0xfffffffc;
    src &= 0xfffffffc;
 
 
  if (state->Bank == USERBANK)
  if (state->Bank == USERBANK)
    state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
    state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE;
  else
  else
    state->Reg[15] = src;
    state->Reg[15] = src;
 
 
  ARMul_R15Altered (state);
  ARMul_R15Altered (state);
#endif
#endif
  FLUSHPIPE;
  FLUSHPIPE;
}
}
 
 
/* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
/* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM
   will switch to Thumb mode if the least significant bit is set.  */
   will switch to Thumb mode if the least significant bit is set.  */
 
 
static void
static void
WriteR15Branch (ARMul_State * state, ARMword src)
WriteR15Branch (ARMul_State * state, ARMword src)
{
{
#ifdef MODET
#ifdef MODET
  if (src & 1)
  if (src & 1)
    {
    {
      /* Thumb bit.  */
      /* Thumb bit.  */
      SETT;
      SETT;
      state->Reg[15] = src & 0xfffffffe;
      state->Reg[15] = src & 0xfffffffe;
    }
    }
  else
  else
    {
    {
      CLEART;
      CLEART;
      state->Reg[15] = src & 0xfffffffc;
      state->Reg[15] = src & 0xfffffffc;
    }
    }
  FLUSHPIPE;
  FLUSHPIPE;
#else
#else
  WriteR15 (state, src);
  WriteR15 (state, src);
#endif
#endif
}
}
 
 
/* This routine evaluates most Load and Store register RHS's.  It is
/* This routine evaluates most Load and Store register RHS's.  It is
   intended to be called from the macro LSRegRHS, which filters the
   intended to be called from the macro LSRegRHS, which filters the
   common case of an unshifted register with in line code.  */
   common case of an unshifted register with in line code.  */
 
 
static ARMword
static ARMword
GetLSRegRHS (ARMul_State * state, ARMword instr)
GetLSRegRHS (ARMul_State * state, ARMword instr)
{
{
  ARMword shamt, base;
  ARMword shamt, base;
 
 
  base = RHSReg;
  base = RHSReg;
#ifndef MODE32
#ifndef MODE32
  if (base == 15)
  if (base == 15)
    /* Now forbidden, but ...  */
    /* Now forbidden, but ...  */
    base = ECC | ER15INT | R15PC | EMODE;
    base = ECC | ER15INT | R15PC | EMODE;
  else
  else
#endif
#endif
    base = state->Reg[base];
    base = state->Reg[base];
 
 
  shamt = BITS (7, 11);
  shamt = BITS (7, 11);
  switch ((int) BITS (5, 6))
  switch ((int) BITS (5, 6))
    {
    {
    case LSL:
    case LSL:
      return (base << shamt);
      return (base << shamt);
    case LSR:
    case LSR:
      if (shamt == 0)
      if (shamt == 0)
        return (0);
        return (0);
      else
      else
        return (base >> shamt);
        return (base >> shamt);
    case ASR:
    case ASR:
      if (shamt == 0)
      if (shamt == 0)
        return ((ARMword) ((ARMsword) base >> 31L));
        return ((ARMword) ((ARMsword) base >> 31L));
      else
      else
        return ((ARMword) ((ARMsword) base >> (int) shamt));
        return ((ARMword) ((ARMsword) base >> (int) shamt));
    case ROR:
    case ROR:
      if (shamt == 0)
      if (shamt == 0)
        /* It's an RRX.  */
        /* It's an RRX.  */
        return ((base >> 1) | (CFLAG << 31));
        return ((base >> 1) | (CFLAG << 31));
      else
      else
        return ((base << (32 - shamt)) | (base >> shamt));
        return ((base << (32 - shamt)) | (base >> shamt));
    default:
    default:
      break;
      break;
    }
    }
  return 0;
  return 0;
}
}
 
 
/* This routine evaluates the ARM7T halfword and signed transfer RHS's.  */
/* This routine evaluates the ARM7T halfword and signed transfer RHS's.  */
 
 
static ARMword
static ARMword
GetLS7RHS (ARMul_State * state, ARMword instr)
GetLS7RHS (ARMul_State * state, ARMword instr)
{
{
  if (BIT (22) == 0)
  if (BIT (22) == 0)
    {
    {
      /* Register.  */
      /* Register.  */
#ifndef MODE32
#ifndef MODE32
      if (RHSReg == 15)
      if (RHSReg == 15)
        /* Now forbidden, but ...  */
        /* Now forbidden, but ...  */
        return ECC | ER15INT | R15PC | EMODE;
        return ECC | ER15INT | R15PC | EMODE;
#endif
#endif
      return state->Reg[RHSReg];
      return state->Reg[RHSReg];
    }
    }
 
 
  /* Immediate.  */
  /* Immediate.  */
  return BITS (0, 3) | (BITS (8, 11) << 4);
  return BITS (0, 3) | (BITS (8, 11) << 4);
}
}
 
 
/* This function does the work of loading a word for a LDR instruction.  */
/* This function does the work of loading a word for a LDR instruction.  */
 
 
static unsigned
static unsigned
LoadWord (ARMul_State * state, ARMword instr, ARMword address)
LoadWord (ARMul_State * state, ARMword instr, ARMword address)
{
{
  ARMword dest;
  ARMword dest;
 
 
  BUSUSEDINCPCS;
  BUSUSEDINCPCS;
#ifndef MODE32
#ifndef MODE32
  if (ADDREXCEPT (address))
  if (ADDREXCEPT (address))
    INTERNALABORT (address);
    INTERNALABORT (address);
#endif
#endif
 
 
  dest = ARMul_LoadWordN (state, address);
  dest = ARMul_LoadWordN (state, address);
 
 
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      TAKEABORT;
      TAKEABORT;
      return state->lateabtSig;
      return state->lateabtSig;
    }
    }
  if (address & 3)
  if (address & 3)
    dest = ARMul_Align (state, address, dest);
    dest = ARMul_Align (state, address, dest);
  WRITEDESTB (dest);
  WRITEDESTB (dest);
  ARMul_Icycles (state, 1, 0L);
  ARMul_Icycles (state, 1, 0L);
 
 
  return (DESTReg != LHSReg);
  return (DESTReg != LHSReg);
}
}
 
 
#ifdef MODET
#ifdef MODET
/* This function does the work of loading a halfword.  */
/* This function does the work of loading a halfword.  */
 
 
static unsigned
static unsigned
LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address,
              int signextend)
              int signextend)
{
{
  ARMword dest;
  ARMword dest;
 
 
  BUSUSEDINCPCS;
  BUSUSEDINCPCS;
#ifndef MODE32
#ifndef MODE32
  if (ADDREXCEPT (address))
  if (ADDREXCEPT (address))
    INTERNALABORT (address);
    INTERNALABORT (address);
#endif
#endif
  dest = ARMul_LoadHalfWord (state, address);
  dest = ARMul_LoadHalfWord (state, address);
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      TAKEABORT;
      TAKEABORT;
      return state->lateabtSig;
      return state->lateabtSig;
    }
    }
  UNDEF_LSRBPC;
  UNDEF_LSRBPC;
  if (signextend)
  if (signextend)
    if (dest & 1 << (16 - 1))
    if (dest & 1 << (16 - 1))
      dest = (dest & ((1 << 16) - 1)) - (1 << 16);
      dest = (dest & ((1 << 16) - 1)) - (1 << 16);
 
 
  WRITEDEST (dest);
  WRITEDEST (dest);
  ARMul_Icycles (state, 1, 0L);
  ARMul_Icycles (state, 1, 0L);
  return (DESTReg != LHSReg);
  return (DESTReg != LHSReg);
}
}
 
 
#endif /* MODET */
#endif /* MODET */
 
 
/* This function does the work of loading a byte for a LDRB instruction.  */
/* This function does the work of loading a byte for a LDRB instruction.  */
 
 
static unsigned
static unsigned
LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend)
{
{
  ARMword dest;
  ARMword dest;
 
 
  BUSUSEDINCPCS;
  BUSUSEDINCPCS;
#ifndef MODE32
#ifndef MODE32
  if (ADDREXCEPT (address))
  if (ADDREXCEPT (address))
    INTERNALABORT (address);
    INTERNALABORT (address);
#endif
#endif
  dest = ARMul_LoadByte (state, address);
  dest = ARMul_LoadByte (state, address);
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      TAKEABORT;
      TAKEABORT;
      return state->lateabtSig;
      return state->lateabtSig;
    }
    }
  UNDEF_LSRBPC;
  UNDEF_LSRBPC;
  if (signextend)
  if (signextend)
    if (dest & 1 << (8 - 1))
    if (dest & 1 << (8 - 1))
      dest = (dest & ((1 << 8) - 1)) - (1 << 8);
      dest = (dest & ((1 << 8) - 1)) - (1 << 8);
 
 
  WRITEDEST (dest);
  WRITEDEST (dest);
  ARMul_Icycles (state, 1, 0L);
  ARMul_Icycles (state, 1, 0L);
 
 
  return (DESTReg != LHSReg);
  return (DESTReg != LHSReg);
}
}
 
 
/* This function does the work of loading two words for a LDRD instruction.  */
/* This function does the work of loading two words for a LDRD instruction.  */
 
 
static void
static void
Handle_Load_Double (ARMul_State * state, ARMword instr)
Handle_Load_Double (ARMul_State * state, ARMword instr)
{
{
  ARMword dest_reg;
  ARMword dest_reg;
  ARMword addr_reg;
  ARMword addr_reg;
  ARMword write_back  = BIT (21);
  ARMword write_back  = BIT (21);
  ARMword immediate   = BIT (22);
  ARMword immediate   = BIT (22);
  ARMword add_to_base = BIT (23);
  ARMword add_to_base = BIT (23);
  ARMword pre_indexed = BIT (24);
  ARMword pre_indexed = BIT (24);
  ARMword offset;
  ARMword offset;
  ARMword addr;
  ARMword addr;
  ARMword sum;
  ARMword sum;
  ARMword base;
  ARMword base;
  ARMword value1;
  ARMword value1;
  ARMword value2;
  ARMword value2;
 
 
  BUSUSEDINCPCS;
  BUSUSEDINCPCS;
 
 
  /* If the writeback bit is set, the pre-index bit must be clear.  */
  /* If the writeback bit is set, the pre-index bit must be clear.  */
  if (write_back && ! pre_indexed)
  if (write_back && ! pre_indexed)
    {
    {
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return;
      return;
    }
    }
 
 
  /* Extract the base address register.  */
  /* Extract the base address register.  */
  addr_reg = LHSReg;
  addr_reg = LHSReg;
 
 
  /* Extract the destination register and check it.  */
  /* Extract the destination register and check it.  */
  dest_reg = DESTReg;
  dest_reg = DESTReg;
 
 
  /* Destination register must be even.  */
  /* Destination register must be even.  */
  if ((dest_reg & 1)
  if ((dest_reg & 1)
    /* Destination register cannot be LR.  */
    /* Destination register cannot be LR.  */
      || (dest_reg == 14))
      || (dest_reg == 14))
    {
    {
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return;
      return;
    }
    }
 
 
  /* Compute the base address.  */
  /* Compute the base address.  */
  base = state->Reg[addr_reg];
  base = state->Reg[addr_reg];
 
 
  /* Compute the offset.  */
  /* Compute the offset.  */
  offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
  offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
 
 
  /* Compute the sum of the two.  */
  /* Compute the sum of the two.  */
  if (add_to_base)
  if (add_to_base)
    sum = base + offset;
    sum = base + offset;
  else
  else
    sum = base - offset;
    sum = base - offset;
 
 
  /* If this is a pre-indexed mode use the sum.  */
  /* If this is a pre-indexed mode use the sum.  */
  if (pre_indexed)
  if (pre_indexed)
    addr = sum;
    addr = sum;
  else
  else
    addr = base;
    addr = base;
 
 
  /* The address must be aligned on a 8 byte boundary.  */
  /* The address must be aligned on a 8 byte boundary.  */
  if (addr & 0x7)
  if (addr & 0x7)
    {
    {
#ifdef ABORTS
#ifdef ABORTS
      ARMul_DATAABORT (addr);
      ARMul_DATAABORT (addr);
#else
#else
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
#endif
#endif
      return;
      return;
    }
    }
 
 
  /* For pre indexed or post indexed addressing modes,
  /* For pre indexed or post indexed addressing modes,
     check that the destination registers do not overlap
     check that the destination registers do not overlap
     the address registers.  */
     the address registers.  */
  if ((! pre_indexed || write_back)
  if ((! pre_indexed || write_back)
      && (   addr_reg == dest_reg
      && (   addr_reg == dest_reg
          || addr_reg == dest_reg + 1))
          || addr_reg == dest_reg + 1))
    {
    {
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return;
      return;
    }
    }
 
 
  /* Load the words.  */
  /* Load the words.  */
  value1 = ARMul_LoadWordN (state, addr);
  value1 = ARMul_LoadWordN (state, addr);
  value2 = ARMul_LoadWordN (state, addr + 4);
  value2 = ARMul_LoadWordN (state, addr + 4);
 
 
  /* Check for data aborts.  */
  /* Check for data aborts.  */
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      TAKEABORT;
      TAKEABORT;
      return;
      return;
    }
    }
 
 
  ARMul_Icycles (state, 2, 0L);
  ARMul_Icycles (state, 2, 0L);
 
 
  /* Store the values.  */
  /* Store the values.  */
  state->Reg[dest_reg] = value1;
  state->Reg[dest_reg] = value1;
  state->Reg[dest_reg + 1] = value2;
  state->Reg[dest_reg + 1] = value2;
 
 
  /* Do the post addressing and writeback.  */
  /* Do the post addressing and writeback.  */
  if (! pre_indexed)
  if (! pre_indexed)
    addr = sum;
    addr = sum;
 
 
  if (! pre_indexed || write_back)
  if (! pre_indexed || write_back)
    state->Reg[addr_reg] = addr;
    state->Reg[addr_reg] = addr;
}
}
 
 
/* This function does the work of storing two words for a STRD instruction.  */
/* This function does the work of storing two words for a STRD instruction.  */
 
 
static void
static void
Handle_Store_Double (ARMul_State * state, ARMword instr)
Handle_Store_Double (ARMul_State * state, ARMword instr)
{
{
  ARMword src_reg;
  ARMword src_reg;
  ARMword addr_reg;
  ARMword addr_reg;
  ARMword write_back  = BIT (21);
  ARMword write_back  = BIT (21);
  ARMword immediate   = BIT (22);
  ARMword immediate   = BIT (22);
  ARMword add_to_base = BIT (23);
  ARMword add_to_base = BIT (23);
  ARMword pre_indexed = BIT (24);
  ARMword pre_indexed = BIT (24);
  ARMword offset;
  ARMword offset;
  ARMword addr;
  ARMword addr;
  ARMword sum;
  ARMword sum;
  ARMword base;
  ARMword base;
 
 
  BUSUSEDINCPCS;
  BUSUSEDINCPCS;
 
 
  /* If the writeback bit is set, the pre-index bit must be clear.  */
  /* If the writeback bit is set, the pre-index bit must be clear.  */
  if (write_back && ! pre_indexed)
  if (write_back && ! pre_indexed)
    {
    {
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return;
      return;
    }
    }
 
 
  /* Extract the base address register.  */
  /* Extract the base address register.  */
  addr_reg = LHSReg;
  addr_reg = LHSReg;
 
 
  /* Base register cannot be PC.  */
  /* Base register cannot be PC.  */
  if (addr_reg == 15)
  if (addr_reg == 15)
    {
    {
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return;
      return;
    }
    }
 
 
  /* Extract the source register.  */
  /* Extract the source register.  */
  src_reg = DESTReg;
  src_reg = DESTReg;
 
 
  /* Source register must be even.  */
  /* Source register must be even.  */
  if (src_reg & 1)
  if (src_reg & 1)
    {
    {
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return;
      return;
    }
    }
 
 
  /* Compute the base address.  */
  /* Compute the base address.  */
  base = state->Reg[addr_reg];
  base = state->Reg[addr_reg];
 
 
  /* Compute the offset.  */
  /* Compute the offset.  */
  offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
  offset = immediate ? ((BITS (8, 11) << 4) | BITS (0, 3)) : state->Reg[RHSReg];
 
 
  /* Compute the sum of the two.  */
  /* Compute the sum of the two.  */
  if (add_to_base)
  if (add_to_base)
    sum = base + offset;
    sum = base + offset;
  else
  else
    sum = base - offset;
    sum = base - offset;
 
 
  /* If this is a pre-indexed mode use the sum.  */
  /* If this is a pre-indexed mode use the sum.  */
  if (pre_indexed)
  if (pre_indexed)
    addr = sum;
    addr = sum;
  else
  else
    addr = base;
    addr = base;
 
 
  /* The address must be aligned on a 8 byte boundary.  */
  /* The address must be aligned on a 8 byte boundary.  */
  if (addr & 0x7)
  if (addr & 0x7)
    {
    {
#ifdef ABORTS
#ifdef ABORTS
      ARMul_DATAABORT (addr);
      ARMul_DATAABORT (addr);
#else
#else
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
#endif
#endif
      return;
      return;
    }
    }
 
 
  /* For pre indexed or post indexed addressing modes,
  /* For pre indexed or post indexed addressing modes,
     check that the destination registers do not overlap
     check that the destination registers do not overlap
     the address registers.  */
     the address registers.  */
  if ((! pre_indexed || write_back)
  if ((! pre_indexed || write_back)
      && (   addr_reg == src_reg
      && (   addr_reg == src_reg
          || addr_reg == src_reg + 1))
          || addr_reg == src_reg + 1))
    {
    {
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return;
      return;
    }
    }
 
 
  /* Load the words.  */
  /* Load the words.  */
  ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
  ARMul_StoreWordN (state, addr, state->Reg[src_reg]);
  ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
  ARMul_StoreWordN (state, addr + 4, state->Reg[src_reg + 1]);
 
 
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      TAKEABORT;
      TAKEABORT;
      return;
      return;
    }
    }
 
 
  /* Do the post addressing and writeback.  */
  /* Do the post addressing and writeback.  */
  if (! pre_indexed)
  if (! pre_indexed)
    addr = sum;
    addr = sum;
 
 
  if (! pre_indexed || write_back)
  if (! pre_indexed || write_back)
    state->Reg[addr_reg] = addr;
    state->Reg[addr_reg] = addr;
}
}
 
 
/* This function does the work of storing a word from a STR instruction.  */
/* This function does the work of storing a word from a STR instruction.  */
 
 
static unsigned
static unsigned
StoreWord (ARMul_State * state, ARMword instr, ARMword address)
StoreWord (ARMul_State * state, ARMword instr, ARMword address)
{
{
  BUSUSEDINCPCN;
  BUSUSEDINCPCN;
#ifndef MODE32
#ifndef MODE32
  if (DESTReg == 15)
  if (DESTReg == 15)
    state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
    state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
#endif
#endif
#ifdef MODE32
#ifdef MODE32
  ARMul_StoreWordN (state, address, DEST);
  ARMul_StoreWordN (state, address, DEST);
#else
#else
  if (VECTORACCESS (address) || ADDREXCEPT (address))
  if (VECTORACCESS (address) || ADDREXCEPT (address))
    {
    {
      INTERNALABORT (address);
      INTERNALABORT (address);
      (void) ARMul_LoadWordN (state, address);
      (void) ARMul_LoadWordN (state, address);
    }
    }
  else
  else
    ARMul_StoreWordN (state, address, DEST);
    ARMul_StoreWordN (state, address, DEST);
#endif
#endif
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      TAKEABORT;
      TAKEABORT;
      return state->lateabtSig;
      return state->lateabtSig;
    }
    }
  return TRUE;
  return TRUE;
}
}
 
 
#ifdef MODET
#ifdef MODET
/* This function does the work of storing a byte for a STRH instruction.  */
/* This function does the work of storing a byte for a STRH instruction.  */
 
 
static unsigned
static unsigned
StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address)
{
{
  BUSUSEDINCPCN;
  BUSUSEDINCPCN;
 
 
#ifndef MODE32
#ifndef MODE32
  if (DESTReg == 15)
  if (DESTReg == 15)
    state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
    state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
#endif
#endif
 
 
#ifdef MODE32
#ifdef MODE32
  ARMul_StoreHalfWord (state, address, DEST);
  ARMul_StoreHalfWord (state, address, DEST);
#else
#else
  if (VECTORACCESS (address) || ADDREXCEPT (address))
  if (VECTORACCESS (address) || ADDREXCEPT (address))
    {
    {
      INTERNALABORT (address);
      INTERNALABORT (address);
      (void) ARMul_LoadHalfWord (state, address);
      (void) ARMul_LoadHalfWord (state, address);
    }
    }
  else
  else
    ARMul_StoreHalfWord (state, address, DEST);
    ARMul_StoreHalfWord (state, address, DEST);
#endif
#endif
 
 
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      TAKEABORT;
      TAKEABORT;
      return state->lateabtSig;
      return state->lateabtSig;
    }
    }
  return TRUE;
  return TRUE;
}
}
 
 
#endif /* MODET */
#endif /* MODET */
 
 
/* This function does the work of storing a byte for a STRB instruction.  */
/* This function does the work of storing a byte for a STRB instruction.  */
 
 
static unsigned
static unsigned
StoreByte (ARMul_State * state, ARMword instr, ARMword address)
StoreByte (ARMul_State * state, ARMword instr, ARMword address)
{
{
  BUSUSEDINCPCN;
  BUSUSEDINCPCN;
#ifndef MODE32
#ifndef MODE32
  if (DESTReg == 15)
  if (DESTReg == 15)
    state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
    state->Reg[15] = ECC | ER15INT | R15PC | EMODE;
#endif
#endif
#ifdef MODE32
#ifdef MODE32
  ARMul_StoreByte (state, address, DEST);
  ARMul_StoreByte (state, address, DEST);
#else
#else
  if (VECTORACCESS (address) || ADDREXCEPT (address))
  if (VECTORACCESS (address) || ADDREXCEPT (address))
    {
    {
      INTERNALABORT (address);
      INTERNALABORT (address);
      (void) ARMul_LoadByte (state, address);
      (void) ARMul_LoadByte (state, address);
    }
    }
  else
  else
    ARMul_StoreByte (state, address, DEST);
    ARMul_StoreByte (state, address, DEST);
#endif
#endif
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      TAKEABORT;
      TAKEABORT;
      return state->lateabtSig;
      return state->lateabtSig;
    }
    }
  UNDEF_LSRBPC;
  UNDEF_LSRBPC;
  return TRUE;
  return TRUE;
}
}
 
 
/* This function does the work of loading the registers listed in an LDM
/* This function does the work of loading the registers listed in an LDM
   instruction, when the S bit is clear.  The code here is always increment
   instruction, when the S bit is clear.  The code here is always increment
   after, it's up to the caller to get the input address correct and to
   after, it's up to the caller to get the input address correct and to
   handle base register modification.  */
   handle base register modification.  */
 
 
static void
static void
LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase)
{
{
  ARMword dest, temp;
  ARMword dest, temp;
 
 
  UNDEF_LSMNoRegs;
  UNDEF_LSMNoRegs;
  UNDEF_LSMPCBase;
  UNDEF_LSMPCBase;
  UNDEF_LSMBaseInListWb;
  UNDEF_LSMBaseInListWb;
  BUSUSEDINCPCS;
  BUSUSEDINCPCS;
#ifndef MODE32
#ifndef MODE32
  if (ADDREXCEPT (address))
  if (ADDREXCEPT (address))
    INTERNALABORT (address);
    INTERNALABORT (address);
#endif
#endif
  if (BIT (21) && LHSReg != 15)
  if (BIT (21) && LHSReg != 15)
    LSBase = WBBase;
    LSBase = WBBase;
 
 
  /* N cycle first.  */
  /* N cycle first.  */
  for (temp = 0; !BIT (temp); temp++)
  for (temp = 0; !BIT (temp); temp++)
    ;
    ;
 
 
  dest = ARMul_LoadWordN (state, address);
  dest = ARMul_LoadWordN (state, address);
 
 
  if (!state->abortSig && !state->Aborted)
  if (!state->abortSig && !state->Aborted)
    state->Reg[temp++] = dest;
    state->Reg[temp++] = dest;
  else if (!state->Aborted)
  else if (!state->Aborted)
    {
    {
      XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
      XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
      state->Aborted = ARMul_DataAbortV;
      state->Aborted = ARMul_DataAbortV;
    }
    }
 
 
  /* S cycles from here on.  */
  /* S cycles from here on.  */
  for (; temp < 16; temp ++)
  for (; temp < 16; temp ++)
    if (BIT (temp))
    if (BIT (temp))
      {
      {
        /* Load this register.  */
        /* Load this register.  */
        address += 4;
        address += 4;
        dest = ARMul_LoadWordS (state, address);
        dest = ARMul_LoadWordS (state, address);
 
 
        if (!state->abortSig && !state->Aborted)
        if (!state->abortSig && !state->Aborted)
          state->Reg[temp] = dest;
          state->Reg[temp] = dest;
        else if (!state->Aborted)
        else if (!state->Aborted)
          {
          {
            XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
            XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
            state->Aborted = ARMul_DataAbortV;
            state->Aborted = ARMul_DataAbortV;
          }
          }
      }
      }
 
 
  if (BIT (15) && !state->Aborted)
  if (BIT (15) && !state->Aborted)
    /* PC is in the reg list.  */
    /* PC is in the reg list.  */
    WriteR15Branch (state, PC);
    WriteR15Branch (state, PC);
 
 
  /* To write back the final register.  */
  /* To write back the final register.  */
  ARMul_Icycles (state, 1, 0L);
  ARMul_Icycles (state, 1, 0L);
 
 
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      if (BIT (21) && LHSReg != 15)
      if (BIT (21) && LHSReg != 15)
        LSBase = WBBase;
        LSBase = WBBase;
      TAKEABORT;
      TAKEABORT;
    }
    }
}
}
 
 
/* This function does the work of loading the registers listed in an LDM
/* This function does the work of loading the registers listed in an LDM
   instruction, when the S bit is set. The code here is always increment
   instruction, when the S bit is set. The code here is always increment
   after, it's up to the caller to get the input address correct and to
   after, it's up to the caller to get the input address correct and to
   handle base register modification.  */
   handle base register modification.  */
 
 
static void
static void
LoadSMult (ARMul_State * state,
LoadSMult (ARMul_State * state,
           ARMword       instr,
           ARMword       instr,
           ARMword       address,
           ARMword       address,
           ARMword       WBBase)
           ARMword       WBBase)
{
{
  ARMword dest, temp;
  ARMword dest, temp;
 
 
  UNDEF_LSMNoRegs;
  UNDEF_LSMNoRegs;
  UNDEF_LSMPCBase;
  UNDEF_LSMPCBase;
  UNDEF_LSMBaseInListWb;
  UNDEF_LSMBaseInListWb;
 
 
  BUSUSEDINCPCS;
  BUSUSEDINCPCS;
 
 
#ifndef MODE32
#ifndef MODE32
  if (ADDREXCEPT (address))
  if (ADDREXCEPT (address))
    INTERNALABORT (address);
    INTERNALABORT (address);
#endif
#endif
 
 
  if (BIT (21) && LHSReg != 15)
  if (BIT (21) && LHSReg != 15)
    LSBase = WBBase;
    LSBase = WBBase;
 
 
  if (!BIT (15) && state->Bank != USERBANK)
  if (!BIT (15) && state->Bank != USERBANK)
    {
    {
      /* Temporary reg bank switch.  */
      /* Temporary reg bank switch.  */
      (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
      (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
      UNDEF_LSMUserBankWb;
      UNDEF_LSMUserBankWb;
    }
    }
 
 
  /* N cycle first.  */
  /* N cycle first.  */
  for (temp = 0; !BIT (temp); temp ++)
  for (temp = 0; !BIT (temp); temp ++)
    ;
    ;
 
 
  dest = ARMul_LoadWordN (state, address);
  dest = ARMul_LoadWordN (state, address);
 
 
  if (!state->abortSig)
  if (!state->abortSig)
    state->Reg[temp++] = dest;
    state->Reg[temp++] = dest;
  else if (!state->Aborted)
  else if (!state->Aborted)
    {
    {
      XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
      XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
      state->Aborted = ARMul_DataAbortV;
      state->Aborted = ARMul_DataAbortV;
    }
    }
 
 
  /* S cycles from here on.  */
  /* S cycles from here on.  */
  for (; temp < 16; temp++)
  for (; temp < 16; temp++)
    if (BIT (temp))
    if (BIT (temp))
      {
      {
        /* Load this register.  */
        /* Load this register.  */
        address += 4;
        address += 4;
        dest = ARMul_LoadWordS (state, address);
        dest = ARMul_LoadWordS (state, address);
 
 
        if (!state->abortSig && !state->Aborted)
        if (!state->abortSig && !state->Aborted)
          state->Reg[temp] = dest;
          state->Reg[temp] = dest;
        else if (!state->Aborted)
        else if (!state->Aborted)
          {
          {
            XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
            XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
            state->Aborted = ARMul_DataAbortV;
            state->Aborted = ARMul_DataAbortV;
          }
          }
      }
      }
 
 
  if (BIT (15) && !state->Aborted)
  if (BIT (15) && !state->Aborted)
    {
    {
      /* PC is in the reg list.  */
      /* PC is in the reg list.  */
#ifdef MODE32
#ifdef MODE32
      if (state->Mode != USER26MODE && state->Mode != USER32MODE)
      if (state->Mode != USER26MODE && state->Mode != USER32MODE)
        {
        {
          state->Cpsr = GETSPSR (state->Bank);
          state->Cpsr = GETSPSR (state->Bank);
          ARMul_CPSRAltered (state);
          ARMul_CPSRAltered (state);
        }
        }
 
 
      WriteR15 (state, PC);
      WriteR15 (state, PC);
#else
#else
      if (state->Mode == USER26MODE || state->Mode == USER32MODE)
      if (state->Mode == USER26MODE || state->Mode == USER32MODE)
        {
        {
          /* Protect bits in user mode.  */
          /* Protect bits in user mode.  */
          ASSIGNN ((state->Reg[15] & NBIT) != 0);
          ASSIGNN ((state->Reg[15] & NBIT) != 0);
          ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
          ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
          ASSIGNC ((state->Reg[15] & CBIT) != 0);
          ASSIGNC ((state->Reg[15] & CBIT) != 0);
          ASSIGNV ((state->Reg[15] & VBIT) != 0);
          ASSIGNV ((state->Reg[15] & VBIT) != 0);
        }
        }
      else
      else
        ARMul_R15Altered (state);
        ARMul_R15Altered (state);
 
 
      FLUSHPIPE;
      FLUSHPIPE;
#endif
#endif
    }
    }
 
 
  if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
  if (!BIT (15) && state->Mode != USER26MODE && state->Mode != USER32MODE)
    /* Restore the correct bank.  */
    /* Restore the correct bank.  */
    (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
    (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
 
 
  /* To write back the final register.  */
  /* To write back the final register.  */
  ARMul_Icycles (state, 1, 0L);
  ARMul_Icycles (state, 1, 0L);
 
 
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      if (BIT (21) && LHSReg != 15)
      if (BIT (21) && LHSReg != 15)
        LSBase = WBBase;
        LSBase = WBBase;
 
 
      TAKEABORT;
      TAKEABORT;
    }
    }
}
}
 
 
/* This function does the work of storing the registers listed in an STM
/* This function does the work of storing the registers listed in an STM
   instruction, when the S bit is clear.  The code here is always increment
   instruction, when the S bit is clear.  The code here is always increment
   after, it's up to the caller to get the input address correct and to
   after, it's up to the caller to get the input address correct and to
   handle base register modification.  */
   handle base register modification.  */
 
 
static void
static void
StoreMult (ARMul_State * state,
StoreMult (ARMul_State * state,
           ARMword instr,
           ARMword instr,
           ARMword address,
           ARMword address,
           ARMword WBBase)
           ARMword WBBase)
{
{
  ARMword temp;
  ARMword temp;
 
 
  UNDEF_LSMNoRegs;
  UNDEF_LSMNoRegs;
  UNDEF_LSMPCBase;
  UNDEF_LSMPCBase;
  UNDEF_LSMBaseInListWb;
  UNDEF_LSMBaseInListWb;
 
 
  if (!TFLAG)
  if (!TFLAG)
    /* N-cycle, increment the PC and update the NextInstr state.  */
    /* N-cycle, increment the PC and update the NextInstr state.  */
    BUSUSEDINCPCN;
    BUSUSEDINCPCN;
 
 
#ifndef MODE32
#ifndef MODE32
  if (VECTORACCESS (address) || ADDREXCEPT (address))
  if (VECTORACCESS (address) || ADDREXCEPT (address))
    INTERNALABORT (address);
    INTERNALABORT (address);
 
 
  if (BIT (15))
  if (BIT (15))
    PATCHR15;
    PATCHR15;
#endif
#endif
 
 
  /* N cycle first.  */
  /* N cycle first.  */
  for (temp = 0; !BIT (temp); temp ++)
  for (temp = 0; !BIT (temp); temp ++)
    ;
    ;
 
 
#ifdef MODE32
#ifdef MODE32
  ARMul_StoreWordN (state, address, state->Reg[temp++]);
  ARMul_StoreWordN (state, address, state->Reg[temp++]);
#else
#else
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      (void) ARMul_LoadWordN (state, address);
      (void) ARMul_LoadWordN (state, address);
 
 
      /* Fake the Stores as Loads.  */
      /* Fake the Stores as Loads.  */
      for (; temp < 16; temp++)
      for (; temp < 16; temp++)
        if (BIT (temp))
        if (BIT (temp))
          {
          {
            /* Save this register.  */
            /* Save this register.  */
            address += 4;
            address += 4;
            (void) ARMul_LoadWordS (state, address);
            (void) ARMul_LoadWordS (state, address);
          }
          }
 
 
      if (BIT (21) && LHSReg != 15)
      if (BIT (21) && LHSReg != 15)
        LSBase = WBBase;
        LSBase = WBBase;
      TAKEABORT;
      TAKEABORT;
      return;
      return;
    }
    }
  else
  else
    ARMul_StoreWordN (state, address, state->Reg[temp++]);
    ARMul_StoreWordN (state, address, state->Reg[temp++]);
#endif
#endif
 
 
  if (state->abortSig && !state->Aborted)
  if (state->abortSig && !state->Aborted)
    {
    {
      XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
      XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
      state->Aborted = ARMul_DataAbortV;
      state->Aborted = ARMul_DataAbortV;
    }
    }
 
 
  if (BIT (21) && LHSReg != 15)
  if (BIT (21) && LHSReg != 15)
    LSBase = WBBase;
    LSBase = WBBase;
 
 
  /* S cycles from here on.  */
  /* S cycles from here on.  */
  for (; temp < 16; temp ++)
  for (; temp < 16; temp ++)
    if (BIT (temp))
    if (BIT (temp))
      {
      {
        /* Save this register.  */
        /* Save this register.  */
        address += 4;
        address += 4;
 
 
        ARMul_StoreWordS (state, address, state->Reg[temp]);
        ARMul_StoreWordS (state, address, state->Reg[temp]);
 
 
        if (state->abortSig && !state->Aborted)
        if (state->abortSig && !state->Aborted)
          {
          {
            XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
            XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
            state->Aborted = ARMul_DataAbortV;
            state->Aborted = ARMul_DataAbortV;
          }
          }
      }
      }
 
 
  if (state->Aborted)
  if (state->Aborted)
    TAKEABORT;
    TAKEABORT;
}
}
 
 
/* This function does the work of storing the registers listed in an STM
/* This function does the work of storing the registers listed in an STM
   instruction when the S bit is set.  The code here is always increment
   instruction when the S bit is set.  The code here is always increment
   after, it's up to the caller to get the input address correct and to
   after, it's up to the caller to get the input address correct and to
   handle base register modification.  */
   handle base register modification.  */
 
 
static void
static void
StoreSMult (ARMul_State * state,
StoreSMult (ARMul_State * state,
            ARMword       instr,
            ARMword       instr,
            ARMword       address,
            ARMword       address,
            ARMword       WBBase)
            ARMword       WBBase)
{
{
  ARMword temp;
  ARMword temp;
 
 
  UNDEF_LSMNoRegs;
  UNDEF_LSMNoRegs;
  UNDEF_LSMPCBase;
  UNDEF_LSMPCBase;
  UNDEF_LSMBaseInListWb;
  UNDEF_LSMBaseInListWb;
 
 
  BUSUSEDINCPCN;
  BUSUSEDINCPCN;
 
 
#ifndef MODE32
#ifndef MODE32
  if (VECTORACCESS (address) || ADDREXCEPT (address))
  if (VECTORACCESS (address) || ADDREXCEPT (address))
    INTERNALABORT (address);
    INTERNALABORT (address);
 
 
  if (BIT (15))
  if (BIT (15))
    PATCHR15;
    PATCHR15;
#endif
#endif
 
 
  if (state->Bank != USERBANK)
  if (state->Bank != USERBANK)
    {
    {
      /* Force User Bank.  */
      /* Force User Bank.  */
      (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
      (void) ARMul_SwitchMode (state, state->Mode, USER26MODE);
      UNDEF_LSMUserBankWb;
      UNDEF_LSMUserBankWb;
    }
    }
 
 
  for (temp = 0; !BIT (temp); temp++)
  for (temp = 0; !BIT (temp); temp++)
    ;   /* N cycle first.  */
    ;   /* N cycle first.  */
 
 
#ifdef MODE32
#ifdef MODE32
  ARMul_StoreWordN (state, address, state->Reg[temp++]);
  ARMul_StoreWordN (state, address, state->Reg[temp++]);
#else
#else
  if (state->Aborted)
  if (state->Aborted)
    {
    {
      (void) ARMul_LoadWordN (state, address);
      (void) ARMul_LoadWordN (state, address);
 
 
      for (; temp < 16; temp++)
      for (; temp < 16; temp++)
        /* Fake the Stores as Loads.  */
        /* Fake the Stores as Loads.  */
        if (BIT (temp))
        if (BIT (temp))
          {
          {
            /* Save this register.  */
            /* Save this register.  */
            address += 4;
            address += 4;
 
 
            (void) ARMul_LoadWordS (state, address);
            (void) ARMul_LoadWordS (state, address);
          }
          }
 
 
      if (BIT (21) && LHSReg != 15)
      if (BIT (21) && LHSReg != 15)
        LSBase = WBBase;
        LSBase = WBBase;
 
 
      TAKEABORT;
      TAKEABORT;
      return;
      return;
    }
    }
  else
  else
    ARMul_StoreWordN (state, address, state->Reg[temp++]);
    ARMul_StoreWordN (state, address, state->Reg[temp++]);
#endif
#endif
 
 
  if (state->abortSig && !state->Aborted)
  if (state->abortSig && !state->Aborted)
    {
    {
      XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
      XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
      state->Aborted = ARMul_DataAbortV;
      state->Aborted = ARMul_DataAbortV;
    }
    }
 
 
  /* S cycles from here on.  */
  /* S cycles from here on.  */
  for (; temp < 16; temp++)
  for (; temp < 16; temp++)
    if (BIT (temp))
    if (BIT (temp))
      {
      {
        /* Save this register.  */
        /* Save this register.  */
        address += 4;
        address += 4;
 
 
        ARMul_StoreWordS (state, address, state->Reg[temp]);
        ARMul_StoreWordS (state, address, state->Reg[temp]);
 
 
        if (state->abortSig && !state->Aborted)
        if (state->abortSig && !state->Aborted)
          {
          {
            XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
            XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address);
            state->Aborted = ARMul_DataAbortV;
            state->Aborted = ARMul_DataAbortV;
          }
          }
      }
      }
 
 
  if (state->Mode != USER26MODE && state->Mode != USER32MODE)
  if (state->Mode != USER26MODE && state->Mode != USER32MODE)
    /* Restore the correct bank.  */
    /* Restore the correct bank.  */
    (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
    (void) ARMul_SwitchMode (state, USER26MODE, state->Mode);
 
 
  if (BIT (21) && LHSReg != 15)
  if (BIT (21) && LHSReg != 15)
    LSBase = WBBase;
    LSBase = WBBase;
 
 
  if (state->Aborted)
  if (state->Aborted)
    TAKEABORT;
    TAKEABORT;
}
}
 
 
/* This function does the work of adding two 32bit values
/* This function does the work of adding two 32bit values
   together, and calculating if a carry has occurred.  */
   together, and calculating if a carry has occurred.  */
 
 
static ARMword
static ARMword
Add32 (ARMword a1, ARMword a2, int *carry)
Add32 (ARMword a1, ARMword a2, int *carry)
{
{
  ARMword result = (a1 + a2);
  ARMword result = (a1 + a2);
  unsigned int uresult = (unsigned int) result;
  unsigned int uresult = (unsigned int) result;
  unsigned int ua1 = (unsigned int) a1;
  unsigned int ua1 = (unsigned int) a1;
 
 
  /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
  /* If (result == RdLo) and (state->Reg[nRdLo] == 0),
     or (result > RdLo) then we have no carry.  */
     or (result > RdLo) then we have no carry.  */
  if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
  if ((uresult == ua1) ? (a2 != 0) : (uresult < ua1))
    *carry = 1;
    *carry = 1;
  else
  else
    *carry = 0;
    *carry = 0;
 
 
  return result;
  return result;
}
}
 
 
/* This function does the work of multiplying
/* This function does the work of multiplying
   two 32bit values to give a 64bit result.  */
   two 32bit values to give a 64bit result.  */
 
 
static unsigned
static unsigned
Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc)
{
{
  /* Operand register numbers.  */
  /* Operand register numbers.  */
  int nRdHi, nRdLo, nRs, nRm;
  int nRdHi, nRdLo, nRs, nRm;
  ARMword RdHi = 0, RdLo = 0, Rm;
  ARMword RdHi = 0, RdLo = 0, Rm;
  /* Cycle count.  */
  /* Cycle count.  */
  int scount;
  int scount;
 
 
  nRdHi = BITS (16, 19);
  nRdHi = BITS (16, 19);
  nRdLo = BITS (12, 15);
  nRdLo = BITS (12, 15);
  nRs = BITS (8, 11);
  nRs = BITS (8, 11);
  nRm = BITS (0, 3);
  nRm = BITS (0, 3);
 
 
  /* Needed to calculate the cycle count.  */
  /* Needed to calculate the cycle count.  */
  Rm = state->Reg[nRm];
  Rm = state->Reg[nRm];
 
 
  /* Check for illegal operand combinations first.  */
  /* Check for illegal operand combinations first.  */
  if (   nRdHi != 15
  if (   nRdHi != 15
      && nRdLo != 15
      && nRdLo != 15
      && nRs   != 15
      && nRs   != 15
      && nRm   != 15
      && nRm   != 15
      && nRdHi != nRdLo
      && nRdHi != nRdLo
      && nRdHi != nRm
      && nRdHi != nRm
      && nRdLo != nRm)
      && nRdLo != nRm)
    {
    {
      /* Intermediate results.  */
      /* Intermediate results.  */
      ARMword lo, mid1, mid2, hi;
      ARMword lo, mid1, mid2, hi;
      int carry;
      int carry;
      ARMword Rs = state->Reg[nRs];
      ARMword Rs = state->Reg[nRs];
      int sign = 0;
      int sign = 0;
 
 
      if (msigned)
      if (msigned)
        {
        {
          /* Compute sign of result and adjust operands if necessary.  */
          /* Compute sign of result and adjust operands if necessary.  */
          sign = (Rm ^ Rs) & 0x80000000;
          sign = (Rm ^ Rs) & 0x80000000;
 
 
          if (((ARMsword) Rm) < 0)
          if (((ARMsword) Rm) < 0)
            Rm = -Rm;
            Rm = -Rm;
 
 
          if (((ARMsword) Rs) < 0)
          if (((ARMsword) Rs) < 0)
            Rs = -Rs;
            Rs = -Rs;
        }
        }
 
 
      /* We can split the 32x32 into four 16x16 operations. This
      /* We can split the 32x32 into four 16x16 operations. This
         ensures that we do not lose precision on 32bit only hosts.  */
         ensures that we do not lose precision on 32bit only hosts.  */
      lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
      lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF));
      mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
      mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
      mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
      mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF));
      hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
      hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF));
 
 
      /* We now need to add all of these results together, taking
      /* We now need to add all of these results together, taking
         care to propogate the carries from the additions.  */
         care to propogate the carries from the additions.  */
      RdLo = Add32 (lo, (mid1 << 16), &carry);
      RdLo = Add32 (lo, (mid1 << 16), &carry);
      RdHi = carry;
      RdHi = carry;
      RdLo = Add32 (RdLo, (mid2 << 16), &carry);
      RdLo = Add32 (RdLo, (mid2 << 16), &carry);
      RdHi +=
      RdHi +=
        (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
        (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi);
 
 
      if (sign)
      if (sign)
        {
        {
          /* Negate result if necessary.  */
          /* Negate result if necessary.  */
          RdLo = ~RdLo;
          RdLo = ~RdLo;
          RdHi = ~RdHi;
          RdHi = ~RdHi;
          if (RdLo == 0xFFFFFFFF)
          if (RdLo == 0xFFFFFFFF)
            {
            {
              RdLo = 0;
              RdLo = 0;
              RdHi += 1;
              RdHi += 1;
            }
            }
          else
          else
            RdLo += 1;
            RdLo += 1;
        }
        }
 
 
      state->Reg[nRdLo] = RdLo;
      state->Reg[nRdLo] = RdLo;
      state->Reg[nRdHi] = RdHi;
      state->Reg[nRdHi] = RdHi;
    }
    }
  else
  else
    fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
    fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n");
 
 
  if (scc)
  if (scc)
    /* Ensure that both RdHi and RdLo are used to compute Z,
    /* Ensure that both RdHi and RdLo are used to compute Z,
       but don't let RdLo's sign bit make it to N.  */
       but don't let RdLo's sign bit make it to N.  */
    ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
    ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
 
 
  /* The cycle count depends on whether the instruction is a signed or
  /* The cycle count depends on whether the instruction is a signed or
     unsigned multiply, and what bits are clear in the multiplier.  */
     unsigned multiply, and what bits are clear in the multiplier.  */
  if (msigned && (Rm & ((unsigned) 1 << 31)))
  if (msigned && (Rm & ((unsigned) 1 << 31)))
    /* Invert the bits to make the check against zero.  */
    /* Invert the bits to make the check against zero.  */
    Rm = ~Rm;
    Rm = ~Rm;
 
 
  if ((Rm & 0xFFFFFF00) == 0)
  if ((Rm & 0xFFFFFF00) == 0)
    scount = 1;
    scount = 1;
  else if ((Rm & 0xFFFF0000) == 0)
  else if ((Rm & 0xFFFF0000) == 0)
    scount = 2;
    scount = 2;
  else if ((Rm & 0xFF000000) == 0)
  else if ((Rm & 0xFF000000) == 0)
    scount = 3;
    scount = 3;
  else
  else
    scount = 4;
    scount = 4;
 
 
  return 2 + scount;
  return 2 + scount;
}
}
 
 
/* This function does the work of multiplying two 32bit
/* This function does the work of multiplying two 32bit
   values and adding a 64bit value to give a 64bit result.  */
   values and adding a 64bit value to give a 64bit result.  */
 
 
static unsigned
static unsigned
MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc)
{
{
  unsigned scount;
  unsigned scount;
  ARMword RdLo, RdHi;
  ARMword RdLo, RdHi;
  int nRdHi, nRdLo;
  int nRdHi, nRdLo;
  int carry = 0;
  int carry = 0;
 
 
  nRdHi = BITS (16, 19);
  nRdHi = BITS (16, 19);
  nRdLo = BITS (12, 15);
  nRdLo = BITS (12, 15);
 
 
  RdHi = state->Reg[nRdHi];
  RdHi = state->Reg[nRdHi];
  RdLo = state->Reg[nRdLo];
  RdLo = state->Reg[nRdLo];
 
 
  scount = Multiply64 (state, instr, msigned, LDEFAULT);
  scount = Multiply64 (state, instr, msigned, LDEFAULT);
 
 
  RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
  RdLo = Add32 (RdLo, state->Reg[nRdLo], &carry);
  RdHi = (RdHi + state->Reg[nRdHi]) + carry;
  RdHi = (RdHi + state->Reg[nRdHi]) + carry;
 
 
  state->Reg[nRdLo] = RdLo;
  state->Reg[nRdLo] = RdLo;
  state->Reg[nRdHi] = RdHi;
  state->Reg[nRdHi] = RdHi;
 
 
  if (scc)
  if (scc)
    /* Ensure that both RdHi and RdLo are used to compute Z,
    /* Ensure that both RdHi and RdLo are used to compute Z,
       but don't let RdLo's sign bit make it to N.  */
       but don't let RdLo's sign bit make it to N.  */
    ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
    ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF));
 
 
  /* Extra cycle for addition.  */
  /* Extra cycle for addition.  */
  return scount + 1;
  return scount + 1;
}
}
 
 

powered by: WebSVN 2.1.0

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