OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [gdb-6.8/] [pre-binutils-2.20.1-sync/] [sim/] [arm/] [iwmmxt.c] - Diff between revs 24 and 157

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 24 Rev 157
/*  iwmmxt.c -- Intel(r) Wireless MMX(tm) technology co-processor interface.
/*  iwmmxt.c -- Intel(r) Wireless MMX(tm) technology co-processor interface.
    Copyright (C) 2002, 2007, 2008 Free Software Foundation, Inc.
    Copyright (C) 2002, 2007, 2008 Free Software Foundation, Inc.
    Contributed by matthew green (mrg@redhat.com).
    Contributed by matthew green (mrg@redhat.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 3 of the License, or
    the Free Software Foundation; either version 3 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, see <http://www.gnu.org/licenses/>. */
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 
#include "armdefs.h"
#include "armdefs.h"
#include "armos.h"
#include "armos.h"
#include "armemu.h"
#include "armemu.h"
#include "ansidecl.h"
#include "ansidecl.h"
#include "iwmmxt.h"
#include "iwmmxt.h"
 
 
/* #define DEBUG 1 */
/* #define DEBUG 1 */
 
 
/* Intel(r) Wireless MMX(tm) technology co-processor.
/* Intel(r) Wireless MMX(tm) technology co-processor.
   It uses co-processor numbers (0 and 1).  There are 16 vector registers wRx
   It uses co-processor numbers (0 and 1).  There are 16 vector registers wRx
   and 16 control registers wCx.  Co-processors 0 and 1 are used in MCR/MRC
   and 16 control registers wCx.  Co-processors 0 and 1 are used in MCR/MRC
   to access wRx and wCx respectively.  */
   to access wRx and wCx respectively.  */
 
 
static ARMdword wR[16];
static ARMdword wR[16];
static ARMword  wC[16] = { 0x69051010 };
static ARMword  wC[16] = { 0x69051010 };
 
 
#define SUBSTR(w,t,m,n) ((t)(w <<  ((sizeof (t) * 8 - 1) - (n))) \
#define SUBSTR(w,t,m,n) ((t)(w <<  ((sizeof (t) * 8 - 1) - (n))) \
                               >> (((sizeof (t) * 8 - 1) - (n)) + (m)))
                               >> (((sizeof (t) * 8 - 1) - (n)) + (m)))
#define wCBITS(w,x,y)   SUBSTR (wC[w], ARMword, x, y)
#define wCBITS(w,x,y)   SUBSTR (wC[w], ARMword, x, y)
#define wRBITS(w,x,y)   SUBSTR (wR[w], ARMdword, x, y)
#define wRBITS(w,x,y)   SUBSTR (wR[w], ARMdword, x, y)
#define wCID   0
#define wCID   0
#define wCon   1
#define wCon   1
#define wCSSF  2
#define wCSSF  2
#define wCASF  3
#define wCASF  3
#define wCGR0  8
#define wCGR0  8
#define wCGR1  9
#define wCGR1  9
#define wCGR2 10
#define wCGR2 10
#define wCGR3 11
#define wCGR3 11
 
 
/* Bits in the wCon register.  */
/* Bits in the wCon register.  */
#define WCON_CUP        (1 << 0)
#define WCON_CUP        (1 << 0)
#define WCON_MUP        (1 << 1)
#define WCON_MUP        (1 << 1)
 
 
/* Set the SIMD wCASF flags for 8, 16, 32 or 64-bit operations.  */
/* Set the SIMD wCASF flags for 8, 16, 32 or 64-bit operations.  */
#define SIMD8_SET(x,  v, n, b)  (x) |= ((v != 0) << ((((b) + 1) * 4) + (n)))
#define SIMD8_SET(x,  v, n, b)  (x) |= ((v != 0) << ((((b) + 1) * 4) + (n)))
#define SIMD16_SET(x, v, n, h)  (x) |= ((v != 0) << ((((h) + 1) * 8) + (n)))
#define SIMD16_SET(x, v, n, h)  (x) |= ((v != 0) << ((((h) + 1) * 8) + (n)))
#define SIMD32_SET(x, v, n, w)  (x) |= ((v != 0) << ((((w) + 1) * 16) + (n)))
#define SIMD32_SET(x, v, n, w)  (x) |= ((v != 0) << ((((w) + 1) * 16) + (n)))
#define SIMD64_SET(x, v, n)     (x) |= ((v != 0) << (32 + (n)))
#define SIMD64_SET(x, v, n)     (x) |= ((v != 0) << (32 + (n)))
 
 
/* Flags to pass as "n" above.  */
/* Flags to pass as "n" above.  */
#define SIMD_NBIT       -1
#define SIMD_NBIT       -1
#define SIMD_ZBIT       -2
#define SIMD_ZBIT       -2
#define SIMD_CBIT       -3
#define SIMD_CBIT       -3
#define SIMD_VBIT       -4
#define SIMD_VBIT       -4
 
 
/* Various status bit macros.  */
/* Various status bit macros.  */
#define NBIT8(x)        ((x) & 0x80)
#define NBIT8(x)        ((x) & 0x80)
#define NBIT16(x)       ((x) & 0x8000)
#define NBIT16(x)       ((x) & 0x8000)
#define NBIT32(x)       ((x) & 0x80000000)
#define NBIT32(x)       ((x) & 0x80000000)
#define NBIT64(x)       ((x) & 0x8000000000000000ULL)
#define NBIT64(x)       ((x) & 0x8000000000000000ULL)
#define ZBIT8(x)        (((x) & 0xff) == 0)
#define ZBIT8(x)        (((x) & 0xff) == 0)
#define ZBIT16(x)       (((x) & 0xffff) == 0)
#define ZBIT16(x)       (((x) & 0xffff) == 0)
#define ZBIT32(x)       (((x) & 0xffffffff) == 0)
#define ZBIT32(x)       (((x) & 0xffffffff) == 0)
#define ZBIT64(x)       (x == 0)
#define ZBIT64(x)       (x == 0)
 
 
/* Access byte/half/word "n" of register "x".  */
/* Access byte/half/word "n" of register "x".  */
#define wRBYTE(x,n)     wRBITS ((x), (n) * 8, (n) * 8 + 7)
#define wRBYTE(x,n)     wRBITS ((x), (n) * 8, (n) * 8 + 7)
#define wRHALF(x,n)     wRBITS ((x), (n) * 16, (n) * 16 + 15)
#define wRHALF(x,n)     wRBITS ((x), (n) * 16, (n) * 16 + 15)
#define wRWORD(x,n)     wRBITS ((x), (n) * 32, (n) * 32 + 31)
#define wRWORD(x,n)     wRBITS ((x), (n) * 32, (n) * 32 + 31)
 
 
/* Macro to handle how the G bit selects wCGR registers.  */
/* Macro to handle how the G bit selects wCGR registers.  */
#define DECODE_G_BIT(state, instr, shift)       \
#define DECODE_G_BIT(state, instr, shift)       \
{                                               \
{                                               \
  unsigned int reg;                             \
  unsigned int reg;                             \
                                                \
                                                \
  reg = BITS (0, 3);                             \
  reg = BITS (0, 3);                             \
                                                \
                                                \
  if (BIT (8))  /* G */                         \
  if (BIT (8))  /* G */                         \
    {                                           \
    {                                           \
      if (reg < wCGR0 || reg > wCGR3)           \
      if (reg < wCGR0 || reg > wCGR3)           \
        {                                       \
        {                                       \
          ARMul_UndefInstr (state, instr);      \
          ARMul_UndefInstr (state, instr);      \
          return ARMul_DONE;                    \
          return ARMul_DONE;                    \
        }                                       \
        }                                       \
      shift = wC [reg];                         \
      shift = wC [reg];                         \
    }                                           \
    }                                           \
  else                                          \
  else                                          \
    shift = wR [reg];                           \
    shift = wR [reg];                           \
                                                \
                                                \
  shift &= 0xff;                                \
  shift &= 0xff;                                \
}
}
 
 
/* Index calculations for the satrv[] array.  */
/* Index calculations for the satrv[] array.  */
#define BITIDX8(x)      (x)
#define BITIDX8(x)      (x)
#define BITIDX16(x)     (((x) + 1) * 2 - 1)
#define BITIDX16(x)     (((x) + 1) * 2 - 1)
#define BITIDX32(x)     (((x) + 1) * 4 - 1)
#define BITIDX32(x)     (((x) + 1) * 4 - 1)
 
 
/* Sign extension macros.  */
/* Sign extension macros.  */
#define EXTEND8(a)      ((a) & 0x80 ? ((a) | 0xffffff00) : (a))
#define EXTEND8(a)      ((a) & 0x80 ? ((a) | 0xffffff00) : (a))
#define EXTEND16(a)     ((a) & 0x8000 ? ((a) | 0xffff0000) : (a))
#define EXTEND16(a)     ((a) & 0x8000 ? ((a) | 0xffff0000) : (a))
#define EXTEND32(a)     ((a) & 0x80000000ULL ? ((a) | 0xffffffff00000000ULL) : (a))
#define EXTEND32(a)     ((a) & 0x80000000ULL ? ((a) | 0xffffffff00000000ULL) : (a))
 
 
/* Set the wCSSF from 8 values.  */
/* Set the wCSSF from 8 values.  */
#define SET_wCSSF(a,b,c,d,e,f,g,h) \
#define SET_wCSSF(a,b,c,d,e,f,g,h) \
  wC[wCSSF] = (((h) != 0) << 7) | (((g) != 0) << 6) \
  wC[wCSSF] = (((h) != 0) << 7) | (((g) != 0) << 6) \
            | (((f) != 0) << 5) | (((e) != 0) << 4) \
            | (((f) != 0) << 5) | (((e) != 0) << 4) \
            | (((d) != 0) << 3) | (((c) != 0) << 2) \
            | (((d) != 0) << 3) | (((c) != 0) << 2) \
            | (((b) != 0) << 1) | (((a) != 0) << 0);
            | (((b) != 0) << 1) | (((a) != 0) << 0);
 
 
/* Set the wCSSR from an array with 8 values.  */
/* Set the wCSSR from an array with 8 values.  */
#define SET_wCSSFvec(v) \
#define SET_wCSSFvec(v) \
  SET_wCSSF((v)[0],(v)[1],(v)[2],(v)[3],(v)[4],(v)[5],(v)[6],(v)[7])
  SET_wCSSF((v)[0],(v)[1],(v)[2],(v)[3],(v)[4],(v)[5],(v)[6],(v)[7])
 
 
/* Size qualifiers for vector operations.  */
/* Size qualifiers for vector operations.  */
#define Bqual                   0
#define Bqual                   0
#define Hqual                   1
#define Hqual                   1
#define Wqual                   2
#define Wqual                   2
#define Dqual                   3
#define Dqual                   3
 
 
/* Saturation qualifiers for vector operations.  */
/* Saturation qualifiers for vector operations.  */
#define NoSaturation            0
#define NoSaturation            0
#define UnsignedSaturation      1
#define UnsignedSaturation      1
#define SignedSaturation        3
#define SignedSaturation        3
 
 


/* Prototypes.  */
/* Prototypes.  */
static ARMword         Add32  (ARMword,  ARMword,  int *, int *, ARMword);
static ARMword         Add32  (ARMword,  ARMword,  int *, int *, ARMword);
static ARMdword        AddS32 (ARMdword, ARMdword, int *, int *);
static ARMdword        AddS32 (ARMdword, ARMdword, int *, int *);
static ARMdword        AddU32 (ARMdword, ARMdword, int *, int *);
static ARMdword        AddU32 (ARMdword, ARMdword, int *, int *);
static ARMword         AddS16 (ARMword,  ARMword,  int *, int *);
static ARMword         AddS16 (ARMword,  ARMword,  int *, int *);
static ARMword         AddU16 (ARMword,  ARMword,  int *, int *);
static ARMword         AddU16 (ARMword,  ARMword,  int *, int *);
static ARMword         AddS8  (ARMword,  ARMword,  int *, int *);
static ARMword         AddS8  (ARMword,  ARMword,  int *, int *);
static ARMword         AddU8  (ARMword,  ARMword,  int *, int *);
static ARMword         AddU8  (ARMword,  ARMword,  int *, int *);
static ARMword         Sub32  (ARMword,  ARMword,  int *, int *, ARMword);
static ARMword         Sub32  (ARMword,  ARMword,  int *, int *, ARMword);
static ARMdword        SubS32 (ARMdword, ARMdword, int *, int *);
static ARMdword        SubS32 (ARMdword, ARMdword, int *, int *);
static ARMdword        SubU32 (ARMdword, ARMdword, int *, int *);
static ARMdword        SubU32 (ARMdword, ARMdword, int *, int *);
static ARMword         SubS16 (ARMword,  ARMword,  int *, int *);
static ARMword         SubS16 (ARMword,  ARMword,  int *, int *);
static ARMword         SubS8  (ARMword,  ARMword,  int *, int *);
static ARMword         SubS8  (ARMword,  ARMword,  int *, int *);
static ARMword         SubU16 (ARMword,  ARMword,  int *, int *);
static ARMword         SubU16 (ARMword,  ARMword,  int *, int *);
static ARMword         SubU8  (ARMword,  ARMword,  int *, int *);
static ARMword         SubU8  (ARMword,  ARMword,  int *, int *);
static unsigned char   IwmmxtSaturateU8  (signed short, int *);
static unsigned char   IwmmxtSaturateU8  (signed short, int *);
static signed char     IwmmxtSaturateS8  (signed short, int *);
static signed char     IwmmxtSaturateS8  (signed short, int *);
static unsigned short  IwmmxtSaturateU16 (signed int, int *);
static unsigned short  IwmmxtSaturateU16 (signed int, int *);
static signed short    IwmmxtSaturateS16 (signed int, int *);
static signed short    IwmmxtSaturateS16 (signed int, int *);
static unsigned long   IwmmxtSaturateU32 (signed long long, int *);
static unsigned long   IwmmxtSaturateU32 (signed long long, int *);
static signed long     IwmmxtSaturateS32 (signed long long, int *);
static signed long     IwmmxtSaturateS32 (signed long long, int *);
static ARMword         Compute_Iwmmxt_Address   (ARMul_State *, ARMword, int *);
static ARMword         Compute_Iwmmxt_Address   (ARMul_State *, ARMword, int *);
static ARMdword        Iwmmxt_Load_Double_Word  (ARMul_State *, ARMword);
static ARMdword        Iwmmxt_Load_Double_Word  (ARMul_State *, ARMword);
static ARMword         Iwmmxt_Load_Word         (ARMul_State *, ARMword);
static ARMword         Iwmmxt_Load_Word         (ARMul_State *, ARMword);
static ARMword         Iwmmxt_Load_Half_Word    (ARMul_State *, ARMword);
static ARMword         Iwmmxt_Load_Half_Word    (ARMul_State *, ARMword);
static ARMword         Iwmmxt_Load_Byte         (ARMul_State *, ARMword);
static ARMword         Iwmmxt_Load_Byte         (ARMul_State *, ARMword);
static void            Iwmmxt_Store_Double_Word (ARMul_State *, ARMword, ARMdword);
static void            Iwmmxt_Store_Double_Word (ARMul_State *, ARMword, ARMdword);
static void            Iwmmxt_Store_Word        (ARMul_State *, ARMword, ARMword);
static void            Iwmmxt_Store_Word        (ARMul_State *, ARMword, ARMword);
static void            Iwmmxt_Store_Half_Word   (ARMul_State *, ARMword, ARMword);
static void            Iwmmxt_Store_Half_Word   (ARMul_State *, ARMword, ARMword);
static void            Iwmmxt_Store_Byte        (ARMul_State *, ARMword, ARMword);
static void            Iwmmxt_Store_Byte        (ARMul_State *, ARMword, ARMword);
static int             Process_Instruction      (ARMul_State *, ARMword);
static int             Process_Instruction      (ARMul_State *, ARMword);
 
 
static int TANDC    (ARMul_State *, ARMword);
static int TANDC    (ARMul_State *, ARMword);
static int TBCST    (ARMul_State *, ARMword);
static int TBCST    (ARMul_State *, ARMword);
static int TEXTRC   (ARMul_State *, ARMword);
static int TEXTRC   (ARMul_State *, ARMword);
static int TEXTRM   (ARMul_State *, ARMword);
static int TEXTRM   (ARMul_State *, ARMword);
static int TINSR    (ARMul_State *, ARMword);
static int TINSR    (ARMul_State *, ARMword);
static int TMCR     (ARMul_State *, ARMword);
static int TMCR     (ARMul_State *, ARMword);
static int TMCRR    (ARMul_State *, ARMword);
static int TMCRR    (ARMul_State *, ARMword);
static int TMIA     (ARMul_State *, ARMword);
static int TMIA     (ARMul_State *, ARMword);
static int TMIAPH   (ARMul_State *, ARMword);
static int TMIAPH   (ARMul_State *, ARMword);
static int TMIAxy   (ARMul_State *, ARMword);
static int TMIAxy   (ARMul_State *, ARMword);
static int TMOVMSK  (ARMul_State *, ARMword);
static int TMOVMSK  (ARMul_State *, ARMword);
static int TMRC     (ARMul_State *, ARMword);
static int TMRC     (ARMul_State *, ARMword);
static int TMRRC    (ARMul_State *, ARMword);
static int TMRRC    (ARMul_State *, ARMword);
static int TORC     (ARMul_State *, ARMword);
static int TORC     (ARMul_State *, ARMword);
static int WACC     (ARMul_State *, ARMword);
static int WACC     (ARMul_State *, ARMword);
static int WADD     (ARMul_State *, ARMword);
static int WADD     (ARMul_State *, ARMword);
static int WALIGNI  (ARMword);
static int WALIGNI  (ARMword);
static int WALIGNR  (ARMul_State *, ARMword);
static int WALIGNR  (ARMul_State *, ARMword);
static int WAND     (ARMword);
static int WAND     (ARMword);
static int WANDN    (ARMword);
static int WANDN    (ARMword);
static int WAVG2    (ARMword);
static int WAVG2    (ARMword);
static int WCMPEQ   (ARMul_State *, ARMword);
static int WCMPEQ   (ARMul_State *, ARMword);
static int WCMPGT   (ARMul_State *, ARMword);
static int WCMPGT   (ARMul_State *, ARMword);
static int WLDR     (ARMul_State *, ARMword);
static int WLDR     (ARMul_State *, ARMword);
static int WMAC     (ARMword);
static int WMAC     (ARMword);
static int WMADD    (ARMword);
static int WMADD    (ARMword);
static int WMAX     (ARMul_State *, ARMword);
static int WMAX     (ARMul_State *, ARMword);
static int WMIN     (ARMul_State *, ARMword);
static int WMIN     (ARMul_State *, ARMword);
static int WMUL     (ARMword);
static int WMUL     (ARMword);
static int WOR      (ARMword);
static int WOR      (ARMword);
static int WPACK    (ARMul_State *, ARMword);
static int WPACK    (ARMul_State *, ARMword);
static int WROR     (ARMul_State *, ARMword);
static int WROR     (ARMul_State *, ARMword);
static int WSAD     (ARMword);
static int WSAD     (ARMword);
static int WSHUFH   (ARMword);
static int WSHUFH   (ARMword);
static int WSLL     (ARMul_State *, ARMword);
static int WSLL     (ARMul_State *, ARMword);
static int WSRA     (ARMul_State *, ARMword);
static int WSRA     (ARMul_State *, ARMword);
static int WSRL     (ARMul_State *, ARMword);
static int WSRL     (ARMul_State *, ARMword);
static int WSTR     (ARMul_State *, ARMword);
static int WSTR     (ARMul_State *, ARMword);
static int WSUB     (ARMul_State *, ARMword);
static int WSUB     (ARMul_State *, ARMword);
static int WUNPCKEH (ARMul_State *, ARMword);
static int WUNPCKEH (ARMul_State *, ARMword);
static int WUNPCKEL (ARMul_State *, ARMword);
static int WUNPCKEL (ARMul_State *, ARMword);
static int WUNPCKIH (ARMul_State *, ARMword);
static int WUNPCKIH (ARMul_State *, ARMword);
static int WUNPCKIL (ARMul_State *, ARMword);
static int WUNPCKIL (ARMul_State *, ARMword);
static int WXOR     (ARMword);
static int WXOR     (ARMword);


/* 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,
Add32 (ARMword a1,
       ARMword a2,
       ARMword a2,
       int * carry_ptr,
       int * carry_ptr,
       int * overflow_ptr,
       int * overflow_ptr,
       ARMword sign_mask)
       ARMword sign_mask)
{
{
  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 == a1) and (a2 == 0),
  /* If (result == a1) and (a2 == 0),
     or (result > a2) then we have no carry.  */
     or (result > a2) then we have no carry.  */
  * carry_ptr = ((uresult == ua1) ? (a2 != 0) : (uresult < ua1));
  * carry_ptr = ((uresult == ua1) ? (a2 != 0) : (uresult < ua1));
 
 
  /* Overflow occurs when both arguments are the
  /* Overflow occurs when both arguments are the
     same sign, but the result is a different sign.  */
     same sign, but the result is a different sign.  */
  * overflow_ptr = (   ( (result & sign_mask) && !(a1 & sign_mask) && !(a2 & sign_mask))
  * overflow_ptr = (   ( (result & sign_mask) && !(a1 & sign_mask) && !(a2 & sign_mask))
                    || (!(result & sign_mask) &&  (a1 & sign_mask) &&  (a2 & sign_mask)));
                    || (!(result & sign_mask) &&  (a1 & sign_mask) &&  (a2 & sign_mask)));
 
 
  return result;
  return result;
}
}
 
 
static ARMdword
static ARMdword
AddS32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr)
AddS32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr)
{
{
  ARMdword     result;
  ARMdword     result;
  unsigned int uresult;
  unsigned int uresult;
  unsigned int ua1;
  unsigned int ua1;
 
 
  a1 = EXTEND32 (a1);
  a1 = EXTEND32 (a1);
  a2 = EXTEND32 (a2);
  a2 = EXTEND32 (a2);
 
 
  result  = a1 + a2;
  result  = a1 + a2;
  uresult = (unsigned int) result;
  uresult = (unsigned int) result;
  ua1     = (unsigned int) a1;
  ua1     = (unsigned int) a1;
 
 
  * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1));
  * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1));
 
 
  * overflow_ptr = (   ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL))
  * overflow_ptr = (   ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL))
                    || (!(result & 0x80000000ULL) &&  (a1 & 0x80000000ULL) &&  (a2 & 0x80000000ULL)));
                    || (!(result & 0x80000000ULL) &&  (a1 & 0x80000000ULL) &&  (a2 & 0x80000000ULL)));
 
 
  return result;
  return result;
}
}
 
 
static ARMdword
static ARMdword
AddU32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr)
AddU32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr)
{
{
  ARMdword     result;
  ARMdword     result;
  unsigned int uresult;
  unsigned int uresult;
  unsigned int ua1;
  unsigned int ua1;
 
 
  a1 &= 0xffffffff;
  a1 &= 0xffffffff;
  a2 &= 0xffffffff;
  a2 &= 0xffffffff;
 
 
  result  = a1 + a2;
  result  = a1 + a2;
  uresult = (unsigned int) result;
  uresult = (unsigned int) result;
  ua1     = (unsigned int) a1;
  ua1     = (unsigned int) a1;
 
 
  * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1));
  * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1));
 
 
  * overflow_ptr = (   ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL))
  * overflow_ptr = (   ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL))
                    || (!(result & 0x80000000ULL) &&  (a1 & 0x80000000ULL) &&  (a2 & 0x80000000ULL)));
                    || (!(result & 0x80000000ULL) &&  (a1 & 0x80000000ULL) &&  (a2 & 0x80000000ULL)));
 
 
  return result;
  return result;
}
}
 
 
static ARMword
static ARMword
AddS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
AddS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
{
{
  a1 = EXTEND16 (a1);
  a1 = EXTEND16 (a1);
  a2 = EXTEND16 (a2);
  a2 = EXTEND16 (a2);
 
 
  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
}
}
 
 
static ARMword
static ARMword
AddU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
AddU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
{
{
  a1 &= 0xffff;
  a1 &= 0xffff;
  a2 &= 0xffff;
  a2 &= 0xffff;
 
 
  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
}
}
 
 
static ARMword
static ARMword
AddS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
AddS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
{
{
  a1 = EXTEND8 (a1);
  a1 = EXTEND8 (a1);
  a2 = EXTEND8 (a2);
  a2 = EXTEND8 (a2);
 
 
  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
}
}
 
 
static ARMword
static ARMword
AddU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
AddU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
{
{
  a1 &= 0xff;
  a1 &= 0xff;
  a2 &= 0xff;
  a2 &= 0xff;
 
 
  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
}
}
 
 
static ARMword
static ARMword
Sub32 (ARMword a1,
Sub32 (ARMword a1,
       ARMword a2,
       ARMword a2,
       int * borrow_ptr,
       int * borrow_ptr,
       int * overflow_ptr,
       int * overflow_ptr,
       ARMword sign_mask)
       ARMword sign_mask)
{
{
  ARMword result = (a1 - a2);
  ARMword result = (a1 - a2);
  unsigned int ua1 = (unsigned int) a1;
  unsigned int ua1 = (unsigned int) a1;
  unsigned int ua2 = (unsigned int) a2;
  unsigned int ua2 = (unsigned int) a2;
 
 
  /* A borrow occurs if a2 is (unsigned) larger than a1.
  /* A borrow occurs if a2 is (unsigned) larger than a1.
     However the carry flag is *cleared* if a borrow occurs.  */
     However the carry flag is *cleared* if a borrow occurs.  */
  * borrow_ptr = ! (ua2 > ua1);
  * borrow_ptr = ! (ua2 > ua1);
 
 
  /* Overflow occurs when a negative number is subtracted from a
  /* Overflow occurs when a negative number is subtracted from a
     positive number and the result is negative or a positive
     positive number and the result is negative or a positive
     number is subtracted from a negative number and the result is
     number is subtracted from a negative number and the result is
     positive.  */
     positive.  */
  * overflow_ptr = ( (! (a1 & sign_mask) &&   (a2 & sign_mask) &&   (result & sign_mask))
  * overflow_ptr = ( (! (a1 & sign_mask) &&   (a2 & sign_mask) &&   (result & sign_mask))
                    || ((a1 & sign_mask) && ! (a2 & sign_mask) && ! (result & sign_mask)));
                    || ((a1 & sign_mask) && ! (a2 & sign_mask) && ! (result & sign_mask)));
 
 
  return result;
  return result;
}
}
 
 
static ARMdword
static ARMdword
SubS32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr)
SubS32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr)
{
{
  ARMdword     result;
  ARMdword     result;
  unsigned int ua1;
  unsigned int ua1;
  unsigned int ua2;
  unsigned int ua2;
 
 
  a1 = EXTEND32 (a1);
  a1 = EXTEND32 (a1);
  a2 = EXTEND32 (a2);
  a2 = EXTEND32 (a2);
 
 
  result = a1 - a2;
  result = a1 - a2;
  ua1    = (unsigned int) a1;
  ua1    = (unsigned int) a1;
  ua2    = (unsigned int) a2;
  ua2    = (unsigned int) a2;
 
 
  * borrow_ptr = ! (ua2 > ua1);
  * borrow_ptr = ! (ua2 > ua1);
 
 
  * overflow_ptr = ( (! (a1 & 0x80000000ULL) &&   (a2 & 0x80000000ULL) &&   (result & 0x80000000ULL))
  * overflow_ptr = ( (! (a1 & 0x80000000ULL) &&   (a2 & 0x80000000ULL) &&   (result & 0x80000000ULL))
                    || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL)));
                    || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL)));
 
 
  return result;
  return result;
}
}
 
 
static ARMword
static ARMword
SubS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
SubS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
{
{
  a1 = EXTEND16 (a1);
  a1 = EXTEND16 (a1);
  a2 = EXTEND16 (a2);
  a2 = EXTEND16 (a2);
 
 
  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
}
}
 
 
static ARMword
static ARMword
SubS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
SubS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
{
{
  a1 = EXTEND8 (a1);
  a1 = EXTEND8 (a1);
  a2 = EXTEND8 (a2);
  a2 = EXTEND8 (a2);
 
 
  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
}
}
 
 
static ARMword
static ARMword
SubU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
SubU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
{
{
  a1 &= 0xffff;
  a1 &= 0xffff;
  a2 &= 0xffff;
  a2 &= 0xffff;
 
 
  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
}
}
 
 
static ARMword
static ARMword
SubU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
SubU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
{
{
  a1 &= 0xff;
  a1 &= 0xff;
  a2 &= 0xff;
  a2 &= 0xff;
 
 
  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
}
}
 
 
static ARMdword
static ARMdword
SubU32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr)
SubU32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr)
{
{
  ARMdword     result;
  ARMdword     result;
  unsigned int ua1;
  unsigned int ua1;
  unsigned int ua2;
  unsigned int ua2;
 
 
  a1 &= 0xffffffff;
  a1 &= 0xffffffff;
  a2 &= 0xffffffff;
  a2 &= 0xffffffff;
 
 
  result = a1 - a2;
  result = a1 - a2;
  ua1    = (unsigned int) a1;
  ua1    = (unsigned int) a1;
  ua2    = (unsigned int) a2;
  ua2    = (unsigned int) a2;
 
 
  * borrow_ptr = ! (ua2 > ua1);
  * borrow_ptr = ! (ua2 > ua1);
 
 
  * overflow_ptr = ( (! (a1 & 0x80000000ULL) &&   (a2 & 0x80000000ULL) &&   (result & 0x80000000ULL))
  * overflow_ptr = ( (! (a1 & 0x80000000ULL) &&   (a2 & 0x80000000ULL) &&   (result & 0x80000000ULL))
                    || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL)));
                    || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL)));
 
 
  return result;
  return result;
}
}
 
 
/* For the saturation.  */
/* For the saturation.  */
 
 
static unsigned char
static unsigned char
IwmmxtSaturateU8 (signed short val, int * sat)
IwmmxtSaturateU8 (signed short val, int * sat)
{
{
  unsigned char rv;
  unsigned char rv;
 
 
  if (val < 0)
  if (val < 0)
    {
    {
      rv = 0;
      rv = 0;
      *sat = 1;
      *sat = 1;
    }
    }
  else if (val > 0xff)
  else if (val > 0xff)
    {
    {
      rv = 0xff;
      rv = 0xff;
      *sat = 1;
      *sat = 1;
    }
    }
  else
  else
    {
    {
      rv = val & 0xff;
      rv = val & 0xff;
      *sat = 0;
      *sat = 0;
    }
    }
  return rv;
  return rv;
}
}
 
 
static signed char
static signed char
IwmmxtSaturateS8 (signed short val, int * sat)
IwmmxtSaturateS8 (signed short val, int * sat)
{
{
  signed char rv;
  signed char rv;
 
 
  if (val < -0x80)
  if (val < -0x80)
    {
    {
      rv = -0x80;
      rv = -0x80;
      *sat = 1;
      *sat = 1;
    }
    }
  else if (val > 0x7f)
  else if (val > 0x7f)
    {
    {
      rv = 0x7f;
      rv = 0x7f;
      *sat = 1;
      *sat = 1;
    }
    }
  else
  else
    {
    {
      rv = val & 0xff;
      rv = val & 0xff;
      *sat = 0;
      *sat = 0;
    }
    }
  return rv;
  return rv;
}
}
 
 
static unsigned short
static unsigned short
IwmmxtSaturateU16 (signed int val, int * sat)
IwmmxtSaturateU16 (signed int val, int * sat)
{
{
  unsigned short rv;
  unsigned short rv;
 
 
  if (val < 0)
  if (val < 0)
    {
    {
      rv = 0;
      rv = 0;
      *sat = 1;
      *sat = 1;
    }
    }
  else if (val > 0xffff)
  else if (val > 0xffff)
    {
    {
      rv = 0xffff;
      rv = 0xffff;
      *sat = 1;
      *sat = 1;
    }
    }
  else
  else
    {
    {
      rv = val & 0xffff;
      rv = val & 0xffff;
      *sat = 0;
      *sat = 0;
    }
    }
  return rv;
  return rv;
}
}
 
 
static signed short
static signed short
IwmmxtSaturateS16 (signed int val, int * sat)
IwmmxtSaturateS16 (signed int val, int * sat)
{
{
  signed short rv;
  signed short rv;
 
 
  if (val < -0x8000)
  if (val < -0x8000)
    {
    {
      rv = - 0x8000;
      rv = - 0x8000;
      *sat = 1;
      *sat = 1;
    }
    }
  else if (val > 0x7fff)
  else if (val > 0x7fff)
    {
    {
      rv = 0x7fff;
      rv = 0x7fff;
      *sat = 1;
      *sat = 1;
    }
    }
  else
  else
    {
    {
      rv = val & 0xffff;
      rv = val & 0xffff;
      *sat = 0;
      *sat = 0;
    }
    }
  return rv;
  return rv;
}
}
 
 
static unsigned long
static unsigned long
IwmmxtSaturateU32 (signed long long val, int * sat)
IwmmxtSaturateU32 (signed long long val, int * sat)
{
{
  unsigned long rv;
  unsigned long rv;
 
 
  if (val < 0)
  if (val < 0)
    {
    {
      rv = 0;
      rv = 0;
      *sat = 1;
      *sat = 1;
    }
    }
  else if (val > 0xffffffff)
  else if (val > 0xffffffff)
    {
    {
      rv = 0xffffffff;
      rv = 0xffffffff;
      *sat = 1;
      *sat = 1;
    }
    }
  else
  else
    {
    {
      rv = val & 0xffffffff;
      rv = val & 0xffffffff;
      *sat = 0;
      *sat = 0;
    }
    }
  return rv;
  return rv;
}
}
 
 
static signed long
static signed long
IwmmxtSaturateS32 (signed long long val, int * sat)
IwmmxtSaturateS32 (signed long long val, int * sat)
{
{
  signed long rv;
  signed long rv;
 
 
  if (val < -0x80000000LL)
  if (val < -0x80000000LL)
    {
    {
      rv = -0x80000000;
      rv = -0x80000000;
      *sat = 1;
      *sat = 1;
    }
    }
  else if (val > 0x7fffffff)
  else if (val > 0x7fffffff)
    {
    {
      rv = 0x7fffffff;
      rv = 0x7fffffff;
      *sat = 1;
      *sat = 1;
    }
    }
  else
  else
    {
    {
      rv = val & 0xffffffff;
      rv = val & 0xffffffff;
      *sat = 0;
      *sat = 0;
    }
    }
  return rv;
  return rv;
}
}
 
 
/* Intel(r) Wireless MMX(tm) technology Acessor functions.  */
/* Intel(r) Wireless MMX(tm) technology Acessor functions.  */
 
 
unsigned
unsigned
IwmmxtLDC (ARMul_State * state ATTRIBUTE_UNUSED,
IwmmxtLDC (ARMul_State * state ATTRIBUTE_UNUSED,
           unsigned      type  ATTRIBUTE_UNUSED,
           unsigned      type  ATTRIBUTE_UNUSED,
           ARMword       instr,
           ARMword       instr,
           ARMword       data)
           ARMword       data)
{
{
  return ARMul_CANT;
  return ARMul_CANT;
}
}
 
 
unsigned
unsigned
IwmmxtSTC (ARMul_State * state ATTRIBUTE_UNUSED,
IwmmxtSTC (ARMul_State * state ATTRIBUTE_UNUSED,
           unsigned      type  ATTRIBUTE_UNUSED,
           unsigned      type  ATTRIBUTE_UNUSED,
           ARMword       instr,
           ARMword       instr,
           ARMword *     data)
           ARMword *     data)
{
{
  return ARMul_CANT;
  return ARMul_CANT;
}
}
 
 
unsigned
unsigned
IwmmxtMRC (ARMul_State * state ATTRIBUTE_UNUSED,
IwmmxtMRC (ARMul_State * state ATTRIBUTE_UNUSED,
           unsigned      type  ATTRIBUTE_UNUSED,
           unsigned      type  ATTRIBUTE_UNUSED,
           ARMword       instr,
           ARMword       instr,
           ARMword *     value)
           ARMword *     value)
{
{
  return ARMul_CANT;
  return ARMul_CANT;
}
}
 
 
unsigned
unsigned
IwmmxtMCR (ARMul_State * state ATTRIBUTE_UNUSED,
IwmmxtMCR (ARMul_State * state ATTRIBUTE_UNUSED,
           unsigned      type  ATTRIBUTE_UNUSED,
           unsigned      type  ATTRIBUTE_UNUSED,
           ARMword       instr,
           ARMword       instr,
           ARMword       value)
           ARMword       value)
{
{
  return ARMul_CANT;
  return ARMul_CANT;
}
}
 
 
unsigned
unsigned
IwmmxtCDP (ARMul_State * state, unsigned type, ARMword instr)
IwmmxtCDP (ARMul_State * state, unsigned type, ARMword instr)
{
{
  return ARMul_CANT;
  return ARMul_CANT;
}
}
 
 
/* Intel(r) Wireless MMX(tm) technology instruction implementations.  */
/* Intel(r) Wireless MMX(tm) technology instruction implementations.  */
 
 
static int
static int
TANDC (ARMul_State * state, ARMword instr)
TANDC (ARMul_State * state, ARMword instr)
{
{
  ARMword cpsr;
  ARMword cpsr;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "tandc\n");
  fprintf (stderr, "tandc\n");
#endif  
#endif  
 
 
  /* The Rd field must be r15.  */
  /* The Rd field must be r15.  */
  if (BITS (12, 15) != 15)
  if (BITS (12, 15) != 15)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  /* The CRn field must be r3.  */
  /* The CRn field must be r3.  */
  if (BITS (16, 19) != 3)
  if (BITS (16, 19) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  /* The CRm field must be r0.  */
  /* The CRm field must be r0.  */
  if (BITS (0, 3) != 0)
  if (BITS (0, 3) != 0)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  cpsr = ARMul_GetCPSR (state) & 0x0fffffff;
  cpsr = ARMul_GetCPSR (state) & 0x0fffffff;
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      cpsr |= (  (wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 24, 27)
      cpsr |= (  (wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 24, 27)
                & wCBITS (wCASF, 20, 23) & wCBITS (wCASF, 16, 19)
                & wCBITS (wCASF, 20, 23) & wCBITS (wCASF, 16, 19)
                & wCBITS (wCASF, 12, 15) & wCBITS (wCASF,  8, 11)
                & wCBITS (wCASF, 12, 15) & wCBITS (wCASF,  8, 11)
                & wCBITS (wCASF,  4,  7) & wCBITS (wCASF,  0,  3)) << 28);
                & wCBITS (wCASF,  4,  7) & wCBITS (wCASF,  0,  3)) << 28);
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      cpsr |= (  (wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 20, 23)
      cpsr |= (  (wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 20, 23)
                & wCBITS (wCASF, 12, 15) & wCBITS (wCASF,  4, 7)) << 28);
                & wCBITS (wCASF, 12, 15) & wCBITS (wCASF,  4, 7)) << 28);
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      cpsr |= ((wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 12, 15)) << 28);
      cpsr |= ((wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 12, 15)) << 28);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  ARMul_SetCPSR (state, cpsr);
  ARMul_SetCPSR (state, cpsr);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TBCST (ARMul_State * state, ARMword instr)
TBCST (ARMul_State * state, ARMword instr)
{
{
  ARMdword Rn;
  ARMdword Rn;
  int wRd;
  int wRd;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "tbcst\n");
  fprintf (stderr, "tbcst\n");
#endif  
#endif  
 
 
  Rn  = state->Reg [BITS (12, 15)];
  Rn  = state->Reg [BITS (12, 15)];
  if (BITS (12, 15) == 15)
  if (BITS (12, 15) == 15)
    Rn &= 0xfffffffc;
    Rn &= 0xfffffffc;
 
 
  wRd = BITS (16, 19);
  wRd = BITS (16, 19);
 
 
  switch (BITS (6, 7))
  switch (BITS (6, 7))
    {
    {
    case Bqual:
    case Bqual:
      Rn &= 0xff;
      Rn &= 0xff;
      wR [wRd] = (Rn << 56) | (Rn << 48) | (Rn << 40) | (Rn << 32)
      wR [wRd] = (Rn << 56) | (Rn << 48) | (Rn << 40) | (Rn << 32)
               | (Rn << 24) | (Rn << 16) | (Rn << 8) | Rn;
               | (Rn << 24) | (Rn << 16) | (Rn << 8) | Rn;
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      Rn &= 0xffff;
      Rn &= 0xffff;
      wR [wRd] = (Rn << 48) | (Rn << 32) | (Rn << 16) | Rn;
      wR [wRd] = (Rn << 48) | (Rn << 32) | (Rn << 16) | Rn;
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      Rn &= 0xffffffff;
      Rn &= 0xffffffff;
      wR [wRd] = (Rn << 32) | Rn;
      wR [wRd] = (Rn << 32) | Rn;
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      break;
      break;
    }
    }
 
 
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TEXTRC (ARMul_State * state, ARMword instr)
TEXTRC (ARMul_State * state, ARMword instr)
{
{
  ARMword cpsr;
  ARMword cpsr;
  ARMword selector;
  ARMword selector;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "textrc\n");
  fprintf (stderr, "textrc\n");
#endif  
#endif  
 
 
  /* The Rd field must be r15.  */
  /* The Rd field must be r15.  */
  if (BITS (12, 15) != 15)
  if (BITS (12, 15) != 15)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  /* The CRn field must be r3.  */
  /* The CRn field must be r3.  */
  if (BITS (16, 19) != 3)
  if (BITS (16, 19) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  /* The CRm field must be 0xxx.  */
  /* The CRm field must be 0xxx.  */
  if (BIT (3) != 0)
  if (BIT (3) != 0)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  selector = BITS (0, 2);
  selector = BITS (0, 2);
  cpsr = ARMul_GetCPSR (state) & 0x0fffffff;
  cpsr = ARMul_GetCPSR (state) & 0x0fffffff;
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual: selector *= 4; break;
    case Bqual: selector *= 4; break;
    case Hqual: selector = ((selector & 3) * 8) + 4; break;
    case Hqual: selector = ((selector & 3) * 8) + 4; break;
    case Wqual: selector = ((selector & 1) * 16) + 12; break;
    case Wqual: selector = ((selector & 1) * 16) + 12; break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  cpsr |= wCBITS (wCASF, selector, selector + 3) << 28;
  cpsr |= wCBITS (wCASF, selector, selector + 3) << 28;
  ARMul_SetCPSR (state, cpsr);
  ARMul_SetCPSR (state, cpsr);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TEXTRM (ARMul_State * state, ARMword instr)
TEXTRM (ARMul_State * state, ARMword instr)
{
{
  ARMword Rd;
  ARMword Rd;
  int     offset;
  int     offset;
  int     wRn;
  int     wRn;
  int     sign;
  int     sign;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "textrm\n");
  fprintf (stderr, "textrm\n");
#endif  
#endif  
 
 
  wRn    = BITS (16, 19);
  wRn    = BITS (16, 19);
  sign   = BIT (3);
  sign   = BIT (3);
  offset = BITS (0, 2);
  offset = BITS (0, 2);
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      offset *= 8;
      offset *= 8;
      Rd = wRBITS (wRn, offset, offset + 7);
      Rd = wRBITS (wRn, offset, offset + 7);
      if (sign)
      if (sign)
        Rd = EXTEND8 (Rd);
        Rd = EXTEND8 (Rd);
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      offset = (offset & 3) * 16;
      offset = (offset & 3) * 16;
      Rd = wRBITS (wRn, offset, offset + 15);
      Rd = wRBITS (wRn, offset, offset + 15);
      if (sign)
      if (sign)
        Rd = EXTEND16 (Rd);
        Rd = EXTEND16 (Rd);
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      offset = (offset & 1) * 32;
      offset = (offset & 1) * 32;
      Rd = wRBITS (wRn, offset, offset + 31);
      Rd = wRBITS (wRn, offset, offset + 31);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  if (BITS (12, 15) == 15)
  if (BITS (12, 15) == 15)
    ARMul_UndefInstr (state, instr);
    ARMul_UndefInstr (state, instr);
  else
  else
    state->Reg [BITS (12, 15)] = Rd;
    state->Reg [BITS (12, 15)] = Rd;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TINSR (ARMul_State * state, ARMword instr)
TINSR (ARMul_State * state, ARMword instr)
{
{
  ARMdword data;
  ARMdword data;
  ARMword  offset;
  ARMword  offset;
  int      wRd;
  int      wRd;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "tinsr\n");
  fprintf (stderr, "tinsr\n");
#endif
#endif
 
 
  wRd = BITS (16, 19);
  wRd = BITS (16, 19);
  data = state->Reg [BITS (12, 15)];
  data = state->Reg [BITS (12, 15)];
  offset = BITS (0, 2);
  offset = BITS (0, 2);
 
 
  switch (BITS (6, 7))
  switch (BITS (6, 7))
    {
    {
    case Bqual:
    case Bqual:
      data &= 0xff;
      data &= 0xff;
      switch (offset)
      switch (offset)
        {
        {
        case 0: wR [wRd] = data | (wRBITS (wRd, 8, 63) << 8); break;
        case 0: wR [wRd] = data | (wRBITS (wRd, 8, 63) << 8); break;
        case 1: wR [wRd] = wRBITS (wRd, 0,  7) | (data <<  8) | (wRBITS (wRd, 16, 63) << 16); break;
        case 1: wR [wRd] = wRBITS (wRd, 0,  7) | (data <<  8) | (wRBITS (wRd, 16, 63) << 16); break;
        case 2: wR [wRd] = wRBITS (wRd, 0, 15) | (data << 16) | (wRBITS (wRd, 24, 63) << 24); break;
        case 2: wR [wRd] = wRBITS (wRd, 0, 15) | (data << 16) | (wRBITS (wRd, 24, 63) << 24); break;
        case 3: wR [wRd] = wRBITS (wRd, 0, 23) | (data << 24) | (wRBITS (wRd, 32, 63) << 32); break;
        case 3: wR [wRd] = wRBITS (wRd, 0, 23) | (data << 24) | (wRBITS (wRd, 32, 63) << 32); break;
        case 4: wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32) | (wRBITS (wRd, 40, 63) << 40); break;
        case 4: wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32) | (wRBITS (wRd, 40, 63) << 40); break;
        case 5: wR [wRd] = wRBITS (wRd, 0, 39) | (data << 40) | (wRBITS (wRd, 48, 63) << 48); break;
        case 5: wR [wRd] = wRBITS (wRd, 0, 39) | (data << 40) | (wRBITS (wRd, 48, 63) << 48); break;
        case 6: wR [wRd] = wRBITS (wRd, 0, 47) | (data << 48) | (wRBITS (wRd, 56, 63) << 56); break;
        case 6: wR [wRd] = wRBITS (wRd, 0, 47) | (data << 48) | (wRBITS (wRd, 56, 63) << 56); break;
        case 7: wR [wRd] = wRBITS (wRd, 0, 55) | (data << 56); break;
        case 7: wR [wRd] = wRBITS (wRd, 0, 55) | (data << 56); break;
        }
        }
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      data &= 0xffff;
      data &= 0xffff;
 
 
      switch (offset & 3)
      switch (offset & 3)
        {
        {
        case 0: wR [wRd] = data | (wRBITS (wRd, 16, 63) << 16); break;
        case 0: wR [wRd] = data | (wRBITS (wRd, 16, 63) << 16); break;
        case 1: wR [wRd] = wRBITS (wRd, 0, 15) | (data << 16) | (wRBITS (wRd, 32, 63) << 32); break;
        case 1: wR [wRd] = wRBITS (wRd, 0, 15) | (data << 16) | (wRBITS (wRd, 32, 63) << 32); break;
        case 2: wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32) | (wRBITS (wRd, 48, 63) << 48); break;
        case 2: wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32) | (wRBITS (wRd, 48, 63) << 48); break;
        case 3: wR [wRd] = wRBITS (wRd, 0, 47) | (data << 48); break;
        case 3: wR [wRd] = wRBITS (wRd, 0, 47) | (data << 48); break;
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      if (offset & 1)
      if (offset & 1)
        wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32);
        wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32);
      else
      else
        wR [wRd] = (wRBITS (wRd, 32, 63) << 32) | data;
        wR [wRd] = (wRBITS (wRd, 32, 63) << 32) | data;
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      break;
      break;
    }
    }
 
 
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TMCR (ARMul_State * state, ARMword instr)
TMCR (ARMul_State * state, ARMword instr)
{
{
  ARMword val;
  ARMword val;
  int     wCreg;
  int     wCreg;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "tmcr\n");
  fprintf (stderr, "tmcr\n");
#endif  
#endif  
 
 
  if (BITS (0, 3) != 0)
  if (BITS (0, 3) != 0)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  val = state->Reg [BITS (12, 15)];
  val = state->Reg [BITS (12, 15)];
  if (BITS (12, 15) == 15)
  if (BITS (12, 15) == 15)
    val &= 0xfffffffc;
    val &= 0xfffffffc;
 
 
  wCreg = BITS (16, 19);
  wCreg = BITS (16, 19);
 
 
  switch (wCreg)
  switch (wCreg)
    {
    {
    case wCID:
    case wCID:
      /* The wCID register is read only.  */
      /* The wCID register is read only.  */
      break;
      break;
 
 
    case wCon:
    case wCon:
      /* Writing to the MUP or CUP bits clears them.  */
      /* Writing to the MUP or CUP bits clears them.  */
      wC [wCon] &= ~ (val & 0x3);
      wC [wCon] &= ~ (val & 0x3);
      break;
      break;
 
 
    case wCSSF:
    case wCSSF:
      /* Only the bottom 8 bits can be written to.
      /* Only the bottom 8 bits can be written to.
          The higher bits write as zero.  */
          The higher bits write as zero.  */
      wC [wCSSF] = (val & 0xff);
      wC [wCSSF] = (val & 0xff);
      wC [wCon] |= WCON_CUP;
      wC [wCon] |= WCON_CUP;
      break;
      break;
 
 
    default:
    default:
      wC [wCreg] = val;
      wC [wCreg] = val;
      wC [wCon] |= WCON_CUP;
      wC [wCon] |= WCON_CUP;
      break;
      break;
    }
    }
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TMCRR (ARMul_State * state, ARMword instr)
TMCRR (ARMul_State * state, ARMword instr)
{
{
  ARMdword RdHi = state->Reg [BITS (16, 19)];
  ARMdword RdHi = state->Reg [BITS (16, 19)];
  ARMword  RdLo = state->Reg [BITS (12, 15)];
  ARMword  RdLo = state->Reg [BITS (12, 15)];
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "tmcrr\n");
  fprintf (stderr, "tmcrr\n");
#endif  
#endif  
 
 
  if ((BITS (16, 19) == 15) || (BITS (12, 15) == 15))
  if ((BITS (16, 19) == 15) || (BITS (12, 15) == 15))
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  wR [BITS (0, 3)] = (RdHi << 32) | RdLo;
  wR [BITS (0, 3)] = (RdHi << 32) | RdLo;
 
 
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TMIA (ARMul_State * state, ARMword instr)
TMIA (ARMul_State * state, ARMword instr)
{
{
  signed long long a, b;
  signed long long a, b;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "tmia\n");
  fprintf (stderr, "tmia\n");
#endif  
#endif  
 
 
  if ((BITS (0, 3) == 15) || (BITS (12, 15) == 15))
  if ((BITS (0, 3) == 15) || (BITS (12, 15) == 15))
    {
    {
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  a = state->Reg [BITS (0, 3)];
  a = state->Reg [BITS (0, 3)];
  b = state->Reg [BITS (12, 15)];
  b = state->Reg [BITS (12, 15)];
 
 
  a = EXTEND32 (a);
  a = EXTEND32 (a);
  b = EXTEND32 (b);
  b = EXTEND32 (b);
 
 
  wR [BITS (5, 8)] += a * b;
  wR [BITS (5, 8)] += a * b;
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TMIAPH (ARMul_State * state, ARMword instr)
TMIAPH (ARMul_State * state, ARMword instr)
{
{
  signed long a, b, result;
  signed long a, b, result;
  signed long long r;
  signed long long r;
  ARMword Rm = state->Reg [BITS (0, 3)];
  ARMword Rm = state->Reg [BITS (0, 3)];
  ARMword Rs = state->Reg [BITS (12, 15)];
  ARMword Rs = state->Reg [BITS (12, 15)];
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "tmiaph\n");
  fprintf (stderr, "tmiaph\n");
#endif  
#endif  
 
 
  if (BITS (0, 3) == 15 || BITS (12, 15) == 15)
  if (BITS (0, 3) == 15 || BITS (12, 15) == 15)
    {
    {
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  a = SUBSTR (Rs, ARMword, 16, 31);
  a = SUBSTR (Rs, ARMword, 16, 31);
  b = SUBSTR (Rm, ARMword, 16, 31);
  b = SUBSTR (Rm, ARMword, 16, 31);
 
 
  a = EXTEND16 (a);
  a = EXTEND16 (a);
  b = EXTEND16 (b);
  b = EXTEND16 (b);
 
 
  result = a * b;
  result = a * b;
 
 
  r = result;
  r = result;
  r = EXTEND32 (r);
  r = EXTEND32 (r);
 
 
  wR [BITS (5, 8)] += r;
  wR [BITS (5, 8)] += r;
 
 
  a = SUBSTR (Rs, ARMword,  0, 15);
  a = SUBSTR (Rs, ARMword,  0, 15);
  b = SUBSTR (Rm, ARMword,  0, 15);
  b = SUBSTR (Rm, ARMword,  0, 15);
 
 
  a = EXTEND16 (a);
  a = EXTEND16 (a);
  b = EXTEND16 (b);
  b = EXTEND16 (b);
 
 
  result = a * b;
  result = a * b;
 
 
  r = result;
  r = result;
  r = EXTEND32 (r);
  r = EXTEND32 (r);
 
 
  wR [BITS (5, 8)] += r;
  wR [BITS (5, 8)] += r;
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TMIAxy (ARMul_State * state, ARMword instr)
TMIAxy (ARMul_State * state, ARMword instr)
{
{
  ARMword Rm;
  ARMword Rm;
  ARMword Rs;
  ARMword Rs;
  long long temp;
  long long temp;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "tmiaxy\n");
  fprintf (stderr, "tmiaxy\n");
#endif  
#endif  
 
 
  if (BITS (0, 3) == 15 || BITS (12, 15) == 15)
  if (BITS (0, 3) == 15 || BITS (12, 15) == 15)
    {
    {
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  Rm = state->Reg [BITS (0, 3)];
  Rm = state->Reg [BITS (0, 3)];
  if (BIT (17))
  if (BIT (17))
    Rm >>= 16;
    Rm >>= 16;
  else
  else
    Rm &= 0xffff;
    Rm &= 0xffff;
 
 
  Rs = state->Reg [BITS (12, 15)];
  Rs = state->Reg [BITS (12, 15)];
  if (BIT (16))
  if (BIT (16))
    Rs >>= 16;
    Rs >>= 16;
  else
  else
    Rs &= 0xffff;
    Rs &= 0xffff;
 
 
  if (Rm & (1 << 15))
  if (Rm & (1 << 15))
    Rm -= 1 << 16;
    Rm -= 1 << 16;
 
 
  if (Rs & (1 << 15))
  if (Rs & (1 << 15))
    Rs -= 1 << 16;
    Rs -= 1 << 16;
 
 
  Rm *= Rs;
  Rm *= Rs;
  temp = Rm;
  temp = Rm;
 
 
  if (temp & (1 << 31))
  if (temp & (1 << 31))
    temp -= 1ULL << 32;
    temp -= 1ULL << 32;
 
 
  wR [BITS (5, 8)] += temp;
  wR [BITS (5, 8)] += temp;
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TMOVMSK (ARMul_State * state, ARMword instr)
TMOVMSK (ARMul_State * state, ARMword instr)
{
{
  ARMdword result;
  ARMdword result;
  int      wRn;
  int      wRn;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "tmovmsk\n");
  fprintf (stderr, "tmovmsk\n");
#endif  
#endif  
 
 
  /* The CRm field must be r0.  */
  /* The CRm field must be r0.  */
  if (BITS (0, 3) != 0)
  if (BITS (0, 3) != 0)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  wRn = BITS (16, 19);
  wRn = BITS (16, 19);
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      result = (  (wRBITS (wRn, 63, 63) << 7)
      result = (  (wRBITS (wRn, 63, 63) << 7)
                | (wRBITS (wRn, 55, 55) << 6)
                | (wRBITS (wRn, 55, 55) << 6)
                | (wRBITS (wRn, 47, 47) << 5)
                | (wRBITS (wRn, 47, 47) << 5)
                | (wRBITS (wRn, 39, 39) << 4)
                | (wRBITS (wRn, 39, 39) << 4)
                | (wRBITS (wRn, 31, 31) << 3)
                | (wRBITS (wRn, 31, 31) << 3)
                | (wRBITS (wRn, 23, 23) << 2)
                | (wRBITS (wRn, 23, 23) << 2)
                | (wRBITS (wRn, 15, 15) << 1)
                | (wRBITS (wRn, 15, 15) << 1)
                | (wRBITS (wRn,  7,  7) << 0));
                | (wRBITS (wRn,  7,  7) << 0));
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      result = (  (wRBITS (wRn, 63, 63) << 3)
      result = (  (wRBITS (wRn, 63, 63) << 3)
                | (wRBITS (wRn, 47, 47) << 2)
                | (wRBITS (wRn, 47, 47) << 2)
                | (wRBITS (wRn, 31, 31) << 1)
                | (wRBITS (wRn, 31, 31) << 1)
                | (wRBITS (wRn, 15, 15) << 0));
                | (wRBITS (wRn, 15, 15) << 0));
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      result = (wRBITS (wRn, 63, 63) << 1) | wRBITS (wRn, 31, 31);
      result = (wRBITS (wRn, 63, 63) << 1) | wRBITS (wRn, 31, 31);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  state->Reg [BITS (12, 15)] = result;
  state->Reg [BITS (12, 15)] = result;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TMRC (ARMul_State * state, ARMword instr)
TMRC (ARMul_State * state, ARMword instr)
{
{
  int reg = BITS (12, 15);
  int reg = BITS (12, 15);
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "tmrc\n");
  fprintf (stderr, "tmrc\n");
#endif  
#endif  
 
 
  if (BITS (0, 3) != 0)
  if (BITS (0, 3) != 0)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  if (reg == 15)
  if (reg == 15)
    ARMul_UndefInstr (state, instr);
    ARMul_UndefInstr (state, instr);
  else
  else
    state->Reg [reg] = wC [BITS (16, 19)];
    state->Reg [reg] = wC [BITS (16, 19)];
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TMRRC (ARMul_State * state, ARMword instr)
TMRRC (ARMul_State * state, ARMword instr)
{
{
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "tmrrc\n");
  fprintf (stderr, "tmrrc\n");
#endif  
#endif  
 
 
  if ((BITS (16, 19) == 15) || (BITS (12, 15) == 15) || (BITS (4, 11) != 0))
  if ((BITS (16, 19) == 15) || (BITS (12, 15) == 15) || (BITS (4, 11) != 0))
    ARMul_UndefInstr (state, instr);
    ARMul_UndefInstr (state, instr);
  else
  else
    {
    {
      state->Reg [BITS (16, 19)] = wRBITS (BITS (0, 3), 32, 63);
      state->Reg [BITS (16, 19)] = wRBITS (BITS (0, 3), 32, 63);
      state->Reg [BITS (12, 15)] = wRBITS (BITS (0, 3),  0, 31);
      state->Reg [BITS (12, 15)] = wRBITS (BITS (0, 3),  0, 31);
    }
    }
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
TORC (ARMul_State * state, ARMword instr)
TORC (ARMul_State * state, ARMword instr)
{
{
  ARMword cpsr = ARMul_GetCPSR (state);
  ARMword cpsr = ARMul_GetCPSR (state);
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "torc\n");
  fprintf (stderr, "torc\n");
#endif  
#endif  
 
 
  /* The Rd field must be r15.  */
  /* The Rd field must be r15.  */
  if (BITS (12, 15) != 15)
  if (BITS (12, 15) != 15)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  /* The CRn field must be r3.  */
  /* The CRn field must be r3.  */
  if (BITS (16, 19) != 3)
  if (BITS (16, 19) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  /* The CRm field must be r0.  */
  /* The CRm field must be r0.  */
  if (BITS (0, 3) != 0)
  if (BITS (0, 3) != 0)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  cpsr &= 0x0fffffff;
  cpsr &= 0x0fffffff;
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      cpsr |= (  (wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 24, 27)
      cpsr |= (  (wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 24, 27)
                | wCBITS (wCASF, 20, 23) | wCBITS (wCASF, 16, 19)
                | wCBITS (wCASF, 20, 23) | wCBITS (wCASF, 16, 19)
                | wCBITS (wCASF, 12, 15) | wCBITS (wCASF,  8, 11)
                | wCBITS (wCASF, 12, 15) | wCBITS (wCASF,  8, 11)
                | wCBITS (wCASF,  4,  7) | wCBITS (wCASF,  0,  3)) << 28);
                | wCBITS (wCASF,  4,  7) | wCBITS (wCASF,  0,  3)) << 28);
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      cpsr |= (  (wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 20, 23)
      cpsr |= (  (wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 20, 23)
                | wCBITS (wCASF, 12, 15) | wCBITS (wCASF,  4,  7)) << 28);
                | wCBITS (wCASF, 12, 15) | wCBITS (wCASF,  4,  7)) << 28);
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      cpsr |= ((wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 12, 15)) << 28);
      cpsr |= ((wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 12, 15)) << 28);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  ARMul_SetCPSR (state, cpsr);
  ARMul_SetCPSR (state, cpsr);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WACC (ARMul_State * state, ARMword instr)
WACC (ARMul_State * state, ARMword instr)
{
{
  int wRn;
  int wRn;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wacc\n");
  fprintf (stderr, "wacc\n");
#endif  
#endif  
 
 
  wRn = BITS (16, 19);
  wRn = BITS (16, 19);
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      wR [BITS (12, 15)] =
      wR [BITS (12, 15)] =
          wRBITS (wRn, 56, 63) + wRBITS (wRn, 48, 55)
          wRBITS (wRn, 56, 63) + wRBITS (wRn, 48, 55)
        + wRBITS (wRn, 40, 47) + wRBITS (wRn, 32, 39)
        + wRBITS (wRn, 40, 47) + wRBITS (wRn, 32, 39)
        + wRBITS (wRn, 24, 31) + wRBITS (wRn, 16, 23)
        + wRBITS (wRn, 24, 31) + wRBITS (wRn, 16, 23)
        + wRBITS (wRn,  8, 15) + wRBITS (wRn,  0,  7);
        + wRBITS (wRn,  8, 15) + wRBITS (wRn,  0,  7);
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      wR [BITS (12, 15)] =
      wR [BITS (12, 15)] =
          wRBITS (wRn, 48, 63) + wRBITS (wRn, 32, 47)
          wRBITS (wRn, 48, 63) + wRBITS (wRn, 32, 47)
        + wRBITS (wRn, 16, 31) + wRBITS (wRn,  0, 15);
        + wRBITS (wRn, 16, 31) + wRBITS (wRn,  0, 15);
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      wR [BITS (12, 15)] = wRBITS (wRn, 32, 63) + wRBITS (wRn, 0, 31);
      wR [BITS (12, 15)] = wRBITS (wRn, 32, 63) + wRBITS (wRn, 0, 31);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      break;
      break;
    }
    }
 
 
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WADD (ARMul_State * state, ARMword instr)
WADD (ARMul_State * state, ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMdword x;
  ARMdword x;
  ARMdword s;
  ARMdword s;
  ARMword  psr = 0;
  ARMword  psr = 0;
  int      i;
  int      i;
  int      carry;
  int      carry;
  int      overflow;
  int      overflow;
  int      satrv[8];
  int      satrv[8];
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wadd\n");
  fprintf (stderr, "wadd\n");
#endif  
#endif  
 
 
  /* Add two numbers using the specified function,
  /* Add two numbers using the specified function,
     leaving setting the carry bit as required.  */
     leaving setting the carry bit as required.  */
#define ADDx(x, y, m, f) \
#define ADDx(x, y, m, f) \
   (*f) (wRBITS (BITS (16, 19), (x), (y)) & (m), \
   (*f) (wRBITS (BITS (16, 19), (x), (y)) & (m), \
         wRBITS (BITS ( 0,  3), (x), (y)) & (m), \
         wRBITS (BITS ( 0,  3), (x), (y)) & (m), \
        & carry, & overflow)
        & carry, & overflow)
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      for (i = 0; i < 8; i++)
      for (i = 0; i < 8; i++)
        {
        {
          switch (BITS (20, 21))
          switch (BITS (20, 21))
            {
            {
            case NoSaturation:
            case NoSaturation:
              s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddS8);
              s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddS8);
              satrv [BITIDX8 (i)] = 0;
              satrv [BITIDX8 (i)] = 0;
              r |= (s & 0xff) << (i * 8);
              r |= (s & 0xff) << (i * 8);
              SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
              SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
              SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
              SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
              SIMD8_SET (psr, carry,     SIMD_CBIT, i);
              SIMD8_SET (psr, carry,     SIMD_CBIT, i);
              SIMD8_SET (psr, overflow,  SIMD_VBIT, i);
              SIMD8_SET (psr, overflow,  SIMD_VBIT, i);
              break;
              break;
 
 
            case UnsignedSaturation:
            case UnsignedSaturation:
              s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddU8);
              s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddU8);
              x = IwmmxtSaturateU8 (s, satrv + BITIDX8 (i));
              x = IwmmxtSaturateU8 (s, satrv + BITIDX8 (i));
              r |= (x & 0xff) << (i * 8);
              r |= (x & 0xff) << (i * 8);
              SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
              SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
              SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
              SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX8 (i)])
              if (! satrv [BITIDX8 (i)])
                {
                {
                  SIMD8_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD8_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD8_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD8_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            case SignedSaturation:
            case SignedSaturation:
              s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddS8);
              s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddS8);
              x = IwmmxtSaturateS8 (s, satrv + BITIDX8 (i));
              x = IwmmxtSaturateS8 (s, satrv + BITIDX8 (i));
              r |= (x & 0xff) << (i * 8);
              r |= (x & 0xff) << (i * 8);
              SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
              SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
              SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
              SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX8 (i)])
              if (! satrv [BITIDX8 (i)])
                {
                {
                  SIMD8_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD8_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD8_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD8_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            default:
            default:
              ARMul_UndefInstr (state, instr);
              ARMul_UndefInstr (state, instr);
              return ARMul_DONE;
              return ARMul_DONE;
            }
            }
        }
        }
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
      satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
 
 
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          switch (BITS (20, 21))
          switch (BITS (20, 21))
            {
            {
            case NoSaturation:
            case NoSaturation:
              s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddS16);
              s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddS16);
              satrv [BITIDX16 (i)] = 0;
              satrv [BITIDX16 (i)] = 0;
              r |= (s & 0xffff) << (i * 16);
              r |= (s & 0xffff) << (i * 16);
              SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
              SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
              SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
              SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
              SIMD16_SET (psr, carry,      SIMD_CBIT, i);
              SIMD16_SET (psr, carry,      SIMD_CBIT, i);
              SIMD16_SET (psr, overflow,   SIMD_VBIT, i);
              SIMD16_SET (psr, overflow,   SIMD_VBIT, i);
              break;
              break;
 
 
            case UnsignedSaturation:
            case UnsignedSaturation:
              s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddU16);
              s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddU16);
              x = IwmmxtSaturateU16 (s, satrv + BITIDX16 (i));
              x = IwmmxtSaturateU16 (s, satrv + BITIDX16 (i));
              r |= (x & 0xffff) << (i * 16);
              r |= (x & 0xffff) << (i * 16);
              SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
              SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
              SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
              SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX16 (i)])
              if (! satrv [BITIDX16 (i)])
                {
                {
                  SIMD16_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD16_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD16_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD16_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            case SignedSaturation:
            case SignedSaturation:
              s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddS16);
              s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddS16);
              x = IwmmxtSaturateS16 (s, satrv + BITIDX16 (i));
              x = IwmmxtSaturateS16 (s, satrv + BITIDX16 (i));
              r |= (x & 0xffff) << (i * 16);
              r |= (x & 0xffff) << (i * 16);
              SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
              SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
              SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
              SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX16 (i)])
              if (! satrv [BITIDX16 (i)])
                {
                {
                  SIMD16_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD16_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD16_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD16_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            default:
            default:
              ARMul_UndefInstr (state, instr);
              ARMul_UndefInstr (state, instr);
              return ARMul_DONE;
              return ARMul_DONE;
            }
            }
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
      satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
 
 
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          switch (BITS (20, 21))
          switch (BITS (20, 21))
            {
            {
            case NoSaturation:
            case NoSaturation:
              s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddS32);
              s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddS32);
              satrv [BITIDX32 (i)] = 0;
              satrv [BITIDX32 (i)] = 0;
              r |= (s & 0xffffffff) << (i * 32);
              r |= (s & 0xffffffff) << (i * 32);
              SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
              SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
              SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
              SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
              SIMD32_SET (psr, carry,      SIMD_CBIT, i);
              SIMD32_SET (psr, carry,      SIMD_CBIT, i);
              SIMD32_SET (psr, overflow,   SIMD_VBIT, i);
              SIMD32_SET (psr, overflow,   SIMD_VBIT, i);
              break;
              break;
 
 
            case UnsignedSaturation:
            case UnsignedSaturation:
              s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddU32);
              s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddU32);
              x = IwmmxtSaturateU32 (s, satrv + BITIDX32 (i));
              x = IwmmxtSaturateU32 (s, satrv + BITIDX32 (i));
              r |= (x & 0xffffffff) << (i * 32);
              r |= (x & 0xffffffff) << (i * 32);
              SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
              SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
              SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
              SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX32 (i)])
              if (! satrv [BITIDX32 (i)])
                {
                {
                  SIMD32_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD32_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD32_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD32_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            case SignedSaturation:
            case SignedSaturation:
              s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddS32);
              s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddS32);
              x = IwmmxtSaturateS32 (s, satrv + BITIDX32 (i));
              x = IwmmxtSaturateS32 (s, satrv + BITIDX32 (i));
              r |= (x & 0xffffffff) << (i * 32);
              r |= (x & 0xffffffff) << (i * 32);
              SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
              SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
              SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
              SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX32 (i)])
              if (! satrv [BITIDX32 (i)])
                {
                {
                  SIMD32_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD32_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD32_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD32_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            default:
            default:
              ARMul_UndefInstr (state, instr);
              ARMul_UndefInstr (state, instr);
              return ARMul_DONE;
              return ARMul_DONE;
            }
            }
        }
        }
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_MUP | WCON_CUP);
  wC [wCon] |= (WCON_MUP | WCON_CUP);
 
 
  SET_wCSSFvec (satrv);
  SET_wCSSFvec (satrv);
 
 
#undef ADDx
#undef ADDx
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WALIGNI (ARMword instr)
WALIGNI (ARMword instr)
{
{
  int shift = BITS (20, 22) * 8;
  int shift = BITS (20, 22) * 8;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "waligni\n");
  fprintf (stderr, "waligni\n");
#endif  
#endif  
 
 
  if (shift)
  if (shift)
    wR [BITS (12, 15)] =
    wR [BITS (12, 15)] =
      wRBITS (BITS (16, 19), shift, 63)
      wRBITS (BITS (16, 19), shift, 63)
      | (wRBITS (BITS (0, 3), 0, shift) << ((64 - shift)));
      | (wRBITS (BITS (0, 3), 0, shift) << ((64 - shift)));
  else
  else
    wR [BITS (12, 15)] = wR [BITS (16, 19)];
    wR [BITS (12, 15)] = wR [BITS (16, 19)];
 
 
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WALIGNR (ARMul_State * state, ARMword instr)
WALIGNR (ARMul_State * state, ARMword instr)
{
{
  int shift = (wC [BITS (20, 21) + 8] & 0x7) * 8;
  int shift = (wC [BITS (20, 21) + 8] & 0x7) * 8;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "walignr\n");
  fprintf (stderr, "walignr\n");
#endif  
#endif  
 
 
  if (shift)
  if (shift)
    wR [BITS (12, 15)] =
    wR [BITS (12, 15)] =
      wRBITS (BITS (16, 19), shift, 63)
      wRBITS (BITS (16, 19), shift, 63)
      | (wRBITS (BITS (0, 3), 0, shift) << ((64 - shift)));
      | (wRBITS (BITS (0, 3), 0, shift) << ((64 - shift)));
  else
  else
    wR [BITS (12, 15)] = wR [BITS (16, 19)];
    wR [BITS (12, 15)] = wR [BITS (16, 19)];
 
 
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WAND (ARMword instr)
WAND (ARMword instr)
{
{
  ARMdword result;
  ARMdword result;
  ARMword  psr = 0;
  ARMword  psr = 0;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wand\n");
  fprintf (stderr, "wand\n");
#endif  
#endif  
 
 
  result = wR [BITS (16, 19)] & wR [BITS (0, 3)];
  result = wR [BITS (16, 19)] & wR [BITS (0, 3)];
  wR [BITS (12, 15)] = result;
  wR [BITS (12, 15)] = result;
 
 
  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WANDN (ARMword instr)
WANDN (ARMword instr)
{
{
  ARMdword result;
  ARMdword result;
  ARMword  psr = 0;
  ARMword  psr = 0;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wandn\n");
  fprintf (stderr, "wandn\n");
#endif  
#endif  
 
 
  result = wR [BITS (16, 19)] & ~ wR [BITS (0, 3)];
  result = wR [BITS (16, 19)] & ~ wR [BITS (0, 3)];
  wR [BITS (12, 15)] = result;
  wR [BITS (12, 15)] = result;
 
 
  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WAVG2 (ARMword instr)
WAVG2 (ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMword  psr = 0;
  ARMword  psr = 0;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
  int      round = BIT (20) ? 1 : 0;
  int      round = BIT (20) ? 1 : 0;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wavg2\n");
  fprintf (stderr, "wavg2\n");
#endif  
#endif  
 
 
#define AVG2x(x, y, m) (((wRBITS (BITS (16, 19), (x), (y)) & (m)) \
#define AVG2x(x, y, m) (((wRBITS (BITS (16, 19), (x), (y)) & (m)) \
                       + (wRBITS (BITS ( 0,  3), (x), (y)) & (m)) \
                       + (wRBITS (BITS ( 0,  3), (x), (y)) & (m)) \
                       + round) / 2)
                       + round) / 2)
 
 
  if (BIT (22))
  if (BIT (22))
    {
    {
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          s = AVG2x ((i * 16), (i * 16) + 15, 0xffff) & 0xffff;
          s = AVG2x ((i * 16), (i * 16) + 15, 0xffff) & 0xffff;
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
          r |= s << (i * 16);
          r |= s << (i * 16);
        }
        }
    }
    }
  else
  else
    {
    {
      for (i = 0; i < 8; i++)
      for (i = 0; i < 8; i++)
        {
        {
          s = AVG2x ((i * 8), (i * 8) + 7, 0xff) & 0xff;
          s = AVG2x ((i * 8), (i * 8) + 7, 0xff) & 0xff;
          SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
          SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
          r |= s << (i * 8);
          r |= s << (i * 8);
        }
        }
    }
    }
 
 
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WCMPEQ (ARMul_State * state, ARMword instr)
WCMPEQ (ARMul_State * state, ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMword  psr = 0;
  ARMword  psr = 0;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wcmpeq\n");
  fprintf (stderr, "wcmpeq\n");
#endif  
#endif  
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      for (i = 0; i < 8; i++)
      for (i = 0; i < 8; i++)
        {
        {
          s = wRBYTE (BITS (16, 19), i) == wRBYTE (BITS (0, 3), i) ? 0xff : 0;
          s = wRBYTE (BITS (16, 19), i) == wRBYTE (BITS (0, 3), i) ? 0xff : 0;
          r |= s << (i * 8);
          r |= s << (i * 8);
          SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
          SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
          SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
          SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          s = wRHALF (BITS (16, 19), i) == wRHALF (BITS (0, 3), i) ? 0xffff : 0;
          s = wRHALF (BITS (16, 19), i) == wRHALF (BITS (0, 3), i) ? 0xffff : 0;
          r |= s << (i * 16);
          r |= s << (i * 16);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          s = wRWORD (BITS (16, 19), i) == wRWORD (BITS (0, 3), i) ? 0xffffffff : 0;
          s = wRWORD (BITS (16, 19), i) == wRWORD (BITS (0, 3), i) ? 0xffffffff : 0;
          r |= s << (i * 32);
          r |= s << (i * 32);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WCMPGT (ARMul_State * state, ARMword instr)
WCMPGT (ARMul_State * state, ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMword  psr = 0;
  ARMword  psr = 0;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wcmpgt\n");
  fprintf (stderr, "wcmpgt\n");
#endif  
#endif  
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      if (BIT (21))
      if (BIT (21))
        {
        {
          /* Use a signed comparison.  */
          /* Use a signed comparison.  */
          for (i = 0; i < 8; i++)
          for (i = 0; i < 8; i++)
            {
            {
              signed char a, b;
              signed char a, b;
 
 
              a = wRBYTE (BITS (16, 19), i);
              a = wRBYTE (BITS (16, 19), i);
              b = wRBYTE (BITS (0, 3), i);
              b = wRBYTE (BITS (0, 3), i);
 
 
              s = (a > b) ? 0xff : 0;
              s = (a > b) ? 0xff : 0;
              r |= s << (i * 8);
              r |= s << (i * 8);
              SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
              SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
              SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
              SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
            }
            }
        }
        }
      else
      else
        {
        {
          for (i = 0; i < 8; i++)
          for (i = 0; i < 8; i++)
            {
            {
              s = (wRBYTE (BITS (16, 19), i) > wRBYTE (BITS (0, 3), i))
              s = (wRBYTE (BITS (16, 19), i) > wRBYTE (BITS (0, 3), i))
                ? 0xff : 0;
                ? 0xff : 0;
              r |= s << (i * 8);
              r |= s << (i * 8);
              SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
              SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
              SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
              SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
            }
            }
        }
        }
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      if (BIT (21))
      if (BIT (21))
        {
        {
          for (i = 0; i < 4; i++)
          for (i = 0; i < 4; i++)
            {
            {
              signed int a, b;
              signed int a, b;
 
 
              a = wRHALF (BITS (16, 19), i);
              a = wRHALF (BITS (16, 19), i);
              a = EXTEND16 (a);
              a = EXTEND16 (a);
 
 
              b = wRHALF (BITS (0, 3), i);
              b = wRHALF (BITS (0, 3), i);
              b = EXTEND16 (b);
              b = EXTEND16 (b);
 
 
              s = (a > b) ? 0xffff : 0;
              s = (a > b) ? 0xffff : 0;
              r |= s << (i * 16);
              r |= s << (i * 16);
              SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
              SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
              SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
              SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
            }
            }
        }
        }
      else
      else
        {
        {
          for (i = 0; i < 4; i++)
          for (i = 0; i < 4; i++)
            {
            {
              s = (wRHALF (BITS (16, 19), i) > wRHALF (BITS (0, 3), i))
              s = (wRHALF (BITS (16, 19), i) > wRHALF (BITS (0, 3), i))
                ? 0xffff : 0;
                ? 0xffff : 0;
              r |= s << (i * 16);
              r |= s << (i * 16);
              SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
              SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
              SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
              SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
            }
            }
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      if (BIT (21))
      if (BIT (21))
        {
        {
          for (i = 0; i < 2; i++)
          for (i = 0; i < 2; i++)
            {
            {
              signed long a, b;
              signed long a, b;
 
 
              a = wRWORD (BITS (16, 19), i);
              a = wRWORD (BITS (16, 19), i);
              b = wRWORD (BITS (0, 3), i);
              b = wRWORD (BITS (0, 3), i);
 
 
              s = (a > b) ? 0xffffffff : 0;
              s = (a > b) ? 0xffffffff : 0;
              r |= s << (i * 32);
              r |= s << (i * 32);
              SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
              SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
              SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
              SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
            }
            }
        }
        }
      else
      else
        {
        {
          for (i = 0; i < 2; i++)
          for (i = 0; i < 2; i++)
            {
            {
              s = (wRWORD (BITS (16, 19), i) > wRWORD (BITS (0, 3), i))
              s = (wRWORD (BITS (16, 19), i) > wRWORD (BITS (0, 3), i))
                ? 0xffffffff : 0;
                ? 0xffffffff : 0;
              r |= s << (i * 32);
              r |= s << (i * 32);
              SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
              SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
              SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
              SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
            }
            }
        }
        }
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static ARMword
static ARMword
Compute_Iwmmxt_Address (ARMul_State * state, ARMword instr, int * pFailed)
Compute_Iwmmxt_Address (ARMul_State * state, ARMword instr, int * pFailed)
{
{
  ARMword  Rn;
  ARMword  Rn;
  ARMword  addr;
  ARMword  addr;
  ARMword  offset;
  ARMword  offset;
  ARMword  multiplier;
  ARMword  multiplier;
 
 
  * pFailed  = 0;
  * pFailed  = 0;
  Rn         = BITS (16, 19);
  Rn         = BITS (16, 19);
  addr       = state->Reg [Rn];
  addr       = state->Reg [Rn];
  offset     = BITS (0, 7);
  offset     = BITS (0, 7);
  multiplier = BIT (8) ? 4 : 1;
  multiplier = BIT (8) ? 4 : 1;
 
 
  if (BIT (24)) /* P */
  if (BIT (24)) /* P */
    {
    {
      /* Pre Indexed Addressing.  */
      /* Pre Indexed Addressing.  */
      if (BIT (23))
      if (BIT (23))
        addr += offset * multiplier;
        addr += offset * multiplier;
      else
      else
        addr -= offset * multiplier;
        addr -= offset * multiplier;
 
 
      /* Immediate Pre-Indexed.  */
      /* Immediate Pre-Indexed.  */
      if (BIT (21)) /* W */
      if (BIT (21)) /* W */
        {
        {
          if (Rn == 15)
          if (Rn == 15)
            {
            {
              /* Writeback into R15 is UNPREDICTABLE.  */
              /* Writeback into R15 is UNPREDICTABLE.  */
#ifdef DEBUG
#ifdef DEBUG
              fprintf (stderr, "iWMMXt: writeback into r15\n");
              fprintf (stderr, "iWMMXt: writeback into r15\n");
#endif
#endif
              * pFailed = 1;
              * pFailed = 1;
            }
            }
          else
          else
            state->Reg [Rn] = addr;
            state->Reg [Rn] = addr;
        }
        }
    }
    }
  else
  else
    {
    {
      /* Post Indexed Addressing.  */
      /* Post Indexed Addressing.  */
      if (BIT (21)) /* W */
      if (BIT (21)) /* W */
        {
        {
          /* Handle the write back of the final address.  */
          /* Handle the write back of the final address.  */
          if (Rn == 15)
          if (Rn == 15)
            {
            {
              /* Writeback into R15 is UNPREDICTABLE.  */
              /* Writeback into R15 is UNPREDICTABLE.  */
#ifdef DEBUG
#ifdef DEBUG
              fprintf (stderr, "iWMMXt: writeback into r15\n");
              fprintf (stderr, "iWMMXt: writeback into r15\n");
#endif  
#endif  
              * pFailed = 1;
              * pFailed = 1;
            }
            }
          else
          else
            {
            {
              ARMword  increment;
              ARMword  increment;
 
 
              if (BIT (23))
              if (BIT (23))
                increment = offset * multiplier;
                increment = offset * multiplier;
              else
              else
                increment = - (offset * multiplier);
                increment = - (offset * multiplier);
 
 
              state->Reg [Rn] = addr + increment;
              state->Reg [Rn] = addr + increment;
            }
            }
        }
        }
      else
      else
        {
        {
          /* P == 0, W == 0, U == 0 is UNPREDICTABLE.  */
          /* P == 0, W == 0, U == 0 is UNPREDICTABLE.  */
          if (BIT (23) == 0)
          if (BIT (23) == 0)
            {
            {
#ifdef DEBUG
#ifdef DEBUG
              fprintf (stderr, "iWMMXt: undefined addressing mode\n");
              fprintf (stderr, "iWMMXt: undefined addressing mode\n");
#endif  
#endif  
              * pFailed = 1;
              * pFailed = 1;
            }
            }
        }
        }
    }
    }
 
 
  return addr;
  return addr;
}
}
 
 
static ARMdword
static ARMdword
Iwmmxt_Load_Double_Word (ARMul_State * state, ARMword address)
Iwmmxt_Load_Double_Word (ARMul_State * state, ARMword address)
{
{
  ARMdword value;
  ARMdword value;
 
 
  /* The address must be aligned on a 8 byte boundary.  */
  /* The address must be aligned on a 8 byte boundary.  */
  if (address & 0x7)
  if (address & 0x7)
    {
    {
      fprintf (stderr, "iWMMXt: At addr 0x%x: Unaligned double word load from 0x%x\n",
      fprintf (stderr, "iWMMXt: At addr 0x%x: Unaligned double word load from 0x%x\n",
               (state->Reg[15] - 8) & ~0x3, address);
               (state->Reg[15] - 8) & ~0x3, address);
#ifdef DEBUG
#ifdef DEBUG
#endif
#endif
      /* No need to check for alignment traps.  An unaligned
      /* No need to check for alignment traps.  An unaligned
         double word load with alignment trapping disabled is
         double word load with alignment trapping disabled is
         UNPREDICTABLE.  */
         UNPREDICTABLE.  */
      ARMul_Abort (state, ARMul_DataAbortV);
      ARMul_Abort (state, ARMul_DataAbortV);
    }
    }
 
 
  /* Load the words.  */
  /* Load the words.  */
  if (! state->bigendSig)
  if (! state->bigendSig)
    {
    {
      value = ARMul_LoadWordN (state, address + 4);
      value = ARMul_LoadWordN (state, address + 4);
      value <<= 32;
      value <<= 32;
      value |= ARMul_LoadWordN (state, address);
      value |= ARMul_LoadWordN (state, address);
    }
    }
  else
  else
    {
    {
      value = ARMul_LoadWordN (state, address);
      value = ARMul_LoadWordN (state, address);
      value <<= 32;
      value <<= 32;
      value |= ARMul_LoadWordN (state, address + 4);
      value |= ARMul_LoadWordN (state, address + 4);
    }
    }
 
 
  /* Check for data aborts.  */
  /* Check for data aborts.  */
  if (state->Aborted)
  if (state->Aborted)
    ARMul_Abort (state, ARMul_DataAbortV);
    ARMul_Abort (state, ARMul_DataAbortV);
  else
  else
    ARMul_Icycles (state, 2, 0L);
    ARMul_Icycles (state, 2, 0L);
 
 
  return value;
  return value;
}
}
 
 
static ARMword
static ARMword
Iwmmxt_Load_Word (ARMul_State * state, ARMword address)
Iwmmxt_Load_Word (ARMul_State * state, ARMword address)
{
{
  ARMword value;
  ARMword value;
 
 
  /* Check for a misaligned address.  */
  /* Check for a misaligned address.  */
  if (address & 3)
  if (address & 3)
    {
    {
      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
        ARMul_Abort (state, ARMul_DataAbortV);
        ARMul_Abort (state, ARMul_DataAbortV);
      else
      else
        address &= ~ 3;
        address &= ~ 3;
    }
    }
 
 
  value = ARMul_LoadWordN (state, address);
  value = ARMul_LoadWordN (state, address);
 
 
  if (state->Aborted)
  if (state->Aborted)
    ARMul_Abort (state, ARMul_DataAbortV);
    ARMul_Abort (state, ARMul_DataAbortV);
  else
  else
    ARMul_Icycles (state, 1, 0L);
    ARMul_Icycles (state, 1, 0L);
 
 
  return value;
  return value;
}
}
 
 
static ARMword
static ARMword
Iwmmxt_Load_Half_Word (ARMul_State * state, ARMword address)
Iwmmxt_Load_Half_Word (ARMul_State * state, ARMword address)
{
{
  ARMword value;
  ARMword value;
 
 
  /* Check for a misaligned address.  */
  /* Check for a misaligned address.  */
  if (address & 1)
  if (address & 1)
    {
    {
      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
        ARMul_Abort (state, ARMul_DataAbortV);
        ARMul_Abort (state, ARMul_DataAbortV);
      else
      else
        address &= ~ 1;
        address &= ~ 1;
    }
    }
 
 
  value = ARMul_LoadHalfWord (state, address);
  value = ARMul_LoadHalfWord (state, address);
 
 
  if (state->Aborted)
  if (state->Aborted)
    ARMul_Abort (state, ARMul_DataAbortV);
    ARMul_Abort (state, ARMul_DataAbortV);
  else
  else
    ARMul_Icycles (state, 1, 0L);
    ARMul_Icycles (state, 1, 0L);
 
 
  return value;
  return value;
}
}
 
 
static ARMword
static ARMword
Iwmmxt_Load_Byte (ARMul_State * state, ARMword address)
Iwmmxt_Load_Byte (ARMul_State * state, ARMword address)
{
{
  ARMword value;
  ARMword value;
 
 
  value = ARMul_LoadByte (state, address);
  value = ARMul_LoadByte (state, address);
 
 
  if (state->Aborted)
  if (state->Aborted)
    ARMul_Abort (state, ARMul_DataAbortV);
    ARMul_Abort (state, ARMul_DataAbortV);
  else
  else
    ARMul_Icycles (state, 1, 0L);
    ARMul_Icycles (state, 1, 0L);
 
 
  return value;
  return value;
}
}
 
 
static void
static void
Iwmmxt_Store_Double_Word (ARMul_State * state, ARMword address, ARMdword value)
Iwmmxt_Store_Double_Word (ARMul_State * state, ARMword address, ARMdword value)
{
{
  /* The address must be aligned on a 8 byte boundary.  */
  /* The address must be aligned on a 8 byte boundary.  */
  if (address & 0x7)
  if (address & 0x7)
    {
    {
      fprintf (stderr, "iWMMXt: At addr 0x%x: Unaligned double word store to 0x%x\n",
      fprintf (stderr, "iWMMXt: At addr 0x%x: Unaligned double word store to 0x%x\n",
               (state->Reg[15] - 8) & ~0x3, address);
               (state->Reg[15] - 8) & ~0x3, address);
#ifdef DEBUG
#ifdef DEBUG
#endif
#endif
      /* No need to check for alignment traps.  An unaligned
      /* No need to check for alignment traps.  An unaligned
         double word store with alignment trapping disabled is
         double word store with alignment trapping disabled is
         UNPREDICTABLE.  */
         UNPREDICTABLE.  */
      ARMul_Abort (state, ARMul_DataAbortV);
      ARMul_Abort (state, ARMul_DataAbortV);
    }
    }
 
 
  /* Store the words.  */
  /* Store the words.  */
  if (! state->bigendSig)
  if (! state->bigendSig)
    {
    {
      ARMul_StoreWordN (state, address, value);
      ARMul_StoreWordN (state, address, value);
      ARMul_StoreWordN (state, address + 4, value >> 32);
      ARMul_StoreWordN (state, address + 4, value >> 32);
    }
    }
  else
  else
    {
    {
      ARMul_StoreWordN (state, address + 4, value);
      ARMul_StoreWordN (state, address + 4, value);
      ARMul_StoreWordN (state, address, value >> 32);
      ARMul_StoreWordN (state, address, value >> 32);
    }
    }
 
 
  /* Check for data aborts.  */
  /* Check for data aborts.  */
  if (state->Aborted)
  if (state->Aborted)
    ARMul_Abort (state, ARMul_DataAbortV);
    ARMul_Abort (state, ARMul_DataAbortV);
  else
  else
    ARMul_Icycles (state, 2, 0L);
    ARMul_Icycles (state, 2, 0L);
}
}
 
 
static void
static void
Iwmmxt_Store_Word (ARMul_State * state, ARMword address, ARMword value)
Iwmmxt_Store_Word (ARMul_State * state, ARMword address, ARMword value)
{
{
  /* Check for a misaligned address.  */
  /* Check for a misaligned address.  */
  if (address & 3)
  if (address & 3)
    {
    {
      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
        ARMul_Abort (state, ARMul_DataAbortV);
        ARMul_Abort (state, ARMul_DataAbortV);
      else
      else
        address &= ~ 3;
        address &= ~ 3;
    }
    }
 
 
  ARMul_StoreWordN (state, address, value);
  ARMul_StoreWordN (state, address, value);
 
 
  if (state->Aborted)
  if (state->Aborted)
    ARMul_Abort (state, ARMul_DataAbortV);
    ARMul_Abort (state, ARMul_DataAbortV);
}
}
 
 
static void
static void
Iwmmxt_Store_Half_Word (ARMul_State * state, ARMword address, ARMword value)
Iwmmxt_Store_Half_Word (ARMul_State * state, ARMword address, ARMword value)
{
{
  /* Check for a misaligned address.  */
  /* Check for a misaligned address.  */
  if (address & 1)
  if (address & 1)
    {
    {
      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
        ARMul_Abort (state, ARMul_DataAbortV);
        ARMul_Abort (state, ARMul_DataAbortV);
      else
      else
        address &= ~ 1;
        address &= ~ 1;
    }
    }
 
 
  ARMul_StoreHalfWord (state, address, value);
  ARMul_StoreHalfWord (state, address, value);
 
 
  if (state->Aborted)
  if (state->Aborted)
    ARMul_Abort (state, ARMul_DataAbortV);
    ARMul_Abort (state, ARMul_DataAbortV);
}
}
 
 
static void
static void
Iwmmxt_Store_Byte (ARMul_State * state, ARMword address, ARMword value)
Iwmmxt_Store_Byte (ARMul_State * state, ARMword address, ARMword value)
{
{
  ARMul_StoreByte (state, address, value);
  ARMul_StoreByte (state, address, value);
 
 
  if (state->Aborted)
  if (state->Aborted)
    ARMul_Abort (state, ARMul_DataAbortV);
    ARMul_Abort (state, ARMul_DataAbortV);
}
}
 
 
static int
static int
WLDR (ARMul_State * state, ARMword instr)
WLDR (ARMul_State * state, ARMword instr)
{
{
  ARMword address;
  ARMword address;
  int failed;
  int failed;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wldr\n");
  fprintf (stderr, "wldr\n");
#endif  
#endif  
 
 
  address = Compute_Iwmmxt_Address (state, instr, & failed);
  address = Compute_Iwmmxt_Address (state, instr, & failed);
  if (failed)
  if (failed)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  if (BITS (28, 31) == 0xf)
  if (BITS (28, 31) == 0xf)
    {
    {
      /* WLDRW wCx */
      /* WLDRW wCx */
      wC [BITS (12, 15)] = Iwmmxt_Load_Word (state, address);
      wC [BITS (12, 15)] = Iwmmxt_Load_Word (state, address);
    }
    }
  else if (BIT (8) == 0)
  else if (BIT (8) == 0)
    {
    {
      if (BIT (22) == 0)
      if (BIT (22) == 0)
        /* WLDRB */
        /* WLDRB */
        wR [BITS (12, 15)] = Iwmmxt_Load_Byte (state, address);
        wR [BITS (12, 15)] = Iwmmxt_Load_Byte (state, address);
      else
      else
        /* WLDRH */
        /* WLDRH */
        wR [BITS (12, 15)] = Iwmmxt_Load_Half_Word (state, address);
        wR [BITS (12, 15)] = Iwmmxt_Load_Half_Word (state, address);
    }
    }
  else
  else
    {
    {
      if (BIT (22) == 0)
      if (BIT (22) == 0)
        /* WLDRW wRd */
        /* WLDRW wRd */
        wR [BITS (12, 15)] = Iwmmxt_Load_Word (state, address);
        wR [BITS (12, 15)] = Iwmmxt_Load_Word (state, address);
      else
      else
        /* WLDRD */
        /* WLDRD */
        wR [BITS (12, 15)] = Iwmmxt_Load_Double_Word (state, address);
        wR [BITS (12, 15)] = Iwmmxt_Load_Double_Word (state, address);
    }
    }
 
 
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WMAC (ARMword instr)
WMAC (ARMword instr)
{
{
  int      i;
  int      i;
  ARMdword t = 0;
  ARMdword t = 0;
  ARMword  a, b;
  ARMword  a, b;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wmac\n");
  fprintf (stderr, "wmac\n");
#endif  
#endif  
 
 
  for (i = 0; i < 4; i++)
  for (i = 0; i < 4; i++)
    {
    {
      if (BIT (21))
      if (BIT (21))
        {
        {
          /* Signed.  */
          /* Signed.  */
          signed long s;
          signed long s;
 
 
          a = wRHALF (BITS (16, 19), i);
          a = wRHALF (BITS (16, 19), i);
          a = EXTEND16 (a);
          a = EXTEND16 (a);
 
 
          b = wRHALF (BITS (0, 3), i);
          b = wRHALF (BITS (0, 3), i);
          b = EXTEND16 (b);
          b = EXTEND16 (b);
 
 
          s = (signed long) a * (signed long) b;
          s = (signed long) a * (signed long) b;
 
 
          t = t + (ARMdword) s;
          t = t + (ARMdword) s;
        }
        }
      else
      else
        {
        {
          /* Unsigned.  */
          /* Unsigned.  */
          a = wRHALF (BITS (16, 19), i);
          a = wRHALF (BITS (16, 19), i);
          b = wRHALF (BITS ( 0,  3), i);
          b = wRHALF (BITS ( 0,  3), i);
 
 
          t += a * b;
          t += a * b;
        }
        }
    }
    }
 
 
  if (BIT (20))
  if (BIT (20))
    wR [BITS (12, 15)] = 0;
    wR [BITS (12, 15)] = 0;
 
 
  if (BIT (21)) /* Signed.  */
  if (BIT (21)) /* Signed.  */
    wR[BITS (12, 15)] += t;
    wR[BITS (12, 15)] += t;
  else
  else
    wR [BITS (12, 15)] += t;
    wR [BITS (12, 15)] += t;
 
 
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WMADD (ARMword instr)
WMADD (ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  int i;
  int i;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wmadd\n");
  fprintf (stderr, "wmadd\n");
#endif  
#endif  
 
 
  for (i = 0; i < 2; i++)
  for (i = 0; i < 2; i++)
    {
    {
      ARMdword s1, s2;
      ARMdword s1, s2;
 
 
      if (BIT (21))     /* Signed.  */
      if (BIT (21))     /* Signed.  */
        {
        {
          signed long a, b;
          signed long a, b;
 
 
          a = wRHALF (BITS (16, 19), i * 2);
          a = wRHALF (BITS (16, 19), i * 2);
          a = EXTEND16 (a);
          a = EXTEND16 (a);
 
 
          b = wRHALF (BITS (0, 3), i * 2);
          b = wRHALF (BITS (0, 3), i * 2);
          b = EXTEND16 (b);
          b = EXTEND16 (b);
 
 
          s1 = (ARMdword) (a * b);
          s1 = (ARMdword) (a * b);
 
 
          a = wRHALF (BITS (16, 19), i * 2 + 1);
          a = wRHALF (BITS (16, 19), i * 2 + 1);
          a = EXTEND16 (a);
          a = EXTEND16 (a);
 
 
          b = wRHALF (BITS (0, 3), i * 2 + 1);
          b = wRHALF (BITS (0, 3), i * 2 + 1);
          b = EXTEND16 (b);
          b = EXTEND16 (b);
 
 
          s2 = (ARMdword) (a * b);
          s2 = (ARMdword) (a * b);
        }
        }
      else                      /* Unsigned.  */
      else                      /* Unsigned.  */
        {
        {
          unsigned long a, b;
          unsigned long a, b;
 
 
          a = wRHALF (BITS (16, 19), i * 2);
          a = wRHALF (BITS (16, 19), i * 2);
          b = wRHALF (BITS ( 0,  3), i * 2);
          b = wRHALF (BITS ( 0,  3), i * 2);
 
 
          s1 = (ARMdword) (a * b);
          s1 = (ARMdword) (a * b);
 
 
          a = wRHALF (BITS (16, 19), i * 2 + 1);
          a = wRHALF (BITS (16, 19), i * 2 + 1);
          b = wRHALF (BITS ( 0,  3), i * 2 + 1);
          b = wRHALF (BITS ( 0,  3), i * 2 + 1);
 
 
          s2 = (ARMdword) a * b;
          s2 = (ARMdword) a * b;
        }
        }
 
 
      r |= (ARMdword) ((s1 + s2) & 0xffffffff) << (i ? 32 : 0);
      r |= (ARMdword) ((s1 + s2) & 0xffffffff) << (i ? 32 : 0);
    }
    }
 
 
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WMAX (ARMul_State * state, ARMword instr)
WMAX (ARMul_State * state, ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wmax\n");
  fprintf (stderr, "wmax\n");
#endif  
#endif  
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      for (i = 0; i < 8; i++)
      for (i = 0; i < 8; i++)
        if (BIT (21))   /* Signed.  */
        if (BIT (21))   /* Signed.  */
          {
          {
            int a, b;
            int a, b;
 
 
            a = wRBYTE (BITS (16, 19), i);
            a = wRBYTE (BITS (16, 19), i);
            a = EXTEND8 (a);
            a = EXTEND8 (a);
 
 
            b = wRBYTE (BITS (0, 3), i);
            b = wRBYTE (BITS (0, 3), i);
            b = EXTEND8 (b);
            b = EXTEND8 (b);
 
 
            if (a > b)
            if (a > b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xff) << (i * 8);
            r |= (s & 0xff) << (i * 8);
          }
          }
        else            /* Unsigned.  */
        else            /* Unsigned.  */
          {
          {
            unsigned int a, b;
            unsigned int a, b;
 
 
            a = wRBYTE (BITS (16, 19), i);
            a = wRBYTE (BITS (16, 19), i);
            b = wRBYTE (BITS (0, 3), i);
            b = wRBYTE (BITS (0, 3), i);
 
 
            if (a > b)
            if (a > b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xff) << (i * 8);
            r |= (s & 0xff) << (i * 8);
          }
          }
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        if (BIT (21))   /* Signed.  */
        if (BIT (21))   /* Signed.  */
          {
          {
            int a, b;
            int a, b;
 
 
            a = wRHALF (BITS (16, 19), i);
            a = wRHALF (BITS (16, 19), i);
            a = EXTEND16 (a);
            a = EXTEND16 (a);
 
 
            b = wRHALF (BITS (0, 3), i);
            b = wRHALF (BITS (0, 3), i);
            b = EXTEND16 (b);
            b = EXTEND16 (b);
 
 
            if (a > b)
            if (a > b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xffff) << (i * 16);
            r |= (s & 0xffff) << (i * 16);
          }
          }
        else            /* Unsigned.  */
        else            /* Unsigned.  */
          {
          {
            unsigned int a, b;
            unsigned int a, b;
 
 
            a = wRHALF (BITS (16, 19), i);
            a = wRHALF (BITS (16, 19), i);
            b = wRHALF (BITS (0, 3), i);
            b = wRHALF (BITS (0, 3), i);
 
 
            if (a > b)
            if (a > b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xffff) << (i * 16);
            r |= (s & 0xffff) << (i * 16);
          }
          }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        if (BIT (21))   /* Signed.  */
        if (BIT (21))   /* Signed.  */
          {
          {
            int a, b;
            int a, b;
 
 
            a = wRWORD (BITS (16, 19), i);
            a = wRWORD (BITS (16, 19), i);
            b = wRWORD (BITS (0, 3), i);
            b = wRWORD (BITS (0, 3), i);
 
 
            if (a > b)
            if (a > b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xffffffff) << (i * 32);
            r |= (s & 0xffffffff) << (i * 32);
          }
          }
        else
        else
          {
          {
            unsigned int a, b;
            unsigned int a, b;
 
 
            a = wRWORD (BITS (16, 19), i);
            a = wRWORD (BITS (16, 19), i);
            b = wRWORD (BITS (0, 3), i);
            b = wRWORD (BITS (0, 3), i);
 
 
            if (a > b)
            if (a > b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xffffffff) << (i * 32);
            r |= (s & 0xffffffff) << (i * 32);
          }
          }
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WMIN (ARMul_State * state, ARMword instr)
WMIN (ARMul_State * state, ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wmin\n");
  fprintf (stderr, "wmin\n");
#endif  
#endif  
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      for (i = 0; i < 8; i++)
      for (i = 0; i < 8; i++)
        if (BIT (21))   /* Signed.  */
        if (BIT (21))   /* Signed.  */
          {
          {
            int a, b;
            int a, b;
 
 
            a = wRBYTE (BITS (16, 19), i);
            a = wRBYTE (BITS (16, 19), i);
            a = EXTEND8 (a);
            a = EXTEND8 (a);
 
 
            b = wRBYTE (BITS (0, 3), i);
            b = wRBYTE (BITS (0, 3), i);
            b = EXTEND8 (b);
            b = EXTEND8 (b);
 
 
            if (a < b)
            if (a < b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xff) << (i * 8);
            r |= (s & 0xff) << (i * 8);
          }
          }
        else            /* Unsigned.  */
        else            /* Unsigned.  */
          {
          {
            unsigned int a, b;
            unsigned int a, b;
 
 
            a = wRBYTE (BITS (16, 19), i);
            a = wRBYTE (BITS (16, 19), i);
            b = wRBYTE (BITS (0, 3), i);
            b = wRBYTE (BITS (0, 3), i);
 
 
            if (a < b)
            if (a < b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xff) << (i * 8);
            r |= (s & 0xff) << (i * 8);
          }
          }
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        if (BIT (21))   /* Signed.  */
        if (BIT (21))   /* Signed.  */
          {
          {
            int a, b;
            int a, b;
 
 
            a = wRHALF (BITS (16, 19), i);
            a = wRHALF (BITS (16, 19), i);
            a = EXTEND16 (a);
            a = EXTEND16 (a);
 
 
            b = wRHALF (BITS (0, 3), i);
            b = wRHALF (BITS (0, 3), i);
            b = EXTEND16 (b);
            b = EXTEND16 (b);
 
 
            if (a < b)
            if (a < b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xffff) << (i * 16);
            r |= (s & 0xffff) << (i * 16);
          }
          }
        else
        else
          {
          {
            /* Unsigned.  */
            /* Unsigned.  */
            unsigned int a, b;
            unsigned int a, b;
 
 
            a = wRHALF (BITS (16, 19), i);
            a = wRHALF (BITS (16, 19), i);
            b = wRHALF (BITS ( 0,  3), i);
            b = wRHALF (BITS ( 0,  3), i);
 
 
            if (a < b)
            if (a < b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xffff) << (i * 16);
            r |= (s & 0xffff) << (i * 16);
          }
          }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        if (BIT (21))   /* Signed.  */
        if (BIT (21))   /* Signed.  */
          {
          {
            int a, b;
            int a, b;
 
 
            a = wRWORD (BITS (16, 19), i);
            a = wRWORD (BITS (16, 19), i);
            b = wRWORD (BITS ( 0,  3), i);
            b = wRWORD (BITS ( 0,  3), i);
 
 
            if (a < b)
            if (a < b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xffffffff) << (i * 32);
            r |= (s & 0xffffffff) << (i * 32);
          }
          }
        else
        else
          {
          {
            unsigned int a, b;
            unsigned int a, b;
 
 
            a = wRWORD (BITS (16, 19), i);
            a = wRWORD (BITS (16, 19), i);
            b = wRWORD (BITS (0, 3), i);
            b = wRWORD (BITS (0, 3), i);
 
 
            if (a < b)
            if (a < b)
              s = a;
              s = a;
            else
            else
              s = b;
              s = b;
 
 
            r |= (s & 0xffffffff) << (i * 32);
            r |= (s & 0xffffffff) << (i * 32);
          }
          }
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WMUL (ARMword instr)
WMUL (ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wmul\n");
  fprintf (stderr, "wmul\n");
#endif  
#endif  
 
 
  for (i = 0; i < 4; i++)
  for (i = 0; i < 4; i++)
    if (BIT (21))       /* Signed.  */
    if (BIT (21))       /* Signed.  */
      {
      {
        long a, b;
        long a, b;
 
 
        a = wRHALF (BITS (16, 19), i);
        a = wRHALF (BITS (16, 19), i);
        a = EXTEND16 (a);
        a = EXTEND16 (a);
 
 
        b = wRHALF (BITS (0, 3), i);
        b = wRHALF (BITS (0, 3), i);
        b = EXTEND16 (b);
        b = EXTEND16 (b);
 
 
        s = a * b;
        s = a * b;
 
 
        if (BIT (20))
        if (BIT (20))
          r |= ((s >> 16) & 0xffff) << (i * 16);
          r |= ((s >> 16) & 0xffff) << (i * 16);
        else
        else
          r |= (s & 0xffff) << (i * 16);
          r |= (s & 0xffff) << (i * 16);
      }
      }
    else                /* Unsigned.  */
    else                /* Unsigned.  */
      {
      {
        unsigned long a, b;
        unsigned long a, b;
 
 
        a = wRHALF (BITS (16, 19), i);
        a = wRHALF (BITS (16, 19), i);
        b = wRHALF (BITS (0, 3), i);
        b = wRHALF (BITS (0, 3), i);
 
 
        s = a * b;
        s = a * b;
 
 
        if (BIT (20))
        if (BIT (20))
          r |= ((s >> 16) & 0xffff) << (i * 16);
          r |= ((s >> 16) & 0xffff) << (i * 16);
        else
        else
          r |= (s & 0xffff) << (i * 16);
          r |= (s & 0xffff) << (i * 16);
      }
      }
 
 
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WOR (ARMword instr)
WOR (ARMword instr)
{
{
  ARMword psr = 0;
  ARMword psr = 0;
  ARMdword result;
  ARMdword result;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wor\n");
  fprintf (stderr, "wor\n");
#endif  
#endif  
 
 
  result = wR [BITS (16, 19)] | wR [BITS (0, 3)];
  result = wR [BITS (16, 19)] | wR [BITS (0, 3)];
  wR [BITS (12, 15)] = result;
  wR [BITS (12, 15)] = result;
 
 
  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WPACK (ARMul_State * state, ARMword instr)
WPACK (ARMul_State * state, ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMword  psr = 0;
  ARMword  psr = 0;
  ARMdword x;
  ARMdword x;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
  int      satrv[8];
  int      satrv[8];
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wpack\n");
  fprintf (stderr, "wpack\n");
#endif  
#endif  
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Hqual:
    case Hqual:
      for (i = 0; i < 8; i++)
      for (i = 0; i < 8; i++)
        {
        {
          x = wRHALF (i < 4 ? BITS (16, 19) : BITS (0, 3), i & 3);
          x = wRHALF (i < 4 ? BITS (16, 19) : BITS (0, 3), i & 3);
 
 
          switch (BITS (20, 21))
          switch (BITS (20, 21))
            {
            {
            case UnsignedSaturation:
            case UnsignedSaturation:
              s = IwmmxtSaturateU8 (x, satrv + BITIDX8 (i));
              s = IwmmxtSaturateU8 (x, satrv + BITIDX8 (i));
              break;
              break;
 
 
            case SignedSaturation:
            case SignedSaturation:
              s = IwmmxtSaturateS8 (x, satrv + BITIDX8 (i));
              s = IwmmxtSaturateS8 (x, satrv + BITIDX8 (i));
              break;
              break;
 
 
            default:
            default:
              ARMul_UndefInstr (state, instr);
              ARMul_UndefInstr (state, instr);
              return ARMul_DONE;
              return ARMul_DONE;
            }
            }
 
 
          r |= (s & 0xff) << (i * 8);
          r |= (s & 0xff) << (i * 8);
          SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
          SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
          SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
          SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
      satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
 
 
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          x = wRWORD (i < 2 ? BITS (16, 19) : BITS (0, 3), i & 1);
          x = wRWORD (i < 2 ? BITS (16, 19) : BITS (0, 3), i & 1);
 
 
          switch (BITS (20, 21))
          switch (BITS (20, 21))
            {
            {
            case UnsignedSaturation:
            case UnsignedSaturation:
              s = IwmmxtSaturateU16 (x, satrv + BITIDX16 (i));
              s = IwmmxtSaturateU16 (x, satrv + BITIDX16 (i));
              break;
              break;
 
 
            case SignedSaturation:
            case SignedSaturation:
              s = IwmmxtSaturateS16 (x, satrv + BITIDX16 (i));
              s = IwmmxtSaturateS16 (x, satrv + BITIDX16 (i));
              break;
              break;
 
 
            default:
            default:
              ARMul_UndefInstr (state, instr);
              ARMul_UndefInstr (state, instr);
              return ARMul_DONE;
              return ARMul_DONE;
            }
            }
 
 
          r |= (s & 0xffff) << (i * 16);
          r |= (s & 0xffff) << (i * 16);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Dqual:
    case Dqual:
      satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
      satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
 
 
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          x = wR [i ? BITS (0, 3) : BITS (16, 19)];
          x = wR [i ? BITS (0, 3) : BITS (16, 19)];
 
 
          switch (BITS (20, 21))
          switch (BITS (20, 21))
            {
            {
            case UnsignedSaturation:
            case UnsignedSaturation:
              s = IwmmxtSaturateU32 (x, satrv + BITIDX32 (i));
              s = IwmmxtSaturateU32 (x, satrv + BITIDX32 (i));
              break;
              break;
 
 
            case SignedSaturation:
            case SignedSaturation:
              s = IwmmxtSaturateS32 (x, satrv + BITIDX32 (i));
              s = IwmmxtSaturateS32 (x, satrv + BITIDX32 (i));
              break;
              break;
 
 
            default:
            default:
              ARMul_UndefInstr (state, instr);
              ARMul_UndefInstr (state, instr);
              return ARMul_DONE;
              return ARMul_DONE;
            }
            }
 
 
          r |= (s & 0xffffffff) << (i * 32);
          r |= (s & 0xffffffff) << (i * 32);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  SET_wCSSFvec (satrv);
  SET_wCSSFvec (satrv);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WROR (ARMul_State * state, ARMword instr)
WROR (ARMul_State * state, ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMdword s;
  ARMdword s;
  ARMword  psr = 0;
  ARMword  psr = 0;
  int      i;
  int      i;
  int      shift;
  int      shift;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wror\n");
  fprintf (stderr, "wror\n");
#endif  
#endif  
 
 
  DECODE_G_BIT (state, instr, shift);
  DECODE_G_BIT (state, instr, shift);
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Hqual:
    case Hqual:
      shift &= 0xf;
      shift &= 0xf;
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          s = ((wRHALF (BITS (16, 19), i) & 0xffff) << (16 - shift))
          s = ((wRHALF (BITS (16, 19), i) & 0xffff) << (16 - shift))
            | ((wRHALF (BITS (16, 19), i) & 0xffff) >> shift);
            | ((wRHALF (BITS (16, 19), i) & 0xffff) >> shift);
          r |= (s & 0xffff) << (i * 16);
          r |= (s & 0xffff) << (i * 16);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      shift &= 0x1f;
      shift &= 0x1f;
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          s = ((wRWORD (BITS (16, 19), i) & 0xffffffff) << (32 - shift))
          s = ((wRWORD (BITS (16, 19), i) & 0xffffffff) << (32 - shift))
            | ((wRWORD (BITS (16, 19), i) & 0xffffffff) >> shift);
            | ((wRWORD (BITS (16, 19), i) & 0xffffffff) >> shift);
          r |= (s & 0xffffffff) << (i * 32);
          r |= (s & 0xffffffff) << (i * 32);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Dqual:
    case Dqual:
      shift &= 0x3f;
      shift &= 0x3f;
      r = (wR [BITS (16, 19)] >> shift)
      r = (wR [BITS (16, 19)] >> shift)
        | (wR [BITS (16, 19)] << (64 - shift));
        | (wR [BITS (16, 19)] << (64 - shift));
 
 
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WSAD (ARMword instr)
WSAD (ARMword instr)
{
{
  ARMdword r;
  ARMdword r;
  int      s;
  int      s;
  int      i;
  int      i;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wsad\n");
  fprintf (stderr, "wsad\n");
#endif  
#endif  
 
 
  /* Z bit.  */
  /* Z bit.  */
  r = BIT (20) ? 0 : (wR [BITS (12, 15)] & 0xffffffff);
  r = BIT (20) ? 0 : (wR [BITS (12, 15)] & 0xffffffff);
 
 
  if (BIT (22))
  if (BIT (22))
    /* Half.  */
    /* Half.  */
    for (i = 0; i < 4; i++)
    for (i = 0; i < 4; i++)
      {
      {
        s = (wRHALF (BITS (16, 19), i) - wRHALF (BITS (0, 3), i));
        s = (wRHALF (BITS (16, 19), i) - wRHALF (BITS (0, 3), i));
        r += abs (s);
        r += abs (s);
      }
      }
  else
  else
    /* Byte.  */
    /* Byte.  */
    for (i = 0; i < 8; i++)
    for (i = 0; i < 8; i++)
      {
      {
        s = (wRBYTE (BITS (16, 19), i) - wRBYTE (BITS (0, 3), i));
        s = (wRBYTE (BITS (16, 19), i) - wRBYTE (BITS (0, 3), i));
        r += abs (s);
        r += abs (s);
      }
      }
 
 
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= WCON_MUP;
  wC [wCon] |= WCON_MUP;
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WSHUFH (ARMword instr)
WSHUFH (ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMword  psr = 0;
  ARMword  psr = 0;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
  int      imm8;
  int      imm8;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wshufh\n");
  fprintf (stderr, "wshufh\n");
#endif  
#endif  
 
 
  imm8 = (BITS (20, 23) << 4) | BITS (0, 3);
  imm8 = (BITS (20, 23) << 4) | BITS (0, 3);
 
 
  for (i = 0; i < 4; i++)
  for (i = 0; i < 4; i++)
    {
    {
      s = wRHALF (BITS (16, 19), ((imm8 >> (i * 2) & 3)) & 0xff);
      s = wRHALF (BITS (16, 19), ((imm8 >> (i * 2) & 3)) & 0xff);
      r |= (s & 0xffff) << (i * 16);
      r |= (s & 0xffff) << (i * 16);
      SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
      SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
      SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
      SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WSLL (ARMul_State * state, ARMword instr)
WSLL (ARMul_State * state, ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMdword s;
  ARMdword s;
  ARMword  psr = 0;
  ARMword  psr = 0;
  int      i;
  int      i;
  unsigned shift;
  unsigned shift;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wsll\n");
  fprintf (stderr, "wsll\n");
#endif  
#endif  
 
 
  DECODE_G_BIT (state, instr, shift);
  DECODE_G_BIT (state, instr, shift);
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Hqual:
    case Hqual:
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          if (shift > 15)
          if (shift > 15)
            s = 0;
            s = 0;
          else
          else
            s = ((wRHALF (BITS (16, 19), i) & 0xffff) << shift);
            s = ((wRHALF (BITS (16, 19), i) & 0xffff) << shift);
          r |= (s & 0xffff) << (i * 16);
          r |= (s & 0xffff) << (i * 16);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          if (shift > 31)
          if (shift > 31)
            s = 0;
            s = 0;
          else
          else
            s = ((wRWORD (BITS (16, 19), i) & 0xffffffff) << shift);
            s = ((wRWORD (BITS (16, 19), i) & 0xffffffff) << shift);
          r |= (s & 0xffffffff) << (i * 32);
          r |= (s & 0xffffffff) << (i * 32);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Dqual:
    case Dqual:
      if (shift > 63)
      if (shift > 63)
        r = 0;
        r = 0;
      else
      else
        r = ((wR[BITS (16, 19)] & 0xffffffffffffffffULL) << shift);
        r = ((wR[BITS (16, 19)] & 0xffffffffffffffffULL) << shift);
 
 
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WSRA (ARMul_State * state, ARMword instr)
WSRA (ARMul_State * state, ARMword instr)
{
{
  ARMdword     r = 0;
  ARMdword     r = 0;
  ARMdword     s;
  ARMdword     s;
  ARMword      psr = 0;
  ARMword      psr = 0;
  int          i;
  int          i;
  unsigned     shift;
  unsigned     shift;
  signed long  t;
  signed long  t;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wsra\n");
  fprintf (stderr, "wsra\n");
#endif  
#endif  
 
 
  DECODE_G_BIT (state, instr, shift);
  DECODE_G_BIT (state, instr, shift);
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Hqual:
    case Hqual:
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          if (shift > 15)
          if (shift > 15)
            t = (wRHALF (BITS (16, 19), i) & 0x8000) ? 0xffff : 0;
            t = (wRHALF (BITS (16, 19), i) & 0x8000) ? 0xffff : 0;
          else
          else
            {
            {
              t = wRHALF (BITS (16, 19), i);
              t = wRHALF (BITS (16, 19), i);
              t = EXTEND16 (t);
              t = EXTEND16 (t);
              t >>= shift;
              t >>= shift;
            }
            }
 
 
          s = t;
          s = t;
          r |= (s & 0xffff) << (i * 16);
          r |= (s & 0xffff) << (i * 16);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          if (shift > 31)
          if (shift > 31)
            t = (wRWORD (BITS (16, 19), i) & 0x80000000) ? 0xffffffff : 0;
            t = (wRWORD (BITS (16, 19), i) & 0x80000000) ? 0xffffffff : 0;
          else
          else
            {
            {
              t = wRWORD (BITS (16, 19), i);
              t = wRWORD (BITS (16, 19), i);
              t >>= shift;
              t >>= shift;
            }
            }
          s = t;
          s = t;
          r |= (s & 0xffffffff) << (i * 32);
          r |= (s & 0xffffffff) << (i * 32);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Dqual:
    case Dqual:
      if (shift > 63)
      if (shift > 63)
        r = (wR [BITS (16, 19)] & 0x8000000000000000ULL) ? 0xffffffffffffffffULL : 0;
        r = (wR [BITS (16, 19)] & 0x8000000000000000ULL) ? 0xffffffffffffffffULL : 0;
      else
      else
        r = ((signed long long) (wR[BITS (16, 19)] & 0xffffffffffffffffULL) >> shift);
        r = ((signed long long) (wR[BITS (16, 19)] & 0xffffffffffffffffULL) >> shift);
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WSRL (ARMul_State * state, ARMword instr)
WSRL (ARMul_State * state, ARMword instr)
{
{
  ARMdword     r = 0;
  ARMdword     r = 0;
  ARMdword     s;
  ARMdword     s;
  ARMword      psr = 0;
  ARMword      psr = 0;
  int          i;
  int          i;
  unsigned int shift;
  unsigned int shift;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wsrl\n");
  fprintf (stderr, "wsrl\n");
#endif
#endif
 
 
  DECODE_G_BIT (state, instr, shift);
  DECODE_G_BIT (state, instr, shift);
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Hqual:
    case Hqual:
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          if (shift > 15)
          if (shift > 15)
            s = 0;
            s = 0;
          else
          else
            s = ((unsigned) (wRHALF (BITS (16, 19), i) & 0xffff) >> shift);
            s = ((unsigned) (wRHALF (BITS (16, 19), i) & 0xffff) >> shift);
 
 
          r |= (s & 0xffff) << (i * 16);
          r |= (s & 0xffff) << (i * 16);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          if (shift > 31)
          if (shift > 31)
            s = 0;
            s = 0;
          else
          else
            s = ((unsigned long) (wRWORD (BITS (16, 19), i) & 0xffffffff) >> shift);
            s = ((unsigned long) (wRWORD (BITS (16, 19), i) & 0xffffffff) >> shift);
 
 
          r |= (s & 0xffffffff) << (i * 32);
          r |= (s & 0xffffffff) << (i * 32);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Dqual:
    case Dqual:
      if (shift > 63)
      if (shift > 63)
        r = 0;
        r = 0;
      else
      else
        r = (wR [BITS (16, 19)] & 0xffffffffffffffffULL) >> shift;
        r = (wR [BITS (16, 19)] & 0xffffffffffffffffULL) >> shift;
 
 
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WSTR (ARMul_State * state, ARMword instr)
WSTR (ARMul_State * state, ARMword instr)
{
{
  ARMword address;
  ARMword address;
  int failed;
  int failed;
 
 
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wstr\n");
  fprintf (stderr, "wstr\n");
#endif
#endif
 
 
  address = Compute_Iwmmxt_Address (state, instr, & failed);
  address = Compute_Iwmmxt_Address (state, instr, & failed);
  if (failed)
  if (failed)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
  if (BITS (28, 31) == 0xf)
  if (BITS (28, 31) == 0xf)
    {
    {
      /* WSTRW wCx */
      /* WSTRW wCx */
      Iwmmxt_Store_Word (state, address, wC [BITS (12, 15)]);
      Iwmmxt_Store_Word (state, address, wC [BITS (12, 15)]);
    }
    }
  else if (BIT (8) == 0)
  else if (BIT (8) == 0)
    {
    {
      if (BIT (22) == 0)
      if (BIT (22) == 0)
        /* WSTRB */
        /* WSTRB */
        Iwmmxt_Store_Byte (state, address, wR [BITS (12, 15)]);
        Iwmmxt_Store_Byte (state, address, wR [BITS (12, 15)]);
      else
      else
        /* WSTRH */
        /* WSTRH */
        Iwmmxt_Store_Half_Word (state, address, wR [BITS (12, 15)]);
        Iwmmxt_Store_Half_Word (state, address, wR [BITS (12, 15)]);
    }
    }
  else
  else
    {
    {
      if (BIT (22) == 0)
      if (BIT (22) == 0)
        /* WSTRW wRd */
        /* WSTRW wRd */
        Iwmmxt_Store_Word (state, address, wR [BITS (12, 15)]);
        Iwmmxt_Store_Word (state, address, wR [BITS (12, 15)]);
      else
      else
        /* WSTRD */
        /* WSTRD */
        Iwmmxt_Store_Double_Word (state, address, wR [BITS (12, 15)]);
        Iwmmxt_Store_Double_Word (state, address, wR [BITS (12, 15)]);
    }
    }
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WSUB (ARMul_State * state, ARMword instr)
WSUB (ARMul_State * state, ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMword  psr = 0;
  ARMword  psr = 0;
  ARMdword x;
  ARMdword x;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
  int      carry;
  int      carry;
  int      overflow;
  int      overflow;
  int      satrv[8];
  int      satrv[8];
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wsub\n");
  fprintf (stderr, "wsub\n");
#endif  
#endif  
 
 
/* Subtract two numbers using the specified function,
/* Subtract two numbers using the specified function,
   leaving setting the carry bit as required.  */
   leaving setting the carry bit as required.  */
#define SUBx(x, y, m, f) \
#define SUBx(x, y, m, f) \
   (*f) (wRBITS (BITS (16, 19), (x), (y)) & (m), \
   (*f) (wRBITS (BITS (16, 19), (x), (y)) & (m), \
         wRBITS (BITS ( 0,  3), (x), (y)) & (m), & carry, & overflow)
         wRBITS (BITS ( 0,  3), (x), (y)) & (m), & carry, & overflow)
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      for (i = 0; i < 8; i++)
      for (i = 0; i < 8; i++)
        {
        {
          switch (BITS (20, 21))
          switch (BITS (20, 21))
            {
            {
            case NoSaturation:
            case NoSaturation:
              s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubS8);
              s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubS8);
              satrv [BITIDX8 (i)] = 0;
              satrv [BITIDX8 (i)] = 0;
              r |= (s & 0xff) << (i * 8);
              r |= (s & 0xff) << (i * 8);
              SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
              SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
              SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
              SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
              SIMD8_SET (psr, carry, SIMD_CBIT, i);
              SIMD8_SET (psr, carry, SIMD_CBIT, i);
              SIMD8_SET (psr, overflow, SIMD_VBIT, i);
              SIMD8_SET (psr, overflow, SIMD_VBIT, i);
              break;
              break;
 
 
            case UnsignedSaturation:
            case UnsignedSaturation:
              s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubU8);
              s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubU8);
              x = IwmmxtSaturateU8 (s, satrv + BITIDX8 (i));
              x = IwmmxtSaturateU8 (s, satrv + BITIDX8 (i));
              r |= (x & 0xff) << (i * 8);
              r |= (x & 0xff) << (i * 8);
              SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
              SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
              SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
              SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX8 (i)])
              if (! satrv [BITIDX8 (i)])
                {
                {
                  SIMD8_SET (psr, carry,     SIMD_CBIT, i);
                  SIMD8_SET (psr, carry,     SIMD_CBIT, i);
                  SIMD8_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD8_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            case SignedSaturation:
            case SignedSaturation:
              s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubS8);
              s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubS8);
              x = IwmmxtSaturateS8 (s, satrv + BITIDX8 (i));
              x = IwmmxtSaturateS8 (s, satrv + BITIDX8 (i));
              r |= (x & 0xff) << (i * 8);
              r |= (x & 0xff) << (i * 8);
              SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
              SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
              SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
              SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX8 (i)])
              if (! satrv [BITIDX8 (i)])
                {
                {
                  SIMD8_SET (psr, carry,     SIMD_CBIT, i);
                  SIMD8_SET (psr, carry,     SIMD_CBIT, i);
                  SIMD8_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD8_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            default:
            default:
              ARMul_UndefInstr (state, instr);
              ARMul_UndefInstr (state, instr);
              return ARMul_DONE;
              return ARMul_DONE;
            }
            }
        }
        }
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
      satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
 
 
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          switch (BITS (20, 21))
          switch (BITS (20, 21))
            {
            {
            case NoSaturation:
            case NoSaturation:
              s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubU16);
              s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubU16);
              satrv [BITIDX16 (i)] = 0;
              satrv [BITIDX16 (i)] = 0;
              r |= (s & 0xffff) << (i * 16);
              r |= (s & 0xffff) << (i * 16);
              SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
              SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
              SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
              SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
              SIMD16_SET (psr, carry,      SIMD_CBIT, i);
              SIMD16_SET (psr, carry,      SIMD_CBIT, i);
              SIMD16_SET (psr, overflow,   SIMD_VBIT, i);
              SIMD16_SET (psr, overflow,   SIMD_VBIT, i);
              break;
              break;
 
 
            case UnsignedSaturation:
            case UnsignedSaturation:
              s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubU16);
              s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubU16);
              x = IwmmxtSaturateU16 (s, satrv + BITIDX16 (i));
              x = IwmmxtSaturateU16 (s, satrv + BITIDX16 (i));
              r |= (x & 0xffff) << (i * 16);
              r |= (x & 0xffff) << (i * 16);
              SIMD16_SET (psr, NBIT16 (x & 0xffff), SIMD_NBIT, i);
              SIMD16_SET (psr, NBIT16 (x & 0xffff), SIMD_NBIT, i);
              SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
              SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX16 (i)])
              if (! satrv [BITIDX16 (i)])
                {
                {
                  SIMD16_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD16_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD16_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD16_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            case SignedSaturation:
            case SignedSaturation:
              s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubS16);
              s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubS16);
              x = IwmmxtSaturateS16 (s, satrv + BITIDX16 (i));
              x = IwmmxtSaturateS16 (s, satrv + BITIDX16 (i));
              r |= (x & 0xffff) << (i * 16);
              r |= (x & 0xffff) << (i * 16);
              SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
              SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
              SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
              SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX16 (i)])
              if (! satrv [BITIDX16 (i)])
                {
                {
                  SIMD16_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD16_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD16_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD16_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            default:
            default:
              ARMul_UndefInstr (state, instr);
              ARMul_UndefInstr (state, instr);
              return ARMul_DONE;
              return ARMul_DONE;
            }
            }
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
      satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
 
 
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          switch (BITS (20, 21))
          switch (BITS (20, 21))
            {
            {
            case NoSaturation:
            case NoSaturation:
              s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubU32);
              s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubU32);
              satrv[BITIDX32 (i)] = 0;
              satrv[BITIDX32 (i)] = 0;
              r |= (s & 0xffffffff) << (i * 32);
              r |= (s & 0xffffffff) << (i * 32);
              SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
              SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
              SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
              SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
              SIMD32_SET (psr, carry,      SIMD_CBIT, i);
              SIMD32_SET (psr, carry,      SIMD_CBIT, i);
              SIMD32_SET (psr, overflow,   SIMD_VBIT, i);
              SIMD32_SET (psr, overflow,   SIMD_VBIT, i);
              break;
              break;
 
 
            case UnsignedSaturation:
            case UnsignedSaturation:
              s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubU32);
              s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubU32);
              x = IwmmxtSaturateU32 (s, satrv + BITIDX32 (i));
              x = IwmmxtSaturateU32 (s, satrv + BITIDX32 (i));
              r |= (x & 0xffffffff) << (i * 32);
              r |= (x & 0xffffffff) << (i * 32);
              SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
              SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
              SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
              SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX32 (i)])
              if (! satrv [BITIDX32 (i)])
                {
                {
                  SIMD32_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD32_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD32_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD32_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            case SignedSaturation:
            case SignedSaturation:
              s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubS32);
              s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubS32);
              x = IwmmxtSaturateS32 (s, satrv + BITIDX32 (i));
              x = IwmmxtSaturateS32 (s, satrv + BITIDX32 (i));
              r |= (x & 0xffffffff) << (i * 32);
              r |= (x & 0xffffffff) << (i * 32);
              SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
              SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
              SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
              SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
              if (! satrv [BITIDX32 (i)])
              if (! satrv [BITIDX32 (i)])
                {
                {
                  SIMD32_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD32_SET (psr, carry,    SIMD_CBIT, i);
                  SIMD32_SET (psr, overflow, SIMD_VBIT, i);
                  SIMD32_SET (psr, overflow, SIMD_VBIT, i);
                }
                }
              break;
              break;
 
 
            default:
            default:
              ARMul_UndefInstr (state, instr);
              ARMul_UndefInstr (state, instr);
              return ARMul_DONE;
              return ARMul_DONE;
            }
            }
        }
        }
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  SET_wCSSFvec (satrv);
  SET_wCSSFvec (satrv);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
#undef SUBx
#undef SUBx
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WUNPCKEH (ARMul_State * state, ARMword instr)
WUNPCKEH (ARMul_State * state, ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMword  psr = 0;
  ARMword  psr = 0;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wunpckeh\n");
  fprintf (stderr, "wunpckeh\n");
#endif  
#endif  
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          s = wRBYTE (BITS (16, 19), i + 4);
          s = wRBYTE (BITS (16, 19), i + 4);
 
 
          if (BIT (21) && NBIT8 (s))
          if (BIT (21) && NBIT8 (s))
            s |= 0xff00;
            s |= 0xff00;
 
 
          r |= (s & 0xffff) << (i * 16);
          r |= (s & 0xffff) << (i * 16);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          s = wRHALF (BITS (16, 19), i + 2);
          s = wRHALF (BITS (16, 19), i + 2);
 
 
          if (BIT (21) && NBIT16 (s))
          if (BIT (21) && NBIT16 (s))
            s |= 0xffff0000;
            s |= 0xffff0000;
 
 
          r |= (s & 0xffffffff) << (i * 32);
          r |= (s & 0xffffffff) << (i * 32);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      r = wRWORD (BITS (16, 19), 1);
      r = wRWORD (BITS (16, 19), 1);
 
 
      if (BIT (21) && NBIT32 (r))
      if (BIT (21) && NBIT32 (r))
        r |= 0xffffffff00000000ULL;
        r |= 0xffffffff00000000ULL;
 
 
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WUNPCKEL (ARMul_State * state, ARMword instr)
WUNPCKEL (ARMul_State * state, ARMword instr)
{
{
  ARMdword r = 0;
  ARMdword r = 0;
  ARMword  psr = 0;
  ARMword  psr = 0;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wunpckel\n");
  fprintf (stderr, "wunpckel\n");
#endif  
#endif  
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          s = wRBYTE (BITS (16, 19), i);
          s = wRBYTE (BITS (16, 19), i);
 
 
          if (BIT (21) && NBIT8 (s))
          if (BIT (21) && NBIT8 (s))
            s |= 0xff00;
            s |= 0xff00;
 
 
          r |= (s & 0xffff) << (i * 16);
          r |= (s & 0xffff) << (i * 16);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
          SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          s = wRHALF (BITS (16, 19), i);
          s = wRHALF (BITS (16, 19), i);
 
 
          if (BIT (21) && NBIT16 (s))
          if (BIT (21) && NBIT16 (s))
            s |= 0xffff0000;
            s |= 0xffff0000;
 
 
          r |= (s & 0xffffffff) << (i * 32);
          r |= (s & 0xffffffff) << (i * 32);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
          SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      r = wRWORD (BITS (16, 19), 0);
      r = wRWORD (BITS (16, 19), 0);
 
 
      if (BIT (21) && NBIT32 (r))
      if (BIT (21) && NBIT32 (r))
        r |= 0xffffffff00000000ULL;
        r |= 0xffffffff00000000ULL;
 
 
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WUNPCKIH (ARMul_State * state, ARMword instr)
WUNPCKIH (ARMul_State * state, ARMword instr)
{
{
  ARMword  a, b;
  ARMword  a, b;
  ARMdword r = 0;
  ARMdword r = 0;
  ARMword  psr = 0;
  ARMword  psr = 0;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wunpckih\n");
  fprintf (stderr, "wunpckih\n");
#endif  
#endif  
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          a = wRBYTE (BITS (16, 19), i + 4);
          a = wRBYTE (BITS (16, 19), i + 4);
          b = wRBYTE (BITS ( 0,  3), i + 4);
          b = wRBYTE (BITS ( 0,  3), i + 4);
          s = a | (b << 8);
          s = a | (b << 8);
          r |= (s & 0xffff) << (i * 16);
          r |= (s & 0xffff) << (i * 16);
          SIMD8_SET (psr, NBIT8 (a), SIMD_NBIT, i * 2);
          SIMD8_SET (psr, NBIT8 (a), SIMD_NBIT, i * 2);
          SIMD8_SET (psr, ZBIT8 (a), SIMD_ZBIT, i * 2);
          SIMD8_SET (psr, ZBIT8 (a), SIMD_ZBIT, i * 2);
          SIMD8_SET (psr, NBIT8 (b), SIMD_NBIT, (i * 2) + 1);
          SIMD8_SET (psr, NBIT8 (b), SIMD_NBIT, (i * 2) + 1);
          SIMD8_SET (psr, ZBIT8 (b), SIMD_ZBIT, (i * 2) + 1);
          SIMD8_SET (psr, ZBIT8 (b), SIMD_ZBIT, (i * 2) + 1);
        }
        }
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          a = wRHALF (BITS (16, 19), i + 2);
          a = wRHALF (BITS (16, 19), i + 2);
          b = wRHALF (BITS ( 0,  3), i + 2);
          b = wRHALF (BITS ( 0,  3), i + 2);
          s = a | (b << 16);
          s = a | (b << 16);
          r |= (s & 0xffffffff) << (i * 32);
          r |= (s & 0xffffffff) << (i * 32);
          SIMD16_SET (psr, NBIT16 (a), SIMD_NBIT, (i * 2));
          SIMD16_SET (psr, NBIT16 (a), SIMD_NBIT, (i * 2));
          SIMD16_SET (psr, ZBIT16 (a), SIMD_ZBIT, (i * 2));
          SIMD16_SET (psr, ZBIT16 (a), SIMD_ZBIT, (i * 2));
          SIMD16_SET (psr, NBIT16 (b), SIMD_NBIT, (i * 2) + 1);
          SIMD16_SET (psr, NBIT16 (b), SIMD_NBIT, (i * 2) + 1);
          SIMD16_SET (psr, ZBIT16 (b), SIMD_ZBIT, (i * 2) + 1);
          SIMD16_SET (psr, ZBIT16 (b), SIMD_ZBIT, (i * 2) + 1);
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      a = wRWORD (BITS (16, 19), 1);
      a = wRWORD (BITS (16, 19), 1);
      s = wRWORD (BITS ( 0,  3), 1);
      s = wRWORD (BITS ( 0,  3), 1);
      r = a | (s << 32);
      r = a | (s << 32);
 
 
      SIMD32_SET (psr, NBIT32 (a), SIMD_NBIT, 0);
      SIMD32_SET (psr, NBIT32 (a), SIMD_NBIT, 0);
      SIMD32_SET (psr, ZBIT32 (a), SIMD_ZBIT, 0);
      SIMD32_SET (psr, ZBIT32 (a), SIMD_ZBIT, 0);
      SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, 1);
      SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, 1);
      SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, 1);
      SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, 1);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WUNPCKIL (ARMul_State * state, ARMword instr)
WUNPCKIL (ARMul_State * state, ARMword instr)
{
{
  ARMword  a, b;
  ARMword  a, b;
  ARMdword r = 0;
  ARMdword r = 0;
  ARMword  psr = 0;
  ARMword  psr = 0;
  ARMdword s;
  ARMdword s;
  int      i;
  int      i;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wunpckil\n");
  fprintf (stderr, "wunpckil\n");
#endif  
#endif  
 
 
  switch (BITS (22, 23))
  switch (BITS (22, 23))
    {
    {
    case Bqual:
    case Bqual:
      for (i = 0; i < 4; i++)
      for (i = 0; i < 4; i++)
        {
        {
          a = wRBYTE (BITS (16, 19), i);
          a = wRBYTE (BITS (16, 19), i);
          b = wRBYTE (BITS ( 0,  3), i);
          b = wRBYTE (BITS ( 0,  3), i);
          s = a | (b << 8);
          s = a | (b << 8);
          r |= (s & 0xffff) << (i * 16);
          r |= (s & 0xffff) << (i * 16);
          SIMD8_SET (psr, NBIT8 (a), SIMD_NBIT, i * 2);
          SIMD8_SET (psr, NBIT8 (a), SIMD_NBIT, i * 2);
          SIMD8_SET (psr, ZBIT8 (a), SIMD_ZBIT, i * 2);
          SIMD8_SET (psr, ZBIT8 (a), SIMD_ZBIT, i * 2);
          SIMD8_SET (psr, NBIT8 (b), SIMD_NBIT, (i * 2) + 1);
          SIMD8_SET (psr, NBIT8 (b), SIMD_NBIT, (i * 2) + 1);
          SIMD8_SET (psr, ZBIT8 (b), SIMD_ZBIT, (i * 2) + 1);
          SIMD8_SET (psr, ZBIT8 (b), SIMD_ZBIT, (i * 2) + 1);
        }
        }
      break;
      break;
 
 
    case Hqual:
    case Hqual:
      for (i = 0; i < 2; i++)
      for (i = 0; i < 2; i++)
        {
        {
          a = wRHALF (BITS (16, 19), i);
          a = wRHALF (BITS (16, 19), i);
          b = wRHALF (BITS ( 0,  3), i);
          b = wRHALF (BITS ( 0,  3), i);
          s = a | (b << 16);
          s = a | (b << 16);
          r |= (s & 0xffffffff) << (i * 32);
          r |= (s & 0xffffffff) << (i * 32);
          SIMD16_SET (psr, NBIT16 (a), SIMD_NBIT, (i * 2));
          SIMD16_SET (psr, NBIT16 (a), SIMD_NBIT, (i * 2));
          SIMD16_SET (psr, ZBIT16 (a), SIMD_ZBIT, (i * 2));
          SIMD16_SET (psr, ZBIT16 (a), SIMD_ZBIT, (i * 2));
          SIMD16_SET (psr, NBIT16 (b), SIMD_NBIT, (i * 2) + 1);
          SIMD16_SET (psr, NBIT16 (b), SIMD_NBIT, (i * 2) + 1);
          SIMD16_SET (psr, ZBIT16 (b), SIMD_ZBIT, (i * 2) + 1);
          SIMD16_SET (psr, ZBIT16 (b), SIMD_ZBIT, (i * 2) + 1);
        }
        }
      break;
      break;
 
 
    case Wqual:
    case Wqual:
      a = wRWORD (BITS (16, 19), 0);
      a = wRWORD (BITS (16, 19), 0);
      s = wRWORD (BITS ( 0,  3), 0);
      s = wRWORD (BITS ( 0,  3), 0);
      r = a | (s << 32);
      r = a | (s << 32);
 
 
      SIMD32_SET (psr, NBIT32 (a), SIMD_NBIT, 0);
      SIMD32_SET (psr, NBIT32 (a), SIMD_NBIT, 0);
      SIMD32_SET (psr, ZBIT32 (a), SIMD_ZBIT, 0);
      SIMD32_SET (psr, ZBIT32 (a), SIMD_ZBIT, 0);
      SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, 1);
      SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, 1);
      SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, 1);
      SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, 1);
      break;
      break;
 
 
    default:
    default:
      ARMul_UndefInstr (state, instr);
      ARMul_UndefInstr (state, instr);
      return ARMul_DONE;
      return ARMul_DONE;
    }
    }
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wR [BITS (12, 15)] = r;
  wR [BITS (12, 15)] = r;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
static int
static int
WXOR (ARMword instr)
WXOR (ARMword instr)
{
{
  ARMword psr = 0;
  ARMword psr = 0;
  ARMdword result;
  ARMdword result;
 
 
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
    return ARMul_CANT;
    return ARMul_CANT;
 
 
#ifdef DEBUG
#ifdef DEBUG
  fprintf (stderr, "wxor\n");
  fprintf (stderr, "wxor\n");
#endif  
#endif  
 
 
  result = wR [BITS (16, 19)] ^ wR [BITS (0, 3)];
  result = wR [BITS (16, 19)] ^ wR [BITS (0, 3)];
  wR [BITS (12, 15)] = result;
  wR [BITS (12, 15)] = result;
 
 
  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
 
 
  wC [wCASF] = psr;
  wC [wCASF] = psr;
  wC [wCon] |= (WCON_CUP | WCON_MUP);
  wC [wCon] |= (WCON_CUP | WCON_MUP);
 
 
  return ARMul_DONE;
  return ARMul_DONE;
}
}
 
 
/* This switch table is moved to a seperate function in order
/* This switch table is moved to a seperate function in order
   to work around a compiler bug in the host compiler...  */
   to work around a compiler bug in the host compiler...  */
 
 
static int
static int
Process_Instruction (ARMul_State * state, ARMword instr)
Process_Instruction (ARMul_State * state, ARMword instr)
{
{
  int status = ARMul_BUSY;
  int status = ARMul_BUSY;
 
 
  switch ((BITS (20, 23) << 8) | BITS (4, 11))
  switch ((BITS (20, 23) << 8) | BITS (4, 11))
    {
    {
    case 0x000: status = WOR (instr); break;
    case 0x000: status = WOR (instr); break;
    case 0x011: status = TMCR (state, instr); break;
    case 0x011: status = TMCR (state, instr); break;
    case 0x100: status = WXOR (instr); break;
    case 0x100: status = WXOR (instr); break;
    case 0x111: status = TMRC (state, instr); break;
    case 0x111: status = TMRC (state, instr); break;
    case 0x300: status = WANDN (instr); break;
    case 0x300: status = WANDN (instr); break;
    case 0x200: status = WAND (instr); break;
    case 0x200: status = WAND (instr); break;
 
 
    case 0x810: case 0xa10:
    case 0x810: case 0xa10:
      status = WMADD (instr); break;
      status = WMADD (instr); break;
 
 
    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:
    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:
      status = WUNPCKIL (state, instr); break;
      status = WUNPCKIL (state, instr); break;
    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:
    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:
      status = WUNPCKIH (state, instr); break;
      status = WUNPCKIH (state, instr); break;
    case 0x012: case 0x112: case 0x412: case 0x512:
    case 0x012: case 0x112: case 0x412: case 0x512:
      status = WSAD (instr); break;
      status = WSAD (instr); break;
    case 0x010: case 0x110: case 0x210: case 0x310:
    case 0x010: case 0x110: case 0x210: case 0x310:
      status = WMUL (instr); break;
      status = WMUL (instr); break;
    case 0x410: case 0x510: case 0x610: case 0x710:
    case 0x410: case 0x510: case 0x610: case 0x710:
      status = WMAC (instr); break;
      status = WMAC (instr); break;
    case 0x006: case 0x406: case 0x806: case 0xc06:
    case 0x006: case 0x406: case 0x806: case 0xc06:
      status = WCMPEQ (state, instr); break;
      status = WCMPEQ (state, instr); break;
    case 0x800: case 0x900: case 0xc00: case 0xd00:
    case 0x800: case 0x900: case 0xc00: case 0xd00:
      status = WAVG2 (instr); break;
      status = WAVG2 (instr); break;
    case 0x802: case 0x902: case 0xa02: case 0xb02:
    case 0x802: case 0x902: case 0xa02: case 0xb02:
      status = WALIGNR (state, instr); break;
      status = WALIGNR (state, instr); break;
    case 0x601: case 0x605: case 0x609: case 0x60d:
    case 0x601: case 0x605: case 0x609: case 0x60d:
      status = TINSR (state, instr); break;
      status = TINSR (state, instr); break;
    case 0x107: case 0x507: case 0x907: case 0xd07:
    case 0x107: case 0x507: case 0x907: case 0xd07:
      status = TEXTRM (state, instr); break;
      status = TEXTRM (state, instr); break;
    case 0x117: case 0x517: case 0x917: case 0xd17:
    case 0x117: case 0x517: case 0x917: case 0xd17:
      status = TEXTRC (state, instr); break;
      status = TEXTRC (state, instr); break;
    case 0x401: case 0x405: case 0x409: case 0x40d:
    case 0x401: case 0x405: case 0x409: case 0x40d:
      status = TBCST (state, instr); break;
      status = TBCST (state, instr); break;
    case 0x113: case 0x513: case 0x913: case 0xd13:
    case 0x113: case 0x513: case 0x913: case 0xd13:
      status = TANDC (state, instr); break;
      status = TANDC (state, instr); break;
    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:
    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:
      status = WACC (state, instr); break;
      status = WACC (state, instr); break;
    case 0x115: case 0x515: case 0x915: case 0xd15:
    case 0x115: case 0x515: case 0x915: case 0xd15:
      status = TORC (state, instr); break;
      status = TORC (state, instr); break;
    case 0x103: case 0x503: case 0x903: case 0xd03:
    case 0x103: case 0x503: case 0x903: case 0xd03:
      status = TMOVMSK (state, instr); break;
      status = TMOVMSK (state, instr); break;
    case 0x106: case 0x306: case 0x506: case 0x706:
    case 0x106: case 0x306: case 0x506: case 0x706:
    case 0x906: case 0xb06: case 0xd06: case 0xf06:
    case 0x906: case 0xb06: case 0xd06: case 0xf06:
      status = WCMPGT (state, instr); break;
      status = WCMPGT (state, instr); break;
    case 0x00e: case 0x20e: case 0x40e: case 0x60e:
    case 0x00e: case 0x20e: case 0x40e: case 0x60e:
    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
      status = WUNPCKEL (state, instr); break;
      status = WUNPCKEL (state, instr); break;
    case 0x00c: case 0x20c: case 0x40c: case 0x60c:
    case 0x00c: case 0x20c: case 0x40c: case 0x60c:
    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
      status = WUNPCKEH (state, instr); break;
      status = WUNPCKEH (state, instr); break;
    case 0x204: case 0x604: case 0xa04: case 0xe04:
    case 0x204: case 0x604: case 0xa04: case 0xe04:
    case 0x214: case 0x614: case 0xa14: case 0xe14:
    case 0x214: case 0x614: case 0xa14: case 0xe14:
      status = WSRL (state, instr); break;
      status = WSRL (state, instr); break;
    case 0x004: case 0x404: case 0x804: case 0xc04:
    case 0x004: case 0x404: case 0x804: case 0xc04:
    case 0x014: case 0x414: case 0x814: case 0xc14:
    case 0x014: case 0x414: case 0x814: case 0xc14:
      status = WSRA (state, instr); break;
      status = WSRA (state, instr); break;
    case 0x104: case 0x504: case 0x904: case 0xd04:
    case 0x104: case 0x504: case 0x904: case 0xd04:
    case 0x114: case 0x514: case 0x914: case 0xd14:
    case 0x114: case 0x514: case 0x914: case 0xd14:
      status = WSLL (state, instr); break;
      status = WSLL (state, instr); break;
    case 0x304: case 0x704: case 0xb04: case 0xf04:
    case 0x304: case 0x704: case 0xb04: case 0xf04:
    case 0x314: case 0x714: case 0xb14: case 0xf14:
    case 0x314: case 0x714: case 0xb14: case 0xf14:
      status = WROR (state, instr); break;
      status = WROR (state, instr); break;
    case 0x116: case 0x316: case 0x516: case 0x716:
    case 0x116: case 0x316: case 0x516: case 0x716:
    case 0x916: case 0xb16: case 0xd16: case 0xf16:
    case 0x916: case 0xb16: case 0xd16: case 0xf16:
      status = WMIN (state, instr); break;
      status = WMIN (state, instr); break;
    case 0x016: case 0x216: case 0x416: case 0x616:
    case 0x016: case 0x216: case 0x416: case 0x616:
    case 0x816: case 0xa16: case 0xc16: case 0xe16:
    case 0x816: case 0xa16: case 0xc16: case 0xe16:
      status = WMAX (state, instr); break;
      status = WMAX (state, instr); break;
    case 0x002: case 0x102: case 0x202: case 0x302:
    case 0x002: case 0x102: case 0x202: case 0x302:
    case 0x402: case 0x502: case 0x602: case 0x702:
    case 0x402: case 0x502: case 0x602: case 0x702:
      status = WALIGNI (instr); break;
      status = WALIGNI (instr); break;
    case 0x01a: case 0x11a: case 0x21a: case 0x31a:
    case 0x01a: case 0x11a: case 0x21a: case 0x31a:
    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
      status = WSUB (state, instr); break;
      status = WSUB (state, instr); break;
    case 0x01e: case 0x11e: case 0x21e: case 0x31e:
    case 0x01e: case 0x11e: case 0x21e: case 0x31e:
    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
      status = WSHUFH (instr); break;
      status = WSHUFH (instr); break;
    case 0x018: case 0x118: case 0x218: case 0x318:
    case 0x018: case 0x118: case 0x218: case 0x318:
    case 0x418: case 0x518: case 0x618: case 0x718:
    case 0x418: case 0x518: case 0x618: case 0x718:
    case 0x818: case 0x918: case 0xa18: case 0xb18:
    case 0x818: case 0x918: case 0xa18: case 0xb18:
    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
      status = WADD (state, instr); break;
      status = WADD (state, instr); break;
    case 0x008: case 0x108: case 0x208: case 0x308:
    case 0x008: case 0x108: case 0x208: case 0x308:
    case 0x408: case 0x508: case 0x608: case 0x708:
    case 0x408: case 0x508: case 0x608: case 0x708:
    case 0x808: case 0x908: case 0xa08: case 0xb08:
    case 0x808: case 0x908: case 0xa08: case 0xb08:
    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
      status = WPACK (state, instr); break;
      status = WPACK (state, instr); break;
    case 0x201: case 0x203: case 0x205: case 0x207:
    case 0x201: case 0x203: case 0x205: case 0x207:
    case 0x209: case 0x20b: case 0x20d: case 0x20f:
    case 0x209: case 0x20b: case 0x20d: case 0x20f:
    case 0x211: case 0x213: case 0x215: case 0x217:
    case 0x211: case 0x213: case 0x215: case 0x217:
    case 0x219: case 0x21b: case 0x21d: case 0x21f:
    case 0x219: case 0x21b: case 0x21d: case 0x21f:
      switch (BITS (16, 19))
      switch (BITS (16, 19))
        {
        {
        case 0x0: status = TMIA (state, instr); break;
        case 0x0: status = TMIA (state, instr); break;
        case 0x8: status = TMIAPH (state, instr); break;
        case 0x8: status = TMIAPH (state, instr); break;
        case 0xc:
        case 0xc:
        case 0xd:
        case 0xd:
        case 0xe:
        case 0xe:
        case 0xf: status = TMIAxy (state, instr); break;
        case 0xf: status = TMIAxy (state, instr); break;
        default: break;
        default: break;
        }
        }
      break;
      break;
    default:
    default:
      break;
      break;
    }
    }
  return status;
  return status;
}
}
 
 
/* Process a possibly Intel(r) Wireless MMX(tm) technology instruction.
/* Process a possibly Intel(r) Wireless MMX(tm) technology instruction.
   Return true if the instruction was handled.  */
   Return true if the instruction was handled.  */
 
 
int
int
ARMul_HandleIwmmxt (ARMul_State * state, ARMword instr)
ARMul_HandleIwmmxt (ARMul_State * state, ARMword instr)
{
{
  int status = ARMul_BUSY;
  int status = ARMul_BUSY;
 
 
  if (BITS (24, 27) == 0xe)
  if (BITS (24, 27) == 0xe)
    {
    {
      status = Process_Instruction (state, instr);
      status = Process_Instruction (state, instr);
    }
    }
  else if (BITS (25, 27) == 0x6)
  else if (BITS (25, 27) == 0x6)
    {
    {
      if (BITS (4, 11) == 0x0 && BITS (20, 24) == 0x4)
      if (BITS (4, 11) == 0x0 && BITS (20, 24) == 0x4)
        status = TMCRR (state, instr);
        status = TMCRR (state, instr);
      else if (BITS (9, 11) == 0x0)
      else if (BITS (9, 11) == 0x0)
        {
        {
          if (BIT (20) == 0x0)
          if (BIT (20) == 0x0)
            status = WSTR (state, instr);
            status = WSTR (state, instr);
          else if (BITS (20, 24) == 0x5)
          else if (BITS (20, 24) == 0x5)
            status = TMRRC (state, instr);
            status = TMRRC (state, instr);
          else
          else
            status = WLDR (state, instr);
            status = WLDR (state, instr);
        }
        }
    }
    }
 
 
  if (status == ARMul_CANT)
  if (status == ARMul_CANT)
    {
    {
      /* If the instruction was a recognised but illegal,
      /* If the instruction was a recognised but illegal,
         perform the abort here rather than returning false.
         perform the abort here rather than returning false.
         If we return false then ARMul_MRC may be called which
         If we return false then ARMul_MRC may be called which
         will still abort, but which also perform the register
         will still abort, but which also perform the register
         transfer...  */
         transfer...  */
      ARMul_Abort (state, ARMul_UndefinedInstrV);
      ARMul_Abort (state, ARMul_UndefinedInstrV);
      status = ARMul_DONE;
      status = ARMul_DONE;
    }
    }
 
 
  return status == ARMul_DONE;
  return status == ARMul_DONE;
}
}
 
 
int
int
Fetch_Iwmmxt_Register (unsigned int regnum, unsigned char * memory)
Fetch_Iwmmxt_Register (unsigned int regnum, unsigned char * memory)
{
{
  if (regnum >= 16)
  if (regnum >= 16)
    {
    {
      memcpy (memory, wC + (regnum - 16), sizeof wC [0]);
      memcpy (memory, wC + (regnum - 16), sizeof wC [0]);
      return sizeof wC [0];
      return sizeof wC [0];
    }
    }
  else
  else
    {
    {
      memcpy (memory, wR + regnum, sizeof wR [0]);
      memcpy (memory, wR + regnum, sizeof wR [0]);
      return sizeof wR [0];
      return sizeof wR [0];
    }
    }
}
}
 
 
int
int
Store_Iwmmxt_Register (unsigned int regnum, unsigned char * memory)
Store_Iwmmxt_Register (unsigned int regnum, unsigned char * memory)
{
{
  if (regnum >= 16)
  if (regnum >= 16)
    {
    {
      memcpy (wC + (regnum - 16), memory, sizeof wC [0]);
      memcpy (wC + (regnum - 16), memory, sizeof wC [0]);
      return sizeof wC [0];
      return sizeof wC [0];
    }
    }
  else
  else
    {
    {
      memcpy (wR + regnum, memory, sizeof wR [0]);
      memcpy (wR + regnum, memory, sizeof wR [0]);
      return sizeof wR [0];
      return sizeof wR [0];
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

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