]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
This commit was manufactured by cvs2svn to create branch
authornobody <>
Wed, 16 Apr 2003 04:55:32 +0000 (04:55 +0000)
committernobody <>
Wed, 16 Apr 2003 04:55:32 +0000 (04:55 +0000)
'carlton_dictionary-branch'.

Cherrypick from master 2003-04-16 04:55:31 UTC DJ Delorie <dj@redhat.com> 'merge from gcc':
    bfd/cpu-xtensa.c
    bfd/elf32-xtensa.c
    bfd/po/zh_CN.po
    bfd/xtensa-isa.c
    bfd/xtensa-modules.c
    gdb/cp-namespace.c
    gdb/doc/observer.texi
    gdb/frame-base.c
    gdb/frame-base.h
    gdb/i386-cygwin-tdep.c
    gdb/infttrace.h
    gdb/mi/mi-cmd-file.c
    gdb/testsuite/gdb.arch/e500-abi.c
    gdb/testsuite/gdb.arch/e500-abi.exp
    gdb/testsuite/gdb.arch/e500-regs.c
    gdb/testsuite/gdb.arch/e500-regs.exp
    gdb/testsuite/gdb.asm/m68hc11.inc
    gdb/testsuite/gdb.base/gdb1090.c
    gdb/testsuite/gdb.base/gdb1090.exp
    gdb/testsuite/gdb.c++/maint.exp
    gdb/testsuite/gdb.gdb/observer.exp
    gdb/testsuite/gdb.mi/mi-file.exp
    include/elf/xtensa.h
    include/xtensa-config.h
    include/xtensa-isa-internal.h
    include/xtensa-isa.h
    libiberty/mempcpy.c
    libiberty/stpcpy.c
    libiberty/stpncpy.c
    opcodes/xtensa-dis.c
    sim/arm/iwmmxt.c
    sim/arm/iwmmxt.h
    sim/arm/maverick.c

33 files changed:
bfd/cpu-xtensa.c [new file with mode: 0644]
bfd/elf32-xtensa.c [new file with mode: 0644]
bfd/po/zh_CN.po [new file with mode: 0644]
bfd/xtensa-isa.c [new file with mode: 0644]
bfd/xtensa-modules.c [new file with mode: 0644]
gdb/cp-namespace.c [new file with mode: 0644]
gdb/doc/observer.texi [new file with mode: 0644]
gdb/frame-base.c [new file with mode: 0644]
gdb/frame-base.h [new file with mode: 0644]
gdb/i386-cygwin-tdep.c [new file with mode: 0644]
gdb/infttrace.h [new file with mode: 0644]
gdb/mi/mi-cmd-file.c [new file with mode: 0644]
gdb/testsuite/gdb.arch/e500-abi.c [new file with mode: 0644]
gdb/testsuite/gdb.arch/e500-abi.exp [new file with mode: 0644]
gdb/testsuite/gdb.arch/e500-regs.c [new file with mode: 0644]
gdb/testsuite/gdb.arch/e500-regs.exp [new file with mode: 0644]
gdb/testsuite/gdb.asm/m68hc11.inc [new file with mode: 0644]
gdb/testsuite/gdb.base/gdb1090.c [new file with mode: 0644]
gdb/testsuite/gdb.base/gdb1090.exp [new file with mode: 0644]
gdb/testsuite/gdb.c++/maint.exp [new file with mode: 0644]
gdb/testsuite/gdb.gdb/observer.exp [new file with mode: 0644]
gdb/testsuite/gdb.mi/mi-file.exp [new file with mode: 0644]
include/elf/xtensa.h [new file with mode: 0644]
include/xtensa-config.h [new file with mode: 0644]
include/xtensa-isa-internal.h [new file with mode: 0644]
include/xtensa-isa.h [new file with mode: 0644]
libiberty/mempcpy.c [new file with mode: 0644]
libiberty/stpcpy.c [new file with mode: 0644]
libiberty/stpncpy.c [new file with mode: 0644]
opcodes/xtensa-dis.c [new file with mode: 0644]
sim/arm/iwmmxt.c [new file with mode: 0644]
sim/arm/iwmmxt.h [new file with mode: 0644]
sim/arm/maverick.c [new file with mode: 0644]

diff --git a/bfd/cpu-xtensa.c b/bfd/cpu-xtensa.c
new file mode 100644 (file)
index 0000000..fbfff64
--- /dev/null
@@ -0,0 +1,38 @@
+/* BFD support for the Xtensa processor.
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   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.
+
+   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 "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_xtensa_arch =
+{
+  32,                          /* Bits per word.  */
+  32,                          /* Bits per address.  */
+  8,                           /* Bits per byte.  */
+  bfd_arch_xtensa,             /* Architecture.  */
+  bfd_mach_xtensa,             /* Machine.  */
+  "xtensa",                    /* Architecture name.  */
+  "xtensa",                    /* Printable name.  */
+  4,                           /* Section align power.  */
+  TRUE,                                /* The default?  */
+  bfd_default_compatible,      /* Architecture comparison fn.  */
+  bfd_default_scan,            /* String to architecture convert fn.  */
+  NULL                         /* Next in list.  */
+};
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
new file mode 100644 (file)
index 0000000..b991df4
--- /dev/null
@@ -0,0 +1,5845 @@
+/* Xtensa-specific support for 32-bit ELF.
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   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.
+
+   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 "bfd.h"
+#include "sysdep.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <strings.h>
+
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elf/xtensa.h"
+#include "xtensa-isa.h"
+#include "xtensa-config.h"
+
+/* Main interface functions.  */
+static void elf_xtensa_info_to_howto_rela
+  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
+static reloc_howto_type *elf_xtensa_reloc_type_lookup
+  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+extern int xtensa_read_table_entries
+  PARAMS ((bfd *, asection *, property_table_entry **, const char *));
+static bfd_boolean elf_xtensa_check_relocs
+  PARAMS ((bfd *, struct bfd_link_info *, asection *,
+          const Elf_Internal_Rela *));
+static void elf_xtensa_hide_symbol
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
+static void elf_xtensa_copy_indirect_symbol
+  PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *,
+          struct elf_link_hash_entry *));
+static asection *elf_xtensa_gc_mark_hook
+  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
+          struct elf_link_hash_entry *, Elf_Internal_Sym *));
+static bfd_boolean elf_xtensa_gc_sweep_hook
+  PARAMS ((bfd *, struct bfd_link_info *, asection *,
+          const Elf_Internal_Rela *));
+static bfd_boolean elf_xtensa_create_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+static bfd_boolean elf_xtensa_adjust_dynamic_symbol
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+static bfd_boolean elf_xtensa_size_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+static bfd_boolean elf_xtensa_modify_segment_map
+  PARAMS ((bfd *));
+static bfd_boolean elf_xtensa_relocate_section
+  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+          Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static bfd_boolean elf_xtensa_relax_section
+  PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *again));
+static bfd_boolean elf_xtensa_finish_dynamic_symbol
+  PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
+          Elf_Internal_Sym *));
+static bfd_boolean elf_xtensa_finish_dynamic_sections
+  PARAMS ((bfd *, struct bfd_link_info *));
+static bfd_boolean elf_xtensa_merge_private_bfd_data
+  PARAMS ((bfd *, bfd *));
+static bfd_boolean elf_xtensa_set_private_flags
+  PARAMS ((bfd *, flagword));
+extern flagword elf_xtensa_get_private_bfd_flags
+  PARAMS ((bfd *));
+static bfd_boolean elf_xtensa_print_private_bfd_data
+  PARAMS ((bfd *, PTR));
+static bfd_boolean elf_xtensa_object_p
+  PARAMS ((bfd *));
+static void elf_xtensa_final_write_processing
+  PARAMS ((bfd *, bfd_boolean));
+static enum elf_reloc_type_class elf_xtensa_reloc_type_class
+  PARAMS ((const Elf_Internal_Rela *));
+static bfd_boolean elf_xtensa_discard_info
+  PARAMS ((bfd *, struct elf_reloc_cookie *, struct bfd_link_info *));
+static bfd_boolean elf_xtensa_ignore_discarded_relocs
+  PARAMS ((asection *));
+static bfd_boolean elf_xtensa_grok_prstatus
+  PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elf_xtensa_grok_psinfo
+  PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elf_xtensa_new_section_hook
+  PARAMS ((bfd *, asection *));
+
+
+/* Local helper functions.  */
+
+static int property_table_compare
+  PARAMS ((const PTR, const PTR));
+static bfd_boolean elf_xtensa_in_literal_pool
+  PARAMS ((property_table_entry *, int, bfd_vma));
+static void elf_xtensa_make_sym_local
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+static bfd_boolean add_extra_plt_sections
+  PARAMS ((bfd *, int));
+static bfd_boolean elf_xtensa_fix_refcounts
+  PARAMS ((struct elf_link_hash_entry *, PTR));
+static bfd_boolean elf_xtensa_allocate_plt_size
+  PARAMS ((struct elf_link_hash_entry *, PTR));
+static bfd_boolean elf_xtensa_allocate_got_size
+  PARAMS ((struct elf_link_hash_entry *, PTR));
+static void elf_xtensa_allocate_local_got_size
+  PARAMS ((struct bfd_link_info *, asection *));
+static bfd_reloc_status_type elf_xtensa_do_reloc
+  PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_vma, bfd_byte *,
+          bfd_vma, bfd_boolean, char **));
+static char * vsprint_msg
+  VPARAMS ((const char *, const char *, int, ...));
+static char *build_encoding_error_message
+  PARAMS ((xtensa_opcode, xtensa_encode_result));
+static bfd_reloc_status_type bfd_elf_xtensa_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static void do_fix_for_relocateable_link
+  PARAMS ((Elf_Internal_Rela *, bfd *, asection *));
+static void do_fix_for_final_link
+  PARAMS ((Elf_Internal_Rela *, asection *, bfd_vma *));
+static bfd_boolean xtensa_elf_dynamic_symbol_p
+  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+static bfd_vma elf_xtensa_create_plt_entry
+  PARAMS ((bfd *, bfd *, unsigned));
+static int elf_xtensa_combine_prop_entries
+  PARAMS ((bfd *, const char *));
+static bfd_boolean elf_xtensa_discard_info_for_section
+  PARAMS ((bfd *, struct elf_reloc_cookie *, struct bfd_link_info *,
+          asection *));
+
+/* Local functions to handle Xtensa configurability.  */
+
+static void init_call_opcodes
+  PARAMS ((void));
+static bfd_boolean is_indirect_call_opcode
+  PARAMS ((xtensa_opcode));
+static bfd_boolean is_direct_call_opcode
+  PARAMS ((xtensa_opcode));
+static bfd_boolean is_windowed_call_opcode
+  PARAMS ((xtensa_opcode));
+static xtensa_opcode get_l32r_opcode
+  PARAMS ((void));
+static bfd_vma l32r_offset
+  PARAMS ((bfd_vma, bfd_vma));
+static int get_relocation_opnd
+  PARAMS ((Elf_Internal_Rela *));
+static xtensa_opcode get_relocation_opcode
+  PARAMS ((asection *, bfd_byte *, Elf_Internal_Rela *));
+static bfd_boolean is_l32r_relocation
+  PARAMS ((asection *, bfd_byte *, Elf_Internal_Rela *));
+
+/* Functions for link-time code simplifications.  */
+
+static bfd_reloc_status_type elf_xtensa_do_asm_simplify 
+  PARAMS ((bfd_byte *, bfd_vma, bfd_vma));
+static bfd_reloc_status_type contract_asm_expansion
+  PARAMS ((bfd_byte *, bfd_vma, Elf_Internal_Rela *));
+static xtensa_opcode swap_callx_for_call_opcode
+  PARAMS ((xtensa_opcode));
+static xtensa_opcode get_expanded_call_opcode
+  PARAMS ((bfd_byte *, int));
+
+/* Access to internal relocations, section contents and symbols.  */
+
+static Elf_Internal_Rela *retrieve_internal_relocs
+  PARAMS ((bfd *, asection *, bfd_boolean));
+static void pin_internal_relocs
+  PARAMS ((asection *, Elf_Internal_Rela *));
+static void release_internal_relocs
+  PARAMS ((asection *, Elf_Internal_Rela *));
+static bfd_byte *retrieve_contents
+  PARAMS ((bfd *, asection *, bfd_boolean));
+static void pin_contents
+  PARAMS ((asection *, bfd_byte *));
+static void release_contents
+  PARAMS ((asection *, bfd_byte *));
+static Elf_Internal_Sym *retrieve_local_syms
+  PARAMS ((bfd *));
+
+/* Miscellaneous utility functions.  */
+
+static asection *elf_xtensa_get_plt_section
+  PARAMS ((bfd *, int));
+static asection *elf_xtensa_get_gotplt_section
+  PARAMS ((bfd *, int));
+static asection *get_elf_r_symndx_section
+  PARAMS ((bfd *, unsigned long));
+static struct elf_link_hash_entry *get_elf_r_symndx_hash_entry
+  PARAMS ((bfd *, unsigned long));
+static bfd_vma get_elf_r_symndx_offset
+  PARAMS ((bfd *, unsigned long));
+static bfd_boolean pcrel_reloc_fits
+  PARAMS ((xtensa_operand, bfd_vma, bfd_vma));
+static bfd_boolean xtensa_is_property_section
+  PARAMS ((asection *));
+static bfd_boolean is_literal_section
+  PARAMS ((asection *));
+static int internal_reloc_compare
+  PARAMS ((const PTR, const PTR));
+static bfd_boolean get_is_linkonce_section
+  PARAMS ((bfd *, asection *));
+extern char *xtensa_get_property_section_name
+  PARAMS ((bfd *, asection *, const char *));
+
+/* Other functions called directly by the linker.  */
+
+typedef void (*deps_callback_t)
+  PARAMS ((asection *, bfd_vma, asection *, bfd_vma, PTR));
+extern bfd_boolean xtensa_callback_required_dependence
+  PARAMS ((bfd *, asection *, struct bfd_link_info *,
+          deps_callback_t, PTR));
+
+
+typedef struct xtensa_relax_info_struct xtensa_relax_info;
+
+
+/* Total count of PLT relocations seen during check_relocs.
+   The actual PLT code must be split into multiple sections and all
+   the sections have to be created before size_dynamic_sections,
+   where we figure out the exact number of PLT entries that will be
+   needed.  It is OK is this count is an overestimate, e.g., some
+   relocations may be removed by GC.  */
+
+static int plt_reloc_count = 0;
+
+
+/* When this is true, relocations may have been modified to refer to
+   symbols from other input files.  The per-section list of "fix"
+   records needs to be checked when resolving relocations.  */
+
+static bfd_boolean relaxing_section = FALSE;
+
+\f
+static reloc_howto_type elf_howto_table[] =
+{
+  HOWTO (R_XTENSA_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+        bfd_elf_xtensa_reloc, "R_XTENSA_NONE",
+        FALSE, 0x00000000, 0x00000000, FALSE),
+  HOWTO (R_XTENSA_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+        bfd_elf_xtensa_reloc, "R_XTENSA_32",
+        TRUE, 0xffffffff, 0xffffffff, FALSE),
+  /* Replace a 32-bit value with a value from the runtime linker (only
+     used by linker-generated stub functions).  The r_addend value is
+     special: 1 means to substitute a pointer to the runtime linker's
+     dynamic resolver function; 2 means to substitute the link map for
+     the shared object.  */
+  HOWTO (R_XTENSA_RTLD, 0, 2, 32, FALSE, 0, complain_overflow_dont,
+        NULL, "R_XTENSA_RTLD",
+        FALSE, 0x00000000, 0x00000000, FALSE),
+  HOWTO (R_XTENSA_GLOB_DAT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+        bfd_elf_generic_reloc, "R_XTENSA_GLOB_DAT",
+        FALSE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO (R_XTENSA_JMP_SLOT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+        bfd_elf_generic_reloc, "R_XTENSA_JMP_SLOT",
+        FALSE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO (R_XTENSA_RELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+        bfd_elf_generic_reloc, "R_XTENSA_RELATIVE",
+        FALSE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO (R_XTENSA_PLT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+        bfd_elf_xtensa_reloc, "R_XTENSA_PLT",
+        FALSE, 0xffffffff, 0xffffffff, FALSE),
+  EMPTY_HOWTO (7),
+  HOWTO (R_XTENSA_OP0, 0, 0, 0, TRUE, 0, complain_overflow_dont,
+        bfd_elf_xtensa_reloc, "R_XTENSA_OP0",
+        FALSE, 0x00000000, 0x00000000, TRUE),
+  HOWTO (R_XTENSA_OP1, 0, 0, 0, TRUE, 0, complain_overflow_dont,
+        bfd_elf_xtensa_reloc, "R_XTENSA_OP1",
+        FALSE, 0x00000000, 0x00000000, TRUE),
+  HOWTO (R_XTENSA_OP2, 0, 0, 0, TRUE, 0, complain_overflow_dont,
+        bfd_elf_xtensa_reloc, "R_XTENSA_OP2",
+        FALSE, 0x00000000, 0x00000000, TRUE),
+  /* Assembly auto-expansion.  */
+  HOWTO (R_XTENSA_ASM_EXPAND, 0, 0, 0, TRUE, 0, complain_overflow_dont,
+        bfd_elf_xtensa_reloc, "R_XTENSA_ASM_EXPAND",
+        FALSE, 0x00000000, 0x00000000, FALSE),
+  /* Relax assembly auto-expansion.  */
+  HOWTO (R_XTENSA_ASM_SIMPLIFY, 0, 0, 0, TRUE, 0, complain_overflow_dont,
+        bfd_elf_xtensa_reloc, "R_XTENSA_ASM_SIMPLIFY",
+        FALSE, 0x00000000, 0x00000000, TRUE),
+  EMPTY_HOWTO (13),
+  EMPTY_HOWTO (14),
+  /* GNU extension to record C++ vtable hierarchy.  */
+  HOWTO (R_XTENSA_GNU_VTINHERIT, 0, 2, 0, FALSE, 0, complain_overflow_dont,
+         NULL, "R_XTENSA_GNU_VTINHERIT",
+        FALSE, 0x00000000, 0x00000000, FALSE),
+  /* GNU extension to record C++ vtable member usage.  */
+  HOWTO (R_XTENSA_GNU_VTENTRY, 0, 2, 0, FALSE, 0, complain_overflow_dont,
+         _bfd_elf_rel_vtable_reloc_fn, "R_XTENSA_GNU_VTENTRY",
+        FALSE, 0x00000000, 0x00000000, FALSE)
+};
+
+#ifdef DEBUG_GEN_RELOC
+#define TRACE(str) \
+  fprintf (stderr, "Xtensa bfd reloc lookup %d (%s)\n", code, str)
+#else
+#define TRACE(str)
+#endif
+
+static reloc_howto_type *
+elf_xtensa_reloc_type_lookup (abfd, code)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     bfd_reloc_code_real_type code;
+{
+  switch (code)
+    {
+    case BFD_RELOC_NONE:
+      TRACE ("BFD_RELOC_NONE");
+      return &elf_howto_table[(unsigned) R_XTENSA_NONE ];
+
+    case BFD_RELOC_32:
+      TRACE ("BFD_RELOC_32");
+      return &elf_howto_table[(unsigned) R_XTENSA_32 ];
+
+    case BFD_RELOC_XTENSA_RTLD:
+      TRACE ("BFD_RELOC_XTENSA_RTLD");
+      return &elf_howto_table[(unsigned) R_XTENSA_RTLD ];
+
+    case BFD_RELOC_XTENSA_GLOB_DAT:
+      TRACE ("BFD_RELOC_XTENSA_GLOB_DAT");
+      return &elf_howto_table[(unsigned) R_XTENSA_GLOB_DAT ];
+
+    case BFD_RELOC_XTENSA_JMP_SLOT:
+      TRACE ("BFD_RELOC_XTENSA_JMP_SLOT");
+      return &elf_howto_table[(unsigned) R_XTENSA_JMP_SLOT ];
+
+    case BFD_RELOC_XTENSA_RELATIVE:
+      TRACE ("BFD_RELOC_XTENSA_RELATIVE");
+      return &elf_howto_table[(unsigned) R_XTENSA_RELATIVE ];
+
+    case BFD_RELOC_XTENSA_PLT:
+      TRACE ("BFD_RELOC_XTENSA_PLT");
+      return &elf_howto_table[(unsigned) R_XTENSA_PLT ];
+
+    case BFD_RELOC_XTENSA_OP0:
+      TRACE ("BFD_RELOC_XTENSA_OP0");
+      return &elf_howto_table[(unsigned) R_XTENSA_OP0 ];
+
+    case BFD_RELOC_XTENSA_OP1:
+      TRACE ("BFD_RELOC_XTENSA_OP1");
+      return &elf_howto_table[(unsigned) R_XTENSA_OP1 ];
+
+    case BFD_RELOC_XTENSA_OP2:
+      TRACE ("BFD_RELOC_XTENSA_OP2");
+      return &elf_howto_table[(unsigned) R_XTENSA_OP2 ];
+
+    case BFD_RELOC_XTENSA_ASM_EXPAND:
+      TRACE ("BFD_RELOC_XTENSA_ASM_EXPAND");
+      return &elf_howto_table[(unsigned) R_XTENSA_ASM_EXPAND ];
+
+    case BFD_RELOC_XTENSA_ASM_SIMPLIFY:
+      TRACE ("BFD_RELOC_XTENSA_ASM_SIMPLIFY");
+      return &elf_howto_table[(unsigned) R_XTENSA_ASM_SIMPLIFY ];
+
+    case BFD_RELOC_VTABLE_INHERIT:
+      TRACE ("BFD_RELOC_VTABLE_INHERIT");
+      return &elf_howto_table[(unsigned) R_XTENSA_GNU_VTINHERIT ];
+
+    case BFD_RELOC_VTABLE_ENTRY:
+      TRACE ("BFD_RELOC_VTABLE_ENTRY");
+      return &elf_howto_table[(unsigned) R_XTENSA_GNU_VTENTRY ];
+
+    default:
+      break;
+    }
+
+  TRACE ("Unknown");
+  return NULL;
+}
+
+
+/* Given an ELF "rela" relocation, find the corresponding howto and record
+   it in the BFD internal arelent representation of the relocation.  */
+
+static void
+elf_xtensa_info_to_howto_rela (abfd, cache_ptr, dst)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *cache_ptr;
+     Elf_Internal_Rela *dst;
+{
+  unsigned int r_type = ELF32_R_TYPE (dst->r_info);
+
+  BFD_ASSERT (r_type < (unsigned int) R_XTENSA_max);
+  cache_ptr->howto = &elf_howto_table[r_type];
+}
+
+\f
+/* Functions for the Xtensa ELF linker.  */
+
+/* The name of the dynamic interpreter.  This is put in the .interp
+   section.  */
+
+#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so"
+
+/* The size in bytes of an entry in the procedure linkage table.
+   (This does _not_ include the space for the literals associated with
+   the PLT entry.) */
+
+#define PLT_ENTRY_SIZE 16
+
+/* For _really_ large PLTs, we may need to alternate between literals
+   and code to keep the literals within the 256K range of the L32R
+   instructions in the code.  It's unlikely that anyone would ever need
+   such a big PLT, but an arbitrary limit on the PLT size would be bad.
+   Thus, we split the PLT into chunks.  Since there's very little
+   overhead (2 extra literals) for each chunk, the chunk size is kept
+   small so that the code for handling multiple chunks get used and
+   tested regularly.  With 254 entries, there are 1K of literals for
+   each chunk, and that seems like a nice round number.  */
+
+#define PLT_ENTRIES_PER_CHUNK 254
+
+/* PLT entries are actually used as stub functions for lazy symbol
+   resolution.  Once the symbol is resolved, the stub function is never
+   invoked.  Note: the 32-byte frame size used here cannot be changed
+   without a corresponding change in the runtime linker.  */
+
+static const bfd_byte elf_xtensa_be_plt_entry[PLT_ENTRY_SIZE] =
+{
+  0x6c, 0x10, 0x04,    /* entry sp, 32 */
+  0x18, 0x00, 0x00,    /* l32r  a8, [got entry for rtld's resolver] */
+  0x1a, 0x00, 0x00,    /* l32r  a10, [got entry for rtld's link map] */
+  0x1b, 0x00, 0x00,    /* l32r  a11, [literal for reloc index] */
+  0x0a, 0x80, 0x00,    /* jx    a8 */
+  0                    /* unused */
+};
+
+static const bfd_byte elf_xtensa_le_plt_entry[PLT_ENTRY_SIZE] =
+{
+  0x36, 0x41, 0x00,    /* entry sp, 32 */
+  0x81, 0x00, 0x00,    /* l32r  a8, [got entry for rtld's resolver] */
+  0xa1, 0x00, 0x00,    /* l32r  a10, [got entry for rtld's link map] */
+  0xb1, 0x00, 0x00,    /* l32r  a11, [literal for reloc index] */
+  0xa0, 0x08, 0x00,    /* jx    a8 */
+  0                    /* unused */
+};
+
+\f
+static int
+property_table_compare (ap, bp)
+     const PTR ap;
+     const PTR bp;
+{
+  const property_table_entry *a = (const property_table_entry *) ap;
+  const property_table_entry *b = (const property_table_entry *) bp;
+
+  /* Check if one entry overlaps with the other; this shouldn't happen
+     except when searching for a match.  */
+  if ((b->address >= a->address && b->address < (a->address + a->size))
+      || (a->address >= b->address && a->address < (b->address + b->size)))
+    return 0;
+
+  return (a->address - b->address);
+}
+
+
+/* Get the literal table or instruction table entries for the given
+   section.  Sets TABLE_P and returns the number of entries.  On error,
+   returns a negative value.  */
+
+int
+xtensa_read_table_entries (abfd, section, table_p, sec_name)
+     bfd *abfd;
+     asection *section;
+     property_table_entry **table_p;
+     const char *sec_name;
+{
+  asection *table_section;
+  char *table_section_name;
+  bfd_size_type table_size = 0;
+  bfd_byte *table_data;
+  property_table_entry *blocks;
+  int block_count;
+  bfd_size_type num_records;
+  Elf_Internal_Rela *internal_relocs;
+
+  table_section_name = 
+    xtensa_get_property_section_name (abfd, section, sec_name);
+  table_section = bfd_get_section_by_name (abfd, table_section_name);
+  if (table_section != NULL)
+    table_size = bfd_get_section_size_before_reloc (table_section);
+  
+  if (table_size == 0) 
+    {
+      *table_p = NULL;
+      return 0;
+    }
+
+  num_records = table_size / sizeof (property_table_entry);
+  table_data = retrieve_contents (abfd, table_section, TRUE);
+  blocks = (property_table_entry *)
+    bfd_malloc (num_records * sizeof (property_table_entry));
+  block_count = 0;
+  
+  /* If the file has not yet been relocated, process the relocations
+     and sort out the table entries that apply to the specified section.  */
+  internal_relocs = retrieve_internal_relocs (abfd, table_section, TRUE);
+  if (internal_relocs)
+    {
+      unsigned i;
+
+      for (i = 0; i < table_section->reloc_count; i++)
+       {
+         Elf_Internal_Rela *rel = &internal_relocs[i];
+         unsigned long r_symndx;
+
+         if (ELF32_R_TYPE (rel->r_info) == R_XTENSA_NONE)
+           continue;
+
+         BFD_ASSERT (ELF32_R_TYPE (rel->r_info) == R_XTENSA_32);
+         r_symndx = ELF32_R_SYM (rel->r_info);
+
+         if (get_elf_r_symndx_section (abfd, r_symndx) == section)
+           {
+             bfd_vma sym_off = get_elf_r_symndx_offset (abfd, r_symndx);
+             blocks[block_count].address =
+               (section->vma + sym_off + rel->r_addend
+                + bfd_get_32 (abfd, table_data + rel->r_offset));
+             blocks[block_count].size =
+               bfd_get_32 (abfd, table_data + rel->r_offset + 4);
+             block_count++;
+           }
+       }
+    }
+  else
+    {
+      /* No relocations.  Presumably the file has been relocated
+        and the addresses are already in the table.  */
+      bfd_vma off;
+
+      for (off = 0; off < table_size; off += sizeof (property_table_entry)) 
+       {
+         bfd_vma address = bfd_get_32 (abfd, table_data + off);
+
+         if (address >= section->vma
+             && address < ( section->vma + section->_raw_size))
+           {
+             blocks[block_count].address = address;
+             blocks[block_count].size =
+               bfd_get_32 (abfd, table_data + off + 4);
+             block_count++;
+           }
+       }
+    }
+
+  release_contents (table_section, table_data);
+  release_internal_relocs (table_section, internal_relocs);
+
+  if (block_count > 0) 
+    {
+      /* Now sort them into address order for easy reference.  */
+      qsort (blocks, block_count, sizeof (property_table_entry),
+            property_table_compare);
+    }
+    
+  *table_p = blocks;
+  return block_count;
+}
+
+
+static bfd_boolean
+elf_xtensa_in_literal_pool (lit_table, lit_table_size, addr)
+     property_table_entry *lit_table;
+     int lit_table_size;
+     bfd_vma addr;
+{
+  property_table_entry entry;
+
+  if (lit_table_size == 0)
+    return FALSE;
+
+  entry.address = addr;
+  entry.size = 1;
+
+  if (bsearch (&entry, lit_table, lit_table_size,
+              sizeof (property_table_entry), property_table_compare))
+    return TRUE;
+
+  return FALSE;
+}
+
+\f
+/* Look through the relocs for a section during the first phase, and
+   calculate needed space in the dynamic reloc sections.  */
+
+static bfd_boolean
+elf_xtensa_check_relocs (abfd, info, sec, relocs)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     asection *sec;
+     const Elf_Internal_Rela *relocs;
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  const Elf_Internal_Rela *rel;
+  const Elf_Internal_Rela *rel_end;
+  property_table_entry *lit_table;
+  int ltblsize;
+
+  if (info->relocateable)
+    return TRUE;
+
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (abfd);
+
+  ltblsize = xtensa_read_table_entries (abfd, sec, &lit_table,
+                                       XTENSA_LIT_SEC_NAME);
+  if (ltblsize < 0)
+    return FALSE;
+
+  rel_end = relocs + sec->reloc_count;
+  for (rel = relocs; rel < rel_end; rel++)
+    {
+      unsigned int r_type;
+      unsigned long r_symndx;
+      struct elf_link_hash_entry *h;
+
+      r_symndx = ELF32_R_SYM (rel->r_info);
+      r_type = ELF32_R_TYPE (rel->r_info);
+
+      if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
+       {
+         (*_bfd_error_handler) (_("%s: bad symbol index: %d"),
+                                bfd_archive_filename (abfd),
+                                r_symndx);
+         return FALSE;
+       }
+
+      if (r_symndx < symtab_hdr->sh_info)
+       h = NULL;
+      else
+       {
+         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+         while (h->root.type == bfd_link_hash_indirect
+                || h->root.type == bfd_link_hash_warning)
+           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+       }
+
+      switch (r_type)
+       {
+       case R_XTENSA_32:
+         if (h == NULL)
+           goto local_literal;
+
+         if ((sec->flags & SEC_ALLOC) != 0)
+           {
+             if ((sec->flags & SEC_READONLY) != 0
+                 && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
+                                                 sec->vma + rel->r_offset))
+               h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+
+             if (h->got.refcount <= 0)
+               h->got.refcount = 1;
+             else
+               h->got.refcount += 1;
+           }
+         break;
+
+       case R_XTENSA_PLT:
+         /* If this relocation is against a local symbol, then it's
+            exactly the same as a normal local GOT entry.  */
+         if (h == NULL)
+           goto local_literal;
+
+         if ((sec->flags & SEC_ALLOC) != 0)
+           {
+             if ((sec->flags & SEC_READONLY) != 0
+                 && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
+                                                 sec->vma + rel->r_offset))
+               h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+
+             if (h->plt.refcount <= 0)
+               {
+                 h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+                 h->plt.refcount = 1;
+               }
+             else
+               h->plt.refcount += 1;
+
+             /* Keep track of the total PLT relocation count even if we
+                don't yet know whether the dynamic sections will be
+                created.  */
+             plt_reloc_count += 1;
+
+             if (elf_hash_table (info)->dynamic_sections_created)
+               {
+                 if (!add_extra_plt_sections (elf_hash_table (info)->dynobj,
+                                              plt_reloc_count))
+                   return FALSE;
+               }
+           }
+         break;
+
+       local_literal:
+         if ((sec->flags & SEC_ALLOC) != 0)
+           {
+             bfd_signed_vma *local_got_refcounts;
+
+             /* This is a global offset table entry for a local symbol.  */
+             local_got_refcounts = elf_local_got_refcounts (abfd);
+             if (local_got_refcounts == NULL)
+               {
+                 bfd_size_type size;
+
+                 size = symtab_hdr->sh_info;
+                 size *= sizeof (bfd_signed_vma);
+                 local_got_refcounts = ((bfd_signed_vma *)
+                                        bfd_zalloc (abfd, size));
+                 if (local_got_refcounts == NULL)
+                   return FALSE;
+                 elf_local_got_refcounts (abfd) = local_got_refcounts;
+               }
+             local_got_refcounts[r_symndx] += 1;
+
+             /* If the relocation is not inside the GOT, the DF_TEXTREL
+                flag needs to be set.  */
+             if (info->shared
+                 && (sec->flags & SEC_READONLY) != 0
+                 && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
+                                                 sec->vma + rel->r_offset))
+               info->flags |= DF_TEXTREL;
+           }
+         break;
+
+       case R_XTENSA_OP0:
+       case R_XTENSA_OP1:
+       case R_XTENSA_OP2:
+       case R_XTENSA_ASM_EXPAND:
+       case R_XTENSA_ASM_SIMPLIFY:
+         /* Nothing to do for these.  */
+         break;
+
+       case R_XTENSA_GNU_VTINHERIT:
+         /* This relocation describes the C++ object vtable hierarchy.
+            Reconstruct it for later use during GC.  */
+         if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+           return FALSE;
+         break;
+
+       case R_XTENSA_GNU_VTENTRY:
+         /* This relocation describes which C++ vtable entries are actually
+            used.  Record for later use during GC.  */
+         if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+           return FALSE;
+         break;
+
+       default:
+         break;
+       }
+    }
+
+  free (lit_table);
+  return TRUE;
+}
+
+
+static void
+elf_xtensa_hide_symbol (info, h, force_local)
+     struct bfd_link_info *info;
+     struct elf_link_hash_entry *h;
+     bfd_boolean force_local;
+{
+  /* For a shared link, move the plt refcount to the got refcount to leave
+     space for RELATIVE relocs.  */
+  elf_xtensa_make_sym_local (info, h);
+
+  _bfd_elf_link_hash_hide_symbol (info, h, force_local);
+}
+
+
+static void
+elf_xtensa_copy_indirect_symbol (bed, dir, ind)
+     struct elf_backend_data *bed;
+     struct elf_link_hash_entry *dir, *ind;
+{
+  _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+
+  /* The standard function doesn't copy the NEEDS_PLT flag.  */
+  dir->elf_link_hash_flags |=
+    (ind->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT);
+}
+
+
+/* Return the section that should be marked against GC for a given
+   relocation.  */
+
+static asection *
+elf_xtensa_gc_mark_hook (sec, info, rel, h, sym)
+     asection *sec;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     Elf_Internal_Rela *rel;
+     struct elf_link_hash_entry *h;
+     Elf_Internal_Sym *sym;
+{
+  if (h != NULL)
+    {
+      switch (ELF32_R_TYPE (rel->r_info))
+       {
+       case R_XTENSA_GNU_VTINHERIT:
+       case R_XTENSA_GNU_VTENTRY:
+         break;
+
+       default:
+         switch (h->root.type)
+           {
+           case bfd_link_hash_defined:
+           case bfd_link_hash_defweak:
+             return h->root.u.def.section;
+
+           case bfd_link_hash_common:
+             return h->root.u.c.p->section;
+
+           default:
+             break;
+           }
+       }
+    }
+  else
+    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
+
+  return NULL;
+}
+
+/* Update the GOT & PLT entry reference counts
+   for the section being removed.  */
+
+static bfd_boolean
+elf_xtensa_gc_sweep_hook (abfd, info, sec, relocs)
+     bfd *abfd;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     asection *sec;
+     const Elf_Internal_Rela *relocs;
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  bfd_signed_vma *local_got_refcounts;
+  const Elf_Internal_Rela *rel, *relend;
+
+  if ((sec->flags & SEC_ALLOC) == 0)
+    return TRUE;
+
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (abfd);
+  local_got_refcounts = elf_local_got_refcounts (abfd);
+
+  relend = relocs + sec->reloc_count;
+  for (rel = relocs; rel < relend; rel++)
+    {
+      unsigned long r_symndx;
+      unsigned int r_type;
+      struct elf_link_hash_entry *h = NULL;
+
+      r_symndx = ELF32_R_SYM (rel->r_info);
+      if (r_symndx >= symtab_hdr->sh_info)
+       h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+      r_type = ELF32_R_TYPE (rel->r_info);
+      switch (r_type)
+       {
+       case R_XTENSA_32:
+         if (h == NULL)
+           goto local_literal;
+         if (h->got.refcount > 0)
+           h->got.refcount--;
+         break;
+
+       case R_XTENSA_PLT:
+         if (h == NULL)
+           goto local_literal;
+         if (h->plt.refcount > 0)
+           h->plt.refcount--;
+         break;
+
+       local_literal:
+         if (local_got_refcounts[r_symndx] > 0)
+           local_got_refcounts[r_symndx] -= 1;
+         break;
+
+       default:
+         break;
+       }
+    }
+
+  return TRUE;
+}
+
+
+/* Create all the dynamic sections.  */
+
+static bfd_boolean
+elf_xtensa_create_dynamic_sections (dynobj, info)
+     bfd *dynobj;
+     struct bfd_link_info *info;
+{
+  flagword flags;
+  asection *s;
+
+  /* First do all the standard stuff.  */
+  if (! _bfd_elf_create_dynamic_sections (dynobj, info))
+    return FALSE;
+
+  /* Create any extra PLT sections in case check_relocs has already
+     been called on all the non-dynamic input files.  */
+  if (!add_extra_plt_sections (dynobj, plt_reloc_count))
+    return FALSE;
+
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+          | SEC_LINKER_CREATED | SEC_READONLY);
+
+  /* Mark the ".got.plt" section READONLY.  */
+  s = bfd_get_section_by_name (dynobj, ".got.plt");
+  if (s == NULL
+      || ! bfd_set_section_flags (dynobj, s, flags))
+    return FALSE;
+
+  /* Create ".rela.got".  */
+  s = bfd_make_section (dynobj, ".rela.got");
+  if (s == NULL
+      || ! bfd_set_section_flags (dynobj, s, flags)
+      || ! bfd_set_section_alignment (dynobj, s, 2))
+    return FALSE;
+
+  /* Create ".xt.lit.plt" (literal table for ".got.plt*").  */
+  s = bfd_make_section (dynobj, ".xt.lit.plt");
+  if (s == NULL
+      || ! bfd_set_section_flags (dynobj, s, flags)
+      || ! bfd_set_section_alignment (dynobj, s, 2))
+    return FALSE;
+
+  return TRUE;
+}
+
+
+static bfd_boolean
+add_extra_plt_sections (dynobj, count)
+     bfd *dynobj;
+     int count;
+{
+  int chunk;
+
+  /* Iterate over all chunks except 0 which uses the standard ".plt" and
+     ".got.plt" sections.  */
+  for (chunk = count / PLT_ENTRIES_PER_CHUNK; chunk > 0; chunk--)
+    {
+      char *sname;
+      flagword flags;
+      asection *s;
+
+      /* Stop when we find a section has already been created.  */
+      if (elf_xtensa_get_plt_section (dynobj, chunk))
+       break;
+
+      flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+              | SEC_LINKER_CREATED | SEC_READONLY);
+
+      sname = (char *) bfd_malloc (10);
+      sprintf (sname, ".plt.%u", chunk);
+      s = bfd_make_section (dynobj, sname);
+      if (s == NULL
+         || ! bfd_set_section_flags (dynobj, s, flags | SEC_CODE)
+         || ! bfd_set_section_alignment (dynobj, s, 2))
+       return FALSE;
+
+      sname = (char *) bfd_malloc (14);
+      sprintf (sname, ".got.plt.%u", chunk);
+      s = bfd_make_section (dynobj, sname);
+      if (s == NULL
+         || ! bfd_set_section_flags (dynobj, s, flags)
+         || ! bfd_set_section_alignment (dynobj, s, 2))
+       return FALSE;
+    }
+
+  return TRUE;
+}
+
+
+/* Adjust a symbol defined by a dynamic object and referenced by a
+   regular object.  The current definition is in some section of the
+   dynamic object, but we're not including those sections.  We have to
+   change the definition to something the rest of the link can
+   understand.  */
+
+static bfd_boolean
+elf_xtensa_adjust_dynamic_symbol (info, h)
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     struct elf_link_hash_entry *h;
+{
+  /* If this is a weak symbol, and there is a real definition, the
+     processor independent code will have arranged for us to see the
+     real definition first, and we can just use the same value.  */
+  if (h->weakdef != NULL)
+    {
+      BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
+                 || h->weakdef->root.type == bfd_link_hash_defweak);
+      h->root.u.def.section = h->weakdef->root.u.def.section;
+      h->root.u.def.value = h->weakdef->root.u.def.value;
+      return TRUE;
+    }
+
+  /* This is a reference to a symbol defined by a dynamic object.  The
+     reference must go through the GOT, so there's no need for COPY relocs,
+     .dynbss, etc.  */
+
+  return TRUE;
+}
+
+
+static void
+elf_xtensa_make_sym_local (info, h)
+     struct bfd_link_info *info;
+     struct elf_link_hash_entry *h;
+{
+  if (info->shared)
+    {
+      if (h->plt.refcount > 0)
+       {
+         /* Will use RELATIVE relocs instead of JMP_SLOT relocs.  */
+         if (h->got.refcount < 0)
+           h->got.refcount = 0;
+         h->got.refcount += h->plt.refcount;
+         h->plt.refcount = 0;
+       }
+    }
+  else
+    {
+      /* Don't need any dynamic relocations at all.  */
+      h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
+      h->plt.refcount = 0;
+      h->got.refcount = 0;
+    }
+}
+
+
+static bfd_boolean
+elf_xtensa_fix_refcounts (h, arg)
+     struct elf_link_hash_entry *h;
+     PTR arg;
+{
+  struct bfd_link_info *info = (struct bfd_link_info *) arg;
+
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  if (! xtensa_elf_dynamic_symbol_p (info, h))
+    elf_xtensa_make_sym_local (info, h);
+
+  /* If the symbol has a relocation outside the GOT, set the
+     DF_TEXTREL flag.  */
+  if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) != 0)
+    info->flags |= DF_TEXTREL;
+
+  return TRUE;
+}
+
+
+static bfd_boolean
+elf_xtensa_allocate_plt_size (h, arg)
+     struct elf_link_hash_entry *h;
+     PTR arg;
+{
+  asection *srelplt = (asection *) arg;
+
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  if (h->plt.refcount > 0)
+    srelplt->_raw_size += (h->plt.refcount * sizeof (Elf32_External_Rela));
+
+  return TRUE;
+}
+
+
+static bfd_boolean
+elf_xtensa_allocate_got_size (h, arg)
+     struct elf_link_hash_entry *h;
+     PTR arg;
+{
+  asection *srelgot = (asection *) arg;
+
+  if (h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  if (h->got.refcount > 0)
+    srelgot->_raw_size += (h->got.refcount * sizeof (Elf32_External_Rela));
+
+  return TRUE;
+}
+
+
+static void
+elf_xtensa_allocate_local_got_size (info, srelgot)
+     struct bfd_link_info *info;
+     asection *srelgot;
+{
+  bfd *i;
+
+  for (i = info->input_bfds; i; i = i->link_next)
+    {
+      bfd_signed_vma *local_got_refcounts;
+      bfd_size_type j, cnt;
+      Elf_Internal_Shdr *symtab_hdr;
+
+      local_got_refcounts = elf_local_got_refcounts (i);
+      if (!local_got_refcounts)
+       continue;
+
+      symtab_hdr = &elf_tdata (i)->symtab_hdr;
+      cnt = symtab_hdr->sh_info;
+
+      for (j = 0; j < cnt; ++j)
+       {
+         if (local_got_refcounts[j] > 0)
+           srelgot->_raw_size += (local_got_refcounts[j]
+                                  * sizeof (Elf32_External_Rela));
+       }
+    }
+}
+
+
+/* Set the sizes of the dynamic sections.  */
+
+static bfd_boolean
+elf_xtensa_size_dynamic_sections (output_bfd, info)
+     bfd *output_bfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *info;
+{
+  bfd *dynobj;
+  asection *s, *srelplt, *splt, *sgotplt, *srelgot, *spltlittbl;
+  bfd_boolean relplt, relgot;
+  int plt_entries, plt_chunks, chunk;
+
+  plt_entries = 0;
+  plt_chunks = 0;
+  srelgot = 0;
+
+  dynobj = elf_hash_table (info)->dynobj;
+  if (dynobj == NULL)
+    abort ();
+
+  if (elf_hash_table (info)->dynamic_sections_created)
+    {
+      /* Set the contents of the .interp section to the interpreter.  */
+      if (! info->shared)
+       {
+         s = bfd_get_section_by_name (dynobj, ".interp");
+         if (s == NULL)
+           abort ();
+         s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+         s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+       }
+
+      /* Allocate room for one word in ".got".  */
+      s = bfd_get_section_by_name (dynobj, ".got");
+      if (s == NULL)
+       abort ();
+      s->_raw_size = 4;
+
+      /* Adjust refcounts for symbols that we now know are not "dynamic".  */
+      elf_link_hash_traverse (elf_hash_table (info),
+                             elf_xtensa_fix_refcounts,
+                             (PTR) info);
+
+      /* Allocate space in ".rela.got" for literals that reference
+        global symbols.  */
+      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+      if (srelgot == NULL)
+       abort ();
+      elf_link_hash_traverse (elf_hash_table (info),
+                             elf_xtensa_allocate_got_size,
+                             (PTR) srelgot);
+
+      /* If we are generating a shared object, we also need space in
+        ".rela.got" for R_XTENSA_RELATIVE relocs for literals that
+        reference local symbols.  */
+      if (info->shared)
+       elf_xtensa_allocate_local_got_size (info, srelgot);
+
+      /* Allocate space in ".rela.plt" for literals that have PLT entries.  */
+      srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
+      if (srelplt == NULL)
+       abort ();
+      elf_link_hash_traverse (elf_hash_table (info),
+                             elf_xtensa_allocate_plt_size,
+                             (PTR) srelplt);
+
+      /* Allocate space in ".plt" to match the size of ".rela.plt".  For
+        each PLT entry, we need the PLT code plus a 4-byte literal.
+        For each chunk of ".plt", we also need two more 4-byte
+        literals, two corresponding entries in ".rela.got", and an
+        8-byte entry in ".xt.lit.plt".  */
+      spltlittbl = bfd_get_section_by_name (dynobj, ".xt.lit.plt");
+      if (spltlittbl == NULL)
+       abort ();
+
+      plt_entries = srelplt->_raw_size / sizeof (Elf32_External_Rela);
+      plt_chunks =
+       (plt_entries + PLT_ENTRIES_PER_CHUNK - 1) / PLT_ENTRIES_PER_CHUNK;
+
+      /* Iterate over all the PLT chunks, including any extra sections
+        created earlier because the initial count of PLT relocations
+        was an overestimate.  */
+      for (chunk = 0;
+          (splt = elf_xtensa_get_plt_section (dynobj, chunk)) != NULL;
+          chunk++)
+       {
+         int chunk_entries;
+
+         sgotplt = elf_xtensa_get_gotplt_section (dynobj, chunk);
+         if (sgotplt == NULL)
+           abort ();
+
+         if (chunk < plt_chunks - 1)
+           chunk_entries = PLT_ENTRIES_PER_CHUNK;
+         else if (chunk == plt_chunks - 1)
+           chunk_entries = plt_entries - (chunk * PLT_ENTRIES_PER_CHUNK);
+         else
+           chunk_entries = 0;
+
+         if (chunk_entries != 0)
+           {
+             sgotplt->_raw_size = 4 * (chunk_entries + 2);
+             splt->_raw_size = PLT_ENTRY_SIZE * chunk_entries;
+             srelgot->_raw_size += 2 * sizeof (Elf32_External_Rela);
+             spltlittbl->_raw_size += 8;
+           }
+         else
+           {
+             sgotplt->_raw_size = 0;
+             splt->_raw_size = 0;
+           }
+       }
+    }
+
+  /* Allocate memory for dynamic sections.  */
+  relplt = FALSE;
+  relgot = FALSE;
+  for (s = dynobj->sections; s != NULL; s = s->next)
+    {
+      const char *name;
+      bfd_boolean strip;
+
+      if ((s->flags & SEC_LINKER_CREATED) == 0)
+       continue;
+
+      /* It's OK to base decisions on the section name, because none
+        of the dynobj section names depend upon the input files.  */
+      name = bfd_get_section_name (dynobj, s);
+
+      strip = FALSE;
+
+      if (strncmp (name, ".rela", 5) == 0)
+       {
+         if (strcmp (name, ".rela.plt") == 0)
+           relplt = TRUE;
+         else if (strcmp (name, ".rela.got") == 0)
+           relgot = TRUE;
+
+         /* We use the reloc_count field as a counter if we need
+            to copy relocs into the output file.  */
+         s->reloc_count = 0;
+       }
+      else if (strncmp (name, ".plt.", 5) == 0
+              || strncmp (name, ".got.plt.", 9) == 0)
+       {
+         if (s->_raw_size == 0)
+           {
+             /* If we don't need this section, strip it from the output
+                file.  We must create the ".plt*" and ".got.plt*"
+                sections in create_dynamic_sections and/or check_relocs
+                based on a conservative estimate of the PLT relocation
+                count, because the sections must be created before the
+                linker maps input sections to output sections.  The
+                linker does that before size_dynamic_sections, where we
+                compute the exact size of the PLT, so there may be more
+                of these sections than are actually needed.  */
+             strip = TRUE;
+           }
+       }
+      else if (strcmp (name, ".got") != 0
+              && strcmp (name, ".plt") != 0
+              && strcmp (name, ".got.plt") != 0
+              && strcmp (name, ".xt.lit.plt") != 0)
+       {
+         /* It's not one of our sections, so don't allocate space.  */
+         continue;
+       }
+
+      if (strip)
+       _bfd_strip_section_from_output (info, s);
+      else
+       {
+         /* Allocate memory for the section contents.  */
+         s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
+         if (s->contents == NULL && s->_raw_size != 0)
+           return FALSE;
+       }
+    }
+
+  if (elf_hash_table (info)->dynamic_sections_created)
+    {
+      /* Add the special XTENSA_RTLD relocations now.  The offsets won't be
+        known until finish_dynamic_sections, but we need to get the relocs
+        in place before they are sorted.  */
+      if (srelgot == NULL)
+       abort ();
+      for (chunk = 0; chunk < plt_chunks; chunk++)
+       {
+         Elf_Internal_Rela irela;
+         bfd_byte *loc;
+
+         irela.r_offset = 0;
+         irela.r_info = ELF32_R_INFO (0, R_XTENSA_RTLD);
+         irela.r_addend = 0;
+
+         loc = (srelgot->contents
+                + srelgot->reloc_count * sizeof (Elf32_External_Rela));
+         bfd_elf32_swap_reloca_out (output_bfd, &irela, loc);
+         bfd_elf32_swap_reloca_out (output_bfd, &irela,
+                                    loc + sizeof (Elf32_External_Rela));
+         srelgot->reloc_count += 2;
+       }
+
+      /* Add some entries to the .dynamic section.  We fill in the
+        values later, in elf_xtensa_finish_dynamic_sections, but we
+        must add the entries now so that we get the correct size for
+        the .dynamic section.  The DT_DEBUG entry is filled in by the
+        dynamic linker and used by the debugger.  */
+#define add_dynamic_entry(TAG, VAL) \
+  bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
+      if (! info->shared)
+       {
+         if (!add_dynamic_entry (DT_DEBUG, 0))
+           return FALSE;
+       }
+
+      if (relplt)
+       {
+         if (!add_dynamic_entry (DT_PLTGOT, 0)
+             || !add_dynamic_entry (DT_PLTRELSZ, 0)
+             || !add_dynamic_entry (DT_PLTREL, DT_RELA)
+             || !add_dynamic_entry (DT_JMPREL, 0))
+           return FALSE;
+       }
+
+      if (relgot)
+       {
+         if (!add_dynamic_entry (DT_RELA, 0)
+             || !add_dynamic_entry (DT_RELASZ, 0)
+             || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
+           return FALSE;
+       }
+
+      if ((info->flags & DF_TEXTREL) != 0)
+       {
+         if (!add_dynamic_entry (DT_TEXTREL, 0))
+           return FALSE;
+       }
+
+      if (!add_dynamic_entry (DT_XTENSA_GOT_LOC_OFF, 0)
+         || !add_dynamic_entry (DT_XTENSA_GOT_LOC_SZ, 0))
+       return FALSE;
+    }
+#undef add_dynamic_entry
+
+  return TRUE;
+}
+
+\f
+/* Remove any PT_LOAD segments with no allocated sections.  Prior to
+   binutils 2.13, this function used to remove the non-SEC_ALLOC
+   sections from PT_LOAD segments, but that task has now been moved
+   into elf.c.  We still need this function to remove any empty
+   segments that result, but there's nothing Xtensa-specific about
+   this and it probably ought to be moved into elf.c as well.  */
+
+static bfd_boolean
+elf_xtensa_modify_segment_map (abfd)
+     bfd *abfd;
+{
+  struct elf_segment_map **m_p;
+
+  m_p = &elf_tdata (abfd)->segment_map;
+  while (*m_p != NULL)
+    {
+      if ((*m_p)->p_type == PT_LOAD && (*m_p)->count == 0)
+       *m_p = (*m_p)->next;
+      else
+       m_p = &(*m_p)->next;
+    }
+  return TRUE;
+}
+
+\f
+/* Perform the specified relocation.  The instruction at (contents + address)
+   is modified to set one operand to represent the value in "relocation".  The
+   operand position is determined by the relocation type recorded in the
+   howto.  */
+
+#define CALL_SEGMENT_BITS (30)
+#define CALL_SEGMENT_SIZE (1<<CALL_SEGMENT_BITS)
+
+static bfd_reloc_status_type
+elf_xtensa_do_reloc (howto, abfd, input_section, relocation,
+                    contents, address, is_weak_undef, error_message)
+     reloc_howto_type *howto;
+     bfd *abfd;
+     asection *input_section;
+     bfd_vma relocation;
+     bfd_byte *contents;
+     bfd_vma address;
+     bfd_boolean is_weak_undef;
+     char **error_message;
+{
+  xtensa_opcode opcode;
+  xtensa_operand operand;
+  xtensa_encode_result encode_result;
+  xtensa_isa isa = xtensa_default_isa;
+  xtensa_insnbuf ibuff;
+  bfd_vma self_address;
+  int opnd;
+  uint32 newval;
+
+  switch (howto->type)
+    {
+    case R_XTENSA_NONE:
+      return bfd_reloc_ok;
+
+    case R_XTENSA_ASM_EXPAND:
+      if (!is_weak_undef)
+       {
+         /* Check for windowed CALL across a 1GB boundary.  */
+         xtensa_opcode opcode =
+           get_expanded_call_opcode (contents + address,
+                                     input_section->_raw_size - address);
+         if (is_windowed_call_opcode (opcode))
+           {
+             self_address = (input_section->output_section->vma
+                             + input_section->output_offset
+                             + address);
+             if ((self_address >> CALL_SEGMENT_BITS) !=
+                 (relocation >> CALL_SEGMENT_BITS)) 
+               {
+                 *error_message = "windowed longcall crosses 1GB boundary; "
+                   "return may fail";
+                 return bfd_reloc_dangerous;
+               }
+           }
+       }
+      return bfd_reloc_ok;
+
+    case R_XTENSA_ASM_SIMPLIFY:
+      { 
+        /* Convert the L32R/CALLX to CALL.  */
+       bfd_reloc_status_type retval = 
+         elf_xtensa_do_asm_simplify (contents, address,
+                                     input_section->_raw_size);
+       if (retval != bfd_reloc_ok)
+         return retval;
+
+       /* The CALL needs to be relocated.  Continue below for that part.  */
+       address += 3;
+       howto = &elf_howto_table[(unsigned) R_XTENSA_OP0 ];
+      }
+      break;
+
+    case R_XTENSA_32:
+    case R_XTENSA_PLT:
+      {
+       bfd_vma x;
+       x = bfd_get_32 (abfd, contents + address);
+       x = x + relocation;
+       bfd_put_32 (abfd, x, contents + address);
+      }
+      return bfd_reloc_ok;
+    }
+
+  /* Read the instruction into a buffer and decode the opcode.  */
+  ibuff = xtensa_insnbuf_alloc (isa);
+  xtensa_insnbuf_from_chars (isa, ibuff, contents + address);
+  opcode = xtensa_decode_insn (isa, ibuff);
+
+  /* Determine which operand is being relocated.  */
+  if (opcode == XTENSA_UNDEFINED)
+    {
+      *error_message = "cannot decode instruction";
+      return bfd_reloc_dangerous;
+    }
+
+  if (howto->type < R_XTENSA_OP0 || howto->type > R_XTENSA_OP2)
+    {
+      *error_message = "unexpected relocation";
+      return bfd_reloc_dangerous;
+    }
+
+  opnd = howto->type - R_XTENSA_OP0;
+
+  /* Calculate the PC address for this instruction.  */
+  if (!howto->pc_relative)
+    {
+      *error_message = "expected PC-relative relocation";
+      return bfd_reloc_dangerous;
+    }
+
+  self_address = (input_section->output_section->vma
+                 + input_section->output_offset
+                 + address);
+
+  /* Apply the relocation.  */
+  operand = xtensa_get_operand (isa, opcode, opnd);
+  newval = xtensa_operand_do_reloc (operand, relocation, self_address);
+  encode_result = xtensa_operand_encode (operand, &newval);
+  xtensa_operand_set_field (operand, ibuff, newval);
+
+  /* Write the modified instruction back out of the buffer.  */
+  xtensa_insnbuf_to_chars (isa, ibuff, contents + address);
+  free (ibuff);
+
+  if (encode_result != xtensa_encode_result_ok)
+    {
+      char *message = build_encoding_error_message (opcode, encode_result);
+      *error_message = message;
+      return bfd_reloc_dangerous;
+    }
+
+  /* Final check for call.  */
+  if (is_direct_call_opcode (opcode)
+      && is_windowed_call_opcode (opcode))
+    {
+      if ((self_address >> CALL_SEGMENT_BITS) !=
+         (relocation >> CALL_SEGMENT_BITS)) 
+       {
+         *error_message = "windowed call crosses 1GB boundary; "
+           "return may fail";
+         return bfd_reloc_dangerous;
+       }
+    }
+
+  return bfd_reloc_ok;
+}
+
+
+static char *
+vsprint_msg VPARAMS ((const char *origmsg, const char *fmt, int arglen, ...))
+{
+  /* To reduce the size of the memory leak,
+     we only use a single message buffer.  */
+  static bfd_size_type alloc_size = 0;
+  static char *message = NULL;
+  bfd_size_type orig_len, len = 0;
+  bfd_boolean is_append;
+
+  VA_OPEN (ap, arglen);
+  VA_FIXEDARG (ap, const char *, origmsg);
+  
+  is_append = (origmsg == message);  
+
+  orig_len = strlen (origmsg);
+  len = orig_len + strlen (fmt) + arglen + 20;
+  if (len > alloc_size)
+    {
+      message = (char *) bfd_realloc (message, len);
+      alloc_size = len;
+    }
+  if (!is_append)
+    memcpy (message, origmsg, orig_len);
+  vsprintf (message + orig_len, fmt, ap);
+  VA_CLOSE (ap);
+  return message;
+}
+
+
+static char *
+build_encoding_error_message (opcode, encode_result)
+     xtensa_opcode opcode;
+     xtensa_encode_result encode_result;
+{
+  const char *opname = xtensa_opcode_name (xtensa_default_isa, opcode);
+  const char *msg = NULL;
+
+  switch (encode_result)
+    {
+    case xtensa_encode_result_ok:
+      msg = "unexpected valid encoding";
+      break;
+    case xtensa_encode_result_align:
+      msg = "misaligned encoding";
+      break;
+    case xtensa_encode_result_not_in_table:
+      msg = "encoding not in lookup table";
+      break;
+    case xtensa_encode_result_too_low:
+      msg = "encoding out of range: too low";
+      break;
+    case xtensa_encode_result_too_high:
+      msg = "encoding out of range: too high";
+      break;
+    case xtensa_encode_result_not_ok:
+    default:
+      msg = "could not encode";
+      break;
+    }
+
+  if (is_direct_call_opcode (opcode)
+      && (encode_result == xtensa_encode_result_too_low
+         || encode_result == xtensa_encode_result_too_high))
+
+    msg = "direct call out of range";
+
+  else if (opcode == get_l32r_opcode ()) 
+    {
+      /* L32Rs have the strange interaction with encoding in that they
+         have an unsigned immediate field, so libisa returns "too high"
+         when the absolute value is out of range and never returns "too
+         low", but I leave the "too low" message in case anything
+         changes.  */
+      if (encode_result == xtensa_encode_result_too_low)
+       msg = "literal out of range";
+      else if (encode_result == xtensa_encode_result_too_high)
+       msg = "literal placed after use";
+    }
+  
+  return vsprint_msg (opname, ": %s", strlen (msg) + 2, msg);
+}
+
+
+/* This function is registered as the "special_function" in the
+   Xtensa howto for handling simplify operations.
+   bfd_perform_relocation / bfd_install_relocation use it to
+   perform (install) the specified relocation.  Since this replaces the code
+   in bfd_perform_relocation, it is basically an Xtensa-specific,
+   stripped-down version of bfd_perform_relocation.  */
+
+static bfd_reloc_status_type
+bfd_elf_xtensa_reloc (abfd, reloc_entry, symbol, data, input_section,
+                     output_bfd, error_message)
+     bfd *abfd;
+     arelent *reloc_entry;
+     asymbol *symbol;
+     PTR data;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message;
+{
+  bfd_vma relocation;
+  bfd_reloc_status_type flag;
+  bfd_size_type octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  bfd_vma output_base = 0;
+  reloc_howto_type *howto = reloc_entry->howto;
+  asection *reloc_target_output_section;
+  bfd_boolean is_weak_undef;
+
+  /* ELF relocs are against symbols.  If we are producing relocateable
+     output, and the reloc is against an external symbol, the resulting
+     reloc will also be against the same symbol.  In such a case, we
+     don't want to change anything about the way the reloc is handled,
+     since it will all be done at final link time.  This test is similar
+     to what bfd_elf_generic_reloc does except that it lets relocs with
+     howto->partial_inplace go through even if the addend is non-zero.
+     (The real problem is that partial_inplace is set for XTENSA_32
+     relocs to begin with, but that's a long story and there's little we
+     can do about it now....)  */
+
+  if (output_bfd != (bfd *) NULL
+      && (symbol->flags & BSF_SECTION_SYM) == 0)
+    {
+      reloc_entry->address += input_section->output_offset;
+      return bfd_reloc_ok;
+    }
+
+  /* Is the address of the relocation really within the section?  */
+  if (reloc_entry->address > (input_section->_cooked_size
+                             / bfd_octets_per_byte (abfd)))
+    return bfd_reloc_outofrange;
+
+  /* Work out which section the relocation is targetted at and the
+     initial relocation command value.  */
+
+  /* Get symbol value.  (Common symbols are special.)  */
+  if (bfd_is_com_section (symbol->section))
+    relocation = 0;
+  else
+    relocation = symbol->value;
+
+  reloc_target_output_section = symbol->section->output_section;
+
+  /* Convert input-section-relative symbol value to absolute.  */
+  if ((output_bfd && !howto->partial_inplace)
+      || reloc_target_output_section == NULL)
+    output_base = 0;
+  else
+    output_base = reloc_target_output_section->vma;
+
+  relocation += output_base + symbol->section->output_offset;
+
+  /* Add in supplied addend.  */
+  relocation += reloc_entry->addend;
+
+  /* Here the variable relocation holds the final address of the
+     symbol we are relocating against, plus any addend.  */
+  if (output_bfd)
+    {
+      if (!howto->partial_inplace)
+       {
+         /* This is a partial relocation, and we want to apply the relocation
+            to the reloc entry rather than the raw data.  Everything except
+            relocations against section symbols has already been handled
+            above.  */
+         
+         BFD_ASSERT (symbol->flags & BSF_SECTION_SYM);
+         reloc_entry->addend = relocation;
+         reloc_entry->address += input_section->output_offset;
+         return bfd_reloc_ok;
+       }
+      else
+       {
+         reloc_entry->address += input_section->output_offset;
+         reloc_entry->addend = 0;
+       }
+    }
+
+  is_weak_undef = (bfd_is_und_section (symbol->section)
+                  && (symbol->flags & BSF_WEAK) != 0);
+  flag = elf_xtensa_do_reloc (howto, abfd, input_section, relocation,
+                             (bfd_byte *) data, (bfd_vma) octets,
+                             is_weak_undef, error_message);
+
+  if (flag == bfd_reloc_dangerous)
+    {
+      /* Add the symbol name to the error message.  */
+      if (! *error_message)
+       *error_message = "";
+      *error_message = vsprint_msg (*error_message, ": (%s + 0x%lx)",
+                                   strlen (symbol->name) + 17,
+                                   symbol->name, reloc_entry->addend);
+    }
+
+  return flag;
+}
+
+
+/* Set up an entry in the procedure linkage table.  */
+
+static bfd_vma
+elf_xtensa_create_plt_entry (dynobj, output_bfd, reloc_index)
+      bfd *dynobj;
+      bfd *output_bfd;
+      unsigned reloc_index;
+{
+  asection *splt, *sgotplt;
+  bfd_vma plt_base, got_base;
+  bfd_vma code_offset, lit_offset;
+  int chunk;
+
+  chunk = reloc_index / PLT_ENTRIES_PER_CHUNK;
+  splt = elf_xtensa_get_plt_section (dynobj, chunk);
+  sgotplt = elf_xtensa_get_gotplt_section (dynobj, chunk);
+  BFD_ASSERT (splt != NULL && sgotplt != NULL);
+
+  plt_base = splt->output_section->vma + splt->output_offset;
+  got_base = sgotplt->output_section->vma + sgotplt->output_offset;
+
+  lit_offset = 8 + (reloc_index % PLT_ENTRIES_PER_CHUNK) * 4;
+  code_offset = (reloc_index % PLT_ENTRIES_PER_CHUNK) * PLT_ENTRY_SIZE;
+
+  /* Fill in the literal entry.  This is the offset of the dynamic
+     relocation entry.  */
+  bfd_put_32 (output_bfd, reloc_index * sizeof (Elf32_External_Rela),
+             sgotplt->contents + lit_offset);
+
+  /* Fill in the entry in the procedure linkage table.  */
+  memcpy (splt->contents + code_offset,
+         (bfd_big_endian (output_bfd)
+          ? elf_xtensa_be_plt_entry
+          : elf_xtensa_le_plt_entry),
+         PLT_ENTRY_SIZE);
+  bfd_put_16 (output_bfd, l32r_offset (got_base + 0,
+                                      plt_base + code_offset + 3),
+             splt->contents + code_offset + 4);
+  bfd_put_16 (output_bfd, l32r_offset (got_base + 4,
+                                      plt_base + code_offset + 6),
+             splt->contents + code_offset + 7);
+  bfd_put_16 (output_bfd, l32r_offset (got_base + lit_offset,
+                                      plt_base + code_offset + 9),
+             splt->contents + code_offset + 10);
+
+  return plt_base + code_offset;
+}
+
+
+static bfd_boolean
+xtensa_elf_dynamic_symbol_p (info, h)
+     struct bfd_link_info *info;
+     struct elf_link_hash_entry *h;
+{
+  if (h == NULL)
+    return FALSE;
+
+  while (h->root.type == bfd_link_hash_indirect
+        || h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+  if (h->dynindx == -1)
+    return FALSE;
+
+  if (h->root.type == bfd_link_hash_undefweak
+      || h->root.type == bfd_link_hash_defweak)
+    return TRUE;
+
+  switch (ELF_ST_VISIBILITY (h->other))
+    {
+    case STV_DEFAULT:
+      break;
+    case STV_HIDDEN:
+    case STV_INTERNAL:
+      return FALSE;
+    case STV_PROTECTED:
+      if (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
+        return FALSE;
+      break;
+    }
+
+  if ((info->shared && !info->symbolic)
+      || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+    return TRUE;
+
+  return FALSE;
+}
+
+
+/* Relocate an Xtensa ELF section.  This is invoked by the linker for
+   both relocateable and final links.  */
+
+static bfd_boolean
+elf_xtensa_relocate_section (output_bfd, info, input_bfd,
+                            input_section, contents, relocs,
+                            local_syms, local_sections)
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+     bfd *input_bfd;
+     asection *input_section;
+     bfd_byte *contents;
+     Elf_Internal_Rela *relocs;
+     Elf_Internal_Sym *local_syms;
+     asection **local_sections;
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Rela *rel;
+  Elf_Internal_Rela *relend;
+  struct elf_link_hash_entry **sym_hashes;
+  asection *srelgot, *srelplt;
+  bfd *dynobj;
+  char *error_message = NULL;
+
+  if (xtensa_default_isa == NULL)
+    xtensa_isa_init ();
+
+  dynobj = elf_hash_table (info)->dynobj;
+  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (input_bfd);
+
+  srelgot = NULL;
+  srelplt = NULL;
+  if (dynobj != NULL)
+    {
+      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");;
+      srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
+    }
+
+  rel = relocs;
+  relend = relocs + input_section->reloc_count;
+  for (; rel < relend; rel++)
+    {
+      int r_type;
+      reloc_howto_type *howto;
+      unsigned long r_symndx;
+      struct elf_link_hash_entry *h;
+      Elf_Internal_Sym *sym;
+      asection *sec;
+      bfd_vma relocation;
+      bfd_reloc_status_type r;
+      bfd_boolean is_weak_undef;
+      bfd_boolean unresolved_reloc;
+      bfd_boolean warned;
+
+      r_type = ELF32_R_TYPE (rel->r_info);
+      if (r_type == (int) R_XTENSA_GNU_VTINHERIT
+         || r_type == (int) R_XTENSA_GNU_VTENTRY)
+       continue;
+
+      if (r_type < 0 || r_type >= (int) R_XTENSA_max)
+       {
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
+      howto = &elf_howto_table[r_type];
+
+      r_symndx = ELF32_R_SYM (rel->r_info);
+
+      if (info->relocateable)
+       {
+         /* This is a relocateable link. 
+            1) If the reloc is against a section symbol, adjust
+            according to the output section.
+            2) If there is a new target for this relocation,
+            the new target will be in the same output section.
+            We adjust the relocation by the output section
+            difference.  */
+
+         if (relaxing_section)
+           {
+             /* Check if this references a section in another input file.  */
+             do_fix_for_relocateable_link (rel, input_bfd, input_section);
+             r_type = ELF32_R_TYPE (rel->r_info);
+           }
+
+         if (r_type == R_XTENSA_ASM_SIMPLIFY) 
+           {
+             /* Convert ASM_SIMPLIFY into the simpler relocation
+                so that they never escape a relaxing link.  */
+             contract_asm_expansion (contents, input_section->_raw_size, rel);
+             r_type = ELF32_R_TYPE (rel->r_info);
+           }
+
+         /* This is a relocateable link, so we don't have to change
+            anything unless the reloc is against a section symbol,
+            in which case we have to adjust according to where the
+            section symbol winds up in the output section.  */
+         if (r_symndx < symtab_hdr->sh_info)
+           {
+             sym = local_syms + r_symndx;
+             if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+               {
+                 sec = local_sections[r_symndx];
+                 rel->r_addend += sec->output_offset + sym->st_value;
+               }
+           }
+
+         /* If there is an addend with a partial_inplace howto,
+            then move the addend to the contents.  This is a hack
+            to work around problems with DWARF in relocateable links
+            with some previous version of BFD.  Now we can't easily get
+            rid of the hack without breaking backward compatibility.... */
+         if (rel->r_addend)
+           {
+             howto = &elf_howto_table[r_type];
+             if (howto->partial_inplace)
+               {
+                 r = elf_xtensa_do_reloc (howto, input_bfd, input_section,
+                                          rel->r_addend, contents,
+                                          rel->r_offset, FALSE,
+                                          &error_message);
+                 if (r != bfd_reloc_ok)
+                   {
+                     if (!((*info->callbacks->reloc_dangerous)
+                           (info, error_message, input_bfd, input_section,
+                            rel->r_offset)))
+                       return FALSE;
+                   }
+                 rel->r_addend = 0;
+               }
+           }
+
+         /* Done with work for relocateable link; continue with next reloc.  */
+         continue;
+       }
+
+      /* This is a final link.  */
+
+      h = NULL;
+      sym = NULL;
+      sec = NULL;
+      is_weak_undef = FALSE;
+      unresolved_reloc = FALSE;
+      warned = FALSE;
+
+      if (howto->partial_inplace)
+       {
+         /* Because R_XTENSA_32 was made partial_inplace to fix some
+            problems with DWARF info in partial links, there may be
+            an addend stored in the contents.  Take it out of there
+            and move it back into the addend field of the reloc.  */
+         rel->r_addend += bfd_get_32 (input_bfd, contents + rel->r_offset);
+         bfd_put_32 (input_bfd, 0, contents + rel->r_offset);
+       }
+
+      if (r_symndx < symtab_hdr->sh_info)
+       {
+         sym = local_syms + r_symndx;
+         sec = local_sections[r_symndx];
+         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
+       }
+      else
+       {
+         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+         while (h->root.type == bfd_link_hash_indirect
+                || h->root.type == bfd_link_hash_warning)
+           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+         relocation = 0;
+         if (h->root.type == bfd_link_hash_defined
+             || h->root.type == bfd_link_hash_defweak)
+           {
+             sec = h->root.u.def.section;
+
+             if (sec->output_section == NULL)
+               /* Set a flag that will be cleared later if we find a
+                  relocation value for this symbol.  output_section
+                  is typically NULL for symbols satisfied by a shared
+                  library.  */
+               unresolved_reloc = TRUE;
+             else
+               relocation = (h->root.u.def.value
+                             + sec->output_section->vma
+                             + sec->output_offset);
+           }
+         else if (h->root.type == bfd_link_hash_undefweak)
+           is_weak_undef = TRUE;
+         else if (info->shared
+                  && !info->no_undefined
+                  && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
+           ;
+         else
+           {
+             if (! ((*info->callbacks->undefined_symbol)
+                    (info, h->root.root.string, input_bfd,
+                     input_section, rel->r_offset,
+                     (!info->shared || info->no_undefined
+                      || ELF_ST_VISIBILITY (h->other)))))
+               return FALSE;
+             warned = TRUE;
+           }
+       }
+
+      if (relaxing_section)
+       {
+         /* Check if this references a section in another input file.  */
+         do_fix_for_final_link (rel, input_section, &relocation);
+
+         /* Update some already cached values.  */
+         r_type = ELF32_R_TYPE (rel->r_info);
+         howto = &elf_howto_table[r_type];
+       }
+
+      /* Sanity check the address.  */
+      if (rel->r_offset >= input_section->_raw_size
+         && ELF32_R_TYPE (rel->r_info) != R_XTENSA_NONE)
+       {
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
+
+      /* Generate dynamic relocations.  */
+      if (elf_hash_table (info)->dynamic_sections_created)
+       {
+         bfd_boolean dynamic_symbol = xtensa_elf_dynamic_symbol_p (info, h);
+
+         if (dynamic_symbol && (r_type == R_XTENSA_OP0
+                                || r_type == R_XTENSA_OP1
+                                || r_type == R_XTENSA_OP2))
+           {
+             /* This is an error.  The symbol's real value won't be known
+                until runtime and it's likely to be out of range anyway.  */
+             const char *name = h->root.root.string;
+             error_message = vsprint_msg ("invalid relocation for dynamic "
+                                          "symbol", ": %s",
+                                          strlen (name) + 2, name);
+             if (!((*info->callbacks->reloc_dangerous)
+                   (info, error_message, input_bfd, input_section,
+                    rel->r_offset)))
+               return FALSE;
+           }
+         else if ((r_type == R_XTENSA_32 || r_type == R_XTENSA_PLT)
+                  && (input_section->flags & SEC_ALLOC) != 0
+                  && (dynamic_symbol || info->shared))
+           {
+             Elf_Internal_Rela outrel;
+             bfd_byte *loc;
+             asection *srel;
+
+             if (dynamic_symbol && r_type == R_XTENSA_PLT)
+               srel = srelplt;
+             else
+               srel = srelgot;
+
+             BFD_ASSERT (srel != NULL);
+
+             outrel.r_offset =
+               _bfd_elf_section_offset (output_bfd, info,
+                                        input_section, rel->r_offset);
+
+             if ((outrel.r_offset | 1) == (bfd_vma) -1)
+               memset (&outrel, 0, sizeof outrel);
+             else
+               {
+                 outrel.r_offset = (input_section->output_section->vma
+                                    + input_section->output_offset);
+
+                 if (dynamic_symbol)
+                   {
+                     outrel.r_addend = rel->r_addend;
+                     rel->r_addend = 0;
+
+                     if (r_type == R_XTENSA_32)
+                       {
+                         outrel.r_info =
+                           ELF32_R_INFO (h->dynindx, R_XTENSA_GLOB_DAT);
+                         relocation = 0;
+                       }
+                     else /* r_type == R_XTENSA_PLT */
+                       {
+                         outrel.r_info =
+                           ELF32_R_INFO (h->dynindx, R_XTENSA_JMP_SLOT);
+
+                         /* Create the PLT entry and set the initial
+                            contents of the literal entry to the address of
+                            the PLT entry.  */
+                         relocation = 
+                           elf_xtensa_create_plt_entry (dynobj, output_bfd,
+                                                        srel->reloc_count);
+                       }
+                     unresolved_reloc = FALSE;
+                   }
+                 else
+                   {
+                     /* Generate a RELATIVE relocation.  */
+                     outrel.r_info = ELF32_R_INFO (0, R_XTENSA_RELATIVE);
+                     outrel.r_addend = 0;
+                   }
+               }
+
+             loc = (srel->contents
+                    + srel->reloc_count++ * sizeof (Elf32_External_Rela));
+             bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
+             BFD_ASSERT (sizeof (Elf32_External_Rela) * srel->reloc_count
+                         <= srel->_cooked_size);
+           }
+       }
+
+      /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
+        because such sections are not SEC_ALLOC and thus ld.so will
+        not process them.  */
+      if (unresolved_reloc
+         && !((input_section->flags & SEC_DEBUGGING) != 0
+              && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0))
+       (*_bfd_error_handler)
+         (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"),
+          bfd_archive_filename (input_bfd),
+          bfd_get_section_name (input_bfd, input_section),
+          (long) rel->r_offset,
+          h->root.root.string);
+
+      /* There's no point in calling bfd_perform_relocation here.
+        Just go directly to our "special function".  */
+      r = elf_xtensa_do_reloc (howto, input_bfd, input_section,
+                              relocation + rel->r_addend,
+                              contents, rel->r_offset, is_weak_undef,
+                              &error_message);
+      
+      if (r != bfd_reloc_ok && !warned)
+       {
+         const char *name;
+
+         BFD_ASSERT (r == bfd_reloc_dangerous);
+         BFD_ASSERT (error_message != (char *) NULL);
+
+         if (h != NULL)
+           name = h->root.root.string;
+         else
+           {
+             name = bfd_elf_string_from_elf_section
+               (input_bfd, symtab_hdr->sh_link, sym->st_name);
+             if (name && *name == '\0')
+               name = bfd_section_name (input_bfd, sec);
+           }
+         if (name)
+           error_message = vsprint_msg (error_message, ": %s",
+                                        strlen (name), name);
+         if (!((*info->callbacks->reloc_dangerous)
+               (info, error_message, input_bfd, input_section,
+                rel->r_offset)))
+           return FALSE;
+       }
+    }
+
+  return TRUE;
+}
+
+
+/* Finish up dynamic symbol handling.  There's not much to do here since
+   the PLT and GOT entries are all set up by relocate_section.  */
+
+static bfd_boolean
+elf_xtensa_finish_dynamic_symbol (output_bfd, info, h, sym)
+     bfd *output_bfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     struct elf_link_hash_entry *h;
+     Elf_Internal_Sym *sym;
+{
+  if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
+      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+    {
+      /* Mark the symbol as undefined, rather than as defined in
+        the .plt section.  Leave the value alone.  */
+      sym->st_shndx = SHN_UNDEF;
+    }
+
+  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
+  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+    sym->st_shndx = SHN_ABS;
+
+  return TRUE;
+}
+
+
+/* Combine adjacent literal table entries in the output.  Adjacent
+   entries within each input section may have been removed during
+   relaxation, but we repeat the process here, even though it's too late
+   to shrink the output section, because it's important to minimize the
+   number of literal table entries to reduce the start-up work for the
+   runtime linker.  Returns the number of remaining table entries or -1
+   on error.  */
+
+static int
+elf_xtensa_combine_prop_entries (output_bfd, secname)
+     bfd *output_bfd;
+     const char *secname;
+{
+  asection *sec;
+  bfd_byte *contents;
+  property_table_entry *table;
+  bfd_size_type section_size;
+  bfd_vma offset;
+  int n, m, num;
+
+  sec = bfd_get_section_by_name (output_bfd, secname);
+  if (!sec)
+    return -1;
+
+  section_size = (sec->_cooked_size != 0 ? sec->_cooked_size : sec->_raw_size);
+  BFD_ASSERT (section_size % 8 == 0);
+  num = section_size / 8;
+
+  contents = (bfd_byte *) bfd_malloc (section_size);
+  table = (property_table_entry *)
+    bfd_malloc (num * sizeof (property_table_entry));
+  if (contents == 0 || table == 0)
+    return -1;
+
+  /* The ".xt.lit.plt" section has the SEC_IN_MEMORY flag set and this
+     propagates to the output section, where it doesn't really apply and
+     where it breaks the following call to bfd_get_section_contents.  */
+  sec->flags &= ~SEC_IN_MEMORY;
+
+  if (! bfd_get_section_contents (output_bfd, sec, contents, 0, section_size))
+    return -1;
+
+  /* There should never be any relocations left at this point, so this
+     is quite a bit easier than what is done during relaxation.  */
+
+  /* Copy the raw contents into a property table array and sort it.  */
+  offset = 0;
+  for (n = 0; n < num; n++)
+    {
+      table[n].address = bfd_get_32 (output_bfd, &contents[offset]);
+      table[n].size = bfd_get_32 (output_bfd, &contents[offset + 4]);
+      offset += 8;
+    }
+  qsort (table, num, sizeof (property_table_entry), property_table_compare);
+
+  for (n = 0; n < num; n++)
+    {
+      bfd_boolean remove = FALSE;
+
+      if (table[n].size == 0)
+       remove = TRUE;
+      else if (n > 0 &&
+              (table[n-1].address + table[n-1].size == table[n].address))
+       {
+         table[n-1].size += table[n].size;
+         remove = TRUE;
+       }
+
+      if (remove)
+       {
+         for (m = n; m < num - 1; m++)
+           {
+             table[m].address = table[m+1].address;
+             table[m].size = table[m+1].size;
+           }
+
+         n--;
+         num--;
+       }
+    }
+
+  /* Copy the data back to the raw contents.  */
+  offset = 0;
+  for (n = 0; n < num; n++)
+    {
+      bfd_put_32 (output_bfd, table[n].address, &contents[offset]);
+      bfd_put_32 (output_bfd, table[n].size, &contents[offset + 4]);
+      offset += 8;
+    }
+
+  /* Clear the removed bytes.  */
+  if ((bfd_size_type) (num * 8) < section_size)
+    {
+      memset (&contents[num * 8], 0, section_size - num * 8);
+      sec->_cooked_size = num * 8;
+    }
+
+  if (! bfd_set_section_contents (output_bfd, sec, contents, 0, section_size))
+    return -1;
+
+  free (contents);
+  return num;
+}
+
+
+/* Finish up the dynamic sections.  */
+
+static bfd_boolean
+elf_xtensa_finish_dynamic_sections (output_bfd, info)
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+{
+  bfd *dynobj;
+  asection *sdyn, *srelplt, *sgot;
+  Elf32_External_Dyn *dyncon, *dynconend;
+  int num_xtlit_entries;
+
+  if (! elf_hash_table (info)->dynamic_sections_created)
+    return TRUE;
+
+  dynobj = elf_hash_table (info)->dynobj;
+  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  BFD_ASSERT (sdyn != NULL);
+
+  /* Set the first entry in the global offset table to the address of
+     the dynamic section.  */
+  sgot = bfd_get_section_by_name (dynobj, ".got");
+  if (sgot)
+    {
+      BFD_ASSERT (sgot->_raw_size == 4);
+      if (sdyn == NULL)
+       bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
+      else
+       bfd_put_32 (output_bfd,
+                   sdyn->output_section->vma + sdyn->output_offset,
+                   sgot->contents);
+    }
+
+  srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
+  if (srelplt != NULL && srelplt->_raw_size != 0)
+    {
+      asection *sgotplt, *srelgot, *spltlittbl;
+      int chunk, plt_chunks, plt_entries;
+      Elf_Internal_Rela irela;
+      bfd_byte *loc;
+      unsigned rtld_reloc;
+
+      srelgot = bfd_get_section_by_name (dynobj, ".rela.got");;
+      BFD_ASSERT (srelgot != NULL);
+
+      spltlittbl = bfd_get_section_by_name (dynobj, ".xt.lit.plt");
+      BFD_ASSERT (spltlittbl != NULL);
+
+      /* Find the first XTENSA_RTLD relocation.  Presumably the rest
+        of them follow immediately after....  */
+      for (rtld_reloc = 0; rtld_reloc < srelgot->reloc_count; rtld_reloc++)
+       {
+         loc = srelgot->contents + rtld_reloc * sizeof (Elf32_External_Rela);
+         bfd_elf32_swap_reloca_in (output_bfd, loc, &irela);
+         if (ELF32_R_TYPE (irela.r_info) == R_XTENSA_RTLD)
+           break;
+       }
+      BFD_ASSERT (rtld_reloc < srelgot->reloc_count);
+
+      plt_entries = (srelplt->_raw_size / sizeof (Elf32_External_Rela));
+      plt_chunks =
+       (plt_entries + PLT_ENTRIES_PER_CHUNK - 1) / PLT_ENTRIES_PER_CHUNK;
+
+      for (chunk = 0; chunk < plt_chunks; chunk++)
+       {
+         int chunk_entries = 0;
+
+         sgotplt = elf_xtensa_get_gotplt_section (dynobj, chunk);
+         BFD_ASSERT (sgotplt != NULL);
+
+         /* Emit special RTLD relocations for the first two entries in
+            each chunk of the .got.plt section.  */
+
+         loc = srelgot->contents + rtld_reloc * sizeof (Elf32_External_Rela);
+         bfd_elf32_swap_reloca_in (output_bfd, loc, &irela);
+         BFD_ASSERT (ELF32_R_TYPE (irela.r_info) == R_XTENSA_RTLD);
+         irela.r_offset = (sgotplt->output_section->vma
+                           + sgotplt->output_offset);
+         irela.r_addend = 1; /* tell rtld to set value to resolver function */
+         bfd_elf32_swap_reloca_out (output_bfd, &irela, loc);
+         rtld_reloc += 1;
+         BFD_ASSERT (rtld_reloc <= srelgot->reloc_count);
+
+         /* Next literal immediately follows the first.  */
+         loc += sizeof (Elf32_External_Rela);
+         bfd_elf32_swap_reloca_in (output_bfd, loc, &irela);
+         BFD_ASSERT (ELF32_R_TYPE (irela.r_info) == R_XTENSA_RTLD);
+         irela.r_offset = (sgotplt->output_section->vma
+                           + sgotplt->output_offset + 4);
+         /* Tell rtld to set value to object's link map.  */
+         irela.r_addend = 2;
+         bfd_elf32_swap_reloca_out (output_bfd, &irela, loc);
+         rtld_reloc += 1;
+         BFD_ASSERT (rtld_reloc <= srelgot->reloc_count);
+
+         /* Fill in the literal table.  */
+         if (chunk < plt_chunks - 1)
+           chunk_entries = PLT_ENTRIES_PER_CHUNK;
+         else
+           chunk_entries = plt_entries - (chunk * PLT_ENTRIES_PER_CHUNK);
+
+         BFD_ASSERT ((unsigned) (chunk + 1) * 8 <= spltlittbl->_cooked_size);
+         bfd_put_32 (output_bfd,
+                     sgotplt->output_section->vma + sgotplt->output_offset,
+                     spltlittbl->contents + (chunk * 8) + 0);
+         bfd_put_32 (output_bfd,
+                     8 + (chunk_entries * 4),
+                     spltlittbl->contents + (chunk * 8) + 4);
+       }
+
+      /* All the dynamic relocations have been emitted at this point.
+        Make sure the relocation sections are the correct size.  */
+      if (srelgot->_cooked_size != (sizeof (Elf32_External_Rela)
+                                   * srelgot->reloc_count)
+         || srelplt->_cooked_size != (sizeof (Elf32_External_Rela)
+                                      * srelplt->reloc_count))
+       abort ();
+
+     /* The .xt.lit.plt section has just been modified.  This must
+       happen before the code below which combines adjacent literal
+       table entries, and the .xt.lit.plt contents have to be forced to
+       the output here.  */
+      if (! bfd_set_section_contents (output_bfd,
+                                     spltlittbl->output_section,
+                                     spltlittbl->contents,
+                                     spltlittbl->output_offset,
+                                     spltlittbl->_raw_size))
+       return FALSE;
+      /* Clear SEC_HAS_CONTENTS so the contents won't be output again.  */
+      spltlittbl->flags &= ~SEC_HAS_CONTENTS;
+    }
+
+  /* Combine adjacent literal table entries.  */
+  BFD_ASSERT (! info->relocateable);
+  num_xtlit_entries = elf_xtensa_combine_prop_entries (output_bfd, ".xt.lit");
+  if (num_xtlit_entries < 0)
+    return FALSE;
+
+  dyncon = (Elf32_External_Dyn *) sdyn->contents;
+  dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+  for (; dyncon < dynconend; dyncon++)
+    {
+      Elf_Internal_Dyn dyn;
+      const char *name;
+      asection *s;
+
+      bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
+
+      switch (dyn.d_tag)
+       {
+       default:
+         break;
+
+       case DT_XTENSA_GOT_LOC_SZ:
+         s = bfd_get_section_by_name (output_bfd, ".xt.lit");
+         BFD_ASSERT (s);
+         dyn.d_un.d_val = num_xtlit_entries;
+         break;
+
+       case DT_XTENSA_GOT_LOC_OFF:
+         name = ".xt.lit";
+         goto get_vma;
+       case DT_PLTGOT:
+         name = ".got";
+         goto get_vma;
+       case DT_JMPREL:
+         name = ".rela.plt";
+       get_vma:
+         s = bfd_get_section_by_name (output_bfd, name);
+         BFD_ASSERT (s);
+         dyn.d_un.d_ptr = s->vma;
+         break;
+
+       case DT_PLTRELSZ:
+         s = bfd_get_section_by_name (output_bfd, ".rela.plt");
+         BFD_ASSERT (s);
+         dyn.d_un.d_val = (s->_cooked_size ? s->_cooked_size : s->_raw_size);
+         break;
+
+       case DT_RELASZ:
+         /* Adjust RELASZ to not include JMPREL.  This matches what
+            glibc expects and what is done for several other ELF
+            targets (e.g., i386, alpha), but the "correct" behavior
+            seems to be unresolved.  Since the linker script arranges
+            for .rela.plt to follow all other relocation sections, we
+            don't have to worry about changing the DT_RELA entry.  */
+         s = bfd_get_section_by_name (output_bfd, ".rela.plt");
+         if (s)
+           {
+             dyn.d_un.d_val -=
+               (s->_cooked_size ? s->_cooked_size : s->_raw_size);
+           }
+         break;
+       }
+
+      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+    }
+
+  return TRUE;
+}
+
+\f
+/* Functions for dealing with the e_flags field.  */
+
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+static bfd_boolean
+elf_xtensa_merge_private_bfd_data (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  unsigned out_mach, in_mach;
+  flagword out_flag, in_flag;
+
+  /* Check if we have the same endianess.  */
+  if (!_bfd_generic_verify_endian_match (ibfd, obfd))
+    return FALSE;
+
+  /* Don't even pretend to support mixed-format linking.  */
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return FALSE;
+
+  out_flag = elf_elfheader (obfd)->e_flags;
+  in_flag = elf_elfheader (ibfd)->e_flags;
+
+  out_mach = out_flag & EF_XTENSA_MACH;
+  in_mach = in_flag & EF_XTENSA_MACH;
+  if (out_mach != in_mach) 
+    {
+      (*_bfd_error_handler)
+       ("%s: incompatible machine type. Output is 0x%x. Input is 0x%x\n",
+        bfd_archive_filename (ibfd), out_mach, in_mach);
+      bfd_set_error (bfd_error_wrong_format);
+      return FALSE;
+    }
+
+  if (! elf_flags_init (obfd))
+    {
+      elf_flags_init (obfd) = TRUE;
+      elf_elfheader (obfd)->e_flags = in_flag;
+      
+      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
+         && bfd_get_arch_info (obfd)->the_default)
+       return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
+                                 bfd_get_mach (ibfd));
+      
+      return TRUE;
+    }
+
+  if ((out_flag & EF_XTENSA_XT_INSN) !=
+      (in_flag & EF_XTENSA_XT_INSN)) 
+    elf_elfheader(obfd)->e_flags &= (~ EF_XTENSA_XT_INSN);
+
+  if ((out_flag & EF_XTENSA_XT_LIT) !=
+      (in_flag & EF_XTENSA_XT_LIT)) 
+    elf_elfheader(obfd)->e_flags &= (~ EF_XTENSA_XT_LIT);
+
+  return TRUE;
+}
+
+
+static bfd_boolean
+elf_xtensa_set_private_flags (abfd, flags)
+     bfd *abfd;
+     flagword flags;
+{
+  BFD_ASSERT (!elf_flags_init (abfd)
+             || elf_elfheader (abfd)->e_flags == flags);
+
+  elf_elfheader (abfd)->e_flags |= flags;
+  elf_flags_init (abfd) = TRUE;
+
+  return TRUE;
+}
+
+
+extern flagword
+elf_xtensa_get_private_bfd_flags (abfd)
+     bfd *abfd;
+{
+  return elf_elfheader (abfd)->e_flags;
+}
+
+
+static bfd_boolean
+elf_xtensa_print_private_bfd_data (abfd, farg)
+     bfd *abfd;
+     PTR farg;
+{
+  FILE *f = (FILE *) farg;
+  flagword e_flags = elf_elfheader (abfd)->e_flags;
+
+  fprintf (f, "\nXtensa header:\n");
+  if ((e_flags & EF_XTENSA_MACH) == E_XTENSA_MACH) 
+    fprintf (f, "\nMachine     = Base\n");
+  else
+    fprintf (f, "\nMachine Id  = 0x%x\n", e_flags & EF_XTENSA_MACH);
+
+  fprintf (f, "Insn tables = %s\n",
+          (e_flags & EF_XTENSA_XT_INSN) ? "true" : "false");
+
+  fprintf (f, "Literal tables = %s\n",
+          (e_flags & EF_XTENSA_XT_LIT) ? "true" : "false");
+
+  return _bfd_elf_print_private_bfd_data (abfd, farg);
+}
+
+
+/* Set the right machine number for an Xtensa ELF file.  */
+
+static bfd_boolean
+elf_xtensa_object_p (abfd)
+     bfd *abfd;
+{
+  int mach;
+  unsigned long arch = elf_elfheader (abfd)->e_flags & EF_XTENSA_MACH;
+
+  switch (arch)
+    {
+    case E_XTENSA_MACH:
+      mach = bfd_mach_xtensa;
+      break;
+    default:
+      return FALSE;
+    }
+
+  (void) bfd_default_set_arch_mach (abfd, bfd_arch_xtensa, mach);
+  return TRUE;
+}
+
+
+/* The final processing done just before writing out an Xtensa ELF object
+   file.  This gets the Xtensa architecture right based on the machine
+   number.  */
+
+static void
+elf_xtensa_final_write_processing (abfd, linker)
+     bfd *abfd;
+     bfd_boolean linker ATTRIBUTE_UNUSED;
+{
+  int mach;
+  unsigned long val;
+
+  switch (mach = bfd_get_mach (abfd))
+    {
+    case bfd_mach_xtensa:
+      val = E_XTENSA_MACH;
+      break;
+    default:
+      return;
+    }
+
+  elf_elfheader (abfd)->e_flags &=  (~ EF_XTENSA_MACH);
+  elf_elfheader (abfd)->e_flags |= val;
+}
+
+
+static enum elf_reloc_type_class
+elf_xtensa_reloc_type_class (rela)
+     const Elf_Internal_Rela *rela;
+{
+  switch ((int) ELF32_R_TYPE (rela->r_info))
+    {
+    case R_XTENSA_RELATIVE:
+      return reloc_class_relative;
+    case R_XTENSA_JMP_SLOT:
+      return reloc_class_plt;
+    default:
+      return reloc_class_normal;
+    }
+}
+
+\f
+static bfd_boolean
+elf_xtensa_discard_info_for_section (abfd, cookie, info, sec)
+     bfd *abfd;
+     struct elf_reloc_cookie *cookie;
+     struct bfd_link_info *info;
+     asection *sec;
+{
+  bfd_byte *contents;
+  bfd_vma section_size;
+  bfd_vma offset, actual_offset;
+  size_t removed_bytes = 0;
+
+  section_size = (sec->_cooked_size ? sec->_cooked_size : sec->_raw_size);
+  if (section_size == 0 || section_size % 8 != 0)
+    return FALSE;
+
+  if (sec->output_section
+      && bfd_is_abs_section (sec->output_section))
+    return FALSE;
+
+  contents = retrieve_contents (abfd, sec, info->keep_memory);
+  if (!contents)
+    return FALSE;
+
+  cookie->rels = retrieve_internal_relocs (abfd, sec, info->keep_memory);
+  if (!cookie->rels)
+    {
+      release_contents (sec, contents);
+      return FALSE;
+    }
+
+  cookie->rel = cookie->rels;
+  cookie->relend = cookie->rels + sec->reloc_count;
+
+  for (offset = 0; offset < section_size; offset += 8)
+    {
+      actual_offset = offset - removed_bytes;
+
+      /* The ...symbol_deleted_p function will skip over relocs but it
+        won't adjust their offsets, so do that here.  */
+      while (cookie->rel < cookie->relend
+            && cookie->rel->r_offset < offset)
+       {
+         cookie->rel->r_offset -= removed_bytes;
+         cookie->rel++;
+       }
+
+      while (cookie->rel < cookie->relend
+            && cookie->rel->r_offset == offset)
+       {
+         if (_bfd_elf32_reloc_symbol_deleted_p (offset, cookie))
+           {
+             /* Remove the table entry.  (If the reloc type is NONE, then
+                the entry has already been merged with another and deleted
+                during relaxation.)  */
+             if (ELF32_R_TYPE (cookie->rel->r_info) != R_XTENSA_NONE)
+               {
+                 /* Shift the contents up.  */
+                 if (offset + 8 < section_size)
+                   memmove (&contents[actual_offset],
+                            &contents[actual_offset+8],
+                            section_size - offset - 8);
+                 removed_bytes += 8;
+               }
+
+             /* Remove this relocation.  */
+             cookie->rel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
+           }
+
+         /* Adjust the relocation offset for previous removals.  This
+            should not be done before calling ...symbol_deleted_p
+            because it might mess up the offset comparisons there.
+            Make sure the offset doesn't underflow in the case where
+            the first entry is removed.  */
+         if (cookie->rel->r_offset >= removed_bytes)
+           cookie->rel->r_offset -= removed_bytes;
+         else
+           cookie->rel->r_offset = 0;
+
+         cookie->rel++;
+       }
+    }
+
+  if (removed_bytes != 0)
+    {
+      /* Adjust any remaining relocs (shouldn't be any).  */
+      for (; cookie->rel < cookie->relend; cookie->rel++)
+       {
+         if (cookie->rel->r_offset >= removed_bytes)
+           cookie->rel->r_offset -= removed_bytes;
+         else
+           cookie->rel->r_offset = 0;
+       }
+
+      /* Clear the removed bytes.  */
+      memset (&contents[section_size - removed_bytes], 0, removed_bytes);
+
+      pin_contents (sec, contents);
+      pin_internal_relocs (sec, cookie->rels);
+
+      sec->_cooked_size = section_size - removed_bytes;
+      /* Also shrink _raw_size.  See comments in relax_property_section.  */
+      sec->_raw_size = sec->_cooked_size;
+    }
+  else
+    {
+      release_contents (sec, contents);
+      release_internal_relocs (sec, cookie->rels);
+    }
+
+  return (removed_bytes != 0);
+}
+
+
+static bfd_boolean
+elf_xtensa_discard_info (abfd, cookie, info)
+     bfd *abfd;
+     struct elf_reloc_cookie *cookie;
+     struct bfd_link_info *info;
+{
+  asection *sec;
+  bfd_boolean changed = FALSE;
+
+  for (sec = abfd->sections; sec != NULL; sec = sec->next)
+    {
+      if (xtensa_is_property_section (sec))
+       {
+         if (elf_xtensa_discard_info_for_section (abfd, cookie, info, sec))
+           changed = TRUE;
+       }
+    }
+
+  return changed;
+}
+
+
+static bfd_boolean
+elf_xtensa_ignore_discarded_relocs (sec)
+     asection *sec;
+{
+  return xtensa_is_property_section (sec);
+}
+
+\f
+/* Support for core dump NOTE sections.  */
+
+static bfd_boolean
+elf_xtensa_grok_prstatus (abfd, note)
+     bfd *abfd;
+     Elf_Internal_Note *note;
+{
+  int offset;
+  unsigned int raw_size;
+
+  /* The size for Xtensa is variable, so don't try to recognize the format
+     based on the size.  Just assume this is GNU/Linux.  */
+
+  /* pr_cursig */
+  elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+
+  /* pr_pid */
+  elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24);
+
+  /* pr_reg */
+  offset = 72;
+  raw_size = note->descsz - offset - 4;
+
+  /* Make a ".reg/999" section.  */
+  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
+                                         raw_size, note->descpos + offset);
+}
+
+
+static bfd_boolean
+elf_xtensa_grok_psinfo (abfd, note)
+     bfd *abfd;
+     Elf_Internal_Note *note;
+{
+  switch (note->descsz)
+    {
+      default:
+       return FALSE;
+
+      case 128:                /* GNU/Linux elf_prpsinfo */
+       elf_tdata (abfd)->core_program
+        = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
+       elf_tdata (abfd)->core_command
+        = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
+    }
+
+  /* Note that for some reason, a spurious space is tacked
+     onto the end of the args in some (at least one anyway)
+     implementations, so strip it off if it exists.  */
+
+  {
+    char *command = elf_tdata (abfd)->core_command;
+    int n = strlen (command);
+
+    if (0 < n && command[n - 1] == ' ')
+      command[n - 1] = '\0';
+  }
+
+  return TRUE;
+}
+
+\f
+/* Generic Xtensa configurability stuff.  */
+
+static xtensa_opcode callx0_op = XTENSA_UNDEFINED;
+static xtensa_opcode callx4_op = XTENSA_UNDEFINED;
+static xtensa_opcode callx8_op = XTENSA_UNDEFINED;
+static xtensa_opcode callx12_op = XTENSA_UNDEFINED;
+static xtensa_opcode call0_op = XTENSA_UNDEFINED;
+static xtensa_opcode call4_op = XTENSA_UNDEFINED;
+static xtensa_opcode call8_op = XTENSA_UNDEFINED;
+static xtensa_opcode call12_op = XTENSA_UNDEFINED;
+
+static void
+init_call_opcodes ()
+{
+  if (callx0_op == XTENSA_UNDEFINED)
+    {
+      callx0_op  = xtensa_opcode_lookup (xtensa_default_isa, "callx0");
+      callx4_op  = xtensa_opcode_lookup (xtensa_default_isa, "callx4");
+      callx8_op  = xtensa_opcode_lookup (xtensa_default_isa, "callx8");
+      callx12_op = xtensa_opcode_lookup (xtensa_default_isa, "callx12");
+      call0_op   = xtensa_opcode_lookup (xtensa_default_isa, "call0");
+      call4_op   = xtensa_opcode_lookup (xtensa_default_isa, "call4");
+      call8_op   = xtensa_opcode_lookup (xtensa_default_isa, "call8");
+      call12_op  = xtensa_opcode_lookup (xtensa_default_isa, "call12");
+    }
+}
+
+
+static bfd_boolean
+is_indirect_call_opcode (opcode)
+     xtensa_opcode opcode;
+{
+  init_call_opcodes ();
+  return (opcode == callx0_op
+         || opcode == callx4_op
+         || opcode == callx8_op
+         || opcode == callx12_op);
+}
+
+
+static bfd_boolean
+is_direct_call_opcode (opcode)
+     xtensa_opcode opcode;
+{
+  init_call_opcodes ();
+  return (opcode == call0_op
+         || opcode == call4_op
+         || opcode == call8_op
+         || opcode == call12_op);
+}
+
+
+static bfd_boolean
+is_windowed_call_opcode (opcode)
+     xtensa_opcode opcode;
+{
+  init_call_opcodes ();
+  return (opcode == call4_op
+         || opcode == call8_op
+         || opcode == call12_op
+         || opcode == callx4_op
+         || opcode == callx8_op
+         || opcode == callx12_op);
+}
+
+
+static xtensa_opcode
+get_l32r_opcode (void)
+{
+  static xtensa_opcode l32r_opcode = XTENSA_UNDEFINED;
+  if (l32r_opcode == XTENSA_UNDEFINED)
+    {
+      l32r_opcode = xtensa_opcode_lookup (xtensa_default_isa, "l32r");
+      BFD_ASSERT (l32r_opcode != XTENSA_UNDEFINED);
+    }
+  return l32r_opcode;
+}
+
+
+static bfd_vma
+l32r_offset (addr, pc)
+     bfd_vma addr;
+     bfd_vma pc;
+{
+  bfd_vma offset;
+
+  offset = addr - ((pc+3) & -4);
+  BFD_ASSERT ((offset & ((1 << 2) - 1)) == 0);
+  offset = (signed int) offset >> 2;
+  BFD_ASSERT ((signed int) offset >> 16 == -1);
+  return offset;
+}
+
+
+/* Get the operand number for a PC-relative relocation.
+   If the relocation is not a PC-relative one, return (-1).  */
+
+static int
+get_relocation_opnd (irel)
+     Elf_Internal_Rela *irel;
+{
+  if (ELF32_R_TYPE (irel->r_info) < R_XTENSA_OP0
+      || ELF32_R_TYPE (irel->r_info) >= R_XTENSA_max)
+    return -1;
+  return ELF32_R_TYPE (irel->r_info) - R_XTENSA_OP0;
+}
+
+
+/* Get the opcode for a relocation.  */
+
+static xtensa_opcode
+get_relocation_opcode (sec, contents, irel)
+     asection *sec;
+     bfd_byte *contents;
+     Elf_Internal_Rela *irel;
+{
+  static xtensa_insnbuf ibuff = NULL;
+  xtensa_isa isa = xtensa_default_isa;
+
+  if (get_relocation_opnd (irel) == -1)
+    return XTENSA_UNDEFINED;
+
+  if (contents == NULL)
+    return XTENSA_UNDEFINED;
+
+  if (sec->_raw_size <= irel->r_offset)
+    return XTENSA_UNDEFINED;
+
+  if (ibuff == NULL)
+    ibuff = xtensa_insnbuf_alloc (isa);
+      
+  /* Decode the instruction.  */
+  xtensa_insnbuf_from_chars (isa, ibuff, &contents[irel->r_offset]);
+  return xtensa_decode_insn (isa, ibuff);
+}
+
+
+bfd_boolean
+is_l32r_relocation (sec, contents, irel)
+     asection *sec;
+     bfd_byte *contents;
+     Elf_Internal_Rela *irel;
+{
+  xtensa_opcode opcode;
+
+  if (ELF32_R_TYPE (irel->r_info) != R_XTENSA_OP1)
+    return FALSE;
+  
+  opcode = get_relocation_opcode (sec, contents, irel);
+  return (opcode == get_l32r_opcode ());
+}
+
+\f
+/* Code for transforming CALLs at link-time.  */
+
+static bfd_reloc_status_type
+elf_xtensa_do_asm_simplify (contents, address, content_length)
+     bfd_byte *contents;
+     bfd_vma address;
+     bfd_vma content_length;
+{
+  static xtensa_insnbuf insnbuf = NULL;
+  xtensa_opcode opcode;
+  xtensa_operand operand;
+  xtensa_opcode direct_call_opcode;
+  xtensa_isa isa = xtensa_default_isa;
+  bfd_byte *chbuf = contents + address;
+  int opn;
+
+  if (insnbuf == NULL)
+    insnbuf = xtensa_insnbuf_alloc (isa);
+
+  if (content_length < address)
+    {
+      (*_bfd_error_handler)
+       ("Attempt to convert L32R/CALLX to CALL failed\n");
+      return bfd_reloc_other;
+    }
+
+  opcode = get_expanded_call_opcode (chbuf, content_length - address);
+  direct_call_opcode = swap_callx_for_call_opcode (opcode);
+  if (direct_call_opcode == XTENSA_UNDEFINED)
+    {
+      (*_bfd_error_handler)
+       ("Attempt to convert L32R/CALLX to CALL failed\n");
+      return bfd_reloc_other;
+    }
+  
+  /* Assemble a NOP ("or a1, a1, a1") into the 0 byte offset.  */
+  opcode = xtensa_opcode_lookup (isa, "or");
+  xtensa_encode_insn (isa, opcode, insnbuf);
+  for (opn = 0; opn < 3; opn++) 
+    {
+      operand = xtensa_get_operand (isa, opcode, opn);
+      xtensa_operand_set_field (operand, insnbuf, 1);
+    }
+  xtensa_insnbuf_to_chars (isa, insnbuf, chbuf);
+
+  /* Assemble a CALL ("callN 0") into the 3 byte offset.  */
+  xtensa_encode_insn (isa, direct_call_opcode, insnbuf);
+  operand = xtensa_get_operand (isa, opcode, 0);
+  xtensa_operand_set_field (operand, insnbuf, 0);
+  xtensa_insnbuf_to_chars (isa, insnbuf, chbuf + 3);
+
+  return bfd_reloc_ok;
+}
+
+
+static bfd_reloc_status_type
+contract_asm_expansion (contents, content_length, irel)
+     bfd_byte *contents;
+     bfd_vma content_length;
+     Elf_Internal_Rela *irel;
+{
+  bfd_reloc_status_type retval =
+    elf_xtensa_do_asm_simplify (contents, irel->r_offset, content_length);
+
+  if (retval != bfd_reloc_ok)
+    return retval;
+
+  /* Update the irel->r_offset field so that the right immediate and
+     the right instruction are modified during the relocation.  */
+  irel->r_offset += 3;
+  irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_XTENSA_OP0);
+  return bfd_reloc_ok;
+}
+
+
+static xtensa_opcode
+swap_callx_for_call_opcode (opcode)
+     xtensa_opcode opcode;
+{
+  init_call_opcodes ();
+
+  if (opcode == callx0_op) return call0_op;
+  if (opcode == callx4_op) return call4_op;
+  if (opcode == callx8_op) return call8_op;
+  if (opcode == callx12_op) return call12_op;
+
+  /* Return XTENSA_UNDEFINED if the opcode is not an indirect call.  */
+  return XTENSA_UNDEFINED;
+}
+
+
+/* Check if "buf" is pointing to a "L32R aN; CALLX aN" sequence, and
+   if so, return the CALLX opcode.  If not, return XTENSA_UNDEFINED.  */
+
+#define L32R_TARGET_REG_OPERAND 0
+#define CALLN_SOURCE_OPERAND 0
+
+static xtensa_opcode 
+get_expanded_call_opcode (buf, bufsize)
+     bfd_byte *buf;
+     int bufsize;
+{
+  static xtensa_insnbuf insnbuf = NULL;
+  xtensa_opcode opcode;
+  xtensa_operand operand;
+  xtensa_isa isa = xtensa_default_isa;
+  uint32 regno, call_regno;
+  
+  /* Buffer must be at least 6 bytes.  */
+  if (bufsize < 6)
+    return XTENSA_UNDEFINED;
+
+  if (insnbuf == NULL)
+    insnbuf = xtensa_insnbuf_alloc (isa);
+      
+  xtensa_insnbuf_from_chars (isa, insnbuf, buf);
+  opcode = xtensa_decode_insn (isa, insnbuf);
+  
+  if (opcode != get_l32r_opcode ())
+    return XTENSA_UNDEFINED;
+  
+  operand = xtensa_get_operand (isa, opcode, L32R_TARGET_REG_OPERAND);
+  regno = xtensa_operand_decode
+    (operand, xtensa_operand_get_field (operand, insnbuf));
+  
+  /* Next instruction should be an CALLXn with operand 0 == regno.  */
+  xtensa_insnbuf_from_chars (isa, insnbuf, 
+                            buf + xtensa_insn_length (isa, opcode));
+  opcode = xtensa_decode_insn (isa, insnbuf);
+  
+  if (!is_indirect_call_opcode (opcode))
+    return XTENSA_UNDEFINED;
+  
+  operand = xtensa_get_operand (isa, opcode, CALLN_SOURCE_OPERAND);
+  call_regno = xtensa_operand_decode
+    (operand, xtensa_operand_get_field (operand, insnbuf));
+  if (call_regno != regno)
+    return XTENSA_UNDEFINED;
+  
+  return opcode;
+}
+
+\f
+/* Data structures used during relaxation.  */
+
+/* r_reloc: relocation values.  */
+
+/* Through the relaxation process, we need to keep track of the values
+   that will result from evaluating relocations.  The standard ELF
+   relocation structure is not sufficient for this purpose because we're
+   operating on multiple input files at once, so we need to know which
+   input file a relocation refers to.  The r_reloc structure thus
+   records both the input file (bfd) and ELF relocation.
+
+   For efficiency, an r_reloc also contains a "target_offset" field to
+   cache the target-section-relative offset value that is represented by
+   the relocation.  */
+
+typedef struct r_reloc_struct r_reloc;
+
+struct r_reloc_struct
+{
+  bfd *abfd;
+  Elf_Internal_Rela rela;
+  bfd_vma target_offset;
+};
+
+static bfd_boolean r_reloc_is_const
+  PARAMS ((const r_reloc *));
+static void r_reloc_init
+  PARAMS ((r_reloc *, bfd *, Elf_Internal_Rela *));
+static bfd_vma r_reloc_get_target_offset
+  PARAMS ((const r_reloc *));
+static asection *r_reloc_get_section
+  PARAMS ((const r_reloc *));
+static bfd_boolean r_reloc_is_defined
+  PARAMS ((const r_reloc *));
+static struct elf_link_hash_entry *r_reloc_get_hash_entry
+  PARAMS ((const r_reloc *));
+
+
+/* The r_reloc structure is included by value in literal_value, but not
+   every literal_value has an associated relocation -- some are simple
+   constants.  In such cases, we set all the fields in the r_reloc
+   struct to zero.  The r_reloc_is_const function should be used to
+   detect this case.  */
+
+static bfd_boolean
+r_reloc_is_const (r_rel)
+     const r_reloc *r_rel;
+{
+  return (r_rel->abfd == NULL);
+}
+
+
+static void
+r_reloc_init (r_rel, abfd, irel) 
+     r_reloc *r_rel;
+     bfd *abfd;
+     Elf_Internal_Rela *irel;
+{
+  if (irel != NULL)
+    {
+      r_rel->rela = *irel;
+      r_rel->abfd = abfd;
+      r_rel->target_offset = r_reloc_get_target_offset (r_rel);
+    }
+  else
+    memset (r_rel, 0, sizeof (r_reloc));
+}
+
+
+static bfd_vma
+r_reloc_get_target_offset (r_rel)
+     const r_reloc *r_rel;
+{
+  bfd_vma target_offset;
+  unsigned long r_symndx;
+
+  BFD_ASSERT (!r_reloc_is_const (r_rel));
+  r_symndx = ELF32_R_SYM (r_rel->rela.r_info);
+  target_offset = get_elf_r_symndx_offset (r_rel->abfd, r_symndx);
+  return (target_offset + r_rel->rela.r_addend);
+}
+
+
+static struct elf_link_hash_entry *
+r_reloc_get_hash_entry (r_rel)
+     const r_reloc *r_rel;
+{
+  unsigned long r_symndx = ELF32_R_SYM (r_rel->rela.r_info);
+  return get_elf_r_symndx_hash_entry (r_rel->abfd, r_symndx);
+}
+
+
+static asection *
+r_reloc_get_section (r_rel)
+     const r_reloc *r_rel;
+{
+  unsigned long r_symndx = ELF32_R_SYM (r_rel->rela.r_info);
+  return get_elf_r_symndx_section (r_rel->abfd, r_symndx);
+}
+
+
+static bfd_boolean
+r_reloc_is_defined (r_rel)
+     const r_reloc *r_rel;
+{
+  asection *sec = r_reloc_get_section (r_rel);
+  if (sec == bfd_abs_section_ptr
+      || sec == bfd_com_section_ptr
+      || sec == bfd_und_section_ptr)
+    return FALSE;
+  return TRUE;
+}
+
+\f
+/* source_reloc: relocations that reference literal sections.  */
+
+/* To determine whether literals can be coalesced, we need to first
+   record all the relocations that reference the literals.  The
+   source_reloc structure below is used for this purpose.  The
+   source_reloc entries are kept in a per-literal-section array, sorted
+   by offset within the literal section (i.e., target offset).
+
+   The source_sec and r_rel.rela.r_offset fields identify the source of
+   the relocation.  The r_rel field records the relocation value, i.e.,
+   the offset of the literal being referenced.  The opnd field is needed
+   to determine the range of the immediate field to which the relocation
+   applies, so we can determine whether another literal with the same
+   value is within range.  The is_null field is true when the relocation
+   is being removed (e.g., when an L32R is being removed due to a CALLX
+   that is converted to a direct CALL).  */
+
+typedef struct source_reloc_struct source_reloc;
+
+struct source_reloc_struct
+{
+  asection *source_sec;
+  r_reloc r_rel;
+  xtensa_operand opnd;
+  bfd_boolean is_null;
+};
+
+
+static void init_source_reloc
+  PARAMS ((source_reloc *, asection *, const r_reloc *, xtensa_operand));
+static source_reloc *find_source_reloc
+  PARAMS ((source_reloc *, int, asection *, Elf_Internal_Rela *));
+static int source_reloc_compare
+  PARAMS ((const PTR, const PTR));
+
+
+static void
+init_source_reloc (reloc, source_sec, r_rel, opnd)
+     source_reloc *reloc;
+     asection *source_sec;
+     const r_reloc *r_rel;
+     xtensa_operand opnd;
+{
+  reloc->source_sec = source_sec;
+  reloc->r_rel = *r_rel;
+  reloc->opnd = opnd;
+  reloc->is_null = FALSE;
+}
+
+
+/* Find the source_reloc for a particular source offset and relocation
+   type.  Note that the array is sorted by _target_ offset, so this is
+   just a linear search.  */
+
+static source_reloc *
+find_source_reloc (src_relocs, src_count, sec, irel)
+     source_reloc *src_relocs;
+     int src_count;
+     asection *sec;
+     Elf_Internal_Rela *irel;
+{
+  int i;
+
+  for (i = 0; i < src_count; i++)
+    {
+      if (src_relocs[i].source_sec == sec
+         && src_relocs[i].r_rel.rela.r_offset == irel->r_offset
+         && (ELF32_R_TYPE (src_relocs[i].r_rel.rela.r_info)
+             == ELF32_R_TYPE (irel->r_info)))
+       return &src_relocs[i];
+    }
+
+  return NULL;
+}
+
+
+static int
+source_reloc_compare (ap, bp)
+     const PTR ap;
+     const PTR bp;
+{
+  const source_reloc *a = (const source_reloc *) ap;
+  const source_reloc *b = (const source_reloc *) bp;
+
+  return (a->r_rel.target_offset - b->r_rel.target_offset);
+}
+
+\f
+/* Literal values and value hash tables.  */
+
+/* Literals with the same value can be coalesced.  The literal_value
+   structure records the value of a literal: the "r_rel" field holds the
+   information from the relocation on the literal (if there is one) and
+   the "value" field holds the contents of the literal word itself.
+
+   The value_map structure records a literal value along with the
+   location of a literal holding that value.  The value_map hash table
+   is indexed by the literal value, so that we can quickly check if a
+   particular literal value has been seen before and is thus a candidate
+   for coalescing.  */
+
+typedef struct literal_value_struct literal_value;
+typedef struct value_map_struct value_map;
+typedef struct value_map_hash_table_struct value_map_hash_table;
+
+struct literal_value_struct
+{
+  r_reloc r_rel; 
+  unsigned long value;
+};
+
+struct value_map_struct
+{
+  literal_value val;                   /* The literal value.  */
+  r_reloc loc;                         /* Location of the literal.  */
+  value_map *next;
+};
+
+struct value_map_hash_table_struct
+{
+  unsigned bucket_count;
+  value_map **buckets;
+  unsigned count;
+};
+
+
+static bfd_boolean is_same_value
+  PARAMS ((const literal_value *, const literal_value *));
+static value_map_hash_table *value_map_hash_table_init
+  PARAMS ((void));
+static unsigned hash_literal_value
+  PARAMS ((const literal_value *));
+static unsigned hash_bfd_vma
+  PARAMS ((bfd_vma));
+static value_map *get_cached_value
+  PARAMS ((value_map_hash_table *, const literal_value *));
+static value_map *add_value_map
+  PARAMS ((value_map_hash_table *, const literal_value *, const r_reloc *));
+
+
+static bfd_boolean
+is_same_value (src1, src2)
+     const literal_value *src1;
+     const literal_value *src2;
+{
+  if (r_reloc_is_const (&src1->r_rel) != r_reloc_is_const (&src2->r_rel)) 
+    return FALSE;
+
+  if (r_reloc_is_const (&src1->r_rel))
+    return (src1->value == src2->value);
+
+  if (ELF32_R_TYPE (src1->r_rel.rela.r_info)
+      != ELF32_R_TYPE (src2->r_rel.rela.r_info))
+    return FALSE;
+
+  if (r_reloc_get_target_offset (&src1->r_rel)
+      != r_reloc_get_target_offset (&src2->r_rel))
+    return FALSE;
+
+  if (src1->value != src2->value)
+    return FALSE;
+  
+  /* Now check for the same section and the same elf_hash.  */
+  if (r_reloc_is_defined (&src1->r_rel))
+    {
+      if (r_reloc_get_section (&src1->r_rel)
+         != r_reloc_get_section (&src2->r_rel))
+       return FALSE;
+    }
+  else
+    {
+      if (r_reloc_get_hash_entry (&src1->r_rel)
+         != r_reloc_get_hash_entry (&src2->r_rel))
+       return FALSE;
+
+      if (r_reloc_get_hash_entry (&src1->r_rel) == 0)
+       return FALSE;
+    }
+
+  return TRUE;
+}
+
+
+/* Must be power of 2.  */
+#define INITIAL_HASH_RELOC_BUCKET_COUNT 1024
+
+static value_map_hash_table *
+value_map_hash_table_init ()
+{
+  value_map_hash_table *values;
+
+  values = (value_map_hash_table *)
+    bfd_malloc (sizeof (value_map_hash_table));
+
+  values->bucket_count = INITIAL_HASH_RELOC_BUCKET_COUNT;
+  values->count = 0;
+  values->buckets = (value_map **)
+    bfd_zmalloc (sizeof (value_map *) * values->bucket_count);
+
+  return values;
+}
+
+
+static unsigned
+hash_bfd_vma (val) 
+     bfd_vma val;
+{
+  return (val >> 2) + (val >> 10);
+}
+
+
+static unsigned
+hash_literal_value (src)
+     const literal_value *src;
+{
+  unsigned hash_val;
+  if (r_reloc_is_const (&src->r_rel))
+    return hash_bfd_vma (src->value);
+
+  hash_val = (hash_bfd_vma (r_reloc_get_target_offset (&src->r_rel))
+             + hash_bfd_vma (src->value));
+  
+  /* Now check for the same section and the same elf_hash.  */
+  if (r_reloc_is_defined (&src->r_rel))
+    hash_val += hash_bfd_vma ((bfd_vma) r_reloc_get_section (&src->r_rel));
+  else
+    hash_val += hash_bfd_vma ((bfd_vma) r_reloc_get_hash_entry (&src->r_rel));
+
+  return hash_val;
+}
+
+
+/* Check if the specified literal_value has been seen before.  */
+
+static value_map *
+get_cached_value (map, val)
+     value_map_hash_table *map;
+     const literal_value *val;
+{
+  value_map *map_e;
+  value_map *bucket;
+  unsigned idx;
+
+  idx = hash_literal_value (val);
+  idx = idx & (map->bucket_count - 1);
+  bucket = map->buckets[idx];
+  for (map_e = bucket; map_e; map_e = map_e->next)
+    {
+      if (is_same_value (&map_e->val, val))
+       return map_e;
+    }
+  return NULL;
+}
+
+
+/* Record a new literal value.  It is illegal to call this if VALUE
+   already has an entry here.  */
+
+static value_map *
+add_value_map (map, val, loc)
+     value_map_hash_table *map;
+     const literal_value *val;
+     const r_reloc *loc;
+{
+  value_map **bucket_p;
+  unsigned idx;
+
+  value_map *val_e = (value_map *) bfd_zmalloc (sizeof (value_map));
+
+  BFD_ASSERT (get_cached_value (map, val) == NULL);
+  val_e->val = *val;
+  val_e->loc = *loc;
+
+  idx = hash_literal_value (val);
+  idx = idx & (map->bucket_count - 1);
+  bucket_p = &map->buckets[idx];
+
+  val_e->next = *bucket_p;
+  *bucket_p = val_e;
+  map->count++;
+  /* FIXME: consider resizing the hash table if we get too many entries */
+  
+  return val_e;
+}
+
+\f
+/* Lists of literals being coalesced or removed.  */
+
+/* In the usual case, the literal identified by "from" is being
+   coalesced with another literal identified by "to".  If the literal is
+   unused and is being removed altogether, "to.abfd" will be NULL.
+   The removed_literal entries are kept on a per-section list, sorted
+   by the "from" offset field.  */
+
+typedef struct removed_literal_struct removed_literal;
+typedef struct removed_literal_list_struct removed_literal_list;
+
+struct removed_literal_struct
+{
+  r_reloc from;
+  r_reloc to;
+  removed_literal *next;
+};
+
+struct removed_literal_list_struct
+{
+  removed_literal *head;
+  removed_literal *tail;
+};
+
+
+static void add_removed_literal
+  PARAMS ((removed_literal_list *, const r_reloc *, const r_reloc *));
+static removed_literal *find_removed_literal
+  PARAMS ((removed_literal_list *, bfd_vma));
+static bfd_vma offset_with_removed_literals
+  PARAMS ((removed_literal_list *, bfd_vma));
+
+
+/* Record that the literal at "from" is being removed.  If "to" is not
+   NULL, the "from" literal is being coalesced with the "to" literal.  */
+
+static void
+add_removed_literal (removed_list, from, to)
+     removed_literal_list *removed_list;
+     const r_reloc *from;
+     const r_reloc *to;
+{
+  removed_literal *r, *new_r, *next_r;
+
+  new_r = (removed_literal *) bfd_zmalloc (sizeof (removed_literal));
+
+  new_r->from = *from;
+  if (to)
+    new_r->to = *to;
+  else
+    new_r->to.abfd = NULL;
+  new_r->next = NULL;
+  
+  r = removed_list->head;
+  if (r == NULL) 
+    {
+      removed_list->head = new_r;
+      removed_list->tail = new_r;
+    }
+  /* Special check for common case of append.  */
+  else if (removed_list->tail->from.target_offset < from->target_offset)
+    {
+      removed_list->tail->next = new_r;
+      removed_list->tail = new_r;
+    }
+  else
+    {
+      while (r->from.target_offset < from->target_offset
+            && r->next != NULL) 
+       {
+         r = r->next;
+       }
+      next_r = r->next;
+      r->next = new_r;
+      new_r->next = next_r;
+      if (next_r == NULL)
+       removed_list->tail = new_r;
+    }
+}
+
+
+/* Check if the list of removed literals contains an entry for the
+   given address.  Return the entry if found.  */
+
+static removed_literal *
+find_removed_literal (removed_list, addr)
+     removed_literal_list *removed_list;
+     bfd_vma addr;
+{
+  removed_literal *r = removed_list->head;
+  while (r && r->from.target_offset < addr)
+    r = r->next;
+  if (r && r->from.target_offset == addr)
+    return r;
+  return NULL;
+}
+
+
+/* Adjust an offset in a section to compensate for literals that are
+   being removed.  Search the list of removed literals and subtract
+   4 bytes for every removed literal prior to the given address.  */
+
+static bfd_vma 
+offset_with_removed_literals (removed_list, addr)
+     removed_literal_list *removed_list;
+     bfd_vma addr;
+{
+  removed_literal *r = removed_list->head;
+  unsigned num_bytes = 0;
+
+  if (r == NULL)
+    return addr;
+
+  while (r && r->from.target_offset <= addr)
+    {
+      num_bytes += 4;
+      r = r->next;
+    }
+  if (num_bytes > addr)
+    return 0;
+  return (addr - num_bytes);
+}
+
+\f
+/* Coalescing literals may require a relocation to refer to a section in
+   a different input file, but the standard relocation information
+   cannot express that.  Instead, the reloc_bfd_fix structures are used
+   to "fix" the relocations that refer to sections in other input files.
+   These structures are kept on per-section lists.  The "src_type" field
+   records the relocation type in case there are multiple relocations on
+   the same location.  FIXME: This is ugly; an alternative might be to
+   add new symbols with the "owner" field to some other input file.  */
+
+typedef struct reloc_bfd_fix_struct reloc_bfd_fix;
+
+struct reloc_bfd_fix_struct
+{
+  asection *src_sec;
+  bfd_vma src_offset;
+  unsigned src_type;                   /* Relocation type.  */
+  
+  bfd *target_abfd;
+  asection *target_sec;
+  bfd_vma target_offset;
+  
+  reloc_bfd_fix *next;
+};
+
+
+static reloc_bfd_fix *reloc_bfd_fix_init
+  PARAMS ((asection *, bfd_vma, unsigned, bfd *, asection *, bfd_vma));
+static reloc_bfd_fix *get_bfd_fix
+  PARAMS ((reloc_bfd_fix *, asection *, bfd_vma, unsigned));
+
+
+static reloc_bfd_fix *
+reloc_bfd_fix_init (src_sec, src_offset, src_type,
+                   target_abfd, target_sec, target_offset)
+     asection *src_sec;
+     bfd_vma src_offset;
+     unsigned src_type;
+     bfd *target_abfd;
+     asection *target_sec;
+     bfd_vma target_offset;
+{
+  reloc_bfd_fix *fix;
+
+  fix = (reloc_bfd_fix *) bfd_malloc (sizeof (reloc_bfd_fix));
+  fix->src_sec = src_sec;
+  fix->src_offset = src_offset;
+  fix->src_type = src_type;
+  fix->target_abfd = target_abfd;
+  fix->target_sec = target_sec;
+  fix->target_offset = target_offset;
+
+  return fix;
+}
+
+
+static reloc_bfd_fix *
+get_bfd_fix (fix_list, sec, offset, type)
+     reloc_bfd_fix *fix_list;
+     asection *sec;
+     bfd_vma offset;
+     unsigned type;
+{
+  reloc_bfd_fix *r;
+
+  for (r = fix_list; r != NULL; r = r->next) 
+    {
+      if (r->src_sec == sec
+         && r->src_offset == offset
+         && r->src_type == type)
+       return r;
+    }
+  return NULL;
+}
+
+\f
+/* Per-section data for relaxation.  */
+
+struct xtensa_relax_info_struct
+{
+  bfd_boolean is_relaxable_literal_section;
+  int visited;                         /* Number of times visited.  */
+
+  source_reloc *src_relocs;            /* Array[src_count].  */
+  int src_count;
+  int src_next;                                /* Next src_relocs entry to assign.  */
+
+  removed_literal_list removed_list;
+
+  reloc_bfd_fix *fix_list;
+};
+
+struct elf_xtensa_section_data
+{
+  struct bfd_elf_section_data elf;
+  xtensa_relax_info relax_info;
+};
+
+static void init_xtensa_relax_info
+  PARAMS ((asection *));
+static xtensa_relax_info *get_xtensa_relax_info
+  PARAMS ((asection *));
+static void add_fix
+  PARAMS ((asection *, reloc_bfd_fix *));
+
+
+static bfd_boolean
+elf_xtensa_new_section_hook (abfd, sec)
+     bfd *abfd;
+     asection *sec;
+{
+  struct elf_xtensa_section_data *sdata;
+  bfd_size_type amt = sizeof (*sdata);
+
+  sdata = (struct elf_xtensa_section_data *) bfd_zalloc (abfd, amt);
+  if (sdata == NULL)
+    return FALSE;
+  sec->used_by_bfd = (PTR) sdata;
+
+  return _bfd_elf_new_section_hook (abfd, sec);
+}
+
+
+static void
+init_xtensa_relax_info (sec)
+     asection *sec;
+{
+  xtensa_relax_info *relax_info = get_xtensa_relax_info (sec);
+
+  relax_info->is_relaxable_literal_section = FALSE;
+  relax_info->visited = 0;
+
+  relax_info->src_relocs = NULL;
+  relax_info->src_count = 0;
+  relax_info->src_next = 0;
+
+  relax_info->removed_list.head = NULL;
+  relax_info->removed_list.tail = NULL;
+
+  relax_info->fix_list = NULL;
+}
+
+
+static xtensa_relax_info *
+get_xtensa_relax_info (sec)
+     asection *sec;
+{
+  struct elf_xtensa_section_data *section_data;
+
+  /* No info available if no section or if it is an output section.  */
+  if (!sec || sec == sec->output_section)
+    return NULL;
+
+  section_data = (struct elf_xtensa_section_data *) elf_section_data (sec);
+  return &section_data->relax_info;
+}
+
+
+static void
+add_fix (src_sec, fix)
+     asection *src_sec;
+     reloc_bfd_fix *fix;
+{
+  xtensa_relax_info *relax_info;
+
+  relax_info = get_xtensa_relax_info (src_sec);
+  fix->next = relax_info->fix_list;
+  relax_info->fix_list = fix;
+}
+
+\f
+/* Access to internal relocations, section contents and symbols.  */
+
+/* During relaxation, we need to modify relocations, section contents,
+   and symbol definitions, and we need to keep the original values from
+   being reloaded from the input files, i.e., we need to "pin" the
+   modified values in memory.  We also want to continue to observe the
+   setting of the "keep-memory" flag.  The following functions wrap the
+   standard BFD functions to take care of this for us.  */
+
+static Elf_Internal_Rela *
+retrieve_internal_relocs (abfd, sec, keep_memory)
+     bfd *abfd;
+     asection *sec;
+     bfd_boolean keep_memory;
+{
+  Elf_Internal_Rela *internal_relocs;
+
+  if ((sec->flags & SEC_LINKER_CREATED) != 0)
+    return NULL;
+
+  internal_relocs = elf_section_data (sec)->relocs;
+  if (internal_relocs == NULL)
+    internal_relocs = (_bfd_elf32_link_read_relocs
+                      (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
+                       keep_memory));
+  return internal_relocs;
+}
+
+
+static void
+pin_internal_relocs (sec, internal_relocs)
+     asection *sec;
+     Elf_Internal_Rela *internal_relocs;
+{
+  elf_section_data (sec)->relocs = internal_relocs;
+}
+
+
+static void
+release_internal_relocs (sec, internal_relocs)
+     asection *sec;
+     Elf_Internal_Rela *internal_relocs;
+{
+  if (internal_relocs
+      && elf_section_data (sec)->relocs != internal_relocs)
+    free (internal_relocs);
+}
+
+
+static bfd_byte *
+retrieve_contents (abfd, sec, keep_memory)
+     bfd *abfd;
+     asection *sec;
+     bfd_boolean keep_memory;
+{
+  bfd_byte *contents;
+
+  contents = elf_section_data (sec)->this_hdr.contents;
+  
+  if (contents == NULL && sec->_raw_size != 0)
+    {
+      contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
+      if (contents != NULL)
+       {
+         if (! bfd_get_section_contents (abfd, sec, contents,
+                                         (file_ptr) 0, sec->_raw_size))
+           {
+             free (contents);
+             return NULL;
+           }
+         if (keep_memory) 
+           elf_section_data (sec)->this_hdr.contents = contents;
+       }
+    }
+  return contents;
+}
+
+
+static void
+pin_contents (sec, contents)
+     asection *sec;
+     bfd_byte *contents;
+{
+  elf_section_data (sec)->this_hdr.contents = contents;
+}
+
+
+static void
+release_contents (sec, contents)
+     asection *sec;
+     bfd_byte *contents;
+{
+  if (contents && 
+      elf_section_data (sec)->this_hdr.contents != contents)
+    free (contents);
+}
+
+
+static Elf_Internal_Sym *
+retrieve_local_syms (input_bfd)
+     bfd *input_bfd;
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Sym *isymbuf;
+  size_t locsymcount;
+
+  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+  locsymcount = symtab_hdr->sh_info;
+
+  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+  if (isymbuf == NULL && locsymcount != 0)
+    isymbuf = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0,
+                                   NULL, NULL, NULL);
+
+  /* Save the symbols for this input file so they won't be read again.  */
+  if (isymbuf && isymbuf != (Elf_Internal_Sym *) symtab_hdr->contents)
+    symtab_hdr->contents = (unsigned char *) isymbuf;
+
+  return isymbuf;
+}
+
+\f
+/* Code for link-time relaxation.  */
+
+/* Local helper functions.  */
+static bfd_boolean analyze_relocations
+  PARAMS ((struct bfd_link_info *));
+static bfd_boolean find_relaxable_sections
+  PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
+static bfd_boolean collect_source_relocs
+  PARAMS ((bfd *, asection *, struct bfd_link_info *));
+static bfd_boolean is_resolvable_asm_expansion
+  PARAMS ((bfd *, asection *, bfd_byte *, Elf_Internal_Rela *,
+          struct bfd_link_info *, bfd_boolean *));
+static bfd_boolean remove_literals
+  PARAMS ((bfd *, asection *, struct bfd_link_info *, value_map_hash_table *));
+static bfd_boolean relax_section
+  PARAMS ((bfd *, asection *, struct bfd_link_info *));
+static bfd_boolean relax_property_section
+  PARAMS ((bfd *, asection *, struct bfd_link_info *));
+static bfd_boolean relax_section_symbols
+  PARAMS ((bfd *, asection *));
+static bfd_boolean relocations_reach
+  PARAMS ((source_reloc *, int, const r_reloc *));
+static void translate_reloc
+  PARAMS ((const r_reloc *, r_reloc *));
+static Elf_Internal_Rela *get_irel_at_offset
+  PARAMS ((asection *, Elf_Internal_Rela *, bfd_vma));
+static Elf_Internal_Rela *find_associated_l32r_irel
+  PARAMS ((asection *, bfd_byte *, Elf_Internal_Rela *,
+          Elf_Internal_Rela *));
+static void shrink_dynamic_reloc_sections
+  PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *));
+
+
+static bfd_boolean 
+elf_xtensa_relax_section (abfd, sec, link_info, again)
+     bfd *abfd;
+     asection *sec;
+     struct bfd_link_info *link_info;
+     bfd_boolean *again;
+{
+  static value_map_hash_table *values = NULL;
+  xtensa_relax_info *relax_info;
+
+  if (!values)
+    {
+      /* Do some overall initialization for relaxation.  */
+      values = value_map_hash_table_init ();
+      relaxing_section = TRUE;
+      if (!analyze_relocations (link_info))
+       return FALSE;
+    }
+  *again = FALSE;
+
+  /* Don't mess with linker-created sections.  */
+  if ((sec->flags & SEC_LINKER_CREATED) != 0)
+    return TRUE;
+
+  relax_info = get_xtensa_relax_info (sec);
+  BFD_ASSERT (relax_info != NULL);
+
+  switch (relax_info->visited)
+    {
+    case 0:
+      /* Note: It would be nice to fold this pass into
+        analyze_relocations, but it is important for this step that the
+        sections be examined in link order.  */
+      if (!remove_literals (abfd, sec, link_info, values))
+       return FALSE;
+      *again = TRUE;
+      break;
+
+    case 1:
+      if (!relax_section (abfd, sec, link_info))
+       return FALSE;
+      *again = TRUE;
+      break;
+
+    case 2:
+      if (!relax_section_symbols (abfd, sec))
+       return FALSE;
+      break;
+    }
+
+  relax_info->visited++;
+  return TRUE;
+}
+
+/* Initialization for relaxation.  */
+
+/* This function is called once at the start of relaxation.  It scans
+   all the input sections and marks the ones that are relaxable (i.e.,
+   literal sections with L32R relocations against them).  It then
+   collect source_reloc information for all the relocations against
+   those relaxable sections.  */
+
+static bfd_boolean
+analyze_relocations (link_info)
+     struct bfd_link_info *link_info;
+{
+  bfd *abfd;
+  asection *sec;
+  bfd_boolean is_relaxable = FALSE;
+
+  /* Initialize the per-section relaxation info.  */
+  for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+    for (sec = abfd->sections; sec != NULL; sec = sec->next)
+      {
+       init_xtensa_relax_info (sec);
+      }
+
+  /* Mark relaxable sections (and count relocations against each one).  */
+  for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+    for (sec = abfd->sections; sec != NULL; sec = sec->next)
+      {
+       if (!find_relaxable_sections (abfd, sec, link_info, &is_relaxable))
+         return FALSE;
+      }
+
+  /* Bail out if there are no relaxable sections.  */
+  if (!is_relaxable)
+    return TRUE;
+
+  /* Allocate space for source_relocs.  */
+  for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+    for (sec = abfd->sections; sec != NULL; sec = sec->next)
+      {
+       xtensa_relax_info *relax_info;
+
+       relax_info = get_xtensa_relax_info (sec);
+       if (relax_info->is_relaxable_literal_section)
+         {
+           relax_info->src_relocs = (source_reloc *)
+             bfd_malloc (relax_info->src_count * sizeof (source_reloc));
+         }
+      }
+
+  /* Collect info on relocations against each relaxable section.  */
+  for (abfd = link_info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+    for (sec = abfd->sections; sec != NULL; sec = sec->next)
+      {
+       if (!collect_source_relocs (abfd, sec, link_info))
+         return FALSE;
+      }
+
+  return TRUE;
+}
+
+
+/* Find all the literal sections that might be relaxed.  The motivation
+   for this pass is that collect_source_relocs() needs to record _all_
+   the relocations that target each relaxable section.  That is
+   expensive and unnecessary unless the target section is actually going
+   to be relaxed.  This pass identifies all such sections by checking if
+   they have L32Rs pointing to them.  In the process, the total number
+   of relocations targetting each section is also counted so that we
+   know how much space to allocate for source_relocs against each
+   relaxable literal section.  */
+
+static bfd_boolean
+find_relaxable_sections (abfd, sec, link_info, is_relaxable_p)
+     bfd *abfd;
+     asection *sec;
+     struct bfd_link_info *link_info;
+     bfd_boolean *is_relaxable_p;
+{
+  Elf_Internal_Rela *internal_relocs;
+  bfd_byte *contents;
+  bfd_boolean ok = TRUE;
+  unsigned i;
+
+  internal_relocs = retrieve_internal_relocs (abfd, sec,
+                                             link_info->keep_memory);
+  if (internal_relocs == NULL) 
+    return ok;
+
+  contents = retrieve_contents (abfd, sec, link_info->keep_memory);
+  if (contents == NULL && sec->_raw_size != 0)
+    {
+      ok = FALSE;
+      goto error_return;
+    }
+
+  for (i = 0; i < sec->reloc_count; i++) 
+    {
+      Elf_Internal_Rela *irel = &internal_relocs[i];
+      r_reloc r_rel;
+      asection *target_sec;
+      xtensa_relax_info *target_relax_info;
+
+      r_reloc_init (&r_rel, abfd, irel);
+
+      target_sec = r_reloc_get_section (&r_rel);
+      target_relax_info = get_xtensa_relax_info (target_sec);
+      if (!target_relax_info)
+       continue;
+
+      /* Count relocations against the target section.  */
+      target_relax_info->src_count++;
+
+      if (is_literal_section (target_sec)
+         && is_l32r_relocation (sec, contents, irel)
+         && r_reloc_is_defined (&r_rel))
+       {
+         /* Mark the target section as relaxable.  */
+         target_relax_info->is_relaxable_literal_section = TRUE;
+         *is_relaxable_p = TRUE;
+       }
+    }
+
+ error_return:
+  release_contents (sec, contents);
+  release_internal_relocs (sec, internal_relocs);
+  return ok;
+}
+
+
+/* Record _all_ the relocations that point to relaxable literal
+   sections, and get rid of ASM_EXPAND relocs by either converting them
+   to ASM_SIMPLIFY or by removing them.  */
+
+static bfd_boolean
+collect_source_relocs (abfd, sec, link_info)
+     bfd *abfd;
+     asection *sec;
+     struct bfd_link_info *link_info;
+{
+  Elf_Internal_Rela *internal_relocs;
+  bfd_byte *contents;
+  bfd_boolean ok = TRUE;
+  unsigned i;
+
+  internal_relocs = retrieve_internal_relocs (abfd, sec, 
+                                             link_info->keep_memory);
+  if (internal_relocs == NULL) 
+    return ok;
+
+  contents = retrieve_contents (abfd, sec, link_info->keep_memory);
+  if (contents == NULL && sec->_raw_size != 0)
+    {
+      ok = FALSE;
+      goto error_return;
+    }
+
+  /* Record relocations against relaxable literal sections.  */
+  for (i = 0; i < sec->reloc_count; i++) 
+    {
+      Elf_Internal_Rela *irel = &internal_relocs[i];
+      r_reloc r_rel;
+      asection *target_sec;
+      xtensa_relax_info *target_relax_info;
+
+      r_reloc_init (&r_rel, abfd, irel);
+
+      target_sec = r_reloc_get_section (&r_rel);
+      target_relax_info = get_xtensa_relax_info (target_sec);
+
+      if (target_relax_info
+         && target_relax_info->is_relaxable_literal_section)
+       {
+         xtensa_opcode opcode;
+         xtensa_operand opnd;
+         source_reloc *s_reloc;
+         int src_next;
+
+         src_next = target_relax_info->src_next++;
+         s_reloc = &target_relax_info->src_relocs[src_next];
+
+         opcode = get_relocation_opcode (sec, contents, irel);
+         if (opcode == XTENSA_UNDEFINED)
+           opnd = NULL;
+         else
+           opnd = xtensa_get_operand (xtensa_default_isa, opcode,
+                                      get_relocation_opnd (irel));
+
+         init_source_reloc (s_reloc, sec, &r_rel, opnd);
+       }
+    }
+
+  /* Now get rid of ASM_EXPAND relocations.  At this point, the
+     src_relocs array for the target literal section may still be
+     incomplete, but it must at least contain the entries for the L32R
+     relocations associated with ASM_EXPANDs because they were just
+     added in the preceding loop over the relocations.  */
+
+  for (i = 0; i < sec->reloc_count; i++) 
+    {
+      Elf_Internal_Rela *irel = &internal_relocs[i];
+      bfd_boolean is_reachable;
+
+      if (!is_resolvable_asm_expansion (abfd, sec, contents, irel, link_info,
+                                       &is_reachable))
+       continue;
+
+      if (is_reachable)
+       {
+         Elf_Internal_Rela *l32r_irel;
+         r_reloc r_rel;
+         asection *target_sec;
+         xtensa_relax_info *target_relax_info;
+
+         /* Mark the source_reloc for the L32R so that it will be
+            removed in remove_literals(), along with the associated
+            literal.  */
+         l32r_irel = find_associated_l32r_irel (sec, contents,
+                                                irel, internal_relocs);
+         if (l32r_irel == NULL)
+           continue;
+
+         r_reloc_init (&r_rel, abfd, l32r_irel);
+
+         target_sec = r_reloc_get_section (&r_rel);
+         target_relax_info = get_xtensa_relax_info (target_sec);
+
+         if (target_relax_info
+             && target_relax_info->is_relaxable_literal_section)
+           {
+             source_reloc *s_reloc;
+
+             /* Search the source_relocs for the entry corresponding to
+                the l32r_irel.  Note: The src_relocs array is not yet
+                sorted, but it wouldn't matter anyway because we're
+                searching by source offset instead of target offset.  */
+             s_reloc = find_source_reloc (target_relax_info->src_relocs, 
+                                          target_relax_info->src_next,
+                                          sec, l32r_irel);
+             BFD_ASSERT (s_reloc);
+             s_reloc->is_null = TRUE;
+           }
+
+         /* Convert this reloc to ASM_SIMPLIFY.  */
+         irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+                                      R_XTENSA_ASM_SIMPLIFY);
+         l32r_irel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
+
+         pin_internal_relocs (sec, internal_relocs);
+       }
+      else
+       {
+         /* It is resolvable but doesn't reach.  We resolve now
+            by eliminating the relocation -- the call will remain
+            expanded into L32R/CALLX.  */
+         irel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
+         pin_internal_relocs (sec, internal_relocs);
+       }
+    }
+
+ error_return:
+  release_contents (sec, contents);
+  release_internal_relocs (sec, internal_relocs);
+  return ok;
+}
+
+
+/* Return TRUE if the asm expansion can be resolved.  Generally it can
+   be resolved on a final link or when a partial link locates it in the
+   same section as the target.  Set "is_reachable" flag if the target of
+   the call is within the range of a direct call, given the current VMA
+   for this section and the target section.  */
+
+bfd_boolean
+is_resolvable_asm_expansion (abfd, sec, contents, irel, link_info,
+                            is_reachable_p)
+     bfd *abfd;
+     asection *sec;
+     bfd_byte *contents;
+     Elf_Internal_Rela *irel;
+     struct bfd_link_info *link_info;
+     bfd_boolean *is_reachable_p;
+{
+  asection *target_sec;
+  bfd_vma target_offset;
+  r_reloc r_rel;
+  xtensa_opcode opcode, direct_call_opcode;
+  bfd_vma self_address;
+  bfd_vma dest_address;
+
+  *is_reachable_p = FALSE;
+
+  if (contents == NULL)
+    return FALSE;
+
+  if (ELF32_R_TYPE (irel->r_info) != R_XTENSA_ASM_EXPAND) 
+    return FALSE;
+  
+  opcode = get_expanded_call_opcode (contents + irel->r_offset,
+                                    sec->_raw_size - irel->r_offset);
+  
+  direct_call_opcode = swap_callx_for_call_opcode (opcode);
+  if (direct_call_opcode == XTENSA_UNDEFINED)
+    return FALSE;
+
+  /* Check and see that the target resolves.  */
+  r_reloc_init (&r_rel, abfd, irel);
+  if (!r_reloc_is_defined (&r_rel))
+    return FALSE;
+
+  target_sec = r_reloc_get_section (&r_rel);
+  target_offset = r_reloc_get_target_offset (&r_rel);
+
+  /* If the target is in a shared library, then it doesn't reach.  This
+     isn't supposed to come up because the compiler should never generate
+     non-PIC calls on systems that use shared libraries, but the linker
+     shouldn't crash regardless.  */
+  if (!target_sec->output_section)
+    return FALSE;
+      
+  /* For relocateable sections, we can only simplify when the output
+     section of the target is the same as the output section of the
+     source.  */
+  if (link_info->relocateable
+      && (target_sec->output_section != sec->output_section))
+    return FALSE;
+
+  self_address = (sec->output_section->vma
+                 + sec->output_offset + irel->r_offset + 3);
+  dest_address = (target_sec->output_section->vma
+                 + target_sec->output_offset + target_offset);
+      
+  *is_reachable_p = pcrel_reloc_fits
+    (xtensa_get_operand (xtensa_default_isa, direct_call_opcode, 0),
+     self_address, dest_address);
+
+  if ((self_address >> CALL_SEGMENT_BITS) !=
+      (dest_address >> CALL_SEGMENT_BITS))
+    return FALSE;
+
+  return TRUE;
+}
+
+
+static Elf_Internal_Rela *
+find_associated_l32r_irel (sec, contents, other_irel, internal_relocs)
+     asection *sec;
+     bfd_byte *contents;
+     Elf_Internal_Rela *other_irel;
+     Elf_Internal_Rela *internal_relocs;
+{
+  unsigned i;
+
+  for (i = 0; i < sec->reloc_count; i++) 
+    {
+      Elf_Internal_Rela *irel = &internal_relocs[i];
+
+      if (irel == other_irel)
+       continue;
+      if (irel->r_offset != other_irel->r_offset)
+       continue;
+      if (is_l32r_relocation (sec, contents, irel))
+       return irel;
+    }
+
+  return NULL;
+}
+
+/* First relaxation pass.  */
+
+/* If the section is relaxable (i.e., a literal section), check each
+   literal to see if it has the same value as another literal that has
+   already been seen, either in the current section or a previous one.
+   If so, add an entry to the per-section list of removed literals.  The
+   actual changes are deferred until the next pass.  */
+
+static bfd_boolean 
+remove_literals (abfd, sec, link_info, values)
+     bfd *abfd;
+     asection *sec;
+     struct bfd_link_info *link_info;
+     value_map_hash_table *values;
+{
+  xtensa_relax_info *relax_info;
+  bfd_byte *contents;
+  Elf_Internal_Rela *internal_relocs;
+  source_reloc *src_relocs;
+  bfd_boolean ok = TRUE;
+  int i;
+
+  /* Do nothing if it is not a relaxable literal section.  */
+  relax_info = get_xtensa_relax_info (sec);
+  BFD_ASSERT (relax_info);
+
+  if (!relax_info->is_relaxable_literal_section)
+    return ok;
+
+  internal_relocs = retrieve_internal_relocs (abfd, sec, 
+                                             link_info->keep_memory);
+
+  contents = retrieve_contents (abfd, sec, link_info->keep_memory);
+  if (contents == NULL && sec->_raw_size != 0)
+    {
+      ok = FALSE;
+      goto error_return;
+    }
+
+  /* Sort the source_relocs by target offset.  */
+  src_relocs = relax_info->src_relocs;
+  qsort (src_relocs, relax_info->src_count,
+        sizeof (source_reloc), source_reloc_compare);
+
+  for (i = 0; i < relax_info->src_count; i++)
+    {
+      source_reloc *rel;
+      Elf_Internal_Rela *irel = NULL;
+      literal_value val;
+      value_map *val_map;
+
+      rel = &src_relocs[i];
+      irel = get_irel_at_offset (sec, internal_relocs,
+                                rel->r_rel.target_offset);
+
+      /* If the target_offset for this relocation is the same as the
+        previous relocation, then we've already considered whether the
+        literal can be coalesced.  Skip to the next one....  */
+      if (i != 0 && (src_relocs[i-1].r_rel.target_offset
+                    == rel->r_rel.target_offset))
+       continue;
+
+      /* Check if the relocation was from an L32R that is being removed
+        because a CALLX was converted to a direct CALL, and check if
+        there are no other relocations to the literal.  */
+      if (rel->is_null
+         && (i == relax_info->src_count - 1
+             || (src_relocs[i+1].r_rel.target_offset
+                 != rel->r_rel.target_offset)))
+       {
+         /* Mark the unused literal so that it will be removed.  */
+         add_removed_literal (&relax_info->removed_list, &rel->r_rel, NULL);
+
+         /* Zero out the relocation on this literal location.  */
+         if (irel)
+           {
+             if (elf_hash_table (link_info)->dynamic_sections_created)
+               shrink_dynamic_reloc_sections (link_info, abfd, sec, irel);
+
+             irel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
+           }
+
+         continue;
+       }
+
+      /* Find the literal value.  */
+      r_reloc_init (&val.r_rel, abfd, irel);
+      BFD_ASSERT (rel->r_rel.target_offset < sec->_raw_size);
+      val.value = bfd_get_32 (abfd, contents + rel->r_rel.target_offset);
+          
+      /* Check if we've seen another literal with the same value.  */
+      val_map = get_cached_value (values, &val);
+      if (val_map != NULL) 
+       {
+         /* First check that THIS and all the other relocs to this
+            literal will FIT if we move them to the new address.  */
+
+         if (relocations_reach (rel, relax_info->src_count - i,
+                                &val_map->loc))
+           {
+             /* Mark that the literal will be coalesced.  */
+             add_removed_literal (&relax_info->removed_list,
+                                  &rel->r_rel, &val_map->loc);
+           }
+         else
+           {
+             /* Relocations do not reach -- do not remove this literal.  */
+             val_map->loc = rel->r_rel;
+           }
+       }
+      else
+       {
+         /* This is the first time we've seen this literal value.  */
+         BFD_ASSERT (sec == r_reloc_get_section (&rel->r_rel));
+         add_value_map (values, &val, &rel->r_rel);
+       }
+    }
+
+error_return:
+  release_contents (sec, contents);
+  release_internal_relocs (sec, internal_relocs);
+  return ok;
+}
+
+
+/* Check if the original relocations (presumably on L32R instructions)
+   identified by reloc[0..N] can be changed to reference the literal
+   identified by r_rel.  If r_rel is out of range for any of the
+   original relocations, then we don't want to coalesce the original
+   literal with the one at r_rel.  We only check reloc[0..N], where the
+   offsets are all the same as for reloc[0] (i.e., they're all
+   referencing the same literal) and where N is also bounded by the
+   number of remaining entries in the "reloc" array.  The "reloc" array
+   is sorted by target offset so we know all the entries for the same
+   literal will be contiguous.  */
+
+static bfd_boolean
+relocations_reach (reloc, remaining_relocs, r_rel)
+     source_reloc *reloc;
+     int remaining_relocs;
+     const r_reloc *r_rel;
+{
+  bfd_vma from_offset, source_address, dest_address;
+  asection *sec;
+  int i;
+
+  if (!r_reloc_is_defined (r_rel))
+    return FALSE;
+
+  sec = r_reloc_get_section (r_rel);
+  from_offset = reloc[0].r_rel.target_offset;
+
+  for (i = 0; i < remaining_relocs; i++)
+    {
+      if (reloc[i].r_rel.target_offset != from_offset)
+       break;
+
+      /* Ignore relocations that have been removed.  */
+      if (reloc[i].is_null)
+       continue;
+
+      /* The original and new output section for these must be the same
+         in order to coalesce.  */
+      if (r_reloc_get_section (&reloc[i].r_rel)->output_section
+         != sec->output_section)
+       return FALSE;
+
+      /* A NULL operand means it is not a PC-relative relocation, so
+         the literal can be moved anywhere.  */
+      if (reloc[i].opnd)
+       {
+         /* Otherwise, check to see that it fits.  */
+         source_address = (reloc[i].source_sec->output_section->vma
+                           + reloc[i].source_sec->output_offset
+                           + reloc[i].r_rel.rela.r_offset);
+         dest_address = (sec->output_section->vma
+                         + sec->output_offset
+                         + r_rel->target_offset);
+
+         if (!pcrel_reloc_fits (reloc[i].opnd, source_address, dest_address))
+           return FALSE;
+       }
+    }
+
+  return TRUE;
+}
+
+
+/* WARNING: linear search here.  If the relocation are in order by
+   address, we can use a faster binary search.  ALSO, we assume that
+   there is only 1 non-NONE relocation per address.  */
+
+static Elf_Internal_Rela *
+get_irel_at_offset (sec, internal_relocs, offset)
+     asection *sec;
+     Elf_Internal_Rela *internal_relocs;
+     bfd_vma offset;
+{
+  unsigned i;
+  if (!internal_relocs) 
+    return NULL;
+  for (i = 0; i < sec->reloc_count; i++)
+    {
+      Elf_Internal_Rela *irel = &internal_relocs[i];
+      if (irel->r_offset == offset
+         && ELF32_R_TYPE (irel->r_info) != R_XTENSA_NONE)
+       return irel;
+    }
+  return NULL;
+}
+
+\f
+/* Second relaxation pass.  */
+
+/* Modify all of the relocations to point to the right spot, and if this
+   is a relaxable section, delete the unwanted literals and fix the
+   cooked_size.  */
+
+bfd_boolean 
+relax_section (abfd, sec, link_info)
+     bfd *abfd;
+     asection *sec;
+     struct bfd_link_info *link_info;
+{
+  Elf_Internal_Rela *internal_relocs;
+  xtensa_relax_info *relax_info;
+  bfd_byte *contents;
+  bfd_boolean ok = TRUE;
+  unsigned i;
+
+  relax_info = get_xtensa_relax_info (sec);
+  BFD_ASSERT (relax_info);
+
+  /* Handle property sections (e.g., literal tables) specially.  */
+  if (xtensa_is_property_section (sec))
+    {
+      BFD_ASSERT (!relax_info->is_relaxable_literal_section);
+      return relax_property_section (abfd, sec, link_info);
+    }
+
+  internal_relocs = retrieve_internal_relocs (abfd, sec, 
+                                             link_info->keep_memory);
+  contents = retrieve_contents (abfd, sec, link_info->keep_memory);
+  if (contents == NULL && sec->_raw_size != 0)
+    {
+      ok = FALSE;
+      goto error_return;
+    }
+
+  if (internal_relocs)
+    {
+      for (i = 0; i < sec->reloc_count; i++) 
+       {
+         Elf_Internal_Rela *irel;
+         xtensa_relax_info *target_relax_info;
+         bfd_vma source_offset;
+         r_reloc r_rel;
+         unsigned r_type;
+         asection *target_sec;
+
+         /* Locally change the source address.
+            Translate the target to the new target address.
+            If it points to this section and has been removed,
+            NULLify it.
+            Write it back.  */
+
+         irel = &internal_relocs[i];
+         source_offset = irel->r_offset;
+
+         r_type = ELF32_R_TYPE (irel->r_info);
+         r_reloc_init (&r_rel, abfd, irel);
+       
+         if (relax_info->is_relaxable_literal_section)
+           {
+             if (r_type != R_XTENSA_NONE
+                 && find_removed_literal (&relax_info->removed_list,
+                                          irel->r_offset))
+               {
+                 /* Remove this relocation.  */
+                 if (elf_hash_table (link_info)->dynamic_sections_created)
+                   shrink_dynamic_reloc_sections (link_info, abfd, sec, irel);
+                 irel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
+                 irel->r_offset = offset_with_removed_literals
+                   (&relax_info->removed_list, irel->r_offset);
+                 continue;
+               }
+             source_offset =
+               offset_with_removed_literals (&relax_info->removed_list,
+                                             irel->r_offset);
+             irel->r_offset = source_offset;
+           }
+
+         target_sec = r_reloc_get_section (&r_rel);
+         target_relax_info = get_xtensa_relax_info (target_sec);
+
+         if (target_relax_info
+             && target_relax_info->is_relaxable_literal_section)
+           {
+             r_reloc new_rel;
+             reloc_bfd_fix *fix;
+
+             translate_reloc (&r_rel, &new_rel);
+
+             /* FIXME: If the relocation still references a section in
+                the same input file, the relocation should be modified
+                directly instead of adding a "fix" record.  */
+
+             fix = reloc_bfd_fix_init (sec, source_offset, r_type, 0,
+                                       r_reloc_get_section (&new_rel),
+                                       new_rel.target_offset);
+             add_fix (sec, fix);
+           }
+
+         pin_internal_relocs (sec, internal_relocs);
+       }
+    }
+
+  if (relax_info->is_relaxable_literal_section)
+    {
+      /* Walk through the contents and delete literals that are not needed 
+         anymore.  */
+
+      unsigned long size = sec->_cooked_size;
+      unsigned long removed = 0;
+
+      removed_literal *reloc = relax_info->removed_list.head;
+      for (; reloc; reloc = reloc->next) 
+       {
+         unsigned long upper = sec->_raw_size;
+         bfd_vma start = reloc->from.target_offset + 4;
+         if (reloc->next)
+           upper = reloc->next->from.target_offset;
+         if (upper - start != 0) 
+           {
+             BFD_ASSERT (start <= upper);
+             memmove (contents + start - removed - 4,
+                      contents + start,
+                      upper - start );
+             pin_contents (sec, contents);
+           }
+         removed += 4;
+         size -= 4;
+       }
+
+      /* Change the section size.  */
+      sec->_cooked_size = size;
+      /* Also shrink _raw_size.  (The code in relocate_section that
+        checks that relocations are within the section must use
+        _raw_size because of the way the stabs sections are relaxed;
+        shrinking _raw_size means that these checks will not be
+        unnecessarily lax.)  */
+      sec->_raw_size = size;
+    }
+  
+ error_return:
+  release_internal_relocs (sec, internal_relocs);
+  release_contents (sec, contents);
+  return ok;
+}
+
+
+/* Fix up a relocation to take account of removed literals.  */
+
+static void
+translate_reloc (orig_rel, new_rel)
+     const r_reloc *orig_rel;
+     r_reloc *new_rel;
+{
+  asection *sec;
+  xtensa_relax_info *relax_info;
+  removed_literal *removed;
+  unsigned long new_offset;
+
+  *new_rel = *orig_rel;
+
+  if (!r_reloc_is_defined (orig_rel))
+    return;
+  sec = r_reloc_get_section (orig_rel);
+
+  relax_info = get_xtensa_relax_info (sec);
+  BFD_ASSERT (relax_info);
+
+  if (!relax_info->is_relaxable_literal_section)
+    return;
+
+  /* Check if the original relocation is against a literal being removed.  */
+  removed = find_removed_literal (&relax_info->removed_list,
+                                 orig_rel->target_offset);
+  if (removed) 
+    {
+      asection *new_sec;
+
+      /* The fact that there is still a relocation to this literal indicates
+        that the literal is being coalesced, not simply removed.  */
+      BFD_ASSERT (removed->to.abfd != NULL);
+
+      /* This was moved to some other address (possibly in another section). */
+      *new_rel = removed->to;
+      new_sec = r_reloc_get_section (new_rel);
+      if (new_sec != sec) 
+       {
+         sec = new_sec;
+         relax_info = get_xtensa_relax_info (sec);
+         if (!relax_info || !relax_info->is_relaxable_literal_section)
+           return;
+       }
+    }
+
+  /* ...and the target address may have been moved within its section.  */
+  new_offset = offset_with_removed_literals (&relax_info->removed_list,
+                                            new_rel->target_offset);
+
+  /* Modify the offset and addend.  */
+  new_rel->target_offset = new_offset;
+  new_rel->rela.r_addend += (new_offset - new_rel->target_offset);
+}
+
+
+/* For dynamic links, there may be a dynamic relocation for each
+   literal.  The number of dynamic relocations must be computed in
+   size_dynamic_sections, which occurs before relaxation.  When a
+   literal is removed, this function checks if there is a corresponding
+   dynamic relocation and shrinks the size of the appropriate dynamic
+   relocation section accordingly.  At this point, the contents of the
+   dynamic relocation sections have not yet been filled in, so there's
+   nothing else that needs to be done.  */
+
+static void
+shrink_dynamic_reloc_sections (info, abfd, input_section, rel)
+     struct bfd_link_info *info;
+     bfd *abfd;
+     asection *input_section;
+     Elf_Internal_Rela *rel;
+{
+  Elf_Internal_Shdr *symtab_hdr;
+  struct elf_link_hash_entry **sym_hashes;
+  unsigned long r_symndx;
+  int r_type;
+  struct elf_link_hash_entry *h;
+  bfd_boolean dynamic_symbol;
+
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  sym_hashes = elf_sym_hashes (abfd);
+
+  r_type = ELF32_R_TYPE (rel->r_info);
+  r_symndx = ELF32_R_SYM (rel->r_info);
+
+  if (r_symndx < symtab_hdr->sh_info)
+    h = NULL;
+  else
+    h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+  dynamic_symbol = xtensa_elf_dynamic_symbol_p (info, h);
+
+  if ((r_type == R_XTENSA_32 || r_type == R_XTENSA_PLT)
+      && (input_section->flags & SEC_ALLOC) != 0
+      && (dynamic_symbol || info->shared))
+    {
+      bfd *dynobj;
+      const char *srel_name;
+      asection *srel;
+      bfd_boolean is_plt = FALSE;
+
+      dynobj = elf_hash_table (info)->dynobj;
+      BFD_ASSERT (dynobj != NULL);
+
+      if (dynamic_symbol && r_type == R_XTENSA_PLT)
+       {
+         srel_name = ".rela.plt";
+         is_plt = TRUE;
+       }
+      else
+       srel_name = ".rela.got";
+
+      /* Reduce size of the .rela.* section by one reloc.  */
+      srel = bfd_get_section_by_name (dynobj, srel_name);
+      BFD_ASSERT (srel != NULL);
+      BFD_ASSERT (srel->_cooked_size >= sizeof (Elf32_External_Rela));
+      srel->_cooked_size -= sizeof (Elf32_External_Rela);
+
+      /* Also shrink _raw_size.  (This seems wrong but other bfd code seems
+        to assume that linker-created sections will never be relaxed and
+        hence _raw_size must always equal _cooked_size.) */
+      srel->_raw_size = srel->_cooked_size;
+
+      if (is_plt)
+       {
+         asection *splt, *sgotplt, *srelgot;
+         int reloc_index, chunk;
+
+         /* Find the PLT reloc index of the entry being removed.  This
+            is computed from the size of ".rela.plt".  It is needed to
+            figure out which PLT chunk to resize.  Usually "last index
+            = size - 1" since the index starts at zero, but in this
+            context, the size has just been decremented so there's no
+            need to subtract one.  */
+         reloc_index = srel->_cooked_size / sizeof (Elf32_External_Rela);
+
+         chunk = reloc_index / PLT_ENTRIES_PER_CHUNK;
+         splt = elf_xtensa_get_plt_section (dynobj, chunk);
+         sgotplt = elf_xtensa_get_gotplt_section (dynobj, chunk);
+         BFD_ASSERT (splt != NULL && sgotplt != NULL);
+
+         /* Check if an entire PLT chunk has just been eliminated.  */
+         if (reloc_index % PLT_ENTRIES_PER_CHUNK == 0)
+           {
+             /* The two magic GOT entries for that chunk can go away.  */
+             srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+             BFD_ASSERT (srelgot != NULL);
+             srelgot->reloc_count -= 2;
+             srelgot->_cooked_size -= 2 * sizeof (Elf32_External_Rela);
+             /* Shrink _raw_size (see comment above).  */
+             srelgot->_raw_size = srelgot->_cooked_size;
+
+             sgotplt->_cooked_size -= 8;
+
+             /* There should be only one entry left (and it will be
+                removed below).  */
+             BFD_ASSERT (sgotplt->_cooked_size == 4);
+             BFD_ASSERT (splt->_cooked_size == PLT_ENTRY_SIZE);
+           }
+
+         BFD_ASSERT (sgotplt->_cooked_size >= 4);
+         BFD_ASSERT (splt->_cooked_size >= PLT_ENTRY_SIZE);
+
+         sgotplt->_cooked_size -= 4;
+         splt->_cooked_size -= PLT_ENTRY_SIZE;
+
+         /* Shrink _raw_sizes (see comment above).  */
+         sgotplt->_raw_size = sgotplt->_cooked_size;
+         splt->_raw_size = splt->_cooked_size;
+       }
+    }
+}
+
+
+/* This is similar to relax_section except that when a target is moved,
+   we shift addresses up.  We also need to modify the size.  This
+   algorithm does NOT allow for relocations into the middle of the
+   property sections.  */
+
+static bfd_boolean 
+relax_property_section (abfd, sec, link_info)
+     bfd *abfd;
+     asection *sec;
+     struct bfd_link_info *link_info;
+{
+  Elf_Internal_Rela *internal_relocs;
+  bfd_byte *contents;
+  unsigned i, nexti;
+  bfd_boolean ok = TRUE;
+
+  internal_relocs = retrieve_internal_relocs (abfd, sec, 
+                                             link_info->keep_memory);
+  contents = retrieve_contents (abfd, sec, link_info->keep_memory);
+  if (contents == NULL && sec->_raw_size != 0)
+    {
+      ok = FALSE;
+      goto error_return;
+    }
+
+  if (internal_relocs) 
+    {
+      for (i = 0; i < sec->reloc_count; i++) 
+       {
+         Elf_Internal_Rela *irel;
+         xtensa_relax_info *target_relax_info;
+         r_reloc r_rel;
+         unsigned r_type;
+         asection *target_sec;
+
+         /* Locally change the source address.
+            Translate the target to the new target address.
+            If it points to this section and has been removed, MOVE IT.
+            Also, don't forget to modify the associated SIZE at
+            (offset + 4).  */
+
+         irel = &internal_relocs[i];
+         r_type = ELF32_R_TYPE (irel->r_info);
+         if (r_type == R_XTENSA_NONE)
+           continue;
+
+         r_reloc_init (&r_rel, abfd, irel);
+
+         target_sec = r_reloc_get_section (&r_rel);
+         target_relax_info = get_xtensa_relax_info (target_sec);
+
+         if (target_relax_info
+             && target_relax_info->is_relaxable_literal_section)
+           {
+             /* Translate the relocation's destination.  */
+             bfd_vma new_offset;
+             bfd_vma new_end_offset;
+             bfd_byte *size_p;
+             long old_size, new_size;
+
+             new_offset =
+               offset_with_removed_literals (&target_relax_info->removed_list,
+                                             r_rel.target_offset);
+
+             /* Assert that we are not out of bounds.  */
+             size_p = &contents[irel->r_offset + 4];
+             old_size = bfd_get_32 (abfd, &contents[irel->r_offset + 4]);
+
+             new_end_offset =
+               offset_with_removed_literals (&target_relax_info->removed_list,
+                                             r_rel.target_offset + old_size);
+             
+             new_size = new_end_offset - new_offset;
+             if (new_size != old_size)
+               {
+                 bfd_put_32 (abfd, new_size, size_p);
+                 pin_contents (sec, contents);
+               }
+             
+             if (new_offset != r_rel.target_offset)
+               {
+                 bfd_vma diff = new_offset - r_rel.target_offset;
+                 irel->r_addend += diff;
+                 pin_internal_relocs (sec, internal_relocs);
+               }
+           }
+       }
+    }
+
+  /* Combine adjacent property table entries.  This is also done in
+     finish_dynamic_sections() but at that point it's too late to
+     reclaim the space in the output section, so we do this twice.  */
+
+  if (internal_relocs)
+    {
+      Elf_Internal_Rela *last_irel = NULL;
+      int removed_bytes = 0;
+      bfd_vma offset, last_irel_offset;
+      bfd_vma section_size;
+
+      /* Walk over memory and irels at the same time.
+         This REQUIRES that the internal_relocs be sorted by offset.  */
+      qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
+            internal_reloc_compare);
+      nexti = 0; /* Index into internal_relocs.  */
+
+      pin_internal_relocs (sec, internal_relocs);
+      pin_contents (sec, contents);
+
+      last_irel_offset = (bfd_vma) -1;
+      section_size = (sec->_cooked_size ? sec->_cooked_size : sec->_raw_size);
+      BFD_ASSERT (section_size % 8 == 0);
+
+      for (offset = 0; offset < section_size; offset += 8)
+       {
+         Elf_Internal_Rela *irel, *next_irel;
+         bfd_vma bytes_to_remove, size, actual_offset;
+         bfd_boolean remove_this_irel;
+
+         irel = NULL;
+         next_irel = NULL;
+
+         /* Find the next two relocations (if there are that many left),
+            skipping over any R_XTENSA_NONE relocs.  On entry, "nexti" is
+            the starting reloc index.  After these two loops, "i"
+            is the index of the first non-NONE reloc past that starting
+            index, and "nexti" is the index for the next non-NONE reloc
+            after "i".  */
+
+         for (i = nexti; i < sec->reloc_count; i++)
+           {
+             if (ELF32_R_TYPE (internal_relocs[i].r_info) != R_XTENSA_NONE)
+               {
+                 irel = &internal_relocs[i];
+                 break;
+               }
+             internal_relocs[i].r_offset -= removed_bytes;
+           }
+
+         for (nexti = i + 1; nexti < sec->reloc_count; nexti++)
+           {
+             if (ELF32_R_TYPE (internal_relocs[nexti].r_info)
+                 != R_XTENSA_NONE)
+               {
+                 next_irel = &internal_relocs[nexti];
+                 break;
+               }
+             internal_relocs[nexti].r_offset -= removed_bytes;
+           }
+
+         remove_this_irel = FALSE;
+         bytes_to_remove = 0;
+         actual_offset = offset - removed_bytes;
+         size = bfd_get_32 (abfd, &contents[actual_offset + 4]);
+
+         /* Check that the irels are sorted by offset,
+            with only one per address.  */
+         BFD_ASSERT (!irel || (int) irel->r_offset > (int) last_irel_offset); 
+         BFD_ASSERT (!next_irel || next_irel->r_offset > irel->r_offset);
+
+         /* Make sure there isn't a reloc on the size field.  */
+         if (irel && irel->r_offset == offset + 4)
+           {
+             irel->r_offset -= removed_bytes;
+             last_irel_offset = irel->r_offset;
+           }
+         else if (next_irel && next_irel->r_offset == offset + 4)
+           {
+             nexti += 1;
+             irel->r_offset -= removed_bytes;
+             next_irel->r_offset -= removed_bytes;
+             last_irel_offset = next_irel->r_offset;
+           }
+         else if (size == 0)
+           {
+             /* Always remove entries with zero size.  */
+             bytes_to_remove = 8;
+             if (irel && irel->r_offset == offset)
+               {
+                 remove_this_irel = TRUE;
+
+                 irel->r_offset -= removed_bytes;
+                 last_irel_offset = irel->r_offset;
+               }
+           }
+         else if (irel && irel->r_offset == offset)
+           {
+             if (ELF32_R_TYPE (irel->r_info) == R_XTENSA_32)
+               {
+                 if (last_irel)
+                   {
+                     bfd_vma old_size = 
+                       bfd_get_32 (abfd, &contents[last_irel->r_offset + 4]);
+                     bfd_vma old_address = 
+                       (last_irel->r_addend 
+                        + bfd_get_32 (abfd, &contents[last_irel->r_offset]));
+                     bfd_vma new_address = 
+                       (irel->r_addend 
+                        + bfd_get_32 (abfd, &contents[actual_offset]));
+
+                     if ((ELF32_R_SYM (irel->r_info) ==
+                          ELF32_R_SYM (last_irel->r_info))
+                         && (old_address + old_size == new_address)) 
+                       {
+                         /* fix the old size */
+                         bfd_put_32 (abfd, old_size + size,
+                                     &contents[last_irel->r_offset + 4]);
+                         bytes_to_remove = 8;
+                         remove_this_irel = TRUE;
+                       }
+                     else
+                       last_irel = irel;
+                   }
+                 else
+                   last_irel = irel;
+               }
+
+             irel->r_offset -= removed_bytes;
+             last_irel_offset = irel->r_offset;
+           }
+
+         if (remove_this_irel)
+           {
+             irel->r_info = ELF32_R_INFO (0, R_XTENSA_NONE);
+             irel->r_offset -= bytes_to_remove;
+           }
+
+         if (bytes_to_remove != 0)
+           {
+             removed_bytes += bytes_to_remove;
+             if (offset + 8 < section_size)
+               memmove (&contents[actual_offset],
+                        &contents[actual_offset+8],
+                        section_size - offset - 8);
+           }
+       }
+
+      if (removed_bytes) 
+       {
+         /* Clear the removed bytes.  */
+         memset (&contents[section_size - removed_bytes], 0, removed_bytes);
+
+         sec->_cooked_size = section_size - removed_bytes;
+         /* Also shrink _raw_size.  (The code in relocate_section that
+            checks that relocations are within the section must use
+            _raw_size because of the way the stabs sections are
+            relaxed; shrinking _raw_size means that these checks will
+            not be unnecessarily lax.)  */
+         sec->_raw_size = sec->_cooked_size;
+       }
+    }
+         
+ error_return:
+  release_internal_relocs (sec, internal_relocs);
+  release_contents (sec, contents);
+  return ok;
+}
+
+\f
+/* Third relaxation pass.  */
+
+/* Change symbol values to account for removed literals.  */
+
+bfd_boolean 
+relax_section_symbols (abfd, sec)
+     bfd *abfd;
+     asection *sec;
+{
+  xtensa_relax_info *relax_info;
+  unsigned int sec_shndx;
+  Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Sym *isymbuf;
+  unsigned i, num_syms, num_locals;
+
+  relax_info = get_xtensa_relax_info (sec);
+  BFD_ASSERT (relax_info);
+
+  if (!relax_info->is_relaxable_literal_section)
+    return TRUE;
+
+  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  isymbuf = retrieve_local_syms (abfd);
+
+  num_syms = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
+  num_locals = symtab_hdr->sh_info;
+
+  /* Adjust the local symbols defined in this section.  */
+  for (i = 0; i < num_locals; i++)
+    {
+      Elf_Internal_Sym *isym = &isymbuf[i];
+
+      if (isym->st_shndx == sec_shndx)
+       {
+         bfd_vma new_address = offset_with_removed_literals
+           (&relax_info->removed_list, isym->st_value);
+         if (new_address != isym->st_value)
+           isym->st_value = new_address;
+       }
+    }
+
+  /* Now adjust the global symbols defined in this section.  */
+  for (i = 0; i < (num_syms - num_locals); i++)
+    {
+      struct elf_link_hash_entry *sym_hash;
+
+      sym_hash = elf_sym_hashes (abfd)[i];
+
+      if (sym_hash->root.type == bfd_link_hash_warning)
+       sym_hash = (struct elf_link_hash_entry *) sym_hash->root.u.i.link;
+
+      if ((sym_hash->root.type == bfd_link_hash_defined
+          || sym_hash->root.type == bfd_link_hash_defweak)
+         && sym_hash->root.u.def.section == sec)
+       {
+         bfd_vma new_address = offset_with_removed_literals
+           (&relax_info->removed_list, sym_hash->root.u.def.value);
+         if (new_address != sym_hash->root.u.def.value)
+           sym_hash->root.u.def.value = new_address;
+       }
+    }
+
+  return TRUE;
+}
+
+\f
+/* "Fix" handling functions, called while performing relocations.  */
+
+static void
+do_fix_for_relocateable_link (rel, input_bfd, input_section)
+     Elf_Internal_Rela *rel;
+     bfd *input_bfd;
+     asection *input_section;
+{
+  r_reloc r_rel;
+  asection *sec, *old_sec;
+  bfd_vma old_offset;
+  int r_type = ELF32_R_TYPE (rel->r_info);
+  reloc_bfd_fix *fix_list;
+  reloc_bfd_fix *fix;
+
+  if (r_type == R_XTENSA_NONE)
+    return;
+
+  fix_list = (get_xtensa_relax_info (input_section))->fix_list;
+  if (fix_list == NULL)
+    return;
+
+  fix = get_bfd_fix (fix_list, input_section, rel->r_offset, r_type);
+  if (fix == NULL)
+    return;
+
+  r_reloc_init (&r_rel, input_bfd, rel);
+  old_sec = r_reloc_get_section (&r_rel);
+  old_offset = r_reloc_get_target_offset (&r_rel);
+             
+  if (old_sec == NULL || !r_reloc_is_defined (&r_rel))
+    {
+      BFD_ASSERT (r_type == R_XTENSA_ASM_EXPAND);
+      /* Leave it be.  Resolution will happen in a later stage.  */
+    }
+  else
+    {
+      sec = fix->target_sec;
+      rel->r_addend += ((sec->output_offset + fix->target_offset)
+                       - (old_sec->output_offset + old_offset));
+    }
+}
+
+
+static void
+do_fix_for_final_link (rel, input_section, relocationp)
+     Elf_Internal_Rela *rel;
+     asection *input_section;
+     bfd_vma *relocationp;
+{
+  asection *sec;
+  int r_type = ELF32_R_TYPE (rel->r_info);
+  reloc_bfd_fix *fix_list;
+  reloc_bfd_fix *fix;
+
+  if (r_type == R_XTENSA_NONE)
+    return;
+
+  fix_list = (get_xtensa_relax_info (input_section))->fix_list;
+  if (fix_list == NULL)
+    return;
+
+  fix = get_bfd_fix (fix_list, input_section, rel->r_offset, r_type);
+  if (fix == NULL)
+    return;
+
+  sec = fix->target_sec;
+  *relocationp = (sec->output_section->vma
+                 + sec->output_offset
+                 + fix->target_offset - rel->r_addend);
+}
+
+\f
+/* Miscellaneous utility functions....  */
+
+static asection *
+elf_xtensa_get_plt_section (dynobj, chunk)
+     bfd *dynobj;
+     int chunk;
+{
+  char plt_name[10];
+
+  if (chunk == 0)
+    return bfd_get_section_by_name (dynobj, ".plt");
+
+  sprintf (plt_name, ".plt.%u", chunk);
+  return bfd_get_section_by_name (dynobj, plt_name);
+}
+
+
+static asection *
+elf_xtensa_get_gotplt_section (dynobj, chunk)
+     bfd *dynobj;
+     int chunk;
+{
+  char got_name[14];
+
+  if (chunk == 0)
+    return bfd_get_section_by_name (dynobj, ".got.plt");
+
+  sprintf (got_name, ".got.plt.%u", chunk);
+  return bfd_get_section_by_name (dynobj, got_name);
+}
+
+
+/* Get the input section for a given symbol index.
+   If the symbol is:
+   . a section symbol, return the section;
+   . a common symbol, return the common section;
+   . an undefined symbol, return the undefined section;
+   . an indirect symbol, follow the links;
+   . an absolute value, return the absolute section.  */
+
+static asection *
+get_elf_r_symndx_section (abfd, r_symndx)
+     bfd *abfd;
+     unsigned long r_symndx;
+{
+  Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  asection *target_sec = NULL;
+  if (r_symndx < symtab_hdr->sh_info) 
+    {
+      Elf_Internal_Sym *isymbuf;
+      unsigned int section_index;
+
+      isymbuf = retrieve_local_syms (abfd);
+      section_index = isymbuf[r_symndx].st_shndx;
+
+      if (section_index == SHN_UNDEF)
+       target_sec = bfd_und_section_ptr;
+      else if (section_index > 0 && section_index < SHN_LORESERVE)
+       target_sec = bfd_section_from_elf_index (abfd, section_index);
+      else if (section_index == SHN_ABS)
+       target_sec = bfd_abs_section_ptr;
+      else if (section_index == SHN_COMMON)
+       target_sec = bfd_com_section_ptr;
+      else 
+       /* Who knows?  */
+       target_sec = NULL;
+    }
+  else
+    {
+      unsigned long indx = r_symndx - symtab_hdr->sh_info;
+      struct elf_link_hash_entry *h = elf_sym_hashes (abfd)[indx];
+
+      while (h->root.type == bfd_link_hash_indirect
+             || h->root.type == bfd_link_hash_warning)
+        h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+      switch (h->root.type)
+       {
+       case bfd_link_hash_defined:
+       case  bfd_link_hash_defweak:
+         target_sec = h->root.u.def.section;
+         break;
+       case bfd_link_hash_common:
+         target_sec = bfd_com_section_ptr;
+         break;
+       case bfd_link_hash_undefined:
+       case bfd_link_hash_undefweak:
+         target_sec = bfd_und_section_ptr;
+         break;
+       default: /* New indirect warning.  */
+         target_sec = bfd_und_section_ptr;
+         break;
+       }
+    }
+  return target_sec;
+}
+
+
+static struct elf_link_hash_entry *
+get_elf_r_symndx_hash_entry (abfd, r_symndx)
+     bfd *abfd;
+     unsigned long r_symndx;
+{
+  unsigned long indx;
+  struct elf_link_hash_entry *h;
+  Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+
+  if (r_symndx < symtab_hdr->sh_info)
+    return NULL;
+  
+  indx = r_symndx - symtab_hdr->sh_info;
+  h = elf_sym_hashes (abfd)[indx];
+  while (h->root.type == bfd_link_hash_indirect
+        || h->root.type == bfd_link_hash_warning)
+    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+  return h;
+}
+
+
+/* Get the section-relative offset for a symbol number.  */
+
+static bfd_vma
+get_elf_r_symndx_offset (abfd, r_symndx)
+     bfd *abfd;
+     unsigned long r_symndx;
+{
+  Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  bfd_vma offset = 0;
+
+  if (r_symndx < symtab_hdr->sh_info) 
+    {
+      Elf_Internal_Sym *isymbuf;
+      isymbuf = retrieve_local_syms (abfd);
+      offset = isymbuf[r_symndx].st_value;
+    }
+  else
+    {
+      unsigned long indx = r_symndx - symtab_hdr->sh_info;
+      struct elf_link_hash_entry *h =
+       elf_sym_hashes (abfd)[indx];
+
+      while (h->root.type == bfd_link_hash_indirect
+             || h->root.type == bfd_link_hash_warning)
+       h = (struct elf_link_hash_entry *) h->root.u.i.link;
+      if (h->root.type == bfd_link_hash_defined
+          || h->root.type == bfd_link_hash_defweak)
+       offset = h->root.u.def.value;
+    }
+  return offset;
+}
+
+
+static bfd_boolean
+pcrel_reloc_fits (opnd, self_address, dest_address)
+     xtensa_operand opnd;
+     bfd_vma self_address;
+     bfd_vma dest_address;
+{
+  uint32 new_address =
+    xtensa_operand_do_reloc (opnd, dest_address, self_address);
+  return (xtensa_operand_encode (opnd, &new_address)
+         == xtensa_encode_result_ok);
+}
+
+
+static bfd_boolean 
+xtensa_is_property_section (sec)
+     asection *sec;
+{
+  static int len = sizeof (".gnu.linkonce.t.") - 1;
+
+  return (strcmp (".xt.insn", sec->name) == 0
+         || strcmp (".xt.lit", sec->name) == 0
+         || strncmp (".gnu.linkonce.x.", sec->name, len) == 0
+         || strncmp (".gnu.linkonce.p.", sec->name, len) == 0);
+}
+
+
+static bfd_boolean
+is_literal_section (sec)
+     asection *sec;
+{
+  /* FIXME: the current definition of this leaves a lot to be desired....  */
+  if (sec == NULL || sec->name == NULL)
+    return FALSE;
+  return (strstr (sec->name, "literal") != NULL);
+}
+
+
+static int
+internal_reloc_compare (ap, bp)
+     const PTR ap;
+     const PTR bp;
+{
+  const Elf_Internal_Rela *a = (const Elf_Internal_Rela *) ap;
+  const Elf_Internal_Rela *b = (const Elf_Internal_Rela *) bp;
+
+  return (a->r_offset - b->r_offset);
+}
+
+
+static bfd_boolean
+get_is_linkonce_section (abfd, sec)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *sec;
+{
+  flagword flags, link_once_flags;
+  bfd_boolean is_linkonce = FALSE;;
+
+  flags = bfd_get_section_flags (abfd, sec);
+  link_once_flags = (flags & SEC_LINK_ONCE);
+  if (link_once_flags != 0)
+    is_linkonce = TRUE;
+
+  /* In order for this to be useful to the assembler
+     before the linkonce flag is set we need to
+     check for the GNU extension name.  */
+  if (!is_linkonce &&
+      strncmp (sec->name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0)
+    is_linkonce = TRUE;
+  
+  return is_linkonce;
+}
+
+
+char *
+xtensa_get_property_section_name (abfd, sec, base_name)
+     bfd *abfd;
+     asection *sec;
+     const char * base_name;
+{
+  char *table_sec_name = NULL;
+  bfd_boolean is_linkonce;
+
+  is_linkonce = get_is_linkonce_section (abfd, sec);
+
+  if (!is_linkonce)
+    {
+      table_sec_name = strdup (base_name);
+    }
+  else
+    {
+      static size_t prefix_len = sizeof (".gnu.linkonce.t.") - 1;
+      size_t len = strlen (sec->name) + 1;
+      char repl_char = '\0';
+      const char *segname = sec->name;
+
+      if (strncmp (segname, ".gnu.linkonce.t.", prefix_len) == 0)
+       {
+         if (strcmp (base_name, ".xt.insn") == 0) 
+           repl_char = 'x';
+         else if (strcmp (base_name, ".xt.lit") == 0) 
+           repl_char = 'p';
+       }
+      
+      if (repl_char != '\0')
+       {
+         char *name = (char *) bfd_malloc (len);
+         memcpy (name, sec->name, len);
+         name[prefix_len - 2] = repl_char;
+         table_sec_name = name;
+       }
+      else
+       {
+         size_t base_len = strlen (base_name) + 1;
+         char *name = (char *) bfd_malloc (len + base_len);
+         memcpy (name, sec->name, len - 1);
+         memcpy (name + len - 1, base_name, base_len);
+         table_sec_name = name;
+       }
+    }
+
+  return table_sec_name;
+}
+
+\f
+/* Other functions called directly by the linker.  */
+
+bfd_boolean
+xtensa_callback_required_dependence (abfd, sec, link_info, callback, closure)
+     bfd *abfd;
+     asection *sec;
+     struct bfd_link_info *link_info;
+     deps_callback_t callback;
+     PTR closure;
+{
+  Elf_Internal_Rela *internal_relocs;
+  bfd_byte *contents;
+  unsigned i;
+  bfd_boolean ok = TRUE;
+
+  /* ".plt*" sections have no explicit relocations but they contain L32R
+     instructions that reference the corresponding ".got.plt*" sections.  */
+  if ((sec->flags & SEC_LINKER_CREATED) != 0
+      && strncmp (sec->name, ".plt", 4) == 0)
+    {
+      asection *sgotplt;
+
+      /* Find the corresponding ".got.plt*" section.  */
+      if (sec->name[4] == '\0')
+       sgotplt = bfd_get_section_by_name (sec->owner, ".got.plt");
+      else
+       {
+         char got_name[14];
+         int chunk = 0;
+
+         BFD_ASSERT (sec->name[4] == '.');
+         chunk = strtol (&sec->name[5], NULL, 10);
+
+         sprintf (got_name, ".got.plt.%u", chunk);
+         sgotplt = bfd_get_section_by_name (sec->owner, got_name);
+       }
+      BFD_ASSERT (sgotplt);
+
+      /* Assume worst-case offsets: L32R at the very end of the ".plt"
+        section referencing a literal at the very beginning of
+        ".got.plt".  This is very close to the real dependence, anyway.  */
+      (*callback) (sec, sec->_raw_size, sgotplt, 0, closure);
+    }
+
+  internal_relocs = retrieve_internal_relocs (abfd, sec, 
+                                             link_info->keep_memory);
+  if (internal_relocs == NULL
+      || sec->reloc_count == 0) 
+    return ok;
+
+  /* Cache the contents for the duration of this scan.  */
+  contents = retrieve_contents (abfd, sec, link_info->keep_memory);
+  if (contents == NULL && sec->_raw_size != 0)
+    {
+      ok = FALSE;
+      goto error_return;
+    }
+
+  if (xtensa_default_isa == NULL)
+    xtensa_isa_init ();
+
+  for (i = 0; i < sec->reloc_count; i++) 
+    {
+      Elf_Internal_Rela *irel = &internal_relocs[i];
+      if (is_l32r_relocation (sec, contents, irel))
+       {
+         r_reloc l32r_rel;
+         asection *target_sec;
+         bfd_vma target_offset;
+         
+         r_reloc_init (&l32r_rel, abfd, irel);
+         target_sec = NULL;
+         target_offset = 0;
+         /* L32Rs must be local to the input file.  */
+         if (r_reloc_is_defined (&l32r_rel))
+           {
+             target_sec = r_reloc_get_section (&l32r_rel);
+             target_offset = r_reloc_get_target_offset (&l32r_rel);
+           }
+         (*callback) (sec, irel->r_offset, target_sec, target_offset,
+                      closure);
+       }
+    }
+
+ error_return:
+  release_internal_relocs (sec, internal_relocs);
+  release_contents (sec, contents);
+  return ok;
+}
+
+\f
+#ifndef ELF_ARCH
+#define TARGET_LITTLE_SYM              bfd_elf32_xtensa_le_vec
+#define TARGET_LITTLE_NAME             "elf32-xtensa-le"
+#define TARGET_BIG_SYM                 bfd_elf32_xtensa_be_vec
+#define TARGET_BIG_NAME                        "elf32-xtensa-be"
+#define ELF_ARCH                       bfd_arch_xtensa
+
+/* The new EM_XTENSA value will be recognized beginning in the Xtensa T1040
+   release. However, we still have to generate files with the EM_XTENSA_OLD
+   value so that pre-T1040 tools can read the files.  As soon as we stop
+   caring about pre-T1040 tools, the following two values should be
+   swapped. At the same time, any other code that uses EM_XTENSA_OLD
+   (e.g., prep_headers() in elf.c) should be changed to use EM_XTENSA.  */
+#define ELF_MACHINE_CODE               EM_XTENSA_OLD
+#define ELF_MACHINE_ALT1               EM_XTENSA
+
+#if XCHAL_HAVE_MMU
+#define ELF_MAXPAGESIZE                        (1 << XCHAL_MMU_MIN_PTE_PAGE_SIZE)
+#else /* !XCHAL_HAVE_MMU */
+#define ELF_MAXPAGESIZE                        1
+#endif /* !XCHAL_HAVE_MMU */
+#endif /* ELF_ARCH */
+
+#define elf_backend_can_gc_sections    1
+#define elf_backend_can_refcount       1
+#define elf_backend_plt_readonly       1
+#define elf_backend_got_header_size    4
+#define elf_backend_want_dynbss                0
+#define elf_backend_want_got_plt       1
+
+#define elf_info_to_howto                   elf_xtensa_info_to_howto_rela
+
+#define bfd_elf32_bfd_final_link            bfd_elf32_bfd_final_link
+#define bfd_elf32_bfd_merge_private_bfd_data elf_xtensa_merge_private_bfd_data
+#define bfd_elf32_new_section_hook          elf_xtensa_new_section_hook
+#define bfd_elf32_bfd_print_private_bfd_data elf_xtensa_print_private_bfd_data
+#define bfd_elf32_bfd_relax_section         elf_xtensa_relax_section
+#define bfd_elf32_bfd_reloc_type_lookup             elf_xtensa_reloc_type_lookup
+#define bfd_elf32_bfd_set_private_flags             elf_xtensa_set_private_flags
+
+#define elf_backend_adjust_dynamic_symbol    elf_xtensa_adjust_dynamic_symbol
+#define elf_backend_check_relocs            elf_xtensa_check_relocs
+#define elf_backend_copy_indirect_symbol     elf_xtensa_copy_indirect_symbol
+#define elf_backend_create_dynamic_sections  elf_xtensa_create_dynamic_sections
+#define elf_backend_discard_info            elf_xtensa_discard_info
+#define elf_backend_ignore_discarded_relocs  elf_xtensa_ignore_discarded_relocs
+#define elf_backend_final_write_processing   elf_xtensa_final_write_processing
+#define elf_backend_finish_dynamic_sections  elf_xtensa_finish_dynamic_sections
+#define elf_backend_finish_dynamic_symbol    elf_xtensa_finish_dynamic_symbol
+#define elf_backend_gc_mark_hook            elf_xtensa_gc_mark_hook
+#define elf_backend_gc_sweep_hook           elf_xtensa_gc_sweep_hook
+#define elf_backend_grok_prstatus           elf_xtensa_grok_prstatus
+#define elf_backend_grok_psinfo                     elf_xtensa_grok_psinfo
+#define elf_backend_hide_symbol                     elf_xtensa_hide_symbol
+#define elf_backend_modify_segment_map      elf_xtensa_modify_segment_map
+#define elf_backend_object_p                elf_xtensa_object_p
+#define elf_backend_reloc_type_class        elf_xtensa_reloc_type_class
+#define elf_backend_relocate_section        elf_xtensa_relocate_section
+#define elf_backend_size_dynamic_sections    elf_xtensa_size_dynamic_sections
+
+#include "elf32-target.h"
diff --git a/bfd/po/zh_CN.po b/bfd/po/zh_CN.po
new file mode 100644 (file)
index 0000000..a7ca6d7
--- /dev/null
@@ -0,0 +1,2702 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# Wang Li <charles@linux.net.cn>, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: bfd 2.12.91\n"
+"POT-Creation-Date: 2002-07-23 15:55-0400\n"
+"PO-Revision-Date: 2003-03-11 09:46+0800\n"
+"Last-Translator: Wang Li <charles@linux.net.cn>\n"
+"Language-Team: Chinese (simplified) <i18n-translation@lists.linux.net.cn>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=gb2312\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: aout-adobe.c:197
+#, c-format
+msgid "%s: Unknown section type in a.out.adobe file: %x\n"
+msgstr "%s£ºa.out.adobe ÎļþÖнڵÄÀàÐÍδ֪£º%x\n"
+
+#: aout-cris.c:208
+#, c-format
+msgid "%s: Invalid relocation type exported: %d"
+msgstr "%s£ºµ¼³öÎÞЧµÄÖØ¶¨Î»ÀàÐÍ£º%d"
+
+#: aout-cris.c:252
+#, c-format
+msgid "%s: Invalid relocation type imported: %d"
+msgstr "%s£ºµ¼ÈëÎÞЧµÄÖØ¶¨Î»ÀàÐÍ£º%d"
+
+#: aout-cris.c:263
+#, c-format
+msgid "%s: Bad relocation record imported: %d"
+msgstr "%s£ºµ¼Èë´íÎóµÄÖØ¶¨Î»¼Ç¼£º%d"
+
+#: aoutx.h:1282 aoutx.h:1699
+#, c-format
+msgid "%s: can not represent section `%s' in a.out object file format"
+msgstr "%s£ºÎÞ·¨ÔÚ a.out ¶ÔÏóÎļþ¸ñʽÖбíʾ½Ú¡°%s¡±"
+
+#: aoutx.h:1669
+#, c-format
+msgid "%s: can not represent section for symbol `%s' in a.out object file format"
+msgstr "%s£ºÎÞ·¨ÔÚ a.out ¶ÔÏóÎļþ¸ñʽÖÐΪ·ûºÅ¡°%s¡±±íʾ½Ú"
+
+#: aoutx.h:1671
+msgid "*unknown*"
+msgstr "*δ֪*"
+
+#: aoutx.h:3732
+#, c-format
+msgid "%s: relocateable link from %s to %s not supported"
+msgstr "%s£º²»Ö§³Ö´Ó %s µ½ %s µÄ¿ÉÖØ¶¨Î»µÄÁ¬½Ó"
+
+#: archive.c:1826
+msgid "Warning: writing archive was slow: rewriting timestamp\n"
+msgstr "¾¯¸æ£ºÐ´Èë¹éµµ¹ýÂý£ºÖØÐÂдÈëʱ¼ä´Á\n"
+
+#: archive.c:2093
+msgid "Reading archive file mod timestamp"
+msgstr "ÕýÔÚ¶ÁÈëÎļþÐÞ¸Äʱ¼ä´Á"
+
+#. FIXME: bfd can't call perror.
+#: archive.c:2120
+msgid "Writing updated armap timestamp"
+msgstr "ÕýÔÚ¸üРarmap Ê±¼ä´Á"
+
+#: bfd.c:274
+msgid "No error"
+msgstr "ÎÞ´íÎó"
+
+#: bfd.c:275
+msgid "System call error"
+msgstr "ϵͳµ÷ÓôíÎó"
+
+#: bfd.c:276
+msgid "Invalid bfd target"
+msgstr "ÎÞЧµÄ bfd Ä¿±ê"
+
+#: bfd.c:277
+msgid "File in wrong format"
+msgstr "Îļþ¸ñʽ´íÎó"
+
+#: bfd.c:278
+msgid "Archive object file in wrong format"
+msgstr "¹éµµÄ¿±êÎļþ¸ñʽ´íÎó"
+
+#: bfd.c:279
+msgid "Invalid operation"
+msgstr "ÎÞЧµÄ²Ù×÷"
+
+#: bfd.c:280
+msgid "Memory exhausted"
+msgstr "ÄÚ´æºÄ¾¡"
+
+#: bfd.c:281
+msgid "No symbols"
+msgstr "ÎÞ·ûºÅ"
+
+#: bfd.c:282
+msgid "Archive has no index; run ranlib to add one"
+msgstr "¹éµµÃ»ÓÐË÷Òý£»ÔËÐРranlib ÒÔÌí¼ÓÒ»¸ö"
+
+#: bfd.c:283
+msgid "No more archived files"
+msgstr "ûÓиü¶àµÄ¹éµµÎļþ"
+
+#: bfd.c:284
+msgid "Malformed archive"
+msgstr "»ûÐεĹ鵵"
+
+#: bfd.c:285
+msgid "File format not recognized"
+msgstr "²»¿Éʶ±ðµÄÎļþ¸ñʽ"
+
+#: bfd.c:286
+msgid "File format is ambiguous"
+msgstr "¶þÒåÐÔµÄÎļþ¸ñʽ"
+
+#: bfd.c:287
+msgid "Section has no contents"
+msgstr "½ÚûÓÐÄÚÈÝ"
+
+#: bfd.c:288
+msgid "Nonrepresentable section on output"
+msgstr "Êä³ö²»¿É±íʾµÄ½Ú"
+
+#: bfd.c:289
+msgid "Symbol needs debug section which does not exist"
+msgstr "·ûºÅÐèÒª²»´æÔڵĵ÷ÊÔ½Ú"
+
+#: bfd.c:290
+msgid "Bad value"
+msgstr "´íÎóµÄÖµ"
+
+#: bfd.c:291
+msgid "File truncated"
+msgstr "Îļþ±»½Ø¶Ï"
+
+#: bfd.c:292
+msgid "File too big"
+msgstr "Îļþ¹ý´ó"
+
+#: bfd.c:293
+msgid "#<Invalid error code>"
+msgstr "#<ÎÞЧµÄ´íÎóÂë>"
+
+#: bfd.c:700
+#, c-format
+msgid "BFD %s assertion fail %s:%d"
+msgstr "BFD %s ¶ÏÑÔʧ°Ü %s£º%d"
+
+#: bfd.c:719
+#, c-format
+msgid "BFD %s internal error, aborting at %s line %d in %s\n"
+msgstr "BFD %1$s ÄÚ²¿´íÎó£¬Òì³£ÖÐÖ¹ÓÚ %4$s µÄ %3$d ÐеĠ%2$s\n"
+
+#: bfd.c:723
+#, c-format
+msgid "BFD %s internal error, aborting at %s line %d\n"
+msgstr "BFD %1$s ÄÚ²¿´íÎó£¬Òì³£ÖÐÖ¹ÓÚ %3$d ÐеĠ%2$s\n"
+
+#: bfd.c:725
+msgid "Please report this bug.\n"
+msgstr "Ç뱨¸æ¸Ã BUG¡£\n"
+
+#: binary.c:306
+#, c-format
+msgid "Warning: Writing section `%s' to huge (ie negative) file offset 0x%lx."
+msgstr "¾¯¸æ£º½«½Ú¡°%s¡±Ð´Èë¹ý´ó(ÀýÈ縺Êý)ÎļþÆ«ÒÆÁ¿µÄλÖà0x%lx¡£"
+
+#: coff-a29k.c:119
+msgid "Missing IHCONST"
+msgstr "ÒÅʧ IHCONST"
+
+#: coff-a29k.c:180
+msgid "Missing IHIHALF"
+msgstr "ÒÅʧ IHIHALF"
+
+#: coff-a29k.c:212 coff-or32.c:229
+msgid "Unrecognized reloc"
+msgstr "ÎÞ·¨Ê¶±ðµÄÖØ¶¨Î»"
+
+#: coff-a29k.c:408
+msgid "missing IHCONST reloc"
+msgstr "ÒÅʧ IHCONST Öض¨Î»"
+
+#: coff-a29k.c:498
+msgid "missing IHIHALF reloc"
+msgstr "ÒÅʧ IHIHALF Öض¨Î»"
+
+#: coff-alpha.c:881 coff-alpha.c:918 coff-alpha.c:1989 coff-mips.c:1432
+msgid "GP relative relocation used when GP not defined"
+msgstr "ÔÚ GP Î´¶¨ÒåµÄÇé¿öÏÂʹÓÃÁË GP Ïà¶ÔÖØ¶¨Î»"
+
+#: coff-alpha.c:1485
+msgid "using multiple gp values"
+msgstr "ʹÓÃÁ˶à¸ö GP Öµ"
+
+#: coff-arm.c:1066 elf32-arm.h:285
+#, c-format
+msgid "%s: unable to find THUMB glue '%s' for `%s'"
+msgstr ""
+
+#: coff-arm.c:1096 elf32-arm.h:320
+#, c-format
+msgid "%s: unable to find ARM glue '%s' for `%s'"
+msgstr ""
+
+#: coff-arm.c:1391 coff-arm.c:1486 elf32-arm.h:887 elf32-arm.h:991
+#, c-format
+msgid "%s(%s): warning: interworking not enabled."
+msgstr ""
+
+#: coff-arm.c:1395 elf32-arm.h:994
+#, c-format
+msgid "  first occurrence: %s: arm call to thumb"
+msgstr ""
+
+#: coff-arm.c:1490 elf32-arm.h:890
+#, c-format
+msgid "  first occurrence: %s: thumb call to arm"
+msgstr ""
+
+#: coff-arm.c:1493
+msgid "  consider relinking with --support-old-code enabled"
+msgstr "  ³¢ÊÔÆôÓà--support-old-code ÖØÐÂÁ¬½Ó"
+
+#: coff-arm.c:1785 coff-tic80.c:686 cofflink.c:3031
+#, c-format
+msgid "%s: bad reloc address 0x%lx in section `%s'"
+msgstr ""
+
+#: coff-arm.c:2127
+#, c-format
+msgid "%s: illegal symbol index in reloc: %d"
+msgstr "%s£ºÖض¨Î»ÖзǷ¨µÄ·ûºÅË÷Òý£º%d"
+
+#: coff-arm.c:2255
+#, c-format
+msgid "ERROR: %s is compiled for APCS-%d, whereas %s is compiled for APCS-%d"
+msgstr "´íÎó£º%s ÊÇΪ APCS-%d ±àÒëµÄ£¬¶ø %s ÊÇΪ APCS-%d ±àÒëµÄ"
+
+#: coff-arm.c:2270 elf32-arm.h:2297
+#, c-format
+msgid "ERROR: %s passes floats in float registers, whereas %s passes them in integer registers"
+msgstr "´íÎó£º%s ÔÚ¸¡µã¼Ä´æÆ÷Öд«µÝ¸¡µãÊý£¬¶ø %s ÔÚÕûÊý¼Ä´æÆ÷Öд«µÝËüÃÇ"
+
+#: coff-arm.c:2273 elf32-arm.h:2302
+#, c-format
+msgid "ERROR: %s passes floats in integer registers, whereas %s passes them in float registers"
+msgstr "´íÎó£º%s ÔÚÕûÊý¼Ä´æÆ÷Öд«µÝ¸¡µãÊý£¬¶ø %s ÔÚ¸¡µãÊý¼Ä´æÆ÷Öд«µÝËüÃÇ"
+
+#: coff-arm.c:2288
+#, c-format
+msgid "ERROR: %s is compiled as position independent code, whereas target %s is absolute position"
+msgstr "´íÎó£º%s ±»±àÒëΪλÖÃÎ޹شúÂ룬¶øÄ¿±ê %s ²ÉÓþø¶ÔλÖÃ"
+
+#: coff-arm.c:2291
+#, c-format
+msgid "ERROR: %s is compiled as absolute position code, whereas target %s is position independent"
+msgstr "´íÎó£º%s ±»±àÒëΪ¾ø¶ÔλÖôúÂ룬¶øÄ¿±ê %s ÊÇλÖÃÎ޹صÄ"
+
+#: coff-arm.c:2320 elf32-arm.h:2358
+#, c-format
+msgid "Warning: %s supports interworking, whereas %s does not"
+msgstr "¾¯¸æ£º%s Ö§³Ö»¥²Ù×÷£¬¶ø %s ²»Ö§³Ö"
+
+#: coff-arm.c:2323 elf32-arm.h:2365
+#, c-format
+msgid "Warning: %s does not support interworking, whereas %s does"
+msgstr "¾¯¸æ£º%s ²»Ö§³Ö»¥²Ù×÷£¬¶ø %s Ö§³Ö"
+
+#: coff-arm.c:2350
+#, c-format
+msgid "private flags = %x:"
+msgstr "˽ÓбêÖ¾ = %x£º"
+
+#: coff-arm.c:2358 elf32-arm.h:2418
+msgid " [floats passed in float registers]"
+msgstr " [ÔÚ¸¡µã¼Ä´æÆ÷Öд«µÝ¸¡µãÊý]"
+
+#: coff-arm.c:2360
+msgid " [floats passed in integer registers]"
+msgstr " [ÔÚÕûÊý¼Ä´æÆ÷Öд«µÝ¸¡µãÊý]"
+
+#: coff-arm.c:2363 elf32-arm.h:2421
+msgid " [position independent]"
+msgstr " [λÖÃÎÞ¹Ø]"
+
+#: coff-arm.c:2365
+msgid " [absolute position]"
+msgstr " [¾ø¶ÔλÖÃ]"
+
+#: coff-arm.c:2369
+msgid " [interworking flag not initialised]"
+msgstr " [»¥²Ù×÷±ê־δ³õʼ»¯]"
+
+#: coff-arm.c:2371
+msgid " [interworking supported]"
+msgstr " [Ö§³Ö»¥²Ù×÷]"
+
+#: coff-arm.c:2373
+msgid " [interworking not supported]"
+msgstr " [²»Ö§³Ö»¥²Ù×÷]"
+
+#: coff-arm.c:2421 elf32-arm.h:2124
+#, c-format
+msgid "Warning: Not setting interworking flag of %s since it has already been specified as non-interworking"
+msgstr "¾¯¸æ£ºÓÉÓÚ %s ÒѾ­±»Ö¸¶¨Îª²»¿É»¥²Ù×÷µÄ£¬Òò¶øÃ»ÓÐÉ趨»¥²Ù×÷±êÖ¾"
+
+#: coff-arm.c:2425 elf32-arm.h:2128
+#, c-format
+msgid "Warning: Clearing the interworking flag of %s due to outside request"
+msgstr "¾¯¸æ£ºÕýÔÚ¸ù¾ÝÍâ½çÇëÇóÇå³ý %s µÄ»¥²Ù×÷±êÖ¾"
+
+#: coff-i960.c:136 coff-i960.c:485
+msgid "uncertain calling convention for non-COFF symbol"
+msgstr "¹ØÓÚ·Ç-COFF ·ûºÅ²»È·¶¨µÄµ÷ÓÃÔ¼¶¨"
+
+#: coff-m68k.c:481 coff-mips.c:2429 elf32-m68k.c:2157 elf32-mips.c:1844
+msgid "unsupported reloc type"
+msgstr "²»Ö§³ÖµÄÖØ¶¨Î»ÀàÐÍ"
+
+#: coff-mips.c:874 elf32-mips.c:1062 elf64-mips.c:1609
+msgid "GP relative relocation when _gp not defined"
+msgstr ""
+
+#. No other sections should appear in -membedded-pic
+#. code.
+#: coff-mips.c:2466
+msgid "reloc against unsupported section"
+msgstr "¹ØÓÚ²»Ö§³Ö½ÚµÄÖØ¶¨Î»"
+
+#: coff-mips.c:2474
+msgid "reloc not properly aligned"
+msgstr "ÖØ¶¨Î»Ã»ÓÐÕýÈ·¶ÔÆë"
+
+#: coff-rs6000.c:2766
+#, c-format
+msgid "%s: unsupported relocation type 0x%02x"
+msgstr "%s£º²»Ö§³ÖµÄÖØ¶¨Î»ÀàÐÍ 0x%02x"
+
+#: coff-rs6000.c:2859
+#, c-format
+msgid "%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry"
+msgstr ""
+
+#: coff-rs6000.c:3590 coff64-rs6000.c:2091
+#, c-format
+msgid "%s: symbol `%s' has unrecognized smclas %d"
+msgstr ""
+
+#: coff-tic54x.c:279 coff-tic80.c:449
+#, c-format
+msgid "Unrecognized reloc type 0x%x"
+msgstr "ÎÞ·¨Ê¶±ðµÄÖØ¶¨Î»ÀàÐÍ 0x%x"
+
+#: coff-tic54x.c:390 coffcode.h:4974
+#, c-format
+msgid "%s: warning: illegal symbol index %ld in relocs"
+msgstr "%s£º¾¯¸æ£ºÖض¨Î»ÖзǷ¨µÄ·ûºÅË÷Òý %ld"
+
+#: coff-w65.c:363
+#, c-format
+msgid "ignoring reloc %s\n"
+msgstr "ÕýÔÚºöÂÔÖØ¶¨Î» %s\n"
+
+#: coffcode.h:1086
+#, c-format
+msgid "%s (%s): Section flag %s (0x%x) ignored"
+msgstr "%s (%s)£ººöÂÔ½Ú±êÖ¾ %s (0x%x)"
+
+#: coffcode.h:2143
+#, c-format
+msgid "Unrecognized TI COFF target id '0x%x'"
+msgstr "ÎÞ·¨Ê¶±ðµÄ TI COFF Ä¿±ê id ¡°0x%x¡±"
+
+#: coffcode.h:4365
+#, c-format
+msgid "%s: warning: illegal symbol index %ld in line numbers"
+msgstr "%s£º¾¯¸æ£ºÐкÅÖеķǷ¨·ûºÅË÷Òý %ld"
+
+#: coffcode.h:4379
+#, c-format
+msgid "%s: warning: duplicate line number information for `%s'"
+msgstr "%s£º¾¯¸æ£ºÎª¡°%s¡±¸´ÖÆÐкÅÐÅÏ¢"
+
+#: coffcode.h:4736
+#, c-format
+msgid "%s: Unrecognized storage class %d for %s symbol `%s'"
+msgstr ""
+
+#: coffcode.h:4867
+#, c-format
+msgid "warning: %s: local symbol `%s' has no section"
+msgstr "¾¯¸æ£º%s£º±¾µØ·ûºÅ¡°%s¡±Ã»ÓнÚ"
+
+#: coffcode.h:5012
+#, c-format
+msgid "%s: illegal relocation type %d at address 0x%lx"
+msgstr "%1$s£ºÎ»ÓÚµØÖ· 0x%3$lx ´¦µÄ·Ç·¨Öض¨Î»ÀàÐÍ %2$d"
+
+#: coffgen.c:1661
+#, c-format
+msgid "%s: bad string table size %lu"
+msgstr "%s£º×Ö·û´®±íµÄ´óС´íÎó %lu"
+
+#: cofflink.c:534 elflink.h:1912
+#, c-format
+msgid "Warning: type of symbol `%s' changed from %d to %d in %s"
+msgstr "¾¯¸æ£º%4$s ÖеķûºÅ¡°%1$s¡±µÄÀàÐÍÓÉ %2$d ±äΪ %3$d"
+
+#: cofflink.c:2321
+#, c-format
+msgid "%s: relocs in section `%s', but it has no contents"
+msgstr ""
+
+#: cofflink.c:2664 coffswap.h:877
+#, c-format
+msgid "%s: %s: reloc overflow: 0x%lx > 0xffff"
+msgstr "%s£º%s£ºÖض¨Î»Òç³ö£º0x%lx > 0xffff"
+
+#: cofflink.c:2673 coffswap.h:864
+#, c-format
+msgid "%s: warning: %s: line number overflow: 0x%lx > 0xffff"
+msgstr "%s£º¾¯¸æ£º%s£ºÐкÅÒç³ö£º0x%lx > 0xffff"
+
+#: dwarf2.c:382
+msgid "Dwarf Error: Can't find .debug_str section."
+msgstr "С´íÎó£ºÎÞ·¨ÕÒµ½ .debug_str ½Ú¡£"
+
+#: dwarf2.c:399
+#, c-format
+msgid "Dwarf Error: DW_FORM_strp offset (%lu) greater than or equal to .debug_str size (%lu)."
+msgstr ""
+
+#: dwarf2.c:543
+msgid "Dwarf Error: Can't find .debug_abbrev section."
+msgstr "С´íÎó£ºÎÞ·¨ÕÒµ½ .debug_abbrev ½Ú¡£"
+
+#: dwarf2.c:560
+#, c-format
+msgid "Dwarf Error: Abbrev offset (%lu) greater than or equal to .debug_abbrev size (%lu)."
+msgstr ""
+
+#: dwarf2.c:757
+#, c-format
+msgid "Dwarf Error: Invalid or unhandled FORM value: %u."
+msgstr "С´íÎó£ºÎÞЧ»òδ´¦ÀíµÄ±íµ¥Öµ£º%u¡£"
+
+#: dwarf2.c:852
+msgid "Dwarf Error: mangled line number section (bad file number)."
+msgstr ""
+
+#: dwarf2.c:938
+msgid "Dwarf Error: Can't find .debug_line section."
+msgstr "С´íÎó£ºÎÞ·¨ÕÒµ½ .debug_line ½Ú¡£"
+
+#: dwarf2.c:961
+#, c-format
+msgid "Dwarf Error: Line offset (%lu) greater than or equal to .debug_line size (%lu)."
+msgstr ""
+
+#: dwarf2.c:1159
+msgid "Dwarf Error: mangled line number section."
+msgstr ""
+
+#: dwarf2.c:1355 dwarf2.c:1566
+#, c-format
+msgid "Dwarf Error: Could not find abbrev number %u."
+msgstr ""
+
+#: dwarf2.c:1527
+#, c-format
+msgid "Dwarf Error: found dwarf version '%u', this reader only handles version 2 information."
+msgstr ""
+
+#: dwarf2.c:1534
+#, c-format
+msgid "Dwarf Error: found address size '%u', this reader can not handle sizes greater than '%u'."
+msgstr ""
+
+#: dwarf2.c:1557
+#, c-format
+msgid "Dwarf Error: Bad abbrev number: %u."
+msgstr "С´íÎ󣺴íÎóµÄËõд±àºÅ£º%u¡£"
+
+#: ecoff.c:1318
+#, c-format
+msgid "Unknown basic type %d"
+msgstr "δ֪µÄ»ù±¾ÀàÐÍ %d"
+
+#: ecoff.c:1578
+#, c-format
+msgid ""
+"\n"
+"      End+1 symbol: %ld"
+msgstr ""
+"\n"
+"      End+1 ·ûºÅ£º%ld"
+
+#: ecoff.c:1585 ecoff.c:1588
+#, c-format
+msgid ""
+"\n"
+"      First symbol: %ld"
+msgstr ""
+"\n"
+"      µÚÒ»¸ö·ûºÅ£º%ld"
+
+#: ecoff.c:1600
+#, c-format
+msgid ""
+"\n"
+"      End+1 symbol: %-7ld   Type:  %s"
+msgstr ""
+"\n"
+"      End+1 ·ûºÅ£º%-7ld   ÀàÐÍ£º%s"
+
+#: ecoff.c:1607
+#, c-format
+msgid ""
+"\n"
+"      Local symbol: %ld"
+msgstr ""
+"\n"
+"      ±¾µØ·ûºÅ£º%ld"
+
+#: ecoff.c:1615
+#, c-format
+msgid ""
+"\n"
+"      struct; End+1 symbol: %ld"
+msgstr ""
+"\n"
+"      ½á¹¹£»End+1 ·ûºÅ£º%ld"
+
+#: ecoff.c:1620
+#, c-format
+msgid ""
+"\n"
+"      union; End+1 symbol: %ld"
+msgstr ""
+"\n"
+"      ÁªºÏ£»End+1 ·ûºÅ£º%ld"
+
+#: ecoff.c:1625
+#, c-format
+msgid ""
+"\n"
+"      enum; End+1 symbol: %ld"
+msgstr ""
+"\n"
+"      Ã¶¾Ù£»End+1 ·ûºÅ£º%ld"
+
+#: ecoff.c:1631
+#, c-format
+msgid ""
+"\n"
+"      Type: %s"
+msgstr ""
+"\n"
+"      ÀàÐÍ£º%s"
+
+#: elf-hppa.h:1476 elf-hppa.h:1509 elf32-ppc.c:3091 elf32-sh.c:4213
+#: elf64-sh64.c:1659
+#, c-format
+msgid "%s: warning: unresolvable relocation against symbol `%s' from %s section"
+msgstr "%1$s£º¾¯¸æ£ºÀ´×Ô %3$s ½ÚµÄ¹ØÓÚ·ûºÅ¡°%2$s¡±µÄ²»¿É½âÎöµÄÖØ¶¨Î»"
+
+#: elf-m10200.c:446 elf-m10300.c:656 elf32-arm.h:2084 elf32-avr.c:833
+#: elf32-cris.c:1403 elf32-d10v.c:481 elf32-fr30.c:635 elf32-frv.c:809
+#: elf32-h8300.c:548 elf32-i860.c:1031 elf32-m32r.c:1278 elf32-openrisc.c:439
+#: elf32-v850.c:1691 elf32-xstormy16.c:933 elf64-mmix.c:1302
+msgid "internal error: out of range error"
+msgstr "ÄÚ²¿´íÎ󣺳¬³ö·¶Î§´íÎó"
+
+#: elf-m10200.c:450 elf-m10300.c:660 elf32-arm.h:2088 elf32-avr.c:837
+#: elf32-cris.c:1407 elf32-d10v.c:485 elf32-fr30.c:639 elf32-frv.c:813
+#: elf32-h8300.c:552 elf32-i860.c:1035 elf32-m32r.c:1282 elf32-openrisc.c:443
+#: elf32-v850.c:1695 elf32-xstormy16.c:937 elf64-mmix.c:1306 elfxx-mips.c:5264
+msgid "internal error: unsupported relocation error"
+msgstr "ÄÚ²¿´íÎ󣺲»Ö§³ÖµÄÖØ¶¨Î»´íÎó"
+
+#: elf-m10200.c:454 elf-m10300.c:664 elf32-arm.h:2092 elf32-d10v.c:489
+#: elf32-h8300.c:556 elf32-m32r.c:1286
+msgid "internal error: dangerous error"
+msgstr "ÄÚ²¿´íÎó£ºÎ£ÏյĴíÎó"
+
+#: elf-m10200.c:458 elf-m10300.c:668 elf32-arm.h:2096 elf32-avr.c:845
+#: elf32-cris.c:1415 elf32-d10v.c:493 elf32-fr30.c:647 elf32-frv.c:821
+#: elf32-h8300.c:560 elf32-i860.c:1043 elf32-m32r.c:1290 elf32-openrisc.c:451
+#: elf32-v850.c:1715 elf32-xstormy16.c:945 elf64-mmix.c:1314
+msgid "internal error: unknown error"
+msgstr "ÄÚ²¿´íÎó£ºÎ´ÖªµÄ´íÎó"
+
+#: elf.c:343
+#, c-format
+msgid "%s: invalid string offset %u >= %lu for section `%s'"
+msgstr ""
+
+#: elf.c:589
+#, c-format
+msgid "%s: invalid SHT_GROUP entry"
+msgstr "%s£ºÎÞЧµÄ SHT_GROUP ÌõÄ¿"
+
+#: elf.c:660
+#, c-format
+msgid "%s: no group info for section %s"
+msgstr "%s£ºÃ»ÓйØÓÚ½Ú %s µÄ×éÐÅÏ¢"
+
+#: elf.c:1023
+msgid ""
+"\n"
+"Program Header:\n"
+msgstr ""
+"\n"
+"³ÌÐòÍ·£º\n"
+
+#: elf.c:1073
+msgid ""
+"\n"
+"Dynamic Section:\n"
+msgstr ""
+"\n"
+"¶¯Ì¬½Ú£º\n"
+
+#: elf.c:1202
+msgid ""
+"\n"
+"Version definitions:\n"
+msgstr ""
+"\n"
+"°æ±¾¶¨Ò壺\n"
+
+#: elf.c:1225
+msgid ""
+"\n"
+"Version References:\n"
+msgstr ""
+"\n"
+"°æ±¾ÒýÓãº\n"
+
+#: elf.c:1230
+#, c-format
+msgid "  required from %s:\n"
+msgstr ""
+
+#: elf.c:1902
+#, c-format
+msgid "%s: invalid link %lu for reloc section %s (index %u)"
+msgstr ""
+
+#: elf.c:3603
+#, c-format
+msgid "%s: Not enough room for program headers (allocated %u, need %u)"
+msgstr "%s£ºÃ»ÓÐ×ã¹»µÄ¿Õ¼ä±£´æ³ÌÐòÍ·£¨·ÖÅä %u£¬ÐèÒª %u£©"
+
+#: elf.c:3708
+#, c-format
+msgid "%s: Not enough room for program headers, try linking with -N"
+msgstr "%s£ºÃ»ÓÐ×ã¹»µÄ¿Õ¼ä±£´æ³ÌÐòÍ·£¬ÊÔÓà-N ½øÐÐÁ¬½Ó"
+
+#: elf.c:3833
+#, c-format
+msgid "Error: First section in segment (%s) starts at 0x%x whereas the segment starts at 0x%x"
+msgstr "´íÎ󣺶Π(%s) ÖеĵÚÒ»¸ö½Ú¿ªÊ¼ÓÚ 0x%x£¬È»¶ø¶Î¿ªÊ¼ÓÚ 0x%x"
+
+#: elf.c:4148
+#, c-format
+msgid "%s: warning: allocated section `%s' not in segment"
+msgstr "%s£º¾¯¸æ£ºÒÑ·ÖÅäµÄ½Ú¡°%s¡±²»ÔÚ¶ÎÖÐ"
+
+#: elf.c:4472
+#, c-format
+msgid "%s: symbol `%s' required but not present"
+msgstr "%s£º±ØÐèµÄ·ûºÅ¡°%s¡±²»´æÔÚ"
+
+#: elf.c:4749
+#, c-format
+msgid "%s: warning: Empty loadable segment detected, is this intentional ?\n"
+msgstr "%s£º¾¯¸æ£º·¢ÏֿյĿÉ×°Èë¶Î£¬ËüÊÇÄÚ²¿µÄ£¿\n"
+
+#: elf.c:6193
+#, c-format
+msgid "%s: unsupported relocation type %s"
+msgstr "%s£º²»Ö§³ÖµÄÖØ¶¨Î»µÄÀàÐÍ %s"
+
+#: elf32-arm.h:1221
+#, c-format
+msgid "%s: Warning: Arm BLX instruction targets Arm function '%s'."
+msgstr ""
+
+#: elf32-arm.h:1417
+#, c-format
+msgid "%s: Warning: Thumb BLX instruction targets thumb function '%s'."
+msgstr ""
+
+#: elf32-arm.h:1914 elf32-sh.c:4125
+#, c-format
+msgid "%s(%s+0x%lx): %s relocation against SEC_MERGE section"
+msgstr "%s(%s+0x%lx)£º¹ØÓÚ SEC_MERGE ½ÚµÄÖØ¶¨Î» %s"
+
+#: elf32-arm.h:2008
+#, c-format
+msgid "%s: warning: unresolvable relocation %d against symbol `%s' from %s section"
+msgstr ""
+
+#: elf32-arm.h:2176
+#, c-format
+msgid "Warning: Clearing the interworking flag of %s because non-interworking code in %s has been linked with it"
+msgstr ""
+
+#: elf32-arm.h:2271
+#, c-format
+msgid "ERROR: %s is compiled for EABI version %d, whereas %s is compiled for version %d"
+msgstr "´íÎó£º%s ÊÇΪ EABI °æ±¾ %d ±àÒëµÄ£¬¶ø %s ÔòÊÇΪ°æ±¾ %d ±àÒëµÄ"
+
+#: elf32-arm.h:2285
+#, c-format
+msgid "ERROR: %s is compiled for APCS-%d, whereas target %s uses APCS-%d"
+msgstr "´íÎó£º%s ÊÇΪ APCS-%d ±àÒëµÄ£¬¶øÄ¿±ê %s Ê¹ÓàAPCS-%d"
+
+#: elf32-arm.h:2313
+#, c-format
+msgid "ERROR: %s uses VFP instructions, whereas %s uses FPA instructions"
+msgstr "´íÎó£º%s Ê¹ÓàVFP Ö¸Á¶ø %s Ê¹ÓàFPA Ö¸Áî"
+
+#: elf32-arm.h:2318
+#, c-format
+msgid "ERROR: %s uses FPA instructions, whereas %s uses VFP instructions"
+msgstr "´íÎó£º%s Ê¹ÓàFPA Ö¸Á¶ø %s Ê¹ÓàVFP Ö¸Áî"
+
+#: elf32-arm.h:2338
+#, c-format
+msgid "ERROR: %s uses software FP, whereas %s uses hardware FP"
+msgstr "´íÎó£º%s Ê¹ÓÃÈí¼þ FP£¬¶ø %s Ê¹ÓÃÓ²¼þ FP"
+
+#: elf32-arm.h:2343
+#, c-format
+msgid "ERROR: %s uses hardware FP, whereas %s uses software FP"
+msgstr "´íÎó£º%s Ê¹ÓÃÓ²¼þ FP£¬¶ø %s Ê¹ÓÃÈí¼þ FP"
+
+#. Ignore init flag - it may not be set, despite the flags field
+#. containing valid data.
+#: elf32-arm.h:2396 elf32-cris.c:2988 elf32-m68k.c:410 elf32-vax.c:543
+#: elfxx-mips.c:7756
+#, c-format
+msgid "private flags = %lx:"
+msgstr "˽ÓбêÖ¾ = %lx£º"
+
+#: elf32-arm.h:2405
+msgid " [interworking enabled]"
+msgstr " [ÆôÓû¥²Ù×÷]"
+
+#: elf32-arm.h:2413
+msgid " [VFP float format]"
+msgstr " [VFP ¸¡µã¸ñʽ]"
+
+#: elf32-arm.h:2415
+msgid " [FPA float format]"
+msgstr " [FPA ¸¡µã¸ñʽ]"
+
+#: elf32-arm.h:2424
+msgid " [new ABI]"
+msgstr " [РABI]"
+
+#: elf32-arm.h:2427
+msgid " [old ABI]"
+msgstr " [¾É ABI]"
+
+#: elf32-arm.h:2430
+msgid " [software FP]"
+msgstr " [Èí¼þ FP]"
+
+#: elf32-arm.h:2438
+msgid " [Version1 EABI]"
+msgstr " [°æ±¾1 EABI]"
+
+#: elf32-arm.h:2441 elf32-arm.h:2452
+msgid " [sorted symbol table]"
+msgstr " [ÅÅÐò¹ýµÄ·ûºÅ±í]"
+
+#: elf32-arm.h:2443 elf32-arm.h:2454
+msgid " [unsorted symbol table]"
+msgstr " [δÅÅÐòµÄ·ûºÅ±í]"
+
+#: elf32-arm.h:2449
+msgid " [Version2 EABI]"
+msgstr " [°æ±¾2 EABI]"
+
+#: elf32-arm.h:2457
+msgid " [dynamic symbols use segment index]"
+msgstr " [¶¯Ì¬·ûºÅʹÓöÎË÷Òý]"
+
+#: elf32-arm.h:2460
+msgid " [mapping symbols precede others]"
+msgstr ""
+
+#: elf32-arm.h:2467
+msgid " <EABI version unrecognised>"
+msgstr " <²»¿Éʶ±ðµÄ EABI °æ±¾>"
+
+#: elf32-arm.h:2474
+msgid " [relocatable executable]"
+msgstr " [¿ÉÖØÐ¶¨Î»µÄ¿ÉÖ´ÐгÌÐò]"
+
+#: elf32-arm.h:2477
+msgid " [has entry point]"
+msgstr " [º¬ÓÐÈë¿Úµã]"
+
+#: elf32-arm.h:2482
+msgid "<Unrecognised flag bits set>"
+msgstr "<ÎÞ·¨Ê¶±ðµÄ±ê־λ¼¯ºÏ>"
+
+#: elf32-avr.c:841 elf32-cris.c:1411 elf32-fr30.c:643 elf32-frv.c:817
+#: elf32-i860.c:1039 elf32-openrisc.c:447 elf32-v850.c:1699
+#: elf32-xstormy16.c:941 elf64-mmix.c:1310
+msgid "internal error: dangerous relocation"
+msgstr "ÄÚ²¿´íÎó£ºÎ£ÏÕµÄÖØ¶¨Î»"
+
+#: elf32-cris.c:949
+#, c-format
+msgid "%s: unresolvable relocation %s against symbol `%s' from %s section"
+msgstr "%1$s£ºÀ´×Ô %4$s ½ÚµÄ¹ØÓÚ·ûºÅ¡°%3$s¡±µÄÎÞ·¨½âÎöµÄÖØ¶¨Î» %2$s"
+
+#: elf32-cris.c:1012
+#, c-format
+msgid "%s: No PLT nor GOT for relocation %s against symbol `%s' from %s section"
+msgstr ""
+
+#: elf32-cris.c:1015 elf32-cris.c:1141
+msgid "[whose name is lost]"
+msgstr ""
+
+#: elf32-cris.c:1130
+#, c-format
+msgid "%s: relocation %s with non-zero addend %d against local symbol from %s section"
+msgstr ""
+
+#: elf32-cris.c:1137
+#, c-format
+msgid "%s: relocation %s with non-zero addend %d against symbol `%s' from %s section"
+msgstr ""
+
+#: elf32-cris.c:1155
+#, c-format
+msgid "%s: relocation %s is not allowed for global symbol: `%s' from %s section"
+msgstr ""
+
+#: elf32-cris.c:1170
+#, c-format
+msgid "%s: relocation %s in section %s with no GOT created"
+msgstr ""
+
+#: elf32-cris.c:1288
+#, c-format
+msgid "%s: Internal inconsistency; no relocation section %s"
+msgstr "%s£ºÄÚ²¿²»Ò»Ö£»Ã»ÓÐÖØ¶¨Î»½Ú %s"
+
+#: elf32-cris.c:2514
+#, c-format
+msgid ""
+"%s, section %s:\n"
+"  relocation %s should not be used in a shared object; recompile with -fPIC"
+msgstr ""
+
+#: elf32-cris.c:2991
+msgid " [symbols have a _ prefix]"
+msgstr " [·ûºÅÓиö _ Ç°×º]"
+
+#: elf32-cris.c:3030
+#, c-format
+msgid "%s: uses _-prefixed symbols, but writing file with non-prefixed symbols"
+msgstr "%s£ºÊ¹Óôø _ Ç°×ºµÄ·ûºÅ£¬µ«ÒÔÎÞǰ׺·ûºÅдÈëÎļþ"
+
+#: elf32-cris.c:3031
+#, c-format
+msgid "%s: uses non-prefixed symbols, but writing file with _-prefixed symbols"
+msgstr "%s£ºÊ¹ÓÃÎÞǰ׺·ûºÅ£¬µ«ÒÔ´ø _ Ç°×ºµÄ·ûºÅдÈëÎļþ"
+
+#: elf32-frv.c:1217
+#, c-format
+msgid "%s: compiled with %s and linked with modules that use non-pic relocations"
+msgstr ""
+
+#: elf32-frv.c:1267
+#, c-format
+msgid "%s: compiled with %s and linked with modules compiled with %s"
+msgstr "%s£ºÒÔ %s ±àÒ벢ͬÒÔ %s ±àÒëµÄÄ£¿éÁ¬½Ó"
+
+#: elf32-frv.c:1279
+#, c-format
+msgid "%s: uses different unknown e_flags (0x%lx) fields than previous modules (0x%lx)"
+msgstr ""
+
+#: elf32-frv.c:1315
+#, c-format
+msgid "private flags = 0x%lx:"
+msgstr "˽ÓбêÖ¾ = 0x%lx£º"
+
+#: elf32-gen.c:82 elf64-gen.c:82
+#, c-format
+msgid "%s: Relocations in generic ELF (EM: %d)"
+msgstr ""
+
+#: elf32-hppa.c:671 elf64-ppc.c:2323
+#, c-format
+msgid "%s: cannot create stub entry %s"
+msgstr ""
+
+#: elf32-hppa.c:956 elf32-hppa.c:3555
+#, c-format
+msgid "%s(%s+0x%lx): cannot reach %s, recompile with -ffunction-sections"
+msgstr ""
+
+#: elf32-hppa.c:1338 elf64-x86-64.c:673
+#, c-format
+msgid "%s: relocation %s can not be used when making a shared object; recompile with -fPIC"
+msgstr ""
+
+#: elf32-hppa.c:1358
+#, c-format
+msgid "%s: relocation %s should not be used when making a shared object; recompile with -fPIC"
+msgstr ""
+
+#: elf32-hppa.c:1551
+#, c-format
+msgid "Could not find relocation section for %s"
+msgstr "ÎÞ·¨Îª %s ÕÒµ½Öض¨Î»½Ú"
+
+#: elf32-hppa.c:2855
+#, c-format
+msgid "%s: duplicate export stub %s"
+msgstr ""
+
+#: elf32-hppa.c:3433
+#, c-format
+msgid "%s(%s+0x%lx): fixing %s"
+msgstr "%s(%s+0x%lx)£ºÕýÔÚÐÞ¸´ %s"
+
+#: elf32-hppa.c:4080
+#, c-format
+msgid "%s(%s+0x%lx): cannot handle %s for %s"
+msgstr ""
+
+#: elf32-hppa.c:4393
+msgid ".got section not immediately after .plt section"
+msgstr ".got ½Ú²»Äܽô½ÓÔÚ .plt ½ÚÖ®ºó"
+
+#: elf32-i386.c:379
+#, c-format
+msgid "%s: invalid relocation type %d"
+msgstr "%s£ºÎÞЧµÄÖØ¶¨Î»ÀàÐÍ %d"
+
+#: elf32-i386.c:876 elf32-s390.c:649 elf64-s390.c:595 elf64-x86-64.c:591
+#, c-format
+msgid "%s: bad symbol index: %d"
+msgstr "%s£º´íÎóµÄ·ûºÅË÷Òý£º%d"
+
+#: elf32-i386.c:948
+#, c-format
+msgid "%s: `%s' accessed both as normal and thread local symbol"
+msgstr ""
+
+#: elf32-i386.c:1072 elf32-s390.c:808 elf64-ppc.c:2827 elf64-s390.c:759
+#: elf64-x86-64.c:761
+#, c-format
+msgid "%s: bad relocation section name `%s'"
+msgstr "%s£º´íÎóµÄÖØ¶¨Î»½ÚÃû³Æ¡°%s¡±"
+
+#: elf32-i386.c:1159 elf64-alpha.c:4768
+#, c-format
+msgid "%s: TLS local exec code cannot be linked into shared objects"
+msgstr ""
+
+#: elf32-i386.c:2747 elf32-s390.c:1981 elf32-sparc.c:1571 elf64-ppc.c:5918
+#: elf64-s390.c:1945 elf64-sparc.c:2578 elf64-x86-64.c:1948
+#, c-format
+msgid "%s(%s+0x%lx): unresolvable relocation against symbol `%s'"
+msgstr ""
+
+#: elf32-i386.c:2784 elf32-s390.c:2019 elf64-ppc.c:5977 elf64-s390.c:1983
+#: elf64-x86-64.c:1986
+#, c-format
+msgid "%s(%s+0x%lx): reloc against `%s': error %d"
+msgstr ""
+
+#: elf32-m32r.c:924
+msgid "SDA relocation when _SDA_BASE_ not defined"
+msgstr "ÔÚ _SDA_BASE_ Î´¶¨Òåʱ³öÏÖ SDA Öض¨Î»"
+
+#: elf32-ia64.c:3687 elf32-m32r.c:1013 elf32-ppc.c:2987 elf64-alpha.c:4185
+#: elf64-alpha.c:4313 elf64-ia64.c:3687
+#, c-format
+msgid "%s: unknown relocation type %d"
+msgstr "%s£ºÎ´ÖªµÄÖØ¶¨Î»ÀàÐÍ %d"
+
+#: elf32-m32r.c:1221
+#, c-format
+msgid "%s: The target (%s) of an %s relocation is in the wrong section (%s)"
+msgstr ""
+
+#: elf32-m32r.c:1947
+#, c-format
+msgid "%s: Instruction set mismatch with previous modules"
+msgstr ""
+
+#: elf32-m32r.c:1970
+#, c-format
+msgid "private flags = %lx"
+msgstr "˽ÓбêÖ¾ = %lx"
+
+#: elf32-m32r.c:1975
+msgid ": m32r instructions"
+msgstr "£ºm32r Ö¸Áî"
+
+#: elf32-m32r.c:1976
+msgid ": m32rx instructions"
+msgstr "£ºm32rx Ö¸Áî"
+
+#: elf32-m68k.c:413
+msgid " [cpu32]"
+msgstr " [cpu32]"
+
+#: elf32-m68k.c:416
+msgid " [m68000]"
+msgstr " [m68000]"
+
+#: elf32-mcore.c:354 elf32-mcore.c:457
+#, c-format
+msgid "%s: Relocation %s (%d) is not currently supported.\n"
+msgstr ""
+
+#: elf32-mcore.c:442
+#, c-format
+msgid "%s: Unknown relocation type %d\n"
+msgstr "%s£ºÎ´ÖªµÄÖØ¶¨Î»ÀàÐÍ %d\n"
+
+#: elf32-mips.c:1152 elf64-mips.c:1783
+msgid "32bits gp relative relocation occurs for an external symbol"
+msgstr ""
+
+#: elf32-mips.c:1301
+#, c-format
+msgid "Linking mips16 objects into %s format is not supported"
+msgstr "½« mips16 Ä¿±êÎļþÁ¬½Óµ½ %s ¸ñʽÊDz»Ö§³ÖµÄ"
+
+#: elf32-ppc.c:1460
+#, c-format
+msgid "%s: compiled with -mrelocatable and linked with modules compiled normally"
+msgstr ""
+
+#: elf32-ppc.c:1468
+#, c-format
+msgid "%s: compiled normally and linked with modules compiled with -mrelocatable"
+msgstr ""
+
+#: elf32-ppc.c:1494 elf64-sparc.c:2989 elfxx-mips.c:7713
+#, c-format
+msgid "%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"
+msgstr ""
+
+#: elf32-ppc.c:1592
+#, c-format
+msgid "%s: Unknown special linker type %d"
+msgstr "%s£ºÎ´ÖªµÄÌØ¶¨Á¬½ÓÆ÷ÀàÐÍ %d"
+
+#: elf32-ppc.c:2273 elf32-ppc.c:2307 elf32-ppc.c:2342
+#, c-format
+msgid "%s: relocation %s cannot be used when making a shared object"
+msgstr "%s£º´´½¨¹²ÏíÄ¿±êÎļþʱ²»ÄÜʹÓÃÖØ¶¨Î» %s"
+
+#: elf32-ppc.c:3126 elf64-ppc.c:5473
+#, c-format
+msgid "%s: unknown relocation type %d for symbol %s"
+msgstr "%1$s£º¹ØÓÚ·ûºÅ %3$s µÄÎ´ÖªÖØ¶¨Î»ÀàÐÍ %2$d"
+
+#: elf32-ppc.c:3482 elf32-ppc.c:3503 elf32-ppc.c:3553
+#, c-format
+msgid "%s: The target (%s) of a %s relocation is in the wrong output section (%s)"
+msgstr ""
+
+#: elf32-ppc.c:3619
+#, c-format
+msgid "%s: Relocation %s is not yet supported for symbol %s."
+msgstr "%s£ºÉв»Ö§³Ö¹ØÓÚ·ûºÅ %s µÄÖØ¶¨Î» %s¡£"
+
+#: elf32-sh.c:1964
+#, c-format
+msgid "%s: 0x%lx: warning: bad R_SH_USES offset"
+msgstr "%s£º0x%lx£º¾¯¸æ£º´íÎóµÄ R_SH_USES Æ«ÒÆÁ¿"
+
+#: elf32-sh.c:1976
+#, c-format
+msgid "%s: 0x%lx: warning: R_SH_USES points to unrecognized insn 0x%x"
+msgstr "%s£º0x%lx£º¾¯¸æ£ºR_SH_USES Ö¸ÏòÎÞ·¨Ê¶±ðµÄÖ¸Áî 0x%x"
+
+#: elf32-sh.c:1993
+#, c-format
+msgid "%s: 0x%lx: warning: bad R_SH_USES load offset"
+msgstr "%s£º0x%lx£º¾¯¸æ£º´íÎóµÄ R_SH_USES ×°ÈëÆ«ÒÆÁ¿"
+
+#: elf32-sh.c:2008
+#, c-format
+msgid "%s: 0x%lx: warning: could not find expected reloc"
+msgstr "%s£º0x%lx£º¾¯¸æ£ºÎÞ·¨ÕÒµ½Ô¤ÆÚµÄÖØ¶¨Î»"
+
+#: elf32-sh.c:2036
+#, c-format
+msgid "%s: 0x%lx: warning: symbol in unexpected section"
+msgstr "%s£º0x%lx£º¾¯¸æ£ºÒâÍâ½ÚÖгöÏÖ·ûºÅ"
+
+#: elf32-sh.c:2153
+#, c-format
+msgid "%s: 0x%lx: warning: could not find expected COUNT reloc"
+msgstr "%s£º0x%lx£º¾¯¸æ£ºÎÞ·¨ÕÒµ½Ô¤ÆÚµÄ COUNT Öض¨Î»"
+
+#: elf32-sh.c:2162
+#, c-format
+msgid "%s: 0x%lx: warning: bad count"
+msgstr "%s£º0x%lx£º¾¯¸æ£º´íÎó¼ÆÊý"
+
+#: elf32-sh.c:2550 elf32-sh.c:2926
+#, c-format
+msgid "%s: 0x%lx: fatal: reloc overflow while relaxing"
+msgstr ""
+
+#: elf32-sh.c:4073 elf64-sh64.c:1576
+msgid "Unexpected STO_SH5_ISA32 on local symbol is not handled"
+msgstr ""
+
+#: elf32-sh.c:4284
+#, c-format
+msgid "%s: 0x%lx: fatal: unaligned branch target for relax-support relocation"
+msgstr ""
+
+#: elf32-sh64.c:203 elf64-sh64.c:2364
+#, c-format
+msgid "%s: compiled as 32-bit object and %s is 64-bit"
+msgstr "%s£º±àÒëΪ 32-λĿ±êÎļþµ« %s ÊÇ 64-λµÄ"
+
+#: elf32-sh64.c:206 elf64-sh64.c:2367
+#, c-format
+msgid "%s: compiled as 64-bit object and %s is 32-bit"
+msgstr "%s£º±àÒëΪ 64-λĿ±êÎļþµ« %s ÊÇ 32-λµÄ"
+
+#: elf32-sh64.c:208 elf64-sh64.c:2369
+#, c-format
+msgid "%s: object size does not match that of target %s"
+msgstr "%s£ºÄ¿±êÎļþ´óСºÍÄ¿±ê %s ²»Æ¥Åä"
+
+#: elf32-sh64.c:440 elf64-sh64.c:2941
+#, c-format
+msgid "%s: encountered datalabel symbol in input"
+msgstr "%s£ºÔÚÊäÈëÖÐÓöµ½Êý¾Ý±êÇ©·ûºÅ"
+
+#: elf32-sh64.c:523
+msgid "PTB mismatch: a SHmedia address (bit 0 == 1)"
+msgstr "PTB ²»Æ¥Å䣺SHmedia µØÖ· (λ 0 == 1)"
+
+#: elf32-sh64.c:526
+msgid "PTA mismatch: a SHcompact address (bit 0 == 0)"
+msgstr "PTA ²»Æ¥Å䣺SHcompact µØÖ· (λ 0 == 0)"
+
+#: elf32-sh64.c:544
+#, c-format
+msgid "%s: GAS error: unexpected PTB insn with R_SH_PT_16"
+msgstr "%s£ºGAS ´íÎó£ºÒâÍâµÄ´øÓРR_SH_PT_16 µÄ PTB Ö¸Áî"
+
+#: elf32-sh64.c:593 elf64-sh64.c:1703
+#, c-format
+msgid "%s: error: unaligned relocation type %d at %08x reloc %08x\n"
+msgstr ""
+
+#: elf32-sh64.c:677
+#, c-format
+msgid "%s: could not write out added .cranges entries"
+msgstr "%s£ºÎÞ·¨Ð´³ö .cranges ÌõÄ¿"
+
+#: elf32-sh64.c:739
+#, c-format
+msgid "%s: could not write out sorted .cranges entries"
+msgstr "%s£ºÎÞ·¨Ð´³ö¾­ÅÅÐòµÄ .cranges ÌõÄ¿"
+
+#: elf32-sparc.c:1535 elf64-sparc.c:2224
+#, c-format
+msgid "%s: probably compiled without -fPIC?"
+msgstr ""
+
+#: elf32-sparc.c:2002
+#, c-format
+msgid "%s: compiled for a 64 bit system and target is 32 bit"
+msgstr "%s£ºÎª 64 Î»ÏµÍ³±àÒ뵫Ŀ±êƽ̨ÊÇ 32 Î»µÄ"
+
+#: elf32-sparc.c:2016
+#, c-format
+msgid "%s: linking little endian files with big endian files"
+msgstr "%s£ºÁ¬½ÓС¶ËÎļþºÍ´ó¶ËÎļþ"
+
+#: elf32-v850.c:682
+#, c-format
+msgid "Variable `%s' cannot occupy in multiple small data regions"
+msgstr "±äÁ¿¡°%s¡±²»ÄÜÕ¼¾Ý¶à¸öСÊý¾ÝÇø"
+
+#: elf32-v850.c:685
+#, c-format
+msgid "Variable `%s' can only be in one of the small, zero, and tiny data regions"
+msgstr "±äÁ¿¡°%s¡±Ö»ÄܳöÏÖÔÚСÊý¾ÝÇø¡¢ÁãÊý¾ÝÇø¡¢Î¢Êý¾ÝÇøÖ®Ò»"
+
+#: elf32-v850.c:688
+#, c-format
+msgid "Variable `%s' cannot be in both small and zero data regions simultaneously"
+msgstr "±äÁ¿¡°%s¡±²»ÄÜͬʱ³öÏÖÔÚСÊý¾ÝÇøºÍÁãÊý¾ÝÇø"
+
+#: elf32-v850.c:691
+#, c-format
+msgid "Variable `%s' cannot be in both small and tiny data regions simultaneously"
+msgstr "±äÁ¿¡°%s¡±²»ÄÜͬʱ³öÏÖÔÚСÊý¾ÝÇøºÍ΢Êý¾ÝÇø"
+
+#: elf32-v850.c:694
+#, c-format
+msgid "Variable `%s' cannot be in both zero and tiny data regions simultaneously"
+msgstr "±äÁ¿¡°%s¡±²»ÄÜͬʱ³öÏÖÔÚÁãÊý¾ÝÇøºÍ΢Êý¾ÝÇø"
+
+#: elf32-v850.c:1072
+msgid "FAILED to find previous HI16 reloc\n"
+msgstr "ѰÕÒÉÏÒ»¸ö HI16 Öض¨Î»Ê§°Ü\n"
+
+#: elf32-v850.c:1703
+msgid "could not locate special linker symbol __gp"
+msgstr "ÎÞ·¨¶¨Î»ÌØÊâÁ¬½ÓÆ÷·ûºÅ __gp"
+
+#: elf32-v850.c:1707
+msgid "could not locate special linker symbol __ep"
+msgstr "ÎÞ·¨¶¨Î»ÌØÊâÁ¬½ÓÆ÷·ûºÅ __ep"
+
+#: elf32-v850.c:1711
+msgid "could not locate special linker symbol __ctbp"
+msgstr "ÎÞ·¨¶¨Î»ÌØÊâÁª»úÆ÷·ûºÅ __ctbp"
+
+#: elf32-v850.c:1875
+#, c-format
+msgid "%s: Architecture mismatch with previous modules"
+msgstr "%s£ºÌåϵ½á¹¹Í¬Ç°Ò»¸öÄ£¿é²»Æ¥Åä"
+
+#: elf32-v850.c:1895
+#, c-format
+msgid "private flags = %lx: "
+msgstr "˽ÓбêÖ¾ = %lx£º"
+
+#: elf32-v850.c:1900
+msgid "v850 architecture"
+msgstr "v850 Ìåϵ½á¹¹"
+
+#: elf32-v850.c:1901
+msgid "v850e architecture"
+msgstr "v850e Ìåϵ½á¹¹"
+
+#: elf32-v850.c:1902
+msgid "v850ea architecture"
+msgstr "v850ea Ìåϵ½á¹¹"
+
+#: elf32-vax.c:546
+msgid " [nonpic]"
+msgstr ""
+
+#: elf32-vax.c:549
+msgid " [d-float]"
+msgstr ""
+
+#: elf32-vax.c:552
+msgid " [g-float]"
+msgstr ""
+
+#: elf32-vax.c:674
+#, c-format
+msgid "%s: warning: GOT addend of %ld to `%s' does not match previous GOT addend of %ld"
+msgstr ""
+
+#: elf32-vax.c:1679
+#, c-format
+msgid "%s: warning: PLT addend of %d to `%s' from %s section ignored"
+msgstr ""
+
+#: elf32-vax.c:1814
+#, c-format
+msgid "%s: warning: %s relocation against symbol `%s' from %s section"
+msgstr ""
+
+#: elf32-vax.c:1820
+#, c-format
+msgid "%s: warning: %s relocation to 0x%x from %s section"
+msgstr ""
+
+#: elf32-ia64.c:2280 elf32-xstormy16.c:414 elf64-ia64.c:2280
+msgid "non-zero addend in @fptr reloc"
+msgstr ""
+
+#: elf64-alpha.c:1097
+msgid "GPDISP relocation did not find ldah and lda instructions"
+msgstr "GPDISP Öض¨Î»ÎÞ·¨ÕÒµ½ ldah ºÍ lda Ö¸Áî"
+
+#: elf64-alpha.c:3675
+#, c-format
+msgid "%s: .got subsegment exceeds 64K (size %d)"
+msgstr "%s£º.got ×Ó½Ú³¬¹ýÁË 64K (´óС %d)"
+
+#: elf64-alpha.c:4498 elf64-alpha.c:4510
+#, c-format
+msgid "%s: gp-relative relocation against dynamic symbol %s"
+msgstr ""
+
+#: elf64-alpha.c:4536 elf64-alpha.c:4676
+#, c-format
+msgid "%s: pc-relative relocation against dynamic symbol %s"
+msgstr ""
+
+#: elf64-alpha.c:4564
+#, c-format
+msgid "%s: change in gp: BRSGP %s"
+msgstr ""
+
+#: elf64-alpha.c:4589
+msgid "<unknown>"
+msgstr "<δ֪>"
+
+#: elf64-alpha.c:4594
+#, c-format
+msgid "%s: !samegp reloc against symbol without .prologue: %s"
+msgstr ""
+
+#: elf64-alpha.c:4639
+#, c-format
+msgid "%s: unhandled dynamic relocation against %s"
+msgstr "%s£ºÎ´´¦ÀíµÄ¹ØÓÚ %s µÄ¶¯Ì¬Öض¨Î»"
+
+#: elf64-alpha.c:4752
+#, c-format
+msgid "%s: dtp-relative relocation against dynamic symbol %s"
+msgstr ""
+
+#: elf64-alpha.c:4775
+#, c-format
+msgid "%s: tp-relative relocation against dynamic symbol %s"
+msgstr ""
+
+#: elf64-hppa.c:2080
+#, c-format
+msgid "stub entry for %s cannot load .plt, dp offset = %ld"
+msgstr ""
+
+#: elf64-mmix.c:1002
+#, c-format
+msgid ""
+"%s: Internal inconsistency error for value for\n"
+" linker-allocated global register: linked: 0x%lx%08lx != relaxed: 0x%lx%08lx\n"
+msgstr ""
+
+#: elf64-mmix.c:1386
+#, c-format
+msgid "%s: base-plus-offset relocation against register symbol: (unknown) in %s"
+msgstr ""
+
+#: elf64-mmix.c:1391
+#, c-format
+msgid "%s: base-plus-offset relocation against register symbol: %s in %s"
+msgstr ""
+
+#: elf64-mmix.c:1435
+#, c-format
+msgid "%s: register relocation against non-register symbol: (unknown) in %s"
+msgstr ""
+
+#: elf64-mmix.c:1440
+#, c-format
+msgid "%s: register relocation against non-register symbol: %s in %s"
+msgstr ""
+
+#: elf64-mmix.c:1477
+#, c-format
+msgid "%s: directive LOCAL valid only with a register or absolute value"
+msgstr "%s£ºÖ¸Áî LOCAL Ö»¶Ô¼Ä´æÆ÷»ò¾ø¶ÔÖµÓÐЧ"
+
+#: elf64-mmix.c:1505
+#, c-format
+msgid "%s: LOCAL directive: Register $%ld is not a local register.  First global register is $%ld."
+msgstr "%s£ºLOCAL Ö¸Á¼Ä´æÆ÷ $%ld ²»ÊDZ¾µØ¼Ä´æÆ÷¡£ µÚÒ»¸öÈ«¾Ö¼Ä´æÆ÷ÊÇ $%ld¡£"
+
+#: elf64-mmix.c:1965
+#, c-format
+msgid "%s: Error: multiple definition of `%s'; start of %s is set in a earlier linked file\n"
+msgstr "%s£º´íÎó£ºÖظ´¶¨Òå¡°%s¡±£»%s µÄÆðµãÔÚ´ËǰÁ¬½ÓµÄÎļþÖÐÒÑÉ趨\n"
+
+#: elf64-mmix.c:2024
+msgid "Register section has contents\n"
+msgstr "¼Ä´æÆ÷½ÚÓÐÄÚÈÝ\n"
+
+#: elf64-mmix.c:2186
+#, c-format
+msgid ""
+"Internal inconsistency: remaining %u != max %u.\n"
+"  Please report this bug."
+msgstr ""
+"ÄÚ²¿²»Ò»Ö£ºÊ£Óà %u != ×î´ó %u¡£\n"
+"  Ç뱨¸æ¸Ã bug¡£"
+
+#: elf64-ppc.c:1669 libbfd.c:1435
+#, c-format
+msgid "%s: compiled for a big endian system and target is little endian"
+msgstr "%s£ºÎª´ó¶Ëϵͳ±àÒ뵫Ŀ±êƽ̨ÊÇС¶ËµÄ"
+
+#: elf64-ppc.c:1671 libbfd.c:1437
+#, c-format
+msgid "%s: compiled for a little endian system and target is big endian"
+msgstr "%s£ºÎªÐ¡¶Ëϵͳ±àÒ뵫Ŀ±êƽ̨ÊÇ´ó¶ËµÄ"
+
+#: elf64-ppc.c:3610
+#, c-format
+msgid "%s: unexpected reloc type %u in .opd section"
+msgstr "%s£º.opd ½ÚÖÐÒâÍâµÄÖØ¶¨Î»ÀàÐÍ %u"
+
+#: elf64-ppc.c:3630
+#, c-format
+msgid "%s: .opd is not a regular array of opd entries"
+msgstr "%s£º.opd ²»ÊÇ opd ÌõÄ¿µÄÆÕͨÊý×é"
+
+#: elf64-ppc.c:3672
+#, c-format
+msgid "%s: undefined sym `%s' in .opd section"
+msgstr "%s£º.opd ½ÚÖÐ䶨ÒåµÄ¡°%s¡±"
+
+#: elf64-ppc.c:4397
+#, c-format
+msgid "can't find branch stub `%s'"
+msgstr ""
+
+#: elf64-ppc.c:4436 elf64-ppc.c:4501
+#, c-format
+msgid "linkage table error against `%s'"
+msgstr ""
+
+#: elf64-ppc.c:4573
+#, c-format
+msgid "can't build branch stub `%s'"
+msgstr ""
+
+#: elf64-ppc.c:5179
+msgid "stubs don't match calculated size"
+msgstr ""
+
+#: elf64-ppc.c:5828
+#, c-format
+msgid "%s: Relocation %s is not supported for symbol %s."
+msgstr "%s£ºÖض¨Î» %s ²»Ö§³Ö·ûºÅ %s¡£"
+
+#: elf64-ppc.c:5872
+#, c-format
+msgid "%s: error: relocation %s not a multiple of 4"
+msgstr "%s£º´íÎó£ºÖض¨Î» %s ²»ÊÇ 4 µÄ±¶Êý"
+
+#: elf64-sparc.c:1280
+#, c-format
+msgid "%s: check_relocs: unhandled reloc type %d"
+msgstr "%s£ºcheck_relocs£ºÎ´´¦ÀíµÄÖØ¶¨Î»ÀàÐÍ %d"
+
+#: elf64-sparc.c:1317
+#, c-format
+msgid "%s: Only registers %%g[2367] can be declared using STT_REGISTER"
+msgstr "%s£ºÖ»ÓмĴæÆ÷ %%g[2367] ¿ÉÒÔÓàSTT_REGISTER À´ÉùÃ÷"
+
+#: elf64-sparc.c:1337
+#, c-format
+msgid "Register %%g%d used incompatibly: %s in %s, previously %s in %s"
+msgstr "²»¼æÈݵØÊ¹ÓüĴæÆ÷ %%g%1$d£ºÔÚ %3$s ÖÐΪ %2$s£¬ÔÚÇ°ÃæµÄ %5$s ÖÐΪ %4$s"
+
+#: elf64-sparc.c:1360
+#, c-format
+msgid "Symbol `%s' has differing types: REGISTER in %s, previously %s in %s"
+msgstr "·ûºÅ¡°%1$s¡±µÄÀàÐͲ»Í¬£º%2$s ÖÐΪ¼Ä´æÆ÷£¬ÔÚÇ°ÃæµÄ %4$s ÖÐΪ %3$s"
+
+#: elf64-sparc.c:1406
+#, c-format
+msgid "Symbol `%s' has differing types: %s in %s, previously REGISTER in %s"
+msgstr ""
+
+#: elf64-sparc.c:2970
+#, c-format
+msgid "%s: linking UltraSPARC specific with HAL specific code"
+msgstr ""
+
+#: elfcode.h:1198
+#, c-format
+msgid "%s: version count (%ld) does not match symbol count (%ld)"
+msgstr "%s£º°æ±¾¼ÆÊý (%ld) ÎÞ·¨Æ¥Åä·ûºÅ¼ÆÊý (%ld)"
+
+#: elflink.c:440
+#, c-format
+msgid "%s: Section %s is too large to add hole of %ld bytes"
+msgstr ""
+
+#: elflink.h:1090
+#, c-format
+msgid "%s: warning: unexpected redefinition of `%s'"
+msgstr "%s£º¾¯¸æ£ºÒâÍâµÄÖØÐ¶¨Òå¡°%s¡±"
+
+#: elflink.h:1727
+#, c-format
+msgid "%s: %s: invalid version %u (max %d)"
+msgstr "%s£º%s£ºÎÞЧµÄ°æ±¾ %u (×î´ó %d)"
+
+#: elflink.h:1768
+#, c-format
+msgid "%s: %s: invalid needed version %d"
+msgstr "%s£º%s£ºÎÞЧµÄ±Ø±¸°æ±¾ %d"
+
+#: elflink.h:1890
+#, c-format
+msgid "Warning: size of symbol `%s' changed from %lu to %lu in %s"
+msgstr "¾¯¸æ£º%4$s ÖеķûºÅ¡°%1$s¡±µÄ´óСÓÉ %2$lu ±äΪ %3$lu"
+
+#: elflink.h:3174
+#, c-format
+msgid "%s: .preinit_array section is not allowed in DSO"
+msgstr "%s£ºDSO Öв»ÔÊÐí³öÏÖ .preinit_array ½Ú"
+
+#: elflink.h:4030
+#, c-format
+msgid "warning: type and size of dynamic symbol `%s' are not defined"
+msgstr "¾¯¸æ£º¶¯Ì¬·ûºÅ¡°%s¡±µÄÀàÐͺʹóС䶨Òå"
+
+#: elflink.h:4345
+#, c-format
+msgid "%s: undefined versioned symbol name %s"
+msgstr "%s£ºÎ´¶¨ÒåµÄÓа汾·ûºÅÃû %s"
+
+#: elflink.h:4611 elflink.h:4619 elflink.h:6508 elflink.h:7600
+msgid "Error: out of memory"
+msgstr "´íÎó£ºÃ»ÓÐÄÚ´æ"
+
+#: elflink.h:4781
+msgid "Not enough memory to sort relocations"
+msgstr "ûÓÐ×ã¹»µÄÄÚ´æ½øÐÐÖØ¶¨Î»ÅÅÐò"
+
+#: elflink.h:5682 elflink.h:5725
+#, c-format
+msgid "%s: could not find output section %s"
+msgstr "%s£ºÎÞ·¨ÕÒµ½Êä³ö½Ú %s"
+
+#: elflink.h:5688
+#, c-format
+msgid "warning: %s section has zero size"
+msgstr "¾¯¸æ£º%s ½ÚµÄ´óСΪÁã"
+
+#: elflink.h:6275
+#, c-format
+msgid "%s: could not find output section %s for input section %s"
+msgstr "%1$s£ºÎÞ·¨ÎªÊäÈë½Ú %3$s ÕÒµ½Êä³ö½Ú %2$s"
+
+#: elflink.h:6486
+#, c-format
+msgid "%s: relocation size mismatch in %s section %s"
+msgstr ""
+
+#: elflink.h:6849
+msgid "warning: relocation against removed section; zeroing"
+msgstr "¾¯¸æ£º¹ØÓÚÒÑɾ³ýµÄ½ÚµÄÖØ¶¨Î»£»ÕýÔÚÇåÁã"
+
+#: elflink.h:6879
+msgid "warning: relocation against removed section"
+msgstr "¾¯¸æ£º¹ØÓÚÒÑɾ³ýµÄ½ÚµÄÖØ¶¨Î»"
+
+#: elflink.h:6892
+#, c-format
+msgid "local symbols in discarded section %s"
+msgstr "ÒѽûÓõĽڠ%s Öеı¾µØ·ûºÅ"
+
+#: elfxx-mips.c:734
+msgid "static procedure (no name)"
+msgstr "¾²Ì¬¹ý³Ì (ÎÞÃû³Æ)"
+
+#: elfxx-mips.c:1601
+msgid "not enough GOT space for local GOT entries"
+msgstr "ûÓÐ×ã¹»µÄ GOT ¿Õ¼äÓÃÓÚ GOT ÌõÄ¿"
+
+#: elfxx-mips.c:2750
+#, c-format
+msgid "%s: %s+0x%lx: jump to stub routine which is not jal"
+msgstr ""
+
+#: elfxx-mips.c:4270
+#, c-format
+msgid "%s: Malformed reloc detected for section %s"
+msgstr ""
+
+#: elfxx-mips.c:4348
+#, c-format
+msgid "%s: CALL16 reloc at 0x%lx not against global symbol"
+msgstr ""
+
+#: elfxx-mips.c:7301
+#, c-format
+msgid "%s: illegal section name `%s'"
+msgstr "%s£º·Ç·¨µÄ½ÚÃû¡°%s¡±"
+
+#: elfxx-mips.c:7615
+#, c-format
+msgid "%s: linking PIC files with non-PIC files"
+msgstr "%s£º½« PIC Îļþͬ·Ç-PIC ÎļþÁ¬½Ó"
+
+#: elfxx-mips.c:7625
+#, c-format
+msgid "%s: linking abicalls files with non-abicalls files"
+msgstr ""
+
+#: elfxx-mips.c:7654
+#, c-format
+msgid "%s: ISA mismatch (-mips%d) with previous modules (-mips%d)"
+msgstr "%s£ºISA (-mips%d) Í¬Ç°ÃæµÄÄ£¿é(-mips%d)²»Æ¥Åä"
+
+#: elfxx-mips.c:7676
+#, c-format
+msgid "%s: ISA mismatch (%d) with previous modules (%d)"
+msgstr "%s£ºISA (%d) Í¬Ç°ÃæµÄÄ£¿é (%d) ²»Æ¥Åä"
+
+#: elfxx-mips.c:7699
+#, c-format
+msgid "%s: ABI mismatch: linking %s module with previous %s modules"
+msgstr "%s£ºABI ²»Æ¥Å䣺ÕýÔÚ½«Ä£¿é %s Í¬Ç°Ò»¸öÄ£¿é %s ½øÐÐÁ¬½Ó"
+
+#: elfxx-mips.c:7759
+msgid " [abi=O32]"
+msgstr " [abi=O32]"
+
+#: elfxx-mips.c:7761
+msgid " [abi=O64]"
+msgstr " [abi=O64]"
+
+#: elfxx-mips.c:7763
+msgid " [abi=EABI32]"
+msgstr " [abi=EABI32]"
+
+#: elfxx-mips.c:7765
+msgid " [abi=EABI64]"
+msgstr " [abi=EABI64]"
+
+#: elfxx-mips.c:7767
+msgid " [abi unknown]"
+msgstr " [abi δ֪]"
+
+#: elfxx-mips.c:7769
+msgid " [abi=N32]"
+msgstr " [abi=N32]"
+
+#: elfxx-mips.c:7771
+msgid " [abi=64]"
+msgstr " [abi=64]"
+
+#: elfxx-mips.c:7773
+msgid " [no abi set]"
+msgstr ""
+
+#: elfxx-mips.c:7776
+msgid " [mips1]"
+msgstr " [mips1]"
+
+#: elfxx-mips.c:7778
+msgid " [mips2]"
+msgstr " [mips2]"
+
+#: elfxx-mips.c:7780
+msgid " [mips3]"
+msgstr " [mips3]"
+
+#: elfxx-mips.c:7782
+msgid " [mips4]"
+msgstr " [mips4]"
+
+#: elfxx-mips.c:7784
+msgid " [mips5]"
+msgstr " [mips5]"
+
+#: elfxx-mips.c:7786
+msgid " [mips32]"
+msgstr " [mips32]"
+
+#: elfxx-mips.c:7788
+msgid " [mips64]"
+msgstr " [mips64]"
+
+#: elfxx-mips.c:7790
+msgid " [unknown ISA]"
+msgstr " [δ֪µÄ ISA]"
+
+#: elfxx-mips.c:7793
+msgid " [mdmx]"
+msgstr " [mdmx]"
+
+#: elfxx-mips.c:7796
+msgid " [mips16]"
+msgstr " [mips16]"
+
+#: elfxx-mips.c:7799
+msgid " [32bitmode]"
+msgstr " [32λģʽ]"
+
+#: elfxx-mips.c:7801
+msgid " [not 32bitmode]"
+msgstr " [·Ç 32λģʽ]"
+
+#: i386linux.c:458 m68klinux.c:462 sparclinux.c:459
+#, c-format
+msgid "Output file requires shared library `%s'\n"
+msgstr "Êä³öÎļþÐèÒª¹²Ïí¿â¡°%s¡±\n"
+
+#: i386linux.c:466 m68klinux.c:470 sparclinux.c:467
+#, c-format
+msgid "Output file requires shared library `%s.so.%s'\n"
+msgstr "Êä³öÎļþÐèÒª¹²Ïí¿â¡°%s.so.%s¡±\n"
+
+#: i386linux.c:655 i386linux.c:705 m68klinux.c:662 m68klinux.c:710
+#: sparclinux.c:657 sparclinux.c:707
+#, c-format
+msgid "Symbol %s not defined for fixups\n"
+msgstr ""
+
+#: i386linux.c:729 m68klinux.c:734 sparclinux.c:731
+msgid "Warning: fixup count mismatch\n"
+msgstr ""
+
+#: ieee.c:235
+#, c-format
+msgid "%s: string too long (%d chars, max 65535)"
+msgstr "%s£º×Ö·û´®¹ý³¤ (%d ×Ö·û£¬×î´ó 65535)"
+
+#: ieee.c:365
+#, c-format
+msgid "%s: unrecognized symbol `%s' flags 0x%x"
+msgstr "%s£ºÎÞ·¨Ê¶±ðµÄ¡°%s¡±±êÖ¾ 0x%x"
+
+#: ieee.c:877
+#, c-format
+msgid "%s: unimplemented ATI record %u for symbol %u"
+msgstr ""
+
+#: ieee.c:902
+#, c-format
+msgid "%s: unexpected ATN type %d in external part"
+msgstr ""
+
+#: ieee.c:924
+#, c-format
+msgid "%s: unexpected type after ATN"
+msgstr "%s£ºATN Ö®ºó³öÏÖÒâÍâµÄÀàÐÍ"
+
+#: ihex.c:258
+#, c-format
+msgid "%s:%d: unexpected character `%s' in Intel Hex file\n"
+msgstr "%s£º%d£ºIntel Ê®Áù½øÖÆÎļþÖеÄÒâÍâ×Ö·û¡°%s\n"
+
+#: ihex.c:366
+#, c-format
+msgid "%s:%u: bad checksum in Intel Hex file (expected %u, found %u)"
+msgstr "%s£º%u£ºIntel Ê®Áù½øÖÆÎļþÖеÄУÑéºÍ´íÎó (ӦΪ %u¡¢ÊµÎª %u)"
+
+#: ihex.c:420
+#, c-format
+msgid "%s:%u: bad extended address record length in Intel Hex file"
+msgstr ""
+
+#: ihex.c:437
+#, c-format
+msgid "%s:%u: bad extended start address length in Intel Hex file"
+msgstr ""
+
+#: ihex.c:454
+#, c-format
+msgid "%s:%u: bad extended linear address record length in Intel Hex file"
+msgstr ""
+
+#: ihex.c:471
+#, c-format
+msgid "%s:%u: bad extended linear start address length in Intel Hex file"
+msgstr ""
+
+#: ihex.c:488
+#, c-format
+msgid "%s:%u: unrecognized ihex type %u in Intel Hex file\n"
+msgstr ""
+
+#: ihex.c:607
+#, c-format
+msgid "%s: internal error in ihex_read_section"
+msgstr ""
+
+#: ihex.c:642
+#, c-format
+msgid "%s: bad section length in ihex_read_section"
+msgstr ""
+
+#: ihex.c:860
+#, c-format
+msgid "%s: address 0x%s out of range for Intel Hex file"
+msgstr ""
+
+#: libbfd.c:492
+#, c-format
+msgid "not mapping: data=%lx mapped=%d\n"
+msgstr ""
+
+#: libbfd.c:495
+msgid "not mapping: env var not set\n"
+msgstr ""
+
+#: libbfd.c:1466
+#, c-format
+msgid "Deprecated %s called at %s line %d in %s\n"
+msgstr ""
+
+#: libbfd.c:1469
+#, c-format
+msgid "Deprecated %s called\n"
+msgstr ""
+
+#: linker.c:1873
+#, c-format
+msgid "%s: indirect symbol `%s' to `%s' is a loop"
+msgstr ""
+
+#: linker.c:2776
+#, c-format
+msgid "Attempt to do relocateable link with %s input and %s output"
+msgstr ""
+
+#: merge.c:892
+#, c-format
+msgid "%s: access beyond end of merged section (%ld + %ld)"
+msgstr ""
+
+#: mmo.c:460
+#, c-format
+msgid "%s: No core to allocate section name %s\n"
+msgstr ""
+
+#: mmo.c:536
+#, c-format
+msgid "%s: No core to allocate a symbol %d bytes long\n"
+msgstr ""
+
+#: mmo.c:1245
+#, c-format
+msgid "%s: invalid mmo file: initialization value for $255 is not `Main'\n"
+msgstr ""
+
+#: mmo.c:1391
+#, c-format
+msgid "%s: unsupported wide character sequence 0x%02X 0x%02X after symbol name starting with `%s'\n"
+msgstr ""
+
+#: mmo.c:1633
+#, c-format
+msgid "%s: invalid mmo file: unsupported lopcode `%d'\n"
+msgstr ""
+
+#: mmo.c:1643
+#, c-format
+msgid "%s: invalid mmo file: expected YZ = 1 got YZ = %d for lop_quote\n"
+msgstr ""
+
+#: mmo.c:1679
+#, c-format
+msgid "%s: invalid mmo file: expected z = 1 or z = 2, got z = %d for lop_loc\n"
+msgstr ""
+
+#: mmo.c:1725
+#, c-format
+msgid "%s: invalid mmo file: expected z = 1 or z = 2, got z = %d for lop_fixo\n"
+msgstr ""
+
+#: mmo.c:1764
+#, c-format
+msgid "%s: invalid mmo file: expected y = 0, got y = %d for lop_fixrx\n"
+msgstr ""
+
+#: mmo.c:1773
+#, c-format
+msgid "%s: invalid mmo file: expected z = 16 or z = 24, got z = %d for lop_fixrx\n"
+msgstr ""
+
+#: mmo.c:1796
+#, c-format
+msgid "%s: invalid mmo file: leading byte of operand word must be 0 or 1, got %d for lop_fixrx\n"
+msgstr ""
+
+#: mmo.c:1819
+#, c-format
+msgid "%s: cannot allocate file name for file number %d, %d bytes\n"
+msgstr ""
+
+#: mmo.c:1839
+#, c-format
+msgid "%s: invalid mmo file: file number %d `%s', was already entered as `%s'\n"
+msgstr ""
+
+#: mmo.c:1852
+#, c-format
+msgid "%s: invalid mmo file: file name for number %d was not specified before use\n"
+msgstr ""
+
+#: mmo.c:1958
+#, c-format
+msgid "%s: invalid mmo file: fields y and z of lop_stab non-zero, y: %d, z: %d\n"
+msgstr ""
+
+#: mmo.c:1994
+#, c-format
+msgid "%s: invalid mmo file: lop_end not last item in file\n"
+msgstr ""
+
+#: mmo.c:2007
+#, c-format
+msgid "%s: invalid mmo file: YZ of lop_end (%ld) not equal to the number of tetras to the preceding lop_stab (%ld)\n"
+msgstr ""
+
+#: mmo.c:2670
+#, c-format
+msgid "%s: invalid symbol table: duplicate symbol `%s'\n"
+msgstr ""
+
+#: mmo.c:2921
+#, c-format
+msgid "%s: Bad symbol definition: `Main' set to %s rather than the start address %s\n"
+msgstr ""
+
+#: mmo.c:3011
+#, c-format
+msgid "%s: warning: symbol table too large for mmo, larger than 65535 32-bit words: %d.  Only `Main' will be emitted.\n"
+msgstr ""
+
+#: mmo.c:3056
+#, c-format
+msgid "%s: internal error, symbol table changed size from %d to %d words\n"
+msgstr ""
+
+#: mmo.c:3111
+#, c-format
+msgid "%s: internal error, internal register section %s had contents\n"
+msgstr ""
+
+#: mmo.c:3163
+#, c-format
+msgid "%s: no initialized registers; section length 0\n"
+msgstr ""
+
+#: mmo.c:3169
+#, c-format
+msgid "%s: too many initialized registers; section length %ld\n"
+msgstr ""
+
+#: mmo.c:3174
+#, c-format
+msgid "%s: invalid start address for initialized registers of length %ld: 0x%lx%08lx\n"
+msgstr ""
+
+#: oasys.c:1029
+#, c-format
+msgid "%s: can not represent section `%s' in oasys"
+msgstr ""
+
+#: osf-core.c:132
+#, c-format
+msgid "Unhandled OSF/1 core file section type %d\n"
+msgstr ""
+
+#: pe-mips.c:658
+#, c-format
+msgid "%s: `ld -r' not supported with PE MIPS objects\n"
+msgstr ""
+
+#. OK, at this point the following variables are set up:
+#. src = VMA of the memory we're fixing up
+#. mem = pointer to memory we're fixing up
+#. val = VMA of what we need to refer to
+#.
+#: pe-mips.c:794
+#, c-format
+msgid "%s: unimplemented %s\n"
+msgstr "%s£ºÎ´ÊµÏֵĠ%s\n"
+
+#: pe-mips.c:820
+#, c-format
+msgid "%s: jump too far away\n"
+msgstr "%s£ºÌø×ª¹ýÔ¶\n"
+
+#: pe-mips.c:847
+#, c-format
+msgid "%s: bad pair/reflo after refhi\n"
+msgstr ""
+
+#. XXX code yet to be written.
+#: peicode.h:785
+#, c-format
+msgid "%s: Unhandled import type; %x"
+msgstr "%s£ºÎ´´¦ÀíµÄµ¼ÈëÀàÐÍ£»%x"
+
+#: peicode.h:790
+#, c-format
+msgid "%s: Unrecognised import type; %x"
+msgstr "%s£ºÎ´Ê¶±ðµÄµ¼ÈëÀàÐÍ£»%x"
+
+#: peicode.h:804
+#, c-format
+msgid "%s: Unrecognised import name type; %x"
+msgstr "%s£ºÎ´Ê¶±ðµÄµ¼ÈëÃû×ÖÀàÐÍ£»%x"
+
+#: peicode.h:1162
+#, c-format
+msgid "%s: Unrecognised machine type (0x%x) in Import Library Format archive"
+msgstr ""
+
+#: peicode.h:1174
+#, c-format
+msgid "%s: Recognised but unhandled machine type (0x%x) in Import Library Format archive"
+msgstr ""
+
+#: peicode.h:1191
+#, c-format
+msgid "%s: size field is zero in Import Library Format header"
+msgstr ""
+
+#: peicode.h:1219
+#, c-format
+msgid "%s: string not null terminated in ILF object file."
+msgstr ""
+
+#: ppcboot.c:416
+msgid ""
+"\n"
+"ppcboot header:\n"
+msgstr ""
+
+#: ppcboot.c:417
+#, c-format
+msgid "Entry offset        = 0x%.8lx (%ld)\n"
+msgstr "ÌõÄ¿Æ«ÒÆÁ¿        = 0x%.8lx (%ld)\n"
+
+#: ppcboot.c:418
+#, c-format
+msgid "Length              = 0x%.8lx (%ld)\n"
+msgstr "³¤¶È              = 0x%.8lx (%ld)\n"
+
+#: ppcboot.c:421
+#, c-format
+msgid "Flag field          = 0x%.2x\n"
+msgstr "±êÖ¾Óò          = 0x%.2x\n"
+
+#: ppcboot.c:427
+#, c-format
+msgid "Partition name      = \"%s\"\n"
+msgstr "·ÖÇøÃû      = \"%s\"\n"
+
+#: ppcboot.c:446
+#, c-format
+msgid ""
+"\n"
+"Partition[%d] start  = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n"
+msgstr ""
+"\n"
+"·ÖÇø[%d] Æðµã  = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n"
+
+#: ppcboot.c:452
+#, c-format
+msgid "Partition[%d] end    = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n"
+msgstr "·ÖÇø[%d] Öյ㠠  = { 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x }\n"
+
+#: ppcboot.c:458
+#, c-format
+msgid "Partition[%d] sector = 0x%.8lx (%ld)\n"
+msgstr "·ÖÇø[%d] ÉÈÇø = 0x%.8lx (%ld)\n"
+
+#: ppcboot.c:459
+#, c-format
+msgid "Partition[%d] length = 0x%.8lx (%ld)\n"
+msgstr "·ÖÇø[%d] ³¤¶È = 0x%.8lx (%ld)\n"
+
+#: som.c:5398
+msgid "som_sizeof_headers unimplemented"
+msgstr ""
+
+#: srec.c:301
+#, c-format
+msgid "%s:%d: Unexpected character `%s' in S-record file\n"
+msgstr ""
+
+#: stabs.c:319
+#, c-format
+msgid "%s(%s+0x%lx): Stabs entry has invalid string index."
+msgstr ""
+
+#: syms.c:1044
+msgid "Unsupported .stab relocation"
+msgstr "²»Ö§³ÖµÄ .stab Öض¨Î»"
+
+#: vms-gsd.c:356
+#, c-format
+msgid "bfd_make_section (%s) failed"
+msgstr ""
+
+#: vms-gsd.c:371
+#, c-format
+msgid "bfd_set_section_flags (%s, %x) failed"
+msgstr ""
+
+#: vms-gsd.c:407
+#, c-format
+msgid "Size mismatch section %s=%lx, %s=%lx"
+msgstr ""
+
+#: vms-gsd.c:702
+#, c-format
+msgid "unknown gsd/egsd subtype %d"
+msgstr ""
+
+#: vms-hdr.c:406
+msgid "Object module NOT error-free !\n"
+msgstr ""
+
+#: vms-misc.c:543
+#, c-format
+msgid "Stack overflow (%d) in _bfd_vms_push"
+msgstr ""
+
+#: vms-misc.c:561
+msgid "Stack underflow in _bfd_vms_pop"
+msgstr ""
+
+#: vms-misc.c:919
+msgid "_bfd_vms_output_counted called with zero bytes"
+msgstr ""
+
+#: vms-misc.c:924
+msgid "_bfd_vms_output_counted called with too many bytes"
+msgstr ""
+
+#: vms-misc.c:1055
+#, c-format
+msgid "Symbol %s replaced by %s\n"
+msgstr ""
+
+#: vms-misc.c:1117
+#, c-format
+msgid "failed to enter %s"
+msgstr ""
+
+#: vms-tir.c:81
+msgid "No Mem !"
+msgstr ""
+
+#: vms-tir.c:362
+#, c-format
+msgid "bad section index in %s"
+msgstr "%s ÖеĴíÎó½ÚË÷Òý"
+
+#: vms-tir.c:375
+#, c-format
+msgid "unsupported STA cmd %s"
+msgstr "²»Ö§³ÖµÄ STA ÃüÁî %s"
+
+#: vms-tir.c:380 vms-tir.c:1240
+#, c-format
+msgid "reserved STA cmd %d"
+msgstr ""
+
+#: vms-tir.c:491 vms-tir.c:514
+#, c-format
+msgid "%s: no symbol \"%s\""
+msgstr ""
+
+#. unsigned shift
+#. rotate
+#. Redefine symbol to current location.
+#. Define a literal.
+#: vms-tir.c:581 vms-tir.c:693 vms-tir.c:803 vms-tir.c:821 vms-tir.c:829
+#: vms-tir.c:838 vms-tir.c:1563
+#, c-format
+msgid "%s: not supported"
+msgstr "%s£º²»Ö§³Ö"
+
+#: vms-tir.c:586 vms-tir.c:1418
+#, c-format
+msgid "%s: not implemented"
+msgstr "%s£ºÎ´ÊµÏÖ"
+
+#: vms-tir.c:590 vms-tir.c:1422
+#, c-format
+msgid "reserved STO cmd %d"
+msgstr "±£ÁôµÄ STO ÃüÁî %d"
+
+#: vms-tir.c:708 vms-tir.c:1568
+#, c-format
+msgid "reserved OPR cmd %d"
+msgstr "±£ÁôµÄ OPR ÃüÁî %d"
+
+#: vms-tir.c:776 vms-tir.c:1632
+#, c-format
+msgid "reserved CTL cmd %d"
+msgstr "±£ÁôµÄ CTL ÃüÁî %d"
+
+#. stack byte from image
+#. arg: none.
+#: vms-tir.c:1148
+msgid "stack-from-image not implemented"
+msgstr "δʵÏÖ stack-from-image"
+
+#: vms-tir.c:1166
+msgid "stack-entry-mask not fully implemented"
+msgstr "ÉÐδÍêȫʵÏÖ stack-entry-mask"
+
+#. compare procedure argument
+#. arg: cs     symbol name
+#. by  argument index
+#. da  argument descriptor
+#.
+#. compare argument descriptor with symbol argument (ARG$V_PASSMECH)
+#. and stack TRUE (args match) or FALSE (args dont match) value.
+#: vms-tir.c:1180
+msgid "PASSMECH not fully implemented"
+msgstr "ÉÐδÍêȫʵÏÖ PASSMECH"
+
+#: vms-tir.c:1199
+msgid "stack-local-symbol not fully implemented"
+msgstr "ÉÐδÍêȫʵÏÖ stack-local-symbol"
+
+#: vms-tir.c:1212
+msgid "stack-literal not fully implemented"
+msgstr "ÉÐδÍêȫʵÏÖ stack-literal"
+
+#: vms-tir.c:1233
+msgid "stack-local-symbol-entry-point-mask not fully implemented"
+msgstr "ÉÐδÍêȫʵÏÖ stack-local-symbol-entry-point-mask"
+
+#: vms-tir.c:1510 vms-tir.c:1522 vms-tir.c:1534 vms-tir.c:1546 vms-tir.c:1611
+#: vms-tir.c:1619 vms-tir.c:1627
+#, c-format
+msgid "%s: not fully implemented"
+msgstr "%s£ºÉÐδÍêȫʵÏÖ"
+
+#: vms-tir.c:1684
+#, c-format
+msgid "obj code %d not found"
+msgstr ""
+
+#: vms-tir.c:2019
+#, c-format
+msgid "SEC_RELOC with no relocs in section %s"
+msgstr ""
+
+#: vms-tir.c:2307
+#, c-format
+msgid "Unhandled relocation %s"
+msgstr "δ´¦ÀíµÄÖØ¶¨Î» %s"
+
+#: xcofflink.c:1243
+#, c-format
+msgid "%s: `%s' has line numbers but no enclosing section"
+msgstr ""
+
+#: xcofflink.c:1296
+#, c-format
+msgid "%s: class %d symbol `%s' has no aux entries"
+msgstr ""
+
+#: xcofflink.c:1319
+#, c-format
+msgid "%s: symbol `%s' has unrecognized csect type %d"
+msgstr ""
+
+#: xcofflink.c:1331
+#, c-format
+msgid "%s: bad XTY_ER symbol `%s': class %d scnum %d scnlen %d"
+msgstr ""
+
+#: xcofflink.c:1367
+#, c-format
+msgid "%s: XMC_TC0 symbol `%s' is class %d scnlen %d"
+msgstr ""
+
+#: xcofflink.c:1519
+#, c-format
+msgid "%s: csect `%s' not in enclosing section"
+msgstr ""
+
+#: xcofflink.c:1626
+#, c-format
+msgid "%s: misplaced XTY_LD `%s'"
+msgstr ""
+
+#: xcofflink.c:1957
+#, c-format
+msgid "%s: reloc %s:%d not in csect"
+msgstr ""
+
+#: xcofflink.c:2092
+#, c-format
+msgid "%s: XCOFF shared object when not producing XCOFF output"
+msgstr ""
+
+#: xcofflink.c:2113
+#, c-format
+msgid "%s: dynamic object with no .loader section"
+msgstr ""
+
+#: xcofflink.c:2758
+#, c-format
+msgid "%s: no such symbol"
+msgstr ""
+
+#: xcofflink.c:2891
+msgid "error: undefined symbol __rtinit"
+msgstr "´íÎó£ºÎ´¶¨ÒåµÄ·ûºÅ __rtinit"
+
+#: xcofflink.c:3453
+#, c-format
+msgid "warning: attempt to export undefined symbol `%s'"
+msgstr "¾¯¸æ£ºÊÔͼµ¼³ö䶨ÒåµÄ·ûºÅ¡°%s¡±"
+
+#: xcofflink.c:4447
+#, c-format
+msgid "TOC overflow: 0x%lx > 0x10000; try -mminimal-toc when compiling"
+msgstr ""
+
+#: xcofflink.c:5287 xcofflink.c:5756 xcofflink.c:5818 xcofflink.c:6119
+#, c-format
+msgid "%s: loader reloc in unrecognized section `%s'"
+msgstr ""
+
+#: xcofflink.c:5309 xcofflink.c:6130
+#, c-format
+msgid "%s: `%s' in loader reloc but not loader sym"
+msgstr ""
+
+#: xcofflink.c:5324
+#, c-format
+msgid "%s: loader reloc in read-only section %s"
+msgstr ""
+
+#: elf32-ia64.c:2222 elf64-ia64.c:2222
+msgid "@pltoff reloc against local symbol"
+msgstr ""
+
+#: elf32-ia64.c:3562 elf64-ia64.c:3562
+#, c-format
+msgid "%s: short data segment overflowed (0x%lx >= 0x400000)"
+msgstr ""
+
+#: elf32-ia64.c:3573 elf64-ia64.c:3573
+#, c-format
+msgid "%s: __gp does not cover short data segment"
+msgstr ""
+
+#: elf32-ia64.c:3858 elf64-ia64.c:3858
+#, c-format
+msgid "%s: linking non-pic code in a shared library"
+msgstr ""
+
+#: elf32-ia64.c:3891 elf64-ia64.c:3891
+#, c-format
+msgid "%s: @gprel relocation against dynamic symbol %s"
+msgstr ""
+
+#: elf32-ia64.c:4030 elf64-ia64.c:4030
+#, c-format
+msgid "%s: dynamic relocation against speculation fixup"
+msgstr ""
+
+#: elf32-ia64.c:4038 elf64-ia64.c:4038
+#, c-format
+msgid "%s: speculation fixup against undefined weak symbol"
+msgstr ""
+
+#: elf32-ia64.c:4271 elf64-ia64.c:4271
+msgid "unsupported reloc"
+msgstr "²»Ö§³ÖµÄÖØ¶¨Î»"
+
+#: elf32-ia64.c:4551 elf64-ia64.c:4551
+#, c-format
+msgid "%s: linking trap-on-NULL-dereference with non-trapping files"
+msgstr ""
+
+#: elf32-ia64.c:4560 elf64-ia64.c:4560
+#, c-format
+msgid "%s: linking big-endian files with little-endian files"
+msgstr "%s£º½«´ó¶ËÎļþͬС¶ËÎļþ"
+
+#: elf32-ia64.c:4569 elf64-ia64.c:4569
+#, c-format
+msgid "%s: linking 64-bit files with 32-bit files"
+msgstr "%s£º½« 64-λÎļþͬ 32-λÎļþÁ¬½Ó"
+
+#: elf32-ia64.c:4578 elf64-ia64.c:4578
+#, c-format
+msgid "%s: linking constant-gp files with non-constant-gp files"
+msgstr ""
+
+#: elf32-ia64.c:4588 elf64-ia64.c:4588
+#, c-format
+msgid "%s: linking auto-pic files with non-auto-pic files"
+msgstr ""
+
+#: peigen.c:962 pepigen.c:962
+#, c-format
+msgid "%s: line number overflow: 0x%lx > 0xffff"
+msgstr "%s£ºÐкÅÒç³ö£º0x%lx > 0xffff"
+
+#: peigen.c:979 pepigen.c:979
+#, c-format
+msgid "%s: reloc overflow 1: 0x%lx > 0xffff"
+msgstr ""
+
+#: peigen.c:993 pepigen.c:993
+msgid "Export Directory [.edata (or where ever we found it)]"
+msgstr "µ¼³öĿ¼ [.edata (»òÕ߯äËüÈκÎÄÜÕÒµ½ËüµÄµØ·½)]"
+
+#: peigen.c:994 pepigen.c:994
+msgid "Import Directory [parts of .idata]"
+msgstr "µ¼ÈëĿ¼ [.idata µÄÒ»²¿·Ö]"
+
+#: peigen.c:995 pepigen.c:995
+msgid "Resource Directory [.rsrc]"
+msgstr "×ÊԴĿ¼ [.rsrc]"
+
+#: peigen.c:996 pepigen.c:996
+msgid "Exception Directory [.pdata]"
+msgstr ""
+
+#: peigen.c:997 pepigen.c:997
+msgid "Security Directory"
+msgstr "°²È«Ä¿Â¼"
+
+#: peigen.c:998 pepigen.c:998
+msgid "Base Relocation Directory [.reloc]"
+msgstr ""
+
+#: peigen.c:999 pepigen.c:999
+msgid "Debug Directory"
+msgstr "µ÷ÊÔĿ¼"
+
+#: peigen.c:1000 pepigen.c:1000
+msgid "Description Directory"
+msgstr "ÃèÊöĿ¼"
+
+#: peigen.c:1001 pepigen.c:1001
+msgid "Special Directory"
+msgstr "ÌØÊâĿ¼"
+
+#: peigen.c:1002 pepigen.c:1002
+msgid "Thread Storage Directory [.tls]"
+msgstr "Ï̴߳洢Ŀ¼ [.tls]"
+
+#: peigen.c:1003 pepigen.c:1003
+msgid "Load Configuration Directory"
+msgstr "×°ÈëÅäÖÃĿ¼"
+
+#: peigen.c:1004 pepigen.c:1004
+msgid "Bound Import Directory"
+msgstr ""
+
+#: peigen.c:1005 pepigen.c:1005
+msgid "Import Address Table Directory"
+msgstr "µ¼ÈëµØÖ·±íĿ¼"
+
+#: peigen.c:1006 pepigen.c:1006
+msgid "Delay Import Directory"
+msgstr "ÑÓ³Ùµ¼ÈëĿ¼"
+
+#: peigen.c:1007 peigen.c:1008 pepigen.c:1007 pepigen.c:1008
+msgid "Reserved"
+msgstr "±£Áô"
+
+#: peigen.c:1071 pepigen.c:1071
+msgid ""
+"\n"
+"There is an import table, but the section containing it could not be found\n"
+msgstr ""
+
+#: peigen.c:1076 pepigen.c:1076
+#, c-format
+msgid ""
+"\n"
+"There is an import table in %s at 0x%lx\n"
+msgstr ""
+
+#: peigen.c:1113 pepigen.c:1113
+#, c-format
+msgid ""
+"\n"
+"Function descriptor located at the start address: %04lx\n"
+msgstr ""
+
+#: peigen.c:1116 pepigen.c:1116
+#, c-format
+msgid "\tcode-base %08lx toc (loadable/actual) %08lx/%08lx\n"
+msgstr ""
+
+#: peigen.c:1122 pepigen.c:1122
+msgid ""
+"\n"
+"No reldata section! Function descriptor not decoded.\n"
+msgstr ""
+
+#: peigen.c:1127 pepigen.c:1127
+#, c-format
+msgid ""
+"\n"
+"The Import Tables (interpreted %s section contents)\n"
+msgstr ""
+
+#: peigen.c:1130 pepigen.c:1130
+msgid ""
+" vma:            Hint    Time      Forward  DLL       First\n"
+"                 Table   Stamp     Chain    Name      Thunk\n"
+msgstr ""
+
+#: peigen.c:1181 pepigen.c:1181
+#, c-format
+msgid ""
+"\n"
+"\tDLL Name: %s\n"
+msgstr ""
+"\n"
+"\tDLL Ãû³Æ£º%s\n"
+
+#: peigen.c:1192 pepigen.c:1192
+msgid "\tvma:  Hint/Ord Member-Name Bound-To\n"
+msgstr ""
+
+#: peigen.c:1217 pepigen.c:1217
+msgid ""
+"\n"
+"There is a first thunk, but the section containing it could not be found\n"
+msgstr ""
+
+#: peigen.c:1357 pepigen.c:1357
+msgid ""
+"\n"
+"There is an export table, but the section containing it could not be found\n"
+msgstr ""
+
+#: peigen.c:1362 pepigen.c:1362
+#, c-format
+msgid ""
+"\n"
+"There is an export table in %s at 0x%lx\n"
+msgstr ""
+"\n"
+"%s Öеĵ¼³ö±íλÓÚ 0x%lx\n"
+
+#: peigen.c:1393 pepigen.c:1393
+#, c-format
+msgid ""
+"\n"
+"The Export Tables (interpreted %s section contents)\n"
+"\n"
+msgstr ""
+
+#: peigen.c:1397 pepigen.c:1397
+#, c-format
+msgid "Export Flags \t\t\t%lx\n"
+msgstr "µ¼³ö±êÖ¾ \t\t\t%lx\n"
+
+#: peigen.c:1400 pepigen.c:1400
+#, c-format
+msgid "Time/Date stamp \t\t%lx\n"
+msgstr "ÈÕÆÚ/ʱ¼ä´Á \t\t%lx\n"
+
+#: peigen.c:1403 pepigen.c:1403
+#, c-format
+msgid "Major/Minor \t\t\t%d/%d\n"
+msgstr ""
+
+#: peigen.c:1406 pepigen.c:1406
+msgid "Name \t\t\t\t"
+msgstr "Ãû³Æ \t\t\t\t"
+
+#: peigen.c:1412 pepigen.c:1412
+#, c-format
+msgid "Ordinal Base \t\t\t%ld\n"
+msgstr ""
+
+#: peigen.c:1415 pepigen.c:1415
+msgid "Number in:\n"
+msgstr ""
+
+#: peigen.c:1418 pepigen.c:1418
+#, c-format
+msgid "\tExport Address Table \t\t%08lx\n"
+msgstr ""
+
+#: peigen.c:1422 pepigen.c:1422
+#, c-format
+msgid "\t[Name Pointer/Ordinal] Table\t%08lx\n"
+msgstr ""
+
+#: peigen.c:1425 pepigen.c:1425
+msgid "Table Addresses\n"
+msgstr "±íµØÖ·\n"
+
+#: peigen.c:1428 pepigen.c:1428
+msgid "\tExport Address Table \t\t"
+msgstr "\tµ¼³öµØÖ·±í \t\t"
+
+#: peigen.c:1433 pepigen.c:1433
+msgid "\tName Pointer Table \t\t"
+msgstr "\tÃû³ÆÖ¸Õë±í \t\t"
+
+#: peigen.c:1438 pepigen.c:1438
+msgid "\tOrdinal Table \t\t\t"
+msgstr ""
+
+#: peigen.c:1453 pepigen.c:1453
+#, c-format
+msgid ""
+"\n"
+"Export Address Table -- Ordinal Base %ld\n"
+msgstr ""
+
+#: peigen.c:1472 pepigen.c:1472
+msgid "Forwarder RVA"
+msgstr ""
+
+#: peigen.c:1483 pepigen.c:1483
+msgid "Export RVA"
+msgstr "µ¼³ö RVA"
+
+#: peigen.c:1490 pepigen.c:1490
+msgid ""
+"\n"
+"[Ordinal/Name Pointer] Table\n"
+msgstr ""
+
+#: peigen.c:1545 pepigen.c:1545
+#, c-format
+msgid "Warning, .pdata section size (%ld) is not a multiple of %d\n"
+msgstr ""
+
+#: peigen.c:1549 pepigen.c:1549
+msgid ""
+"\n"
+"The Function Table (interpreted .pdata section contents)\n"
+msgstr ""
+
+#: peigen.c:1552 pepigen.c:1552
+msgid " vma:\t\t\tBegin Address    End Address      Unwind Info\n"
+msgstr ""
+
+#: peigen.c:1554 pepigen.c:1554
+msgid ""
+" vma:\t\tBegin    End      EH       EH       PrologEnd  Exception\n"
+"     \t\tAddress  Address  Handler  Data     Address    Mask\n"
+msgstr ""
+
+#: peigen.c:1624 pepigen.c:1624
+msgid " Register save millicode"
+msgstr ""
+
+#: peigen.c:1627 pepigen.c:1627
+msgid " Register restore millicode"
+msgstr ""
+
+#: peigen.c:1630 pepigen.c:1630
+msgid " Glue code sequence"
+msgstr ""
+
+#: peigen.c:1682 pepigen.c:1682
+msgid ""
+"\n"
+"\n"
+"PE File Base Relocations (interpreted .reloc section contents)\n"
+msgstr ""
+
+#: peigen.c:1712 pepigen.c:1712
+#, c-format
+msgid ""
+"\n"
+"Virtual Address: %08lx Chunk size %ld (0x%lx) Number of fixups %ld\n"
+msgstr ""
+
+#: peigen.c:1725 pepigen.c:1725
+#, c-format
+msgid "\treloc %4d offset %4x [%4lx] %s"
+msgstr ""
+
+#. The MS dumpbin program reportedly ands with 0xff0f before
+#. printing the characteristics field.  Not sure why.  No reason to
+#. emulate it here.
+#: peigen.c:1765 pepigen.c:1765
+#, c-format
+msgid ""
+"\n"
+"Characteristics 0x%x\n"
+msgstr ""
diff --git a/bfd/xtensa-isa.c b/bfd/xtensa-isa.c
new file mode 100644 (file)
index 0000000..ffbef53
--- /dev/null
@@ -0,0 +1,593 @@
+/* Configurable Xtensa ISA support.
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   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.
+
+   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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include "xtensa-isa.h"
+#include "xtensa-isa-internal.h"
+
+xtensa_isa xtensa_default_isa = NULL;
+
+static int
+opname_lookup_compare (const void *v1, const void *v2)
+{
+  opname_lookup_entry *e1 = (opname_lookup_entry *)v1;
+  opname_lookup_entry *e2 = (opname_lookup_entry *)v2;
+
+  return strcmp (e1->key, e2->key);
+}
+
+
+xtensa_isa
+xtensa_isa_init (void)
+{
+  xtensa_isa isa;
+  int mod;
+
+  isa = xtensa_load_isa (0);
+  if (isa == 0)
+    {
+      fprintf (stderr, "Failed to initialize Xtensa base ISA module\n");
+      return NULL;
+    }
+
+  for (mod = 1; xtensa_isa_modules[mod].get_num_opcodes_fn; mod++)
+    {
+      if (!xtensa_extend_isa (isa, mod))
+       {
+         fprintf (stderr, "Failed to initialize Xtensa TIE ISA module\n");
+         return NULL;
+       }
+    }
+
+  return isa;
+}
+
+/* ISA information.  */
+
+static int
+xtensa_check_isa_config (xtensa_isa_internal *isa,
+                        struct config_struct *config_table)
+{
+  int i, j;
+
+  if (!config_table)
+    {
+      fprintf (stderr, "Error: Empty configuration table in ISA DLL\n");
+      return 0;
+    }
+
+  /* For the first module, save a pointer to the table and record the
+     specified endianness and availability of the density option.  */
+
+  if (isa->num_modules == 0)
+    {
+      int found_memory_order = 0;
+
+      isa->config = config_table;
+      isa->has_density = 1;  /* Default to have density option.  */
+
+      for (i = 0; config_table[i].param_name; i++)
+       {
+         if (!strcmp (config_table[i].param_name, "IsaMemoryOrder"))
+           {
+             isa->is_big_endian =
+               (strcmp (config_table[i].param_value, "BigEndian") == 0);
+             found_memory_order = 1;
+           }
+         if (!strcmp (config_table[i].param_name, "IsaUseDensityInstruction"))
+           {
+             isa->has_density = atoi (config_table[i].param_value);
+           }
+       }
+      if (!found_memory_order)
+       {
+         fprintf (stderr, "Error: \"IsaMemoryOrder\" missing from "
+                  "configuration table in ISA DLL\n");
+         return 0;
+       }
+
+      return 1;
+    }
+
+  /* For subsequent modules, check that the parameters match.  Note: This
+     code is sufficient to handle the current model where there are never
+     more than 2 modules; we might at some point want to handle cases where
+     module N > 0 specifies some parameters not included in the base table,
+     and we would then add those to isa->config so that subsequent modules
+     would check against them. */
+
+  for (i = 0; config_table[i].param_name; i++)
+    {
+      for (j = 0; isa->config[j].param_name; j++)
+       {
+         if (!strcmp (config_table[i].param_name, isa->config[j].param_name))
+           {
+             int mismatch;
+             if (!strcmp (config_table[i].param_name, "IsaCoprocessorCount"))
+               {
+                 /* Only require the coprocessor count to be <= the base.  */
+                 int tiecnt = atoi (config_table[i].param_value);
+                 int basecnt = atoi (isa->config[j].param_value);
+                 mismatch = (tiecnt > basecnt);
+               }
+             else
+               mismatch = strcmp (config_table[i].param_value,
+                                  isa->config[j].param_value);
+             if (mismatch)
+               {
+#define MISMATCH_MESSAGE \
+"Error: Configuration mismatch in the \"%s\" parameter:\n\
+the configuration used when the TIE file was compiled had a value of\n\
+\"%s\", while the current configuration has a value of\n\
+\"%s\". Please rerun the TIE compiler with a matching\n\
+configuration.\n"
+                 fprintf (stderr, MISMATCH_MESSAGE,
+                          config_table[i].param_name,
+                          config_table[i].param_value,
+                          isa->config[j].param_value);
+                 return 0;
+               }
+             break;
+           }
+       }
+    }
+
+  return 1;
+}
+
+
+static int
+xtensa_add_isa (xtensa_isa_internal *isa, libisa_module_specifier libisa)
+{
+  const int (*get_num_opcodes_fn) (void);
+  struct config_struct *(*get_config_table_fn) (void);
+  xtensa_opcode_internal **(*get_opcodes_fn) (void);
+  int (*decode_insn_fn) (const xtensa_insnbuf);
+  xtensa_opcode_internal **opcodes;
+  int opc, insn_size, prev_num_opcodes, new_num_opcodes, this_module;
+
+  get_num_opcodes_fn = xtensa_isa_modules[libisa].get_num_opcodes_fn;
+  get_opcodes_fn = xtensa_isa_modules[libisa].get_opcodes_fn;
+  decode_insn_fn = xtensa_isa_modules[libisa].decode_insn_fn;
+  get_config_table_fn = xtensa_isa_modules[libisa].get_config_table_fn;
+
+  if (!get_num_opcodes_fn || !get_opcodes_fn || !decode_insn_fn
+      || (!get_config_table_fn && isa->num_modules == 0))
+    return 0;
+
+  if (get_config_table_fn
+      && !xtensa_check_isa_config (isa, get_config_table_fn ()))
+    return 0;
+
+  prev_num_opcodes = isa->num_opcodes;
+  new_num_opcodes = (*get_num_opcodes_fn) ();
+
+  isa->num_opcodes += new_num_opcodes;
+  isa->opcode_table = (xtensa_opcode_internal **)
+    realloc (isa->opcode_table, isa->num_opcodes *
+            sizeof (xtensa_opcode_internal *));
+  isa->opname_lookup_table = (opname_lookup_entry *)
+    realloc (isa->opname_lookup_table, isa->num_opcodes *
+            sizeof (opname_lookup_entry));
+
+  opcodes = (*get_opcodes_fn) ();
+
+  insn_size = isa->insn_size;
+  for (opc = 0; opc < new_num_opcodes; opc++)
+    {
+      xtensa_opcode_internal *intopc = opcodes[opc];
+      int newopc = prev_num_opcodes + opc;
+      isa->opcode_table[newopc] = intopc;
+      isa->opname_lookup_table[newopc].key = intopc->name;
+      isa->opname_lookup_table[newopc].opcode = newopc;
+      if (intopc->length > insn_size)
+       insn_size = intopc->length;
+    }
+
+  isa->insn_size = insn_size;
+  isa->insnbuf_size = ((isa->insn_size + sizeof (xtensa_insnbuf_word) - 1) /
+                      sizeof (xtensa_insnbuf_word));
+
+  qsort (isa->opname_lookup_table, isa->num_opcodes,
+        sizeof (opname_lookup_entry), opname_lookup_compare);
+
+  /* Check for duplicate opcode names.  */
+  for (opc = 1; opc < isa->num_opcodes; opc++)
+    {
+      if (!opname_lookup_compare (&isa->opname_lookup_table[opc-1],
+                                 &isa->opname_lookup_table[opc]))
+       {
+         fprintf (stderr, "Error: Duplicate TIE opcode \"%s\"\n",
+                  isa->opname_lookup_table[opc].key);
+         return 0;
+       }
+    }
+
+  this_module = isa->num_modules;
+  isa->num_modules += 1;
+
+  isa->module_opcode_base = (int *) realloc (isa->module_opcode_base,
+                                            isa->num_modules * sizeof (int));
+  isa->module_decode_fn = (xtensa_insn_decode_fn *)
+    realloc (isa->module_decode_fn, isa->num_modules *
+            sizeof (xtensa_insn_decode_fn));
+
+  isa->module_opcode_base[this_module] = prev_num_opcodes;
+  isa->module_decode_fn[this_module] = decode_insn_fn;
+
+  xtensa_default_isa = isa;
+
+  return 1;    /* Library was successfully added.  */
+}
+
+
+xtensa_isa
+xtensa_load_isa (libisa_module_specifier libisa)
+{
+  xtensa_isa_internal *isa;
+
+  isa = (xtensa_isa_internal *) malloc (sizeof (xtensa_isa_internal));
+  memset (isa, 0, sizeof (xtensa_isa_internal));
+  if (!xtensa_add_isa (isa, libisa))
+    {
+      xtensa_isa_free (isa);
+      return NULL;
+    }
+  return (xtensa_isa) isa;
+}
+
+
+int
+xtensa_extend_isa (xtensa_isa isa, libisa_module_specifier libisa)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  return xtensa_add_isa (intisa, libisa);
+}
+
+
+void
+xtensa_isa_free (xtensa_isa isa)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  if (intisa->opcode_table)
+    free (intisa->opcode_table);
+  if (intisa->opname_lookup_table)
+    free (intisa->opname_lookup_table);
+  if (intisa->module_opcode_base)
+    free (intisa->module_opcode_base);
+  if (intisa->module_decode_fn)
+    free (intisa->module_decode_fn);
+  free (intisa);
+}
+
+
+int
+xtensa_insn_maxlength (xtensa_isa isa)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  return intisa->insn_size;
+}
+
+
+int
+xtensa_insnbuf_size (xtensa_isa isa)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
+  return intisa->insnbuf_size;
+}
+
+
+int
+xtensa_num_opcodes (xtensa_isa isa)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  return intisa->num_opcodes;
+}
+
+
+xtensa_opcode
+xtensa_opcode_lookup (xtensa_isa isa, const char *opname)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  opname_lookup_entry entry, *result;
+
+  entry.key = opname;
+  result = bsearch (&entry, intisa->opname_lookup_table, intisa->num_opcodes,
+                   sizeof (opname_lookup_entry), opname_lookup_compare);
+  if (!result) return XTENSA_UNDEFINED;
+  return result->opcode;
+}
+
+
+xtensa_opcode
+xtensa_decode_insn (xtensa_isa isa, const xtensa_insnbuf insn)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  int n, opc;
+  for (n = 0; n < intisa->num_modules; n++) {
+    opc = (intisa->module_decode_fn[n]) (insn);
+    if (opc != XTENSA_UNDEFINED)
+      return intisa->module_opcode_base[n] + opc;
+  }
+  return XTENSA_UNDEFINED;
+}
+
+
+/* Opcode information.  */
+
+void
+xtensa_encode_insn (xtensa_isa isa, xtensa_opcode opc, xtensa_insnbuf insn)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  xtensa_insnbuf template = intisa->opcode_table[opc]->template();
+  int len = intisa->opcode_table[opc]->length;
+  int n;
+
+  /* Convert length to 32-bit words.  */
+  len = (len + 3) / 4;
+
+  /* Copy the template.  */
+  for (n = 0; n < len; n++)
+    insn[n] = template[n];
+
+  /* Fill any unused buffer space with zeros.  */
+  for ( ; n < intisa->insnbuf_size; n++)
+    insn[n] = 0;
+}
+
+
+const char *
+xtensa_opcode_name (xtensa_isa isa, xtensa_opcode opc)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  return intisa->opcode_table[opc]->name;
+}
+
+
+int
+xtensa_insn_length (xtensa_isa isa, xtensa_opcode opc)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  return intisa->opcode_table[opc]->length;
+}
+
+
+int
+xtensa_insn_length_from_first_byte (xtensa_isa isa, char first_byte)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  int is_density = (first_byte & (intisa->is_big_endian ? 0x80 : 0x08)) != 0;
+  return (intisa->has_density && is_density ? 2 : 3);
+}
+
+
+int
+xtensa_num_operands (xtensa_isa isa, xtensa_opcode opc)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  return intisa->opcode_table[opc]->iclass->num_operands;
+}
+
+
+xtensa_operand
+xtensa_get_operand (xtensa_isa isa, xtensa_opcode opc, int opnd)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  xtensa_iclass_internal *iclass = intisa->opcode_table[opc]->iclass;
+  if (opnd >= iclass->num_operands)
+    return NULL;
+  return (xtensa_operand) iclass->operands[opnd];
+}
+
+
+/* Operand information.  */
+
+char *
+xtensa_operand_kind (xtensa_operand opnd)
+{
+  xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
+  return intop->operand_kind;
+}
+
+
+char
+xtensa_operand_inout (xtensa_operand opnd)
+{
+  xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
+  return intop->inout;
+}
+
+
+uint32
+xtensa_operand_get_field (xtensa_operand opnd, const xtensa_insnbuf insn)
+{
+  xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
+  return (*intop->get_field) (insn);
+}
+
+
+void
+xtensa_operand_set_field (xtensa_operand opnd, xtensa_insnbuf insn, uint32 val)
+{
+  xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
+  return (*intop->set_field) (insn, val);
+}
+
+
+xtensa_encode_result
+xtensa_operand_encode (xtensa_operand opnd, uint32 *valp)
+{
+  xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
+  return (*intop->encode) (valp);
+}
+
+
+uint32
+xtensa_operand_decode (xtensa_operand opnd, uint32 val)
+{
+  xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
+  return (*intop->decode) (val);
+}
+
+
+int
+xtensa_operand_isPCRelative (xtensa_operand opnd)
+{
+  xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
+  return intop->isPCRelative;
+}
+
+
+uint32
+xtensa_operand_do_reloc (xtensa_operand opnd, uint32 addr, uint32 pc)
+{
+  xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
+  if (!intop->isPCRelative)
+    return addr;
+  return (*intop->do_reloc) (addr, pc);
+}
+
+
+uint32
+xtensa_operand_undo_reloc (xtensa_operand opnd, uint32 offset, uint32 pc)
+{
+  xtensa_operand_internal *intop = (xtensa_operand_internal *) opnd;
+  if (!intop->isPCRelative)
+    return offset;
+  return (*intop->undo_reloc) (offset, pc);
+}
+
+
+/* Instruction buffers.  */
+
+xtensa_insnbuf
+xtensa_insnbuf_alloc (xtensa_isa isa)
+{
+  return (xtensa_insnbuf) malloc (xtensa_insnbuf_size (isa) *
+                                 sizeof (xtensa_insnbuf_word));
+}
+
+
+void
+xtensa_insnbuf_free (xtensa_insnbuf buf)
+{
+  free( buf );
+}
+
+
+/* Given <byte_index>, the index of a byte in a xtensa_insnbuf, our
+   internal representation of a xtensa instruction word, return the index of
+   its word and the bit index of its low order byte in the xtensa_insnbuf.  */
+
+static inline int
+byte_to_word_index (int byte_index)
+{
+  return byte_index / sizeof (xtensa_insnbuf_word);
+}
+
+
+static inline int
+byte_to_bit_index (int byte_index)
+{
+  return (byte_index & 0x3) * 8;
+}
+
+
+/* Copy an instruction in the 32 bit words pointed at by <insn> to characters
+   pointed at by <cp>.  This is more complicated than you might think because
+   we want 16 bit instructions in bytes 2,3 for big endian. This function
+   allows us to specify which byte in <insn> to start with and which way to
+   increment, allowing trivial implementation for both big and little endian.
+   And it seems to make pretty good code for both.  */
+
+void
+xtensa_insnbuf_to_chars (xtensa_isa isa, const xtensa_insnbuf insn, char *cp)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  int insn_size = xtensa_insn_maxlength (intisa);
+  int fence_post, start, increment, i, byte_count;
+  xtensa_opcode opc;
+
+  if (intisa->is_big_endian)
+    {
+      start = insn_size - 1;
+      increment = -1;
+    }
+  else
+    {
+      start = 0;
+      increment = 1;
+    }
+
+  /* Find the opcode; do nothing if the buffer does not contain a valid
+     instruction since we need to know how many bytes to copy.  */
+  opc = xtensa_decode_insn (isa, insn);
+  if (opc == XTENSA_UNDEFINED)
+    return;
+
+  byte_count = xtensa_insn_length (isa, opc);
+  fence_post = start + (byte_count * increment);
+
+  for (i = start; i != fence_post; i += increment, ++cp)
+    {
+      int word_inx = byte_to_word_index (i);
+      int bit_inx = byte_to_bit_index (i);
+
+      *cp = (insn[word_inx] >> bit_inx) & 0xff;
+    }
+}
+
+/* Inward conversion from byte stream to xtensa_insnbuf.  See
+   xtensa_insnbuf_to_chars for a discussion of why this is
+   complicated by endianness.  */
+    
+void
+xtensa_insnbuf_from_chars (xtensa_isa isa, xtensa_insnbuf insn, const char* cp)
+{
+  xtensa_isa_internal *intisa = (xtensa_isa_internal *) isa;
+  int insn_size = xtensa_insn_maxlength (intisa);
+  int fence_post, start, increment, i;
+
+  if (intisa->is_big_endian)
+    {
+      start = insn_size - 1;
+      increment = -1;
+    }
+  else
+    {
+      start = 0;
+      increment = 1;
+    }
+
+  fence_post = start + (insn_size * increment);
+  memset (insn, 0, xtensa_insnbuf_size (isa) * sizeof (xtensa_insnbuf_word));
+
+  for ( i = start; i != fence_post; i += increment, ++cp )
+    {
+      int word_inx = byte_to_word_index (i);
+      int bit_inx = byte_to_bit_index (i);
+
+      insn[word_inx] |= (*cp & 0xff) << bit_inx;
+    }
+}
+
diff --git a/bfd/xtensa-modules.c b/bfd/xtensa-modules.c
new file mode 100644 (file)
index 0000000..d023b52
--- /dev/null
@@ -0,0 +1,6088 @@
+/* Xtensa configuration-specific ISA information.
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   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.
+
+   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 <xtensa-isa.h>
+#include "xtensa-isa-internal.h"
+#include "ansidecl.h"
+
+#define BPW 32
+#define WINDEX(_n) ((_n) / BPW)
+#define BINDEX(_n) ((_n) %% BPW)
+
+static uint32 tie_do_reloc_l (uint32, uint32) ATTRIBUTE_UNUSED;
+static uint32 tie_undo_reloc_l (uint32, uint32) ATTRIBUTE_UNUSED;
+
+static uint32
+tie_do_reloc_l (uint32 addr, uint32 pc)
+{
+  return (addr - pc);
+}
+
+static uint32
+tie_undo_reloc_l (uint32 offset, uint32 pc)
+{
+  return (pc + offset);
+}
+
+xtensa_opcode_internal** get_opcodes (void);
+const int get_num_opcodes (void);
+int decode_insn (const xtensa_insnbuf);
+int interface_version (void);
+
+uint32 get_bbi_field (const xtensa_insnbuf);
+void set_bbi_field (xtensa_insnbuf, uint32);
+uint32 get_bbi4_field (const xtensa_insnbuf);
+void set_bbi4_field (xtensa_insnbuf, uint32);
+uint32 get_i_field (const xtensa_insnbuf);
+void set_i_field (xtensa_insnbuf, uint32);
+uint32 get_imm12_field (const xtensa_insnbuf);
+void set_imm12_field (xtensa_insnbuf, uint32);
+uint32 get_imm12b_field (const xtensa_insnbuf);
+void set_imm12b_field (xtensa_insnbuf, uint32);
+uint32 get_imm16_field (const xtensa_insnbuf);
+void set_imm16_field (xtensa_insnbuf, uint32);
+uint32 get_imm4_field (const xtensa_insnbuf);
+void set_imm4_field (xtensa_insnbuf, uint32);
+uint32 get_imm6_field (const xtensa_insnbuf);
+void set_imm6_field (xtensa_insnbuf, uint32);
+uint32 get_imm6hi_field (const xtensa_insnbuf);
+void set_imm6hi_field (xtensa_insnbuf, uint32);
+uint32 get_imm6lo_field (const xtensa_insnbuf);
+void set_imm6lo_field (xtensa_insnbuf, uint32);
+uint32 get_imm7_field (const xtensa_insnbuf);
+void set_imm7_field (xtensa_insnbuf, uint32);
+uint32 get_imm7hi_field (const xtensa_insnbuf);
+void set_imm7hi_field (xtensa_insnbuf, uint32);
+uint32 get_imm7lo_field (const xtensa_insnbuf);
+void set_imm7lo_field (xtensa_insnbuf, uint32);
+uint32 get_imm8_field (const xtensa_insnbuf);
+void set_imm8_field (xtensa_insnbuf, uint32);
+uint32 get_m_field (const xtensa_insnbuf);
+void set_m_field (xtensa_insnbuf, uint32);
+uint32 get_mn_field (const xtensa_insnbuf);
+void set_mn_field (xtensa_insnbuf, uint32);
+uint32 get_n_field (const xtensa_insnbuf);
+void set_n_field (xtensa_insnbuf, uint32);
+uint32 get_none_field (const xtensa_insnbuf);
+void set_none_field (xtensa_insnbuf, uint32);
+uint32 get_offset_field (const xtensa_insnbuf);
+void set_offset_field (xtensa_insnbuf, uint32);
+uint32 get_op0_field (const xtensa_insnbuf);
+void set_op0_field (xtensa_insnbuf, uint32);
+uint32 get_op1_field (const xtensa_insnbuf);
+void set_op1_field (xtensa_insnbuf, uint32);
+uint32 get_op2_field (const xtensa_insnbuf);
+void set_op2_field (xtensa_insnbuf, uint32);
+uint32 get_r_field (const xtensa_insnbuf);
+void set_r_field (xtensa_insnbuf, uint32);
+uint32 get_s_field (const xtensa_insnbuf);
+void set_s_field (xtensa_insnbuf, uint32);
+uint32 get_sa4_field (const xtensa_insnbuf);
+void set_sa4_field (xtensa_insnbuf, uint32);
+uint32 get_sae_field (const xtensa_insnbuf);
+void set_sae_field (xtensa_insnbuf, uint32);
+uint32 get_sae4_field (const xtensa_insnbuf);
+void set_sae4_field (xtensa_insnbuf, uint32);
+uint32 get_sal_field (const xtensa_insnbuf);
+void set_sal_field (xtensa_insnbuf, uint32);
+uint32 get_sar_field (const xtensa_insnbuf);
+void set_sar_field (xtensa_insnbuf, uint32);
+uint32 get_sas_field (const xtensa_insnbuf);
+void set_sas_field (xtensa_insnbuf, uint32);
+uint32 get_sas4_field (const xtensa_insnbuf);
+void set_sas4_field (xtensa_insnbuf, uint32);
+uint32 get_sr_field (const xtensa_insnbuf);
+void set_sr_field (xtensa_insnbuf, uint32);
+uint32 get_t_field (const xtensa_insnbuf);
+void set_t_field (xtensa_insnbuf, uint32);
+uint32 get_thi3_field (const xtensa_insnbuf);
+void set_thi3_field (xtensa_insnbuf, uint32);
+uint32 get_z_field (const xtensa_insnbuf);
+void set_z_field (xtensa_insnbuf, uint32);
+
+
+uint32
+get_bbi_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf0000) >> 16) |
+         ((insn[0] & 0x100) >> 4);
+}
+
+void
+set_bbi_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfff0ffff) | ((val << 16) & 0xf0000);
+  insn[0] = (insn[0] & 0xfffffeff) | ((val << 4) & 0x100);
+}
+
+uint32
+get_bbi4_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x100) >> 8);
+}
+
+void
+set_bbi4_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffffeff) | ((val << 8) & 0x100);
+}
+
+uint32
+get_i_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x80000) >> 19);
+}
+
+void
+set_i_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfff7ffff) | ((val << 19) & 0x80000);
+}
+
+uint32
+get_imm12_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xfff));
+}
+
+void
+set_imm12_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffff000) | (val & 0xfff);
+}
+
+uint32
+get_imm12b_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xff)) |
+         ((insn[0] & 0xf000) >> 4);
+}
+
+void
+set_imm12b_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xffffff00) | (val & 0xff);
+  insn[0] = (insn[0] & 0xffff0fff) | ((val << 4) & 0xf000);
+}
+
+uint32
+get_imm16_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xffff));
+}
+
+void
+set_imm16_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xffff0000) | (val & 0xffff);
+}
+
+uint32
+get_imm4_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf00) >> 8);
+}
+
+void
+set_imm4_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffff0ff) | ((val << 8) & 0xf00);
+}
+
+uint32
+get_imm6_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf00) >> 8) |
+         ((insn[0] & 0x30000) >> 12);
+}
+
+void
+set_imm6_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffff0ff) | ((val << 8) & 0xf00);
+  insn[0] = (insn[0] & 0xfffcffff) | ((val << 12) & 0x30000);
+}
+
+uint32
+get_imm6hi_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x30000) >> 16);
+}
+
+void
+set_imm6hi_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffcffff) | ((val << 16) & 0x30000);
+}
+
+uint32
+get_imm6lo_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf00) >> 8);
+}
+
+void
+set_imm6lo_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffff0ff) | ((val << 8) & 0xf00);
+}
+
+uint32
+get_imm7_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf00) >> 8) |
+         ((insn[0] & 0x70000) >> 12);
+}
+
+void
+set_imm7_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffff0ff) | ((val << 8) & 0xf00);
+  insn[0] = (insn[0] & 0xfff8ffff) | ((val << 12) & 0x70000);
+}
+
+uint32
+get_imm7hi_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x70000) >> 16);
+}
+
+void
+set_imm7hi_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfff8ffff) | ((val << 16) & 0x70000);
+}
+
+uint32
+get_imm7lo_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf00) >> 8);
+}
+
+void
+set_imm7lo_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffff0ff) | ((val << 8) & 0xf00);
+}
+
+uint32
+get_imm8_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xff));
+}
+
+void
+set_imm8_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xffffff00) | (val & 0xff);
+}
+
+uint32
+get_m_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x30000) >> 16);
+}
+
+void
+set_m_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffcffff) | ((val << 16) & 0x30000);
+}
+
+uint32
+get_mn_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x30000) >> 16) |
+         ((insn[0] & 0xc0000) >> 16);
+}
+
+void
+set_mn_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffcffff) | ((val << 16) & 0x30000);
+  insn[0] = (insn[0] & 0xfff3ffff) | ((val << 16) & 0xc0000);
+}
+
+uint32
+get_n_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xc0000) >> 18);
+}
+
+void
+set_n_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfff3ffff) | ((val << 18) & 0xc0000);
+}
+
+uint32
+get_none_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x0));
+}
+
+void
+set_none_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xffffffff) | (val & 0x0);
+}
+
+uint32
+get_offset_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x3ffff));
+}
+
+void
+set_offset_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffc0000) | (val & 0x3ffff);
+}
+
+uint32
+get_op0_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf00000) >> 20);
+}
+
+void
+set_op0_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xff0fffff) | ((val << 20) & 0xf00000);
+}
+
+uint32
+get_op1_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf0) >> 4);
+}
+
+void
+set_op1_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xffffff0f) | ((val << 4) & 0xf0);
+}
+
+uint32
+get_op2_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf));
+}
+
+void
+set_op2_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffffff0) | (val & 0xf);
+}
+
+uint32
+get_r_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf00) >> 8);
+}
+
+void
+set_r_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffff0ff) | ((val << 8) & 0xf00);
+}
+
+uint32
+get_s_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf000) >> 12);
+}
+
+void
+set_s_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xffff0fff) | ((val << 12) & 0xf000);
+}
+
+uint32
+get_sa4_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x1));
+}
+
+void
+set_sa4_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffffffe) | (val & 0x1);
+}
+
+uint32
+get_sae_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf000) >> 12) |
+         ((insn[0] & 0x10));
+}
+
+void
+set_sae_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xffff0fff) | ((val << 12) & 0xf000);
+  insn[0] = (insn[0] & 0xffffffef) | (val & 0x10);
+}
+
+uint32
+get_sae4_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x10) >> 4);
+}
+
+void
+set_sae4_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xffffffef) | ((val << 4) & 0x10);
+}
+
+uint32
+get_sal_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf0000) >> 16) |
+         ((insn[0] & 0x1) << 4);
+}
+
+void
+set_sal_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfff0ffff) | ((val << 16) & 0xf0000);
+  insn[0] = (insn[0] & 0xfffffffe) | ((val >> 4) & 0x1);
+}
+
+uint32
+get_sar_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf000) >> 12) |
+         ((insn[0] & 0x1) << 4);
+}
+
+void
+set_sar_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xffff0fff) | ((val << 12) & 0xf000);
+  insn[0] = (insn[0] & 0xfffffffe) | ((val >> 4) & 0x1);
+}
+
+uint32
+get_sas_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf000) >> 12) |
+         ((insn[0] & 0x10000) >> 12);
+}
+
+void
+set_sas_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xffff0fff) | ((val << 12) & 0xf000);
+  insn[0] = (insn[0] & 0xfffeffff) | ((val << 12) & 0x10000);
+}
+
+uint32
+get_sas4_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x10000) >> 16);
+}
+
+void
+set_sas4_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffeffff) | ((val << 16) & 0x10000);
+}
+
+uint32
+get_sr_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf00) >> 8) |
+         ((insn[0] & 0xf000) >> 8);
+}
+
+void
+set_sr_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffff0ff) | ((val << 8) & 0xf00);
+  insn[0] = (insn[0] & 0xffff0fff) | ((val << 8) & 0xf000);
+}
+
+uint32
+get_t_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xf0000) >> 16);
+}
+
+void
+set_t_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfff0ffff) | ((val << 16) & 0xf0000);
+}
+
+uint32
+get_thi3_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0xe0000) >> 17);
+}
+
+void
+set_thi3_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfff1ffff) | ((val << 17) & 0xe0000);
+}
+
+uint32
+get_z_field (const xtensa_insnbuf insn)
+{
+  return ((insn[0] & 0x40000) >> 18);
+}
+
+void
+set_z_field (xtensa_insnbuf insn, uint32 val)
+{
+  insn[0] = (insn[0] & 0xfffbffff) | ((val << 18) & 0x40000);
+}
+
+uint32 decode_b4constu (uint32);
+xtensa_encode_result encode_b4constu (uint32 *);
+uint32 decode_simm8x256 (uint32);
+xtensa_encode_result encode_simm8x256 (uint32 *);
+uint32 decode_soffset (uint32);
+xtensa_encode_result encode_soffset (uint32 *);
+uint32 decode_imm4 (uint32);
+xtensa_encode_result encode_imm4 (uint32 *);
+uint32 decode_op0 (uint32);
+xtensa_encode_result encode_op0 (uint32 *);
+uint32 decode_op1 (uint32);
+xtensa_encode_result encode_op1 (uint32 *);
+uint32 decode_imm6 (uint32);
+xtensa_encode_result encode_imm6 (uint32 *);
+uint32 decode_op2 (uint32);
+xtensa_encode_result encode_op2 (uint32 *);
+uint32 decode_imm7 (uint32);
+xtensa_encode_result encode_imm7 (uint32 *);
+uint32 decode_simm4 (uint32);
+xtensa_encode_result encode_simm4 (uint32 *);
+uint32 decode_ai4const (uint32);
+xtensa_encode_result encode_ai4const (uint32 *);
+uint32 decode_imm8 (uint32);
+xtensa_encode_result encode_imm8 (uint32 *);
+uint32 decode_sae (uint32);
+xtensa_encode_result encode_sae (uint32 *);
+uint32 decode_imm7lo (uint32);
+xtensa_encode_result encode_imm7lo (uint32 *);
+uint32 decode_simm7 (uint32);
+xtensa_encode_result encode_simm7 (uint32 *);
+uint32 decode_simm8 (uint32);
+xtensa_encode_result encode_simm8 (uint32 *);
+uint32 decode_uimm12x8 (uint32);
+xtensa_encode_result encode_uimm12x8 (uint32 *);
+uint32 decode_sal (uint32);
+xtensa_encode_result encode_sal (uint32 *);
+uint32 decode_uimm6 (uint32);
+xtensa_encode_result encode_uimm6 (uint32 *);
+uint32 decode_sas4 (uint32);
+xtensa_encode_result encode_sas4 (uint32 *);
+uint32 decode_uimm8 (uint32);
+xtensa_encode_result encode_uimm8 (uint32 *);
+uint32 decode_uimm16x4 (uint32);
+xtensa_encode_result encode_uimm16x4 (uint32 *);
+uint32 decode_sar (uint32);
+xtensa_encode_result encode_sar (uint32 *);
+uint32 decode_sa4 (uint32);
+xtensa_encode_result encode_sa4 (uint32 *);
+uint32 decode_sas (uint32);
+xtensa_encode_result encode_sas (uint32 *);
+uint32 decode_imm6hi (uint32);
+xtensa_encode_result encode_imm6hi (uint32 *);
+uint32 decode_bbi (uint32);
+xtensa_encode_result encode_bbi (uint32 *);
+uint32 decode_uimm8x2 (uint32);
+xtensa_encode_result encode_uimm8x2 (uint32 *);
+uint32 decode_uimm8x4 (uint32);
+xtensa_encode_result encode_uimm8x4 (uint32 *);
+uint32 decode_msalp32 (uint32);
+xtensa_encode_result encode_msalp32 (uint32 *);
+uint32 decode_bbi4 (uint32);
+xtensa_encode_result encode_bbi4 (uint32 *);
+uint32 decode_op2p1 (uint32);
+xtensa_encode_result encode_op2p1 (uint32 *);
+uint32 decode_soffsetx4 (uint32);
+xtensa_encode_result encode_soffsetx4 (uint32 *);
+uint32 decode_imm6lo (uint32);
+xtensa_encode_result encode_imm6lo (uint32 *);
+uint32 decode_imm12 (uint32);
+xtensa_encode_result encode_imm12 (uint32 *);
+uint32 decode_b4const (uint32);
+xtensa_encode_result encode_b4const (uint32 *);
+uint32 decode_i (uint32);
+xtensa_encode_result encode_i (uint32 *);
+uint32 decode_imm16 (uint32);
+xtensa_encode_result encode_imm16 (uint32 *);
+uint32 decode_mn (uint32);
+xtensa_encode_result encode_mn (uint32 *);
+uint32 decode_m (uint32);
+xtensa_encode_result encode_m (uint32 *);
+uint32 decode_n (uint32);
+xtensa_encode_result encode_n (uint32 *);
+uint32 decode_none (uint32);
+xtensa_encode_result encode_none (uint32 *);
+uint32 decode_imm12b (uint32);
+xtensa_encode_result encode_imm12b (uint32 *);
+uint32 decode_r (uint32);
+xtensa_encode_result encode_r (uint32 *);
+uint32 decode_s (uint32);
+xtensa_encode_result encode_s (uint32 *);
+uint32 decode_t (uint32);
+xtensa_encode_result encode_t (uint32 *);
+uint32 decode_thi3 (uint32);
+xtensa_encode_result encode_thi3 (uint32 *);
+uint32 decode_sae4 (uint32);
+xtensa_encode_result encode_sae4 (uint32 *);
+uint32 decode_offset (uint32);
+xtensa_encode_result encode_offset (uint32 *);
+uint32 decode_imm7hi (uint32);
+xtensa_encode_result encode_imm7hi (uint32 *);
+uint32 decode_uimm4x16 (uint32);
+xtensa_encode_result encode_uimm4x16 (uint32 *);
+uint32 decode_simm12b (uint32);
+xtensa_encode_result encode_simm12b (uint32 *);
+uint32 decode_lsi4x4 (uint32);
+xtensa_encode_result encode_lsi4x4 (uint32 *);
+uint32 decode_z (uint32);
+xtensa_encode_result encode_z (uint32 *);
+uint32 decode_simm12 (uint32);
+xtensa_encode_result encode_simm12 (uint32 *);
+uint32 decode_sr (uint32);
+xtensa_encode_result encode_sr (uint32 *);
+uint32 decode_nimm4x2 (uint32);
+xtensa_encode_result encode_nimm4x2 (uint32 *);
+
+
+static const uint32 b4constu_table[] = {
+  32768,
+  65536,
+  2,
+  3,
+  4,
+  5,
+  6,
+  7,
+  8,
+  10,
+  12,
+  16,
+  32,
+  64,
+  128,
+  256
+};
+
+uint32
+decode_b4constu (uint32 val)
+{
+  val = b4constu_table[val];
+  return val;
+}
+
+xtensa_encode_result
+encode_b4constu (uint32 *valp)
+{
+  uint32 val = *valp;
+  unsigned i;
+  for (i = 0; i < (1 << 4); i += 1)
+    if (b4constu_table[i] == val) goto found;
+  return xtensa_encode_result_not_in_table;
+ found:
+  val = i;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_simm8x256 (uint32 val)
+{
+  val = (val ^ 0x80) - 0x80;
+  val <<= 8;
+  return val;
+}
+
+xtensa_encode_result
+encode_simm8x256 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val & ((1 << 8) - 1)) != 0)
+    return xtensa_encode_result_align;
+  val = (signed int) val >> 8;
+  if (((val + (1 << 7)) >> 8) != 0)
+    {
+      if ((signed int) val > 0)
+        return xtensa_encode_result_too_high;
+      else
+        return xtensa_encode_result_too_low;
+    }
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_soffset (uint32 val)
+{
+  val = (val ^ 0x20000) - 0x20000;
+  return val;
+}
+
+xtensa_encode_result
+encode_soffset (uint32 *valp)
+{
+  uint32 val = *valp;
+  if (((val + (1 << 17)) >> 18) != 0)
+    {
+      if ((signed int) val > 0)
+        return xtensa_encode_result_too_high;
+      else
+        return xtensa_encode_result_too_low;
+    }
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_imm4 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_imm4 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_op0 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_op0 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_op1 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_op1 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_imm6 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_imm6 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 6) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_op2 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_op2 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_imm7 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_imm7 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 7) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_simm4 (uint32 val)
+{
+  val = (val ^ 0x8) - 0x8;
+  return val;
+}
+
+xtensa_encode_result
+encode_simm4 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if (((val + (1 << 3)) >> 4) != 0)
+    {
+      if ((signed int) val > 0)
+        return xtensa_encode_result_too_high;
+      else
+        return xtensa_encode_result_too_low;
+    }
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+static const uint32 ai4const_table[] = {
+  -1,
+  1,
+  2,
+  3,
+  4,
+  5,
+  6,
+  7,
+  8,
+  9,
+  10,
+  11,
+  12,
+  13,
+  14,
+  15
+};
+
+uint32
+decode_ai4const (uint32 val)
+{
+  val = ai4const_table[val];
+  return val;
+}
+
+xtensa_encode_result
+encode_ai4const (uint32 *valp)
+{
+  uint32 val = *valp;
+  unsigned i;
+  for (i = 0; i < (1 << 4); i += 1)
+    if (ai4const_table[i] == val) goto found;
+  return xtensa_encode_result_not_in_table;
+ found:
+  val = i;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_imm8 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_imm8 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 8) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_sae (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_sae (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 5) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_imm7lo (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_imm7lo (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_simm7 (uint32 val)
+{
+  if (val > 95)
+      val |= -32;
+  return val;
+}
+
+xtensa_encode_result
+encode_simm7 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((signed int) val < -32)
+    return xtensa_encode_result_too_low;
+  if ((signed int) val > 95)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_simm8 (uint32 val)
+{
+  val = (val ^ 0x80) - 0x80;
+  return val;
+}
+
+xtensa_encode_result
+encode_simm8 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if (((val + (1 << 7)) >> 8) != 0)
+    {
+      if ((signed int) val > 0)
+        return xtensa_encode_result_too_high;
+      else
+        return xtensa_encode_result_too_low;
+    }
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_uimm12x8 (uint32 val)
+{
+  val <<= 3;
+  return val;
+}
+
+xtensa_encode_result
+encode_uimm12x8 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val & ((1 << 3) - 1)) != 0)
+    return xtensa_encode_result_align;
+  val = (signed int) val >> 3;
+  if ((val >> 12) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_sal (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_sal (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 5) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_uimm6 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_uimm6 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 6) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_sas4 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_sas4 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 1) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_uimm8 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_uimm8 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 8) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_uimm16x4 (uint32 val)
+{
+  val |= -1 << 16;
+  val <<= 2;
+  return val;
+}
+
+xtensa_encode_result
+encode_uimm16x4 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val & ((1 << 2) - 1)) != 0)
+    return xtensa_encode_result_align;
+  val = (signed int) val >> 2;
+  if ((signed int) val >> 16 != -1)
+    {
+      if ((signed int) val >= 0)
+        return xtensa_encode_result_too_high;
+      else
+        return xtensa_encode_result_too_low;
+    }
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_sar (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_sar (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 5) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_sa4 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_sa4 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 1) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_sas (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_sas (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 5) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_imm6hi (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_imm6hi (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 2) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_bbi (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_bbi (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 5) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_uimm8x2 (uint32 val)
+{
+  val <<= 1;
+  return val;
+}
+
+xtensa_encode_result
+encode_uimm8x2 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val & ((1 << 1) - 1)) != 0)
+    return xtensa_encode_result_align;
+  val = (signed int) val >> 1;
+  if ((val >> 8) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_uimm8x4 (uint32 val)
+{
+  val <<= 2;
+  return val;
+}
+
+xtensa_encode_result
+encode_uimm8x4 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val & ((1 << 2) - 1)) != 0)
+    return xtensa_encode_result_align;
+  val = (signed int) val >> 2;
+  if ((val >> 8) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+static const uint32 mip32const_table[] = {
+  32,
+  31,
+  30,
+  29,
+  28,
+  27,
+  26,
+  25,
+  24,
+  23,
+  22,
+  21,
+  20,
+  19,
+  18,
+  17,
+  16,
+  15,
+  14,
+  13,
+  12,
+  11,
+  10,
+  9,
+  8,
+  7,
+  6,
+  5,
+  4,
+  3,
+  2,
+  1
+};
+
+uint32
+decode_msalp32 (uint32 val)
+{
+  val = mip32const_table[val];
+  return val;
+}
+
+xtensa_encode_result
+encode_msalp32 (uint32 *valp)
+{
+  uint32 val = *valp;
+  unsigned i;
+  for (i = 0; i < (1 << 5); i += 1)
+    if (mip32const_table[i] == val) goto found;
+  return xtensa_encode_result_not_in_table;
+ found:
+  val = i;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_bbi4 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_bbi4 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 1) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+static const uint32 i4p1const_table[] = {
+  1,
+  2,
+  3,
+  4,
+  5,
+  6,
+  7,
+  8,
+  9,
+  10,
+  11,
+  12,
+  13,
+  14,
+  15,
+  16
+};
+
+uint32
+decode_op2p1 (uint32 val)
+{
+  val = i4p1const_table[val];
+  return val;
+}
+
+xtensa_encode_result
+encode_op2p1 (uint32 *valp)
+{
+  uint32 val = *valp;
+  unsigned i;
+  for (i = 0; i < (1 << 4); i += 1)
+    if (i4p1const_table[i] == val) goto found;
+  return xtensa_encode_result_not_in_table;
+ found:
+  val = i;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_soffsetx4 (uint32 val)
+{
+  val = (val ^ 0x20000) - 0x20000;
+  val <<= 2;
+  return val;
+}
+
+xtensa_encode_result
+encode_soffsetx4 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val & ((1 << 2) - 1)) != 0)
+    return xtensa_encode_result_align;
+  val = (signed int) val >> 2;
+  if (((val + (1 << 17)) >> 18) != 0)
+    {
+      if ((signed int) val > 0)
+        return xtensa_encode_result_too_high;
+      else
+        return xtensa_encode_result_too_low;
+    }
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_imm6lo (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_imm6lo (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_imm12 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_imm12 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 12) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+static const uint32 b4const_table[] = {
+  -1,
+  1,
+  2,
+  3,
+  4,
+  5,
+  6,
+  7,
+  8,
+  10,
+  12,
+  16,
+  32,
+  64,
+  128,
+  256
+};
+
+uint32
+decode_b4const (uint32 val)
+{
+  val = b4const_table[val];
+  return val;
+}
+
+xtensa_encode_result
+encode_b4const (uint32 *valp)
+{
+  uint32 val = *valp;
+  unsigned i;
+  for (i = 0; i < (1 << 4); i += 1)
+    if (b4const_table[i] == val) goto found;
+  return xtensa_encode_result_not_in_table;
+ found:
+  val = i;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_i (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_i (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 1) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_imm16 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_imm16 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 16) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_mn (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_mn (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_m (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_m (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 2) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_n (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_n (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 2) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_none (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_none (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 0) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_imm12b (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_imm12b (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 12) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_r (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_r (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_s (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_s (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_t (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_t (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_thi3 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_thi3 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 3) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_sae4 (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_sae4 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 1) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_offset (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_offset (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 18) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_imm7hi (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_imm7hi (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 3) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_uimm4x16 (uint32 val)
+{
+  val <<= 4;
+  return val;
+}
+
+xtensa_encode_result
+encode_uimm4x16 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val & ((1 << 4) - 1)) != 0)
+    return xtensa_encode_result_align;
+  val = (signed int) val >> 4;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_simm12b (uint32 val)
+{
+  val = (val ^ 0x800) - 0x800;
+  return val;
+}
+
+xtensa_encode_result
+encode_simm12b (uint32 *valp)
+{
+  uint32 val = *valp;
+  if (((val + (1 << 11)) >> 12) != 0)
+    {
+      if ((signed int) val > 0)
+        return xtensa_encode_result_too_high;
+      else
+        return xtensa_encode_result_too_low;
+    }
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_lsi4x4 (uint32 val)
+{
+  val <<= 2;
+  return val;
+}
+
+xtensa_encode_result
+encode_lsi4x4 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val & ((1 << 2) - 1)) != 0)
+    return xtensa_encode_result_align;
+  val = (signed int) val >> 2;
+  if ((val >> 4) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_z (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_z (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 1) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_simm12 (uint32 val)
+{
+  val = (val ^ 0x800) - 0x800;
+  return val;
+}
+
+xtensa_encode_result
+encode_simm12 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if (((val + (1 << 11)) >> 12) != 0)
+    {
+      if ((signed int) val > 0)
+        return xtensa_encode_result_too_high;
+      else
+        return xtensa_encode_result_too_low;
+    }
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_sr (uint32 val)
+{
+  return val;
+}
+
+xtensa_encode_result
+encode_sr (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val >> 8) != 0)
+    return xtensa_encode_result_too_high;
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+uint32
+decode_nimm4x2 (uint32 val)
+{
+  val |= -1 << 4;
+  val <<= 2;
+  return val;
+}
+
+xtensa_encode_result
+encode_nimm4x2 (uint32 *valp)
+{
+  uint32 val = *valp;
+  if ((val & ((1 << 2) - 1)) != 0)
+    return xtensa_encode_result_align;
+  val = (signed int) val >> 2;
+  if ((signed int) val >> 4 != -1)
+    {
+      if ((signed int) val >= 0)
+        return xtensa_encode_result_too_high;
+      else
+        return xtensa_encode_result_too_low;
+    }
+  *valp = val;
+  return xtensa_encode_result_ok;
+}
+
+
+
+uint32 do_reloc_l (uint32, uint32);
+uint32 undo_reloc_l (uint32, uint32);
+uint32 do_reloc_L (uint32, uint32);
+uint32 undo_reloc_L (uint32, uint32);
+uint32 do_reloc_r (uint32, uint32);
+uint32 undo_reloc_r (uint32, uint32);
+
+
+uint32
+do_reloc_l (uint32 addr, uint32 pc)
+{
+  return addr - pc - 4;
+}
+
+uint32
+undo_reloc_l (uint32 offset, uint32 pc)
+{
+  return pc + offset + 4;
+}
+
+uint32
+do_reloc_L (uint32 addr, uint32 pc)
+{
+  return addr - (pc & -4) - 4;
+}
+
+uint32
+undo_reloc_L (uint32 offset, uint32 pc)
+{
+  return (pc & -4) + offset + 4;
+}
+
+uint32
+do_reloc_r (uint32 addr, uint32 pc)
+{
+  return addr - ((pc+3) & -4);
+}
+
+uint32
+undo_reloc_r (uint32 offset, uint32 pc)
+{
+  return ((pc+3) & -4) + offset;
+}
+
+static xtensa_operand_internal iib4const_operand = {
+  "i",
+  '<',
+  0,
+  get_r_field,
+  set_r_field,
+  encode_b4const,
+  decode_b4const,
+  0,
+  0
+};
+
+static xtensa_operand_internal iiuimm8_operand = {
+  "i",
+  '<',
+  0,
+  get_imm8_field,
+  set_imm8_field,
+  encode_uimm8,
+  decode_uimm8,
+  0,
+  0
+};
+
+static xtensa_operand_internal lisoffsetx4_operand = {
+  "L",
+  '<',
+  1,
+  get_offset_field,
+  set_offset_field,
+  encode_soffsetx4,
+  decode_soffsetx4,
+  do_reloc_L,
+  undo_reloc_L,
+};
+
+static xtensa_operand_internal iisimm8x256_operand = {
+  "i",
+  '<',
+  0,
+  get_imm8_field,
+  set_imm8_field,
+  encode_simm8x256,
+  decode_simm8x256,
+  0,
+  0
+};
+
+static xtensa_operand_internal lisimm12_operand = {
+  "l",
+  '<',
+  1,
+  get_imm12_field,
+  set_imm12_field,
+  encode_simm12,
+  decode_simm12,
+  do_reloc_l,
+  undo_reloc_l,
+};
+
+static xtensa_operand_internal iiop2p1_operand = {
+  "i",
+  '<',
+  0,
+  get_op2_field,
+  set_op2_field,
+  encode_op2p1,
+  decode_op2p1,
+  0,
+  0
+};
+
+static xtensa_operand_internal iisae_operand = {
+  "i",
+  '<',
+  0,
+  get_sae_field,
+  set_sae_field,
+  encode_sae,
+  decode_sae,
+  0,
+  0
+};
+
+static xtensa_operand_internal iis_operand = {
+  "i",
+  '<',
+  0,
+  get_s_field,
+  set_s_field,
+  encode_s,
+  decode_s,
+  0,
+  0
+};
+
+static xtensa_operand_internal iit_operand = {
+  "i",
+  '<',
+  0,
+  get_t_field,
+  set_t_field,
+  encode_t,
+  decode_t,
+  0,
+  0
+};
+
+static xtensa_operand_internal iisimm12b_operand = {
+  "i",
+  '<',
+  0,
+  get_imm12b_field,
+  set_imm12b_field,
+  encode_simm12b,
+  decode_simm12b,
+  0,
+  0
+};
+
+static xtensa_operand_internal iinimm4x2_operand = {
+  "i",
+  '<',
+  0,
+  get_imm4_field,
+  set_imm4_field,
+  encode_nimm4x2,
+  decode_nimm4x2,
+  0,
+  0
+};
+
+static xtensa_operand_internal iiuimm4x16_operand = {
+  "i",
+  '<',
+  0,
+  get_op2_field,
+  set_op2_field,
+  encode_uimm4x16,
+  decode_uimm4x16,
+  0,
+  0
+};
+
+static xtensa_operand_internal abs_operand = {
+  "a",
+  '=',
+  0,
+  get_s_field,
+  set_s_field,
+  encode_s,
+  decode_s,
+  0,
+  0
+};
+
+static xtensa_operand_internal iisar_operand = {
+  "i",
+  '<',
+  0,
+  get_sar_field,
+  set_sar_field,
+  encode_sar,
+  decode_sar,
+  0,
+  0
+};
+
+static xtensa_operand_internal abt_operand = {
+  "a",
+  '=',
+  0,
+  get_t_field,
+  set_t_field,
+  encode_t,
+  decode_t,
+  0,
+  0
+};
+
+static xtensa_operand_internal iisas_operand = {
+  "i",
+  '<',
+  0,
+  get_sas_field,
+  set_sas_field,
+  encode_sas,
+  decode_sas,
+  0,
+  0
+};
+
+static xtensa_operand_internal amr_operand = {
+  "a",
+  '=',
+  0,
+  get_r_field,
+  set_r_field,
+  encode_r,
+  decode_r,
+  0,
+  0
+};
+
+static xtensa_operand_internal iib4constu_operand = {
+  "i",
+  '<',
+  0,
+  get_r_field,
+  set_r_field,
+  encode_b4constu,
+  decode_b4constu,
+  0,
+  0
+};
+
+static xtensa_operand_internal iisr_operand = {
+  "i",
+  '<',
+  0,
+  get_sr_field,
+  set_sr_field,
+  encode_sr,
+  decode_sr,
+  0,
+  0
+};
+
+static xtensa_operand_internal iibbi_operand = {
+  "i",
+  '<',
+  0,
+  get_bbi_field,
+  set_bbi_field,
+  encode_bbi,
+  decode_bbi,
+  0,
+  0
+};
+
+static xtensa_operand_internal iiai4const_operand = {
+  "i",
+  '<',
+  0,
+  get_t_field,
+  set_t_field,
+  encode_ai4const,
+  decode_ai4const,
+  0,
+  0
+};
+
+static xtensa_operand_internal iiuimm12x8_operand = {
+  "i",
+  '<',
+  0,
+  get_imm12_field,
+  set_imm12_field,
+  encode_uimm12x8,
+  decode_uimm12x8,
+  0,
+  0
+};
+
+static xtensa_operand_internal riuimm16x4_operand = {
+  "r",
+  '<',
+  1,
+  get_imm16_field,
+  set_imm16_field,
+  encode_uimm16x4,
+  decode_uimm16x4,
+  do_reloc_r,
+  undo_reloc_r,
+};
+
+static xtensa_operand_internal lisimm8_operand = {
+  "l",
+  '<',
+  1,
+  get_imm8_field,
+  set_imm8_field,
+  encode_simm8,
+  decode_simm8,
+  do_reloc_l,
+  undo_reloc_l,
+};
+
+static xtensa_operand_internal iilsi4x4_operand = {
+  "i",
+  '<',
+  0,
+  get_r_field,
+  set_r_field,
+  encode_lsi4x4,
+  decode_lsi4x4,
+  0,
+  0
+};
+
+static xtensa_operand_internal iiuimm8x2_operand = {
+  "i",
+  '<',
+  0,
+  get_imm8_field,
+  set_imm8_field,
+  encode_uimm8x2,
+  decode_uimm8x2,
+  0,
+  0
+};
+
+static xtensa_operand_internal iisimm4_operand = {
+  "i",
+  '<',
+  0,
+  get_mn_field,
+  set_mn_field,
+  encode_simm4,
+  decode_simm4,
+  0,
+  0
+};
+
+static xtensa_operand_internal iimsalp32_operand = {
+  "i",
+  '<',
+  0,
+  get_sal_field,
+  set_sal_field,
+  encode_msalp32,
+  decode_msalp32,
+  0,
+  0
+};
+
+static xtensa_operand_internal liuimm6_operand = {
+  "l",
+  '<',
+  1,
+  get_imm6_field,
+  set_imm6_field,
+  encode_uimm6,
+  decode_uimm6,
+  do_reloc_l,
+  undo_reloc_l,
+};
+
+static xtensa_operand_internal iiuimm8x4_operand = {
+  "i",
+  '<',
+  0,
+  get_imm8_field,
+  set_imm8_field,
+  encode_uimm8x4,
+  decode_uimm8x4,
+  0,
+  0
+};
+
+static xtensa_operand_internal lisoffset_operand = {
+  "l",
+  '<',
+  1,
+  get_offset_field,
+  set_offset_field,
+  encode_soffset,
+  decode_soffset,
+  do_reloc_l,
+  undo_reloc_l,
+};
+
+static xtensa_operand_internal iisimm7_operand = {
+  "i",
+  '<',
+  0,
+  get_imm7_field,
+  set_imm7_field,
+  encode_simm7,
+  decode_simm7,
+  0,
+  0
+};
+
+static xtensa_operand_internal ais_operand = {
+  "a",
+  '<',
+  0,
+  get_s_field,
+  set_s_field,
+  encode_s,
+  decode_s,
+  0,
+  0
+};
+
+static xtensa_operand_internal liuimm8_operand = {
+  "l",
+  '<',
+  1,
+  get_imm8_field,
+  set_imm8_field,
+  encode_uimm8,
+  decode_uimm8,
+  do_reloc_l,
+  undo_reloc_l,
+};
+
+static xtensa_operand_internal ait_operand = {
+  "a",
+  '<',
+  0,
+  get_t_field,
+  set_t_field,
+  encode_t,
+  decode_t,
+  0,
+  0
+};
+
+static xtensa_operand_internal iisimm8_operand = {
+  "i",
+  '<',
+  0,
+  get_imm8_field,
+  set_imm8_field,
+  encode_simm8,
+  decode_simm8,
+  0,
+  0
+};
+
+static xtensa_operand_internal aor_operand = {
+  "a",
+  '>',
+  0,
+  get_r_field,
+  set_r_field,
+  encode_r,
+  decode_r,
+  0,
+  0
+};
+
+static xtensa_operand_internal aos_operand = {
+  "a",
+  '>',
+  0,
+  get_s_field,
+  set_s_field,
+  encode_s,
+  decode_s,
+  0,
+  0
+};
+
+static xtensa_operand_internal aot_operand = {
+  "a",
+  '>',
+  0,
+  get_t_field,
+  set_t_field,
+  encode_t,
+  decode_t,
+  0,
+  0
+};
+
+static xtensa_iclass_internal nopn_iclass = {
+  0,
+  0
+};
+
+static xtensa_operand_internal *movi_operand_list[] = {
+  &aot_operand,
+  &iisimm12b_operand
+};
+
+static xtensa_iclass_internal movi_iclass = {
+  2,
+  &movi_operand_list[0]
+};
+
+static xtensa_operand_internal *bsi8u_operand_list[] = {
+  &ais_operand,
+  &iib4constu_operand,
+  &lisimm8_operand
+};
+
+static xtensa_iclass_internal bsi8u_iclass = {
+  3,
+  &bsi8u_operand_list[0]
+};
+
+static xtensa_operand_internal *itlb_operand_list[] = {
+  &ais_operand
+};
+
+static xtensa_iclass_internal itlb_iclass = {
+  1,
+  &itlb_operand_list[0]
+};
+
+static xtensa_operand_internal *shiftst_operand_list[] = {
+  &aor_operand,
+  &ais_operand,
+  &ait_operand
+};
+
+static xtensa_iclass_internal shiftst_iclass = {
+  3,
+  &shiftst_operand_list[0]
+};
+
+static xtensa_operand_internal *l32r_operand_list[] = {
+  &aot_operand,
+  &riuimm16x4_operand
+};
+
+static xtensa_iclass_internal l32r_iclass = {
+  2,
+  &l32r_operand_list[0]
+};
+
+static xtensa_iclass_internal rfe_iclass = {
+  0,
+  0
+};
+
+static xtensa_operand_internal *wait_operand_list[] = {
+  &iis_operand
+};
+
+static xtensa_iclass_internal wait_iclass = {
+  1,
+  &wait_operand_list[0]
+};
+
+static xtensa_operand_internal *rfi_operand_list[] = {
+  &iis_operand
+};
+
+static xtensa_iclass_internal rfi_iclass = {
+  1,
+  &rfi_operand_list[0]
+};
+
+static xtensa_operand_internal *movz_operand_list[] = {
+  &amr_operand,
+  &ais_operand,
+  &ait_operand
+};
+
+static xtensa_iclass_internal movz_iclass = {
+  3,
+  &movz_operand_list[0]
+};
+
+static xtensa_operand_internal *callx_operand_list[] = {
+  &ais_operand
+};
+
+static xtensa_iclass_internal callx_iclass = {
+  1,
+  &callx_operand_list[0]
+};
+
+static xtensa_operand_internal *mov_n_operand_list[] = {
+  &aot_operand,
+  &ais_operand
+};
+
+static xtensa_iclass_internal mov_n_iclass = {
+  2,
+  &mov_n_operand_list[0]
+};
+
+static xtensa_operand_internal *loadi4_operand_list[] = {
+  &aot_operand,
+  &ais_operand,
+  &iilsi4x4_operand
+};
+
+static xtensa_iclass_internal loadi4_iclass = {
+  3,
+  &loadi4_operand_list[0]
+};
+
+static xtensa_operand_internal *exti_operand_list[] = {
+  &aor_operand,
+  &ait_operand,
+  &iisae_operand,
+  &iiop2p1_operand
+};
+
+static xtensa_iclass_internal exti_iclass = {
+  4,
+  &exti_operand_list[0]
+};
+
+static xtensa_operand_internal *break_operand_list[] = {
+  &iis_operand,
+  &iit_operand
+};
+
+static xtensa_iclass_internal break_iclass = {
+  2,
+  &break_operand_list[0]
+};
+
+static xtensa_operand_internal *slli_operand_list[] = {
+  &aor_operand,
+  &ais_operand,
+  &iimsalp32_operand
+};
+
+static xtensa_iclass_internal slli_iclass = {
+  3,
+  &slli_operand_list[0]
+};
+
+static xtensa_operand_internal *s16i_operand_list[] = {
+  &ait_operand,
+  &ais_operand,
+  &iiuimm8x2_operand
+};
+
+static xtensa_iclass_internal s16i_iclass = {
+  3,
+  &s16i_operand_list[0]
+};
+
+static xtensa_operand_internal *call_operand_list[] = {
+  &lisoffsetx4_operand
+};
+
+static xtensa_iclass_internal call_iclass = {
+  1,
+  &call_operand_list[0]
+};
+
+static xtensa_operand_internal *shifts_operand_list[] = {
+  &aor_operand,
+  &ais_operand
+};
+
+static xtensa_iclass_internal shifts_iclass = {
+  2,
+  &shifts_operand_list[0]
+};
+
+static xtensa_operand_internal *shiftt_operand_list[] = {
+  &aor_operand,
+  &ait_operand
+};
+
+static xtensa_iclass_internal shiftt_iclass = {
+  2,
+  &shiftt_operand_list[0]
+};
+
+static xtensa_operand_internal *rotw_operand_list[] = {
+  &iisimm4_operand
+};
+
+static xtensa_iclass_internal rotw_iclass = {
+  1,
+  &rotw_operand_list[0]
+};
+
+static xtensa_operand_internal *addsub_operand_list[] = {
+  &aor_operand,
+  &ais_operand,
+  &ait_operand
+};
+
+static xtensa_iclass_internal addsub_iclass = {
+  3,
+  &addsub_operand_list[0]
+};
+
+static xtensa_operand_internal *l8i_operand_list[] = {
+  &aot_operand,
+  &ais_operand,
+  &iiuimm8_operand
+};
+
+static xtensa_iclass_internal l8i_iclass = {
+  3,
+  &l8i_operand_list[0]
+};
+
+static xtensa_operand_internal *sari_operand_list[] = {
+  &iisas_operand
+};
+
+static xtensa_iclass_internal sari_iclass = {
+  1,
+  &sari_operand_list[0]
+};
+
+static xtensa_operand_internal *xsr_operand_list[] = {
+  &abt_operand,
+  &iisr_operand
+};
+
+static xtensa_iclass_internal xsr_iclass = {
+  2,
+  &xsr_operand_list[0]
+};
+
+static xtensa_operand_internal *rsil_operand_list[] = {
+  &aot_operand,
+  &iis_operand
+};
+
+static xtensa_iclass_internal rsil_iclass = {
+  2,
+  &rsil_operand_list[0]
+};
+
+static xtensa_operand_internal *bst8_operand_list[] = {
+  &ais_operand,
+  &ait_operand,
+  &lisimm8_operand
+};
+
+static xtensa_iclass_internal bst8_iclass = {
+  3,
+  &bst8_operand_list[0]
+};
+
+static xtensa_operand_internal *addi_operand_list[] = {
+  &aot_operand,
+  &ais_operand,
+  &iisimm8_operand
+};
+
+static xtensa_iclass_internal addi_iclass = {
+  3,
+  &addi_operand_list[0]
+};
+
+static xtensa_operand_internal *callx12_operand_list[] = {
+  &ais_operand
+};
+
+static xtensa_iclass_internal callx12_iclass = {
+  1,
+  &callx12_operand_list[0]
+};
+
+static xtensa_operand_internal *bsi8_operand_list[] = {
+  &ais_operand,
+  &iib4const_operand,
+  &lisimm8_operand
+};
+
+static xtensa_iclass_internal bsi8_iclass = {
+  3,
+  &bsi8_operand_list[0]
+};
+
+static xtensa_operand_internal *jumpx_operand_list[] = {
+  &ais_operand
+};
+
+static xtensa_iclass_internal jumpx_iclass = {
+  1,
+  &jumpx_operand_list[0]
+};
+
+static xtensa_iclass_internal retn_iclass = {
+  0,
+  0
+};
+
+static xtensa_operand_internal *nsa_operand_list[] = {
+  &aot_operand,
+  &ais_operand
+};
+
+static xtensa_iclass_internal nsa_iclass = {
+  2,
+  &nsa_operand_list[0]
+};
+
+static xtensa_operand_internal *storei4_operand_list[] = {
+  &ait_operand,
+  &ais_operand,
+  &iilsi4x4_operand
+};
+
+static xtensa_iclass_internal storei4_iclass = {
+  3,
+  &storei4_operand_list[0]
+};
+
+static xtensa_operand_internal *wtlb_operand_list[] = {
+  &ait_operand,
+  &ais_operand
+};
+
+static xtensa_iclass_internal wtlb_iclass = {
+  2,
+  &wtlb_operand_list[0]
+};
+
+static xtensa_operand_internal *dce_operand_list[] = {
+  &ais_operand,
+  &iiuimm4x16_operand
+};
+
+static xtensa_iclass_internal dce_iclass = {
+  2,
+  &dce_operand_list[0]
+};
+
+static xtensa_operand_internal *l16i_operand_list[] = {
+  &aot_operand,
+  &ais_operand,
+  &iiuimm8x2_operand
+};
+
+static xtensa_iclass_internal l16i_iclass = {
+  3,
+  &l16i_operand_list[0]
+};
+
+static xtensa_operand_internal *callx4_operand_list[] = {
+  &ais_operand
+};
+
+static xtensa_iclass_internal callx4_iclass = {
+  1,
+  &callx4_operand_list[0]
+};
+
+static xtensa_operand_internal *callx8_operand_list[] = {
+  &ais_operand
+};
+
+static xtensa_iclass_internal callx8_iclass = {
+  1,
+  &callx8_operand_list[0]
+};
+
+static xtensa_operand_internal *movsp_operand_list[] = {
+  &aot_operand,
+  &ais_operand
+};
+
+static xtensa_iclass_internal movsp_iclass = {
+  2,
+  &movsp_operand_list[0]
+};
+
+static xtensa_operand_internal *wsr_operand_list[] = {
+  &ait_operand,
+  &iisr_operand
+};
+
+static xtensa_iclass_internal wsr_iclass = {
+  2,
+  &wsr_operand_list[0]
+};
+
+static xtensa_operand_internal *call12_operand_list[] = {
+  &lisoffsetx4_operand
+};
+
+static xtensa_iclass_internal call12_iclass = {
+  1,
+  &call12_operand_list[0]
+};
+
+static xtensa_operand_internal *call4_operand_list[] = {
+  &lisoffsetx4_operand
+};
+
+static xtensa_iclass_internal call4_iclass = {
+  1,
+  &call4_operand_list[0]
+};
+
+static xtensa_operand_internal *addmi_operand_list[] = {
+  &aot_operand,
+  &ais_operand,
+  &iisimm8x256_operand
+};
+
+static xtensa_iclass_internal addmi_iclass = {
+  3,
+  &addmi_operand_list[0]
+};
+
+static xtensa_operand_internal *bit_operand_list[] = {
+  &aor_operand,
+  &ais_operand,
+  &ait_operand
+};
+
+static xtensa_iclass_internal bit_iclass = {
+  3,
+  &bit_operand_list[0]
+};
+
+static xtensa_operand_internal *call8_operand_list[] = {
+  &lisoffsetx4_operand
+};
+
+static xtensa_iclass_internal call8_iclass = {
+  1,
+  &call8_operand_list[0]
+};
+
+static xtensa_iclass_internal itlba_iclass = {
+  0,
+  0
+};
+
+static xtensa_operand_internal *break_n_operand_list[] = {
+  &iis_operand
+};
+
+static xtensa_iclass_internal break_n_iclass = {
+  1,
+  &break_n_operand_list[0]
+};
+
+static xtensa_operand_internal *sar_operand_list[] = {
+  &ais_operand
+};
+
+static xtensa_iclass_internal sar_iclass = {
+  1,
+  &sar_operand_list[0]
+};
+
+static xtensa_operand_internal *s32e_operand_list[] = {
+  &ait_operand,
+  &ais_operand,
+  &iinimm4x2_operand
+};
+
+static xtensa_iclass_internal s32e_iclass = {
+  3,
+  &s32e_operand_list[0]
+};
+
+static xtensa_operand_internal *bz6_operand_list[] = {
+  &ais_operand,
+  &liuimm6_operand
+};
+
+static xtensa_iclass_internal bz6_iclass = {
+  2,
+  &bz6_operand_list[0]
+};
+
+static xtensa_operand_internal *loop_operand_list[] = {
+  &ais_operand,
+  &liuimm8_operand
+};
+
+static xtensa_iclass_internal loop_iclass = {
+  2,
+  &loop_operand_list[0]
+};
+
+static xtensa_operand_internal *rsr_operand_list[] = {
+  &aot_operand,
+  &iisr_operand
+};
+
+static xtensa_iclass_internal rsr_iclass = {
+  2,
+  &rsr_operand_list[0]
+};
+
+static xtensa_operand_internal *icache_operand_list[] = {
+  &ais_operand,
+  &iiuimm8x4_operand
+};
+
+static xtensa_iclass_internal icache_iclass = {
+  2,
+  &icache_operand_list[0]
+};
+
+static xtensa_operand_internal *s8i_operand_list[] = {
+  &ait_operand,
+  &ais_operand,
+  &iiuimm8_operand
+};
+
+static xtensa_iclass_internal s8i_iclass = {
+  3,
+  &s8i_operand_list[0]
+};
+
+static xtensa_iclass_internal return_iclass = {
+  0,
+  0
+};
+
+static xtensa_operand_internal *dcache_operand_list[] = {
+  &ais_operand,
+  &iiuimm8x4_operand
+};
+
+static xtensa_iclass_internal dcache_iclass = {
+  2,
+  &dcache_operand_list[0]
+};
+
+static xtensa_operand_internal *s32i_operand_list[] = {
+  &ait_operand,
+  &ais_operand,
+  &iiuimm8x4_operand
+};
+
+static xtensa_iclass_internal s32i_iclass = {
+  3,
+  &s32i_operand_list[0]
+};
+
+static xtensa_operand_internal *jump_operand_list[] = {
+  &lisoffset_operand
+};
+
+static xtensa_iclass_internal jump_iclass = {
+  1,
+  &jump_operand_list[0]
+};
+
+static xtensa_operand_internal *addi_n_operand_list[] = {
+  &aor_operand,
+  &ais_operand,
+  &iiai4const_operand
+};
+
+static xtensa_iclass_internal addi_n_iclass = {
+  3,
+  &addi_n_operand_list[0]
+};
+
+static xtensa_iclass_internal sync_iclass = {
+  0,
+  0
+};
+
+static xtensa_operand_internal *neg_operand_list[] = {
+  &aor_operand,
+  &ait_operand
+};
+
+static xtensa_iclass_internal neg_iclass = {
+  2,
+  &neg_operand_list[0]
+};
+
+static xtensa_iclass_internal syscall_iclass = {
+  0,
+  0
+};
+
+static xtensa_operand_internal *bsz12_operand_list[] = {
+  &ais_operand,
+  &lisimm12_operand
+};
+
+static xtensa_iclass_internal bsz12_iclass = {
+  2,
+  &bsz12_operand_list[0]
+};
+
+static xtensa_iclass_internal excw_iclass = {
+  0,
+  0
+};
+
+static xtensa_operand_internal *movi_n_operand_list[] = {
+  &aos_operand,
+  &iisimm7_operand
+};
+
+static xtensa_iclass_internal movi_n_iclass = {
+  2,
+  &movi_n_operand_list[0]
+};
+
+static xtensa_operand_internal *rtlb_operand_list[] = {
+  &aot_operand,
+  &ais_operand
+};
+
+static xtensa_iclass_internal rtlb_iclass = {
+  2,
+  &rtlb_operand_list[0]
+};
+
+static xtensa_operand_internal *actl_operand_list[] = {
+  &aot_operand,
+  &ais_operand
+};
+
+static xtensa_iclass_internal actl_iclass = {
+  2,
+  &actl_operand_list[0]
+};
+
+static xtensa_operand_internal *srli_operand_list[] = {
+  &aor_operand,
+  &ait_operand,
+  &iis_operand
+};
+
+static xtensa_iclass_internal srli_iclass = {
+  3,
+  &srli_operand_list[0]
+};
+
+static xtensa_operand_internal *bsi8b_operand_list[] = {
+  &ais_operand,
+  &iibbi_operand,
+  &lisimm8_operand
+};
+
+static xtensa_iclass_internal bsi8b_iclass = {
+  3,
+  &bsi8b_operand_list[0]
+};
+
+static xtensa_operand_internal *acts_operand_list[] = {
+  &ait_operand,
+  &ais_operand
+};
+
+static xtensa_iclass_internal acts_iclass = {
+  2,
+  &acts_operand_list[0]
+};
+
+static xtensa_operand_internal *add_n_operand_list[] = {
+  &aor_operand,
+  &ais_operand,
+  &ait_operand
+};
+
+static xtensa_iclass_internal add_n_iclass = {
+  3,
+  &add_n_operand_list[0]
+};
+
+static xtensa_operand_internal *srai_operand_list[] = {
+  &aor_operand,
+  &ait_operand,
+  &iisar_operand
+};
+
+static xtensa_iclass_internal srai_iclass = {
+  3,
+  &srai_operand_list[0]
+};
+
+static xtensa_operand_internal *entry_operand_list[] = {
+  &abs_operand,
+  &iiuimm12x8_operand
+};
+
+static xtensa_iclass_internal entry_iclass = {
+  2,
+  &entry_operand_list[0]
+};
+
+static xtensa_operand_internal *l32e_operand_list[] = {
+  &aot_operand,
+  &ais_operand,
+  &iinimm4x2_operand
+};
+
+static xtensa_iclass_internal l32e_iclass = {
+  3,
+  &l32e_operand_list[0]
+};
+
+static xtensa_operand_internal *dpf_operand_list[] = {
+  &ais_operand,
+  &iiuimm8x4_operand
+};
+
+static xtensa_iclass_internal dpf_iclass = {
+  2,
+  &dpf_operand_list[0]
+};
+
+static xtensa_operand_internal *l32i_operand_list[] = {
+  &aot_operand,
+  &ais_operand,
+  &iiuimm8x4_operand
+};
+
+static xtensa_iclass_internal l32i_iclass = {
+  3,
+  &l32i_operand_list[0]
+};
+
+static xtensa_insnbuf abs_template (void);
+static xtensa_insnbuf add_template (void);
+static xtensa_insnbuf add_n_template (void);
+static xtensa_insnbuf addi_template (void);
+static xtensa_insnbuf addi_n_template (void);
+static xtensa_insnbuf addmi_template (void);
+static xtensa_insnbuf addx2_template (void);
+static xtensa_insnbuf addx4_template (void);
+static xtensa_insnbuf addx8_template (void);
+static xtensa_insnbuf and_template (void);
+static xtensa_insnbuf ball_template (void);
+static xtensa_insnbuf bany_template (void);
+static xtensa_insnbuf bbc_template (void);
+static xtensa_insnbuf bbci_template (void);
+static xtensa_insnbuf bbs_template (void);
+static xtensa_insnbuf bbsi_template (void);
+static xtensa_insnbuf beq_template (void);
+static xtensa_insnbuf beqi_template (void);
+static xtensa_insnbuf beqz_template (void);
+static xtensa_insnbuf beqz_n_template (void);
+static xtensa_insnbuf bge_template (void);
+static xtensa_insnbuf bgei_template (void);
+static xtensa_insnbuf bgeu_template (void);
+static xtensa_insnbuf bgeui_template (void);
+static xtensa_insnbuf bgez_template (void);
+static xtensa_insnbuf blt_template (void);
+static xtensa_insnbuf blti_template (void);
+static xtensa_insnbuf bltu_template (void);
+static xtensa_insnbuf bltui_template (void);
+static xtensa_insnbuf bltz_template (void);
+static xtensa_insnbuf bnall_template (void);
+static xtensa_insnbuf bne_template (void);
+static xtensa_insnbuf bnei_template (void);
+static xtensa_insnbuf bnez_template (void);
+static xtensa_insnbuf bnez_n_template (void);
+static xtensa_insnbuf bnone_template (void);
+static xtensa_insnbuf break_template (void);
+static xtensa_insnbuf break_n_template (void);
+static xtensa_insnbuf call0_template (void);
+static xtensa_insnbuf call12_template (void);
+static xtensa_insnbuf call4_template (void);
+static xtensa_insnbuf call8_template (void);
+static xtensa_insnbuf callx0_template (void);
+static xtensa_insnbuf callx12_template (void);
+static xtensa_insnbuf callx4_template (void);
+static xtensa_insnbuf callx8_template (void);
+static xtensa_insnbuf dhi_template (void);
+static xtensa_insnbuf dhwb_template (void);
+static xtensa_insnbuf dhwbi_template (void);
+static xtensa_insnbuf dii_template (void);
+static xtensa_insnbuf diwb_template (void);
+static xtensa_insnbuf diwbi_template (void);
+static xtensa_insnbuf dpfr_template (void);
+static xtensa_insnbuf dpfro_template (void);
+static xtensa_insnbuf dpfw_template (void);
+static xtensa_insnbuf dpfwo_template (void);
+static xtensa_insnbuf dsync_template (void);
+static xtensa_insnbuf entry_template (void);
+static xtensa_insnbuf esync_template (void);
+static xtensa_insnbuf excw_template (void);
+static xtensa_insnbuf extui_template (void);
+static xtensa_insnbuf idtlb_template (void);
+static xtensa_insnbuf idtlba_template (void);
+static xtensa_insnbuf ihi_template (void);
+static xtensa_insnbuf iii_template (void);
+static xtensa_insnbuf iitlb_template (void);
+static xtensa_insnbuf iitlba_template (void);
+static xtensa_insnbuf ipf_template (void);
+static xtensa_insnbuf isync_template (void);
+static xtensa_insnbuf j_template (void);
+static xtensa_insnbuf jx_template (void);
+static xtensa_insnbuf l16si_template (void);
+static xtensa_insnbuf l16ui_template (void);
+static xtensa_insnbuf l32e_template (void);
+static xtensa_insnbuf l32i_template (void);
+static xtensa_insnbuf l32i_n_template (void);
+static xtensa_insnbuf l32r_template (void);
+static xtensa_insnbuf l8ui_template (void);
+static xtensa_insnbuf ldct_template (void);
+static xtensa_insnbuf lict_template (void);
+static xtensa_insnbuf licw_template (void);
+static xtensa_insnbuf loop_template (void);
+static xtensa_insnbuf loopgtz_template (void);
+static xtensa_insnbuf loopnez_template (void);
+static xtensa_insnbuf memw_template (void);
+static xtensa_insnbuf mov_n_template (void);
+static xtensa_insnbuf moveqz_template (void);
+static xtensa_insnbuf movgez_template (void);
+static xtensa_insnbuf movi_template (void);
+static xtensa_insnbuf movi_n_template (void);
+static xtensa_insnbuf movltz_template (void);
+static xtensa_insnbuf movnez_template (void);
+static xtensa_insnbuf movsp_template (void);
+static xtensa_insnbuf neg_template (void);
+static xtensa_insnbuf nop_n_template (void);
+static xtensa_insnbuf nsa_template (void);
+static xtensa_insnbuf nsau_template (void);
+static xtensa_insnbuf or_template (void);
+static xtensa_insnbuf pdtlb_template (void);
+static xtensa_insnbuf pitlb_template (void);
+static xtensa_insnbuf rdtlb0_template (void);
+static xtensa_insnbuf rdtlb1_template (void);
+static xtensa_insnbuf ret_template (void);
+static xtensa_insnbuf ret_n_template (void);
+static xtensa_insnbuf retw_template (void);
+static xtensa_insnbuf retw_n_template (void);
+static xtensa_insnbuf rfde_template (void);
+static xtensa_insnbuf rfe_template (void);
+static xtensa_insnbuf rfi_template (void);
+static xtensa_insnbuf rfwo_template (void);
+static xtensa_insnbuf rfwu_template (void);
+static xtensa_insnbuf ritlb0_template (void);
+static xtensa_insnbuf ritlb1_template (void);
+static xtensa_insnbuf rotw_template (void);
+static xtensa_insnbuf rsil_template (void);
+static xtensa_insnbuf rsr_template (void);
+static xtensa_insnbuf rsync_template (void);
+static xtensa_insnbuf s16i_template (void);
+static xtensa_insnbuf s32e_template (void);
+static xtensa_insnbuf s32i_template (void);
+static xtensa_insnbuf s32i_n_template (void);
+static xtensa_insnbuf s8i_template (void);
+static xtensa_insnbuf sdct_template (void);
+static xtensa_insnbuf sict_template (void);
+static xtensa_insnbuf sicw_template (void);
+static xtensa_insnbuf simcall_template (void);
+static xtensa_insnbuf sll_template (void);
+static xtensa_insnbuf slli_template (void);
+static xtensa_insnbuf sra_template (void);
+static xtensa_insnbuf srai_template (void);
+static xtensa_insnbuf src_template (void);
+static xtensa_insnbuf srl_template (void);
+static xtensa_insnbuf srli_template (void);
+static xtensa_insnbuf ssa8b_template (void);
+static xtensa_insnbuf ssa8l_template (void);
+static xtensa_insnbuf ssai_template (void);
+static xtensa_insnbuf ssl_template (void);
+static xtensa_insnbuf ssr_template (void);
+static xtensa_insnbuf sub_template (void);
+static xtensa_insnbuf subx2_template (void);
+static xtensa_insnbuf subx4_template (void);
+static xtensa_insnbuf subx8_template (void);
+static xtensa_insnbuf syscall_template (void);
+static xtensa_insnbuf waiti_template (void);
+static xtensa_insnbuf wdtlb_template (void);
+static xtensa_insnbuf witlb_template (void);
+static xtensa_insnbuf wsr_template (void);
+static xtensa_insnbuf xor_template (void);
+static xtensa_insnbuf xsr_template (void);
+
+static xtensa_insnbuf
+abs_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00001006 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+add_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000008 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+add_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00a00000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+addi_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00200c00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+addi_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00b00000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+addmi_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00200d00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+addx2_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000009 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+addx4_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000000a };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+addx8_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000000b };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+and_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000001 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ball_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700400 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bany_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700800 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bbc_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700500 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bbci_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700600 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bbs_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700d00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bbsi_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700e00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+beq_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700100 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+beqi_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00680000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+beqz_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00640000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+beqz_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00c80000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bge_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700a00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bgei_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x006b0000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bgeu_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700b00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bgeui_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x006f0000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bgez_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00670000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+blt_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700200 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+blti_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x006a0000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bltu_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700300 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bltui_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x006e0000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bltz_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00660000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bnall_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700c00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bne_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700900 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bnei_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00690000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bnez_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00650000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bnez_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00cc0000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+bnone_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00700000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+break_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000400 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+break_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00d20f00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+call0_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00500000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+call12_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x005c0000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+call4_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00540000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+call8_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00580000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+callx0_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00030000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+callx12_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x000f0000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+callx4_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00070000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+callx8_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x000b0000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+dhi_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00260700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+dhwb_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00240700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+dhwbi_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00250700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+dii_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00270700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+diwb_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00280740 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+diwbi_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00280750 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+dpfr_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00200700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+dpfro_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00220700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+dpfw_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00210700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+dpfwo_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00230700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+dsync_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00030200 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+entry_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x006c0000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+esync_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00020200 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+excw_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00080200 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+extui_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000040 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+idtlb_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000c05 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+idtlba_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000805 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ihi_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x002e0700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+iii_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x002f0700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+iitlb_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000405 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+iitlba_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000005 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ipf_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x002c0700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+isync_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000200 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+j_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00600000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+jx_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x000a0000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+l16si_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00200900 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+l16ui_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00200100 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+l32e_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000090 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+l32i_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00200200 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+l32i_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00800000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+l32r_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00100000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+l8ui_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00200000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ldct_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000081f };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+lict_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000001f };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+licw_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000021f };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+loop_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x006d0800 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+loopgtz_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x006d0a00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+loopnez_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x006d0900 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+memw_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x000c0200 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+mov_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00d00000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+moveqz_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000038 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+movgez_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000003b };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+movi_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00200a00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+movi_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00c00000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+movltz_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000003a };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+movnez_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000039 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+movsp_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000100 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+neg_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000006 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+nop_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00d30f00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+nsa_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000e04 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+nsau_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000f04 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+or_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000002 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+pdtlb_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000d05 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+pitlb_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000505 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+rdtlb0_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000b05 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+rdtlb1_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000f05 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ret_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00020000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ret_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00d00f00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+retw_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00060000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+retw_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00d10f00 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+rfde_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00002300 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+rfe_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000300 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+rfi_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00010300 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+rfwo_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00004300 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+rfwu_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00005300 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ritlb0_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000305 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ritlb1_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000705 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+rotw_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000804 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+rsil_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000600 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+rsr_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000030 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+rsync_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00010200 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+s16i_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00200500 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+s32e_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000094 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+s32i_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00200600 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+s32i_n_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00900000 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+s8i_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00200400 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+sdct_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000091f };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+sict_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000011f };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+sicw_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000031f };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+simcall_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00001500 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+sll_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000001a };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+slli_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000010 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+sra_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000001b };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+srai_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000012 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+src_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000018 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+srl_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000019 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+srli_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000014 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ssa8b_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000304 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ssa8l_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000204 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ssai_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000404 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ssl_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000104 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+ssr_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000004 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+sub_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000000c };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+subx2_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000000d };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+subx4_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000000e };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+subx8_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x0000000f };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+syscall_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000500 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+waiti_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000700 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+wdtlb_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000e05 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+witlb_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000605 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+wsr_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000031 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+xor_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000003 };
+  return &template[0];
+}
+
+static xtensa_insnbuf
+xsr_template (void)
+{
+  static xtensa_insnbuf_word template[] = { 0x00000016 };
+  return &template[0];
+}
+
+static xtensa_opcode_internal abs_opcode = {
+  "abs",
+  3,
+  abs_template,
+  &neg_iclass
+};
+
+static xtensa_opcode_internal add_opcode = {
+  "add",
+  3,
+  add_template,
+  &addsub_iclass
+};
+
+static xtensa_opcode_internal add_n_opcode = {
+  "add.n",
+  2,
+  add_n_template,
+  &add_n_iclass
+};
+
+static xtensa_opcode_internal addi_opcode = {
+  "addi",
+  3,
+  addi_template,
+  &addi_iclass
+};
+
+static xtensa_opcode_internal addi_n_opcode = {
+  "addi.n",
+  2,
+  addi_n_template,
+  &addi_n_iclass
+};
+
+static xtensa_opcode_internal addmi_opcode = {
+  "addmi",
+  3,
+  addmi_template,
+  &addmi_iclass
+};
+
+static xtensa_opcode_internal addx2_opcode = {
+  "addx2",
+  3,
+  addx2_template,
+  &addsub_iclass
+};
+
+static xtensa_opcode_internal addx4_opcode = {
+  "addx4",
+  3,
+  addx4_template,
+  &addsub_iclass
+};
+
+static xtensa_opcode_internal addx8_opcode = {
+  "addx8",
+  3,
+  addx8_template,
+  &addsub_iclass
+};
+
+static xtensa_opcode_internal and_opcode = {
+  "and",
+  3,
+  and_template,
+  &bit_iclass
+};
+
+static xtensa_opcode_internal ball_opcode = {
+  "ball",
+  3,
+  ball_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal bany_opcode = {
+  "bany",
+  3,
+  bany_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal bbc_opcode = {
+  "bbc",
+  3,
+  bbc_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal bbci_opcode = {
+  "bbci",
+  3,
+  bbci_template,
+  &bsi8b_iclass
+};
+
+static xtensa_opcode_internal bbs_opcode = {
+  "bbs",
+  3,
+  bbs_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal bbsi_opcode = {
+  "bbsi",
+  3,
+  bbsi_template,
+  &bsi8b_iclass
+};
+
+static xtensa_opcode_internal beq_opcode = {
+  "beq",
+  3,
+  beq_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal beqi_opcode = {
+  "beqi",
+  3,
+  beqi_template,
+  &bsi8_iclass
+};
+
+static xtensa_opcode_internal beqz_opcode = {
+  "beqz",
+  3,
+  beqz_template,
+  &bsz12_iclass
+};
+
+static xtensa_opcode_internal beqz_n_opcode = {
+  "beqz.n",
+  2,
+  beqz_n_template,
+  &bz6_iclass
+};
+
+static xtensa_opcode_internal bge_opcode = {
+  "bge",
+  3,
+  bge_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal bgei_opcode = {
+  "bgei",
+  3,
+  bgei_template,
+  &bsi8_iclass
+};
+
+static xtensa_opcode_internal bgeu_opcode = {
+  "bgeu",
+  3,
+  bgeu_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal bgeui_opcode = {
+  "bgeui",
+  3,
+  bgeui_template,
+  &bsi8u_iclass
+};
+
+static xtensa_opcode_internal bgez_opcode = {
+  "bgez",
+  3,
+  bgez_template,
+  &bsz12_iclass
+};
+
+static xtensa_opcode_internal blt_opcode = {
+  "blt",
+  3,
+  blt_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal blti_opcode = {
+  "blti",
+  3,
+  blti_template,
+  &bsi8_iclass
+};
+
+static xtensa_opcode_internal bltu_opcode = {
+  "bltu",
+  3,
+  bltu_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal bltui_opcode = {
+  "bltui",
+  3,
+  bltui_template,
+  &bsi8u_iclass
+};
+
+static xtensa_opcode_internal bltz_opcode = {
+  "bltz",
+  3,
+  bltz_template,
+  &bsz12_iclass
+};
+
+static xtensa_opcode_internal bnall_opcode = {
+  "bnall",
+  3,
+  bnall_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal bne_opcode = {
+  "bne",
+  3,
+  bne_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal bnei_opcode = {
+  "bnei",
+  3,
+  bnei_template,
+  &bsi8_iclass
+};
+
+static xtensa_opcode_internal bnez_opcode = {
+  "bnez",
+  3,
+  bnez_template,
+  &bsz12_iclass
+};
+
+static xtensa_opcode_internal bnez_n_opcode = {
+  "bnez.n",
+  2,
+  bnez_n_template,
+  &bz6_iclass
+};
+
+static xtensa_opcode_internal bnone_opcode = {
+  "bnone",
+  3,
+  bnone_template,
+  &bst8_iclass
+};
+
+static xtensa_opcode_internal break_opcode = {
+  "break",
+  3,
+  break_template,
+  &break_iclass
+};
+
+static xtensa_opcode_internal break_n_opcode = {
+  "break.n",
+  2,
+  break_n_template,
+  &break_n_iclass
+};
+
+static xtensa_opcode_internal call0_opcode = {
+  "call0",
+  3,
+  call0_template,
+  &call_iclass
+};
+
+static xtensa_opcode_internal call12_opcode = {
+  "call12",
+  3,
+  call12_template,
+  &call12_iclass
+};
+
+static xtensa_opcode_internal call4_opcode = {
+  "call4",
+  3,
+  call4_template,
+  &call4_iclass
+};
+
+static xtensa_opcode_internal call8_opcode = {
+  "call8",
+  3,
+  call8_template,
+  &call8_iclass
+};
+
+static xtensa_opcode_internal callx0_opcode = {
+  "callx0",
+  3,
+  callx0_template,
+  &callx_iclass
+};
+
+static xtensa_opcode_internal callx12_opcode = {
+  "callx12",
+  3,
+  callx12_template,
+  &callx12_iclass
+};
+
+static xtensa_opcode_internal callx4_opcode = {
+  "callx4",
+  3,
+  callx4_template,
+  &callx4_iclass
+};
+
+static xtensa_opcode_internal callx8_opcode = {
+  "callx8",
+  3,
+  callx8_template,
+  &callx8_iclass
+};
+
+static xtensa_opcode_internal dhi_opcode = {
+  "dhi",
+  3,
+  dhi_template,
+  &dcache_iclass
+};
+
+static xtensa_opcode_internal dhwb_opcode = {
+  "dhwb",
+  3,
+  dhwb_template,
+  &dcache_iclass
+};
+
+static xtensa_opcode_internal dhwbi_opcode = {
+  "dhwbi",
+  3,
+  dhwbi_template,
+  &dcache_iclass
+};
+
+static xtensa_opcode_internal dii_opcode = {
+  "dii",
+  3,
+  dii_template,
+  &dcache_iclass
+};
+
+static xtensa_opcode_internal diwb_opcode = {
+  "diwb",
+  3,
+  diwb_template,
+  &dce_iclass
+};
+
+static xtensa_opcode_internal diwbi_opcode = {
+  "diwbi",
+  3,
+  diwbi_template,
+  &dce_iclass
+};
+
+static xtensa_opcode_internal dpfr_opcode = {
+  "dpfr",
+  3,
+  dpfr_template,
+  &dpf_iclass
+};
+
+static xtensa_opcode_internal dpfro_opcode = {
+  "dpfro",
+  3,
+  dpfro_template,
+  &dpf_iclass
+};
+
+static xtensa_opcode_internal dpfw_opcode = {
+  "dpfw",
+  3,
+  dpfw_template,
+  &dpf_iclass
+};
+
+static xtensa_opcode_internal dpfwo_opcode = {
+  "dpfwo",
+  3,
+  dpfwo_template,
+  &dpf_iclass
+};
+
+static xtensa_opcode_internal dsync_opcode = {
+  "dsync",
+  3,
+  dsync_template,
+  &sync_iclass
+};
+
+static xtensa_opcode_internal entry_opcode = {
+  "entry",
+  3,
+  entry_template,
+  &entry_iclass
+};
+
+static xtensa_opcode_internal esync_opcode = {
+  "esync",
+  3,
+  esync_template,
+  &sync_iclass
+};
+
+static xtensa_opcode_internal excw_opcode = {
+  "excw",
+  3,
+  excw_template,
+  &excw_iclass
+};
+
+static xtensa_opcode_internal extui_opcode = {
+  "extui",
+  3,
+  extui_template,
+  &exti_iclass
+};
+
+static xtensa_opcode_internal idtlb_opcode = {
+  "idtlb",
+  3,
+  idtlb_template,
+  &itlb_iclass
+};
+
+static xtensa_opcode_internal idtlba_opcode = {
+  "idtlba",
+  3,
+  idtlba_template,
+  &itlba_iclass
+};
+
+static xtensa_opcode_internal ihi_opcode = {
+  "ihi",
+  3,
+  ihi_template,
+  &icache_iclass
+};
+
+static xtensa_opcode_internal iii_opcode = {
+  "iii",
+  3,
+  iii_template,
+  &icache_iclass
+};
+
+static xtensa_opcode_internal iitlb_opcode = {
+  "iitlb",
+  3,
+  iitlb_template,
+  &itlb_iclass
+};
+
+static xtensa_opcode_internal iitlba_opcode = {
+  "iitlba",
+  3,
+  iitlba_template,
+  &itlba_iclass
+};
+
+static xtensa_opcode_internal ipf_opcode = {
+  "ipf",
+  3,
+  ipf_template,
+  &icache_iclass
+};
+
+static xtensa_opcode_internal isync_opcode = {
+  "isync",
+  3,
+  isync_template,
+  &sync_iclass
+};
+
+static xtensa_opcode_internal j_opcode = {
+  "j",
+  3,
+  j_template,
+  &jump_iclass
+};
+
+static xtensa_opcode_internal jx_opcode = {
+  "jx",
+  3,
+  jx_template,
+  &jumpx_iclass
+};
+
+static xtensa_opcode_internal l16si_opcode = {
+  "l16si",
+  3,
+  l16si_template,
+  &l16i_iclass
+};
+
+static xtensa_opcode_internal l16ui_opcode = {
+  "l16ui",
+  3,
+  l16ui_template,
+  &l16i_iclass
+};
+
+static xtensa_opcode_internal l32e_opcode = {
+  "l32e",
+  3,
+  l32e_template,
+  &l32e_iclass
+};
+
+static xtensa_opcode_internal l32i_opcode = {
+  "l32i",
+  3,
+  l32i_template,
+  &l32i_iclass
+};
+
+static xtensa_opcode_internal l32i_n_opcode = {
+  "l32i.n",
+  2,
+  l32i_n_template,
+  &loadi4_iclass
+};
+
+static xtensa_opcode_internal l32r_opcode = {
+  "l32r",
+  3,
+  l32r_template,
+  &l32r_iclass
+};
+
+static xtensa_opcode_internal l8ui_opcode = {
+  "l8ui",
+  3,
+  l8ui_template,
+  &l8i_iclass
+};
+
+static xtensa_opcode_internal ldct_opcode = {
+  "ldct",
+  3,
+  ldct_template,
+  &actl_iclass
+};
+
+static xtensa_opcode_internal lict_opcode = {
+  "lict",
+  3,
+  lict_template,
+  &actl_iclass
+};
+
+static xtensa_opcode_internal licw_opcode = {
+  "licw",
+  3,
+  licw_template,
+  &actl_iclass
+};
+
+static xtensa_opcode_internal loop_opcode = {
+  "loop",
+  3,
+  loop_template,
+  &loop_iclass
+};
+
+static xtensa_opcode_internal loopgtz_opcode = {
+  "loopgtz",
+  3,
+  loopgtz_template,
+  &loop_iclass
+};
+
+static xtensa_opcode_internal loopnez_opcode = {
+  "loopnez",
+  3,
+  loopnez_template,
+  &loop_iclass
+};
+
+static xtensa_opcode_internal memw_opcode = {
+  "memw",
+  3,
+  memw_template,
+  &sync_iclass
+};
+
+static xtensa_opcode_internal mov_n_opcode = {
+  "mov.n",
+  2,
+  mov_n_template,
+  &mov_n_iclass
+};
+
+static xtensa_opcode_internal moveqz_opcode = {
+  "moveqz",
+  3,
+  moveqz_template,
+  &movz_iclass
+};
+
+static xtensa_opcode_internal movgez_opcode = {
+  "movgez",
+  3,
+  movgez_template,
+  &movz_iclass
+};
+
+static xtensa_opcode_internal movi_opcode = {
+  "movi",
+  3,
+  movi_template,
+  &movi_iclass
+};
+
+static xtensa_opcode_internal movi_n_opcode = {
+  "movi.n",
+  2,
+  movi_n_template,
+  &movi_n_iclass
+};
+
+static xtensa_opcode_internal movltz_opcode = {
+  "movltz",
+  3,
+  movltz_template,
+  &movz_iclass
+};
+
+static xtensa_opcode_internal movnez_opcode = {
+  "movnez",
+  3,
+  movnez_template,
+  &movz_iclass
+};
+
+static xtensa_opcode_internal movsp_opcode = {
+  "movsp",
+  3,
+  movsp_template,
+  &movsp_iclass
+};
+
+static xtensa_opcode_internal neg_opcode = {
+  "neg",
+  3,
+  neg_template,
+  &neg_iclass
+};
+
+static xtensa_opcode_internal nop_n_opcode = {
+  "nop.n",
+  2,
+  nop_n_template,
+  &nopn_iclass
+};
+
+static xtensa_opcode_internal nsa_opcode = {
+  "nsa",
+  3,
+  nsa_template,
+  &nsa_iclass
+};
+
+static xtensa_opcode_internal nsau_opcode = {
+  "nsau",
+  3,
+  nsau_template,
+  &nsa_iclass
+};
+
+static xtensa_opcode_internal or_opcode = {
+  "or",
+  3,
+  or_template,
+  &bit_iclass
+};
+
+static xtensa_opcode_internal pdtlb_opcode = {
+  "pdtlb",
+  3,
+  pdtlb_template,
+  &rtlb_iclass
+};
+
+static xtensa_opcode_internal pitlb_opcode = {
+  "pitlb",
+  3,
+  pitlb_template,
+  &rtlb_iclass
+};
+
+static xtensa_opcode_internal rdtlb0_opcode = {
+  "rdtlb0",
+  3,
+  rdtlb0_template,
+  &rtlb_iclass
+};
+
+static xtensa_opcode_internal rdtlb1_opcode = {
+  "rdtlb1",
+  3,
+  rdtlb1_template,
+  &rtlb_iclass
+};
+
+static xtensa_opcode_internal ret_opcode = {
+  "ret",
+  3,
+  ret_template,
+  &return_iclass
+};
+
+static xtensa_opcode_internal ret_n_opcode = {
+  "ret.n",
+  2,
+  ret_n_template,
+  &retn_iclass
+};
+
+static xtensa_opcode_internal retw_opcode = {
+  "retw",
+  3,
+  retw_template,
+  &return_iclass
+};
+
+static xtensa_opcode_internal retw_n_opcode = {
+  "retw.n",
+  2,
+  retw_n_template,
+  &retn_iclass
+};
+
+static xtensa_opcode_internal rfde_opcode = {
+  "rfde",
+  3,
+  rfde_template,
+  &rfe_iclass
+};
+
+static xtensa_opcode_internal rfe_opcode = {
+  "rfe",
+  3,
+  rfe_template,
+  &rfe_iclass
+};
+
+static xtensa_opcode_internal rfi_opcode = {
+  "rfi",
+  3,
+  rfi_template,
+  &rfi_iclass
+};
+
+static xtensa_opcode_internal rfwo_opcode = {
+  "rfwo",
+  3,
+  rfwo_template,
+  &rfe_iclass
+};
+
+static xtensa_opcode_internal rfwu_opcode = {
+  "rfwu",
+  3,
+  rfwu_template,
+  &rfe_iclass
+};
+
+static xtensa_opcode_internal ritlb0_opcode = {
+  "ritlb0",
+  3,
+  ritlb0_template,
+  &rtlb_iclass
+};
+
+static xtensa_opcode_internal ritlb1_opcode = {
+  "ritlb1",
+  3,
+  ritlb1_template,
+  &rtlb_iclass
+};
+
+static xtensa_opcode_internal rotw_opcode = {
+  "rotw",
+  3,
+  rotw_template,
+  &rotw_iclass
+};
+
+static xtensa_opcode_internal rsil_opcode = {
+  "rsil",
+  3,
+  rsil_template,
+  &rsil_iclass
+};
+
+static xtensa_opcode_internal rsr_opcode = {
+  "rsr",
+  3,
+  rsr_template,
+  &rsr_iclass
+};
+
+static xtensa_opcode_internal rsync_opcode = {
+  "rsync",
+  3,
+  rsync_template,
+  &sync_iclass
+};
+
+static xtensa_opcode_internal s16i_opcode = {
+  "s16i",
+  3,
+  s16i_template,
+  &s16i_iclass
+};
+
+static xtensa_opcode_internal s32e_opcode = {
+  "s32e",
+  3,
+  s32e_template,
+  &s32e_iclass
+};
+
+static xtensa_opcode_internal s32i_opcode = {
+  "s32i",
+  3,
+  s32i_template,
+  &s32i_iclass
+};
+
+static xtensa_opcode_internal s32i_n_opcode = {
+  "s32i.n",
+  2,
+  s32i_n_template,
+  &storei4_iclass
+};
+
+static xtensa_opcode_internal s8i_opcode = {
+  "s8i",
+  3,
+  s8i_template,
+  &s8i_iclass
+};
+
+static xtensa_opcode_internal sdct_opcode = {
+  "sdct",
+  3,
+  sdct_template,
+  &acts_iclass
+};
+
+static xtensa_opcode_internal sict_opcode = {
+  "sict",
+  3,
+  sict_template,
+  &acts_iclass
+};
+
+static xtensa_opcode_internal sicw_opcode = {
+  "sicw",
+  3,
+  sicw_template,
+  &acts_iclass
+};
+
+static xtensa_opcode_internal simcall_opcode = {
+  "simcall",
+  3,
+  simcall_template,
+  &syscall_iclass
+};
+
+static xtensa_opcode_internal sll_opcode = {
+  "sll",
+  3,
+  sll_template,
+  &shifts_iclass
+};
+
+static xtensa_opcode_internal slli_opcode = {
+  "slli",
+  3,
+  slli_template,
+  &slli_iclass
+};
+
+static xtensa_opcode_internal sra_opcode = {
+  "sra",
+  3,
+  sra_template,
+  &shiftt_iclass
+};
+
+static xtensa_opcode_internal srai_opcode = {
+  "srai",
+  3,
+  srai_template,
+  &srai_iclass
+};
+
+static xtensa_opcode_internal src_opcode = {
+  "src",
+  3,
+  src_template,
+  &shiftst_iclass
+};
+
+static xtensa_opcode_internal srl_opcode = {
+  "srl",
+  3,
+  srl_template,
+  &shiftt_iclass
+};
+
+static xtensa_opcode_internal srli_opcode = {
+  "srli",
+  3,
+  srli_template,
+  &srli_iclass
+};
+
+static xtensa_opcode_internal ssa8b_opcode = {
+  "ssa8b",
+  3,
+  ssa8b_template,
+  &sar_iclass
+};
+
+static xtensa_opcode_internal ssa8l_opcode = {
+  "ssa8l",
+  3,
+  ssa8l_template,
+  &sar_iclass
+};
+
+static xtensa_opcode_internal ssai_opcode = {
+  "ssai",
+  3,
+  ssai_template,
+  &sari_iclass
+};
+
+static xtensa_opcode_internal ssl_opcode = {
+  "ssl",
+  3,
+  ssl_template,
+  &sar_iclass
+};
+
+static xtensa_opcode_internal ssr_opcode = {
+  "ssr",
+  3,
+  ssr_template,
+  &sar_iclass
+};
+
+static xtensa_opcode_internal sub_opcode = {
+  "sub",
+  3,
+  sub_template,
+  &addsub_iclass
+};
+
+static xtensa_opcode_internal subx2_opcode = {
+  "subx2",
+  3,
+  subx2_template,
+  &addsub_iclass
+};
+
+static xtensa_opcode_internal subx4_opcode = {
+  "subx4",
+  3,
+  subx4_template,
+  &addsub_iclass
+};
+
+static xtensa_opcode_internal subx8_opcode = {
+  "subx8",
+  3,
+  subx8_template,
+  &addsub_iclass
+};
+
+static xtensa_opcode_internal syscall_opcode = {
+  "syscall",
+  3,
+  syscall_template,
+  &syscall_iclass
+};
+
+static xtensa_opcode_internal waiti_opcode = {
+  "waiti",
+  3,
+  waiti_template,
+  &wait_iclass
+};
+
+static xtensa_opcode_internal wdtlb_opcode = {
+  "wdtlb",
+  3,
+  wdtlb_template,
+  &wtlb_iclass
+};
+
+static xtensa_opcode_internal witlb_opcode = {
+  "witlb",
+  3,
+  witlb_template,
+  &wtlb_iclass
+};
+
+static xtensa_opcode_internal wsr_opcode = {
+  "wsr",
+  3,
+  wsr_template,
+  &wsr_iclass
+};
+
+static xtensa_opcode_internal xor_opcode = {
+  "xor",
+  3,
+  xor_template,
+  &bit_iclass
+};
+
+static xtensa_opcode_internal xsr_opcode = {
+  "xsr",
+  3,
+  xsr_template,
+  &xsr_iclass
+};
+
+static xtensa_opcode_internal * opcodes[149] = {
+  &abs_opcode,
+  &add_opcode,
+  &add_n_opcode,
+  &addi_opcode,
+  &addi_n_opcode,
+  &addmi_opcode,
+  &addx2_opcode,
+  &addx4_opcode,
+  &addx8_opcode,
+  &and_opcode,
+  &ball_opcode,
+  &bany_opcode,
+  &bbc_opcode,
+  &bbci_opcode,
+  &bbs_opcode,
+  &bbsi_opcode,
+  &beq_opcode,
+  &beqi_opcode,
+  &beqz_opcode,
+  &beqz_n_opcode,
+  &bge_opcode,
+  &bgei_opcode,
+  &bgeu_opcode,
+  &bgeui_opcode,
+  &bgez_opcode,
+  &blt_opcode,
+  &blti_opcode,
+  &bltu_opcode,
+  &bltui_opcode,
+  &bltz_opcode,
+  &bnall_opcode,
+  &bne_opcode,
+  &bnei_opcode,
+  &bnez_opcode,
+  &bnez_n_opcode,
+  &bnone_opcode,
+  &break_opcode,
+  &break_n_opcode,
+  &call0_opcode,
+  &call12_opcode,
+  &call4_opcode,
+  &call8_opcode,
+  &callx0_opcode,
+  &callx12_opcode,
+  &callx4_opcode,
+  &callx8_opcode,
+  &dhi_opcode,
+  &dhwb_opcode,
+  &dhwbi_opcode,
+  &dii_opcode,
+  &diwb_opcode,
+  &diwbi_opcode,
+  &dpfr_opcode,
+  &dpfro_opcode,
+  &dpfw_opcode,
+  &dpfwo_opcode,
+  &dsync_opcode,
+  &entry_opcode,
+  &esync_opcode,
+  &excw_opcode,
+  &extui_opcode,
+  &idtlb_opcode,
+  &idtlba_opcode,
+  &ihi_opcode,
+  &iii_opcode,
+  &iitlb_opcode,
+  &iitlba_opcode,
+  &ipf_opcode,
+  &isync_opcode,
+  &j_opcode,
+  &jx_opcode,
+  &l16si_opcode,
+  &l16ui_opcode,
+  &l32e_opcode,
+  &l32i_opcode,
+  &l32i_n_opcode,
+  &l32r_opcode,
+  &l8ui_opcode,
+  &ldct_opcode,
+  &lict_opcode,
+  &licw_opcode,
+  &loop_opcode,
+  &loopgtz_opcode,
+  &loopnez_opcode,
+  &memw_opcode,
+  &mov_n_opcode,
+  &moveqz_opcode,
+  &movgez_opcode,
+  &movi_opcode,
+  &movi_n_opcode,
+  &movltz_opcode,
+  &movnez_opcode,
+  &movsp_opcode,
+  &neg_opcode,
+  &nop_n_opcode,
+  &nsa_opcode,
+  &nsau_opcode,
+  &or_opcode,
+  &pdtlb_opcode,
+  &pitlb_opcode,
+  &rdtlb0_opcode,
+  &rdtlb1_opcode,
+  &ret_opcode,
+  &ret_n_opcode,
+  &retw_opcode,
+  &retw_n_opcode,
+  &rfde_opcode,
+  &rfe_opcode,
+  &rfi_opcode,
+  &rfwo_opcode,
+  &rfwu_opcode,
+  &ritlb0_opcode,
+  &ritlb1_opcode,
+  &rotw_opcode,
+  &rsil_opcode,
+  &rsr_opcode,
+  &rsync_opcode,
+  &s16i_opcode,
+  &s32e_opcode,
+  &s32i_opcode,
+  &s32i_n_opcode,
+  &s8i_opcode,
+  &sdct_opcode,
+  &sict_opcode,
+  &sicw_opcode,
+  &simcall_opcode,
+  &sll_opcode,
+  &slli_opcode,
+  &sra_opcode,
+  &srai_opcode,
+  &src_opcode,
+  &srl_opcode,
+  &srli_opcode,
+  &ssa8b_opcode,
+  &ssa8l_opcode,
+  &ssai_opcode,
+  &ssl_opcode,
+  &ssr_opcode,
+  &sub_opcode,
+  &subx2_opcode,
+  &subx4_opcode,
+  &subx8_opcode,
+  &syscall_opcode,
+  &waiti_opcode,
+  &wdtlb_opcode,
+  &witlb_opcode,
+  &wsr_opcode,
+  &xor_opcode,
+  &xsr_opcode
+};
+
+xtensa_opcode_internal **
+get_opcodes (void)
+{
+  return &opcodes[0];
+}
+
+const int
+get_num_opcodes (void)
+{
+  return 149;
+}
+
+#define xtensa_abs_op 0
+#define xtensa_add_op 1
+#define xtensa_add_n_op 2
+#define xtensa_addi_op 3
+#define xtensa_addi_n_op 4
+#define xtensa_addmi_op 5
+#define xtensa_addx2_op 6
+#define xtensa_addx4_op 7
+#define xtensa_addx8_op 8
+#define xtensa_and_op 9
+#define xtensa_ball_op 10
+#define xtensa_bany_op 11
+#define xtensa_bbc_op 12
+#define xtensa_bbci_op 13
+#define xtensa_bbs_op 14
+#define xtensa_bbsi_op 15
+#define xtensa_beq_op 16
+#define xtensa_beqi_op 17
+#define xtensa_beqz_op 18
+#define xtensa_beqz_n_op 19
+#define xtensa_bge_op 20
+#define xtensa_bgei_op 21
+#define xtensa_bgeu_op 22
+#define xtensa_bgeui_op 23
+#define xtensa_bgez_op 24
+#define xtensa_blt_op 25
+#define xtensa_blti_op 26
+#define xtensa_bltu_op 27
+#define xtensa_bltui_op 28
+#define xtensa_bltz_op 29
+#define xtensa_bnall_op 30
+#define xtensa_bne_op 31
+#define xtensa_bnei_op 32
+#define xtensa_bnez_op 33
+#define xtensa_bnez_n_op 34
+#define xtensa_bnone_op 35
+#define xtensa_break_op 36
+#define xtensa_break_n_op 37
+#define xtensa_call0_op 38
+#define xtensa_call12_op 39
+#define xtensa_call4_op 40
+#define xtensa_call8_op 41
+#define xtensa_callx0_op 42
+#define xtensa_callx12_op 43
+#define xtensa_callx4_op 44
+#define xtensa_callx8_op 45
+#define xtensa_dhi_op 46
+#define xtensa_dhwb_op 47
+#define xtensa_dhwbi_op 48
+#define xtensa_dii_op 49
+#define xtensa_diwb_op 50
+#define xtensa_diwbi_op 51
+#define xtensa_dpfr_op 52
+#define xtensa_dpfro_op 53
+#define xtensa_dpfw_op 54
+#define xtensa_dpfwo_op 55
+#define xtensa_dsync_op 56
+#define xtensa_entry_op 57
+#define xtensa_esync_op 58
+#define xtensa_excw_op 59
+#define xtensa_extui_op 60
+#define xtensa_idtlb_op 61
+#define xtensa_idtlba_op 62
+#define xtensa_ihi_op 63
+#define xtensa_iii_op 64
+#define xtensa_iitlb_op 65
+#define xtensa_iitlba_op 66
+#define xtensa_ipf_op 67
+#define xtensa_isync_op 68
+#define xtensa_j_op 69
+#define xtensa_jx_op 70
+#define xtensa_l16si_op 71
+#define xtensa_l16ui_op 72
+#define xtensa_l32e_op 73
+#define xtensa_l32i_op 74
+#define xtensa_l32i_n_op 75
+#define xtensa_l32r_op 76
+#define xtensa_l8ui_op 77
+#define xtensa_ldct_op 78
+#define xtensa_lict_op 79
+#define xtensa_licw_op 80
+#define xtensa_loop_op 81
+#define xtensa_loopgtz_op 82
+#define xtensa_loopnez_op 83
+#define xtensa_memw_op 84
+#define xtensa_mov_n_op 85
+#define xtensa_moveqz_op 86
+#define xtensa_movgez_op 87
+#define xtensa_movi_op 88
+#define xtensa_movi_n_op 89
+#define xtensa_movltz_op 90
+#define xtensa_movnez_op 91
+#define xtensa_movsp_op 92
+#define xtensa_neg_op 93
+#define xtensa_nop_n_op 94
+#define xtensa_nsa_op 95
+#define xtensa_nsau_op 96
+#define xtensa_or_op 97
+#define xtensa_pdtlb_op 98
+#define xtensa_pitlb_op 99
+#define xtensa_rdtlb0_op 100
+#define xtensa_rdtlb1_op 101
+#define xtensa_ret_op 102
+#define xtensa_ret_n_op 103
+#define xtensa_retw_op 104
+#define xtensa_retw_n_op 105
+#define xtensa_rfde_op 106
+#define xtensa_rfe_op 107
+#define xtensa_rfi_op 108
+#define xtensa_rfwo_op 109
+#define xtensa_rfwu_op 110
+#define xtensa_ritlb0_op 111
+#define xtensa_ritlb1_op 112
+#define xtensa_rotw_op 113
+#define xtensa_rsil_op 114
+#define xtensa_rsr_op 115
+#define xtensa_rsync_op 116
+#define xtensa_s16i_op 117
+#define xtensa_s32e_op 118
+#define xtensa_s32i_op 119
+#define xtensa_s32i_n_op 120
+#define xtensa_s8i_op 121
+#define xtensa_sdct_op 122
+#define xtensa_sict_op 123
+#define xtensa_sicw_op 124
+#define xtensa_simcall_op 125
+#define xtensa_sll_op 126
+#define xtensa_slli_op 127
+#define xtensa_sra_op 128
+#define xtensa_srai_op 129
+#define xtensa_src_op 130
+#define xtensa_srl_op 131
+#define xtensa_srli_op 132
+#define xtensa_ssa8b_op 133
+#define xtensa_ssa8l_op 134
+#define xtensa_ssai_op 135
+#define xtensa_ssl_op 136
+#define xtensa_ssr_op 137
+#define xtensa_sub_op 138
+#define xtensa_subx2_op 139
+#define xtensa_subx4_op 140
+#define xtensa_subx8_op 141
+#define xtensa_syscall_op 142
+#define xtensa_waiti_op 143
+#define xtensa_wdtlb_op 144
+#define xtensa_witlb_op 145
+#define xtensa_wsr_op 146
+#define xtensa_xor_op 147
+#define xtensa_xsr_op 148
+
+int
+decode_insn (const xtensa_insnbuf insn)
+{
+  switch (get_op0_field (insn)) {
+  case 0: /* QRST: op0=0000 */
+    switch (get_op1_field (insn)) {
+    case 3: /* RST3: op1=0011 */
+      switch (get_op2_field (insn)) {
+      case 8: /* MOVEQZ: op2=1000 */
+        return xtensa_moveqz_op;
+      case 9: /* MOVNEZ: op2=1001 */
+        return xtensa_movnez_op;
+      case 10: /* MOVLTZ: op2=1010 */
+        return xtensa_movltz_op;
+      case 11: /* MOVGEZ: op2=1011 */
+        return xtensa_movgez_op;
+      case 0: /* RSR: op2=0000 */
+        return xtensa_rsr_op;
+      case 1: /* WSR: op2=0001 */
+        return xtensa_wsr_op;
+      }
+      break;
+    case 9: /* LSI4: op1=1001 */
+      switch (get_op2_field (insn)) {
+      case 4: /* S32E: op2=0100 */
+        return xtensa_s32e_op;
+      case 0: /* L32E: op2=0000 */
+        return xtensa_l32e_op;
+      }
+      break;
+    case 4: /* EXTUI: op1=010x */
+    case 5: /* EXTUI: op1=010x */
+      return xtensa_extui_op;
+    case 0: /* RST0: op1=0000 */
+      switch (get_op2_field (insn)) {
+      case 15: /* SUBX8: op2=1111 */
+        return xtensa_subx8_op;
+      case 0: /* ST0: op2=0000 */
+        switch (get_r_field (insn)) {
+        case 0: /* SNM0: r=0000 */
+          switch (get_m_field (insn)) {
+          case 2: /* JR: m=10 */
+            switch (get_n_field (insn)) {
+            case 0: /* RET: n=00 */
+              return xtensa_ret_op;
+            case 1: /* RETW: n=01 */
+              return xtensa_retw_op;
+            case 2: /* JX: n=10 */
+              return xtensa_jx_op;
+            }
+            break;
+          case 3: /* CALLX: m=11 */
+            switch (get_n_field (insn)) {
+            case 0: /* CALLX0: n=00 */
+              return xtensa_callx0_op;
+            case 1: /* CALLX4: n=01 */
+              return xtensa_callx4_op;
+            case 2: /* CALLX8: n=10 */
+              return xtensa_callx8_op;
+            case 3: /* CALLX12: n=11 */
+              return xtensa_callx12_op;
+            }
+            break;
+          }
+          break;
+        case 1: /* MOVSP: r=0001 */
+          return xtensa_movsp_op;
+        case 2: /* SYNC: r=0010 */
+          switch (get_s_field (insn)) {
+          case 0: /* SYNCT: s=0000 */
+            switch (get_t_field (insn)) {
+            case 2: /* ESYNC: t=0010 */
+              return xtensa_esync_op;
+            case 3: /* DSYNC: t=0011 */
+              return xtensa_dsync_op;
+            case 8: /* EXCW: t=1000 */
+              return xtensa_excw_op;
+            case 12: /* MEMW: t=1100 */
+              return xtensa_memw_op;
+            case 0: /* ISYNC: t=0000 */
+              return xtensa_isync_op;
+            case 1: /* RSYNC: t=0001 */
+              return xtensa_rsync_op;
+            }
+            break;
+          }
+          break;
+        case 4: /* BREAK: r=0100 */
+          return xtensa_break_op;
+        case 3: /* RFEI: r=0011 */
+          switch (get_t_field (insn)) {
+          case 0: /* RFET: t=0000 */
+            switch (get_s_field (insn)) {
+            case 2: /* RFDE: s=0010 */
+              return xtensa_rfde_op;
+            case 4: /* RFWO: s=0100 */
+              return xtensa_rfwo_op;
+            case 5: /* RFWU: s=0101 */
+              return xtensa_rfwu_op;
+            case 0: /* RFE: s=0000 */
+              return xtensa_rfe_op;
+            }
+            break;
+          case 1: /* RFI: t=0001 */
+            return xtensa_rfi_op;
+          }
+          break;
+        case 5: /* SCALL: r=0101 */
+          switch (get_s_field (insn)) {
+          case 0: /* SYSCALL: s=0000 */
+            return xtensa_syscall_op;
+          case 1: /* SIMCALL: s=0001 */
+            return xtensa_simcall_op;
+          }
+          break;
+        case 6: /* RSIL: r=0110 */
+          return xtensa_rsil_op;
+        case 7: /* WAITI: r=0111 */
+          return xtensa_waiti_op;
+        }
+        break;
+      case 1: /* AND: op2=0001 */
+        return xtensa_and_op;
+      case 2: /* OR: op2=0010 */
+        return xtensa_or_op;
+      case 3: /* XOR: op2=0011 */
+        return xtensa_xor_op;
+      case 4: /* ST1: op2=0100 */
+        switch (get_r_field (insn)) {
+        case 15: /* NSAU: r=1111 */
+          return xtensa_nsau_op;
+        case 0: /* SSR: r=0000 */
+          return xtensa_ssr_op;
+        case 1: /* SSL: r=0001 */
+          return xtensa_ssl_op;
+        case 2: /* SSA8L: r=0010 */
+          return xtensa_ssa8l_op;
+        case 3: /* SSA8B: r=0011 */
+          return xtensa_ssa8b_op;
+        case 4: /* SSAI: r=0100 */
+          return xtensa_ssai_op;
+        case 8: /* ROTW: r=1000 */
+          return xtensa_rotw_op;
+        case 14: /* NSA: r=1110 */
+          return xtensa_nsa_op;
+        }
+        break;
+      case 8: /* ADD: op2=1000 */
+        return xtensa_add_op;
+      case 5: /* ST4: op2=0101 */
+        switch (get_r_field (insn)) {
+        case 15: /* RDTLB1: r=1111 */
+          return xtensa_rdtlb1_op;
+        case 0: /* IITLBA: r=0000 */
+          return xtensa_iitlba_op;
+        case 3: /* RITLB0: r=0011 */
+          return xtensa_ritlb0_op;
+        case 4: /* IITLB: r=0100 */
+          return xtensa_iitlb_op;
+        case 8: /* IDTLBA: r=1000 */
+          return xtensa_idtlba_op;
+        case 5: /* PITLB: r=0101 */
+          return xtensa_pitlb_op;
+        case 6: /* WITLB: r=0110 */
+          return xtensa_witlb_op;
+        case 7: /* RITLB1: r=0111 */
+          return xtensa_ritlb1_op;
+        case 11: /* RDTLB0: r=1011 */
+          return xtensa_rdtlb0_op;
+        case 12: /* IDTLB: r=1100 */
+          return xtensa_idtlb_op;
+        case 13: /* PDTLB: r=1101 */
+          return xtensa_pdtlb_op;
+        case 14: /* WDTLB: r=1110 */
+          return xtensa_wdtlb_op;
+        }
+        break;
+      case 6: /* RT0: op2=0110 */
+        switch (get_s_field (insn)) {
+        case 0: /* NEG: s=0000 */
+          return xtensa_neg_op;
+        case 1: /* ABS: s=0001 */
+          return xtensa_abs_op;
+        }
+        break;
+      case 9: /* ADDX2: op2=1001 */
+        return xtensa_addx2_op;
+      case 10: /* ADDX4: op2=1010 */
+        return xtensa_addx4_op;
+      case 11: /* ADDX8: op2=1011 */
+        return xtensa_addx8_op;
+      case 12: /* SUB: op2=1100 */
+        return xtensa_sub_op;
+      case 13: /* SUBX2: op2=1101 */
+        return xtensa_subx2_op;
+      case 14: /* SUBX4: op2=1110 */
+        return xtensa_subx4_op;
+      }
+      break;
+    case 1: /* RST1: op1=0001 */
+      switch (get_op2_field (insn)) {
+      case 15: /* IMP: op2=1111 */
+        switch (get_r_field (insn)) {
+        case 0: /* LICT: r=0000 */
+          return xtensa_lict_op;
+        case 1: /* SICT: r=0001 */
+          return xtensa_sict_op;
+        case 2: /* LICW: r=0010 */
+          return xtensa_licw_op;
+        case 3: /* SICW: r=0011 */
+          return xtensa_sicw_op;
+        case 8: /* LDCT: r=1000 */
+          return xtensa_ldct_op;
+        case 9: /* SDCT: r=1001 */
+          return xtensa_sdct_op;
+        }
+        break;
+      case 0: /* SLLI: op2=000x */
+      case 1: /* SLLI: op2=000x */
+        return xtensa_slli_op;
+      case 2: /* SRAI: op2=001x */
+      case 3: /* SRAI: op2=001x */
+        return xtensa_srai_op;
+      case 4: /* SRLI: op2=0100 */
+        return xtensa_srli_op;
+      case 8: /* SRC: op2=1000 */
+        return xtensa_src_op;
+      case 9: /* SRL: op2=1001 */
+        return xtensa_srl_op;
+      case 6: /* XSR: op2=0110 */
+        return xtensa_xsr_op;
+      case 10: /* SLL: op2=1010 */
+        return xtensa_sll_op;
+      case 11: /* SRA: op2=1011 */
+        return xtensa_sra_op;
+      }
+      break;
+    }
+    break;
+  case 1: /* L32R: op0=0001 */
+    return xtensa_l32r_op;
+  case 2: /* LSAI: op0=0010 */
+    switch (get_r_field (insn)) {
+    case 0: /* L8UI: r=0000 */
+      return xtensa_l8ui_op;
+    case 1: /* L16UI: r=0001 */
+      return xtensa_l16ui_op;
+    case 2: /* L32I: r=0010 */
+      return xtensa_l32i_op;
+    case 4: /* S8I: r=0100 */
+      return xtensa_s8i_op;
+    case 5: /* S16I: r=0101 */
+      return xtensa_s16i_op;
+    case 9: /* L16SI: r=1001 */
+      return xtensa_l16si_op;
+    case 6: /* S32I: r=0110 */
+      return xtensa_s32i_op;
+    case 7: /* CACHE: r=0111 */
+      switch (get_t_field (insn)) {
+      case 15: /* III: t=1111 */
+        return xtensa_iii_op;
+      case 0: /* DPFR: t=0000 */
+        return xtensa_dpfr_op;
+      case 1: /* DPFW: t=0001 */
+        return xtensa_dpfw_op;
+      case 2: /* DPFRO: t=0010 */
+        return xtensa_dpfro_op;
+      case 4: /* DHWB: t=0100 */
+        return xtensa_dhwb_op;
+      case 3: /* DPFWO: t=0011 */
+        return xtensa_dpfwo_op;
+      case 8: /* DCE: t=1000 */
+        switch (get_op1_field (insn)) {
+        case 4: /* DIWB: op1=0100 */
+          return xtensa_diwb_op;
+        case 5: /* DIWBI: op1=0101 */
+          return xtensa_diwbi_op;
+        }
+        break;
+      case 5: /* DHWBI: t=0101 */
+        return xtensa_dhwbi_op;
+      case 6: /* DHI: t=0110 */
+        return xtensa_dhi_op;
+      case 7: /* DII: t=0111 */
+        return xtensa_dii_op;
+      case 12: /* IPF: t=1100 */
+        return xtensa_ipf_op;
+      case 14: /* IHI: t=1110 */
+        return xtensa_ihi_op;
+      }
+      break;
+    case 10: /* MOVI: r=1010 */
+      return xtensa_movi_op;
+    case 12: /* ADDI: r=1100 */
+      return xtensa_addi_op;
+    case 13: /* ADDMI: r=1101 */
+      return xtensa_addmi_op;
+    }
+    break;
+  case 8: /* L32I.N: op0=1000 */
+    return xtensa_l32i_n_op;
+  case 5: /* CALL: op0=0101 */
+    switch (get_n_field (insn)) {
+    case 0: /* CALL0: n=00 */
+      return xtensa_call0_op;
+    case 1: /* CALL4: n=01 */
+      return xtensa_call4_op;
+    case 2: /* CALL8: n=10 */
+      return xtensa_call8_op;
+    case 3: /* CALL12: n=11 */
+      return xtensa_call12_op;
+    }
+    break;
+  case 6: /* SI: op0=0110 */
+    switch (get_n_field (insn)) {
+    case 0: /* J: n=00 */
+      return xtensa_j_op;
+    case 1: /* BZ: n=01 */
+      switch (get_m_field (insn)) {
+      case 0: /* BEQZ: m=00 */
+        return xtensa_beqz_op;
+      case 1: /* BNEZ: m=01 */
+        return xtensa_bnez_op;
+      case 2: /* BLTZ: m=10 */
+        return xtensa_bltz_op;
+      case 3: /* BGEZ: m=11 */
+        return xtensa_bgez_op;
+      }
+      break;
+    case 2: /* BI0: n=10 */
+      switch (get_m_field (insn)) {
+      case 0: /* BEQI: m=00 */
+        return xtensa_beqi_op;
+      case 1: /* BNEI: m=01 */
+        return xtensa_bnei_op;
+      case 2: /* BLTI: m=10 */
+        return xtensa_blti_op;
+      case 3: /* BGEI: m=11 */
+        return xtensa_bgei_op;
+      }
+      break;
+    case 3: /* BI1: n=11 */
+      switch (get_m_field (insn)) {
+      case 0: /* ENTRY: m=00 */
+        return xtensa_entry_op;
+      case 1: /* B1: m=01 */
+        switch (get_r_field (insn)) {
+        case 8: /* LOOP: r=1000 */
+          return xtensa_loop_op;
+        case 9: /* LOOPNEZ: r=1001 */
+          return xtensa_loopnez_op;
+        case 10: /* LOOPGTZ: r=1010 */
+          return xtensa_loopgtz_op;
+        }
+        break;
+      case 2: /* BLTUI: m=10 */
+        return xtensa_bltui_op;
+      case 3: /* BGEUI: m=11 */
+        return xtensa_bgeui_op;
+      }
+      break;
+    }
+    break;
+  case 9: /* S32I.N: op0=1001 */
+    return xtensa_s32i_n_op;
+  case 10: /* ADD.N: op0=1010 */
+    return xtensa_add_n_op;
+  case 7: /* B: op0=0111 */
+    switch (get_r_field (insn)) {
+    case 6: /* BBCI: r=011x */
+    case 7: /* BBCI: r=011x */
+      return xtensa_bbci_op;
+    case 0: /* BNONE: r=0000 */
+      return xtensa_bnone_op;
+    case 1: /* BEQ: r=0001 */
+      return xtensa_beq_op;
+    case 2: /* BLT: r=0010 */
+      return xtensa_blt_op;
+    case 4: /* BALL: r=0100 */
+      return xtensa_ball_op;
+    case 14: /* BBSI: r=111x */
+    case 15: /* BBSI: r=111x */
+      return xtensa_bbsi_op;
+    case 3: /* BLTU: r=0011 */
+      return xtensa_bltu_op;
+    case 5: /* BBC: r=0101 */
+      return xtensa_bbc_op;
+    case 8: /* BANY: r=1000 */
+      return xtensa_bany_op;
+    case 9: /* BNE: r=1001 */
+      return xtensa_bne_op;
+    case 10: /* BGE: r=1010 */
+      return xtensa_bge_op;
+    case 11: /* BGEU: r=1011 */
+      return xtensa_bgeu_op;
+    case 12: /* BNALL: r=1100 */
+      return xtensa_bnall_op;
+    case 13: /* BBS: r=1101 */
+      return xtensa_bbs_op;
+    }
+    break;
+  case 11: /* ADDI.N: op0=1011 */
+    return xtensa_addi_n_op;
+  case 12: /* ST2: op0=1100 */
+    switch (get_i_field (insn)) {
+    case 0: /* MOVI.N: i=0 */
+      return xtensa_movi_n_op;
+    case 1: /* BZ6: i=1 */
+      switch (get_z_field (insn)) {
+      case 0: /* BEQZ.N: z=0 */
+        return xtensa_beqz_n_op;
+      case 1: /* BNEZ.N: z=1 */
+        return xtensa_bnez_n_op;
+      }
+      break;
+    }
+    break;
+  case 13: /* ST3: op0=1101 */
+    switch (get_r_field (insn)) {
+    case 15: /* S3: r=1111 */
+      switch (get_t_field (insn)) {
+      case 0: /* RET.N: t=0000 */
+        return xtensa_ret_n_op;
+      case 1: /* RETW.N: t=0001 */
+        return xtensa_retw_n_op;
+      case 2: /* BREAK.N: t=0010 */
+        return xtensa_break_n_op;
+      case 3: /* NOP.N: t=0011 */
+        return xtensa_nop_n_op;
+      }
+      break;
+    case 0: /* MOV.N: r=0000 */
+      return xtensa_mov_n_op;
+    }
+    break;
+  }
+  return XTENSA_UNDEFINED;
+}
+
+int
+interface_version (void)
+{
+  return 3;
+}
+
+static struct config_struct config_table[] = {
+  {"IsaMemoryOrder", "BigEndian"},
+  {"PIFReadDataBits", "128"},
+  {"PIFWriteDataBits", "128"},
+  {"IsaCoprocessorCount", "0"},
+  {"IsaUseBooleans", "0"},
+  {"IsaUseDensityInstruction", "1"},
+  {0, 0}
+};
+
+struct config_struct * get_config_table (void);
+
+struct config_struct *
+get_config_table (void)
+{
+  return config_table;
+}
+
+xtensa_isa_module xtensa_isa_modules[] = {
+  { get_num_opcodes, get_opcodes, decode_insn, get_config_table },
+  { 0, 0, 0, 0 }
+};
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
new file mode 100644 (file)
index 0000000..7205cf7
--- /dev/null
@@ -0,0 +1,266 @@
+/* Helper routines for C++ support in GDB.
+   Copyright 2003 Free Software Foundation, Inc.
+
+   Contributed by David Carlton.
+
+   This file is part of GDB.
+
+   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.
+
+   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 "defs.h"
+#include "cp-support.h"
+#include "gdb_obstack.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "gdb_assert.h"
+#include "block.h"
+
+/* When set, the file that we're processing seems to have debugging
+   info for C++ namespaces, so cp-namespace.c shouldn't try to guess
+   namespace info itself.  */
+
+unsigned char processing_has_namespace_info;
+
+/* If processing_has_namespace_info is nonzero, this string should
+   contain the name of the current namespace.  The string is
+   temporary; copy it if you need it.  */
+
+const char *processing_current_namespace;
+
+/* List of using directives that are active in the current file.  */
+
+static struct using_direct *using_list;
+
+static struct using_direct *cp_add_using (const char *name,
+                                         unsigned int inner_len,
+                                         unsigned int outer_len,
+                                         struct using_direct *next);
+
+static struct using_direct *cp_copy_usings (struct using_direct *using,
+                                           struct obstack *obstack);
+
+/* Set up support for dealing with C++ namespace info in the current
+   symtab.  */
+
+void cp_initialize_namespace ()
+{
+  processing_has_namespace_info = 0;
+  using_list = NULL;
+}
+
+/* Add all the using directives we've gathered to the current symtab.
+   STATIC_BLOCK should be the symtab's static block; OBSTACK is used
+   for allocation.  */
+
+void
+cp_finalize_namespace (struct block *static_block,
+                      struct obstack *obstack)
+{
+  if (using_list != NULL)
+    {
+      block_set_using (static_block,
+                      cp_copy_usings (using_list, obstack),
+                      obstack);
+      using_list = NULL;
+    }
+}
+
+/* Check to see if SYMBOL refers to an object contained within an
+   anonymous namespace; if so, add an appropriate using directive.  */
+
+/* Optimize away strlen ("(anonymous namespace)").  */
+
+#define ANONYMOUS_NAMESPACE_LEN 21
+
+void
+cp_scan_for_anonymous_namespaces (const struct symbol *symbol)
+{
+  if (!processing_has_namespace_info
+      && SYMBOL_CPLUS_DEMANGLED_NAME (symbol) != NULL)
+    {
+      const char *name = SYMBOL_CPLUS_DEMANGLED_NAME (symbol);
+      unsigned int previous_component;
+      unsigned int next_component;
+      const char *len;
+
+      /* Start with a quick-and-dirty check for mention of "(anonymous
+        namespace)".  */
+
+      if (!cp_is_anonymous (name))
+       return;
+
+      previous_component = 0;
+      next_component = cp_find_first_component (name + previous_component);
+
+      while (name[next_component] == ':')
+       {
+         if ((next_component - previous_component) == ANONYMOUS_NAMESPACE_LEN
+             && strncmp (name + previous_component,
+                         "(anonymous namespace)",
+                         ANONYMOUS_NAMESPACE_LEN) == 0)
+           {
+             /* We've found a component of the name that's an
+                anonymous namespace.  So add symbols in it to the
+                namespace given by the previous component if there is
+                one, or to the global namespace if there isn't.  */
+             cp_add_using_directive (name,
+                                     previous_component == 0
+                                     ? 0 : previous_component - 2,
+                                     next_component);
+           }
+         /* The "+ 2" is for the "::".  */
+         previous_component = next_component + 2;
+         next_component = (previous_component
+                           + cp_find_first_component (name
+                                                      + previous_component));
+       }
+    }
+}
+
+/* Add a using directive to using_list.  NAME is the start of a string
+   that should contain the namespaces we want to add as initial
+   substrings, OUTER_LENGTH is the end of the outer namespace, and
+   INNER_LENGTH is the end of the inner namespace.  If the using
+   directive in question has already been added, don't add it
+   twice.  */
+
+void
+cp_add_using_directive (const char *name, unsigned int outer_length,
+                       unsigned int inner_length)
+{
+  struct using_direct *current;
+  struct using_direct *new;
+
+  /* Has it already been added?  */
+
+  for (current = using_list; current != NULL; current = current->next)
+    {
+      if ((strncmp (current->inner, name, inner_length) == 0)
+         && (strlen (current->inner) == inner_length)
+         && (strlen (current->outer) == outer_length))
+       return;
+    }
+
+  using_list = cp_add_using (name, inner_length, outer_length,
+                            using_list);
+}
+
+/* Record the namespace that the function defined by SYMBOL was
+   defined in, if necessary.  BLOCK is the associated block; use
+   OBSTACK for allocation.  */
+
+void
+cp_set_block_scope (const struct symbol *symbol,
+                   struct block *block,
+                   struct obstack *obstack)
+{
+  /* Make sure that the name was originally mangled: if not, there
+     certainly isn't any namespace information to worry about!  */
+
+  if (SYMBOL_CPLUS_DEMANGLED_NAME (symbol) != NULL)
+    {
+      if (processing_has_namespace_info)
+       {
+         block_set_scope
+           (block, obsavestring (processing_current_namespace,
+                                 strlen (processing_current_namespace),
+                                 obstack),
+            obstack);
+       }
+      else
+       {
+         /* Try to figure out the appropriate namespace from the
+            demangled name.  */
+
+         /* FIXME: carlton/2003-04-15: If the function in question is
+            a method of a class, the name will actually include the
+            name of the class as well.  This should be harmless, but
+            is a little unfortunate.  */
+
+         const char *name = SYMBOL_CPLUS_DEMANGLED_NAME (symbol);
+         unsigned int prefix_len = cp_entire_prefix_len (name);
+
+         block_set_scope (block,
+                          obsavestring (name, prefix_len, obstack),
+                          obstack);
+       }
+    }
+}
+
+/* Test whether or not NAMESPACE looks like it mentions an anonymous
+   namespace; return nonzero if so.  */
+
+int
+cp_is_anonymous (const char *namespace)
+{
+  return (strstr (namespace, "(anonymous namespace)")
+         != NULL);
+}
+
+/* Create a new struct using direct whose inner namespace is the
+   initial substring of NAME of leng INNER_LEN and whose outer
+   namespace is the initial substring of NAME of length OUTER_LENGTH.
+   Set its next member in the linked list to NEXT; allocate all memory
+   using xmalloc.  It copies the strings, so NAME can be a temporary
+   string.  */
+
+static struct using_direct *
+cp_add_using (const char *name,
+             unsigned int inner_len,
+             unsigned int outer_len,
+             struct using_direct *next)
+{
+  struct using_direct *retval;
+
+  gdb_assert (outer_len < inner_len);
+
+  retval = xmalloc (sizeof (struct using_direct));
+  retval->inner = savestring (name, inner_len);
+  retval->outer = savestring (name, outer_len);
+  retval->next = next;
+
+  return retval;
+}
+
+/* Make a copy of the using directives in the list pointed to by
+   USING, using OBSTACK to allocate memory.  Free all memory pointed
+   to by USING via xfree.  */
+
+static struct using_direct *
+cp_copy_usings (struct using_direct *using,
+               struct obstack *obstack)
+{
+  if (using == NULL)
+    {
+      return NULL;
+    }
+  else
+    {
+      struct using_direct *retval
+       = obstack_alloc (obstack, sizeof (struct using_direct));
+      retval->inner = obsavestring (using->inner, strlen (using->inner),
+                                   obstack);
+      retval->outer = obsavestring (using->outer, strlen (using->outer),
+                                   obstack);
+      retval->next = cp_copy_usings (using->next, obstack);
+
+      xfree (using->inner);
+      xfree (using->outer);
+      xfree (using);
+
+      return retval;
+    }
+}
diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
new file mode 100644 (file)
index 0000000..de48a19
--- /dev/null
@@ -0,0 +1,70 @@
+@c -*-texinfo-*-
+@node GDB Observers
+@appendix @value{GDBN} Currently available observers
+
+@section Implementation rationale
+@cindex observers implementation rationale
+
+An @dfn{observer} is an entity which is interested in being notified
+when GDB reaches certain states, or certain events occur in GDB.
+The entity being observed is called the @dfn{subject}.  To receive
+notifications, the observer attaches a callback to the subject.
+One subject can have several observers.
+
+@file{observer.c} implements an internal generic low-level event
+notification mechanism.  This generic event notification mechanism is
+then re-used to implement the exported high-level notification
+management routines for all possible notifications.
+
+The current implementation of the generic observer provides support
+for contextual data.  This contextual data is given to the subject
+when attaching the callback.  In return, the subject will provide
+this contextual data back to the observer as a parameter of the
+callback.
+
+Note that the current support for the contextual data is only partial,
+as it lacks a mechanism that would deallocate this data when the
+callback is detached.  This is not a problem so far, as this contextual
+data is only used internally to hold a function pointer.  Later on, if
+a certain observer needs to provide support for user-level contextual
+data, then the generic notification mechanism will need to be
+enhanced to allow the observer to provide a routine to deallocate the
+data when attaching the callback.
+
+The observer implementation is also currently not reentrant.
+In particular, it is therefore not possible to call the attach
+or detach routines during a notification.
+
+@section @code{normal_stop} Notifications
+@cindex @code{normal_stop} observer
+@cindex notification about inferior execution stop
+
+@value{GDBN} notifies all @code{normal_stop} observers when the
+inferior execution has just stopped, the associated messages and
+annotations have been printed, and the control is about to be returned
+to the user. 
+
+Note that the @code{normal_stop} notification is not emitted when
+the execution stops due to a breakpoint, and this breakpoint has
+a condition that is not met.  If the breakpoint has any associated
+commands list, the commands are executed after the notification
+is emitted.
+
+The following interface is available to manage @code{normal_stop}
+observers:
+
+@deftypefun extern struct observer *observer_attach_normal_stop (observer_normal_stop_ftype *@var{f})
+Attach the given @code{normal_stop} callback function @var{f} and
+return the associated observer.
+@end deftypefun
+
+@deftypefun extern void observer_detach_normal_stop (struct observer *@var{observer});
+Remove @var{observer} from the list of observers to be notified when
+a @code{normal_stop} event occurs.
+@end deftypefun
+
+@deftypefun extern void observer_notify_normal_stop (void);
+Send a notification to all @code{normal_stop} observers.
+@end deftypefun
+
+
diff --git a/gdb/frame-base.c b/gdb/frame-base.c
new file mode 100644 (file)
index 0000000..f7ba4be
--- /dev/null
@@ -0,0 +1,154 @@
+/* Definitions for frame address handler, for GDB, the GNU debugger.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.
+
+   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 "defs.h"
+#include "frame-base.h"
+#include "frame.h"
+
+/* A default frame base implementations.  If it wasn't for the old
+   FRAME_LOCALS_ADDRESS and FRAME_ARGS_ADDRESS, these could be
+   combined into a single function.  All architectures really need to
+   override this.  */
+
+static CORE_ADDR
+default_frame_base_address (struct frame_info *next_frame, void **this_cache)
+{
+  struct frame_info *this_frame = get_prev_frame (next_frame);
+  return get_frame_base (this_frame); /* sigh! */
+}
+
+static CORE_ADDR
+default_frame_locals_address (struct frame_info *next_frame, void **this_cache)
+{
+  struct frame_info *this_frame = get_prev_frame (next_frame);
+  return FRAME_LOCALS_ADDRESS (this_frame);
+}
+
+static CORE_ADDR
+default_frame_args_address (struct frame_info *next_frame, void **this_cache)
+{
+  struct frame_info *this_frame = get_prev_frame (next_frame);
+  /* FRAME_ARGS_ADDRESS_CORRECT is just like FRAME_ARGS_ADDRESS except
+     that if it is unsure about the answer, it returns 0 instead of
+     guessing (this happens on the VAX and i960, for example).
+
+     On most machines, we never have to guess about the args address,
+     so FRAME_ARGS_ADDRESS{,_CORRECT} are the same.  */
+#ifdef FRAME_ARGS_ADDRESS_CORRECT
+  return FRAME_ARGS_ADDRESS_CORRECT (this_frame);
+#else
+  return FRAME_ARGS_ADDRESS (this_frame);
+#endif
+}
+
+const struct frame_base default_frame_base = {
+  NULL, /* No parent.  */
+  default_frame_base_address,
+  default_frame_locals_address,
+  default_frame_args_address
+};
+
+static struct gdbarch_data *frame_base_data;
+
+struct frame_base_table
+{
+  frame_base_p_ftype **p;
+  const struct frame_base *default_base;
+  int nr;
+};
+
+static void *
+frame_base_init (struct gdbarch *gdbarch)
+{
+  struct frame_base_table *table = XCALLOC (1, struct frame_base_table);
+  table->default_base = &default_frame_base;
+  return table;
+}
+
+static void
+frame_base_free (struct gdbarch *gdbarch, void *data)
+{
+  struct frame_base_table *table =
+    gdbarch_data (gdbarch, frame_base_data);
+  xfree (table->p);
+  xfree (table);
+}
+
+static struct frame_base_table *
+frame_base_table (struct gdbarch *gdbarch)
+{
+  struct frame_base_table *table = gdbarch_data (gdbarch, frame_base_data);
+  if (table == NULL)
+    {
+      /* ULGH, called during architecture initialization.  Patch
+         things up.  */
+      table = frame_base_init (gdbarch);
+      set_gdbarch_data (gdbarch, frame_base_data, table);
+    }
+  return table;
+}
+
+/* Append a predicate to the end of the table.  */
+static void
+append_predicate (struct frame_base_table *table, frame_base_p_ftype *p)
+{
+  table->p = xrealloc (table->p, ((table->nr + 1)
+                                 * sizeof (frame_base_p_ftype *)));
+  table->p[table->nr] = p;
+  table->nr++;
+}
+
+void
+frame_base_append_predicate (struct gdbarch *gdbarch,
+                            frame_base_p_ftype *p)
+{
+  struct frame_base_table *table = frame_base_table (gdbarch);
+  append_predicate (table, p);
+}
+
+void
+frame_base_set_default (struct gdbarch *gdbarch,
+                       const struct frame_base *default_base)
+{
+  struct frame_base_table *table = frame_base_table (gdbarch);
+  table->default_base = default_base;
+}
+
+const struct frame_base *
+frame_base_find_by_pc (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  int i;
+  struct frame_base_table *table = frame_base_table (gdbarch);
+  for (i = 0; i < table->nr; i++)
+    {
+      const struct frame_base *desc = table->p[i] (pc);
+      if (desc != NULL)
+       return desc;
+    }
+  return table->default_base;
+}
+
+void
+_initialize_frame_base (void)
+{
+  frame_base_data = register_gdbarch_data (frame_base_init,
+                                          frame_base_free);
+}
diff --git a/gdb/frame-base.h b/gdb/frame-base.h
new file mode 100644 (file)
index 0000000..5e0d5db
--- /dev/null
@@ -0,0 +1,94 @@
+/* Definitions for a frame base, for GDB, the GNU debugger.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.
+
+   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.  */
+
+#if !defined (FRAME_BASE_H)
+#define FRAME_BASE_H 1
+
+struct frame_info;
+struct frame_id;
+struct frame_unwind;
+struct frame_base;
+struct gdbarch;
+struct regcache;
+
+/* Return the frame base methods for the function that contains PC, or
+   NULL if it can't handle this frame.  */
+
+typedef const struct frame_base *(frame_base_p_ftype) (CORE_ADDR pc);
+
+/* Add a frame base handler to the list.  The predicates are polled in
+   the order that they are appended.  */
+
+extern void frame_base_append_predicate (struct gdbarch *gdbarch,
+                                        frame_base_p_ftype *p);
+
+/* Set the default frame base.  If all else fails, this one is
+   returned.  If this isn't set, the default is to use legacy code
+   that uses things like the frame ID's base (ulgh!).  */
+
+extern void frame_base_set_default (struct gdbarch *gdbarch,
+                                   const struct frame_base *def);
+
+/* Iterate through the list of frame base handlers until one returns
+   an implementation.  */
+
+extern const struct frame_base *frame_base_find_by_pc (struct gdbarch *gdbarch,
+                                                      CORE_ADDR pc);
+
+/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
+   and that this is a `normal frame'; use the NEXT frame, and its
+   register unwind method, to determine the address of THIS frame's
+   `base'.
+
+   The exact meaning of `base' is highly dependant on the type of the
+   debug info.  It is assumed that dwarf2, stabs, ... will each
+   provide their own methods.
+
+   A typical implmentation will return the same value for base,
+   locals-base and args-base.  That value, however, will likely be
+   different to the frame ID's stack address.  */
+
+/* A generic base address.  */
+
+typedef CORE_ADDR (frame_this_base_ftype) (struct frame_info *next_frame,
+                                          void **this_base_cache);
+
+/* The base address of the frame's local variables.  */
+
+typedef CORE_ADDR (frame_this_locals_ftype) (struct frame_info *next_frame,
+                                            void **this_base_cache);
+
+/* The base address of the frame's arguments / parameters.  */
+
+typedef CORE_ADDR (frame_this_args_ftype) (struct frame_info *next_frame,
+                                          void **this_base_cache);
+
+struct frame_base
+{
+  /* If non-NULL, a low-level unwinder that shares its implementation
+     with this high-level frame-base method.  */
+  const struct frame_unwind *unwind;
+  frame_this_base_ftype *this_base;
+  frame_this_locals_ftype *this_locals;
+  frame_this_args_ftype *this_args;
+};
+
+#endif
diff --git a/gdb/i386-cygwin-tdep.c b/gdb/i386-cygwin-tdep.c
new file mode 100644 (file)
index 0000000..5911ec9
--- /dev/null
@@ -0,0 +1,86 @@
+/* Target-dependent code for Cygwin running on i386's, for GDB.
+   Copyright 2003 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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.
+
+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 "defs.h"
+
+#include "gdb_string.h"
+#include "gdbcore.h"
+#include "i386-tdep.h"
+#include "osabi.h"
+#include "frame.h"
+#include "dummy-frame.h"
+
+static int
+i386_cygwin_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
+{
+  /* In the context where this is used, we get the saved PC before we've
+     successfully unwound far enough to be sure what we've got (it may
+     be a signal handler caller).  If we're dealing with a signal
+     handler caller, this will return valid, which is fine.  If not,
+     it'll make the correct test.  */
+  return ((get_frame_type (thisframe) == SIGTRAMP_FRAME) || chain != 0);
+}
+/* Return the chain-pointer for FRAME.  In the case of the i386, the
+   frame's nominal address is the address of a 4-byte word containing
+   the calling frame's address.  */
+static CORE_ADDR
+i386_cygwin_frame_chain (struct frame_info *frame)
+{
+  if (pc_in_dummy_frame (get_frame_pc (frame)))
+    return get_frame_base (frame);
+
+  if (get_frame_type (frame) == SIGTRAMP_FRAME
+      || i386_frameless_signal_p (frame))
+    return get_frame_base (frame);
+
+  return read_memory_unsigned_integer (get_frame_base (frame), 4);
+}
+
+static void
+i386_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  tdep->struct_return = reg_struct_return;
+  set_gdbarch_deprecated_frame_chain (gdbarch, i386_cygwin_frame_chain);
+  set_gdbarch_deprecated_frame_chain_valid (gdbarch, i386_cygwin_frame_chain_valid);
+}
+
+static enum gdb_osabi
+i386_cygwin_osabi_sniffer (bfd * abfd)
+{ 
+  char *target_name = bfd_get_target (abfd);
+
+  /* Interix also uses pei-i386. 
+     We need a way to distinguish between the two. */
+  if (strcmp (target_name, "pei-i386") == 0)
+    return GDB_OSABI_CYGWIN;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
+void
+_initialize_i386_cygwin_tdep (void)
+{
+  gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
+                                  i386_cygwin_osabi_sniffer);
+
+  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_CYGWIN,
+                          i386_cygwin_init_abi);
+}
diff --git a/gdb/infttrace.h b/gdb/infttrace.h
new file mode 100644 (file)
index 0000000..d3330e3
--- /dev/null
@@ -0,0 +1,28 @@
+/* Low level Unix child interface to ttrace, for GDB when running under HP-UX.
+
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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.
+
+   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.  */
+
+#ifndef INFTTRACE_H
+#define INFTTRACE_H
+
+extern int parent_attach_all (int, PTRACE_ARG3_TYPE, int);
+extern pid_t hppa_switched_threads (pid_t gdb_pid);
+
+#endif
diff --git a/gdb/mi/mi-cmd-file.c b/gdb/mi/mi-cmd-file.c
new file mode 100644 (file)
index 0000000..eb1d67a
--- /dev/null
@@ -0,0 +1,67 @@
+/* MI Command Set - breakpoint and watchpoint commands.
+   Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
+   Contributed by Cygnus Solutions (a Red Hat company).
+
+   This file is part of GDB.
+
+   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.
+
+   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 "defs.h"
+#include "mi-cmds.h"
+#include "mi-getopt.h"
+#include "ui-out.h"
+#include "symtab.h"
+#include "source.h"
+
+/* Return to the client the absolute path and line number of the 
+   current file being executed. */
+
+enum mi_cmd_result
+mi_cmd_file_list_exec_source_file(char *command, char **argv, int argc)
+{
+  struct symtab_and_line st;
+  int optind = 0;
+  char *optarg;
+  
+  if ( !mi_valid_noargs("mi_cmd_file_list_exec_source_file", argc, argv) )
+    error ("mi_cmd_file_list_exec_source_file: Usage: No args");
+
+  
+  /* Set the default file and line, also get them */
+  set_default_source_symtab_and_line();
+  st = get_current_source_symtab_and_line();
+
+  /* We should always get a symtab. 
+     Apparently, filename does not need to be tested for NULL.
+     The documentation in symtab.h suggests it will always be correct */
+  if (!st.symtab)
+    error ("mi_cmd_file_list_exec_source_file: No symtab");
+
+  /* Extract the fullname if it is not known yet */
+  if (st.symtab->fullname == NULL)
+    symtab_to_filename (st.symtab);
+
+  /* We may not be able to open the file (not available). */
+  if (st.symtab->fullname == NULL)
+    error ("mi_cmd_file_list_exec_source_file: File not found");
+
+  /* Print to the user the line, filename and fullname */
+  ui_out_field_int (uiout, "line", st.line);
+  ui_out_field_string (uiout, "file", st.symtab->filename);
+  ui_out_field_string (uiout, "fullname", st.symtab->fullname);
+
+  return MI_CMD_DONE;
+}
diff --git a/gdb/testsuite/gdb.arch/e500-abi.c b/gdb/testsuite/gdb.arch/e500-abi.c
new file mode 100644 (file)
index 0000000..e215612
--- /dev/null
@@ -0,0 +1,106 @@
+#include <spe.h>
+
+/* Test PowerPC SPU extensions.  */
+
+#define vector __attribute__((vector_size(8)))
+
+vector unsigned short f_vec;
+vector short g_vec;
+vector float h_vec;
+vector float i_vec;
+vector unsigned int l_vec;
+vector int m_vec;
+vector int n_vec;
+
+/* dummy variables used in the testfile */
+vector unsigned int a_vec_d = {1, 1};
+vector int b_vec_d = {0, 0};
+vector float c_vec_d = {1.0, 1.0};
+vector unsigned int d_vec_d = {0, 0};
+vector int e_vec_d = {1, 1};
+vector unsigned short f_vec_d = {1, 1, 1, 1};
+vector short g_vec_d = {1, 1, 1, 1};
+vector float h_vec_d = {1.0, 1.0};
+vector float i_vec_d = {2.0, 2.0};
+vector unsigned int l_vec_d = {0, 0};
+vector int m_vec_d = {0, 0};
+
+
+vector int
+vec_func (vector unsigned int a_vec_f,
+          vector int b_vec_f,
+          vector float c_vec_f,
+          vector unsigned int d_vec_f,
+          vector int e_vec_f,
+          vector unsigned short f_vec_f,
+          vector short g_vec_f,
+          vector float h_vec_f,
+          vector float i_vec_f,
+          vector unsigned int l_vec_f,
+          vector int m_vec_f) 
+{
+  vector int n_vec;
+
+
+  int x,y,z;
+  x = 2;
+  y = 3;
+  z = x + y;
+  z++;
+  n_vec = __ev_and(a_vec_f, b_vec_f);
+  n_vec = __ev_or(c_vec_f, d_vec_f);
+  n_vec = __ev_or(e_vec_f, f_vec_f);
+  n_vec = __ev_and(g_vec_f, h_vec_f);
+  n_vec = __ev_and(i_vec_f, l_vec_f);
+  n_vec = __ev_or(m_vec_f, a_vec_f);
+
+  return n_vec;
+}
+
+void marker(void) {};
+
+int
+main (void)
+{
+  vector unsigned int a_vec;
+  vector int b_vec;
+  vector float c_vec;
+  vector unsigned int d_vec;
+  vector int e_vec;
+
+  vector int res_vec;
+
+  a_vec = (vector unsigned int)__ev_create_u64 ((uint64_t) 55);
+  b_vec = __ev_create_s64 ((int64_t) 66);
+  c_vec = (vector float) __ev_create_fs (3.14F, 2.18F);
+  d_vec = (vector unsigned int) __ev_create_u32 ((uint32_t) 5, (uint32_t) 4);
+  e_vec = (vector int) __ev_create_s32 ((int32_t) 5, (int32_t) 6);
+  f_vec = (vector unsigned short) __ev_create_u16 ((uint16_t) 6, (uint16_t) 6, (uint16_t) 7, (uint16_t) 1);
+  g_vec = (vector short) __ev_create_s16 ((int16_t) 6, (int16_t) 6, (int16_t) 7, (int16_t) 9);
+  h_vec = (vector float) __ev_create_sfix32_fs (3.0F, 2.0F);
+  i_vec = (vector float) __ev_create_ufix32_fs (3.0F, 2.0F);
+  l_vec = (vector unsigned int) __ev_create_ufix32_u32 (3U, 5U);
+  m_vec = (vector int) __ev_create_sfix32_s32 (6, 9);
+
+  marker ();
+
+#if 0
+/* This line is useful for cut-n-paste from a gdb session. */
+vec_func(a_vec,b_vec,c_vec,d_vec,e_vec,f_vec,g_vec,h_vec,i_vec,l_vec,m_vec)
+#endif
+
+  res_vec = vec_func (a_vec,  /* goes in r3 */
+                      b_vec,  /* goes in r4 */
+                      c_vec,  /* goes in r5 */
+                      d_vec,  /* goes in r6 */
+                      e_vec,  /* goes in r7 */
+                      f_vec,  /* goes in r8 */
+                      g_vec,  /* goes in r9 */
+                      h_vec,  /* goes in r10 */
+                      i_vec,  /* goes in stack */
+                      l_vec,  /* goes in stack */
+                      m_vec);  /* goes in stack */
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/e500-abi.exp b/gdb/testsuite/gdb.arch/e500-abi.exp
new file mode 100644 (file)
index 0000000..0d11ad3
--- /dev/null
@@ -0,0 +1,90 @@
+# Copyright 2003 Free Software Foundation, Inc.
+#
+# 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.
+#
+# 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.
+#
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+#
+
+# Tests for Powerpc e500 ABI
+
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+#
+# This file uses e500-abi.c for input.
+#
+
+set prms_id 0
+set bug_id 0
+
+if ![istarget "powerpc-*eabispe"] then {
+    verbose "Skipping e500 abi tests."
+    return
+}
+
+set testfile "e500-abi"
+set binfile ${objdir}/${subdir}/${testfile}
+
+set src1 ${srcdir}/${subdir}/${testfile}.c
+
+if  { [gdb_compile ${src1} ${binfile} executable {debug additional_flags=-w}] != "" } {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+#
+# Run to `main' where we begin our tests.
+#
+
+if ![runto_main] then {
+    gdb_suppress_tests
+}
+
+gdb_test "b marker" "Breakpoint 2 at.*file.*e500-abi.c, line \[0-9\]+." "break marker"
+gdb_test "continue" "Breakpoint 2.*marker.*e500-abi.c.*" "continue to marker"
+gdb_test "finish" "Run till exit from .0.*marker.*at.*e500-abi.c.*main \\(\\) at.*e500-abi.c.*res_vec = vec_func \\(a_vec,.*goes in r3.*" "back to main (1)"
+
+# now all the arguments of vec_func are initialized
+
+set pattern "vec_func .a_vec_f=.0, 55., b_vec_f=.0, 66., c_vec_f=.3.14.*2.18.*, d_vec_f=.5, 4., e_vec_f=.5, 6., f_vec_f=.6, 6, 7, 1., g_vec_f=.6, 6, 7, 9., h_vec_f=.3, 2., i_vec_f=.3, 2., l_vec_f=.3, 5., m_vec_f=.6, 9.."
+
+set pattern1 $pattern
+append pattern1 " at.*e500-abi.c.*x = 2;"
+
+# Now let's call the function.  This function has > 8 args,
+# the last ones will go on the stack.
+gdb_test "p vec_func(a_vec,b_vec,c_vec,d_vec,e_vec,f_vec,g_vec,h_vec,i_vec,l_vec,m_vec)" \
+".\[0-9\]+ = .6, 63." "call inferior function with vectors (1) "
+
+# Let's call the function again with dummy arguments.  This is to clean
+# up the contents of the ev registers before the next call.
+gdb_test "p vec_func(a_vec_d,b_vec_d,c_vec_d,d_vec_d,e_vec_d,f_vec_d,g_vec_d,h_vec_d,i_vec_d,l_vec_d,m_vec_d)" \
+".\[0-9\]+ = .1, 1." "call inferior function with vectors (2) "
+
+# Let's step into the function, to see if the args are printed correctly.
+gdb_test "step" \
+  $pattern1 \
+  "step into vec_func"
+
+# Let's see if the result is returned correctly.
+gdb_test "finish" \
+  "Run till exit from .0.* at.*e500-abi.c.*main.*res_vec = vec_func .a_vec,.*goes in r3.*Value returned is.*= .6, 63." \
+  "vector value returned correctly"
diff --git a/gdb/testsuite/gdb.arch/e500-regs.c b/gdb/testsuite/gdb.arch/e500-regs.c
new file mode 100644 (file)
index 0000000..bae5f39
--- /dev/null
@@ -0,0 +1,38 @@
+#include <spe.h>
+#include <stdio.h>
+
+#define vector __attribute__((vector_size(8)))
+
+
+vector int
+vector_fun (vector int a, vector int b)
+{
+  vector int c;
+  a = (vector int) __ev_create_s32 (2, 2);
+  b = (vector int) __ev_create_s32 (3, 3);
+
+  c = __ev_and (a, b);
+  return c;
+}
+int
+main ()
+{
+  vector int y; 
+  vector int x; 
+  vector int z; 
+  int a;
+
+  /* This line may look unnecessary but we do need it, because we want to
+     have a line to do a next over (so that gdb refetches the registers)
+     and we don't want the code to change any vector registers.
+     The splat operations below modify the VRs,
+     so we don't want to execute them yet.  */
+  a = 9;
+  x = (vector int) __ev_create_s32 (-2, -2);
+  y = (vector int) __ev_create_s32 (1, 1);
+       
+  z = vector_fun (x, y);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/e500-regs.exp b/gdb/testsuite/gdb.arch/e500-regs.exp
new file mode 100644 (file)
index 0000000..9224704
--- /dev/null
@@ -0,0 +1,229 @@
+# Copyright 2003 Free Software Foundation, Inc.
+# 
+# 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.
+# 
+# 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.
+#
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+#
+
+# Tests for Powerpc E500 register setting and fetching
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+#
+# Test the use of registers, especially E500 registers, for Powerpc.
+# This file uses e500-regs.c for input.
+#
+
+set prms_id 0
+set bug_id 0
+
+if ![istarget "powerpc-*eabispe"] then {
+    verbose "Skipping e500 register tests."
+    return
+}
+
+set testfile "e500-regs"
+set binfile ${objdir}/${subdir}/${testfile}
+set src1 ${srcdir}/${subdir}/${testfile}.c
+
+if  { [gdb_compile ${src1} ${binfile} executable {debug additional_flags=-w}] != "" } {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+#
+# Run to `main' where we begin our tests.
+#
+
+if ![runto_main] then {
+    gdb_suppress_tests
+}
+
+# set all the registers integer portions to 1
+for {set i 0} {$i < 32} {incr i 1} {
+        for {set j 0} {$j < 2} {incr j 1} {
+           gdb_test "set \$ev$i.v2_int32\[$j\] = 1" "" "set reg ev$i.v4si.f\[$j\]"
+        }
+}
+
+# Now execute some target code, so that GDB's register cache is flushed.
+
+#gdb_test "next" "" ""
+
+send_gdb "show endian\n"
+gdb_expect {
+    -re "(The target endianness is set automatically .currently )(big|little)( endian.*)$gdb_prompt $" {
+        pass "endianness"
+       set endianness $expect_out(2,string)
+    }
+    -re ".*$gdb_prompt $" {
+       fail "couldn't get endianness"
+    }
+    timeout            { fail "(timeout) endianness" }
+}
+
+# And then read the E500 registers back, to see that
+# a) the register write above worked, and
+# b) the register read (below) also works.
+
+if {$endianness == "big"} {
+set vector_register ".uint64 = 0x100000001, v2_float = .0x0, 0x0., v2_int32 = .0x1, 0x1., v4_int16 = .0x0, 0x1, 0x0, 0x1., v8_int8 = .0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.."
+} else {
+set vector_register ".uint64 = 0x100000001, v2_float = .0x0, 0x0., v2_int32 = .0x1, 0x1., v4_int16 = .0x1, 0x0, 0x1, 0x0., v8_int8 = .0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0.."
+}
+
+for {set i 0} {$i < 32} {incr i 1} {
+        gdb_test "info reg ev$i" "ev$i.*$vector_register" "info reg ev$i"
+}
+
+# Test wether the GPRs are updated accordingly. (GPRs are just the lower
+# 32 bits of the EV registers.)
+
+set general_register "0x1\[ \t\]+1"
+
+for {set i 0} {$i < 32} {incr i 1} {
+        gdb_test "info reg r$i" "r$i.*$general_register" "info reg r$i"
+}
+
+# Now redo the same tests, but using the print command.
+# Note: in LE case, the char array is printed WITHOUT the last character.
+# Gdb treats the terminating null char in the array like the terminating
+# null char in a string and doesn't print it. This is not a failure, but
+# the way gdb works.
+
+if {$endianness == "big"} {
+     set decimal_vector ".uint64 = 4294967297, v2_float = .1.*e-45, 1.*e-45., v2_int32 = .1, 1., v4_int16 = .0, 1, 0, 1., v8_int8 = ..000.000.000.001.000.000.000.001.."
+} else {
+     set decimal_vector ".uint64 = 0x0000000100000001, v2_float = .1.*e-45, 1.*e-45., v2_int32 = .1, 1., v4_int16 = .1, 0, 1, 0., v8_int8 = ..001.000.000.000.001.000.000.000.001.000.000.000.001.000.000.."
+}
+
+for {set i 0} {$i < 32} {incr i 1} {
+        gdb_test "print \$ev$i" ".* = $decimal_vector" "print ev$i"
+}
+
+for {set i 0} {$i < 32} {incr i 1} {
+         set pattern$i ".*ev$i.*"
+         append pattern$i $vector_register
+}
+
+send_gdb "info vector\n"
+gdb_expect_list "info vector" ".*$gdb_prompt $" {
+[$pattern0]
+[$pattern1]
+[$pattern2]
+[$pattern3]
+[$pattern4]
+[$pattern5]
+[$pattern6]
+[$pattern7]
+[$pattern8]
+[$pattern9]
+[$pattern10]
+[$pattern11]
+[$pattern12]
+[$pattern13]
+[$pattern14]
+[$pattern15]
+[$pattern16]
+[$pattern17]
+[$pattern18]
+[$pattern19]
+[$pattern20]
+[$pattern21]
+[$pattern22]
+[$pattern23]
+[$pattern24]
+[$pattern25]
+[$pattern26]
+[$pattern27]
+[$pattern28]
+[$pattern29]
+[$pattern30]
+[$pattern31]
+}
+
+# We must restart everything, because we have set important registers to
+# some unusual values.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+if ![runto_main] then {
+    gdb_suppress_tests
+}
+
+gdb_test "break vector_fun" \
+ "Breakpoint 2 at.*e500-regs.c, line \[0-9\]+\\." \
+ "Set breakpoint at vector_fun"
+
+# Actually it is nuch easier to see these results printed in hex.
+# gdb_test "set output-radix 16" \
+#   "Output radix now set to decimal 16, hex 10, octal 20." \
+#   "Set output radix to hex"
+
+gdb_test "continue" \
+  "Breakpoint 2, vector_fun .a=.-2, -2., b=.1, 1.*e500-regs.c.*ev_create_s32 .2, 2.;" \
+  "continue to vector_fun"
+
+# Do a next over the assignment to vector 'a'. 
+gdb_test "next" ".*b = \\(vector int\\) __ev_create_s32 \\(3, 3\\);" \
+  "next (1)"
+
+# Do a next over the assignment to vector 'b'. 
+gdb_test "next" "c = __ev_and \\(a, b\\);" \
+  "next (2)"
+
+# Now 'a' should be '0x02020202...' and 'b' should be '0x03030303...'
+gdb_test "print/x a" \
+  ".*= .0x2, 0x2." \
+  "print vector parameter a"
+
+gdb_test "print/x b" \
+  ".*= .0x3, 0x3." \
+  "print vector parameter b"
+
+# If we do an 'up' now, and print 'x' and 'y' we should see the values they
+# have in main, not the values they have in vector_fun.
+gdb_test "up" ".1.*main \\(\\) at.*e500-regs.c.*z = vector_fun \\(x, y\\);" \
+  "up to main"
+
+gdb_test "print x" \
+  ".*= .-2, -2." \
+  "print vector x"
+
+gdb_test "print y" \
+  ".*= .1, 1." \
+  "print vector y"
+
+# now go back to vector_func and do a finish, to see if we can print the return
+# value correctly.
+
+gdb_test "down" \
+  ".0  vector_fun \\(a=.2, 2., b=.3, 3.\\) at.*e500-regs.c.*c = __ev_and \\(a, b\\);" \
+  "down to vector_fun"
+
+gdb_test "finish" \
+  "Run till exit from .0  vector_fun \\(a=.2, 2., b=.3, 3.\\) at.*e500-regs.c.*main \\(\\) at.*e500-regs.c.*z = vector_fun \\(x, y\\);.*Value returned is.*= .2, 2." \
+  "finish returned correct value"
+
+
+
diff --git a/gdb/testsuite/gdb.asm/m68hc11.inc b/gdb/testsuite/gdb.asm/m68hc11.inc
new file mode 100644 (file)
index 0000000..90795e3
--- /dev/null
@@ -0,0 +1,49 @@
+       comment "subroutine prologue"
+       .macro gdbasm_enter
+        ldx     _.frame
+       pshx
+       sts     _.frame
+       .endm
+
+       comment "subroutine epilogue"
+       .macro gdbasm_leave
+        pulx
+        stx     _.frame
+       rts
+       .endm
+
+       .macro gdbasm_call subr
+       jsr     \subr
+       .endm
+
+       .macro gdbasm_several_nops
+       nop
+       nop
+       nop
+       nop
+       .endm
+
+       comment "exit (0)"
+       .macro gdbasm_exit0
+        clra
+        clrb
+        wai
+       .endm
+
+       comment "crt0 startup"
+       .macro gdbasm_startup
+        .sect .data
+        .globl _.frame
+_.frame: .word 0
+        .previous
+        lds     #0x2000
+        clr     _.frame
+        clr     _.frame+1
+       .endm
+
+       comment "Declare a data variable"
+       .macro gdbasm_datavar name value
+       .data
+\name:
+       .long   \value
+       .endm
diff --git a/gdb/testsuite/gdb.base/gdb1090.c b/gdb/testsuite/gdb.base/gdb1090.c
new file mode 100644 (file)
index 0000000..cd9e2cd
--- /dev/null
@@ -0,0 +1,48 @@
+/* Test program for multi-register variable.
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of the gdb testsuite.
+
+   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.
+
+   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.
+   This file was written by Michael Elizabeth Chastain (mec@shout.net).  */
+
+struct s_2_by_4
+{
+  int field_0;
+  int field_1;
+};
+
+void marker (struct s_2_by_4 s_whatever)
+{
+  s_whatever = s_whatever;
+  return;
+}
+
+void foo ()
+{
+  /* I want this variable in a register but I can't really force it */
+  register struct s_2_by_4 s24;
+  s24.field_0 = 1170;
+  s24.field_1 = 64701;
+  marker (s24);
+  return;
+}
+
+int main ()
+{
+  foo ();
+}
diff --git a/gdb/testsuite/gdb.base/gdb1090.exp b/gdb/testsuite/gdb.base/gdb1090.exp
new file mode 100644 (file)
index 0000000..20da3b1
--- /dev/null
@@ -0,0 +1,67 @@
+# Copyright 2003 Free Software Foundation, Inc.
+
+# 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.
+# 
+# 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.  
+
+# Tests for PR gdb/1090.
+# 2003-02-23  Michael Chastain <mec@shout.net>
+
+# This file is part of the gdb testsuite.
+
+if $tracelevel then {
+        strace $tracelevel
+        }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "gdb1090"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto marker] then {
+    perror "couldn't run to breakpoint"
+    continue
+} 
+gdb_test "up" ".*foo.*" "up from marker"
+
+send_gdb "print s24\n"
+gdb_expect {
+    -re "\\\$\[0-9\]* = \\{field_0 = 1170, field_1 = 64701\\}\r\n$gdb_prompt $" {
+       pass "print s24"
+    }
+    -re "\\\$\[0-9\]* = \\{field_0 = 1170, field_1 = .*\\}\r\n$gdb_prompt $" {
+       # happens with gcc 2.95.3, which actually puts s24 in registers.
+       # gdb cannot find the second register and prints garbage.
+       kfail "gdb/1090" "print s24"
+    }
+    -re ".*$gdb_prompt $" {
+       fail "print s24"
+    }
+    timeout {
+       fail "print s24 (timeout)"
+    }
+}
diff --git a/gdb/testsuite/gdb.c++/maint.exp b/gdb/testsuite/gdb.c++/maint.exp
new file mode 100644 (file)
index 0000000..6e1da97
--- /dev/null
@@ -0,0 +1,79 @@
+# Copyright 2003 Free Software Foundation Inc.
+
+# 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.
+# 
+# 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.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+
+# This file tests C++-specific maintenance commands and help on those.
+
+# Currently, no source file is used.
+
+if $tracelevel then {
+        strace $tracelevel
+        }
+
+# Test the help messages.
+
+proc test_help {} {
+    gdb_test "help maintenance cplus" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous."
+
+    gdb_test "help maint cp" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous."
+
+    gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous."
+
+    gdb_test "help maint cp first_component" "Print the first class/namespace component of NAME."
+}
+
+# This is used when NAME should contain only a single component.  Be
+# careful to make sure that parentheses get escaped properly.
+proc test_single_component {name} {
+    set matchname [string_to_regexp "$name"]
+    gdb_test "maint cp first_component $name" "$matchname"
+}
+
+proc test_first_component {} {
+    test_single_component "foo"
+    test_single_component "operator<<"
+    test_single_component "operator>>"
+    test_single_component "operator ->"
+    test_single_component "operator()"
+    test_single_component "operator>"
+    test_single_component "operator<"
+    test_single_component "operator ->"
+    test_single_component "operator  ->"
+
+    test_single_component "foo()"
+    test_single_component "foo(int)"
+    test_single_component "foo(X::Y)"
+    test_single_component "foo(X::Y, A::B)"
+    test_single_component "foo(std::basic_streambuf<wchar_t,std::char_traits<wchar_t> >)"
+    test_single_component "operator>(X::Y)"
+
+    gdb_test "maint cp first_component foo::bar" "foo"
+    gdb_test "maint cp first_component foo::bar::baz" "foo"
+    gdb_test "maint cp first_component C<A>::bar" "C<A>"
+    gdb_test "maint cp first_component C<std::basic_streambuf<wchar_t,std::char_traits<wchar_t> > >::bar" "C<std::basic_streambuf<wchar_t,std::char_traits<wchar_t> > >"
+}
+
+gdb_exit
+gdb_start
+
+test_help
+test_first_component
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.gdb/observer.exp b/gdb/testsuite/gdb.gdb/observer.exp
new file mode 100644 (file)
index 0000000..390df8d
--- /dev/null
@@ -0,0 +1,274 @@
+#   Copyright 2003
+#   Free Software Foundation, Inc.
+
+# 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.
+# 
+# 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.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Joel Brobecker (brobecker@gnat.com), derived
+# from xfullpath.exp.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if [is_remote target] {
+    return
+}
+
+if [istarget "m68k*-*-hpux*"] then {
+    # The top-level makefile passes CFLAGS= (no -g) for hp300.  This probably
+    # should be fixed (it is only needed for gcc bootstrapping, not gdb),
+    # but until then.....
+    setup_xfail "*-*-*"
+    fail "cannot test self if compiled without debug info"
+    return -1
+}
+
+proc setup_test { executable } {
+    global gdb_prompt
+    global timeout
+
+    # load yourself into the debugger
+    # This can take a relatively long time, particularly for testing where
+    # the executable is being accessed over a network, or where gdb does not
+    # support partial symbols for a particular target and has to load the
+    # entire symbol table.  Set the timeout to 10 minutes, which should be
+    # adequate for most environments (it *has* timed out with 5 min on a
+    # SPARCstation SLC under moderate load, so this isn't unreasonable).
+    # After gdb is started, set the timeout to 30 seconds for the duration
+    # of this test, and then back to the original value.
+
+    set oldtimeout $timeout
+    set timeout 600
+    verbose "Timeout is now $timeout seconds" 2
+    if {[gdb_load $executable] <0} then {
+       set timeout $oldtimeout
+       verbose "Timeout is now $timeout seconds" 2
+       return -1
+    }
+    set timeout $oldtimeout
+    verbose "Timeout is now $timeout seconds" 2
+
+    # Set a breakpoint at main
+    gdb_test "break captured_main" \
+            "Breakpoint.*at.* file.*, line.*" \
+            "breakpoint in captured_main"
+
+    # run yourself
+    # It may take a very long time for the inferior gdb to start (lynx),
+    # so we bump it back up for the duration of this command.
+    set timeout 600
+
+    set description "run until breakpoint at captured_main"
+    send_gdb "run -nw\n"
+    gdb_expect {
+        -re "Starting program.*Breakpoint \[0-9\]+,.*captured_main .data.* at .*main.c:.*$gdb_prompt $" {
+            pass "$description"
+        }
+        -re "Starting program.*Breakpoint \[0-9\]+,.*captured_main .data.*$gdb_prompt $" {
+            xfail "$description (line numbers scrambled?)"
+        }
+        -re "vfork: No more processes.*$gdb_prompt $" {
+            fail "$description (out of virtual memory)"
+            set timeout $oldtimeout
+            verbose "Timeout is now $timeout seconds" 2
+            return -1
+        }
+        -re ".*$gdb_prompt $" {
+            fail "$description"
+            set timeout $oldtimeout
+            verbose "Timeout is now $timeout seconds" 2
+            return -1
+        }
+        timeout {
+            fail "$description (timeout)"
+        }
+    }
+
+    set timeout $oldtimeout
+    verbose "Timeout is now $timeout seconds" 2
+
+    return 0
+}
+
+proc attach_first_observer { } {
+    gdb_test "set \$first_obs = observer_attach_normal_stop (&observer_test_first_notification_function)" \
+             "" "attach first observer"
+}
+
+proc attach_second_observer { } {
+    gdb_test "set \$second_obs = observer_attach_normal_stop (&observer_test_second_notification_function)" \
+             "" "attach second observer"
+}
+
+proc attach_third_observer { } {
+    gdb_test "set \$third_obs = observer_attach_normal_stop (&observer_test_third_notification_function)" \
+             "" "attach third observer"
+}
+
+proc detach_first_observer { } {
+    gdb_test "call observer_detach_normal_stop (\$first_obs)" \
+             "" "detach first observer"
+}
+
+proc detach_second_observer { } {
+    gdb_test "call observer_detach_normal_stop (\$second_obs)" \
+             "" "detach second observer"
+}
+
+proc detach_third_observer { } {
+    gdb_test "call observer_detach_normal_stop (\$third_obs)" \
+             "" "detach third observer"
+}
+
+proc check_counters { first second third message } {
+    gdb_test "print observer_test_first_observer" \
+             ".\[0-9\]+ =.*$first" \
+             "check first observer counter value ($message)"
+    gdb_test "print observer_test_second_observer" \
+             ".\[0-9\]+ =.*$second" \
+             "check second observer counter value ($message)"
+    gdb_test "print observer_test_third_observer" \
+             ".\[0-9\]+ =.*$third" \
+             "check third observer counter value ($message)"
+}
+
+proc reset_counters { } {
+    gdb_test "set variable observer_test_first_observer = 0" "" \
+             "reset first observer counter"
+    gdb_test "set variable observer_test_second_observer = 0" "" \
+             "reset second observer counter"
+    gdb_test "set variable observer_test_third_observer = 0" "" \
+             "reset third observer counter"
+}
+
+proc test_normal_stop_notifications { first second third message } {
+    reset_counters
+    gdb_test "call observer_notify_normal_stop ()" "" \
+             "sending notification ($message)"
+    check_counters $first $second $third $message
+}
+
+proc test_observer_normal_stop { executable } {
+
+    set setup_result [setup_test $executable]
+    if {$setup_result <0} then {
+        return -1
+    }
+
+    # First, try sending a notification without any observer attached.
+    test_normal_stop_notifications 0 0 0 "no observer"
+
+    # Now, attach one observer, and send a notification.
+    attach_second_observer
+    test_normal_stop_notifications 0 1 0 "one observer"
+
+    # Remove the observer, and send a notification.
+    detach_second_observer
+    test_normal_stop_notifications 0 0 0 "no observer"
+
+    # With a new observer.
+    attach_first_observer
+    test_normal_stop_notifications 1 0 0 "a new observer"
+
+    # With 2 observers.
+    attach_second_observer
+    test_normal_stop_notifications 1 1 0 "2 observers"
+
+    # With 3 observers.
+    attach_third_observer
+    test_normal_stop_notifications 1 1 1 "3 observers"
+
+    # Remove middle observer.
+    detach_second_observer
+    test_normal_stop_notifications 1 0 1 "middle observer removed"
+
+    # Remove first observer.
+    detach_first_observer
+    test_normal_stop_notifications 0 0 1 "first observer removed"
+
+    # Remove last observer.
+    detach_third_observer
+    test_normal_stop_notifications 0 0 0 "last observer removed"
+
+    # Go back to 3 observers, and remove them in a different order...
+    attach_first_observer
+    attach_second_observer
+    attach_third_observer
+    test_normal_stop_notifications 1 1 1 "3 observers again"
+
+    # Remove the third observer.
+    detach_third_observer
+    test_normal_stop_notifications 1 1 0 "third observer removed"
+
+    # Remove the second observer.
+    detach_second_observer
+    test_normal_stop_notifications 1 0 0 "second observer removed"
+
+    # Remove the first observer, no more observers.
+    detach_first_observer
+    test_normal_stop_notifications 0 0 0 "last observer removed"
+
+    return 0
+}
+
+# Find a pathname to a file that we would execute if the shell was asked
+# to run $arg using the current PATH.
+
+proc find_gdb { arg } {
+
+    # If the arg directly specifies an existing executable file, then
+    # simply use it.
+
+    if [file executable $arg] then {
+       return $arg
+    }
+
+    set result [which $arg]
+    if [string match "/" [ string range $result 0 0 ]] then {
+       return $result
+    }
+
+    # If everything fails, just return the unqualified pathname as default
+    # and hope for best.
+
+    return $arg
+}
+
+# Run the test with self.
+# Copy the file executable file in case this OS doesn't like to edit its own
+# text space.
+
+set GDB_FULLPATH [find_gdb $GDB]
+
+# Remove any old copy lying around.
+remote_file host delete x$tool
+
+gdb_start
+set file [remote_download host $GDB_FULLPATH x$tool]
+set result [test_observer_normal_stop $file];
+gdb_exit;
+catch "remote_file host delete $file";
+
+if {$result <0} then {
+    warning "Couldn't test self"
+    return -1
+}
diff --git a/gdb/testsuite/gdb.mi/mi-file.exp b/gdb/testsuite/gdb.mi/mi-file.exp
new file mode 100644 (file)
index 0000000..2ffdcbf
--- /dev/null
@@ -0,0 +1,65 @@
+#   Copyright 1999 Free Software Foundation, Inc.
+
+# 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.
+# 
+# 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.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+#
+# Test essential Machine interface (MI) operations
+#
+# Verify that, using the MI, we can run a simple program and perform basic
+# debugging activities like: insert breakpoints, run the program,
+# step, next, continue until it ends and, last but not least, quit.
+#
+# The goal is not to test gdb functionality, which is done by other tests,
+# but to verify the correct output response to MI operations.
+#
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+set testfile "basics"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DFAKEARGV}] != "" } {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+mi_delete_breakpoints
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load ${binfile}
+
+proc test_tbreak_creation_and_listing {} {
+    global srcfile
+    global srcdir
+    global subdir
+    set srcfilepath [string_to_regexp ${srcdir}/${subdir}/${srcfile}]
+
+    # get the path and absolute path to the current executable
+    mi_gdb_test "111-file-list-exec-source-file" \
+           "111\\\^done,line=\"23\",file=\"${srcfilepath}\",fullname=\"/.*/${srcfile}\"" \
+               "request path info of current source file (${srcfile})"
+}
+
+test_tbreak_creation_and_listing
+
+mi_gdb_exit
+return 0
diff --git a/include/elf/xtensa.h b/include/elf/xtensa.h
new file mode 100644 (file)
index 0000000..394ee41
--- /dev/null
@@ -0,0 +1,87 @@
+/* Xtensa ELF support for BFD.
+   Copyright 2003 Free Software Foundation, Inc.
+   Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   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.
+
+   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.  */
+
+/* This file holds definitions specific to the Xtensa ELF ABI.  */
+
+#ifndef _ELF_XTENSA_H
+#define _ELF_XTENSA_H
+
+#include "elf/reloc-macros.h"
+
+/* Relocations.  */
+START_RELOC_NUMBERS (elf_xtensa_reloc_type)
+     RELOC_NUMBER (R_XTENSA_NONE, 0)
+     RELOC_NUMBER (R_XTENSA_32, 1)
+     RELOC_NUMBER (R_XTENSA_RTLD, 2)
+     RELOC_NUMBER (R_XTENSA_GLOB_DAT, 3)
+     RELOC_NUMBER (R_XTENSA_JMP_SLOT, 4)
+     RELOC_NUMBER (R_XTENSA_RELATIVE, 5)
+     RELOC_NUMBER (R_XTENSA_PLT, 6)
+     RELOC_NUMBER (R_XTENSA_OP0, 8)
+     RELOC_NUMBER (R_XTENSA_OP1, 9)
+     RELOC_NUMBER (R_XTENSA_OP2, 10) 
+     RELOC_NUMBER (R_XTENSA_ASM_EXPAND, 11)
+     RELOC_NUMBER (R_XTENSA_ASM_SIMPLIFY, 12)
+     RELOC_NUMBER (R_XTENSA_GNU_VTINHERIT, 15)
+     RELOC_NUMBER (R_XTENSA_GNU_VTENTRY, 16)
+END_RELOC_NUMBERS (R_XTENSA_max)
+
+/* Processor-specific flags for the ELF header e_flags field.  */
+
+/* Four-bit Xtensa machine type field.  */
+#define EF_XTENSA_MACH                 0x0000000f
+
+/* Various CPU types.  */
+#define E_XTENSA_MACH                  0x00000000
+
+/* Leave bits 0xf0 alone in case we ever have more than 16 cpu types.
+   Highly unlikely, but what the heck.  */
+
+#define EF_XTENSA_XT_INSN              0x00000100
+#define EF_XTENSA_XT_LIT               0x00000200
+
+
+/* Processor-specific dynamic array tags.  */
+
+/* Offset of the table that records the GOT location(s).  */
+#define DT_XTENSA_GOT_LOC_OFF          0x70000000
+
+/* Number of entries in the GOT location table.  */
+#define DT_XTENSA_GOT_LOC_SZ           0x70000001
+
+
+/* Definitions for instruction and literal property tables.  The
+   instruction tables for ".gnu.linkonce.t.*" sections are placed in
+   the following sections:
+
+   instruction tables: .gnu.linkonce.x.*
+   literal tables:     .gnu.linkonce.p.*
+*/
+
+#define XTENSA_INSN_SEC_NAME ".xt.insn"
+#define XTENSA_LIT_SEC_NAME  ".xt.lit"
+
+typedef struct property_table_entry_t
+{
+  bfd_vma address;
+  bfd_vma size;
+} property_table_entry;
+
+#endif /* _ELF_XTENSA_H */
diff --git a/include/xtensa-config.h b/include/xtensa-config.h
new file mode 100644 (file)
index 0000000..b47cbd7
--- /dev/null
@@ -0,0 +1,64 @@
+/* Xtensa configuration settings.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
+
+   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, 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef XTENSA_CONFIG_H
+#define XTENSA_CONFIG_H
+
+/* The macros defined here match those with the same names in the Xtensa
+   compile-time HAL (Hardware Abstraction Layer).  Please refer to the
+   Xtensa System Software Reference Manual for documentation of these
+   macros.  */
+
+#define XCHAL_HAVE_BE                  1
+#define XCHAL_HAVE_DENSITY             1
+#define XCHAL_HAVE_MAC16               0
+#define XCHAL_HAVE_MUL16               0
+#define XCHAL_HAVE_MUL32               0
+#define XCHAL_HAVE_DIV32               0
+#define XCHAL_HAVE_NSA                 1
+#define XCHAL_HAVE_MINMAX              0
+#define XCHAL_HAVE_SEXT                        0
+#define XCHAL_HAVE_LOOPS               1
+#define XCHAL_HAVE_BOOLEANS            0
+#define XCHAL_HAVE_FP                  0
+#define XCHAL_HAVE_FP_DIV              0
+#define XCHAL_HAVE_FP_RECIP            0
+#define XCHAL_HAVE_FP_SQRT             0
+#define XCHAL_HAVE_FP_RSQRT            0
+#define XCHAL_HAVE_WINDOWED            1
+
+#define XCHAL_ICACHE_SIZE              8192
+#define XCHAL_DCACHE_SIZE              8192
+#define XCHAL_ICACHE_LINESIZE          16
+#define XCHAL_DCACHE_LINESIZE          16
+#define XCHAL_ICACHE_LINEWIDTH         4
+#define XCHAL_DCACHE_LINEWIDTH         4
+#define XCHAL_DCACHE_IS_WRITEBACK      0
+
+#define XCHAL_HAVE_MMU                 1
+#define XCHAL_MMU_MIN_PTE_PAGE_SIZE    12
+
+#define XCHAL_HAVE_DEBUG               1
+#define XCHAL_NUM_IBREAK               2
+#define XCHAL_NUM_DBREAK               2
+#define XCHAL_DEBUGLEVEL               4
+
+#define XCHAL_EXTRA_SA_SIZE             0
+#define XCHAL_EXTRA_SA_ALIGN            1
+
+#endif /* !XTENSA_CONFIG_H */
diff --git a/include/xtensa-isa-internal.h b/include/xtensa-isa-internal.h
new file mode 100644 (file)
index 0000000..d2244c5
--- /dev/null
@@ -0,0 +1,114 @@
+/* Internal definitions for configurable Xtensa ISA support.
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   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.
+
+   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.  */
+
+/* Use the statically-linked version for the GNU tools.  */
+#define STATIC_LIBISA 1
+
+#define ISA_INTERFACE_VERSION 3
+
+struct config_struct
+{
+    char *param_name;
+    char *param_value;
+};
+
+/* Encode/decode function types for immediate operands.  */
+typedef uint32 (*xtensa_immed_decode_fn) (uint32);
+typedef xtensa_encode_result (*xtensa_immed_encode_fn) (uint32 *);
+
+/* Field accessor function types.  */
+typedef uint32 (*xtensa_get_field_fn) (const xtensa_insnbuf);
+typedef void (*xtensa_set_field_fn) (xtensa_insnbuf, uint32);
+
+/* PC-relative relocation function types.  */
+typedef uint32 (*xtensa_do_reloc_fn) (uint32, uint32);
+typedef uint32 (*xtensa_undo_reloc_fn) (uint32, uint32);
+
+/* Instruction decode function type.  */
+typedef int (*xtensa_insn_decode_fn) (const xtensa_insnbuf);
+
+/* Instruction encoding template function type (each of these functions
+   returns a constant template; they exist only to make it easier for the
+   TIE compiler to generate endian-independent DLLs).  */
+typedef xtensa_insnbuf (*xtensa_encoding_template_fn) (void);
+
+
+typedef struct xtensa_operand_internal_struct
+{
+  char *operand_kind;                  /* e.g., "a", "f", "i", "l"....  */
+  char inout;                          /* '<', '>', or '='.  */
+  char isPCRelative;                   /* Is this a PC-relative offset?  */
+  xtensa_get_field_fn get_field;       /* Get encoded value of the field.  */
+  xtensa_set_field_fn set_field;       /* Set field with an encoded value.  */
+  xtensa_immed_encode_fn encode;       /* Encode the operand value.  */
+  xtensa_immed_decode_fn decode;       /* Decode the value from the field.  */
+  xtensa_do_reloc_fn do_reloc;         /* Perform a PC-relative relocation.  */
+  xtensa_undo_reloc_fn undo_reloc;     /* Undo a PC-relative relocation.  */
+} xtensa_operand_internal;
+
+
+typedef struct xtensa_iclass_internal_struct
+{
+  int num_operands;                    /* Size of "operands" array.  */
+  xtensa_operand_internal **operands;  /* Array of operand structures.  */
+} xtensa_iclass_internal;
+
+
+typedef struct xtensa_opcode_internal_struct
+{
+  const char *name;                    /* Opcode mnemonic.  */
+  int length;                          /* Length in bytes of the insn.  */
+  xtensa_encoding_template_fn template;        /* Fn returning encoding template.  */
+  xtensa_iclass_internal *iclass;      /* Iclass for this opcode.  */
+} xtensa_opcode_internal;
+
+
+typedef struct opname_lookup_entry_struct
+{
+  const char *key;                     /* Opcode mnemonic.  */
+  xtensa_opcode opcode;                        /* Internal opcode number.  */
+} opname_lookup_entry;
+
+
+typedef struct xtensa_isa_internal_struct
+{
+  int is_big_endian;                   /* Endianness.  */
+  int insn_size;                       /* Maximum length in bytes.  */
+  int insnbuf_size;                    /* Number of insnbuf_words.  */
+  int num_opcodes;                     /* Total number for all modules.  */
+  xtensa_opcode_internal **opcode_table;/* Indexed by internal opcode #.  */
+  int num_modules;                     /* Number of modules (DLLs) loaded.  */
+  int *module_opcode_base;             /* Starting opcode # for each module.  */
+  xtensa_insn_decode_fn *module_decode_fn; /* Decode fn for each module.  */
+  opname_lookup_entry *opname_lookup_table; /* Lookup table for each module.  */
+  struct config_struct *config;                /* Table of configuration parameters.  */
+  int has_density;                     /* Is density option available?  */
+} xtensa_isa_internal;
+
+
+typedef struct xtensa_isa_module_struct
+{
+  const int (*get_num_opcodes_fn) (void);
+  xtensa_opcode_internal **(*get_opcodes_fn) (void);
+  int (*decode_insn_fn) (const xtensa_insnbuf);
+  struct config_struct *(*get_config_table_fn) (void);
+} xtensa_isa_module;
+
+extern xtensa_isa_module xtensa_isa_modules[];
+
diff --git a/include/xtensa-isa.h b/include/xtensa-isa.h
new file mode 100644 (file)
index 0000000..54f750c
--- /dev/null
@@ -0,0 +1,230 @@
+/* Interface definition for configurable Xtensa ISA support.
+   Copyright 2003 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   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.
+
+   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.  */
+
+#ifndef XTENSA_LIBISA_H
+#define XTENSA_LIBISA_H
+
+/* Use the statically-linked version for the GNU tools.  */
+#define STATIC_LIBISA 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef uint32
+#define uint32 unsigned int
+#endif
+
+/* This file defines the interface to the Xtensa ISA library.  This library
+   contains most of the ISA-specific information for a particular Xtensa
+   processor.  For example, the set of valid instructions, their opcode
+   encodings and operand fields are all included here.  To support Xtensa's
+   configurability and user-defined instruction extensions (i.e., TIE), the
+   library is initialized by loading one or more dynamic libraries; only a
+   small set of interface code is present in the statically-linked portion
+   of the library.
+
+   This interface basically defines four abstract data types.
+
+   . an instruction buffer - for holding the raw instruction bits
+   . ISA info - information about the ISA as a whole
+   . opcode info - information about individual instructions
+   . operand info - information about specific instruction operands
+
+   It would be nice to implement these as classes in C++, but the library is
+   implemented in C to match the expectations of the GNU tools.
+   Instead, the interface defines a set of functions to access each data
+   type.  With the exception of the instruction buffer, the internal
+   representations of the data structures are hidden.  All accesses must be
+   made through the functions defined here.  */
+
+typedef void* xtensa_isa;
+typedef void* xtensa_operand;
+
+
+/* Opcodes are represented here using sequential integers beginning with 0.
+   The specific value used for a particular opcode is only fixed for a
+   particular instantiation of an xtensa_isa structure, so these values
+   should only be used internally.  */
+typedef int xtensa_opcode;
+
+/* Define a unique value for undefined opcodes ("static const int" doesn't
+   seem to work for this because EGCS 1.0.3 on i686-Linux without -O won't
+   allow it to be used as an initializer).  */
+#define XTENSA_UNDEFINED -1
+
+
+typedef int libisa_module_specifier;
+
+extern xtensa_isa xtensa_isa_init (void);
+
+
+/* Instruction buffers.  */
+
+typedef uint32 xtensa_insnbuf_word;
+typedef xtensa_insnbuf_word *xtensa_insnbuf;
+
+/* Get the size in words of the xtensa_insnbuf array.  */
+extern int xtensa_insnbuf_size (xtensa_isa); 
+
+/* Allocate (with malloc) an xtensa_insnbuf of the right size.  */
+extern xtensa_insnbuf xtensa_insnbuf_alloc (xtensa_isa);
+
+/* Release (with free) an xtensa_insnbuf of the right size.  */
+extern void xtensa_insnbuf_free (xtensa_insnbuf);
+
+/* Inward and outward conversion from memory images (byte streams) to our
+   internal instruction representation.  */
+extern void xtensa_insnbuf_to_chars (xtensa_isa, const xtensa_insnbuf,
+                                    char *);
+
+extern void xtensa_insnbuf_from_chars (xtensa_isa, xtensa_insnbuf,
+                                      const char *);
+
+
+/* ISA information.  */
+
+/* Load the ISA information from a shared library.  If successful, this returns
+   a value which identifies the ISA for use in subsequent calls to the ISA
+   library; otherwise, it returns NULL.  Multiple ISAs can be loaded to support
+   heterogeneous multiprocessor systems.  */
+extern xtensa_isa xtensa_load_isa (libisa_module_specifier);
+
+/* Extend an existing set of ISA information by loading an additional shared
+   library of ISA information.  This is primarily intended for loading TIE
+   extensions.  If successful, the return value is non-zero.  */
+extern int xtensa_extend_isa (xtensa_isa, libisa_module_specifier);
+
+/* The default ISA.  This variable is set automatically to the ISA most
+   recently loaded and is provided as a convenience.  An exception is the GNU
+   opcodes library, where there is a fixed interface that does not allow
+   passing the ISA as a parameter and the ISA must be taken from this global
+   variable.  (Note: Since this variable is just a convenience, it is not
+   exported when libisa is built as a DLL, due to the hassle of dealing with
+   declspecs.)  */
+extern xtensa_isa xtensa_default_isa;
+
+
+/* Deallocate an xtensa_isa structure.  */
+extern void xtensa_isa_free (xtensa_isa);
+
+/* Get the maximum instruction size in bytes.  */
+extern int xtensa_insn_maxlength (xtensa_isa); 
+
+/* Get the total number of opcodes for this processor.  */
+extern int xtensa_num_opcodes (xtensa_isa);
+
+/* Translate a mnemonic name to an opcode.  Returns XTENSA_UNDEFINED if
+   the name is not a valid opcode mnemonic.  */
+extern xtensa_opcode xtensa_opcode_lookup (xtensa_isa, const char *);
+
+/* Decode a binary instruction buffer.  Returns the opcode or
+   XTENSA_UNDEFINED if the instruction is illegal.  */
+extern xtensa_opcode xtensa_decode_insn (xtensa_isa, const xtensa_insnbuf);
+
+
+/* Opcode information.  */
+
+/* Set the opcode field(s) in a binary instruction buffer.  The operand
+   fields are set to zero.  */
+extern void xtensa_encode_insn (xtensa_isa, xtensa_opcode, xtensa_insnbuf);
+
+/* Get the mnemonic name for an opcode.  */
+extern const char * xtensa_opcode_name (xtensa_isa, xtensa_opcode);
+
+/* Find the length (in bytes) of an instruction.  */
+extern int xtensa_insn_length (xtensa_isa, xtensa_opcode);
+
+/* Find the length of an instruction by looking only at the first byte.  */
+extern int xtensa_insn_length_from_first_byte (xtensa_isa, char);
+
+/* Find the number of operands for an instruction.  */
+extern int xtensa_num_operands (xtensa_isa, xtensa_opcode);
+
+/* Get the information about operand number "opnd" of a particular opcode.  */
+extern xtensa_operand xtensa_get_operand (xtensa_isa, xtensa_opcode, int);
+
+/* Operand information.  */
+
+/* Find the kind of operand.  There are three possibilities:
+   1) PC-relative immediates (e.g., "l", "L").  These can be identified with
+      the xtensa_operand_isPCRelative function.
+   2) non-PC-relative immediates ("i").
+   3) register-file short names (e.g., "a", "b", "m" and others defined
+      via TIE).  */
+extern char * xtensa_operand_kind (xtensa_operand);
+
+/* Check if an operand is an input ('<'), output ('>'), or inout ('=')
+   operand.  Note: The output operand of a conditional assignment
+   (e.g., movnez) appears here as an inout ('=') even if it is declared
+   in the TIE code as an output ('>'); this allows the compiler to
+   properly handle register allocation for conditional assignments.  */
+extern char xtensa_operand_inout (xtensa_operand);
+
+/* Get and set the raw (encoded) value of the field for the specified
+   operand.  The "set" function does not check if the value fits in the
+   field; that is done by the "encode" function below.  */
+extern uint32 xtensa_operand_get_field (xtensa_operand, const xtensa_insnbuf);
+
+extern void xtensa_operand_set_field (xtensa_operand, xtensa_insnbuf, uint32);
+
+
+/* Encode and decode operands.  The raw bits in the operand field
+   may be encoded in a variety of different ways.  These functions hide the
+   details of that encoding.  The encode function has a special return type
+   (xtensa_encode_result) to indicate success or the reason for failure; the
+   encoded value is returned through the argument pointer.  The decode function
+   has no possibility of failure and returns the decoded value.  */
+
+typedef enum
+{
+  xtensa_encode_result_ok,
+  xtensa_encode_result_align,
+  xtensa_encode_result_not_in_table,
+  xtensa_encode_result_too_low,
+  xtensa_encode_result_too_high,
+  xtensa_encode_result_not_ok,
+  xtensa_encode_result_max = xtensa_encode_result_not_ok
+} xtensa_encode_result;
+
+extern xtensa_encode_result xtensa_operand_encode (xtensa_operand, uint32 *);
+
+extern uint32 xtensa_operand_decode (xtensa_operand, uint32);
+
+
+/* For PC-relative offset operands, the interpretation of the offset may vary
+   between opcodes, e.g., is it relative to the current PC or that of the next
+   instruction?  The following functions are defined to perform PC-relative
+   relocations and to undo them (as in the disassembler).  The first function
+   takes the desired address and the PC of the current instruction and returns
+   the unencoded value to be stored in the offset field.  The second function
+   takes the unencoded offset value and the current PC and returns the address.
+   Note that these functions do not replace the encode/decode functions; the
+   operands must be encoded/decoded separately.  */
+
+extern int xtensa_operand_isPCRelative (xtensa_operand);
+
+extern uint32 xtensa_operand_do_reloc (xtensa_operand, uint32, uint32);
+
+extern uint32 xtensa_operand_undo_reloc        (xtensa_operand, uint32, uint32);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XTENSA_LIBISA_H */
diff --git a/libiberty/mempcpy.c b/libiberty/mempcpy.c
new file mode 100644 (file)
index 0000000..b0dccfa
--- /dev/null
@@ -0,0 +1,48 @@
+/* Implement the mempcpy function.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Written by Kaveh R. Ghazi <ghazi@caip.rutgers.edu>.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/*
+
+@deftypefn Supplemental void* mempcpy (void *@var{out}, const void *@var{in}, size_t @var{length})
+
+Copies @var{length} bytes from memory region @var{in} to region
+@var{out}.  Returns a pointer to @var{out} + @var{length}.
+
+@end deftypefn
+
+*/
+
+#include <ansidecl.h>
+#ifdef ANSI_PROTOTYPES
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+extern PTR memcpy PARAMS ((PTR, const PTR, size_t));
+
+PTR
+mempcpy (dst, src, len)
+     PTR dst;
+     const PTR src;
+     size_t len;
+{
+  return (char *) memcpy (dst, src, len) + len;
+}
diff --git a/libiberty/stpcpy.c b/libiberty/stpcpy.c
new file mode 100644 (file)
index 0000000..a589642
--- /dev/null
@@ -0,0 +1,49 @@
+/* Implement the stpcpy function.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Written by Kaveh R. Ghazi <ghazi@caip.rutgers.edu>.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/*
+
+@deftypefn Supplemental char* stpcpy (char *@var{dst}, const char *@var{src})
+
+Copies the string @var{src} into @var{dst}.  Returns a pointer to
+@var{dst} + strlen(@var{src}).
+
+@end deftypefn
+
+*/
+
+#include <ansidecl.h>
+#ifdef ANSI_PROTOTYPES
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+extern size_t strlen PARAMS ((const char *));
+extern PTR memcpy PARAMS ((PTR, const PTR, size_t));
+
+char *
+stpcpy (dst, src)
+     char *dst;
+     const char *src;
+{
+  const size_t len = strlen (src);
+  return (char *) memcpy (dst, src, len + 1) + len;
+}
diff --git a/libiberty/stpncpy.c b/libiberty/stpncpy.c
new file mode 100644 (file)
index 0000000..cb67b4d
--- /dev/null
@@ -0,0 +1,54 @@
+/* Implement the stpncpy function.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Written by Kaveh R. Ghazi <ghazi@caip.rutgers.edu>.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/*
+
+@deftypefn Supplemental char* stpncpy (char *@var{dst}, const char *@var{src}, size_t @var{len})
+
+Copies the string @var{src} into @var{dst}, copying exactly @var{len}
+and padding with zeros if necessary.  If @var{len} < strlen(@var{src})
+then return @var{dst} + @var{len}, otherwise returns @var{dst} +
+strlen(@var{src}).
+
+@end deftypefn
+
+*/
+
+#include <ansidecl.h>
+#ifdef ANSI_PROTOTYPES
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+extern size_t strlen PARAMS ((const char *));
+extern char *strncpy PARAMS ((char *, const char *, size_t));
+
+char *
+stpncpy (dst, src, len)
+     char *dst;
+     const char *src;
+     size_t len;
+{
+  size_t n = strlen (src);
+  if (n > len)
+    n = len;
+  return strncpy (dst, src, len) + n;
+}
diff --git a/opcodes/xtensa-dis.c b/opcodes/xtensa-dis.c
new file mode 100644 (file)
index 0000000..bf5f5bf
--- /dev/null
@@ -0,0 +1,526 @@
+/* xtensa-dis.c.  Disassembly functions for Xtensa.
+   Copyright 2003 Free Software Foundation, Inc.
+   Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com)
+
+   This file is part of GDB, GAS, and the GNU binutils.
+
+   GDB, GAS, and the GNU binutils are free software; you can redistribute
+   them and/or modify them under the terms of the GNU General Public
+   License as published by the Free Software Foundation; either version 2,
+   or (at your option) any later version.
+
+   GDB, GAS, and the GNU binutils are distributed in the hope that they
+   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 file; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <string.h>
+#include "xtensa-isa.h"
+#include "ansidecl.h"
+#include "sysdep.h"
+#include "dis-asm.h"
+
+#include <setjmp.h>
+
+#ifndef MAX
+#define MAX(a,b) (a > b ? a : b)
+#endif
+
+static char* state_names[256] =
+{
+  "lbeg",                      /* 0 */
+  "lend",                      /* 1 */
+  "lcount",                    /* 2 */
+  "sar",                       /* 3 */
+  "br",                                /* 4 */
+
+  "reserved_5",                        /* 5 */
+  "reserved_6",                        /* 6 */
+  "reserved_7",                        /* 7 */
+
+  "av",                                /* 8 */
+  "avh",                       /* 9 */
+  "bv",                                /* 10 */
+  "sav",                       /* 11 */
+  "scompare1",                 /* 12 */
+
+  "reserved_13",               /* 13 */
+  "reserved_14",               /* 14 */
+  "reserved_15",               /* 15 */
+
+  "acclo",                     /* 16 */
+  "acchi",                     /* 17 */
+
+  "reserved_18",               /* 18 */
+  "reserved_19",               /* 19 */
+  "reserved_20",               /* 20 */
+  "reserved_21",               /* 21 */
+  "reserved_22",               /* 22 */
+  "reserved_23",               /* 23 */
+  "reserved_24",               /* 24 */
+  "reserved_25",               /* 25 */
+  "reserved_26",               /* 26 */
+  "reserved_27",               /* 27 */
+  "reserved_28",               /* 28 */
+  "reserved_29",               /* 29 */
+  "reserved_30",               /* 30 */
+  "reserved_31",               /* 31 */
+
+  "mr0",                       /* 32 */
+  "mr1",                       /* 33 */
+  "mr2",                       /* 34 */
+  "mr3",                       /* 35 */
+
+  "reserved_36",               /* 36 */
+  "reserved_37",               /* 37 */
+  "reserved_38",               /* 38 */
+  "reserved_39",               /* 39 */
+  "reserved_40",               /* 40 */
+  "reserved_41",               /* 41 */
+  "reserved_42",               /* 42 */
+  "reserved_43",               /* 43 */
+  "reserved_44",               /* 44 */
+  "reserved_45",               /* 45 */
+  "reserved_46",               /* 46 */
+  "reserved_47",               /* 47 */
+  "reserved_48",               /* 48 */
+  "reserved_49",               /* 49 */
+  "reserved_50",               /* 50 */
+  "reserved_51",               /* 51 */
+  "reserved_52",               /* 52 */
+  "reserved_53",               /* 53 */
+  "reserved_54",               /* 54 */
+  "reserved_55",               /* 55 */
+  "reserved_56",               /* 56 */
+  "reserved_57",               /* 57 */
+  "reserved_58",               /* 58 */
+  "reserved_59",               /* 59 */
+  "reserved_60",               /* 60 */
+  "reserved_61",               /* 61 */
+  "reserved_62",               /* 62 */
+  "reserved_63",               /* 63 */
+
+  "reserved_64",               /* 64 */
+  "reserved_65",               /* 65 */
+  "reserved_66",               /* 66 */
+  "reserved_67",               /* 67 */
+  "reserved_68",               /* 68 */
+  "reserved_69",               /* 69 */
+  "reserved_70",               /* 70 */
+  "reserved_71",               /* 71 */
+
+  "wb",                                /* 72 */
+  "ws",                                /* 73 */
+
+  "reserved_74",               /* 74 */
+  "reserved_75",               /* 75 */
+  "reserved_76",               /* 76 */
+  "reserved_77",               /* 77 */
+  "reserved_78",               /* 78 */
+  "reserved_79",               /* 79 */
+  "reserved_80",               /* 80 */
+  "reserved_81",               /* 81 */
+  "reserved_82",               /* 82 */
+
+  "ptevaddr",                  /* 83 */
+
+  "reserved_84",               /* 84 */
+  "reserved_85",               /* 85 */
+  "reserved_86",               /* 86 */
+  "reserved_87",               /* 87 */
+  "reserved_88",               /* 88 */
+  "reserved_89",               /* 89 */
+
+  "rasid",                     /* 90 */
+  "itlbcfg",                   /* 91 */
+  "dtlbcfg",                   /* 92 */
+
+  "reserved_93",               /* 93 */
+  "reserved_94",               /* 94 */
+  "reserved_95",               /* 95 */
+
+  "ibreakenable",              /* 96 */
+
+  "reserved_97",               /* 97 */
+
+  "cacheattr",                 /* 98 */
+
+  "reserved_99",               /* 99 */
+  "reserved_100",              /* 100 */
+  "reserved_101",              /* 101 */
+  "reserved_102",              /* 102 */
+  "reserved_103",              /* 103 */
+
+  "ddr",                       /* 104 */
+
+  "reserved_105",              /* 105 */
+  "reserved_106",              /* 106 */
+  "reserved_107",              /* 107 */
+  "reserved_108",              /* 108 */
+  "reserved_109",              /* 109 */
+  "reserved_110",              /* 110 */
+  "reserved_111",              /* 111 */
+  "reserved_112",              /* 112 */
+  "reserved_113",              /* 113 */
+  "reserved_114",              /* 114 */
+  "reserved_115",              /* 115 */
+  "reserved_116",              /* 116 */
+  "reserved_117",              /* 117 */
+  "reserved_118",              /* 118 */
+  "reserved_119",              /* 119 */
+  "reserved_120",              /* 120 */
+  "reserved_121",              /* 121 */
+  "reserved_122",              /* 122 */
+  "reserved_123",              /* 123 */
+  "reserved_124",              /* 124 */
+  "reserved_125",              /* 125 */
+  "reserved_126",              /* 126 */
+  "reserved_127",              /* 127 */
+
+  "ibreaka0",                  /* 128 */
+  "ibreaka1",                  /* 129 */
+  "ibreaka2",                  /* 130 */
+  "ibreaka3",                  /* 131 */
+  "ibreaka4",                  /* 132 */
+  "ibreaka5",                  /* 133 */
+  "ibreaka6",                  /* 134 */
+  "ibreaka7",                  /* 135 */
+  "ibreaka8",                  /* 136 */
+  "ibreaka9",                  /* 137 */
+  "ibreaka10",                 /* 138 */
+  "ibreaka11",                 /* 139 */
+  "ibreaka12",                 /* 140 */
+  "ibreaka13",                 /* 141 */
+  "ibreaka14",                 /* 142 */
+  "ibreaka15",                 /* 143 */
+                          
+  "dbreaka0",                  /* 144 */
+  "dbreaka1",                  /* 145 */
+  "dbreaka2",                  /* 146 */
+  "dbreaka3",                  /* 147 */
+  "dbreaka4",                  /* 148 */
+  "dbreaka5",                  /* 149 */
+  "dbreaka6",                  /* 150 */
+  "dbreaka7",                  /* 151 */
+  "dbreaka8",                  /* 152 */
+  "dbreaka9",                  /* 153 */
+  "dbreaka10",                 /* 154 */
+  "dbreaka11",                 /* 155 */
+  "dbreaka12",                 /* 156 */
+  "dbreaka13",                 /* 157 */
+  "dbreaka14",                 /* 158 */
+  "dbreaka15",                 /* 159 */
+                          
+  "dbreakc0",                  /* 160 */
+  "dbreakc1",                  /* 161 */
+  "dbreakc2",                  /* 162 */
+  "dbreakc3",                  /* 163 */
+  "dbreakc4",                  /* 164 */
+  "dbreakc5",                  /* 165 */
+  "dbreakc6",                  /* 166 */
+  "dbreakc7",                  /* 167 */
+  "dbreakc8",                  /* 168 */
+  "dbreakc9",                  /* 169 */
+  "dbreakc10",                 /* 170 */
+  "dbreakc11",                 /* 171 */
+  "dbreakc12",                 /* 172 */
+  "dbreakc13",                 /* 173 */
+  "dbreakc14",                 /* 174 */
+  "dbreakc15",                 /* 175 */
+
+  "reserved_176",              /* 176 */
+
+  "epc1",                      /* 177 */
+  "epc2",                      /* 178 */
+  "epc3",                      /* 179 */
+  "epc4",                      /* 180 */
+  "epc5",                      /* 181 */
+  "epc6",                      /* 182 */
+  "epc7",                      /* 183 */
+  "epc8",                      /* 184 */
+  "epc9",                      /* 185 */
+  "epc10",                     /* 186 */
+  "epc11",                     /* 187 */
+  "epc12",                     /* 188 */
+  "epc13",                     /* 189 */
+  "epc14",                     /* 190 */
+  "epc15",                     /* 191 */
+  "depc",                      /* 192 */
+
+  "reserved_193",              /* 193 */
+
+  "eps2",                      /* 194 */
+  "eps3",                      /* 195 */
+  "eps4",                      /* 196 */
+  "eps5",                      /* 197 */
+  "eps6",                      /* 198 */
+  "eps7",                      /* 199 */
+  "eps8",                      /* 200 */
+  "eps9",                      /* 201 */
+  "eps10",                     /* 202 */
+  "eps11",                     /* 203 */
+  "eps12",                     /* 204 */
+  "eps13",                     /* 205 */
+  "eps14",                     /* 206 */
+  "eps15",                     /* 207 */
+
+  "reserved_208",              /* 208 */
+
+  "excsave1",                  /* 209 */
+  "excsave2",                  /* 210 */
+  "excsave3",                  /* 211 */
+  "excsave4",                  /* 212 */
+  "excsave5",                  /* 213 */
+  "excsave6",                  /* 214 */
+  "excsave7",                  /* 215 */
+  "excsave8",                  /* 216 */
+  "excsave9",                  /* 217 */
+  "excsave10",                 /* 218 */
+  "excsave11",                 /* 219 */
+  "excsave12",                 /* 220 */
+  "excsave13",                 /* 221 */
+  "excsave14",                 /* 222 */
+  "excsave15",                 /* 223 */
+  "cpenable",                  /* 224 */
+
+  "reserved_225",              /* 225 */
+
+  "interrupt",                 /* 226 */
+  "interrupt2",                        /* 227 */
+  "intenable",                 /* 228 */
+
+  "reserved_229",              /* 229 */
+
+  "ps",                                /* 230 */
+
+  "reserved_231",              /* 231 */
+
+  "exccause",                  /* 232 */
+  "debugcause",                        /* 233 */
+  "ccount",                    /* 234 */
+  "prid",                      /* 235 */
+  "icount",                    /* 236 */
+  "icountlvl",                         /* 237 */
+  "excvaddr",                  /* 238 */
+
+  "reserved_239",              /* 239 */
+
+  "ccompare0",                 /* 240 */
+  "ccompare1",                 /* 241 */
+  "ccompare2",                 /* 242 */
+  "ccompare3",                 /* 243 */
+
+  "misc0",                     /* 244 */
+  "misc1",                     /* 245 */
+  "misc2",                     /* 246 */
+  "misc3",                     /* 247 */
+
+  "reserved_248",              /* 248 */
+  "reserved_249",              /* 249 */
+  "reserved_250",              /* 250 */
+  "reserved_251",              /* 251 */
+  "reserved_252",              /* 252 */
+  "reserved_253",              /* 253 */
+  "reserved_254",              /* 254 */
+  "reserved_255",              /* 255 */
+};
+
+
+int show_raw_fields;
+
+static int fetch_data
+  PARAMS ((struct disassemble_info *info, bfd_vma memaddr, int numBytes));
+static void print_xtensa_operand
+  PARAMS ((bfd_vma, struct disassemble_info *, xtensa_operand,
+          unsigned operand_val, int print_sr_name));
+
+struct dis_private {
+  bfd_byte *byte_buf;
+  jmp_buf bailout;
+};
+
+static int
+fetch_data (info, memaddr, numBytes)
+     struct disassemble_info *info;
+     bfd_vma memaddr;
+     int numBytes;
+{
+  int length, status = 0;
+  struct dis_private *priv = (struct dis_private *) info->private_data;
+  int insn_size = (numBytes != 0 ? numBytes :
+                  xtensa_insn_maxlength (xtensa_default_isa));
+
+  /* Read the maximum instruction size, padding with zeros if we go past
+     the end of the text section.  This code will automatically adjust
+     length when we hit the end of the buffer.  */
+
+  memset (priv->byte_buf, 0, insn_size);
+  for (length = insn_size; length > 0; length--)
+    {
+      status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
+                                         info);
+      if (status == 0)
+       return length;
+    }
+  (*info->memory_error_func) (status, memaddr, info);
+  longjmp (priv->bailout, 1);
+  /*NOTREACHED*/
+}
+
+
+static void
+print_xtensa_operand (memaddr, info, opnd, operand_val, print_sr_name)
+     bfd_vma memaddr;
+     struct disassemble_info *info;
+     xtensa_operand opnd;
+     unsigned operand_val;
+     int print_sr_name;
+{
+  char *kind = xtensa_operand_kind (opnd);
+  int signed_operand_val;
+    
+  if (show_raw_fields)
+    {
+      if (operand_val < 0xa)
+       (*info->fprintf_func) (info->stream, "%u", operand_val);
+      else
+       (*info->fprintf_func) (info->stream, "0x%x", operand_val);
+      return;
+    }
+
+  operand_val = xtensa_operand_decode (opnd, operand_val);
+  signed_operand_val = (int) operand_val;
+
+  if (xtensa_operand_isPCRelative (opnd))
+    {
+      operand_val = xtensa_operand_undo_reloc (opnd, operand_val, memaddr);
+      info->target = operand_val;
+      (*info->print_address_func) (info->target, info);
+    }
+  else if (!strcmp (kind, "i"))
+    {
+      if (print_sr_name
+         && signed_operand_val >= 0
+         && signed_operand_val <= 255)
+       (*info->fprintf_func) (info->stream, "%s",
+                              state_names[signed_operand_val]);
+      else if ((signed_operand_val > -256) && (signed_operand_val < 256))
+       (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
+      else
+       (*info->fprintf_func) (info->stream, "0x%x",signed_operand_val);
+    }
+  else
+    (*info->fprintf_func) (info->stream, "%s%u", kind, operand_val);
+}
+
+
+/* Print the Xtensa instruction at address MEMADDR on info->stream.
+   Returns length of the instruction in bytes.  */
+
+int
+print_insn_xtensa (memaddr, info)
+     bfd_vma memaddr;
+     struct disassemble_info *info;
+{
+  unsigned operand_val;
+  int bytes_fetched, size, maxsize, i, noperands;
+  xtensa_isa isa;
+  xtensa_opcode opc;
+  char *op_name;
+  int print_sr_name;
+  struct dis_private priv;
+  static bfd_byte *byte_buf = NULL;
+  static xtensa_insnbuf insn_buffer = NULL;
+
+  if (!xtensa_default_isa)
+    (void) xtensa_isa_init ();
+
+  info->target = 0;
+  maxsize = xtensa_insn_maxlength (xtensa_default_isa);
+
+  /* Set bytes_per_line to control the amount of whitespace between the hex
+     values and the opcode.  For Xtensa, we always print one "chunk" and we
+     vary bytes_per_chunk to determine how many bytes to print.  (objdump
+     would apparently prefer that we set bytes_per_chunk to 1 and vary
+     bytes_per_line but that makes it hard to fit 64-bit instructions on
+     an 80-column screen.)  The value of bytes_per_line here is not exactly
+     right, because objdump adds an extra space for each chunk so that the
+     amount of whitespace depends on the chunk size.  Oh well, it's good
+     enough....  Note that we set the minimum size to 4 to accomodate
+     literal pools.  */
+  info->bytes_per_line = MAX (maxsize, 4);
+
+  /* Allocate buffers the first time through.  */
+  if (!insn_buffer)
+    insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
+  if (!byte_buf)
+    byte_buf = (bfd_byte *) malloc (MAX (maxsize, 4));
+
+  priv.byte_buf = byte_buf;
+
+  info->private_data = (PTR) &priv;
+  if (setjmp (priv.bailout) != 0)
+      /* Error return.  */
+      return -1;
+
+  /* Don't set "isa" before the setjmp to keep the compiler from griping.  */
+  isa = xtensa_default_isa;
+
+  /* Fetch the maximum size instruction.  */
+  bytes_fetched = fetch_data (info, memaddr, 0);
+
+  /* Copy the bytes into the decode buffer.  */
+  memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
+                          sizeof (xtensa_insnbuf_word)));
+  xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf);
+
+  opc = xtensa_decode_insn (isa, insn_buffer);
+  if (opc == XTENSA_UNDEFINED
+      || ((size = xtensa_insn_length (isa, opc)) > bytes_fetched))
+    {
+      (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
+      return 1;
+    }
+
+  op_name = (char *) xtensa_opcode_name (isa, opc);
+  (*info->fprintf_func) (info->stream, "%s", op_name);
+
+  print_sr_name = (!strcasecmp (op_name, "wsr")
+                  || !strcasecmp (op_name, "xsr")
+                  || !strcasecmp (op_name, "rsr"));
+
+  /* Print the operands (if any).  */
+  noperands = xtensa_num_operands (isa, opc);
+  if (noperands > 0)
+    {
+      int first = 1;
+
+      (*info->fprintf_func) (info->stream, "\t");
+      for (i = 0; i < noperands; i++)
+       {
+         xtensa_operand opnd = xtensa_get_operand (isa, opc, i);
+
+         if (first)
+           first = 0;
+         else
+           (*info->fprintf_func) (info->stream, ", ");
+         operand_val = xtensa_operand_get_field (opnd, insn_buffer);
+         print_xtensa_operand (memaddr, info, opnd, operand_val,
+                               print_sr_name);
+        }
+    }
+
+  info->bytes_per_chunk = size;
+  info->display_endian = info->endian;
+
+  return size;
+}
+
diff --git a/sim/arm/iwmmxt.c b/sim/arm/iwmmxt.c
new file mode 100644 (file)
index 0000000..72444f6
--- /dev/null
@@ -0,0 +1,3730 @@
+/*  iwmmxt.c -- Intel(r) Wireless MMX(tm) technology co-processor interface.
+    Copyright (C) 2002 Free Software Foundation, Inc.
+    Contributed by matthew green (mrg@redhat.com).
+    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.
+    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 "armdefs.h"
+#include "armos.h"
+#include "armemu.h"
+#include "ansidecl.h"
+#include "iwmmxt.h"
+
+/* #define DEBUG 1 */
+
+/* Intel(r) Wireless MMX(tm) technology co-processor.  
+   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
+   to access wRx and wCx respectively.  */
+
+static ARMdword wR[16];
+static ARMword  wC[16] = { 0x69051010 };
+
+#define SUBSTR(w,t,m,n) ((t)(w <<  ((sizeof (t) * 8 - 1) - (n))) \
+                               >> (((sizeof (t) * 8 - 1) - (n)) + (m)))
+#define wCBITS(w,x,y)   SUBSTR (wC[w], ARMword, x, y)
+#define wRBITS(w,x,y)   SUBSTR (wR[w], ARMdword, x, y)
+#define wCID   0
+#define wCon   1
+#define wCSSF  2
+#define wCASF  3
+#define wCGR0  8
+#define wCGR1  9
+#define wCGR2 10
+#define wCGR3 11
+
+/* Bits in the wCon register.  */
+#define WCON_CUP       (1 << 0)
+#define WCON_MUP       (1 << 1)
+
+/* 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 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 SIMD64_SET(x, v, n)    (x) |= ((v != 0) << (32 + (n)))
+
+/* Flags to pass as "n" above.  */
+#define SIMD_NBIT      -1
+#define SIMD_ZBIT      -2
+#define SIMD_CBIT      -3
+#define SIMD_VBIT      -4
+
+/* Various status bit macros.  */
+#define NBIT8(x)       ((x) & 0x80)
+#define NBIT16(x)      ((x) & 0x8000)
+#define NBIT32(x)      ((x) & 0x80000000)
+#define NBIT64(x)      ((x) & 0x8000000000000000ULL)
+#define ZBIT8(x)       (((x) & 0xff) == 0)
+#define ZBIT16(x)      (((x) & 0xffff) == 0)
+#define ZBIT32(x)      (((x) & 0xffffffff) == 0)
+#define ZBIT64(x)      (x == 0)
+
+/* Access byte/half/word "n" of register "x".  */
+#define wRBYTE(x,n)    wRBITS ((x), (n) * 8, (n) * 8 + 7)
+#define wRHALF(x,n)    wRBITS ((x), (n) * 16, (n) * 16 + 15)
+#define wRWORD(x,n)    wRBITS ((x), (n) * 32, (n) * 32 + 31)
+
+/* Macro to handle how the G bit selects wCGR registers.  */
+#define DECODE_G_BIT(state, instr, shift)      \
+{                                              \
+  unsigned int reg;                            \
+                                               \
+  reg = BITS (0, 3);                           \
+                                               \
+  if (BIT (8)) /* G */                         \
+    {                                          \
+      if (reg < wCGR0 || reg > wCGR3)          \
+       {                                       \
+         ARMul_UndefInstr (state, instr);      \
+         return ARMul_DONE;                    \
+       }                                       \
+      shift = wC [reg];                                \
+    }                                          \
+  else                                         \
+    shift = wR [reg];                          \
+                                               \
+  shift &= 0xff;                               \
+}
+
+/* Index calculations for the satrv[] array.  */
+#define BITIDX8(x)     (x)
+#define BITIDX16(x)    (((x) + 1) * 2 - 1)
+#define BITIDX32(x)    (((x) + 1) * 4 - 1)
+
+/* Sign extension macros.  */
+#define EXTEND8(a)     ((a) & 0x80 ? ((a) | 0xffffff00) : (a))
+#define EXTEND16(a)    ((a) & 0x8000 ? ((a) | 0xffff0000) : (a))
+#define EXTEND32(a)    ((a) & 0x80000000ULL ? ((a) | 0xffffffff00000000ULL) : (a))
+
+/* Set the wCSSF from 8 values.  */
+#define SET_wCSSF(a,b,c,d,e,f,g,h) \
+  wC[wCSSF] = (((h) != 0) << 7) | (((g) != 0) << 6) \
+            | (((f) != 0) << 5) | (((e) != 0) << 4) \
+            | (((d) != 0) << 3) | (((c) != 0) << 2) \
+            | (((b) != 0) << 1) | (((a) != 0) << 0);
+
+/* Set the wCSSR from an array with 8 values.  */
+#define SET_wCSSFvec(v) \
+  SET_wCSSF((v)[0],(v)[1],(v)[2],(v)[3],(v)[4],(v)[5],(v)[6],(v)[7])
+
+/* Size qualifiers for vector operations.  */
+#define Bqual                  0
+#define Hqual                  1
+#define Wqual                  2
+#define Dqual                  3
+
+/* Saturation qualifiers for vector operations.  */
+#define NoSaturation           0
+#define UnsignedSaturation     1
+#define SignedSaturation       3
+
+\f
+/* Prototypes.  */
+static ARMword         Add32  (ARMword,  ARMword,  int *, int *, ARMword);
+static ARMdword        AddS32 (ARMdword, ARMdword, int *, int *);
+static ARMdword        AddU32 (ARMdword, ARMdword, int *, int *);
+static ARMword         AddS16 (ARMword,  ARMword,  int *, int *);
+static ARMword         AddU16 (ARMword,  ARMword,  int *, int *);
+static ARMword         AddS8  (ARMword,  ARMword,  int *, int *);
+static ARMword         AddU8  (ARMword,  ARMword,  int *, int *);
+static ARMword         Sub32  (ARMword,  ARMword,  int *, int *, ARMword);
+static ARMdword        SubS32 (ARMdword, ARMdword, int *, int *);
+static ARMdword        SubU32 (ARMdword, ARMdword, int *, int *);
+static ARMword         SubS16 (ARMword,  ARMword,  int *, int *);
+static ARMword         SubS8  (ARMword,  ARMword,  int *, int *);
+static ARMword         SubU16 (ARMword,  ARMword,  int *, int *);
+static ARMword         SubU8  (ARMword,  ARMword,  int *, int *);
+static unsigned char   IwmmxtSaturateU8  (signed short, int *);
+static signed char     IwmmxtSaturateS8  (signed short, int *);
+static unsigned short  IwmmxtSaturateU16 (signed int, int *);
+static signed short    IwmmxtSaturateS16 (signed int, int *);
+static unsigned long   IwmmxtSaturateU32 (signed long long, int *);
+static signed long     IwmmxtSaturateS32 (signed long long, int *);
+static ARMword         Compute_Iwmmxt_Address   (ARMul_State *, ARMword, int *);
+static ARMdword        Iwmmxt_Load_Double_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_Byte         (ARMul_State *, ARMword);
+static void            Iwmmxt_Store_Double_Word (ARMul_State *, ARMword, ARMdword);
+static void            Iwmmxt_Store_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 int             Process_Instruction      (ARMul_State *, ARMword);
+
+static int TANDC    (ARMul_State *, ARMword);
+static int TBCST    (ARMul_State *, ARMword);
+static int TEXTRC   (ARMul_State *, ARMword);
+static int TEXTRM   (ARMul_State *, ARMword);
+static int TINSR    (ARMul_State *, ARMword);
+static int TMCR     (ARMul_State *, ARMword);
+static int TMCRR    (ARMul_State *, ARMword);
+static int TMIA     (ARMul_State *, ARMword);
+static int TMIAPH   (ARMul_State *, ARMword);
+static int TMIAxy   (ARMul_State *, ARMword);
+static int TMOVMSK  (ARMul_State *, ARMword);
+static int TMRC     (ARMul_State *, ARMword);
+static int TMRRC    (ARMul_State *, ARMword);
+static int TORC     (ARMul_State *, ARMword);
+static int WACC     (ARMul_State *, ARMword);
+static int WADD     (ARMul_State *, ARMword);
+static int WALIGNI  (ARMword);
+static int WALIGNR  (ARMul_State *, ARMword);
+static int WAND     (ARMword);
+static int WANDN    (ARMword);
+static int WAVG2    (ARMword);
+static int WCMPEQ   (ARMul_State *, ARMword);
+static int WCMPGT   (ARMul_State *, ARMword);
+static int WLDR     (ARMul_State *, ARMword);
+static int WMAC     (ARMword);
+static int WMADD    (ARMword);
+static int WMAX     (ARMul_State *, ARMword);
+static int WMIN     (ARMul_State *, ARMword);
+static int WMUL     (ARMword);
+static int WOR      (ARMword);
+static int WPACK    (ARMul_State *, ARMword);
+static int WROR     (ARMul_State *, ARMword);
+static int WSAD     (ARMword);
+static int WSHUFH   (ARMword);
+static int WSLL     (ARMul_State *, ARMword);
+static int WSRA     (ARMul_State *, ARMword);
+static int WSRL     (ARMul_State *, ARMword);
+static int WSTR     (ARMul_State *, ARMword);
+static int WSUB     (ARMul_State *, ARMword);
+static int WUNPCKEH (ARMul_State *, ARMword);
+static int WUNPCKEL (ARMul_State *, ARMword);
+static int WUNPCKIH (ARMul_State *, ARMword);
+static int WUNPCKIL (ARMul_State *, ARMword);
+static int WXOR     (ARMword);
+\f
+/* This function does the work of adding two 32bit values
+   together, and calculating if a carry has occurred.  */
+
+static ARMword
+Add32 (ARMword a1,
+       ARMword a2,
+       int * carry_ptr,
+       int * overflow_ptr,
+       ARMword sign_mask)
+{
+  ARMword result = (a1 + a2);
+  unsigned int uresult = (unsigned int) result;
+  unsigned int ua1 = (unsigned int) a1;
+
+  /* If (result == a1) and (a2 == 0),
+     or (result > a2) then we have no carry.  */
+  * carry_ptr = ((uresult == ua1) ? (a2 != 0) : (uresult < ua1));
+
+  /* Overflow occurs when both arguments are the
+     same sign, but the result is a different sign.  */
+  * overflow_ptr = (   ( (result & sign_mask) && !(a1 & sign_mask) && !(a2 & sign_mask))
+                   || (!(result & sign_mask) &&  (a1 & sign_mask) &&  (a2 & sign_mask)));
+  
+  return result;
+}
+
+static ARMdword
+AddS32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr)
+{
+  ARMdword     result;
+  unsigned int uresult;
+  unsigned int ua1;
+
+  a1 = EXTEND32 (a1);
+  a2 = EXTEND32 (a2);
+
+  result  = a1 + a2;
+  uresult = (unsigned int) result;
+  ua1     = (unsigned int) a1;
+
+  * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1));
+
+  * overflow_ptr = (   ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL))
+                   || (!(result & 0x80000000ULL) &&  (a1 & 0x80000000ULL) &&  (a2 & 0x80000000ULL)));
+
+  return result;
+}
+
+static ARMdword
+AddU32 (ARMdword a1, ARMdword a2, int * carry_ptr, int * overflow_ptr)
+{
+  ARMdword     result;
+  unsigned int uresult;
+  unsigned int ua1;
+
+  a1 &= 0xffffffff;
+  a2 &= 0xffffffff;
+
+  result  = a1 + a2;
+  uresult = (unsigned int) result;
+  ua1     = (unsigned int) a1;
+
+  * carry_ptr = ((uresult == a1) ? (a2 != 0) : (uresult < ua1));
+
+  * overflow_ptr = (   ( (result & 0x80000000ULL) && !(a1 & 0x80000000ULL) && !(a2 & 0x80000000ULL))
+                   || (!(result & 0x80000000ULL) &&  (a1 & 0x80000000ULL) &&  (a2 & 0x80000000ULL)));
+
+  return result;
+}
+
+static ARMword
+AddS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
+{
+  a1 = EXTEND16 (a1);
+  a2 = EXTEND16 (a2);
+
+  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
+}
+
+static ARMword
+AddU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
+{
+  a1 &= 0xffff;
+  a2 &= 0xffff;
+
+  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
+}
+
+static ARMword
+AddS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
+{
+  a1 = EXTEND8 (a1);
+  a2 = EXTEND8 (a2);
+
+  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
+}
+
+static ARMword
+AddU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
+{
+  a1 &= 0xff;
+  a2 &= 0xff;
+
+  return Add32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
+}
+
+static ARMword
+Sub32 (ARMword a1,
+       ARMword a2,
+       int * borrow_ptr,
+       int * overflow_ptr,
+       ARMword sign_mask)
+{
+  ARMword result = (a1 - a2);
+  unsigned int ua1 = (unsigned int) a1;
+  unsigned int ua2 = (unsigned int) a2;
+
+  /* A borrow occurs if a2 is (unsigned) larger than a1.
+     However the carry flag is *cleared* if a borrow occurs.  */
+  * borrow_ptr = ! (ua2 > ua1);
+
+  /* Overflow occurs when a negative number is subtracted from a
+     positive number and the result is negative or a positive
+     number is subtracted from a negative number and the result is
+     positive.  */
+  * overflow_ptr = ( (! (a1 & sign_mask) &&   (a2 & sign_mask) &&   (result & sign_mask))
+                   || ((a1 & sign_mask) && ! (a2 & sign_mask) && ! (result & sign_mask)));
+
+  return result;
+}
+
+static ARMdword
+SubS32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr)
+{
+  ARMdword     result;
+  unsigned int ua1;
+  unsigned int ua2;
+
+  a1 = EXTEND32 (a1);
+  a2 = EXTEND32 (a2);
+
+  result = a1 - a2;
+  ua1    = (unsigned int) a1;
+  ua2    = (unsigned int) a2;
+
+  * borrow_ptr = ! (ua2 > ua1);
+
+  * overflow_ptr = ( (! (a1 & 0x80000000ULL) &&   (a2 & 0x80000000ULL) &&   (result & 0x80000000ULL))
+                   || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL)));
+
+  return result;
+}
+
+static ARMword
+SubS16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
+{
+  a1 = EXTEND16 (a1);
+  a2 = EXTEND16 (a2);
+
+  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
+}
+
+static ARMword
+SubS8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
+{
+  a1 = EXTEND8 (a1);
+  a2 = EXTEND8 (a2);
+
+  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
+}
+
+static ARMword
+SubU16 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
+{
+  a1 &= 0xffff;
+  a2 &= 0xffff;
+
+  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x8000);
+}
+
+static ARMword
+SubU8 (ARMword a1, ARMword a2, int * carry_ptr, int * overflow_ptr)
+{
+  a1 &= 0xff;
+  a2 &= 0xff;
+
+  return Sub32 (a1, a2, carry_ptr, overflow_ptr, 0x80);
+}
+
+static ARMdword
+SubU32 (ARMdword a1, ARMdword a2, int * borrow_ptr, int * overflow_ptr)
+{
+  ARMdword     result;
+  unsigned int ua1;
+  unsigned int ua2;
+
+  a1 &= 0xffffffff;
+  a2 &= 0xffffffff;
+
+  result = a1 - a2;
+  ua1    = (unsigned int) a1;
+  ua2    = (unsigned int) a2;
+
+  * borrow_ptr = ! (ua2 > ua1);
+
+  * overflow_ptr = ( (! (a1 & 0x80000000ULL) &&   (a2 & 0x80000000ULL) &&   (result & 0x80000000ULL))
+                   || ((a1 & 0x80000000ULL) && ! (a2 & 0x80000000ULL) && ! (result & 0x80000000ULL)));
+
+  return result;
+}
+
+/* For the saturation.  */
+
+static unsigned char
+IwmmxtSaturateU8 (signed short val, int * sat)
+{
+  unsigned char rv;
+
+  if (val < 0)
+    {
+      rv = 0;
+      *sat = 1;
+    }
+  else if (val > 0xff)
+    {
+      rv = 0xff;
+      *sat = 1;
+    }
+  else
+    {
+      rv = val & 0xff;
+      *sat = 0;
+    }
+  return rv;
+}
+
+static signed char
+IwmmxtSaturateS8 (signed short val, int * sat)
+{
+  signed char rv;
+
+  if (val < -0x80)
+    {
+      rv = -0x80;
+      *sat = 1;
+    }
+  else if (val > 0x7f)
+    {
+      rv = 0x7f;
+      *sat = 1;
+    }
+  else
+    {
+      rv = val & 0xff;
+      *sat = 0;
+    }
+  return rv;
+}
+
+static unsigned short
+IwmmxtSaturateU16 (signed int val, int * sat)
+{
+  unsigned short rv;
+
+  if (val < 0)
+    {
+      rv = 0;
+      *sat = 1;
+    }
+  else if (val > 0xffff)
+    {
+      rv = 0xffff;
+      *sat = 1;
+    }
+  else
+    {
+      rv = val & 0xffff;
+      *sat = 0;
+    }
+  return rv;
+}
+
+static signed short
+IwmmxtSaturateS16 (signed int val, int * sat)
+{
+  signed short rv;
+  
+  if (val < -0x8000)
+    {
+      rv = - 0x8000;
+      *sat = 1;
+    }
+  else if (val > 0x7fff)
+    {
+      rv = 0x7fff;
+      *sat = 1;
+    }
+  else
+    {
+      rv = val & 0xffff;
+      *sat = 0;
+    }
+  return rv;
+}
+
+static unsigned long
+IwmmxtSaturateU32 (signed long long val, int * sat)
+{
+  unsigned long rv;
+
+  if (val < 0)
+    {
+      rv = 0;
+      *sat = 1;
+    }
+  else if (val > 0xffffffff)
+    {
+      rv = 0xffffffff;
+      *sat = 1;
+    }
+  else
+    {
+      rv = val & 0xffffffff;
+      *sat = 0;
+    }
+  return rv;
+}
+
+static signed long
+IwmmxtSaturateS32 (signed long long val, int * sat)
+{
+  signed long rv;
+  
+  if (val < -0x80000000LL)
+    {
+      rv = -0x80000000;
+      *sat = 1;
+    }
+  else if (val > 0x7fffffff)
+    {
+      rv = 0x7fffffff;
+      *sat = 1;
+    }
+  else
+    {
+      rv = val & 0xffffffff;
+      *sat = 0;
+    }
+  return rv;
+}
+
+/* Intel(r) Wireless MMX(tm) technology Acessor functions.  */
+
+unsigned
+IwmmxtLDC (ARMul_State * state ATTRIBUTE_UNUSED,
+          unsigned      type  ATTRIBUTE_UNUSED,
+          ARMword       instr,
+          ARMword       data)
+{
+  return ARMul_CANT;
+}
+
+unsigned
+IwmmxtSTC (ARMul_State * state ATTRIBUTE_UNUSED,
+          unsigned      type  ATTRIBUTE_UNUSED,
+          ARMword       instr,
+          ARMword *     data)
+{
+  return ARMul_CANT;
+}
+
+unsigned
+IwmmxtMRC (ARMul_State * state ATTRIBUTE_UNUSED,
+          unsigned      type  ATTRIBUTE_UNUSED,
+          ARMword       instr,
+          ARMword *     value)
+{
+  return ARMul_CANT;
+}
+
+unsigned
+IwmmxtMCR (ARMul_State * state ATTRIBUTE_UNUSED,
+          unsigned      type  ATTRIBUTE_UNUSED,
+          ARMword       instr,
+          ARMword       value)
+{
+  return ARMul_CANT;
+}
+
+unsigned
+IwmmxtCDP (ARMul_State * state, unsigned type, ARMword instr)
+{
+  return ARMul_CANT;
+}
+
+/* Intel(r) Wireless MMX(tm) technology instruction implementations.  */
+
+static int
+TANDC (ARMul_State * state, ARMword instr)
+{
+  ARMword cpsr;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "tandc\n");
+#endif  
+
+  /* The Rd field must be r15.  */
+  if (BITS (12, 15) != 15)
+    return ARMul_CANT;
+
+  /* The CRn field must be r3.  */
+  if (BITS (16, 19) != 3)
+    return ARMul_CANT;
+
+  /* The CRm field must be r0.  */
+  if (BITS (0, 3) != 0)
+    return ARMul_CANT;
+
+  cpsr = ARMul_GetCPSR (state) & 0x0fffffff;
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      cpsr |= (  (wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 24, 27)
+               & wCBITS (wCASF, 20, 23) & wCBITS (wCASF, 16, 19)
+               & wCBITS (wCASF, 12, 15) & wCBITS (wCASF,  8, 11)
+               & wCBITS (wCASF,  4,  7) & wCBITS (wCASF,  0,  3)) << 28);
+      break;
+
+    case Hqual:
+      cpsr |= (  (wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 20, 23)
+               & wCBITS (wCASF, 12, 15) & wCBITS (wCASF,  4, 7)) << 28);
+      break;
+
+    case Wqual:
+      cpsr |= ((wCBITS (wCASF, 28, 31) & wCBITS (wCASF, 12, 15)) << 28);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+  
+  ARMul_SetCPSR (state, cpsr);
+
+  return ARMul_DONE;
+}
+
+static int
+TBCST (ARMul_State * state, ARMword instr)
+{
+  ARMdword Rn;
+  int wRd;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "tbcst\n");
+#endif  
+
+  Rn  = state->Reg [BITS (12, 15)];
+  if (BITS (12, 15) == 15)
+    Rn &= 0xfffffffc;
+
+  wRd = BITS (16, 19);
+
+  switch (BITS (6, 7))
+    {
+    case Bqual:
+      Rn &= 0xff;
+      wR [wRd] = (Rn << 56) | (Rn << 48) | (Rn << 40) | (Rn << 32)
+              | (Rn << 24) | (Rn << 16) | (Rn << 8) | Rn;
+      break;
+
+    case Hqual:
+      Rn &= 0xffff;
+      wR [wRd] = (Rn << 48) | (Rn << 32) | (Rn << 16) | Rn;
+      break;
+
+    case Wqual:
+      Rn &= 0xffffffff;
+      wR [wRd] = (Rn << 32) | Rn;
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      break;
+    }
+
+  wC [wCon] |= WCON_MUP;
+  return ARMul_DONE;
+}
+
+static int
+TEXTRC (ARMul_State * state, ARMword instr)
+{
+  ARMword cpsr;
+  ARMword selector;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "textrc\n");
+#endif  
+
+  /* The Rd field must be r15.  */
+  if (BITS (12, 15) != 15)
+    return ARMul_CANT;
+
+  /* The CRn field must be r3.  */
+  if (BITS (16, 19) != 3)
+    return ARMul_CANT;
+
+  /* The CRm field must be 0xxx.  */
+  if (BIT (3) != 0)
+    return ARMul_CANT;
+
+  selector = BITS (0, 2);
+  cpsr = ARMul_GetCPSR (state) & 0x0fffffff;
+
+  switch (BITS (22, 23))
+    {
+    case Bqual: selector *= 4; break;
+    case Hqual: selector = ((selector & 3) * 8) + 4; break;
+    case Wqual: selector = ((selector & 1) * 16) + 12; break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+  
+  cpsr |= wCBITS (wCASF, selector, selector + 3) << 28;
+  ARMul_SetCPSR (state, cpsr);
+
+  return ARMul_DONE;
+}
+
+static int
+TEXTRM (ARMul_State * state, ARMword instr)
+{
+  ARMword Rd;
+  int     offset;
+  int     wRn;
+  int     sign;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "textrm\n");
+#endif  
+
+  wRn    = BITS (16, 19);
+  sign   = BIT (3);
+  offset = BITS (0, 2);
+  
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      offset *= 8;
+      Rd = wRBITS (wRn, offset, offset + 7);
+      if (sign)
+       Rd = EXTEND8 (Rd);
+      break;
+
+    case Hqual:
+      offset = (offset & 3) * 16;
+      Rd = wRBITS (wRn, offset, offset + 15);
+      if (sign)
+       Rd = EXTEND16 (Rd);
+      break;
+
+    case Wqual:
+      offset = (offset & 1) * 32;
+      Rd = wRBITS (wRn, offset, offset + 31);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  if (BITS (12, 15) == 15)
+    ARMul_UndefInstr (state, instr);
+  else
+    state->Reg [BITS (12, 15)] = Rd;
+
+  return ARMul_DONE;
+}
+
+static int
+TINSR (ARMul_State * state, ARMword instr)
+{
+  ARMdword data;
+  ARMword  offset;
+  int      wRd;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "tinsr\n");
+#endif
+
+  wRd = BITS (16, 19);
+  data = state->Reg [BITS (12, 15)];
+  offset = BITS (0, 2);
+
+  switch (BITS (6, 7))
+    {
+    case Bqual:
+      data &= 0xff;
+      switch (offset)
+       {
+       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 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 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 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;
+       }
+      break;
+
+    case Hqual:
+      data &= 0xffff;
+
+      switch (offset & 3)
+       {
+       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 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;
+       }
+      break;
+
+    case Wqual:
+      if (offset & 1)
+       wR [wRd] = wRBITS (wRd, 0, 31) | (data << 32);
+      else
+       wR [wRd] = (wRBITS (wRd, 32, 63) << 32) | data;
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      break;
+    }
+
+  wC [wCon] |= WCON_MUP;
+  return ARMul_DONE;
+}
+
+static int
+TMCR (ARMul_State * state, ARMword instr)
+{
+  ARMword val;
+  int     wCreg;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "tmcr\n");
+#endif  
+
+  if (BITS (0, 3) != 0)
+    return ARMul_CANT;
+
+  val = state->Reg [BITS (12, 15)];
+  if (BITS (12, 15) == 15)
+    val &= 0xfffffffc;
+
+  wCreg = BITS (16, 19);
+
+  switch (wCreg)
+    {
+    case wCID:
+      /* The wCID register is read only.  */
+      break;
+
+    case wCon:
+      /* Writing to the MUP or CUP bits clears them.  */
+      wC [wCon] &= ~ (val & 0x3);
+      break;
+      
+    case wCSSF:
+      /* Only the bottom 8 bits can be written to.
+          The higher bits write as zero.  */
+      wC [wCSSF] = (val & 0xff);
+      wC [wCon] |= WCON_CUP;
+      break;
+      
+    default:
+      wC [wCreg] = val;
+      wC [wCon] |= WCON_CUP;
+      break;
+    }
+
+  return ARMul_DONE;
+}
+
+static int
+TMCRR (ARMul_State * state, ARMword instr)
+{
+  ARMdword RdHi = state->Reg [BITS (16, 19)];
+  ARMword  RdLo = state->Reg [BITS (12, 15)];
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "tmcrr\n");
+#endif  
+
+  if ((BITS (16, 19) == 15) || (BITS (12, 15) == 15))
+    return ARMul_CANT;
+
+  wR [BITS (0, 3)] = (RdHi << 32) | RdLo;
+
+  wC [wCon] |= WCON_MUP;
+
+  return ARMul_DONE;
+}
+
+static int
+TMIA (ARMul_State * state, ARMword instr)
+{
+  signed long long a, b;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "tmia\n");
+#endif  
+
+  if ((BITS (0, 3) == 15) || (BITS (12, 15) == 15))
+    {
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  a = state->Reg [BITS (0, 3)];
+  b = state->Reg [BITS (12, 15)];
+
+  a = EXTEND32 (a);
+  b = EXTEND32 (b);
+
+  wR [BITS (5, 8)] += a * b;
+  wC [wCon] |= WCON_MUP;
+
+  return ARMul_DONE;
+}
+
+static int
+TMIAPH (ARMul_State * state, ARMword instr)
+{
+  signed long a, b, result;
+  signed long long r;
+  ARMword Rm = state->Reg [BITS (0, 3)];
+  ARMword Rs = state->Reg [BITS (12, 15)];
+  
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "tmiaph\n");
+#endif  
+
+  if (BITS (0, 3) == 15 || BITS (12, 15) == 15)
+    {
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  a = SUBSTR (Rs, ARMword, 16, 31);
+  b = SUBSTR (Rm, ARMword, 16, 31);
+
+  a = EXTEND16 (a);
+  b = EXTEND16 (b);
+
+  result = a * b;
+
+  r = result;
+  r = EXTEND32 (r);
+  
+  wR [BITS (5, 8)] += r;
+
+  a = SUBSTR (Rs, ARMword,  0, 15);
+  b = SUBSTR (Rm, ARMword,  0, 15);
+
+  a = EXTEND16 (a);
+  b = EXTEND16 (b);
+
+  result = a * b;
+
+  r = result;
+  r = EXTEND32 (r);
+  
+  wR [BITS (5, 8)] += r;
+  wC [wCon] |= WCON_MUP;
+
+  return ARMul_DONE;
+}
+
+static int
+TMIAxy (ARMul_State * state, ARMword instr)
+{
+  ARMword Rm;
+  ARMword Rs;
+  long long temp;
+  
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "tmiaxy\n");
+#endif  
+
+  if (BITS (0, 3) == 15 || BITS (12, 15) == 15)
+    {
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  Rm = state->Reg [BITS (0, 3)];
+  if (BIT (17))
+    Rm >>= 16;
+  else
+    Rm &= 0xffff;
+
+  Rs = state->Reg [BITS (12, 15)];
+  if (BIT (16))
+    Rs >>= 16;
+  else
+    Rs &= 0xffff;
+
+  if (Rm & (1 << 15))
+    Rm -= 1 << 16;
+
+  if (Rs & (1 << 15))
+    Rs -= 1 << 16;
+
+  Rm *= Rs;
+  temp = Rm;
+
+  if (temp & (1 << 31))
+    temp -= 1ULL << 32;
+
+  wR [BITS (5, 8)] += temp;
+  wC [wCon] |= WCON_MUP;
+
+  return ARMul_DONE;
+}
+
+static int
+TMOVMSK (ARMul_State * state, ARMword instr)
+{
+  ARMdword result;
+  int      wRn;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "tmovmsk\n");
+#endif  
+
+  /* The CRm field must be r0.  */
+  if (BITS (0, 3) != 0)
+    return ARMul_CANT;
+
+  wRn = BITS (16, 19);
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      result = (  (wRBITS (wRn, 63, 63) << 7)
+               | (wRBITS (wRn, 55, 55) << 6)
+               | (wRBITS (wRn, 47, 47) << 5)
+               | (wRBITS (wRn, 39, 39) << 4)
+               | (wRBITS (wRn, 31, 31) << 3)
+               | (wRBITS (wRn, 23, 23) << 2)
+               | (wRBITS (wRn, 15, 15) << 1)
+               | (wRBITS (wRn,  7,  7) << 0));
+      break;
+
+    case Hqual:
+      result = (  (wRBITS (wRn, 63, 63) << 3)
+               | (wRBITS (wRn, 47, 47) << 2)
+               | (wRBITS (wRn, 31, 31) << 1)
+               | (wRBITS (wRn, 15, 15) << 0));
+      break;
+
+    case Wqual:
+      result = (wRBITS (wRn, 63, 63) << 1) | wRBITS (wRn, 31, 31);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  state->Reg [BITS (12, 15)] = result;
+
+  return ARMul_DONE;
+}
+
+static int
+TMRC (ARMul_State * state, ARMword instr)
+{
+  int reg = BITS (12, 15);
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "tmrc\n");
+#endif  
+
+  if (BITS (0, 3) != 0)
+    return ARMul_CANT;
+
+  if (reg == 15)
+    ARMul_UndefInstr (state, instr);
+  else
+    state->Reg [reg] = wC [BITS (16, 19)];
+
+  return ARMul_DONE;
+}
+
+static int
+TMRRC (ARMul_State * state, ARMword instr)
+{
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "tmrrc\n");
+#endif  
+
+  if ((BITS (16, 19) == 15) || (BITS (12, 15) == 15) || (BITS (4, 11) != 0))
+    ARMul_UndefInstr (state, instr);
+  else
+    {
+      state->Reg [BITS (16, 19)] = wRBITS (BITS (0, 3), 32, 63);
+      state->Reg [BITS (12, 15)] = wRBITS (BITS (0, 3),  0, 31);
+    }
+
+  return ARMul_DONE;
+}
+
+static int
+TORC (ARMul_State * state, ARMword instr)
+{
+  ARMword cpsr = ARMul_GetCPSR (state);
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "torc\n");
+#endif  
+
+  /* The Rd field must be r15.  */
+  if (BITS (12, 15) != 15)
+    return ARMul_CANT;
+  
+  /* The CRn field must be r3.  */
+  if (BITS (16, 19) != 3)
+    return ARMul_CANT;
+  
+  /* The CRm field must be r0.  */
+  if (BITS (0, 3) != 0)
+    return ARMul_CANT;
+
+  cpsr &= 0x0fffffff;
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      cpsr |= (  (wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 24, 27)
+               | wCBITS (wCASF, 20, 23) | wCBITS (wCASF, 16, 19)
+               | wCBITS (wCASF, 12, 15) | wCBITS (wCASF,  8, 11)
+               | wCBITS (wCASF,  4,  7) | wCBITS (wCASF,  0,  3)) << 28);
+      break;
+
+    case Hqual:
+      cpsr |= (  (wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 20, 23)
+               | wCBITS (wCASF, 12, 15) | wCBITS (wCASF,  4,  7)) << 28);
+      break;
+
+    case Wqual:
+      cpsr |= ((wCBITS (wCASF, 28, 31) | wCBITS (wCASF, 12, 15)) << 28);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+  
+  ARMul_SetCPSR (state, cpsr);
+
+  return ARMul_DONE;
+}
+
+static int
+WACC (ARMul_State * state, ARMword instr)
+{
+  int wRn;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wacc\n");
+#endif  
+
+  wRn = BITS (16, 19);
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      wR [BITS (12, 15)] =
+         wRBITS (wRn, 56, 63) + wRBITS (wRn, 48, 55)
+       + wRBITS (wRn, 40, 47) + wRBITS (wRn, 32, 39)
+       + wRBITS (wRn, 24, 31) + wRBITS (wRn, 16, 23)
+       + wRBITS (wRn,  8, 15) + wRBITS (wRn,  0,  7);
+      break;
+
+    case Hqual:
+      wR [BITS (12, 15)] =
+         wRBITS (wRn, 48, 63) + wRBITS (wRn, 32, 47)
+       + wRBITS (wRn, 16, 31) + wRBITS (wRn,  0, 15);
+      break;
+
+    case Wqual:
+      wR [BITS (12, 15)] = wRBITS (wRn, 32, 63) + wRBITS (wRn, 0, 31);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      break;
+    }
+
+  wC [wCon] |= WCON_MUP;
+  return ARMul_DONE;
+}
+
+static int
+WADD (ARMul_State * state, ARMword instr)
+{
+  ARMdword r = 0;
+  ARMdword x;
+  ARMdword s;
+  ARMword  psr = 0;
+  int      i;
+  int      carry;
+  int      overflow;
+  int      satrv[8];
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wadd\n");
+#endif  
+
+  /* Add two numbers using the specified function,
+     leaving setting the carry bit as required.  */
+#define ADDx(x, y, m, f) \
+   (*f) (wRBITS (BITS (16, 19), (x), (y)) & (m), \
+         wRBITS (BITS ( 0,  3), (x), (y)) & (m), \
+        & carry, & overflow)
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      for (i = 0; i < 8; i++)
+        {
+         switch (BITS (20, 21))
+           {
+           case NoSaturation:
+             s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddS8);
+             satrv [BITIDX8 (i)] = 0;
+             r |= (s & 0xff) << (i * 8);
+             SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
+             SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
+             SIMD8_SET (psr, carry,     SIMD_CBIT, i);
+             SIMD8_SET (psr, overflow,  SIMD_VBIT, i);
+             break;
+
+           case UnsignedSaturation:
+             s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddU8);
+             x = IwmmxtSaturateU8 (s, satrv + BITIDX8 (i));
+             r |= (x & 0xff) << (i * 8);
+             SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
+             SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX8 (i)])
+               {
+                 SIMD8_SET (psr, carry,    SIMD_CBIT, i);
+                 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           case SignedSaturation:
+             s = ADDx ((i * 8), (i * 8) + 7, 0xff, AddS8);
+             x = IwmmxtSaturateS8 (s, satrv + BITIDX8 (i));
+             r |= (x & 0xff) << (i * 8);
+             SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
+             SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX8 (i)])
+               {
+                 SIMD8_SET (psr, carry,    SIMD_CBIT, i);
+                 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           default:
+             ARMul_UndefInstr (state, instr);
+             return ARMul_DONE;
+           }
+       }
+      break;
+
+    case Hqual:
+      satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
+
+      for (i = 0; i < 4; i++)
+       {
+         switch (BITS (20, 21))
+           {
+           case NoSaturation:
+             s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddS16);
+             satrv [BITIDX16 (i)] = 0;
+             r |= (s & 0xffff) << (i * 16);
+             SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+             SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+             SIMD16_SET (psr, carry,      SIMD_CBIT, i);
+             SIMD16_SET (psr, overflow,   SIMD_VBIT, i);
+             break;
+
+           case UnsignedSaturation:
+             s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddU16);
+             x = IwmmxtSaturateU16 (s, satrv + BITIDX16 (i));
+             r |= (x & 0xffff) << (i * 16);
+             SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
+             SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX16 (i)])
+               {
+                 SIMD16_SET (psr, carry,    SIMD_CBIT, i);
+                 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           case SignedSaturation:
+             s = ADDx ((i * 16), (i * 16) + 15, 0xffff, AddS16);
+             x = IwmmxtSaturateS16 (s, satrv + BITIDX16 (i));
+             r |= (x & 0xffff) << (i * 16);
+             SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
+             SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX16 (i)])
+               {
+                 SIMD16_SET (psr, carry,    SIMD_CBIT, i);
+                 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           default:
+             ARMul_UndefInstr (state, instr);
+             return ARMul_DONE;
+           }
+       }
+      break;
+
+    case Wqual:
+      satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
+
+      for (i = 0; i < 2; i++)
+       {
+         switch (BITS (20, 21))
+           {
+           case NoSaturation:
+             s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddS32);
+             satrv [BITIDX32 (i)] = 0;
+             r |= (s & 0xffffffff) << (i * 32);
+             SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+             SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+             SIMD32_SET (psr, carry,      SIMD_CBIT, i);
+             SIMD32_SET (psr, overflow,   SIMD_VBIT, i);
+             break;
+
+           case UnsignedSaturation:
+             s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddU32);
+             x = IwmmxtSaturateU32 (s, satrv + BITIDX32 (i));
+             r |= (x & 0xffffffff) << (i * 32);
+             SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
+             SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX32 (i)])
+               {
+                 SIMD32_SET (psr, carry,    SIMD_CBIT, i);
+                 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           case SignedSaturation:
+             s = ADDx ((i * 32), (i * 32) + 31, 0xffffffff, AddS32);
+             x = IwmmxtSaturateS32 (s, satrv + BITIDX32 (i));
+             r |= (x & 0xffffffff) << (i * 32);
+             SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
+             SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX32 (i)])
+               {
+                 SIMD32_SET (psr, carry,    SIMD_CBIT, i);
+                 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           default:
+             ARMul_UndefInstr (state, instr);
+             return ARMul_DONE;
+           }
+       }
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_MUP | WCON_CUP);
+
+  SET_wCSSFvec (satrv);
+  
+#undef ADDx
+
+  return ARMul_DONE;
+}
+
+static int
+WALIGNI (ARMword instr)
+{
+  int shift = BITS (20, 22) * 8;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "waligni\n");
+#endif  
+
+  if (shift)
+    wR [BITS (12, 15)] =
+      wRBITS (BITS (16, 19), shift, 63)
+      | (wRBITS (BITS (0, 3), 0, shift) << ((64 - shift)));
+  else
+    wR [BITS (12, 15)] = wR [BITS (16, 19)];
+          
+  wC [wCon] |= WCON_MUP;
+  return ARMul_DONE;
+}
+
+static int
+WALIGNR (ARMul_State * state, ARMword instr)
+{
+  int shift = (wC [BITS (20, 21) + 8] & 0x7) * 8;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "walignr\n");
+#endif  
+
+  if (shift)
+    wR [BITS (12, 15)] =
+      wRBITS (BITS (16, 19), shift, 63)
+      | (wRBITS (BITS (0, 3), 0, shift) << ((64 - shift)));
+  else
+    wR [BITS (12, 15)] = wR [BITS (16, 19)];
+
+  wC [wCon] |= WCON_MUP;
+  return ARMul_DONE;
+}
+
+static int
+WAND (ARMword instr)
+{
+  ARMdword result;
+  ARMword  psr = 0;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wand\n");
+#endif  
+
+  result = wR [BITS (16, 19)] & wR [BITS (0, 3)];
+  wR [BITS (12, 15)] = result;
+
+  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
+  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
+  
+  wC [wCASF] = psr;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WANDN (ARMword instr)
+{
+  ARMdword result;
+  ARMword  psr = 0;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wandn\n");
+#endif  
+
+  result = wR [BITS (16, 19)] & ~ wR [BITS (0, 3)];
+  wR [BITS (12, 15)] = result;
+
+  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
+  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
+  
+  wC [wCASF] = psr;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WAVG2 (ARMword instr)
+{
+  ARMdword r = 0;
+  ARMword  psr = 0;
+  ARMdword s;
+  int      i;
+  int      round = BIT (20) ? 1 : 0;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wavg2\n");
+#endif  
+
+#define AVG2x(x, y, m) (((wRBITS (BITS (16, 19), (x), (y)) & (m)) \
+                      + (wRBITS (BITS ( 0,  3), (x), (y)) & (m)) \
+                      + round) / 2)
+
+  if (BIT (22))
+    {
+      for (i = 0; i < 4; i++)
+       {
+         s = AVG2x ((i * 16), (i * 16) + 15, 0xffff) & 0xffff;
+         SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+         r |= s << (i * 16);
+       }
+    }
+  else
+    {
+      for (i = 0; i < 8; i++)
+       {
+         s = AVG2x ((i * 8), (i * 8) + 7, 0xff) & 0xff;
+         SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
+         r |= s << (i * 8);
+       }
+    }
+
+  wR [BITS (12, 15)] = r;
+  wC [wCASF] = psr;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WCMPEQ (ARMul_State * state, ARMword instr)
+{
+  ARMdword r = 0;
+  ARMword  psr = 0;
+  ARMdword s;
+  int      i;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wcmpeq\n");
+#endif  
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      for (i = 0; i < 8; i++)
+       {
+         s = wRBYTE (BITS (16, 19), i) == wRBYTE (BITS (0, 3), i) ? 0xff : 0;
+         r |= s << (i * 8);
+         SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
+         SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Hqual:
+      for (i = 0; i < 4; i++)
+       {
+         s = wRHALF (BITS (16, 19), i) == wRHALF (BITS (0, 3), i) ? 0xffff : 0;
+         r |= s << (i * 16);
+         SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+         SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Wqual:
+      for (i = 0; i < 2; i++)
+       {
+         s = wRWORD (BITS (16, 19), i) == wRWORD (BITS (0, 3), i) ? 0xffffffff : 0;
+         r |= s << (i * 32);
+         SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+         SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WCMPGT (ARMul_State * state, ARMword instr)
+{
+  ARMdword r = 0;
+  ARMword  psr = 0;
+  ARMdword s;
+  int      i;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wcmpgt\n");
+#endif  
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      if (BIT (21))
+       {
+         /* Use a signed comparison.  */
+         for (i = 0; i < 8; i++)
+           {
+             signed char a, b;
+             
+             a = wRBYTE (BITS (16, 19), i);
+             b = wRBYTE (BITS (0, 3), i);
+
+             s = (a > b) ? 0xff : 0;
+             r |= s << (i * 8);
+             SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
+             SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
+           }
+       }
+      else
+       {
+         for (i = 0; i < 8; i++)
+           {
+             s = (wRBYTE (BITS (16, 19), i) > wRBYTE (BITS (0, 3), i))
+               ? 0xff : 0;
+             r |= s << (i * 8);
+             SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
+             SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
+           }
+       }
+      break;
+
+    case Hqual:
+      if (BIT (21))
+       {
+         for (i = 0; i < 4; i++)
+           {
+             signed int a, b;
+
+             a = wRHALF (BITS (16, 19), i);
+             a = EXTEND16 (a);
+
+             b = wRHALF (BITS (0, 3), i);
+             b = EXTEND16 (b);
+
+             s = (a > b) ? 0xffff : 0;         
+             r |= s << (i * 16);
+             SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+             SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+           }
+       }
+      else
+       {
+         for (i = 0; i < 4; i++)
+           {
+             s = (wRHALF (BITS (16, 19), i) > wRHALF (BITS (0, 3), i))
+               ? 0xffff : 0;
+             r |= s << (i * 16);
+             SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+             SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+           }
+       }
+      break;
+
+    case Wqual:
+      if (BIT (21))
+       {
+         for (i = 0; i < 2; i++)
+           {
+             signed long a, b;
+
+             a = wRWORD (BITS (16, 19), i);
+             b = wRWORD (BITS (0, 3), i);
+
+             s = (a > b) ? 0xffffffff : 0;
+             r |= s << (i * 32);
+             SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+             SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+           }
+       }
+      else
+       {
+         for (i = 0; i < 2; i++)
+           {
+             s = (wRWORD (BITS (16, 19), i) > wRWORD (BITS (0, 3), i))
+               ? 0xffffffff : 0;
+             r |= s << (i * 32);
+             SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+             SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+           }
+       }
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static ARMword
+Compute_Iwmmxt_Address (ARMul_State * state, ARMword instr, int * pFailed)
+{
+  ARMword  Rn;
+  ARMword  addr;
+  ARMword  offset;
+  ARMword  multiplier;
+
+  * pFailed  = 0;
+  Rn         = BITS (16, 19);
+  addr       = state->Reg [Rn];
+  offset     = BITS (0, 7);
+  multiplier = BIT (8) ? 4 : 1;
+
+  if (BIT (24)) /* P */
+    {
+      /* Pre Indexed Addressing.  */
+      if (BIT (23))
+       addr += offset * multiplier;
+      else
+       addr -= offset * multiplier;
+
+      /* Immediate Pre-Indexed.  */
+      if (BIT (21)) /* W */
+       {
+         if (Rn == 15)
+           {
+             /* Writeback into R15 is UNPREDICTABLE.  */
+#ifdef DEBUG
+             fprintf (stderr, "iWMMXt: writeback into r15\n");
+#endif
+             * pFailed = 1;
+           }
+         else
+           state->Reg [Rn] = addr;
+       }
+    }
+  else
+    {
+      /* Post Indexed Addressing.  */
+      if (BIT (21)) /* W */
+       {
+         /* Handle the write back of the final address.  */
+         if (Rn == 15)
+           {
+             /* Writeback into R15 is UNPREDICTABLE.  */
+#ifdef DEBUG
+             fprintf (stderr, "iWMMXt: writeback into r15\n");
+#endif  
+             * pFailed = 1;
+           }
+         else
+           {
+             ARMword  increment;
+
+             if (BIT (23))
+               increment = offset * multiplier;
+             else
+               increment = - (offset * multiplier);
+
+             state->Reg [Rn] = addr + increment;
+           }
+       }
+      else
+       {
+         /* P == 0, W == 0, U == 0 is UNPREDICTABLE.  */
+         if (BIT (23) == 0)
+           {
+#ifdef DEBUG
+             fprintf (stderr, "iWMMXt: undefined addressing mode\n");
+#endif  
+             * pFailed = 1;
+           }
+       }
+    }
+
+  return addr;
+}
+
+static ARMdword
+Iwmmxt_Load_Double_Word (ARMul_State * state, ARMword address)
+{
+  ARMdword value;
+  
+  /* The address must be aligned on a 8 byte boundary.  */
+  if (address & 0x7)
+    {
+      fprintf (stderr, "iWMMXt: At addr 0x%x: Unaligned double word load from 0x%x\n",
+              (state->Reg[15] - 8) & ~0x3, address);
+#ifdef DEBUG
+#endif
+      /* No need to check for alignment traps.  An unaligned
+        double word load with alignment trapping disabled is
+        UNPREDICTABLE.  */
+      ARMul_Abort (state, ARMul_DataAbortV);
+    }
+
+  /* Load the words.  */
+  if (! state->bigendSig)
+    {
+      value = ARMul_LoadWordN (state, address + 4);
+      value <<= 32;
+      value |= ARMul_LoadWordN (state, address);
+    }
+  else
+    {
+      value = ARMul_LoadWordN (state, address);
+      value <<= 32;
+      value |= ARMul_LoadWordN (state, address + 4);
+    }
+
+  /* Check for data aborts.  */
+  if (state->Aborted)
+    ARMul_Abort (state, ARMul_DataAbortV);
+  else
+    ARMul_Icycles (state, 2, 0L);
+
+  return value;
+}
+
+static ARMword
+Iwmmxt_Load_Word (ARMul_State * state, ARMword address)
+{
+  ARMword value;
+
+  /* Check for a misaligned address.  */
+  if (address & 3)
+    {
+      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
+       ARMul_Abort (state, ARMul_DataAbortV);
+      else
+       address &= ~ 3;
+    }
+  
+  value = ARMul_LoadWordN (state, address);
+
+  if (state->Aborted)
+    ARMul_Abort (state, ARMul_DataAbortV);
+  else
+    ARMul_Icycles (state, 1, 0L);
+
+  return value;
+}
+
+static ARMword
+Iwmmxt_Load_Half_Word (ARMul_State * state, ARMword address)
+{
+  ARMword value;
+
+  /* Check for a misaligned address.  */
+  if (address & 1)
+    {
+      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
+       ARMul_Abort (state, ARMul_DataAbortV);
+      else
+       address &= ~ 1;
+    }
+
+  value = ARMul_LoadHalfWord (state, address);
+
+  if (state->Aborted)
+    ARMul_Abort (state, ARMul_DataAbortV);
+  else
+    ARMul_Icycles (state, 1, 0L);
+
+  return value;
+}
+
+static ARMword
+Iwmmxt_Load_Byte (ARMul_State * state, ARMword address)
+{
+  ARMword value;
+
+  value = ARMul_LoadByte (state, address);
+
+  if (state->Aborted)
+    ARMul_Abort (state, ARMul_DataAbortV);
+  else
+    ARMul_Icycles (state, 1, 0L);
+
+  return value;
+}
+
+static void
+Iwmmxt_Store_Double_Word (ARMul_State * state, ARMword address, ARMdword value)
+{
+  /* The address must be aligned on a 8 byte boundary.  */
+  if (address & 0x7)
+    {
+      fprintf (stderr, "iWMMXt: At addr 0x%x: Unaligned double word store to 0x%x\n",
+              (state->Reg[15] - 8) & ~0x3, address);
+#ifdef DEBUG
+#endif
+      /* No need to check for alignment traps.  An unaligned
+        double word store with alignment trapping disabled is
+        UNPREDICTABLE.  */
+      ARMul_Abort (state, ARMul_DataAbortV);
+    }
+
+  /* Store the words.  */
+  if (! state->bigendSig)
+    {
+      ARMul_StoreWordN (state, address, value);
+      ARMul_StoreWordN (state, address + 4, value >> 32);
+    }
+  else
+    {
+      ARMul_StoreWordN (state, address + 4, value);
+      ARMul_StoreWordN (state, address, value >> 32);
+    }
+
+  /* Check for data aborts.  */
+  if (state->Aborted)
+    ARMul_Abort (state, ARMul_DataAbortV);
+  else
+    ARMul_Icycles (state, 2, 0L);
+}
+
+static void
+Iwmmxt_Store_Word (ARMul_State * state, ARMword address, ARMword value)
+{
+  /* Check for a misaligned address.  */
+  if (address & 3)
+    {
+      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
+       ARMul_Abort (state, ARMul_DataAbortV);
+      else
+       address &= ~ 3;
+    }
+
+  ARMul_StoreWordN (state, address, value);
+
+  if (state->Aborted)
+    ARMul_Abort (state, ARMul_DataAbortV);
+}
+
+static void
+Iwmmxt_Store_Half_Word (ARMul_State * state, ARMword address, ARMword value)
+{
+  /* Check for a misaligned address.  */
+  if (address & 1)
+    {
+      if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN))
+       ARMul_Abort (state, ARMul_DataAbortV);
+      else
+       address &= ~ 1;
+    }
+
+  ARMul_StoreHalfWord (state, address, value);
+
+  if (state->Aborted)
+    ARMul_Abort (state, ARMul_DataAbortV);
+}
+
+static void
+Iwmmxt_Store_Byte (ARMul_State * state, ARMword address, ARMword value)
+{
+  ARMul_StoreByte (state, address, value);
+
+  if (state->Aborted)
+    ARMul_Abort (state, ARMul_DataAbortV);
+}
+
+static int
+WLDR (ARMul_State * state, ARMword instr)
+{
+  ARMword address;
+  int failed;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wldr\n");
+#endif  
+
+  address = Compute_Iwmmxt_Address (state, instr, & failed);
+  if (failed)
+    return ARMul_CANT;
+
+  if (BITS (28, 31) == 0xf)
+    {
+      /* WLDRW wCx */
+      wC [BITS (12, 15)] = Iwmmxt_Load_Word (state, address);
+    }
+  else if (BIT (8) == 0)
+    {
+      if (BIT (22) == 0)
+       /* WLDRB */
+       wR [BITS (12, 15)] = Iwmmxt_Load_Byte (state, address);
+      else
+       /* WLDRH */
+       wR [BITS (12, 15)] = Iwmmxt_Load_Half_Word (state, address);
+    }
+  else
+    {
+      if (BIT (22) == 0)
+       /* WLDRW wRd */
+       wR [BITS (12, 15)] = Iwmmxt_Load_Word (state, address);
+      else
+       /* WLDRD */
+       wR [BITS (12, 15)] = Iwmmxt_Load_Double_Word (state, address);
+    }
+
+  wC [wCon] |= WCON_MUP;
+
+  return ARMul_DONE;
+}
+
+static int
+WMAC (ARMword instr)
+{
+  int      i;
+  ARMdword t = 0;
+  ARMword  a, b;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wmac\n");
+#endif  
+
+  for (i = 0; i < 4; i++)
+    {
+      if (BIT (21))
+        {
+         /* Signed.  */
+         signed long s;
+
+         a = wRHALF (BITS (16, 19), i);
+         a = EXTEND16 (a);
+
+         b = wRHALF (BITS (0, 3), i);
+         b = EXTEND16 (b);
+
+         s = (signed long) a * (signed long) b;
+
+         (signed long long) t += s;
+        }
+      else
+        {
+         /* Unsigned.  */
+         a = wRHALF (BITS (16, 19), i);
+         b = wRHALF (BITS ( 0,  3), i);
+
+         t += a * b;
+        }
+    }
+
+  if (BIT (20))
+    wR [BITS (12, 15)] = 0;
+
+  if (BIT (21))        /* Signed.  */
+    (signed long long) wR[BITS (12, 15)] += (signed long long) t;
+  else
+    wR [BITS (12, 15)] += t;
+
+  wC [wCon] |= WCON_MUP;
+
+  return ARMul_DONE;
+}
+
+static int
+WMADD (ARMword instr)
+{
+  ARMdword r = 0;
+  int i;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wmadd\n");
+#endif  
+
+  for (i = 0; i < 2; i++)
+    {
+      ARMdword s1, s2;
+
+      if (BIT (21))    /* Signed.  */
+        {
+         signed long a, b;
+
+         a = wRHALF (BITS (16, 19), i * 2);
+         a = EXTEND16 (a);
+
+         b = wRHALF (BITS (0, 3), i * 2);
+         b = EXTEND16 (b);
+
+         (signed long) s1 = a * b;
+
+         a = wRHALF (BITS (16, 19), i * 2 + 1);
+         a = EXTEND16 (a);
+
+         b = wRHALF (BITS (0, 3), i * 2 + 1);
+         b = EXTEND16 (b);
+
+         (signed long) s2 = a * b;
+        }
+      else                     /* Unsigned.  */
+        {
+         unsigned long a, b;
+
+         a = wRHALF (BITS (16, 19), i * 2);
+         b = wRHALF (BITS ( 0,  3), i * 2);
+
+         (unsigned long) s1 = a * b;
+
+         a = wRHALF (BITS (16, 19), i * 2 + 1);
+         b = wRHALF (BITS ( 0,  3), i * 2 + 1);
+
+         (signed long) s2 = a * b;
+        }
+
+      r |= (ARMdword) ((s1 + s2) & 0xffffffff) << (i ? 32 : 0);
+    }
+
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= WCON_MUP;
+
+  return ARMul_DONE;
+}
+
+static int
+WMAX (ARMul_State * state, ARMword instr)
+{
+  ARMdword r = 0;
+  ARMdword s;
+  int      i;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wmax\n");
+#endif  
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      for (i = 0; i < 8; i++)
+       if (BIT (21))   /* Signed.  */
+         {
+           int a, b;
+
+           a = wRBYTE (BITS (16, 19), i);
+           a = EXTEND8 (a);
+
+           b = wRBYTE (BITS (0, 3), i);
+           b = EXTEND8 (b);
+
+           if (a > b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xff) << (i * 8);
+         }
+       else            /* Unsigned.  */
+         {
+           unsigned int a, b;
+
+           a = wRBYTE (BITS (16, 19), i);
+           b = wRBYTE (BITS (0, 3), i);
+
+           if (a > b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xff) << (i * 8);
+          }
+      break;
+
+    case Hqual:
+      for (i = 0; i < 4; i++)
+       if (BIT (21))   /* Signed.  */
+         {
+           int a, b;
+
+           a = wRHALF (BITS (16, 19), i);
+           a = EXTEND16 (a);
+
+           b = wRHALF (BITS (0, 3), i);
+           b = EXTEND16 (b);
+
+           if (a > b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xffff) << (i * 16);
+         }
+       else            /* Unsigned.  */
+         {
+           unsigned int a, b;
+
+           a = wRHALF (BITS (16, 19), i);
+           b = wRHALF (BITS (0, 3), i);
+
+           if (a > b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xffff) << (i * 16);
+          }
+      break;
+
+    case Wqual:
+      for (i = 0; i < 2; i++)
+       if (BIT (21))   /* Signed.  */
+         {
+           int a, b;
+
+           a = wRWORD (BITS (16, 19), i);
+           b = wRWORD (BITS (0, 3), i);
+
+           if (a > b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xffffffff) << (i * 32);
+         }
+       else
+         {
+           unsigned int a, b;
+
+           a = wRWORD (BITS (16, 19), i);
+           b = wRWORD (BITS (0, 3), i);
+
+           if (a > b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xffffffff) << (i * 32);
+          }
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= WCON_MUP;
+
+  return ARMul_DONE;
+}
+
+static int
+WMIN (ARMul_State * state, ARMword instr)
+{
+  ARMdword r = 0;
+  ARMdword s;
+  int      i;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wmin\n");
+#endif  
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      for (i = 0; i < 8; i++)
+       if (BIT (21))   /* Signed.  */
+         {
+           int a, b;
+
+           a = wRBYTE (BITS (16, 19), i);
+           a = EXTEND8 (a);
+
+           b = wRBYTE (BITS (0, 3), i);
+           b = EXTEND8 (b);
+
+           if (a < b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xff) << (i * 8);
+         }
+       else            /* Unsigned.  */
+         {
+           unsigned int a, b;
+
+           a = wRBYTE (BITS (16, 19), i);
+           b = wRBYTE (BITS (0, 3), i);
+
+           if (a < b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xff) << (i * 8);
+          }
+      break;
+
+    case Hqual:
+      for (i = 0; i < 4; i++)
+       if (BIT (21))   /* Signed.  */
+         {
+           int a, b;
+
+           a = wRHALF (BITS (16, 19), i);
+           a = EXTEND16 (a);
+
+           b = wRHALF (BITS (0, 3), i);
+           b = EXTEND16 (b);
+
+           if (a < b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xffff) << (i * 16);
+         }
+       else
+         {
+           /* Unsigned.  */
+           unsigned int a, b;
+
+           a = wRHALF (BITS (16, 19), i);
+           b = wRHALF (BITS ( 0,  3), i);
+
+           if (a < b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xffff) << (i * 16);
+          }
+      break;
+
+    case Wqual:
+      for (i = 0; i < 2; i++)
+       if (BIT (21))   /* Signed.  */
+         {
+           int a, b;
+
+           a = wRWORD (BITS (16, 19), i);
+           b = wRWORD (BITS ( 0,  3), i);
+
+           if (a < b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xffffffff) << (i * 32);
+         }
+       else
+         {
+           unsigned int a, b;
+
+           a = wRWORD (BITS (16, 19), i);
+           b = wRWORD (BITS (0, 3), i);
+
+           if (a < b)
+             s = a;
+           else
+             s = b;
+
+           r |= (s & 0xffffffff) << (i * 32);
+          }
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= WCON_MUP;
+  
+  return ARMul_DONE;
+}
+
+static int
+WMUL (ARMword instr)
+{
+  ARMdword r = 0;
+  ARMdword s;
+  int      i;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wmul\n");
+#endif  
+
+  for (i = 0; i < 4; i++)
+    if (BIT (21))      /* Signed.  */
+      {
+       long a, b;
+
+       a = wRHALF (BITS (16, 19), i);
+       a = EXTEND16 (a);
+
+       b = wRHALF (BITS (0, 3), i);
+       b = EXTEND16 (b);
+
+       s = a * b;
+
+       if (BIT (20))
+         r |= ((s >> 16) & 0xffff) << (i * 16);
+       else
+         r |= (s & 0xffff) << (i * 16);
+      }
+    else               /* Unsigned.  */
+      {
+       unsigned long a, b;
+
+       a = wRHALF (BITS (16, 19), i);
+       b = wRHALF (BITS (0, 3), i);
+
+       s = a * b;
+
+       if (BIT (20))
+         r |= ((s >> 16) & 0xffff) << (i * 16);
+       else
+         r |= (s & 0xffff) << (i * 16);
+      }
+
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= WCON_MUP;
+
+  return ARMul_DONE;
+}
+
+static int
+WOR (ARMword instr)
+{
+  ARMword psr = 0;
+  ARMdword result;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wor\n");
+#endif  
+
+  result = wR [BITS (16, 19)] | wR [BITS (0, 3)];
+  wR [BITS (12, 15)] = result;
+
+  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
+  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
+  
+  wC [wCASF] = psr;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WPACK (ARMul_State * state, ARMword instr)
+{
+  ARMdword r = 0;
+  ARMword  psr = 0;
+  ARMdword x;
+  ARMdword s;
+  int      i;
+  int      satrv[8];
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wpack\n");
+#endif  
+  switch (BITS (22, 23))
+    {
+    case Hqual:
+      for (i = 0; i < 8; i++)
+       {
+         x = wRHALF (i < 4 ? BITS (16, 19) : BITS (0, 3), i & 3);
+
+         switch (BITS (20, 21))
+           {
+           case UnsignedSaturation:
+             s = IwmmxtSaturateU8 (x, satrv + BITIDX8 (i));
+             break;
+
+           case SignedSaturation:
+             s = IwmmxtSaturateS8 (x, satrv + BITIDX8 (i));
+             break;
+
+           default:
+             ARMul_UndefInstr (state, instr);
+             return ARMul_DONE;
+           }
+
+         r |= (s & 0xff) << (i * 8);
+         SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
+         SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Wqual:
+      satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
+
+      for (i = 0; i < 4; i++)
+       {
+         x = wRWORD (i < 2 ? BITS (16, 19) : BITS (0, 3), i & 1);
+
+         switch (BITS (20, 21))
+           {
+           case UnsignedSaturation:
+             s = IwmmxtSaturateU16 (x, satrv + BITIDX16 (i));
+             break;
+
+           case SignedSaturation:
+             s = IwmmxtSaturateS16 (x, satrv + BITIDX16 (i));
+             break;
+
+           default:
+             ARMul_UndefInstr (state, instr);
+             return ARMul_DONE;
+           }
+
+         r |= (s & 0xffff) << (i * 16);
+         SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+         SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Dqual:
+      satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
+
+      for (i = 0; i < 2; i++)
+       {
+         x = wR [i ? BITS (0, 3) : BITS (16, 19)];
+
+         switch (BITS (20, 21))
+           {
+           case UnsignedSaturation:
+             s = IwmmxtSaturateU32 (x, satrv + BITIDX32 (i));
+             break;
+
+           case SignedSaturation:
+             s = IwmmxtSaturateS32 (x, satrv + BITIDX32 (i));
+             break;
+
+           default:
+             ARMul_UndefInstr (state, instr);
+             return ARMul_DONE;
+           }
+
+         r |= (s & 0xffffffff) << (i * 32);
+         SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+         SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  SET_wCSSFvec (satrv);
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WROR (ARMul_State * state, ARMword instr)
+{
+  ARMdword r = 0;
+  ARMdword s;
+  ARMword  psr = 0;
+  int      i;
+  int      shift;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wror\n");
+#endif  
+
+  DECODE_G_BIT (state, instr, shift);
+
+  switch (BITS (22, 23))
+    {
+    case Hqual:
+      shift &= 0xf;
+      for (i = 0; i < 4; i++)
+       {
+         s = ((wRHALF (BITS (16, 19), i) & 0xffff) << (16 - shift))
+           | ((wRHALF (BITS (16, 19), i) & 0xffff) >> shift);
+         r |= (s & 0xffff) << (i * 16);
+         SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+         SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Wqual:
+      shift &= 0x1f;
+      for (i = 0; i < 2; i++)
+       {
+         s = ((wRWORD (BITS (16, 19), i) & 0xffffffff) << (32 - shift))
+           | ((wRWORD (BITS (16, 19), i) & 0xffffffff) >> shift);
+         r |= (s & 0xffffffff) << (i * 32);
+         SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+         SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Dqual:
+      shift &= 0x3f;
+      r = (wR [BITS (16, 19)] >> shift)
+       | (wR [BITS (16, 19)] << (64 - shift));
+
+      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
+      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WSAD (ARMword instr)
+{
+  ARMdword r;
+  int      s;
+  int      i;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wsad\n");
+#endif  
+
+  /* Z bit.  */
+  r = BIT (20) ? 0 : (wR [BITS (12, 15)] & 0xffffffff);
+
+  if (BIT (22))
+    /* Half.  */
+    for (i = 0; i < 4; i++)
+      {
+       s = (wRHALF (BITS (16, 19), i) - wRHALF (BITS (0, 3), i));
+       r += abs (s);
+      }
+  else
+    /* Byte.  */
+    for (i = 0; i < 8; i++)
+      {
+       s = (wRBYTE (BITS (16, 19), i) - wRBYTE (BITS (0, 3), i));
+       r += abs (s);
+      }
+
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= WCON_MUP;
+
+  return ARMul_DONE;
+}
+
+static int
+WSHUFH (ARMword instr)
+{
+  ARMdword r = 0;
+  ARMword  psr = 0;
+  ARMdword s;
+  int      i;
+  int      imm8;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wshufh\n");
+#endif  
+
+  imm8 = (BITS (20, 23) << 4) | BITS (0, 3);
+
+  for (i = 0; i < 4; i++)
+    {
+      s = wRHALF (BITS (16, 19), ((imm8 >> (i * 2) & 3)) & 0xff);
+      r |= (s & 0xffff) << (i * 16);
+      SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+      SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WSLL (ARMul_State * state, ARMword instr)
+{
+  ARMdword r = 0;
+  ARMdword s;
+  ARMword  psr = 0;
+  int      i;
+  unsigned shift;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wsll\n");
+#endif  
+
+  DECODE_G_BIT (state, instr, shift);
+
+  switch (BITS (22, 23))
+    {
+    case Hqual:
+      for (i = 0; i < 4; i++)
+       {
+         if (shift > 15)
+           s = 0;
+         else
+           s = ((wRHALF (BITS (16, 19), i) & 0xffff) << shift);
+         r |= (s & 0xffff) << (i * 16);
+         SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+         SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Wqual:
+      for (i = 0; i < 2; i++)
+       {
+         if (shift > 31)
+           s = 0;
+         else
+           s = ((wRWORD (BITS (16, 19), i) & 0xffffffff) << shift);
+         r |= (s & 0xffffffff) << (i * 32);
+         SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+         SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Dqual:
+      if (shift > 63)
+       r = 0;
+      else
+       r = ((wR[BITS (16, 19)] & 0xffffffffffffffff) << shift);
+
+      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
+      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WSRA (ARMul_State * state, ARMword instr)
+{
+  ARMdword     r = 0;
+  ARMdword     s;
+  ARMword      psr = 0;
+  int          i;
+  unsigned     shift;
+  signed long  t;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wsra\n");
+#endif  
+
+  DECODE_G_BIT (state, instr, shift);
+
+  switch (BITS (22, 23))
+    {
+    case Hqual:
+      for (i = 0; i < 4; i++)
+       {
+         if (shift > 15)
+           t = (wRHALF (BITS (16, 19), i) & 0x8000) ? 0xffff : 0;
+         else
+           {
+             t = wRHALF (BITS (16, 19), i);
+             t = EXTEND16 (t);
+             t >>= shift;
+           }
+
+         s = t;
+         r |= (s & 0xffff) << (i * 16);
+         SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+         SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Wqual:
+      for (i = 0; i < 2; i++)
+       {
+         if (shift > 31)
+           t = (wRWORD (BITS (16, 19), i) & 0x80000000) ? 0xffffffff : 0;
+         else
+           {
+             t = wRWORD (BITS (16, 19), i);
+             t >>= shift;
+           }
+         s = t;
+         r |= (s & 0xffffffff) << (i * 32);
+         SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+         SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+       }
+      break;
+      
+    case Dqual:
+      if (shift > 63)
+       r = (wR [BITS (16, 19)] & 0x8000000000000000) ? 0xffffffffffffffff : 0;
+      else
+       r = ((signed long long) (wR[BITS (16, 19)] & 0xffffffffffffffff) >> shift);
+      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
+      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WSRL (ARMul_State * state, ARMword instr)
+{
+  ARMdword     r = 0;
+  ARMdword     s;
+  ARMword      psr = 0;
+  int          i;
+  unsigned int shift;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wsrl\n");
+#endif
+
+  DECODE_G_BIT (state, instr, shift);
+
+  switch (BITS (22, 23))
+    {
+    case Hqual:
+      for (i = 0; i < 4; i++)
+       {
+         if (shift > 15)
+           s = 0;
+         else
+           s = ((unsigned) (wRHALF (BITS (16, 19), i) & 0xffff) >> shift);
+
+         r |= (s & 0xffff) << (i * 16);
+         SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+         SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Wqual:
+      for (i = 0; i < 2; i++)
+       {
+         if (shift > 31)
+           s = 0;
+         else
+           s = ((unsigned long) (wRWORD (BITS (16, 19), i) & 0xffffffff) >> shift);
+
+         r |= (s & 0xffffffff) << (i * 32);
+         SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+         SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Dqual:
+      if (shift > 63)
+       r = 0;
+      else
+       r = (wR [BITS (16, 19)] & 0xffffffffffffffff) >> shift;
+
+      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
+      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WSTR (ARMul_State * state, ARMword instr)
+{
+  ARMword address;
+  int failed;
+
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wstr\n");
+#endif
+  
+  address = Compute_Iwmmxt_Address (state, instr, & failed);
+  if (failed)
+    return ARMul_CANT;
+
+  if (BITS (28, 31) == 0xf)
+    {
+      /* WSTRW wCx */
+      Iwmmxt_Store_Word (state, address, wC [BITS (12, 15)]);
+    }
+  else if (BIT (8) == 0)
+    {
+      if (BIT (22) == 0)
+       /* WSTRB */
+       Iwmmxt_Store_Byte (state, address, wR [BITS (12, 15)]);
+      else
+       /* WSTRH */
+       Iwmmxt_Store_Half_Word (state, address, wR [BITS (12, 15)]);
+    }
+  else
+    {
+      if (BIT (22) == 0)
+       /* WSTRW wRd */
+       Iwmmxt_Store_Word (state, address, wR [BITS (12, 15)]);
+      else
+       /* WSTRD */
+       Iwmmxt_Store_Double_Word (state, address, wR [BITS (12, 15)]);
+    }
+
+  return ARMul_DONE;
+}
+
+static int
+WSUB (ARMul_State * state, ARMword instr)
+{
+  ARMdword r = 0;
+  ARMword  psr = 0;
+  ARMdword x;
+  ARMdword s;
+  int      i;
+  int      carry;
+  int      overflow;
+  int      satrv[8];
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wsub\n");
+#endif  
+
+/* Subtract two numbers using the specified function,
+   leaving setting the carry bit as required.  */
+#define SUBx(x, y, m, f) \
+   (*f) (wRBITS (BITS (16, 19), (x), (y)) & (m), \
+         wRBITS (BITS ( 0,  3), (x), (y)) & (m), & carry, & overflow)
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      for (i = 0; i < 8; i++)
+        {
+         switch (BITS (20, 21))
+           {
+           case NoSaturation:
+             s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubS8);
+             satrv [BITIDX8 (i)] = 0;
+             r |= (s & 0xff) << (i * 8);
+             SIMD8_SET (psr, NBIT8 (s), SIMD_NBIT, i);
+             SIMD8_SET (psr, ZBIT8 (s), SIMD_ZBIT, i);
+             SIMD8_SET (psr, carry, SIMD_CBIT, i);
+             SIMD8_SET (psr, overflow, SIMD_VBIT, i);
+             break;
+
+           case UnsignedSaturation:
+             s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubU8);
+             x = IwmmxtSaturateU8 (s, satrv + BITIDX8 (i));
+             r |= (x & 0xff) << (i * 8);
+             SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
+             SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX8 (i)])
+               {
+                 SIMD8_SET (psr, carry,     SIMD_CBIT, i);
+                 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           case SignedSaturation:
+             s = SUBx ((i * 8), (i * 8) + 7, 0xff, SubS8);
+             x = IwmmxtSaturateS8 (s, satrv + BITIDX8 (i));
+             r |= (x & 0xff) << (i * 8);
+             SIMD8_SET (psr, NBIT8 (x), SIMD_NBIT, i);
+             SIMD8_SET (psr, ZBIT8 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX8 (i)])
+               {
+                 SIMD8_SET (psr, carry,     SIMD_CBIT, i);
+                 SIMD8_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           default:
+             ARMul_UndefInstr (state, instr);
+             return ARMul_DONE;
+           }
+       }
+      break;
+
+    case Hqual:
+      satrv[0] = satrv[2] = satrv[4] = satrv[6] = 0;
+
+      for (i = 0; i < 4; i++)
+       {
+         switch (BITS (20, 21))
+           {
+           case NoSaturation:
+             s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubU16);
+             satrv [BITIDX16 (i)] = 0;
+             r |= (s & 0xffff) << (i * 16);
+             SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+             SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+             SIMD16_SET (psr, carry,      SIMD_CBIT, i);
+             SIMD16_SET (psr, overflow,   SIMD_VBIT, i);
+             break;
+
+           case UnsignedSaturation:
+             s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubU16);
+             x = IwmmxtSaturateU16 (s, satrv + BITIDX16 (i));
+             r |= (x & 0xffff) << (i * 16);
+             SIMD16_SET (psr, NBIT16 (x & 0xffff), SIMD_NBIT, i);
+             SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX16 (i)])
+               {
+                 SIMD16_SET (psr, carry,    SIMD_CBIT, i);
+                 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           case SignedSaturation:
+             s = SUBx ((i * 16), (i * 16) + 15, 0xffff, SubS16);
+             x = IwmmxtSaturateS16 (s, satrv + BITIDX16 (i));
+             r |= (x & 0xffff) << (i * 16);
+             SIMD16_SET (psr, NBIT16 (x), SIMD_NBIT, i);
+             SIMD16_SET (psr, ZBIT16 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX16 (i)])
+               {
+                 SIMD16_SET (psr, carry,    SIMD_CBIT, i);
+                 SIMD16_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           default:
+             ARMul_UndefInstr (state, instr);
+             return ARMul_DONE;
+           }
+       }
+      break;
+
+    case Wqual:
+      satrv[0] = satrv[1] = satrv[2] = satrv[4] = satrv[5] = satrv[6] = 0;
+
+      for (i = 0; i < 2; i++)
+       {
+         switch (BITS (20, 21))
+           {
+           case NoSaturation:
+             s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubU32);
+             satrv[BITIDX32 (i)] = 0;
+             r |= (s & 0xffffffff) << (i * 32);
+             SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+             SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+             SIMD32_SET (psr, carry,      SIMD_CBIT, i);
+             SIMD32_SET (psr, overflow,   SIMD_VBIT, i);
+             break;
+
+           case UnsignedSaturation:
+             s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubU32);
+             x = IwmmxtSaturateU32 (s, satrv + BITIDX32 (i));
+             r |= (x & 0xffffffff) << (i * 32);
+             SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
+             SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX32 (i)])
+               {
+                 SIMD32_SET (psr, carry,    SIMD_CBIT, i);
+                 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           case SignedSaturation:
+             s = SUBx ((i * 32), (i * 32) + 31, 0xffffffff, SubS32);
+             x = IwmmxtSaturateS32 (s, satrv + BITIDX32 (i));
+             r |= (x & 0xffffffff) << (i * 32);
+             SIMD32_SET (psr, NBIT32 (x), SIMD_NBIT, i);
+             SIMD32_SET (psr, ZBIT32 (x), SIMD_ZBIT, i);
+             if (! satrv [BITIDX32 (i)])
+               {
+                 SIMD32_SET (psr, carry,    SIMD_CBIT, i);
+                 SIMD32_SET (psr, overflow, SIMD_VBIT, i);
+               }
+             break;
+
+           default:
+             ARMul_UndefInstr (state, instr);
+             return ARMul_DONE;
+           }
+       }
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wR [BITS (12, 15)] = r;
+  wC [wCASF] = psr;
+  SET_wCSSFvec (satrv);
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+#undef SUBx
+
+  return ARMul_DONE;
+}
+
+static int
+WUNPCKEH (ARMul_State * state, ARMword instr)
+{
+  ARMdword r = 0;
+  ARMword  psr = 0;
+  ARMdword s;
+  int      i;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wunpckeh\n");
+#endif  
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      for (i = 0; i < 4; i++)
+       {
+         s = wRBYTE (BITS (16, 19), i + 4);
+
+         if (BIT (21) && NBIT8 (s))
+           s |= 0xff00;
+
+         r |= (s & 0xffff) << (i * 16);
+         SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+         SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Hqual:
+      for (i = 0; i < 2; i++)
+       {
+         s = wRHALF (BITS (16, 19), i + 2);
+
+         if (BIT (21) && NBIT16 (s))
+           s |= 0xffff0000;
+
+         r |= (s & 0xffffffff) << (i * 32);
+         SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+         SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Wqual:
+      r = wRWORD (BITS (16, 19), 1);
+
+      if (BIT (21) && NBIT32 (r))
+       r |= 0xffffffff00000000;
+
+      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
+      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WUNPCKEL (ARMul_State * state, ARMword instr)
+{
+  ARMdword r = 0;
+  ARMword  psr = 0;
+  ARMdword s;
+  int      i;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wunpckel\n");
+#endif  
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      for (i = 0; i < 4; i++)
+       {
+         s = wRBYTE (BITS (16, 19), i);
+
+         if (BIT (21) && NBIT8 (s))
+           s |= 0xff00;
+
+         r |= (s & 0xffff) << (i * 16);
+         SIMD16_SET (psr, NBIT16 (s), SIMD_NBIT, i);
+         SIMD16_SET (psr, ZBIT16 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Hqual:
+      for (i = 0; i < 2; i++)
+       {
+         s = wRHALF (BITS (16, 19), i);
+
+         if (BIT (21) && NBIT16 (s))
+           s |= 0xffff0000;
+
+         r |= (s & 0xffffffff) << (i * 32);
+         SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, i);
+         SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, i);
+       }
+      break;
+
+    case Wqual:
+      r = wRWORD (BITS (16, 19), 0);
+
+      if (BIT (21) && NBIT32 (r))
+       r |= 0xffffffff00000000;
+
+      SIMD64_SET (psr, NBIT64 (r), SIMD_NBIT);
+      SIMD64_SET (psr, ZBIT64 (r), SIMD_ZBIT);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WUNPCKIH (ARMul_State * state, ARMword instr)
+{
+  ARMword  a, b;
+  ARMdword r = 0;
+  ARMword  psr = 0;
+  ARMdword s;
+  int      i;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wunpckih\n");
+#endif  
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      for (i = 0; i < 4; i++)
+       {
+         a = wRBYTE (BITS (16, 19), i + 4);
+         b = wRBYTE (BITS ( 0,  3), i + 4);
+         s = a | (b << 8);
+         r |= (s & 0xffff) << (i * 16);
+         SIMD8_SET (psr, NBIT8 (a), SIMD_NBIT, i * 2);
+         SIMD8_SET (psr, ZBIT8 (a), SIMD_ZBIT, i * 2);
+         SIMD8_SET (psr, NBIT8 (b), SIMD_NBIT, (i * 2) + 1);
+         SIMD8_SET (psr, ZBIT8 (b), SIMD_ZBIT, (i * 2) + 1);
+       }
+      break;
+      
+    case Hqual:
+      for (i = 0; i < 2; i++)
+       {
+         a = wRHALF (BITS (16, 19), i + 2);
+         b = wRHALF (BITS ( 0,  3), i + 2);
+         s = a | (b << 16);
+         r |= (s & 0xffffffff) << (i * 32);
+         SIMD16_SET (psr, NBIT16 (a), SIMD_NBIT, (i * 2));
+         SIMD16_SET (psr, ZBIT16 (a), SIMD_ZBIT, (i * 2));
+         SIMD16_SET (psr, NBIT16 (b), SIMD_NBIT, (i * 2) + 1);
+         SIMD16_SET (psr, ZBIT16 (b), SIMD_ZBIT, (i * 2) + 1);
+       }
+      break;
+
+    case Wqual:
+      a = wRWORD (BITS (16, 19), 1);
+      s = wRWORD (BITS ( 0,  3), 1);
+      r = a | (s << 32);
+
+      SIMD32_SET (psr, NBIT32 (a), SIMD_NBIT, 0);
+      SIMD32_SET (psr, ZBIT32 (a), SIMD_ZBIT, 0);
+      SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, 1);
+      SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, 1);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WUNPCKIL (ARMul_State * state, ARMword instr)
+{
+  ARMword  a, b;
+  ARMdword r = 0;
+  ARMword  psr = 0;
+  ARMdword s;
+  int      i;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wunpckil\n");
+#endif  
+
+  switch (BITS (22, 23))
+    {
+    case Bqual:
+      for (i = 0; i < 4; i++)
+       {
+         a = wRBYTE (BITS (16, 19), i);
+         b = wRBYTE (BITS ( 0,  3), i);
+         s = a | (b << 8);
+         r |= (s & 0xffff) << (i * 16);
+         SIMD8_SET (psr, NBIT8 (a), SIMD_NBIT, i * 2);
+         SIMD8_SET (psr, ZBIT8 (a), SIMD_ZBIT, i * 2);
+         SIMD8_SET (psr, NBIT8 (b), SIMD_NBIT, (i * 2) + 1);
+         SIMD8_SET (psr, ZBIT8 (b), SIMD_ZBIT, (i * 2) + 1);
+       }
+      break;
+
+    case Hqual:
+      for (i = 0; i < 2; i++)
+       {
+         a = wRHALF (BITS (16, 19), i);
+         b = wRHALF (BITS ( 0,  3), i);
+         s = a | (b << 16);
+         r |= (s & 0xffffffff) << (i * 32);
+         SIMD16_SET (psr, NBIT16 (a), SIMD_NBIT, (i * 2));
+         SIMD16_SET (psr, ZBIT16 (a), SIMD_ZBIT, (i * 2));
+         SIMD16_SET (psr, NBIT16 (b), SIMD_NBIT, (i * 2) + 1);
+         SIMD16_SET (psr, ZBIT16 (b), SIMD_ZBIT, (i * 2) + 1);
+       }
+      break;
+
+    case Wqual:
+      a = wRWORD (BITS (16, 19), 0);
+      s = wRWORD (BITS ( 0,  3), 0);
+      r = a | (s << 32);
+
+      SIMD32_SET (psr, NBIT32 (a), SIMD_NBIT, 0);
+      SIMD32_SET (psr, ZBIT32 (a), SIMD_ZBIT, 0);
+      SIMD32_SET (psr, NBIT32 (s), SIMD_NBIT, 1);
+      SIMD32_SET (psr, ZBIT32 (s), SIMD_ZBIT, 1);
+      break;
+
+    default:
+      ARMul_UndefInstr (state, instr);
+      return ARMul_DONE;
+    }
+
+  wC [wCASF] = psr;
+  wR [BITS (12, 15)] = r;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+static int
+WXOR (ARMword instr)
+{
+  ARMword psr = 0;
+  ARMdword result;
+
+  if ((read_cp15_reg (15, 0, 1) & 3) != 3)
+    return ARMul_CANT;
+
+#ifdef DEBUG
+  fprintf (stderr, "wxor\n");
+#endif  
+
+  result = wR [BITS (16, 19)] ^ wR [BITS (0, 3)];
+  wR [BITS (12, 15)] = result;
+
+  SIMD64_SET (psr, (result == 0), SIMD_ZBIT);
+  SIMD64_SET (psr, (result & (1ULL << 63)), SIMD_NBIT);
+  
+  wC [wCASF] = psr;
+  wC [wCon] |= (WCON_CUP | WCON_MUP);
+
+  return ARMul_DONE;
+}
+
+/* This switch table is moved to a seperate function in order
+   to work around a compiler bug in the host compiler...  */
+
+static int
+Process_Instruction (ARMul_State * state, ARMword instr)
+{
+  int status = ARMul_BUSY;
+
+  switch ((BITS (20, 23) << 8) | BITS (4, 11))
+    {
+    case 0x000: status = WOR (instr); break;
+    case 0x011: status = TMCR (state, instr); break;
+    case 0x100: status = WXOR (instr); break;
+    case 0x111: status = TMRC (state, instr); break;
+    case 0x300: status = WANDN (instr); break;
+    case 0x200: status = WAND (instr); break;
+
+    case 0x810: case 0xa10:
+      status = WMADD (instr); break;
+
+    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:
+      status = WUNPCKIL (state, instr); break;   
+    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:
+      status = WUNPCKIH (state, instr); break;
+    case 0x012: case 0x112: case 0x412: case 0x512:
+      status = WSAD (instr); break;
+    case 0x010: case 0x110: case 0x210: case 0x310:
+      status = WMUL (instr); break;
+    case 0x410: case 0x510: case 0x610: case 0x710:
+      status = WMAC (instr); break;
+    case 0x006: case 0x406: case 0x806: case 0xc06:
+      status = WCMPEQ (state, instr); break;
+    case 0x800: case 0x900: case 0xc00: case 0xd00:
+      status = WAVG2 (instr); break;
+    case 0x802: case 0x902: case 0xa02: case 0xb02:
+      status = WALIGNR (state, instr); break;
+    case 0x601: case 0x605: case 0x609: case 0x60d:
+      status = TINSR (state, instr); break;
+    case 0x107: case 0x507: case 0x907: case 0xd07:
+      status = TEXTRM (state, instr); break;
+    case 0x117: case 0x517: case 0x917: case 0xd17:
+      status = TEXTRC (state, instr); break;
+    case 0x401: case 0x405: case 0x409: case 0x40d:
+      status = TBCST (state, instr); break;
+    case 0x113: case 0x513: case 0x913: case 0xd13:
+      status = TANDC (state, instr); break;
+    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:
+      status = WACC (state, instr); break;
+    case 0x115: case 0x515: case 0x915: case 0xd15:
+      status = TORC (state, instr); break;
+    case 0x103: case 0x503: case 0x903: case 0xd03:
+      status = TMOVMSK (state, instr); break;
+    case 0x106: case 0x306: case 0x506: case 0x706:
+    case 0x906: case 0xb06: case 0xd06: case 0xf06:
+      status = WCMPGT (state, instr); break;
+    case 0x00e: case 0x20e: case 0x40e: case 0x60e:
+    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
+      status = WUNPCKEL (state, instr); break;
+    case 0x00c: case 0x20c: case 0x40c: case 0x60c:
+    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
+      status = WUNPCKEH (state, instr); break;
+    case 0x204: case 0x604: case 0xa04: case 0xe04:
+    case 0x214: case 0x614: case 0xa14: case 0xe14:
+      status = WSRL (state, instr); break;
+    case 0x004: case 0x404: case 0x804: case 0xc04:
+    case 0x014: case 0x414: case 0x814: case 0xc14:
+      status = WSRA (state, instr); break;
+    case 0x104: case 0x504: case 0x904: case 0xd04:
+    case 0x114: case 0x514: case 0x914: case 0xd14:
+      status = WSLL (state, instr); break;
+    case 0x304: case 0x704: case 0xb04: case 0xf04:
+    case 0x314: case 0x714: case 0xb14: case 0xf14:
+      status = WROR (state, instr); break;
+    case 0x116: case 0x316: case 0x516: case 0x716:
+    case 0x916: case 0xb16: case 0xd16: case 0xf16:
+      status = WMIN (state, instr); break;
+    case 0x016: case 0x216: case 0x416: case 0x616:
+    case 0x816: case 0xa16: case 0xc16: case 0xe16:
+      status = WMAX (state, instr); break;
+    case 0x002: case 0x102: case 0x202: case 0x302:
+    case 0x402: case 0x502: case 0x602: case 0x702:
+      status = WALIGNI (instr); break;
+    case 0x01a: case 0x11a: case 0x21a: case 0x31a:
+    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
+    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
+    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
+      status = WSUB (state, instr); break;
+    case 0x01e: case 0x11e: case 0x21e: case 0x31e:      
+    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
+    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
+    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
+      status = WSHUFH (instr); break;
+    case 0x018: case 0x118: case 0x218: case 0x318:
+    case 0x418: case 0x518: case 0x618: case 0x718:
+    case 0x818: case 0x918: case 0xa18: case 0xb18:
+    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
+      status = WADD (state, instr); break;
+    case 0x008: case 0x108: case 0x208: case 0x308:
+    case 0x408: case 0x508: case 0x608: case 0x708:
+    case 0x808: case 0x908: case 0xa08: case 0xb08:
+    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
+      status = WPACK (state, instr); break;
+    case 0x201: case 0x203: case 0x205: case 0x207:
+    case 0x209: case 0x20b: case 0x20d: case 0x20f:
+    case 0x211: case 0x213: case 0x215: case 0x217:      
+    case 0x219: case 0x21b: case 0x21d: case 0x21f:      
+      switch (BITS (16, 19))
+       {
+       case 0x0: status = TMIA (state, instr); break;
+       case 0x8: status = TMIAPH (state, instr); break;
+       case 0xc:
+       case 0xd:
+       case 0xe:
+       case 0xf: status = TMIAxy (state, instr); break;
+       default: break;
+       }
+      break;
+    default:
+      break;
+    }
+  return status;
+}
+
+/* Process a possibly Intel(r) Wireless MMX(tm) technology instruction.
+   Return true if the instruction was handled.  */
+
+int
+ARMul_HandleIwmmxt (ARMul_State * state, ARMword instr)
+{     
+  int status = ARMul_BUSY;
+
+  if (BITS (24, 27) == 0xe)
+    {
+      status = Process_Instruction (state, instr);
+    }
+  else if (BITS (25, 27) == 0x6)
+    {
+      if (BITS (4, 11) == 0x0 && BITS (20, 24) == 0x4)
+       status = TMCRR (state, instr);
+      else if (BITS (9, 11) == 0x0)
+       {
+         if (BIT (20) == 0x0)
+           status = WSTR (state, instr);
+         else if (BITS (20, 24) == 0x5)
+           status = TMRRC (state, instr);
+         else
+           status = WLDR (state, instr);
+       }
+    }
+
+  if (status == ARMul_CANT)
+    {
+      /* If the instruction was a recognised but illegal,
+        perform the abort here rather than returning false.
+        If we return false then ARMul_MRC may be called which
+        will still abort, but which also perform the register
+        transfer...  */
+      ARMul_Abort (state, ARMul_UndefinedInstrV);
+      status = ARMul_DONE;
+    }
+
+  return status == ARMul_DONE;
+}
+
+int
+Fetch_Iwmmxt_Register (unsigned int regnum, unsigned char * memory)
+{
+  if (regnum >= 16)
+    {
+      memcpy (memory, wC + (regnum - 16), sizeof wC [0]);
+      return sizeof wC [0];
+    }
+  else
+    {
+      memcpy (memory, wR + regnum, sizeof wR [0]);
+      return sizeof wR [0];
+    }
+}
+
+int
+Store_Iwmmxt_Register (unsigned int regnum, unsigned char * memory)
+{
+  if (regnum >= 16)
+    {
+      memcpy (wC + (regnum - 16), memory, sizeof wC [0]);
+      return sizeof wC [0];
+    }
+  else
+    {
+      memcpy (wR + regnum, memory, sizeof wR [0]);
+      return sizeof wR [0];
+    }
+}
diff --git a/sim/arm/iwmmxt.h b/sim/arm/iwmmxt.h
new file mode 100644 (file)
index 0000000..e25feab
--- /dev/null
@@ -0,0 +1,28 @@
+/*  iwmmxt.h -- Intel(r) Wireless MMX(tm) technology co-processor interface.
+    Copyright (C) 2002 Free Software Foundation, Inc.
+    Contributed by matthew green (mrg@redhat.com).
+    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.
+    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. */
+
+extern unsigned IwmmxtLDC (ARMul_State *, unsigned, ARMword, ARMword);
+extern unsigned IwmmxtSTC (ARMul_State *, unsigned, ARMword, ARMword *);
+extern unsigned IwmmxtMCR (ARMul_State *, unsigned, ARMword, ARMword);
+extern unsigned IwmmxtMRC (ARMul_State *, unsigned, ARMword, ARMword *);
+extern unsigned IwmmxtCDP (ARMul_State *, unsigned, ARMword);
+
+extern int ARMul_HandleIwmmxt (ARMul_State *, ARMword);
+
+extern int Fetch_Iwmmxt_Register (unsigned int, unsigned char *);
+extern int Store_Iwmmxt_Register (unsigned int, unsigned char *);
diff --git a/sim/arm/maverick.c b/sim/arm/maverick.c
new file mode 100644 (file)
index 0000000..82871f9
--- /dev/null
@@ -0,0 +1,1291 @@
+/*  maverick.c -- Cirrus/DSP co-processor interface.
+    Copyright (C) 2003 Free Software Foundation, Inc.
+    Contributed by Aldy Hernandez (aldyh@redhat.com).
+    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.
+    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 <assert.h>
+#include "armdefs.h"
+#include "ansidecl.h"
+#include "armemu.h"
+
+/*#define CIRRUS_DEBUG 1       /**/
+#if CIRRUS_DEBUG
+#  define printfdbg printf
+#else
+#  define printfdbg printf_nothing
+#endif
+
+#define POS64(i) ( (~(i)) >> 63 )
+#define NEG64(i) ( (i) >> 63 )
+
+/* Define Co-Processor instruction handlers here.  */
+
+/* Here's ARMulator's DSP definition.  A few things to note:
+   1) it has 16 64-bit registers and 4 72-bit accumulators
+   2) you can only access its registers with MCR and MRC.  */
+
+/* We can't define these in here because this file might not be linked
+   unless the target is arm9e-*.  They are defined in wrapper.c.
+   Eventually the simulator should be made to handle any coprocessor
+   at run time.  */
+struct maverick_regs
+{
+  union
+  {
+    int i;
+    float f;
+  } upper;
+  
+  union
+  {
+    int i;
+    float f;
+  } lower;
+};
+
+union maverick_acc_regs
+{
+  long double ld;              /* Acc registers are 72-bits.  */
+};
+
+struct maverick_regs DSPregs[16];
+union maverick_acc_regs DSPacc[4];
+ARMword DSPsc;
+
+#define DEST_REG       (BITS (12, 15))
+#define SRC1_REG       (BITS (16, 19))
+#define SRC2_REG       (BITS (0, 3))
+
+static int lsw_int_index, msw_int_index;
+static int lsw_float_index, msw_float_index;
+
+static double mv_getRegDouble (int);
+static long long mv_getReg64int (int);
+static void mv_setRegDouble (int, double val);
+static void mv_setReg64int (int, long long val);
+
+static union
+{
+  double d;
+  long long ll;
+  int ints[2];
+} reg_conv;
+
+static void
+printf_nothing (void * foo, ...)
+{
+}
+
+static void
+cirrus_not_implemented (char * insn)
+{
+  fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn);
+  fprintf (stderr, "aborting!\n");
+  
+  exit (1);
+}
+
+static unsigned
+DSPInit (ARMul_State * state)
+{
+  ARMul_ConsolePrint (state, ", DSP present");
+  return TRUE;
+}
+
+unsigned
+DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED,
+        unsigned      type  ATTRIBUTE_UNUSED,
+        ARMword       instr,
+        ARMword *     value)
+{
+  switch (BITS (5, 7))
+    {
+    case 0: /* cfmvrdl */
+      /* Move lower half of a DF stored in a DSP reg into an Arm reg.  */
+      printfdbg ("cfmvrdl\n");
+      printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i);
+      printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
+      
+      *value = (ARMword) DSPregs[SRC1_REG].lower.i;
+      break;
+      
+    case 1: /* cfmvrdh */
+      /* Move upper half of a DF stored in a DSP reg into an Arm reg.  */
+      printfdbg ("cfmvrdh\n");
+      printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i);
+      printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG));
+      
+      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
+      break;
+      
+    case 2: /* cfmvrs */
+      /* Move SF from upper half of a DSP register to an Arm register.  */
+      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
+      printfdbg ("cfmvrs = mvf%d <-- %f\n",
+                SRC1_REG,
+                DSPregs[SRC1_REG].upper.f);
+      break;
+      
+#ifdef doesnt_work
+    case 4: /* cfcmps */
+      {
+       float a, b;
+       int n, z, c, v;
+
+       a = DSPregs[SRC1_REG].upper.f;
+       b = DSPregs[SRC2_REG].upper.f;
+
+       printfdbg ("cfcmps\n");
+       printfdbg ("\tcomparing %f and %f\n", a, b);
+
+       z = a == b;             /* zero */
+       n = a != b;             /* negative */
+       v = a > b;              /* overflow */
+       c = 0;                  /* carry */
+       *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+       break;
+      }
+      
+    case 5: /* cfcmpd */
+      {
+       double a, b;
+       int n, z, c, v;
+
+       a = mv_getRegDouble (SRC1_REG);
+       b = mv_getRegDouble (SRC2_REG);
+
+       printfdbg ("cfcmpd\n");
+       printfdbg ("\tcomparing %g and %g\n", a, b);
+
+       z = a == b;             /* zero */
+       n = a != b;             /* negative */
+       v = a > b;              /* overflow */
+       c = 0;                  /* carry */
+       *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+       break;
+      }
+#else
+      case 4: /* cfcmps */
+        {
+         float a, b;
+         int n, z, c, v;
+
+         a = DSPregs[SRC1_REG].upper.f;
+         b = DSPregs[SRC2_REG].upper.f;
+  
+         printfdbg ("cfcmps\n");
+         printfdbg ("\tcomparing %f and %f\n", a, b);
+
+         z = a == b;           /* zero */
+         n = a < b;            /* negative */
+         c = a > b;            /* carry */
+         v = 0;                /* fixme */
+         printfdbg ("\tz = %d, n = %d\n", z, n);
+         *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+         break;
+        }
+       
+      case 5: /* cfcmpd */
+        {
+         double a, b;
+         int n, z, c, v;
+
+         a = mv_getRegDouble (SRC1_REG);
+         b = mv_getRegDouble (SRC2_REG);
+  
+         printfdbg ("cfcmpd\n");
+         printfdbg ("\tcomparing %g and %g\n", a, b);
+  
+         z = a == b;           /* zero */
+         n = a < b;            /* negative */
+         c = a > b;            /* carry */
+         v = 0;                /* fixme */
+         *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+         break;
+        }
+#endif
+    default:
+      fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr);
+      cirrus_not_implemented ("unknown");
+      break;
+    }
+
+  return ARMul_DONE;
+}
+
+unsigned
+DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED,
+        unsigned      type  ATTRIBUTE_UNUSED,
+        ARMword       instr,
+        ARMword *     value)
+{
+  switch (BITS (5, 7))
+    {
+    case 0: /* cfmvr64l */
+      /* Move lower half of 64bit int from Cirrus to Arm.  */
+      *value = (ARMword) DSPregs[SRC1_REG].lower.i;
+      printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n",
+                DEST_REG,
+                (int) *value);
+      break;
+      
+    case 1: /* cfmvr64h */
+      /* Move upper half of 64bit int from Cirrus to Arm.  */
+      *value = (ARMword) DSPregs[SRC1_REG].upper.i;
+      printfdbg ("cfmvr64h <-- %d\n", (int) *value);
+      break;
+      
+    case 4: /* cfcmp32 */
+      {
+       int res;
+       int n, z, c, v;
+       unsigned int a, b;
+
+       printfdbg ("cfcmp32 mvfx%d - mvfx%d\n",
+                  SRC1_REG,
+                  SRC2_REG);
+
+       /* FIXME: see comment for cfcmps.  */
+       a = DSPregs[SRC1_REG].lower.i;
+       b = DSPregs[SRC2_REG].lower.i;
+
+       res = DSPregs[SRC1_REG].lower.i - DSPregs[SRC2_REG].lower.i;
+       /* zero */
+       z = res == 0;
+       /* negative */
+       n = res < 0;
+       /* overflow */
+       v = SubOverflow (DSPregs[SRC1_REG].lower.i, DSPregs[SRC2_REG].lower.i,
+                        res);
+       /* carry */
+       c = (NEG (a) && POS (b) ||
+            (NEG (a) && POS (res)) || (POS (b) && POS (res)));
+
+       *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+       break;
+      }
+      
+    case 5: /* cfcmp64 */
+      {
+       long long res;
+       int n, z, c, v;
+       unsigned long long a, b;
+
+       printfdbg ("cfcmp64 mvdx%d - mvdx%d\n",
+                  SRC1_REG,
+                  SRC2_REG);
+
+       /* fixme: see comment for cfcmps.  */
+
+       a = mv_getReg64int (SRC1_REG);
+       b = mv_getReg64int (SRC2_REG);
+
+       res = mv_getReg64int (SRC1_REG) - mv_getReg64int (SRC2_REG);
+       /* zero */
+       z = res == 0;
+       /* negative */
+       n = res < 0;
+       /* overflow */
+       v = ((NEG64 (a) && POS64 (b) && POS64 (res))
+            || (POS64 (a) && NEG64 (b) && NEG64 (res)));
+       /* carry */
+       c = (NEG64 (a) && POS64 (b) ||
+            (NEG64 (a) && POS64 (res)) || (POS64 (b) && POS64 (res)));
+
+       *value = (n << 31) | (z << 30) | (c << 29) | (v << 28);
+       break;
+      }
+      
+    default:
+      fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr);
+      cirrus_not_implemented ("unknown");
+      break;
+    }
+
+  return ARMul_DONE;
+}
+
+unsigned
+DSPMRC6 (ARMul_State * state ATTRIBUTE_UNUSED,
+        unsigned      type  ATTRIBUTE_UNUSED,
+        ARMword       instr,
+        ARMword *     value)
+{
+  switch (BITS (5, 7))
+    {
+    case 0: /* cfmval32 */
+      cirrus_not_implemented ("cfmval32");
+      break;
+      
+    case 1: /* cfmvam32 */
+      cirrus_not_implemented ("cfmvam32");
+      break;
+      
+    case 2: /* cfmvah32 */
+      cirrus_not_implemented ("cfmvah32");
+      break;
+      
+    case 3: /* cfmva32 */
+      cirrus_not_implemented ("cfmva32");
+      break;
+      
+    case 4: /* cfmva64 */
+      cirrus_not_implemented ("cfmva64");
+      break;
+      
+    case 5: /* cfmvsc32 */
+      cirrus_not_implemented ("cfmvsc32");
+      break;
+      
+    default:
+      fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr);
+      cirrus_not_implemented ("unknown");
+      break;
+    }
+
+  return ARMul_DONE;
+}
+
+unsigned
+DSPMCR4 (ARMul_State * state,
+        unsigned      type ATTRIBUTE_UNUSED,
+        ARMword       instr,
+        ARMword       value)
+{
+  switch (BITS (5, 7))
+    {
+    case 0: /* cfmvdlr */
+      /* Move the lower half of a DF value from an Arm register into
+        the lower half of a Cirrus register.  */
+      printfdbg ("cfmvdlr <-- 0x%x\n", (int) value);
+      DSPregs[SRC1_REG].lower.i = (int) value;
+      break;
+      
+    case 1: /* cfmvdhr */
+      /* Move the upper half of a DF value from an Arm register into
+        the upper half of a Cirrus register.  */
+      printfdbg ("cfmvdhr <-- 0x%x\n", (int) value);
+      DSPregs[SRC1_REG].upper.i = (int) value;
+      break;
+      
+    case 2: /* cfmvsr */
+      /* Move SF from Arm register into upper half of Cirrus register.  */
+      printfdbg ("cfmvsr <-- 0x%x\n", (int) value);
+      DSPregs[SRC1_REG].upper.i = (int) value;
+      break;
+      
+    default:
+      fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr);
+      cirrus_not_implemented ("unknown");
+      break;
+    }
+
+  return ARMul_DONE;
+}
+
+unsigned
+DSPMCR5 (ARMul_State * state,
+        unsigned      type   ATTRIBUTE_UNUSED,
+        ARMword       instr,
+        ARMword       value)
+{
+  union
+  {
+    int s;
+    unsigned int us;
+  } val;
+
+  switch (BITS (5, 7))
+    {
+    case 0: /* cfmv64lr */
+      /* Move lower half of a 64bit int from an ARM register into the
+         lower half of a DSP register and sign extend it.  */
+      printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG, (int) value);
+      DSPregs[SRC1_REG].lower.i = (int) value;
+      break;
+      
+    case 1: /* cfmv64hr */
+      /* Move upper half of a 64bit int from an ARM register into the
+        upper half of a DSP register.  */
+      printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n",
+                SRC1_REG,
+                (int) value);
+      DSPregs[SRC1_REG].upper.i = (int) value;
+      break;
+      
+    case 2: /* cfrshl32 */
+      printfdbg ("cfrshl32\n");
+      val.us = value;
+      if (val.s > 0)
+       DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i << value;
+      else
+       DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -value;
+      break;
+      
+    case 3: /* cfrshl64 */
+      printfdbg ("cfrshl64\n");
+      val.us = value;
+      if (val.s > 0)
+       mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) << value);
+      else
+       mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) >> -value);
+      break;
+      
+    default:
+      fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr);
+      cirrus_not_implemented ("unknown");
+      break;
+    }
+
+  return ARMul_DONE;
+}
+
+unsigned
+DSPMCR6 (ARMul_State * state,
+        unsigned      type   ATTRIBUTE_UNUSED,
+        ARMword       instr,
+        ARMword       value)
+{
+  switch (BITS (5, 7))
+    {
+    case 0: /* cfmv32al */
+      cirrus_not_implemented ("cfmv32al");
+      break;
+      
+    case 1: /* cfmv32am */
+      cirrus_not_implemented ("cfmv32am");
+      break;
+      
+    case 2: /* cfmv32ah */
+      cirrus_not_implemented ("cfmv32ah");
+      break;
+      
+    case 3: /* cfmv32a */
+      cirrus_not_implemented ("cfmv32a");
+      break;
+      
+    case 4: /* cfmv64a */
+      cirrus_not_implemented ("cfmv64a");
+      break;
+      
+    case 5: /* cfmv32sc */
+      cirrus_not_implemented ("cfmv32sc");
+      break;
+      
+    default:
+      fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr);
+      cirrus_not_implemented ("unknown");
+      break;
+    }
+
+  return ARMul_DONE;
+}
+
+unsigned
+DSPLDC4 (ARMul_State * state ATTRIBUTE_UNUSED,
+        unsigned      type,
+        ARMword       instr,
+        ARMword       data)
+{
+  static unsigned words;
+
+  if (type != ARMul_DATA)
+    {
+      words = 0;
+      return ARMul_DONE;
+    }
+  
+  if (BIT (22))
+    {                          /* it's a long access, get two words */
+      /* cfldrd */
+
+      printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n",
+                data, words, state->bigendSig, DEST_REG);
+      
+      if (words == 0)
+       {
+         if (state->bigendSig)
+           DSPregs[DEST_REG].upper.i = (int) data;
+         else
+           DSPregs[DEST_REG].lower.i = (int) data;
+       }
+      else
+       {
+         if (state->bigendSig)
+           DSPregs[DEST_REG].lower.i = (int) data;
+         else
+           DSPregs[DEST_REG].upper.i = (int) data;
+       }
+      
+      ++ words;
+      
+      if (words == 2)
+       {
+         printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG,
+                    mv_getRegDouble (DEST_REG));
+         
+         return ARMul_DONE;
+       }
+      else
+       return ARMul_INC;
+    }
+  else
+    {
+      /* Get just one word.  */
+      
+      /* cfldrs */
+      printfdbg ("cfldrs\n");
+
+      DSPregs[DEST_REG].upper.i = (int) data;
+
+      printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG,
+                DSPregs[DEST_REG].upper.f);
+
+      return ARMul_DONE;
+    }
+}
+
+unsigned
+DSPLDC5 (ARMul_State * state ATTRIBUTE_UNUSED,
+        unsigned      type,
+        ARMword       instr,
+        ARMword       data)
+{
+  static unsigned words;
+
+  if (type != ARMul_DATA)
+    {
+      words = 0;
+      return ARMul_DONE;
+    }
+  
+  if (BIT (22))
+    {
+      /* It's a long access, get two words.  */
+      
+      /* cfldr64 */
+      printfdbg ("cfldr64: %d\n", data);
+
+      if (words == 0)
+       {
+         if (state->bigendSig)
+           DSPregs[DEST_REG].upper.i = (int) data;
+         else
+           DSPregs[DEST_REG].lower.i = (int) data;
+       }
+      else
+       {
+         if (state->bigendSig)
+           DSPregs[DEST_REG].lower.i = (int) data;
+         else
+           DSPregs[DEST_REG].upper.i = (int) data;
+       }
+      
+      ++ words;
+      
+      if (words == 2)
+       {
+         printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG,
+                    mv_getReg64int (DEST_REG));
+         
+         return ARMul_DONE;
+       }
+      else
+       return ARMul_INC;
+    }
+  else
+    {
+      /* Get just one word.  */
+      
+      /* cfldr32 */
+      printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data);
+      
+      /* 32bit ints should be sign extended to 64bits when loaded.  */
+      mv_setReg64int (DEST_REG, (long long) data);
+
+      return ARMul_DONE;
+    }
+}
+
+unsigned
+DSPSTC4 (ARMul_State * state ATTRIBUTE_UNUSED,
+        unsigned      type,
+        ARMword       instr,
+        ARMword *     data)
+{
+  static unsigned words;
+
+  if (type != ARMul_DATA)
+    {
+      words = 0;
+      return ARMul_DONE;
+    }
+  
+  if (BIT (22))
+    {
+      /* It's a long access, get two words.  */
+      /* cfstrd */
+      printfdbg ("cfstrd\n");
+
+      if (words == 0)
+       {
+         if (state->bigendSig)
+           *data = (ARMword) DSPregs[DEST_REG].upper.i;
+         else
+           *data = (ARMword) DSPregs[DEST_REG].lower.i;
+       }
+      else
+       {
+         if (state->bigendSig)
+           *data = (ARMword) DSPregs[DEST_REG].lower.i;
+         else
+           *data = (ARMword) DSPregs[DEST_REG].upper.i;
+       }
+      
+      ++ words;
+      
+      if (words == 2)
+       {
+         printfdbg ("\tmem = mvd%d = %g\n", DEST_REG,
+                    mv_getRegDouble (DEST_REG));
+         
+         return ARMul_DONE;
+       }
+      else
+       return ARMul_INC;
+    }
+  else
+    {
+      /* Get just one word.  */
+      /* cfstrs */
+      printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG,
+                DSPregs[DEST_REG].upper.f);
+
+      *data = (ARMword) DSPregs[DEST_REG].upper.i;
+
+      return ARMul_DONE;
+    }
+}
+
+unsigned
+DSPSTC5 (ARMul_State * state ATTRIBUTE_UNUSED,
+        unsigned      type,
+        ARMword       instr,
+        ARMword *     data)
+{
+  static unsigned words;
+
+  if (type != ARMul_DATA)
+    {
+      words = 0;
+      return ARMul_DONE;
+    }
+  
+  if (BIT (22))
+    {
+      /* It's a long access, store two words.  */
+      /* cfstr64 */
+      printfdbg ("cfstr64\n");
+
+      if (words == 0)
+       {
+         if (state->bigendSig)
+           *data = (ARMword) DSPregs[DEST_REG].upper.i;
+         else
+           *data = (ARMword) DSPregs[DEST_REG].lower.i;
+       }
+      else
+       {
+         if (state->bigendSig)
+           *data = (ARMword) DSPregs[DEST_REG].lower.i;
+         else
+           *data = (ARMword) DSPregs[DEST_REG].upper.i;
+       }
+      
+      ++ words;
+      
+      if (words == 2)
+       {
+         printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG,
+                    mv_getReg64int (DEST_REG));
+         
+         return ARMul_DONE;
+       }
+      else
+       return ARMul_INC;
+    }
+  else
+    {
+      /* Store just one word.  */
+      /* cfstr32 */
+      *data = (ARMword) DSPregs[DEST_REG].lower.i;
+      
+      printfdbg ("cfstr32 MEM = %d\n", (int) *data);
+
+      return ARMul_DONE;
+    }
+}
+
+unsigned
+DSPCDP4 (ARMul_State * state,
+        unsigned      type,
+        ARMword       instr)
+{
+  int opcode2;
+
+  opcode2 = BITS (5,7);
+
+  switch (BITS (20,21))
+    {
+    case 0:
+      switch (opcode2)
+       {
+       case 0: /* cfcpys */
+         printfdbg ("cfcpys mvf%d = mvf%d = %f\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    DSPregs[SRC1_REG].upper.f);
+         DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f;
+         break;
+         
+       case 1: /* cfcpyd */
+         printfdbg ("cfcpyd mvd%d = mvd%d = %g\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    mv_getRegDouble (SRC1_REG));
+         mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG));
+         break;
+         
+       case 2: /* cfcvtds */
+         printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    (float) mv_getRegDouble (SRC1_REG));
+         DSPregs[DEST_REG].upper.f = (float) mv_getRegDouble (SRC1_REG);
+         break;
+         
+       case 3: /* cfcvtsd */
+         printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    (double) DSPregs[SRC1_REG].upper.f);
+         mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].upper.f);
+         break;
+         
+       case 4: /* cfcvt32s */
+         printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    (float) DSPregs[SRC1_REG].lower.i);
+         DSPregs[DEST_REG].upper.f = (float) DSPregs[SRC1_REG].lower.i;
+         break;
+         
+       case 5: /* cfcvt32d */
+         printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    (double) DSPregs[SRC1_REG].lower.i);
+         mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].lower.i);
+         break;
+         
+       case 6: /* cfcvt64s */
+         printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    (float) mv_getReg64int (SRC1_REG));
+         DSPregs[DEST_REG].upper.f = (float) mv_getReg64int (SRC1_REG);
+         break;
+         
+       case 7: /* cfcvt64d */
+         printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    (double) mv_getReg64int (SRC1_REG));
+         mv_setRegDouble (DEST_REG, (double) mv_getReg64int (SRC1_REG));
+         break;
+       }
+      break;
+
+    case 1:
+      switch (opcode2)
+       {
+       case 0: /* cfmuls */
+         printfdbg ("cfmuls mvf%d = mvf%d = %f\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    DSPregs[SRC1_REG].upper.f * DSPregs[SRC2_REG].upper.f);
+                    
+         DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
+           * DSPregs[SRC2_REG].upper.f;
+         break;
+         
+       case 1: /* cfmuld */
+         printfdbg ("cfmuld mvd%d = mvd%d = %g\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    mv_getRegDouble (SRC1_REG) * mv_getRegDouble (SRC2_REG));
+
+         mv_setRegDouble (DEST_REG,
+                          mv_getRegDouble (SRC1_REG)
+                          * mv_getRegDouble (SRC2_REG));
+         break;
+         
+       default:
+         fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
+         cirrus_not_implemented ("unknown");
+         break;
+       }
+      break;
+
+    case 3:
+      switch (opcode2)
+       {
+       case 0: /* cfabss */
+         DSPregs[DEST_REG].upper.f = (DSPregs[SRC1_REG].upper.f < 0.0F ?
+                                      -DSPregs[SRC1_REG].upper.f
+                                      : DSPregs[SRC1_REG].upper.f);
+         printfdbg ("cfabss mvf%d = |mvf%d| = %f\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    DSPregs[DEST_REG].upper.f);
+         break;
+         
+       case 1: /* cfabsd */
+         mv_setRegDouble (DEST_REG,
+                          (mv_getRegDouble (SRC1_REG) < 0.0 ?
+                           -mv_getRegDouble (SRC1_REG)
+                           : mv_getRegDouble (SRC1_REG)));
+         printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    mv_getRegDouble (DEST_REG));
+         break;
+         
+       case 2: /* cfnegs */
+         DSPregs[DEST_REG].upper.f = -DSPregs[SRC1_REG].upper.f;
+         printfdbg ("cfnegs mvf%d = -mvf%d = %f\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    DSPregs[DEST_REG].upper.f);
+         break;
+         
+       case 3: /* cfnegd */
+         mv_setRegDouble (DEST_REG,
+                          -mv_getRegDouble (SRC1_REG));
+         printfdbg ("cfnegd mvd%d = -mvd%d = %g\n",
+                    DEST_REG,
+                    mv_getRegDouble (DEST_REG));
+         break;
+         
+       case 4: /* cfadds */
+         DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
+           + DSPregs[SRC2_REG].upper.f;
+         printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    SRC2_REG,
+                    DSPregs[DEST_REG].upper.f);
+         break;
+         
+       case 5: /* cfaddd */
+         mv_setRegDouble (DEST_REG,
+                          mv_getRegDouble (SRC1_REG)
+                          + mv_getRegDouble (SRC2_REG));
+         printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    SRC2_REG,
+                    mv_getRegDouble (DEST_REG));
+         break;
+         
+       case 6: /* cfsubs */
+         DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f
+           - DSPregs[SRC2_REG].upper.f;
+         printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    SRC2_REG,
+                    DSPregs[DEST_REG].upper.f);
+         break;
+         
+       case 7: /* cfsubd */
+         mv_setRegDouble (DEST_REG,
+                          mv_getRegDouble (SRC1_REG)
+                          - mv_getRegDouble (SRC2_REG));
+         printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n",
+                    DEST_REG,
+                    SRC1_REG,
+                    SRC2_REG,
+                    mv_getRegDouble (DEST_REG));
+         break;
+       }
+      break;
+
+    default:
+      fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr);
+      cirrus_not_implemented ("unknown");
+      break;
+    }
+
+  return ARMul_DONE;
+}
+
+unsigned
+DSPCDP5 (ARMul_State * state,
+        unsigned      type,
+        ARMword       instr)
+{
+   int opcode2;
+   char shift;
+
+   opcode2 = BITS (5,7);
+
+   /* Shift constants are 7bit signed numbers in bits 0..3|5..7.  */
+   shift = BITS (0, 3) | (BITS (5, 7)) << 4;
+   if (shift & 0x40)
+     shift |= 0xc0;
+
+   switch (BITS (20,21))
+     {
+     case 0:
+       /* cfsh32 */
+       printfdbg ("cfsh32 %s amount=%d\n", shift < 0 ? "right" : "left",
+                 shift);
+       if (shift < 0)
+        /* Negative shift is a right shift.  */
+        DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -shift;
+       else
+        /* Positive shift is a left shift.  */
+        DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i << shift;
+       break;
+
+     case 1:
+       switch (opcode2)
+         {
+         case 0: /* cfmul32 */
+          DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
+            * DSPregs[SRC2_REG].lower.i;
+          printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     DSPregs[DEST_REG].lower.i);
+           break;
+          
+         case 1: /* cfmul64 */
+          mv_setReg64int (DEST_REG,
+                          mv_getReg64int (SRC1_REG)
+                          * mv_getReg64int (SRC2_REG));
+          printfdbg ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     mv_getReg64int (DEST_REG));
+           break;
+          
+         case 2: /* cfmac32 */
+          DSPregs[DEST_REG].lower.i
+            += DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
+          printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     DSPregs[DEST_REG].lower.i);
+           break;
+          
+         case 3: /* cfmsc32 */
+          DSPregs[DEST_REG].lower.i
+            -= DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i;
+          printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     DSPregs[DEST_REG].lower.i);
+           break;
+          
+         case 4: /* cfcvts32 */
+          /* fixme: this should round */
+          DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
+          printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     DSPregs[DEST_REG].lower.i);
+           break;
+          
+         case 5: /* cfcvtd32 */
+          /* fixme: this should round */
+          DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
+          printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     DSPregs[DEST_REG].lower.i);
+           break;
+          
+         case 6: /* cftruncs32 */
+          DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f;
+          printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     DSPregs[DEST_REG].lower.i);
+           break;
+          
+         case 7: /* cftruncd32 */
+          DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG);
+          printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     DSPregs[DEST_REG].lower.i);
+           break;
+         }
+       break;
+
+     case 2:
+       /* cfsh64 */
+       printfdbg ("cfsh64\n");
+       
+       if (shift < 0)
+        /* Negative shift is a right shift.  */
+        mv_setReg64int (DEST_REG,
+                        mv_getReg64int (SRC1_REG) >> -shift);
+       else
+        /* Positive shift is a left shift.  */
+        mv_setReg64int (DEST_REG,
+                        mv_getReg64int (SRC1_REG) << shift);
+       printfdbg ("\t%llx\n", mv_getReg64int(DEST_REG));
+       break;
+
+     case 3:
+       switch (opcode2)
+         {
+         case 0: /* cfabs32 */
+          DSPregs[DEST_REG].lower.i = (DSPregs[SRC1_REG].lower.i < 0
+            ? -DSPregs[SRC1_REG].lower.i : DSPregs[SRC1_REG].lower.i);
+          printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     DSPregs[DEST_REG].lower.i);
+           break;
+          
+         case 1: /* cfabs64 */
+          mv_setReg64int (DEST_REG,
+                          (mv_getReg64int (SRC1_REG) < 0
+                           ? -mv_getReg64int (SRC1_REG)
+                           : mv_getReg64int (SRC1_REG)));
+          printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     mv_getReg64int (DEST_REG));
+           break;
+          
+         case 2: /* cfneg32 */
+          DSPregs[DEST_REG].lower.i = -DSPregs[SRC1_REG].lower.i;
+          printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     DSPregs[DEST_REG].lower.i);
+           break;
+          
+         case 3: /* cfneg64 */
+          mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG));
+          printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     mv_getReg64int (DEST_REG));
+           break;
+          
+         case 4: /* cfadd32 */
+          DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
+            + DSPregs[SRC2_REG].lower.i;
+          printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     DSPregs[DEST_REG].lower.i);
+           break;
+          
+         case 5: /* cfadd64 */
+          mv_setReg64int (DEST_REG,
+                          mv_getReg64int (SRC1_REG)
+                          + mv_getReg64int (SRC2_REG));
+          printfdbg ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     mv_getReg64int (DEST_REG));
+           break;
+          
+         case 6: /* cfsub32 */
+          DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i
+            - DSPregs[SRC2_REG].lower.i;
+          printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     DSPregs[DEST_REG].lower.i);
+           break;
+          
+         case 7: /* cfsub64 */
+          mv_setReg64int (DEST_REG,
+                          mv_getReg64int (SRC1_REG)
+                          - mv_getReg64int (SRC2_REG));
+          printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n",
+                     DEST_REG,
+                     SRC1_REG,
+                     SRC2_REG,
+                     mv_getReg64int (DEST_REG));
+           break;
+         }
+       break;
+
+     default:
+       fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr);
+       cirrus_not_implemented ("unknown");
+       break;
+     }
+
+  return ARMul_DONE;
+}
+
+unsigned
+DSPCDP6 (ARMul_State * state,
+        unsigned      type,
+        ARMword       instr)
+{
+   int opcode2;
+
+   opcode2 = BITS (5,7);
+
+   switch (BITS (20,21))
+     {
+     case 0:
+       /* cfmadd32 */
+       cirrus_not_implemented ("cfmadd32");
+       break;
+       
+     case 1:
+       /* cfmsub32 */
+       cirrus_not_implemented ("cfmsub32");
+       break;
+       
+     case 2:
+       /* cfmadda32 */
+       cirrus_not_implemented ("cfmadda32");
+       break;
+       
+     case 3:
+       /* cfmsuba32 */
+       cirrus_not_implemented ("cfmsuba32");
+       break;
+
+     default:
+       fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr);
+     }
+
+   return ARMul_DONE;
+}
+
+/* Conversion functions.
+
+   32-bit integers are stored in the LOWER half of a 64-bit physical
+   register.
+
+   Single precision floats are stored in the UPPER half of a 64-bit
+   physical register.  */
+
+static double
+mv_getRegDouble (int regnum)
+{
+  reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i;
+  reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i;
+  return reg_conv.d;
+}
+
+static void
+mv_setRegDouble (int regnum, double val)
+{
+  reg_conv.d = val;
+  DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index];
+  DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index];
+}
+
+static long long
+mv_getReg64int (int regnum)
+{
+  reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i;
+  reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i;
+  return reg_conv.ll;
+}
+
+static void
+mv_setReg64int (int regnum, long long val)
+{
+  reg_conv.ll = val;
+  DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index];
+  DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index];
+}
+
+/* Compute LSW in a double and a long long.  */
+
+void
+mv_compute_host_endianness (ARMul_State * state)
+{
+  static union
+  {
+    long long ll;
+    long ints[2];
+    long i;
+    double d;
+    float floats[2];
+    float f;
+  } conv;
+
+  /* Calculate where's the LSW in a 64bit int.  */
+  conv.ll = 45;
+  
+  if (conv.ints[0] == 0)
+    {
+      msw_int_index = 0;
+      lsw_int_index = 1;
+    }
+  else
+    {
+      assert (conv.ints[1] == 0);
+      msw_int_index = 1;
+      lsw_int_index = 0;
+    }
+
+  /* Calculate where's the LSW in a double.  */
+  conv.d = 3.0;
+  
+  if (conv.ints[0] == 0)
+    {
+      msw_float_index = 0;
+      lsw_float_index = 1;
+    }
+  else
+    {
+      assert (conv.ints[1] == 0);
+      msw_float_index = 1;
+      lsw_float_index = 0;
+    }
+
+  printfdbg ("lsw_int_index   %d\n", lsw_int_index);
+  printfdbg ("lsw_float_index %d\n", lsw_float_index);
+}