OSDN Git Service

Add iWMMXt support
authorNick Clifton <nickc@redhat.com>
Tue, 25 Mar 2003 20:56:01 +0000 (20:56 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 25 Mar 2003 20:56:01 +0000 (20:56 +0000)
17 files changed:
bfd/ChangeLog
bfd/archures.c
bfd/bfd-in2.h
bfd/coff-arm.c
bfd/coffcode.h
bfd/coffgen.c
bfd/cpu-arm.c
bfd/elf32-arm.h
bfd/libbfd.h
bfd/reloc.c
include/coff/ChangeLog
include/coff/arm.h
include/elf/ChangeLog
include/elf/arm.h
opcodes/ChangeLog
opcodes/arm-dis.c
opcodes/arm-opc.h

index e0f41fd..a29b48a 100644 (file)
@@ -1,3 +1,26 @@
+2003-03-25  Stan Cox   <scox@redhat.com>
+           Nick Clifton  <nickc@redhat.com>
+           
+       Contribute support for Intel's iWMMXt chip - an ARM variant:
+
+       * archures.c: Add bfd_mach_arm_iWMMXt.
+       * reloc.c: Add BFD_RELOC_ARM_CP_OFF_IMM_S2.
+       * bfd-in2.h: Regenerate.
+       * libbfd.h: Regenerate.
+       * coff-arm.c (coff_arm_merge_private_bfd_data): Allow iWMMXt
+       object files to be linked with XScale ones.
+       (coff_arm_final_link_postscript): Update note section.
+       * coffcode.h (coff_set_arch_mach_hook): Handle note section.
+       * coffgen.c (coff_real_object_p): Call bfd_coff_set_arch_mach_hook
+       after identifying a coff binary.
+       * cpu-arm.c (processors): Add iWMMXt.
+       (arch_inf): Likewise.
+       * elf32-arm.h (arm_object_p): Handle note section.
+       (elf32_arm_merge_private_bfd_data):  Allow iWMMXt object files to
+       be linked with XScale ones.
+       (elf32_arm_section_flags): New function: Set flags on note section.
+       (elf32_arm_final_write_processing): Handle note section.
+
 2003-03-21  DJ Delorie  <dj@redhat.com>
 
        * elf32-xstormy16.c (elf32_xstormy16_relocate_section): Call
index 62edda1..18ebb83 100644 (file)
@@ -235,6 +235,7 @@ DESCRIPTION
 .#define bfd_mach_arm_5TE      9
 .#define bfd_mach_arm_XScale   10
 .#define bfd_mach_arm_ep9312   11
+.#define bfd_mach_arm_iWMMXt   12
 .  bfd_arch_ns32k,     {* National Semiconductors ns32000 *}
 .  bfd_arch_w65,       {* WDC 65816 *}
 .  bfd_arch_tic30,     {* Texas Instruments TMS320C30 *}
index 2385c40..8960f66 100644 (file)
@@ -1691,6 +1691,7 @@ enum bfd_architecture
 #define bfd_mach_arm_5TE       9
 #define bfd_mach_arm_XScale    10
 #define bfd_mach_arm_ep9312    11
+#define bfd_mach_arm_iWMMXt    12
   bfd_arch_ns32k,     /* National Semiconductors ns32000 */
   bfd_arch_w65,       /* WDC 65816 */
   bfd_arch_tic30,     /* Texas Instruments TMS320C30 */
@@ -2563,6 +2564,7 @@ field in the instruction.  */
   BFD_RELOC_ARM_SWI,
   BFD_RELOC_ARM_MULTI,
   BFD_RELOC_ARM_CP_OFF_IMM,
+  BFD_RELOC_ARM_CP_OFF_IMM_S2,
   BFD_RELOC_ARM_ADR_IMM,
   BFD_RELOC_ARM_LDR_IMM,
   BFD_RELOC_ARM_LITERAL,
index 2fadcbe..2401504 100644 (file)
@@ -2240,6 +2240,25 @@ coff_arm_merge_private_bfd_data (ibfd, obfd)
   if (ibfd == obfd)
     return TRUE;
 
+  if (bfd_get_mach (obfd) && bfd_get_mach (obfd) != bfd_get_mach (ibfd))
+    {
+      /* For now, allow an output file type of 'xscale' if the
+        input file type is 'iWMMXt'.  This means that we will
+        not have to build an entire iWMMXt enabled set of libraries
+        just to test a iWMMXt enabled binary.  Change the output
+        type to iWMMXt though.  Similarly allow 'xscale' binaries
+         to be linked into a 'iWMMXt' output binary.  */
+      if (   bfd_get_mach (obfd) == bfd_mach_arm_XScale
+         && bfd_get_mach (ibfd) == bfd_mach_arm_iWMMXt)
+       bfd_set_arch_mach (obfd, bfd_get_arch (obfd), bfd_mach_arm_iWMMXt);
+      else if (   bfd_get_mach (ibfd) != bfd_mach_arm_XScale
+              || bfd_get_mach (obfd) != bfd_mach_arm_iWMMXt)
+       {
+         bfd_set_error (bfd_error_wrong_format);
+         return FALSE;
+       }
+    }
+
   /* If the two formats are different we cannot merge anything.
      This is not an error, since it is permissable to change the
      input and output formats.  */
@@ -2584,6 +2603,44 @@ coff_arm_final_link_postscript (abfd, pfinfo)
       globals->bfd_of_glue_owner->output_has_begun = TRUE;
     }
 
+  {
+    asection * arm_arch_section;
+
+    /* Look for a .note section.  If one is present check
+       the machine number encoded in it, and set it to the current
+       machine number if it is different.  This allows XScale and
+       iWMMXt binaries to be merged and the resulting output to be set
+       to iWMMXt, even if the first input file had an XScale .note.  */
+
+    arm_arch_section = bfd_get_section_by_name (abfd, ".note");
+
+    if (arm_arch_section != NULL)
+      {
+       char buffer [4];
+
+       if (bfd_get_section_contents (abfd, arm_arch_section, buffer,
+                                       (file_ptr) 0, sizeof buffer))
+         {
+           unsigned long arm_mach;
+
+           /* We have to extract the value this way to allow for a
+              host whose endian-ness is different from the target.  */
+           arm_mach = bfd_get_32 (abfd, buffer);
+  
+           if (arm_mach != bfd_get_mach (abfd))
+             {
+               bfd_put_32 (abfd, bfd_get_mach (abfd), buffer);
+
+               if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
+                                               (file_ptr) 0, sizeof buffer))
+                 (*_bfd_error_handler)
+                   (_("warning: unable to update contents of .note section in %s"),
+                    bfd_get_filename (abfd));
+             }
+         }
+      }
+  }
+
   return TRUE;
 }
 
index ee50a10..da8121f 100644 (file)
@@ -1899,6 +1899,27 @@ coff_set_arch_mach_hook (abfd, filehdr)
             currently the XScale.  */
         case F_ARM_5:  machine = bfd_mach_arm_XScale;  break;
        }
+
+      {
+       asection * arm_arch_section;
+  
+       arm_arch_section = bfd_get_section_by_name (abfd, ".note");
+
+       if (arm_arch_section)
+         {
+           bfd_byte buffer [4];
+
+           if (! bfd_get_section_contents (abfd, arm_arch_section, buffer,
+                                           (file_ptr) 0, sizeof buffer))
+             (*_bfd_error_handler)
+               (_("%s: warning: unable to retrieve .note section from %s"),
+                bfd_get_filename (abfd));
+             
+           /* We have to extract the value this way to allow for a
+              host whose endian-ness is different from the target.  */
+           machine = bfd_get_32 (abfd, buffer);
+         }
+      }
       break;
 #endif
 #ifdef MC68MAGIC
index c905ab1..a3e3eec 100644 (file)
@@ -226,7 +226,7 @@ coff_real_object_p (abfd, nscns, internal_f, internal_a)
   if (! bfd_coff_set_arch_mach_hook (abfd, (PTR) internal_f))
     goto fail;
 
-  /* Now copy data as required; construct all asections etc */
+  /* Now copy data as required; construct all asections etc */
   if (nscns != 0)
     {
       unsigned int i;
@@ -241,6 +241,7 @@ coff_real_object_p (abfd, nscns, internal_f, internal_a)
        }
     }
 
+  bfd_coff_set_arch_mach_hook (abfd, (PTR) internal_f);
   /*  make_abs_section (abfd); */
 
   return abfd->xvec;
index 923c250..eb3011d 100644 (file)
@@ -96,7 +96,8 @@ processors[] =
   { bfd_mach_arm_4,  "strongarm110" },
   { bfd_mach_arm_4,  "strongarm1100" },
   { bfd_mach_arm_XScale, "xscale" },
-  { bfd_mach_arm_ep9312, "ep9312" }
+  { bfd_mach_arm_ep9312, "ep9312" },
+  { bfd_mach_arm_iWMMXt, "iwmmxt" }
 };
 
 static bfd_boolean
@@ -142,7 +143,8 @@ static const bfd_arch_info_type arch_info_struct[] =
   N (bfd_mach_arm_5T,     "armv5t",  FALSE, & arch_info_struct[8]),
   N (bfd_mach_arm_5TE,    "armv5te", FALSE, & arch_info_struct[9]),
   N (bfd_mach_arm_XScale, "xscale",  FALSE, & arch_info_struct[10]),
-  N (bfd_mach_arm_ep9312, "ep9312",  FALSE, NULL)
+  N (bfd_mach_arm_ep9312, "ep9312",  FALSE, & arch_info_struct[11]),
+  N (bfd_mach_arm_iWMMXt,"iwmmxt",  FALSE, NULL)
 };
 
 const bfd_arch_info_type bfd_arm_arch =
index 509b481..417284b 100644 (file)
@@ -2119,10 +2119,43 @@ static bfd_boolean
 elf32_arm_object_p (abfd)
      bfd *abfd;
 {
-  /* XXX - we ought to examine a .note section here.  */
+  asection * arm_arch_section;
 
-  if (elf_elfheader (abfd)->e_flags & EF_ARM_MAVERICK_FLOAT)
-    bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_ep9312);
+  arm_arch_section = bfd_get_section_by_name (abfd, ARM_NOTE_SECTION);
+
+  if (arm_arch_section)
+    {
+      char          buffer [4];
+      unsigned long arm_mach;
+
+      if (! bfd_get_section_contents (abfd, arm_arch_section, buffer,
+                                     (file_ptr) 0, sizeof buffer))
+       (*_bfd_error_handler)
+         (_("%s: warning: unable to retrieve %s section from %s"),
+          ARM_NOTE_SECTION, bfd_get_filename (abfd));
+      else
+       {
+         /* We have to extract the value this way to allow for a
+            host whose endian-ness is different from the target.  */
+         arm_mach = bfd_get_32 (abfd, buffer);
+         bfd_default_set_arch_mach (abfd, bfd_arch_arm, arm_mach);
+
+         if (bfd_get_arch (abfd) == bfd_arch_arm)
+           return TRUE;
+      
+         /* If the set failed for some reason, do not leave the architecture
+            type as 0 (unknown), but issue a warning message and force it to
+            be set to bfd_arch_arm.  */
+         (*_bfd_error_handler)
+           (_("%s: warning: unrecognized ARM machine number: %x"),
+            bfd_get_filename (abfd), arm_mach);
+       }
+    }
+  else
+    {
+      if (elf_elfheader (abfd)->e_flags & EF_ARM_MAVERICK_FLOAT)
+       bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_ep9312);
+    }
 
   return TRUE;
 }
@@ -2263,6 +2296,25 @@ elf32_arm_merge_private_bfd_data (ibfd, obfd)
       return TRUE;
     }
 
+  if (bfd_get_mach (obfd) && bfd_get_mach (obfd) != bfd_get_mach (ibfd))
+    {
+      /* For now, allow an output file type of 'xscale' if the
+        input file type is 'iWMMXt'.  This means that we will
+        not have to build an entire iWMMXt enabled set of libraries
+        just to test a iWMMXt enabled binary.  Change the output
+        type to iWMMXt though.  Similarly allow 'xscale' binaries
+         to be linked into a 'iWMMXt' output binary.  */
+      if (   bfd_get_mach (obfd) == bfd_mach_arm_XScale
+         && bfd_get_mach (ibfd) == bfd_mach_arm_iWMMXt)
+       bfd_set_arch_mach (obfd, bfd_get_arch (obfd), bfd_mach_arm_iWMMXt);
+      else if (   bfd_get_mach (ibfd) != bfd_mach_arm_XScale
+              || bfd_get_mach (obfd) != bfd_mach_arm_iWMMXt)
+       {
+         bfd_set_error (bfd_error_wrong_format);
+         return FALSE;
+       }
+    }
+
   /* Identical flags must be compatible.  */
   if (in_flags == out_flags)
     return TRUE;
@@ -3660,6 +3712,65 @@ elf32_arm_reloc_type_class (rela)
     }
 }
 
+static bfd_boolean elf32_arm_section_flags           PARAMS ((flagword *, Elf_Internal_Shdr *));
+static void        elf32_arm_final_write_processing  PARAMS ((bfd *, bfd_boolean));
+
+/* Set the right machine number for an Arm ELF file.  */
+
+static bfd_boolean
+elf32_arm_section_flags (flags, hdr)
+     flagword *flags;
+     Elf_Internal_Shdr *hdr;
+{
+  if (hdr->sh_type == SHT_NOTE)
+    *flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_CONTENTS;
+
+  return TRUE;
+}
+
+void
+elf32_arm_final_write_processing (abfd, linker)
+     bfd *abfd;
+     bfd_boolean linker ATTRIBUTE_UNUSED;
+{
+  asection *    arm_arch_section;
+  char          buffer [4];
+  unsigned long arm_mach;
+
+  /* Look for a .note.arm.ident section.  If one is present check
+     the machine number encoded in it, and set it to the current
+     machine number if it is different.  This allows XScale and
+     iWMMXt binaries to be merged and the resulting output to be set
+     to iWMMXt, even if the first input file had an XScale .note.  */
+
+  arm_arch_section = bfd_get_section_by_name (abfd, ARM_NOTE_SECTION);
+
+  if (arm_arch_section == NULL)
+    return;
+
+  if (! bfd_get_section_contents (abfd, arm_arch_section, buffer,
+                               (file_ptr) 0, sizeof buffer))
+    /* If the ident section does not exist then just skip this check.  */
+    return;
+
+  /* We have to extract the value this way to allow for a
+     host whose endian-ness is different from the target.  */
+  arm_mach = bfd_get_32 (abfd, buffer);
+
+  if (arm_mach == bfd_get_mach (abfd))
+    return;
+
+  bfd_put_32 (abfd, bfd_get_mach (abfd), buffer);
+
+  if (! bfd_set_section_contents (abfd, arm_arch_section, buffer,
+                                 (file_ptr) 0, sizeof buffer))
+    (*_bfd_error_handler)
+      (_("warning: unable to update contents of %s section in %s"),
+       ARM_NOTE_SECTION, bfd_get_filename (abfd));
+
+  return;
+}
+
 #define ELF_ARCH                       bfd_arch_arm
 #define ELF_MACHINE_CODE               EM_ARM
 #define ELF_MAXPAGESIZE                        0x8000
@@ -3685,6 +3796,8 @@ elf32_arm_reloc_type_class (rela)
 #define elf_backend_post_process_headers       elf32_arm_post_process_headers
 #define elf_backend_reloc_type_class           elf32_arm_reloc_type_class
 #define elf_backend_object_p                   elf32_arm_object_p
+#define elf_backend_section_flags              elf32_arm_section_flags
+#define elf_backend_final_write_processing      elf32_arm_final_write_processing
 
 #define elf_backend_can_gc_sections 1
 #define elf_backend_plt_readonly    1
index 222b23d..df2ba3e 100644 (file)
@@ -1043,6 +1043,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_ARM_SWI",
   "BFD_RELOC_ARM_MULTI",
   "BFD_RELOC_ARM_CP_OFF_IMM",
+  "BFD_RELOC_ARM_CP_OFF_IMM_S2",
   "BFD_RELOC_ARM_ADR_IMM",
   "BFD_RELOC_ARM_LDR_IMM",
   "BFD_RELOC_ARM_LITERAL",
index 9f8a952..f4a3321 100644 (file)
@@ -2519,6 +2519,8 @@ ENUMX
 ENUMX
   BFD_RELOC_ARM_CP_OFF_IMM
 ENUMX
+  BFD_RELOC_ARM_CP_OFF_IMM_S2
+ENUMX
   BFD_RELOC_ARM_ADR_IMM
 ENUMX
   BFD_RELOC_ARM_LDR_IMM
index b2eec4c..be6154d 100644 (file)
@@ -1,3 +1,10 @@
+2003-03-25  Stan Cox   <scox@redhat.com>
+           Nick Clifton  <nickc@redhat.com>
+           
+       Contribute support for Intel's iWMMXt chip - an ARM variant:
+
+       * arm.h (ARM_NOTE_SECTION): Define.
+
 2002-11-30  Alan Modra  <amodra@bigpond.net.au>
 
        * ecoff.h: Replace boolean with bfd_boolean.
index bcfdcbe..8b90228 100644 (file)
@@ -124,3 +124,5 @@ struct external_reloc
 #define RELOC struct external_reloc
 #define RELSZ 14
 #endif
+
+#define ARM_NOTE_SECTION ".note"
index e87cdd2..5411f76 100644 (file)
@@ -1,4 +1,11 @@
-Mon Mar  3 20:35:58 2003  J"orn Rennecke <joern.rennecke@superh.com>
+2003-03-25  Stan Cox   <scox@redhat.com>
+           Nick Clifton  <nickc@redhat.com>
+           
+       Contribute support for Intel's iWMMXt chip - an ARM variant:
+
+       * arm.h (ARM_NOTE_SECTION): Define.
+
+2003-03-03  J"orn Rennecke <joern.rennecke@superh.com>
 
        * sh.h (EF_SH_MERGE_MACH): Make sure SH2E & SH3/SH3E merge to SH3E,
        and SH2E & SH4 merge to SH4, not SH2E.
index 5347017..3b3f8d0 100644 (file)
@@ -140,4 +140,7 @@ START_RELOC_NUMBERS (elf_arm_reloc_type)
   RELOC_NUMBER (R_ARM_RBASE,          255)
 END_RELOC_NUMBERS (R_ARM_max)
 
+/* The name of the note section used to identify arm variants.  */
+#define ARM_NOTE_SECTION ".note.arm.ident"
+     
 #endif /* _ELF_ARM_H */
index d316279..b133896 100644 (file)
@@ -1,3 +1,14 @@
+2003-03-25  Stan Cox   <scox@redhat.com>
+           Nick Clifton  <nickc@redhat.com>
+           
+       Contribute support for Intel's iWMMXt chip - an ARM variant:
+
+       * arm-dis.c (regnames): Add iWMMXt register names.
+       (set_iwmmxt_regnames): New function.
+       (print_insn_arm): Handle iWMMXt formatters.
+       * arm-opc.h: Document iWMMXt formatters.
+       (arm_opcod): Add iWMMXt instructions.
+
 2003-03-22  Doug Evans  <dje@sebabeach.org>
 
        * i386-dis.c (dis386): Recognize icebp (0xf1).
index 62a2a39..8fb9702 100644 (file)
@@ -1,24 +1,24 @@
 /* Instruction printing code for the ARM
-   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
    Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
    Modification by James G. Smith (jsmith@cygnus.co.uk)
 
-This file is part of libopcodes.
+   This file is part of libopcodes.
 
-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 the Free
-Software Foundation; either version 2 of the License, or (at your option)
-any later version.
+   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 the Free
+   Software Foundation; either version 2 of the License, or (at your option)
+   any later version.
 
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-more details.
+   This program is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+   more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "sysdep.h"
 #include "dis-asm.h"
@@ -70,7 +70,21 @@ static arm_regname regnames[] =
   { "atpcs", "Select register names used in the ATPCS",
     { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7",  "v8",  "IP",  "SP",  "LR",  "PC" }},
   { "special-atpcs", "Select special register names used in the ATPCS",
-    { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL",  "FP",  "IP",  "SP",  "LR",  "PC" }}
+    { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL",  "FP",  "IP",  "SP",  "LR",  "PC" }},
+  { "iwmmxt_regnames", "Select register names used on the Intel(r) Wireless MMX(tm) technology coprocessor",
+    { "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7", "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15"}},
+  { "iwmmxt_Cregnames", "Select control register names used on the Intel(r) Wireless MMX(tm) technology coprocessor",
+    {"wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved", "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved"}}
+};
+
+static char * iwmmxt_wwnames[] =
+{"b", "h", "w", "d"};
+
+static char * iwmmxt_wwssnames[] =
+{"b", "bus", "b", "bss",
+ "h", "hus", "h", "hss",
+ "w", "wus", "w", "wss",
+ "d", "dus", "d", "dss"
 };
 
 /* Default to GCC register name set.  */
@@ -98,11 +112,15 @@ static void parse_disassembler_options
   PARAMS ((char *));
 static int  print_insn
   PARAMS ((bfd_vma, struct disassemble_info *, bfd_boolean));
-int get_arm_regname_num_options (void);
-int set_arm_regname_option (int option);
-int get_arm_regnames (int option, const char **setname,
-                     const char **setdescription,
-                     const char ***register_names);
+static int set_iwmmxt_regnames
+  PARAMS ((void));
+
+int get_arm_regname_num_options
+  PARAMS ((void));
+int set_arm_regname_option
+  PARAMS ((int));
+int get_arm_regnames
+  PARAMS ((int, const char **, const char **, const char ***));
 \f
 /* Functions.  */
 int
@@ -167,6 +185,24 @@ arm_decode_shift (given, func, stream)
     }
 }
 
+static int
+set_iwmmxt_regnames ()
+{
+  const char * setname;
+  const char * setdesc;
+  const char ** regnames;
+  int iwmmxt_regnames = 0;
+  int num_regnames = get_arm_regname_num_options ();
+
+  get_arm_regnames (iwmmxt_regnames, &setname,
+                   &setdesc, &regnames);
+  while ((strcmp ("iwmmxt_regnames", setname))
+        && (iwmmxt_regnames < num_regnames))
+    get_arm_regnames (++iwmmxt_regnames, &setname, &setdesc, &regnames);
+
+  return iwmmxt_regnames;
+}
+                         
 /* Print one instruction from PC on INFO->STREAM.
    Return the size of the instruction (always 4 on ARM). */
 
@@ -179,9 +215,15 @@ print_insn_arm (pc, info, given)
   const struct arm_opcode *insn;
   void *stream = info->stream;
   fprintf_ftype func   = info->fprintf_func;
+  static int iwmmxt_regnames = 0;
 
   for (insn = arm_opcodes; insn->assembler; insn++)
     {
+      if (insn->value == FIRST_IWMMXT_INSN
+         && info->mach != bfd_mach_arm_XScale
+         && info->mach != bfd_mach_arm_iWMMXt)
+       insn = insn + IWMMXT_INSN_COUNT;
+
       if ((given & insn->mask) == insn->value)
        {
          char * c;
@@ -629,6 +671,63 @@ print_insn_arm (pc, info, given)
                                    func (stream, "f%d", reg);
                                }
                                break;
+
+                             case 'w':
+                               {
+                                 long reg;
+
+                                 if (bitstart != bitend)
+                                   {
+                                     reg = given >> bitstart;
+                                     reg &= (2 << (bitend - bitstart)) - 1;
+                                     if (bitend - bitstart == 1)
+                                       func (stream, "%s", iwmmxt_wwnames[reg]);
+                                     else
+                                       func (stream, "%s", iwmmxt_wwssnames[reg]);
+                                   }
+                                 else
+                                   {
+                                     reg = (((given >> 8)  & 0x1) |
+                                            ((given >> 22) & 0x1));
+                                     func (stream, "%s", iwmmxt_wwnames[reg]);
+                                   }
+                               }
+                               break;
+
+                             case 'g':
+                               {
+                                 long reg;
+                                 int current_regnames;
+
+                                 if (! iwmmxt_regnames)
+                                   iwmmxt_regnames = set_iwmmxt_regnames ();
+                                 current_regnames = set_arm_regname_option
+                                   (iwmmxt_regnames);
+
+                                 reg = given >> bitstart;
+                                 reg &= (2 << (bitend - bitstart)) - 1;
+                                 func (stream, "%s", arm_regnames[reg]);
+                                 set_arm_regname_option (current_regnames);
+                               }
+                               break;
+
+                             case 'G':
+                               {
+                                 long reg;
+                                 int current_regnames;
+
+                                 if (! iwmmxt_regnames)
+                                   iwmmxt_regnames = set_iwmmxt_regnames ();
+                                 current_regnames = set_arm_regname_option
+                                   (iwmmxt_regnames + 1);
+
+                                 reg = given >> bitstart;
+                                 reg &= (2 << (bitend - bitstart)) - 1;
+                                 func (stream, "%s", arm_regnames[reg]);
+                                 set_arm_regname_option (current_regnames);
+                               }
+                               break;
+
                              default:
                                abort ();
                              }
@@ -734,6 +833,54 @@ print_insn_arm (pc, info, given)
                          }
                        break;
 
+                     case 'L':
+                       switch (given & 0x00400100)
+                         {
+                         case 0x00000000: func (stream, "b"); break;
+                         case 0x00400000: func (stream, "h"); break;
+                         case 0x00000100: func (stream, "w"); break;
+                         case 0x00400100: func (stream, "d"); break;
+                         default:
+                           break;
+                         }
+                       break;
+
+                     case 'Z':
+                       {
+                         int value;
+                         /* given (20, 23) | given (0, 3) */
+                         value = ((given >> 16) & 0xf0) | (given & 0xf);
+                         func (stream, "%d", value);
+                       }
+                       break;
+
+                     case 'l':
+                       /* This is like the 'A' operator, except that if
+                          the width field "M" is zero, then the offset is
+                          *not* multiplied by four.  */
+                       {
+                         int offset = given & 0xff;
+                         int multiplier = (given & 0x00000100) ? 4 : 1;
+
+                         func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
+
+                         if (offset)
+                           {
+                             if ((given & 0x01000000) != 0)
+                               func (stream, ", %s#%d]%s",
+                                     ((given & 0x00800000) == 0 ? "-" : ""),
+                                     offset * multiplier,
+                                     ((given & 0x00200000) != 0 ? "!" : ""));
+                             else
+                               func (stream, "], %s#%d",
+                                     ((given & 0x00800000) == 0 ? "-" : ""),
+                                     offset * multiplier);
+                           }
+                         else
+                           func (stream, "]");
+                       }
+                       break;
+
                      default:
                        abort ();
                      }
index 213d4f0..233a830 100644 (file)
@@ -1,6 +1,6 @@
 /* Opcode table for the ARM.
 
-   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2003
    Free Software Foundation, Inc.
    
    This program is free software; you can redistribute it and/or modify
@@ -60,6 +60,13 @@ struct thumb_opcode
    %m                  print register mask for ldm/stm instruction
    %C                  print the PSR sub type.
    %F                  print the COUNT field of a LFM/SFM instruction.
+IWMMXT specific format options:
+   %<bitfield>g         print as an iWMMXt 64-bit register
+   %<bitfield>G         print as an iWMMXt general purpose or control register
+   %<bitfield>w         print as an iWMMXt width field - [bhwd]ss/us
+   %Z                  print the Immediate of a WSHUFH instruction.
+   %L                  print as an iWMMXt N/M width field.
+   %l                  like 'A' except use byte offsets for 'B' & 'H' versions
 Thumb specific format options:
    %D                   print Thumb register (bits 0..2 as high number if bit 7 set)
    %S                   print Thumb register (bits 3..5 as high number if bit 6 set)
@@ -101,6 +108,59 @@ static const struct arm_opcode arm_opcodes[] =
     {0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"},
     {0xf450f000, 0xfc70f000, "pld\t%a"},
     
+    /* Intel(r) Wireless MMX(tm) technology instructions.  */
+#define FIRST_IWMMXT_INSN 0x0e130130
+#define IWMMXT_INSN_COUNT 47
+    {0x0e130130, 0x0f3f0fff, "tandc%22-23w%c\t%12-15r"},
+    {0x0e400010, 0x0ff00f3f, "tbcst%6-7w%c\t%16-19g, %12-15r"},
+    {0x0e130170, 0x0f3f0ff8, "textrc%22-23w%c\t%12-15r, #%0-2d"},
+    {0x0e100070, 0x0f300ff0, "textrm%3?su%22-23w%c\t%12-15r, %16-19g, #%0-2d"},
+    {0x0e600010, 0x0ff00f38, "tinsr%6-7w%c\t%16-19g, %12-15r, #%0-2d"},
+    {0x0e000110, 0x0ff00fff, "tmcr%c\t%16-19G, %12-15r"},
+    {0x0c400000, 0x0ff00ff0, "tmcrr%c\t%0-3g, %12-15r, %16-19r"},
+    {0x0e2c0010, 0x0ffc0e10, "tmia%17?tb%16?tb%c\t%5-8g, %0-3r, %12-15r"},
+    {0x0e200010, 0x0fff0e10, "tmia%c\t%5-8g, %0-3r, %12-15r"},
+    {0x0e280010, 0x0fff0e10, "tmiaph%c\t%5-8g, %0-3r, %12-15r"},
+    {0x0e100030, 0x0f300fff, "tmovmsk%22-23w%c\t%12-15r, %16-19g"},
+    {0x0e100110, 0x0ff00ff0, "tmrc%c\t%12-15r, %16-19G"},
+    {0x0c500000, 0x0ff00ff0, "tmrrc%c\t%12-15r, %16-19r, %0-3g"},
+    {0x0e130150, 0x0f3f0fff, "torc%22-23w%c\t%12-15r"},
+    {0x0e0001c0, 0x0f300fff, "wacc%22-23w%c\t%12-15g, %16-19g"},
+    {0x0e000180, 0x0f000ff0, "wadd%20-23w%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e000020, 0x0f800ff0, "waligni%c\t%12-15g, %16-19g, %0-3g, #%20-22d"},
+    {0x0e800020, 0x0fc00ff0, "walignr%20-21d%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e200000, 0x0fe00ff0, "wand%20'n%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e800000, 0x0fa00ff0, "wavg2%22?hb%20'r%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e000060, 0x0f300ff0, "wcmpeq%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e100060, 0x0f100ff0, "wcmpgt%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+    {0xfc100100, 0xfe500f00, "wldrw\t%12-15G, %A"},
+    {0x0c100000, 0x0e100e00, "wldr%L%c\t%12-15g, %l"},
+    {0x0e400100, 0x0fc00ff0, "wmac%21?su%20'z%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e800100, 0x0fd00ff0, "wmadd%21?su%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e000160, 0x0f100ff0, "wmax%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e100160, 0x0f100ff0, "wmin%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e000100, 0x0fc00ff0, "wmul%21?su%20?ml%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e000000, 0x0ff00ff0, "wor%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e000080, 0x0f000ff0, "wpack%20-23w%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e300040, 0x0f300ff0, "wror%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e300148, 0x0f300ffc, "wror%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
+    {0x0e000120, 0x0fa00ff0, "wsad%22?hb%20'z%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e0001e0, 0x0f000ff0, "wshufh%c\t%12-15g, %16-19g, #%Z"},
+    {0x0e100040, 0x0f300ff0, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e100148, 0x0f300ffc, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
+    {0x0e000040, 0x0f300ff0, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e000148, 0x0f300ffc, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
+    {0x0e200040, 0x0f300ff0, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e200148, 0x0f300ffc, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"},
+    {0xfc000100, 0xfe500f00, "wstrw\t%12-15G, %A"},
+    {0x0c000000, 0x0e100e00, "wstr%L%c\t%12-15g, %l"},
+    {0x0e0001a0, 0x0f000ff0, "wsub%20-23w%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e0000c0, 0x0f100fff, "wunpckeh%21?su%22-23w%c\t%12-15g, %16-19g"},
+    {0x0e0000e0, 0x0f100fff, "wunpckel%21?su%22-23w%c\t%12-15g, %16-19g"},
+    {0x0e1000c0, 0x0f300ff0, "wunpckih%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e1000e0, 0x0f300ff0, "wunpckil%22-23w%c\t%12-15g, %16-19g, %0-3g"},
+    {0x0e100000, 0x0ff00ff0, "wxor%c\t%12-15g, %16-19g, %0-3g"},
+
     /* V5 Instructions.  */
     {0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"},
     {0xfa000000, 0xfe000000, "blx\t%B"},