OSDN Git Service

Remove auot generated man pages
authornickc <nickc>
Tue, 19 Jun 2001 11:57:12 +0000 (11:57 +0000)
committernickc <nickc>
Tue, 19 Jun 2001 11:57:12 +0000 (11:57 +0000)
gas/ChangeLog
gas/Makefile.am
gas/Makefile.in
gas/config/tc-arm.c [deleted file]

index f7365a8..a9a0332 100644 (file)
@@ -1,3 +1,11 @@
+2001-06-18  H.J. Lu <hjl@gnu.org>
+
+        * doc/Makefile.am (info): Depend on $(MANS).
+        (as.1): Remove the prefix `$(srcdir)/'.
+        * doc/Makefile.in: Regenerated.
+
+        * as.1: Removed.
+
 2001-06-18  Philip Blundell  <philb@gnu.org>
 
        * config/tc-arm.c (do_msr): Remove restriction on usage of
index 52a19a6..499e9ef 100644 (file)
@@ -435,10 +435,8 @@ stamp-mk.com: vmsconf.sh Makefile
        $(SHELL) $(srcdir)/../move-if-change new-make.com $(srcdir)/make-gas.com
        touch stamp-mk.com
 
-EXTRA_DIST = make-gas.com
-
-DISTSTUFF = make-gas.com m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c
-diststuff: $(DISTSTUFF) info
+EXTRA_DIST = make-gas.com m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c
+diststuff: $(EXTRA_DIST) info
 
 DISTCLEANFILES = targ-cpu.h obj-format.h targ-env.h itbl-cpu.h cgen-desc.h
 
index 1de6c50..bcce02f 100644 (file)
@@ -552,9 +552,7 @@ noinst_PROGRAMS = as-new gasp-new
 noinst_SCRIPTS = $(GDBINIT)
 EXTRA_SCRIPTS = .gdbinit
 
-EXTRA_DIST = make-gas.com
-
-DISTSTUFF = make-gas.com m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c
+EXTRA_DIST = make-gas.com m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c
 
 DISTCLEANFILES = targ-cpu.h obj-format.h targ-env.h itbl-cpu.h cgen-desc.h
 
@@ -2008,7 +2006,7 @@ configure configure.in gdbinit.in itbl-lex.c itbl-parse.c
 
 DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
-TAR = tar
+TAR = gtar
 GZIP_ENV = --best
 SOURCES = $(itbl_test_SOURCES) $(as_new_SOURCES) $(EXTRA_as_new_SOURCES) $(gasp_new_SOURCES)
 OBJECTS = $(itbl_test_OBJECTS) $(as_new_OBJECTS) $(gasp_new_OBJECTS)
@@ -2407,7 +2405,7 @@ stamp-mk.com: vmsconf.sh Makefile
        sh $(srcdir)/vmsconf.sh $(GENERIC_OBJS) > new-make.com
        $(SHELL) $(srcdir)/../move-if-change new-make.com $(srcdir)/make-gas.com
        touch stamp-mk.com
-diststuff: $(DISTSTUFF) info
+diststuff: $(EXTRA_DIST) info
 
 $(OBJS): @ALL_OBJ_DEPS@
 
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
deleted file mode 100644 (file)
index 99aff8e..0000000
+++ /dev/null
@@ -1,8897 +0,0 @@
-/* tc-arm.c -- Assemble for the ARM
-   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
-   Free Software Foundation, Inc.
-   Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
-       Modified by David Taylor (dtaylor@armltd.co.uk)
-
-   This file is part of GAS, the GNU Assembler.
-
-   GAS 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.
-
-   GAS 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 GAS; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
-
-#include <ctype.h>
-#include <string.h>
-#define  NO_RELOC 0
-#include "as.h"
-
-/* Need TARGET_CPU.  */
-#include "config.h"
-#include "subsegs.h"
-#include "obstack.h"
-#include "symbols.h"
-#include "listing.h"
-
-#ifdef OBJ_ELF
-#include "elf/arm.h"
-#include "dwarf2dbg.h"
-#endif
-
-/* Types of processor to assemble for.  */
-#define ARM_1          0x00000001
-#define ARM_2          0x00000002
-#define ARM_3          0x00000004
-#define ARM_250                ARM_3
-#define ARM_6          0x00000008
-#define ARM_7          ARM_6           /* Same core instruction set.  */
-#define ARM_8          ARM_6           /* Same core instruction set.  */
-#define ARM_9          ARM_6           /* Same core instruction set.  */
-#define ARM_CPU_MASK   0x0000000f
-
-/* The following bitmasks control CPU extensions (ARM7 onwards):   */
-#define ARM_EXT_LONGMUL        0x00000010      /* Allow long multiplies.  */
-#define ARM_EXT_HALFWORD 0x00000020    /* Allow half word loads.  */
-#define ARM_EXT_THUMB  0x00000040      /* Allow BX instruction.   */
-#define ARM_EXT_V5     0x00000080      /* Allow CLZ, etc.         */
-#define ARM_EXT_V5E    0x00000100      /* "El Segundo".           */
-#define ARM_EXT_XSCALE 0x00000200      /* Allow MIA etc.          */
-
-/* Architectures are the sum of the base and extensions.  */
-#define ARM_ARCH_V3M     ARM_EXT_LONGMUL
-#define ARM_ARCH_V4     (ARM_ARCH_V3M | ARM_EXT_HALFWORD)
-#define ARM_ARCH_V4T   (ARM_ARCH_V4 | ARM_EXT_THUMB)
-#define ARM_ARCH_V5    (ARM_ARCH_V4 | ARM_EXT_V5)
-#define ARM_ARCH_V5T   (ARM_ARCH_V5 | ARM_EXT_THUMB)
-#define ARM_ARCH_V5TE  (ARM_ARCH_V5T | ARM_EXT_V5E)
-#define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_EXT_XSCALE)
-
-/* Some useful combinations:  */
-#define ARM_ANY                0x00ffffff
-#define ARM_2UP                (ARM_ANY - ARM_1)
-#define ARM_ALL                ARM_2UP         /* Not arm1 only.  */
-#define ARM_3UP                0x00fffffc
-#define ARM_6UP                0x00fffff8      /* Includes ARM7.  */
-
-#define FPU_CORE       0x80000000
-#define FPU_FPA10      0x40000000
-#define FPU_FPA11      0x40000000
-#define FPU_NONE       0
-
-/* Some useful combinations.  */
-#define FPU_ALL                0xff000000      /* Note this is ~ARM_ANY.  */
-#define FPU_MEMMULTI   0x7f000000      /* Not fpu_core.  */
-
-#ifndef CPU_DEFAULT
-#if defined __XSCALE__
-#define CPU_DEFAULT    (ARM_9 | ARM_ARCH_XSCALE)
-#else
-#if defined __thumb__
-#define CPU_DEFAULT    (ARM_7 | ARM_ARCH_V4T)
-#else
-#define CPU_DEFAULT    ARM_ALL
-#endif
-#endif
-#endif
-
-#ifndef FPU_DEFAULT
-#define FPU_DEFAULT FPU_ALL
-#endif
-
-#define streq(a, b)           (strcmp (a, b) == 0)
-#define skip_whitespace(str)  while (*(str) == ' ') ++(str)
-
-static unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT;
-static int target_oabi = 0;
-
-#if defined OBJ_COFF || defined OBJ_ELF
-/* Flags stored in private area of BFD structure.  */
-static boolean uses_apcs_26      = false;
-static boolean atpcs             = false;
-static boolean support_interwork = false;
-static boolean uses_apcs_float   = false;
-static boolean pic_code          = false;
-#endif
-
-/* This array holds the chars that always start a comment.  If the
-   pre-processor is disabled, these aren't very useful.  */
-CONST char comment_chars[] = "@";
-
-/* This array holds the chars that only start a comment at the beginning of
-   a line.  If the line seems to have the form '# 123 filename'
-   .line and .file directives will appear in the pre-processed output.  */
-/* Note that input_file.c hand checks for '#' at the beginning of the
-   first line of the input file.  This is because the compiler outputs
-   #NO_APP at the beginning of its output.  */
-/* Also note that comments like this one will always work.  */
-CONST char line_comment_chars[] = "#";
-
-CONST char line_separator_chars[] = ";";
-
-/* Chars that can be used to separate mant
-   from exp in floating point numbers.  */
-CONST char EXP_CHARS[] = "eE";
-
-/* Chars that mean this number is a floating point constant.  */
-/* As in 0f12.456  */
-/* or    0d1.2345e12  */
-
-CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP";
-
-/* Prefix characters that indicate the start of an immediate
-   value.  */
-#define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
-
-#ifdef OBJ_ELF
-/* Pre-defined "_GLOBAL_OFFSET_TABLE_"  */
-symbolS * GOT_symbol;
-#endif
-
-/* Size of relocation record.  */
-CONST int md_reloc_size = 8;
-
-/* 0: assemble for ARM,
-   1: assemble for Thumb,
-   2: assemble for Thumb even though target CPU does not support thumb
-      instructions.  */
-static int thumb_mode = 0;
-
-typedef struct arm_fix
-{
-  int thumb_mode;
-} arm_fix_data;
-
-struct arm_it
-{
-  CONST char *  error;
-  unsigned long instruction;
-  int           suffix;
-  int           size;
-  struct
-  {
-    bfd_reloc_code_real_type type;
-    expressionS              exp;
-    int                      pc_rel;
-  } reloc;
-};
-
-struct arm_it inst;
-
-enum asm_shift_index
-{
-  SHIFT_LSL = 0,
-  SHIFT_LSR,
-  SHIFT_ASR,
-  SHIFT_ROR,
-  SHIFT_RRX
-};
-
-struct asm_shift_properties
-{
-  enum asm_shift_index index;
-  unsigned long        bit_field;
-  unsigned int         allows_0  : 1;
-  unsigned int         allows_32 : 1;
-};
-
-static const struct asm_shift_properties shift_properties [] =
-{
-  { SHIFT_LSL, 0,    1, 0},
-  { SHIFT_LSR, 0x20, 0, 1},
-  { SHIFT_ASR, 0x40, 0, 1},
-  { SHIFT_ROR, 0x60, 0, 0},
-  { SHIFT_RRX, 0x60, 0, 0}
-};
-
-struct asm_shift_name
-{
-  const char *                        name;
-  const struct asm_shift_properties * properties;
-};
-
-static const struct asm_shift_name shift_names [] =
-{
-  { "asl", shift_properties + SHIFT_LSL },
-  { "lsl", shift_properties + SHIFT_LSL },
-  { "lsr", shift_properties + SHIFT_LSR },
-  { "asr", shift_properties + SHIFT_ASR },
-  { "ror", shift_properties + SHIFT_ROR },
-  { "rrx", shift_properties + SHIFT_RRX },
-  { "ASL", shift_properties + SHIFT_LSL },
-  { "LSL", shift_properties + SHIFT_LSL },
-  { "LSR", shift_properties + SHIFT_LSR },
-  { "ASR", shift_properties + SHIFT_ASR },
-  { "ROR", shift_properties + SHIFT_ROR },
-  { "RRX", shift_properties + SHIFT_RRX }
-};
-
-#define NO_SHIFT_RESTRICT 1
-#define SHIFT_RESTRICT   0
-
-#define NUM_FLOAT_VALS 8
-
-CONST char * fp_const[] =
-{
-  "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
-};
-
-/* Number of littlenums required to hold an extended precision number.  */
-#define MAX_LITTLENUMS 6
-
-LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
-
-#define FAIL   (-1)
-#define SUCCESS (0)
-
-#define SUFF_S 1
-#define SUFF_D 2
-#define SUFF_E 3
-#define SUFF_P 4
-
-#define CP_T_X   0x00008000
-#define CP_T_Y   0x00400000
-#define CP_T_Pre 0x01000000
-#define CP_T_UD  0x00800000
-#define CP_T_WB  0x00200000
-
-#define CONDS_BIT        0x00100000
-#define LOAD_BIT         0x00100000
-#define TRANS_BIT       0x00200000
-
-#define DOUBLE_LOAD_FLAG 0x00000001
-
-struct asm_cond
-{
-  CONST char *  template;
-  unsigned long value;
-};
-
-/* This is to save a hash look-up in the common case.  */
-#define COND_ALWAYS 0xe0000000
-
-static CONST struct asm_cond conds[] =
-{
-  {"eq", 0x00000000},
-  {"ne", 0x10000000},
-  {"cs", 0x20000000}, {"hs", 0x20000000},
-  {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
-  {"mi", 0x40000000},
-  {"pl", 0x50000000},
-  {"vs", 0x60000000},
-  {"vc", 0x70000000},
-  {"hi", 0x80000000},
-  {"ls", 0x90000000},
-  {"ge", 0xa0000000},
-  {"lt", 0xb0000000},
-  {"gt", 0xc0000000},
-  {"le", 0xd0000000},
-  {"al", 0xe0000000},
-  {"nv", 0xf0000000}
-};
-
-/* Warning: If the top bit of the set_bits is set, then the standard
-   instruction bitmask is ignored, and the new bitmask is taken from
-   the set_bits:  */
-struct asm_flg
-{
-  CONST char *  template;      /* Basic flag string.  */
-  unsigned long set_bits;      /* Bits to set.  */
-};
-
-static CONST struct asm_flg s_flag[] =
-{
-  {"s", CONDS_BIT},
-  {NULL, 0}
-};
-
-static CONST struct asm_flg ldr_flags[] =
-{
-  {"d",  DOUBLE_LOAD_FLAG},
-  {"b",  0x00400000},
-  {"t",  TRANS_BIT},
-  {"bt", 0x00400000 | TRANS_BIT},
-  {"h",  0x801000b0},
-  {"sh", 0x801000f0},
-  {"sb", 0x801000d0},
-  {NULL, 0}
-};
-
-static CONST struct asm_flg str_flags[] =
-{
-  {"d",  DOUBLE_LOAD_FLAG},
-  {"b",  0x00400000},
-  {"t",  TRANS_BIT},
-  {"bt", 0x00400000 | TRANS_BIT},
-  {"h",  0x800000b0},
-  {NULL, 0}
-};
-
-static CONST struct asm_flg byte_flag[] =
-{
-  {"b", 0x00400000},
-  {NULL, 0}
-};
-
-static CONST struct asm_flg cmp_flags[] =
-{
-  {"s", CONDS_BIT},
-  {"p", 0x0010f000},
-  {NULL, 0}
-};
-
-static CONST struct asm_flg ldm_flags[] =
-{
-  {"ed", 0x01800000},
-  {"fd", 0x00800000},
-  {"ea", 0x01000000},
-  {"fa", 0x00000000},
-  {"ib", 0x01800000},
-  {"ia", 0x00800000},
-  {"db", 0x01000000},
-  {"da", 0x00000000},
-  {NULL, 0}
-};
-
-static CONST struct asm_flg stm_flags[] =
-{
-  {"ed", 0x00000000},
-  {"fd", 0x01000000},
-  {"ea", 0x00800000},
-  {"fa", 0x01800000},
-  {"ib", 0x01800000},
-  {"ia", 0x00800000},
-  {"db", 0x01000000},
-  {"da", 0x00000000},
-  {NULL, 0}
-};
-
-static CONST struct asm_flg lfm_flags[] =
-{
-  {"fd", 0x00800000},
-  {"ea", 0x01000000},
-  {NULL, 0}
-};
-
-static CONST struct asm_flg sfm_flags[] =
-{
-  {"fd", 0x01000000},
-  {"ea", 0x00800000},
-  {NULL, 0}
-};
-
-static CONST struct asm_flg round_flags[] =
-{
-  {"p", 0x00000020},
-  {"m", 0x00000040},
-  {"z", 0x00000060},
-  {NULL, 0}
-};
-
-/* The implementation of the FIX instruction is broken on some assemblers,
-   in that it accepts a precision specifier as well as a rounding specifier,
-   despite the fact that this is meaningless.  To be more compatible, we
-   accept it as well, though of course it does not set any bits.  */
-static CONST struct asm_flg fix_flags[] =
-{
-  {"p", 0x00000020},
-  {"m", 0x00000040},
-  {"z", 0x00000060},
-  {"sp", 0x00000020},
-  {"sm", 0x00000040},
-  {"sz", 0x00000060},
-  {"dp", 0x00000020},
-  {"dm", 0x00000040},
-  {"dz", 0x00000060},
-  {"ep", 0x00000020},
-  {"em", 0x00000040},
-  {"ez", 0x00000060},
-  {NULL, 0}
-};
-
-static CONST struct asm_flg except_flag[] =
-{
-  {"e", 0x00400000},
-  {NULL, 0}
-};
-
-static CONST struct asm_flg cplong_flag[] =
-{
-  {"l", 0x00400000},
-  {NULL, 0}
-};
-
-struct asm_psr
-{
-  CONST char *  template;
-  boolean       cpsr;
-  unsigned long field;
-};
-
-/* The bit that distnguishes CPSR and SPSR.  */
-#define SPSR_BIT   (1 << 22)
-
-/* How many bits to shift the PSR_xxx bits up by.  */
-#define PSR_SHIFT  16
-
-#define PSR_c   (1 << 0)
-#define PSR_x   (1 << 1)
-#define PSR_s   (1 << 2)
-#define PSR_f   (1 << 3)
-
-static CONST struct asm_psr psrs[] =
-{
-  {"CPSR",     true,  PSR_c | PSR_f},
-  {"CPSR_all", true,  PSR_c | PSR_f},
-  {"SPSR",     false, PSR_c | PSR_f},
-  {"SPSR_all", false, PSR_c | PSR_f},
-  {"CPSR_flg", true,  PSR_f},
-  {"CPSR_f",    true,  PSR_f},
-  {"SPSR_flg", false, PSR_f},
-  {"SPSR_f",    false, PSR_f},
-  {"CPSR_c",   true,  PSR_c},
-  {"CPSR_ctl", true,  PSR_c},
-  {"SPSR_c",   false, PSR_c},
-  {"SPSR_ctl", false, PSR_c},
-  {"CPSR_x",    true,  PSR_x},
-  {"CPSR_s",    true,  PSR_s},
-  {"SPSR_x",    false, PSR_x},
-  {"SPSR_s",    false, PSR_s},
-  /* Combinations of flags.  */
-  {"CPSR_fs",  true, PSR_f | PSR_s},
-  {"CPSR_fx",  true, PSR_f | PSR_x},
-  {"CPSR_fc",  true, PSR_f | PSR_c},
-  {"CPSR_sf",  true, PSR_s | PSR_f},
-  {"CPSR_sx",  true, PSR_s | PSR_x},
-  {"CPSR_sc",  true, PSR_s | PSR_c},
-  {"CPSR_xf",  true, PSR_x | PSR_f},
-  {"CPSR_xs",  true, PSR_x | PSR_s},
-  {"CPSR_xc",  true, PSR_x | PSR_c},
-  {"CPSR_cf",  true, PSR_c | PSR_f},
-  {"CPSR_cs",  true, PSR_c | PSR_s},
-  {"CPSR_cx",  true, PSR_c | PSR_x},
-  {"CPSR_fsx", true, PSR_f | PSR_s | PSR_x},
-  {"CPSR_fsc", true, PSR_f | PSR_s | PSR_c},
-  {"CPSR_fxs", true, PSR_f | PSR_x | PSR_s},
-  {"CPSR_fxc", true, PSR_f | PSR_x | PSR_c},
-  {"CPSR_fcs", true, PSR_f | PSR_c | PSR_s},
-  {"CPSR_fcx", true, PSR_f | PSR_c | PSR_x},
-  {"CPSR_sfx", true, PSR_s | PSR_f | PSR_x},
-  {"CPSR_sfc", true, PSR_s | PSR_f | PSR_c},
-  {"CPSR_sxf", true, PSR_s | PSR_x | PSR_f},
-  {"CPSR_sxc", true, PSR_s | PSR_x | PSR_c},
-  {"CPSR_scf", true, PSR_s | PSR_c | PSR_f},
-  {"CPSR_scx", true, PSR_s | PSR_c | PSR_x},
-  {"CPSR_xfs", true, PSR_x | PSR_f | PSR_s},
-  {"CPSR_xfc", true, PSR_x | PSR_f | PSR_c},
-  {"CPSR_xsf", true, PSR_x | PSR_s | PSR_f},
-  {"CPSR_xsc", true, PSR_x | PSR_s | PSR_c},
-  {"CPSR_xcf", true, PSR_x | PSR_c | PSR_f},
-  {"CPSR_xcs", true, PSR_x | PSR_c | PSR_s},
-  {"CPSR_cfs", true, PSR_c | PSR_f | PSR_s},
-  {"CPSR_cfx", true, PSR_c | PSR_f | PSR_x},
-  {"CPSR_csf", true, PSR_c | PSR_s | PSR_f},
-  {"CPSR_csx", true, PSR_c | PSR_s | PSR_x},
-  {"CPSR_cxf", true, PSR_c | PSR_x | PSR_f},
-  {"CPSR_cxs", true, PSR_c | PSR_x | PSR_s},
-  {"CPSR_fsxc",        true, PSR_f | PSR_s | PSR_x | PSR_c},
-  {"CPSR_fscx",        true, PSR_f | PSR_s | PSR_c | PSR_x},
-  {"CPSR_fxsc",        true, PSR_f | PSR_x | PSR_s | PSR_c},
-  {"CPSR_fxcs",        true, PSR_f | PSR_x | PSR_c | PSR_s},
-  {"CPSR_fcsx",        true, PSR_f | PSR_c | PSR_s | PSR_x},
-  {"CPSR_fcxs",        true, PSR_f | PSR_c | PSR_x | PSR_s},
-  {"CPSR_sfxc",        true, PSR_s | PSR_f | PSR_x | PSR_c},
-  {"CPSR_sfcx",        true, PSR_s | PSR_f | PSR_c | PSR_x},
-  {"CPSR_sxfc",        true, PSR_s | PSR_x | PSR_f | PSR_c},
-  {"CPSR_sxcf",        true, PSR_s | PSR_x | PSR_c | PSR_f},
-  {"CPSR_scfx",        true, PSR_s | PSR_c | PSR_f | PSR_x},
-  {"CPSR_scxf",        true, PSR_s | PSR_c | PSR_x | PSR_f},
-  {"CPSR_xfsc",        true, PSR_x | PSR_f | PSR_s | PSR_c},
-  {"CPSR_xfcs",        true, PSR_x | PSR_f | PSR_c | PSR_s},
-  {"CPSR_xsfc",        true, PSR_x | PSR_s | PSR_f | PSR_c},
-  {"CPSR_xscf",        true, PSR_x | PSR_s | PSR_c | PSR_f},
-  {"CPSR_xcfs",        true, PSR_x | PSR_c | PSR_f | PSR_s},
-  {"CPSR_xcsf",        true, PSR_x | PSR_c | PSR_s | PSR_f},
-  {"CPSR_cfsx",        true, PSR_c | PSR_f | PSR_s | PSR_x},
-  {"CPSR_cfxs",        true, PSR_c | PSR_f | PSR_x | PSR_s},
-  {"CPSR_csfx",        true, PSR_c | PSR_s | PSR_f | PSR_x},
-  {"CPSR_csxf",        true, PSR_c | PSR_s | PSR_x | PSR_f},
-  {"CPSR_cxfs",        true, PSR_c | PSR_x | PSR_f | PSR_s},
-  {"CPSR_cxsf",        true, PSR_c | PSR_x | PSR_s | PSR_f},
-  {"SPSR_fs",  false, PSR_f | PSR_s},
-  {"SPSR_fx",  false, PSR_f | PSR_x},
-  {"SPSR_fc",  false, PSR_f | PSR_c},
-  {"SPSR_sf",  false, PSR_s | PSR_f},
-  {"SPSR_sx",  false, PSR_s | PSR_x},
-  {"SPSR_sc",  false, PSR_s | PSR_c},
-  {"SPSR_xf",  false, PSR_x | PSR_f},
-  {"SPSR_xs",  false, PSR_x | PSR_s},
-  {"SPSR_xc",  false, PSR_x | PSR_c},
-  {"SPSR_cf",  false, PSR_c | PSR_f},
-  {"SPSR_cs",  false, PSR_c | PSR_s},
-  {"SPSR_cx",  false, PSR_c | PSR_x},
-  {"SPSR_fsx", false, PSR_f | PSR_s | PSR_x},
-  {"SPSR_fsc", false, PSR_f | PSR_s | PSR_c},
-  {"SPSR_fxs", false, PSR_f | PSR_x | PSR_s},
-  {"SPSR_fxc", false, PSR_f | PSR_x | PSR_c},
-  {"SPSR_fcs", false, PSR_f | PSR_c | PSR_s},
-  {"SPSR_fcx", false, PSR_f | PSR_c | PSR_x},
-  {"SPSR_sfx", false, PSR_s | PSR_f | PSR_x},
-  {"SPSR_sfc", false, PSR_s | PSR_f | PSR_c},
-  {"SPSR_sxf", false, PSR_s | PSR_x | PSR_f},
-  {"SPSR_sxc", false, PSR_s | PSR_x | PSR_c},
-  {"SPSR_scf", false, PSR_s | PSR_c | PSR_f},
-  {"SPSR_scx", false, PSR_s | PSR_c | PSR_x},
-  {"SPSR_xfs", false, PSR_x | PSR_f | PSR_s},
-  {"SPSR_xfc", false, PSR_x | PSR_f | PSR_c},
-  {"SPSR_xsf", false, PSR_x | PSR_s | PSR_f},
-  {"SPSR_xsc", false, PSR_x | PSR_s | PSR_c},
-  {"SPSR_xcf", false, PSR_x | PSR_c | PSR_f},
-  {"SPSR_xcs", false, PSR_x | PSR_c | PSR_s},
-  {"SPSR_cfs", false, PSR_c | PSR_f | PSR_s},
-  {"SPSR_cfx", false, PSR_c | PSR_f | PSR_x},
-  {"SPSR_csf", false, PSR_c | PSR_s | PSR_f},
-  {"SPSR_csx", false, PSR_c | PSR_s | PSR_x},
-  {"SPSR_cxf", false, PSR_c | PSR_x | PSR_f},
-  {"SPSR_cxs", false, PSR_c | PSR_x | PSR_s},
-  {"SPSR_fsxc",        false, PSR_f | PSR_s | PSR_x | PSR_c},
-  {"SPSR_fscx",        false, PSR_f | PSR_s | PSR_c | PSR_x},
-  {"SPSR_fxsc",        false, PSR_f | PSR_x | PSR_s | PSR_c},
-  {"SPSR_fxcs",        false, PSR_f | PSR_x | PSR_c | PSR_s},
-  {"SPSR_fcsx",        false, PSR_f | PSR_c | PSR_s | PSR_x},
-  {"SPSR_fcxs",        false, PSR_f | PSR_c | PSR_x | PSR_s},
-  {"SPSR_sfxc",        false, PSR_s | PSR_f | PSR_x | PSR_c},
-  {"SPSR_sfcx",        false, PSR_s | PSR_f | PSR_c | PSR_x},
-  {"SPSR_sxfc",        false, PSR_s | PSR_x | PSR_f | PSR_c},
-  {"SPSR_sxcf",        false, PSR_s | PSR_x | PSR_c | PSR_f},
-  {"SPSR_scfx",        false, PSR_s | PSR_c | PSR_f | PSR_x},
-  {"SPSR_scxf",        false, PSR_s | PSR_c | PSR_x | PSR_f},
-  {"SPSR_xfsc",        false, PSR_x | PSR_f | PSR_s | PSR_c},
-  {"SPSR_xfcs",        false, PSR_x | PSR_f | PSR_c | PSR_s},
-  {"SPSR_xsfc",        false, PSR_x | PSR_s | PSR_f | PSR_c},
-  {"SPSR_xscf",        false, PSR_x | PSR_s | PSR_c | PSR_f},
-  {"SPSR_xcfs",        false, PSR_x | PSR_c | PSR_f | PSR_s},
-  {"SPSR_xcsf",        false, PSR_x | PSR_c | PSR_s | PSR_f},
-  {"SPSR_cfsx",        false, PSR_c | PSR_f | PSR_s | PSR_x},
-  {"SPSR_cfxs",        false, PSR_c | PSR_f | PSR_x | PSR_s},
-  {"SPSR_csfx",        false, PSR_c | PSR_s | PSR_f | PSR_x},
-  {"SPSR_csxf",        false, PSR_c | PSR_s | PSR_x | PSR_f},
-  {"SPSR_cxfs",        false, PSR_c | PSR_x | PSR_f | PSR_s},
-  {"SPSR_cxsf",        false, PSR_c | PSR_x | PSR_s | PSR_f},
-};
-
-/* Functions called by parser.  */
-/* ARM instructions.  */
-static void do_arit            PARAMS ((char *, unsigned long));
-static void do_cmp             PARAMS ((char *, unsigned long));
-static void do_mov             PARAMS ((char *, unsigned long));
-static void do_ldst            PARAMS ((char *, unsigned long));
-static void do_ldmstm          PARAMS ((char *, unsigned long));
-static void do_branch          PARAMS ((char *, unsigned long));
-static void do_swi             PARAMS ((char *, unsigned long));
-/* Pseudo Op codes.  */
-static void do_adr             PARAMS ((char *, unsigned long));
-static void do_adrl            PARAMS ((char *, unsigned long));
-static void do_nop             PARAMS ((char *, unsigned long));
-/* ARM 2.  */
-static void do_mul             PARAMS ((char *, unsigned long));
-static void do_mla             PARAMS ((char *, unsigned long));
-/* ARM 3.  */
-static void do_swap            PARAMS ((char *, unsigned long));
-/* ARM 6.  */
-static void do_msr             PARAMS ((char *, unsigned long));
-static void do_mrs             PARAMS ((char *, unsigned long));
-/* ARM 7M.  */
-static void do_mull            PARAMS ((char *, unsigned long));
-/* ARM THUMB.  */
-static void do_bx               PARAMS ((char *, unsigned long));
-
-/* ARM_EXT_XScale.  */
-static void do_mia             PARAMS ((char *, unsigned long));
-static void do_mar             PARAMS ((char *, unsigned long));
-static void do_mra             PARAMS ((char *, unsigned long));
-static void do_pld             PARAMS ((char *, unsigned long));
-static void do_ldrd            PARAMS ((char *, unsigned long));
-
-/* ARM_EXT_V5.  */
-static void do_blx             PARAMS ((char *, unsigned long));
-static void do_bkpt            PARAMS ((char *, unsigned long));
-static void do_clz             PARAMS ((char *, unsigned long));
-static void do_lstc2           PARAMS ((char *, unsigned long));
-static void do_cdp2            PARAMS ((char *, unsigned long));
-static void do_co_reg2         PARAMS ((char *, unsigned long));
-
-static void do_t_blx           PARAMS ((char *));
-static void do_t_bkpt          PARAMS ((char *));
-
-/* ARM_EXT_V5E.  */
-static void do_smla            PARAMS ((char *, unsigned long));
-static void do_smlal           PARAMS ((char *, unsigned long));
-static void do_smul            PARAMS ((char *, unsigned long));
-static void do_qadd            PARAMS ((char *, unsigned long));
-static void do_co_reg2c                PARAMS ((char *, unsigned long));
-
-/* Coprocessor Instructions.  */
-static void do_cdp             PARAMS ((char *, unsigned long));
-static void do_lstc            PARAMS ((char *, unsigned long));
-static void do_co_reg          PARAMS ((char *, unsigned long));
-static void do_fp_ctrl         PARAMS ((char *, unsigned long));
-static void do_fp_ldst         PARAMS ((char *, unsigned long));
-static void do_fp_ldmstm       PARAMS ((char *, unsigned long));
-static void do_fp_dyadic       PARAMS ((char *, unsigned long));
-static void do_fp_monadic      PARAMS ((char *, unsigned long));
-static void do_fp_cmp          PARAMS ((char *, unsigned long));
-static void do_fp_from_reg     PARAMS ((char *, unsigned long));
-static void do_fp_to_reg       PARAMS ((char *, unsigned long));
-
-static void fix_new_arm                PARAMS ((fragS *, int, short, expressionS *, int, int));
-static int arm_reg_parse       PARAMS ((char **));
-static CONST struct asm_psr * arm_psr_parse PARAMS ((char **));
-static void symbol_locate      PARAMS ((symbolS *, CONST char *, segT, valueT, fragS *));
-static int add_to_lit_pool     PARAMS ((void));
-static unsigned validate_immediate PARAMS ((unsigned));
-static unsigned validate_immediate_twopart PARAMS ((unsigned int, unsigned int *));
-static int validate_offset_imm PARAMS ((unsigned int, int));
-static void opcode_select      PARAMS ((int));
-static void end_of_line                PARAMS ((char *));
-static int reg_required_here   PARAMS ((char **, int));
-static int psr_required_here   PARAMS ((char **));
-static int co_proc_number      PARAMS ((char **));
-static int cp_opc_expr         PARAMS ((char **, int, int));
-static int cp_reg_required_here        PARAMS ((char **, int));
-static int fp_reg_required_here        PARAMS ((char **, int));
-static int cp_address_offset   PARAMS ((char **));
-static int cp_address_required_here    PARAMS ((char **));
-static int my_get_float_expression     PARAMS ((char **));
-static int skip_past_comma     PARAMS ((char **));
-static int walk_no_bignums     PARAMS ((symbolS *));
-static int negate_data_op      PARAMS ((unsigned long *, unsigned long));
-static int data_op2            PARAMS ((char **));
-static int fp_op2              PARAMS ((char **));
-static long reg_list           PARAMS ((char **));
-static void thumb_load_store   PARAMS ((char *, int, int));
-static int decode_shift                PARAMS ((char **, int));
-static int ldst_extend         PARAMS ((char **, int));
-static void thumb_add_sub      PARAMS ((char *, int));
-static void insert_reg         PARAMS ((int));
-static void thumb_shift                PARAMS ((char *, int));
-static void thumb_mov_compare  PARAMS ((char *, int));
-static void set_constant_flonums       PARAMS ((void));
-static valueT md_chars_to_number       PARAMS ((char *, int));
-static void insert_reg_alias   PARAMS ((char *, int));
-static void output_inst                PARAMS ((void));
-#ifdef OBJ_ELF
-static bfd_reloc_code_real_type        arm_parse_reloc PARAMS ((void));
-#endif
-
-/* ARM instructions take 4bytes in the object file, Thumb instructions
-   take 2:  */
-#define INSN_SIZE       4
-
-/* LONGEST_INST is the longest basic instruction name without
-   conditions or flags.  ARM7M has 4 of length 5.  El Segundo
-   has one basic instruction name of length 7 (SMLALxy).  */
-#define LONGEST_INST 7
-
-struct asm_opcode
-{
-  /* Basic string to match.  */
-  CONST char * template;
-
-  /* Basic instruction code.  */
-  unsigned long value;
-
-  /* Compulsory suffix that must follow conds.  If "", then the
-     instruction is not conditional and must have no suffix.  */
-  CONST char * comp_suffix;
-
-  /* Bits to toggle if flag 'n' set.  */
-  CONST struct asm_flg * flags;
-
-  /* Which CPU variants this exists for.  */
-  unsigned long variants;
-
-  /* Function to call to parse args.  */
-  void (* parms) PARAMS ((char *, unsigned long));
-};
-
-static CONST struct asm_opcode insns[] =
-{
-/* Intel XScale extensions to ARM V5 ISA.  */
-  {"mia",   0x0e200010, NULL,   NULL,        ARM_EXT_XSCALE, do_mia},
-  {"miaph", 0x0e280010, NULL,   NULL,        ARM_EXT_XSCALE, do_mia},
-  {"miabb", 0x0e2c0010, NULL,   NULL,        ARM_EXT_XSCALE, do_mia},
-  {"miabt", 0x0e2d0010, NULL,   NULL,        ARM_EXT_XSCALE, do_mia},
-  {"miatb", 0x0e2e0010, NULL,   NULL,        ARM_EXT_XSCALE, do_mia},
-  {"miatt", 0x0e2f0010, NULL,   NULL,        ARM_EXT_XSCALE, do_mia},
-  {"mar",   0x0c400000, NULL,   NULL,        ARM_EXT_XSCALE, do_mar},
-  {"mra",   0x0c500000, NULL,   NULL,        ARM_EXT_XSCALE, do_mra},
-  {"pld",   0xf450f000, "",     NULL,        ARM_EXT_XSCALE, do_pld},
-  {"ldr",   0x000000d0, NULL,   ldr_flags,   ARM_ANY,        do_ldrd},
-  {"str",   0x000000f0, NULL,   str_flags,   ARM_ANY,        do_ldrd},
-
-/* ARM Instructions.  */
-  {"and",   0x00000000, NULL,   s_flag,      ARM_ANY,      do_arit},
-  {"eor",   0x00200000, NULL,   s_flag,      ARM_ANY,      do_arit},
-  {"sub",   0x00400000, NULL,   s_flag,      ARM_ANY,      do_arit},
-  {"rsb",   0x00600000, NULL,   s_flag,      ARM_ANY,      do_arit},
-  {"add",   0x00800000, NULL,   s_flag,      ARM_ANY,      do_arit},
-  {"adc",   0x00a00000, NULL,   s_flag,      ARM_ANY,      do_arit},
-  {"sbc",   0x00c00000, NULL,   s_flag,      ARM_ANY,      do_arit},
-  {"rsc",   0x00e00000, NULL,   s_flag,      ARM_ANY,      do_arit},
-  {"orr",   0x01800000, NULL,   s_flag,      ARM_ANY,      do_arit},
-  {"bic",   0x01c00000, NULL,   s_flag,      ARM_ANY,      do_arit},
-  {"tst",   0x01000000, NULL,   cmp_flags,   ARM_ANY,      do_cmp},
-  {"teq",   0x01200000, NULL,   cmp_flags,   ARM_ANY,      do_cmp},
-  {"cmp",   0x01400000, NULL,   cmp_flags,   ARM_ANY,      do_cmp},
-  {"cmn",   0x01600000, NULL,   cmp_flags,   ARM_ANY,      do_cmp},
-  {"mov",   0x01a00000, NULL,   s_flag,      ARM_ANY,      do_mov},
-  {"mvn",   0x01e00000, NULL,   s_flag,      ARM_ANY,      do_mov},
-  {"str",   0x04000000, NULL,   str_flags,   ARM_ANY,      do_ldst},
-  {"ldr",   0x04100000, NULL,   ldr_flags,   ARM_ANY,      do_ldst},
-  {"stm",   0x08000000, NULL,   stm_flags,   ARM_ANY,      do_ldmstm},
-  {"ldm",   0x08100000, NULL,   ldm_flags,   ARM_ANY,      do_ldmstm},
-  {"swi",   0x0f000000, NULL,   NULL,        ARM_ANY,      do_swi},
-#ifdef TE_WINCE
-  {"bl",    0x0b000000, NULL,   NULL,        ARM_ANY,      do_branch},
-  {"b",     0x0a000000, NULL,   NULL,        ARM_ANY,      do_branch},
-#else
-  {"bl",    0x0bfffffe, NULL,   NULL,        ARM_ANY,      do_branch},
-  {"b",     0x0afffffe, NULL,   NULL,        ARM_ANY,      do_branch},
-#endif
-
-/* Pseudo ops.  */
-  {"adr",   0x028f0000, NULL,   NULL,        ARM_ANY,      do_adr},
-  {"adrl",  0x028f0000, NULL,   NULL,        ARM_ANY,      do_adrl},
-  {"nop",   0x01a00000, NULL,   NULL,        ARM_ANY,      do_nop},
-
-/* ARM 2 multiplies.  */
-  {"mul",   0x00000090, NULL,   s_flag,      ARM_2UP,      do_mul},
-  {"mla",   0x00200090, NULL,   s_flag,      ARM_2UP,      do_mla},
-
-/* ARM 3 - swp instructions.  */
-  {"swp",   0x01000090, NULL,   byte_flag,   ARM_3UP,      do_swap},
-
-/* ARM 6 Coprocessor instructions.  */
-  {"mrs",   0x010f0000, NULL,   NULL,        ARM_6UP,      do_mrs},
-  {"msr",   0x0120f000, NULL,   NULL,        ARM_6UP,      do_msr},
-/* ScottB: our code uses 0x0128f000 for msr.
-   NickC:  but this is wrong because the bits 16 through 19 are
-           handled by the PSR_xxx defines above.  */
-
-/* ARM 7M long multiplies - need signed/unsigned flags!  */
-  {"smull", 0x00c00090, NULL,   s_flag,      ARM_EXT_LONGMUL,  do_mull},
-  {"umull", 0x00800090, NULL,   s_flag,      ARM_EXT_LONGMUL,  do_mull},
-  {"smlal", 0x00e00090, NULL,   s_flag,      ARM_EXT_LONGMUL,  do_mull},
-  {"umlal", 0x00a00090, NULL,   s_flag,      ARM_EXT_LONGMUL,  do_mull},
-
-/* ARM THUMB interworking.  */
-  {"bx",    0x012fff10, NULL,   NULL,        ARM_EXT_THUMB,    do_bx},
-
-/* Floating point instructions.  */
-  {"wfs",   0x0e200110, NULL,   NULL,        FPU_ALL,      do_fp_ctrl},
-  {"rfs",   0x0e300110, NULL,   NULL,        FPU_ALL,      do_fp_ctrl},
-  {"wfc",   0x0e400110, NULL,   NULL,        FPU_ALL,      do_fp_ctrl},
-  {"rfc",   0x0e500110, NULL,   NULL,        FPU_ALL,      do_fp_ctrl},
-  {"ldf",   0x0c100100, "sdep", NULL,        FPU_ALL,      do_fp_ldst},
-  {"stf",   0x0c000100, "sdep", NULL,        FPU_ALL,      do_fp_ldst},
-  {"lfm",   0x0c100200, NULL,   lfm_flags,   FPU_MEMMULTI, do_fp_ldmstm},
-  {"sfm",   0x0c000200, NULL,   sfm_flags,   FPU_MEMMULTI, do_fp_ldmstm},
-  {"mvf",   0x0e008100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"mnf",   0x0e108100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"abs",   0x0e208100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"rnd",   0x0e308100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"sqt",   0x0e408100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"log",   0x0e508100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"lgn",   0x0e608100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"exp",   0x0e708100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"sin",   0x0e808100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"cos",   0x0e908100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"tan",   0x0ea08100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"asn",   0x0eb08100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"acs",   0x0ec08100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"atn",   0x0ed08100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"urd",   0x0ee08100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"nrm",   0x0ef08100, "sde",  round_flags, FPU_ALL,      do_fp_monadic},
-  {"adf",   0x0e000100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"suf",   0x0e200100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"rsf",   0x0e300100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"muf",   0x0e100100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"dvf",   0x0e400100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"rdf",   0x0e500100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"pow",   0x0e600100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"rpw",   0x0e700100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"rmf",   0x0e800100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"fml",   0x0e900100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"fdv",   0x0ea00100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"frd",   0x0eb00100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"pol",   0x0ec00100, "sde",  round_flags, FPU_ALL,      do_fp_dyadic},
-  {"cmf",   0x0e90f110, NULL,   except_flag, FPU_ALL,      do_fp_cmp},
-  {"cnf",   0x0eb0f110, NULL,   except_flag, FPU_ALL,      do_fp_cmp},
-/* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should not
-   be an optional suffix, but part of the instruction.  To be compatible,
-   we accept either.  */
-  {"cmfe",  0x0ed0f110, NULL,   NULL,        FPU_ALL,      do_fp_cmp},
-  {"cnfe",  0x0ef0f110, NULL,   NULL,        FPU_ALL,      do_fp_cmp},
-  {"flt",   0x0e000110, "sde",  round_flags, FPU_ALL,      do_fp_from_reg},
-  {"fix",   0x0e100110, NULL,   fix_flags,   FPU_ALL,      do_fp_to_reg},
-
-/* Generic copressor instructions.  */
-  {"cdp",   0x0e000000, NULL,  NULL,         ARM_2UP,      do_cdp},
-  {"ldc",   0x0c100000, NULL,  cplong_flag,  ARM_2UP,      do_lstc},
-  {"stc",   0x0c000000, NULL,  cplong_flag,  ARM_2UP,      do_lstc},
-  {"mcr",   0x0e000010, NULL,  NULL,         ARM_2UP,      do_co_reg},
-  {"mrc",   0x0e100010, NULL,  NULL,         ARM_2UP,      do_co_reg},
-
-/*  ARM ISA extension 5.  */
-/* Note: blx is actually 2 opcodes, so the .value is set dynamically.
-   And it's sometimes conditional and sometimes not.  */
-  {"blx",            0, NULL,   NULL,        ARM_EXT_V5, do_blx},
-  {"clz",   0x016f0f10, NULL,   NULL,        ARM_EXT_V5, do_clz},
-  {"bkpt",  0xe1200070, "",    NULL,        ARM_EXT_V5, do_bkpt},
-  {"ldc2",  0xfc100000, "",    cplong_flag, ARM_EXT_V5, do_lstc2},
-  {"stc2",  0xfc000000, "",    cplong_flag, ARM_EXT_V5, do_lstc2},
-  {"cdp2",  0xfe000000, "",    NULL,        ARM_EXT_V5, do_cdp2},
-  {"mcr2",  0xfe000010, "",    NULL,        ARM_EXT_V5, do_co_reg2},
-  {"mrc2",  0xfe100010, "",    NULL,        ARM_EXT_V5, do_co_reg2},
-
-/*  ARM ISA extension 5E, El Segundo.  */
-  {"smlabb", 0x01000080, NULL,   NULL,        ARM_EXT_V5E, do_smla},
-  {"smlatb", 0x010000a0, NULL,   NULL,        ARM_EXT_V5E, do_smla},
-  {"smlabt", 0x010000c0, NULL,   NULL,        ARM_EXT_V5E, do_smla},
-  {"smlatt", 0x010000e0, NULL,   NULL,        ARM_EXT_V5E, do_smla},
-
-  {"smlawb", 0x01200080, NULL,   NULL,        ARM_EXT_V5E, do_smla},
-  {"smlawt", 0x012000c0, NULL,   NULL,        ARM_EXT_V5E, do_smla},
-
-  {"smlalbb",0x01400080, NULL,   NULL,        ARM_EXT_V5E, do_smlal},
-  {"smlaltb",0x014000a0, NULL,   NULL,        ARM_EXT_V5E, do_smlal},
-  {"smlalbt",0x014000c0, NULL,   NULL,        ARM_EXT_V5E, do_smlal},
-  {"smlaltt",0x014000e0, NULL,   NULL,        ARM_EXT_V5E, do_smlal},
-
-  {"smulbb", 0x01600080, NULL,   NULL,        ARM_EXT_V5E, do_smul},
-  {"smultb", 0x016000a0, NULL,   NULL,        ARM_EXT_V5E, do_smul},
-  {"smulbt", 0x016000c0, NULL,   NULL,        ARM_EXT_V5E, do_smul},
-  {"smultt", 0x016000e0, NULL,   NULL,        ARM_EXT_V5E, do_smul},
-
-  {"smulwb", 0x012000a0, NULL,   NULL,        ARM_EXT_V5E, do_smul},
-  {"smulwt", 0x012000e0, NULL,   NULL,        ARM_EXT_V5E, do_smul},
-
-  {"qadd",   0x01000050, NULL,   NULL,        ARM_EXT_V5E, do_qadd},
-  {"qdadd",  0x01400050, NULL,   NULL,        ARM_EXT_V5E, do_qadd},
-  {"qsub",   0x01200050, NULL,   NULL,        ARM_EXT_V5E, do_qadd},
-  {"qdsub",  0x01600050, NULL,   NULL,        ARM_EXT_V5E, do_qadd},
-
-  {"mcrr",  0x0c400000, NULL,   NULL,         ARM_EXT_V5E, do_co_reg2c},
-  {"mrrc",  0x0c500000, NULL,   NULL,         ARM_EXT_V5E, do_co_reg2c},
-};
-
-/* Defines for various bits that we will want to toggle.  */
-#define INST_IMMEDIATE 0x02000000
-#define OFFSET_REG     0x02000000
-#define HWOFFSET_IMM    0x00400000
-#define SHIFT_BY_REG   0x00000010
-#define PRE_INDEX      0x01000000
-#define INDEX_UP       0x00800000
-#define WRITE_BACK     0x00200000
-#define LDM_TYPE_2_OR_3        0x00400000
-
-#define LITERAL_MASK   0xf000f000
-#define COND_MASK      0xf0000000
-#define OPCODE_MASK    0xfe1fffff
-#define DATA_OP_SHIFT  21
-
-/* Codes to distinguish the arithmetic instructions.  */
-#define OPCODE_AND     0
-#define OPCODE_EOR     1
-#define OPCODE_SUB     2
-#define OPCODE_RSB     3
-#define OPCODE_ADD     4
-#define OPCODE_ADC     5
-#define OPCODE_SBC     6
-#define OPCODE_RSC     7
-#define OPCODE_TST     8
-#define OPCODE_TEQ     9
-#define OPCODE_CMP     10
-#define OPCODE_CMN     11
-#define OPCODE_ORR     12
-#define OPCODE_MOV     13
-#define OPCODE_BIC     14
-#define OPCODE_MVN     15
-
-static void do_t_nop           PARAMS ((char *));
-static void do_t_arit          PARAMS ((char *));
-static void do_t_add           PARAMS ((char *));
-static void do_t_asr           PARAMS ((char *));
-static void do_t_branch9       PARAMS ((char *));
-static void do_t_branch12      PARAMS ((char *));
-static void do_t_branch23      PARAMS ((char *));
-static void do_t_bx            PARAMS ((char *));
-static void do_t_compare       PARAMS ((char *));
-static void do_t_ldmstm                PARAMS ((char *));
-static void do_t_ldr           PARAMS ((char *));
-static void do_t_ldrb          PARAMS ((char *));
-static void do_t_ldrh          PARAMS ((char *));
-static void do_t_lds           PARAMS ((char *));
-static void do_t_lsl           PARAMS ((char *));
-static void do_t_lsr           PARAMS ((char *));
-static void do_t_mov           PARAMS ((char *));
-static void do_t_push_pop      PARAMS ((char *));
-static void do_t_str           PARAMS ((char *));
-static void do_t_strb          PARAMS ((char *));
-static void do_t_strh          PARAMS ((char *));
-static void do_t_sub           PARAMS ((char *));
-static void do_t_swi           PARAMS ((char *));
-static void do_t_adr           PARAMS ((char *));
-
-#define T_OPCODE_MUL 0x4340
-#define T_OPCODE_TST 0x4200
-#define T_OPCODE_CMN 0x42c0
-#define T_OPCODE_NEG 0x4240
-#define T_OPCODE_MVN 0x43c0
-
-#define T_OPCODE_ADD_R3        0x1800
-#define T_OPCODE_SUB_R3 0x1a00
-#define T_OPCODE_ADD_HI 0x4400
-#define T_OPCODE_ADD_ST 0xb000
-#define T_OPCODE_SUB_ST 0xb080
-#define T_OPCODE_ADD_SP 0xa800
-#define T_OPCODE_ADD_PC 0xa000
-#define T_OPCODE_ADD_I8 0x3000
-#define T_OPCODE_SUB_I8 0x3800
-#define T_OPCODE_ADD_I3 0x1c00
-#define T_OPCODE_SUB_I3 0x1e00
-
-#define T_OPCODE_ASR_R 0x4100
-#define T_OPCODE_LSL_R 0x4080
-#define T_OPCODE_LSR_R  0x40c0
-#define T_OPCODE_ASR_I 0x1000
-#define T_OPCODE_LSL_I 0x0000
-#define T_OPCODE_LSR_I 0x0800
-
-#define T_OPCODE_MOV_I8        0x2000
-#define T_OPCODE_CMP_I8 0x2800
-#define T_OPCODE_CMP_LR 0x4280
-#define T_OPCODE_MOV_HR 0x4600
-#define T_OPCODE_CMP_HR 0x4500
-
-#define T_OPCODE_LDR_PC 0x4800
-#define T_OPCODE_LDR_SP 0x9800
-#define T_OPCODE_STR_SP 0x9000
-#define T_OPCODE_LDR_IW 0x6800
-#define T_OPCODE_STR_IW 0x6000
-#define T_OPCODE_LDR_IH 0x8800
-#define T_OPCODE_STR_IH 0x8000
-#define T_OPCODE_LDR_IB 0x7800
-#define T_OPCODE_STR_IB 0x7000
-#define T_OPCODE_LDR_RW 0x5800
-#define T_OPCODE_STR_RW 0x5000
-#define T_OPCODE_LDR_RH 0x5a00
-#define T_OPCODE_STR_RH 0x5200
-#define T_OPCODE_LDR_RB 0x5c00
-#define T_OPCODE_STR_RB 0x5400
-
-#define T_OPCODE_PUSH  0xb400
-#define T_OPCODE_POP   0xbc00
-
-#define T_OPCODE_BRANCH 0xe7fe
-
-static int thumb_reg           PARAMS ((char ** str, int hi_lo));
-
-#define THUMB_SIZE     2       /* Size of thumb instruction.  */
-#define THUMB_REG_LO   0x1
-#define THUMB_REG_HI   0x2
-#define THUMB_REG_ANY  0x3
-
-#define THUMB_H1       0x0080
-#define THUMB_H2       0x0040
-
-#define THUMB_ASR 0
-#define THUMB_LSL 1
-#define THUMB_LSR 2
-
-#define THUMB_MOVE 0
-#define THUMB_COMPARE 1
-
-#define THUMB_LOAD 0
-#define THUMB_STORE 1
-
-#define THUMB_PP_PC_LR 0x0100
-
-/* These three are used for immediate shifts, do not alter.  */
-#define THUMB_WORD 2
-#define THUMB_HALFWORD 1
-#define THUMB_BYTE 0
-
-struct thumb_opcode
-{
-  /* Basic string to match.  */
-  CONST char * template;
-
-  /* Basic instruction code.  */
-  unsigned long value;
-
-  int size;
-
-  /* Which CPU variants this exists for.  */
-  unsigned long variants;
-
-  /* Function to call to parse args.  */
-  void (* parms) PARAMS ((char *));
-};
-
-static CONST struct thumb_opcode tinsns[] =
-{
-  {"adc",      0x4140,         2,      ARM_EXT_THUMB, do_t_arit},
-  {"add",      0x0000,         2,      ARM_EXT_THUMB, do_t_add},
-  {"and",      0x4000,         2,      ARM_EXT_THUMB, do_t_arit},
-  {"asr",      0x0000,         2,      ARM_EXT_THUMB, do_t_asr},
-  {"b",                T_OPCODE_BRANCH, 2,     ARM_EXT_THUMB, do_t_branch12},
-  {"beq",      0xd0fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bne",      0xd1fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bcs",      0xd2fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bhs",      0xd2fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bcc",      0xd3fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bul",      0xd3fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"blo",      0xd3fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bmi",      0xd4fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bpl",      0xd5fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bvs",      0xd6fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bvc",      0xd7fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bhi",      0xd8fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bls",      0xd9fe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bge",      0xdafe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"blt",      0xdbfe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bgt",      0xdcfe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"ble",      0xddfe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bal",      0xdefe,         2,      ARM_EXT_THUMB, do_t_branch9},
-  {"bic",      0x4380,         2,      ARM_EXT_THUMB, do_t_arit},
-  {"bl",       0xf7fffffe,     4,      ARM_EXT_THUMB, do_t_branch23},
-  {"blx",      0,              0,      ARM_EXT_V5, do_t_blx},
-  {"bkpt",     0xbe00,         2,      ARM_EXT_V5, do_t_bkpt},
-  {"bx",       0x4700,         2,      ARM_EXT_THUMB, do_t_bx},
-  {"cmn",      T_OPCODE_CMN,   2,      ARM_EXT_THUMB, do_t_arit},
-  {"cmp",      0x0000,         2,      ARM_EXT_THUMB, do_t_compare},
-  {"eor",      0x4040,         2,      ARM_EXT_THUMB, do_t_arit},
-  {"ldmia",    0xc800,         2,      ARM_EXT_THUMB, do_t_ldmstm},
-  {"ldr",      0x0000,         2,      ARM_EXT_THUMB, do_t_ldr},
-  {"ldrb",     0x0000,         2,      ARM_EXT_THUMB, do_t_ldrb},
-  {"ldrh",     0x0000,         2,      ARM_EXT_THUMB, do_t_ldrh},
-  {"ldrsb",    0x5600,         2,      ARM_EXT_THUMB, do_t_lds},
-  {"ldrsh",    0x5e00,         2,      ARM_EXT_THUMB, do_t_lds},
-  {"ldsb",     0x5600,         2,      ARM_EXT_THUMB, do_t_lds},
-  {"ldsh",     0x5e00,         2,      ARM_EXT_THUMB, do_t_lds},
-  {"lsl",      0x0000,         2,      ARM_EXT_THUMB, do_t_lsl},
-  {"lsr",      0x0000,         2,      ARM_EXT_THUMB, do_t_lsr},
-  {"mov",      0x0000,         2,      ARM_EXT_THUMB, do_t_mov},
-  {"mul",      T_OPCODE_MUL,   2,      ARM_EXT_THUMB, do_t_arit},
-  {"mvn",      T_OPCODE_MVN,   2,      ARM_EXT_THUMB, do_t_arit},
-  {"neg",      T_OPCODE_NEG,   2,      ARM_EXT_THUMB, do_t_arit},
-  {"orr",      0x4300,         2,      ARM_EXT_THUMB, do_t_arit},
-  {"pop",      0xbc00,         2,      ARM_EXT_THUMB, do_t_push_pop},
-  {"push",     0xb400,         2,      ARM_EXT_THUMB, do_t_push_pop},
-  {"ror",      0x41c0,         2,      ARM_EXT_THUMB, do_t_arit},
-  {"sbc",      0x4180,         2,      ARM_EXT_THUMB, do_t_arit},
-  {"stmia",    0xc000,         2,      ARM_EXT_THUMB, do_t_ldmstm},
-  {"str",      0x0000,         2,      ARM_EXT_THUMB, do_t_str},
-  {"strb",     0x0000,         2,      ARM_EXT_THUMB, do_t_strb},
-  {"strh",     0x0000,         2,      ARM_EXT_THUMB, do_t_strh},
-  {"swi",      0xdf00,         2,      ARM_EXT_THUMB, do_t_swi},
-  {"sub",      0x0000,         2,      ARM_EXT_THUMB, do_t_sub},
-  {"tst",      T_OPCODE_TST,   2,      ARM_EXT_THUMB, do_t_arit},
-  /* Pseudo ops:  */
-  {"adr",       0x0000,         2,      ARM_EXT_THUMB, do_t_adr},
-  {"nop",       0x46C0,         2,      ARM_EXT_THUMB, do_t_nop},      /* mov r8,r8  */
-};
-
-struct reg_entry
-{
-  CONST char * name;
-  int          number;
-};
-
-#define int_register(reg) ((reg) >= 0 && (reg) <= 15)
-#define cp_register(reg) ((reg) >= 32 && (reg) <= 47)
-#define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
-
-#define REG_PC 15
-#define REG_LR  14
-#define REG_SP  13
-
-/* These are the standard names.  Users can add aliases with .req.  */
-static CONST struct reg_entry reg_table[] =
-{
-  /* Processor Register Numbers.  */
-  {"r0", 0},    {"r1", 1},      {"r2", 2},      {"r3", 3},
-  {"r4", 4},    {"r5", 5},      {"r6", 6},      {"r7", 7},
-  {"r8", 8},    {"r9", 9},      {"r10", 10},    {"r11", 11},
-  {"r12", 12},  {"r13", REG_SP},{"r14", REG_LR},{"r15", REG_PC},
-  /* APCS conventions.  */
-  {"a1", 0},   {"a2", 1},    {"a3", 2},     {"a4", 3},
-  {"v1", 4},   {"v2", 5},    {"v3", 6},     {"v4", 7},     {"v5", 8},
-  {"v6", 9},   {"sb", 9},    {"v7", 10},    {"sl", 10},
-  {"fp", 11},  {"ip", 12},   {"sp", REG_SP},{"lr", REG_LR},{"pc", REG_PC},
-  /* ATPCS additions to APCS conventions.  */
-  {"wr", 7},    {"v8", 11},
-  /* FP Registers.  */
-  {"f0", 16},   {"f1", 17},   {"f2", 18},   {"f3", 19},
-  {"f4", 20},   {"f5", 21},   {"f6", 22},   {"f7", 23},
-  {"c0", 32},   {"c1", 33},   {"c2", 34},   {"c3", 35},
-  {"c4", 36},   {"c5", 37},   {"c6", 38},   {"c7", 39},
-  {"c8", 40},   {"c9", 41},   {"c10", 42},  {"c11", 43},
-  {"c12", 44},  {"c13", 45},  {"c14", 46},  {"c15", 47},
-  {"cr0", 32},  {"cr1", 33},  {"cr2", 34},  {"cr3", 35},
-  {"cr4", 36},  {"cr5", 37},  {"cr6", 38},  {"cr7", 39},
-  {"cr8", 40},  {"cr9", 41},  {"cr10", 42}, {"cr11", 43},
-  {"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47},
-  /* ATPCS additions to float register names.  */
-  {"s0",16},   {"s1",17},      {"s2",18},      {"s3",19},
-  {"s4",20},   {"s5",21},      {"s6",22},      {"s7",23},
-  {"d0",16},   {"d1",17},      {"d2",18},      {"d3",19},
-  {"d4",20},   {"d5",21},      {"d6",22},      {"d7",23},
-  /* FIXME: At some point we need to add VFP register names.  */
-  /* Array terminator.  */
-  {NULL, 0}
-};
-
-#define BAD_ARGS       _("Bad arguments to instruction")
-#define BAD_PC                 _("r15 not allowed here")
-#define BAD_FLAGS      _("Instruction should not have flags")
-#define BAD_COND       _("Instruction is not conditional")
-#define ERR_NO_ACCUM   _("acc0 expected")
-
-static struct hash_control * arm_ops_hsh   = NULL;
-static struct hash_control * arm_tops_hsh  = NULL;
-static struct hash_control * arm_cond_hsh  = NULL;
-static struct hash_control * arm_shift_hsh = NULL;
-static struct hash_control * arm_reg_hsh   = NULL;
-static struct hash_control * arm_psr_hsh   = NULL;
-
-/* This table describes all the machine specific pseudo-ops the assembler
-   has to support.  The fields are:
-     pseudo-op name without dot
-     function to call to execute this pseudo-op
-     Integer arg to pass to the function.  */
-
-static void s_req PARAMS ((int));
-static void s_align PARAMS ((int));
-static void s_bss PARAMS ((int));
-static void s_even PARAMS ((int));
-static void s_ltorg PARAMS ((int));
-static void s_arm PARAMS ((int));
-static void s_thumb PARAMS ((int));
-static void s_code PARAMS ((int));
-static void s_force_thumb PARAMS ((int));
-static void s_thumb_func PARAMS ((int));
-static void s_thumb_set PARAMS ((int));
-static void arm_s_text PARAMS ((int));
-static void arm_s_data PARAMS ((int));
-#ifdef OBJ_ELF
-static void arm_s_section PARAMS ((int));
-static void s_arm_elf_cons PARAMS ((int));
-#endif
-
-static int my_get_expression PARAMS ((expressionS *, char **));
-
-CONST pseudo_typeS md_pseudo_table[] =
-{
-  /* Never called becasue '.req' does not start line.  */
-  { "req",         s_req,         0 },
-  { "bss",         s_bss,         0 },
-  { "align",       s_align,       0 },
-  { "arm",         s_arm,         0 },
-  { "thumb",       s_thumb,       0 },
-  { "code",        s_code,        0 },
-  { "force_thumb", s_force_thumb, 0 },
-  { "thumb_func",  s_thumb_func,  0 },
-  { "thumb_set",   s_thumb_set,   0 },
-  { "even",        s_even,        0 },
-  { "ltorg",       s_ltorg,       0 },
-  { "pool",        s_ltorg,       0 },
-  /* Allow for the effect of section changes.  */
-  { "text",        arm_s_text,    0 },
-  { "data",        arm_s_data,    0 },
-#ifdef OBJ_ELF
-  { "section",     arm_s_section, 0 },
-  { "section.s",   arm_s_section, 0 },
-  { "sect",        arm_s_section, 0 },
-  { "sect.s",      arm_s_section, 0 },
-  { "word",        s_arm_elf_cons, 4 },
-  { "long",        s_arm_elf_cons, 4 },
-  { "file",        dwarf2_directive_file, 0 },
-  { "loc",         dwarf2_directive_loc,  0 },
-#else
-  { "word",        cons, 4},
-#endif
-  { "extend",      float_cons, 'x' },
-  { "ldouble",     float_cons, 'x' },
-  { "packed",      float_cons, 'p' },
-  { 0, 0, 0 }
-};
-
-/* Stuff needed to resolve the label ambiguity
-   As:
-     ...
-     label:   <insn>
-   may differ from:
-     ...
-     label:
-              <insn>
-*/
-
-symbolS *  last_label_seen;
-static int label_is_thumb_function_name = false;
-
-/* Literal stuff.  */
-
-#define MAX_LITERAL_POOL_SIZE 1024
-
-typedef struct literalS
-{
-  struct expressionS exp;
-  struct arm_it *    inst;
-} literalT;
-
-literalT literals[MAX_LITERAL_POOL_SIZE];
-
-/* Next free entry in the pool.  */
-int next_literal_pool_place = 0;
-
-/* Next literal pool number.  */
-int lit_pool_num = 1;
-
-symbolS * current_poolP = NULL;
-
-static int
-add_to_lit_pool ()
-{
-  int lit_count = 0;
-
-  if (current_poolP == NULL)
-    current_poolP = symbol_create (FAKE_LABEL_NAME, undefined_section,
-                                  (valueT) 0, &zero_address_frag);
-
-  /* Check if this literal value is already in the pool:  */
-  while (lit_count < next_literal_pool_place)
-    {
-      if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
-         && inst.reloc.exp.X_op == O_constant
-         && (literals[lit_count].exp.X_add_number
-             == inst.reloc.exp.X_add_number)
-         && literals[lit_count].exp.X_unsigned == inst.reloc.exp.X_unsigned)
-       break;
-
-      if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
-          && inst.reloc.exp.X_op == O_symbol
-          && (literals[lit_count].exp.X_add_number
-             == inst.reloc.exp.X_add_number)
-          && (literals[lit_count].exp.X_add_symbol
-             == inst.reloc.exp.X_add_symbol)
-          && (literals[lit_count].exp.X_op_symbol
-             == inst.reloc.exp.X_op_symbol))
-        break;
-
-      lit_count++;
-    }
-
-  if (lit_count == next_literal_pool_place) /* New entry.  */
-    {
-      if (next_literal_pool_place >= MAX_LITERAL_POOL_SIZE)
-       {
-         inst.error = _("Literal Pool Overflow");
-         return FAIL;
-       }
-
-      literals[next_literal_pool_place].exp = inst.reloc.exp;
-      lit_count = next_literal_pool_place++;
-    }
-
-  inst.reloc.exp.X_op = O_symbol;
-  inst.reloc.exp.X_add_number = (lit_count) * 4 - 8;
-  inst.reloc.exp.X_add_symbol = current_poolP;
-
-  return SUCCESS;
-}
-
-/* Can't use symbol_new here, so have to create a symbol and then at
-   a later date assign it a value. Thats what these functions do.  */
-
-static void
-symbol_locate (symbolP, name, segment, valu, frag)
-     symbolS *    symbolP;
-     CONST char * name;                /* It is copied, the caller can modify.  */
-     segT         segment;     /* Segment identifier (SEG_<something>).  */
-     valueT       valu;                /* Symbol value.  */
-     fragS *      frag;                /* Associated fragment.  */
-{
-  unsigned int name_length;
-  char * preserved_copy_of_name;
-
-  name_length = strlen (name) + 1;   /* +1 for \0.  */
-  obstack_grow (&notes, name, name_length);
-  preserved_copy_of_name = obstack_finish (&notes);
-#ifdef STRIP_UNDERSCORE
-  if (preserved_copy_of_name[0] == '_')
-    preserved_copy_of_name++;
-#endif
-
-#ifdef tc_canonicalize_symbol_name
-  preserved_copy_of_name =
-    tc_canonicalize_symbol_name (preserved_copy_of_name);
-#endif
-
-  S_SET_NAME (symbolP, preserved_copy_of_name);
-
-  S_SET_SEGMENT (symbolP, segment);
-  S_SET_VALUE (symbolP, valu);
-  symbol_clear_list_pointers(symbolP);
-
-  symbol_set_frag (symbolP, frag);
-
-  /* Link to end of symbol chain.  */
-  {
-    extern int symbol_table_frozen;
-    if (symbol_table_frozen)
-      abort ();
-  }
-
-  symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
-
-  obj_symbol_new_hook (symbolP);
-
-#ifdef tc_symbol_new_hook
-  tc_symbol_new_hook (symbolP);
-#endif
-
-#ifdef DEBUG_SYMS
-  verify_symbol_chain (symbol_rootP, symbol_lastP);
-#endif /* DEBUG_SYMS  */
-}
-
-/* Check that an immediate is valid.
-   If so, convert it to the right format.  */
-
-static unsigned int
-validate_immediate (val)
-     unsigned int val;
-{
-  unsigned int a;
-  unsigned int i;
-
-#define rotate_left(v, n) (v << n | v >> (32 - n))
-
-  for (i = 0; i < 32; i += 2)
-    if ((a = rotate_left (val, i)) <= 0xff)
-      return a | (i << 7); /* 12-bit pack: [shift-cnt,const].  */
-
-  return FAIL;
-}
-
-/* Check to see if an immediate can be computed as two seperate immediate
-   values, added together.  We already know that this value cannot be
-   computed by just one ARM instruction.  */
-
-static unsigned int
-validate_immediate_twopart (val, highpart)
-     unsigned int   val;
-     unsigned int * highpart;
-{
-  unsigned int a;
-  unsigned int i;
-
-  for (i = 0; i < 32; i += 2)
-    if (((a = rotate_left (val, i)) & 0xff) != 0)
-      {
-       if (a & 0xff00)
-         {
-           if (a & ~ 0xffff)
-             continue;
-           * highpart = (a  >> 8) | ((i + 24) << 7);
-         }
-       else if (a & 0xff0000)
-         {
-           if (a & 0xff000000)
-             continue;
-           * highpart = (a >> 16) | ((i + 16) << 7);
-         }
-       else
-         {
-           assert (a & 0xff000000);
-           * highpart = (a >> 24) | ((i + 8) << 7);
-         }
-
-       return (a & 0xff) | (i << 7);
-      }
-
-  return FAIL;
-}
-
-static int
-validate_offset_imm (val, hwse)
-     unsigned int val;
-     int hwse;
-{
-  if ((hwse && val > 255) || val > 4095)
-    return FAIL;
-  return val;
-}
-
-static void
-s_req (a)
-     int a ATTRIBUTE_UNUSED;
-{
-  as_bad (_("Invalid syntax for .req directive."));
-}
-
-static void
-s_bss (ignore)
-     int ignore ATTRIBUTE_UNUSED;
-{
-  /* We don't support putting frags in the BSS segment, we fake it by
-     marking in_bss, then looking at s_skip for clues.  */
-  subseg_set (bss_section, 0);
-  demand_empty_rest_of_line ();
-}
-
-static void
-s_even (ignore)
-     int ignore ATTRIBUTE_UNUSED;
-{
-  /* Never make frag if expect extra pass.  */
-  if (!need_pass_2)
-    frag_align (1, 0, 0);
-
-  record_alignment (now_seg, 1);
-
-  demand_empty_rest_of_line ();
-}
-
-static void
-s_ltorg (ignored)
-     int ignored ATTRIBUTE_UNUSED;
-{
-  int lit_count = 0;
-  char sym_name[20];
-
-  if (current_poolP == NULL)
-    return;
-
-  /* Align pool as you have word accesses.
-     Only make a frag if we have to.  */
-  if (!need_pass_2)
-    frag_align (2, 0, 0);
-
-  record_alignment (now_seg, 2);
-
-  sprintf (sym_name, "$$lit_\002%x", lit_pool_num++);
-
-  symbol_locate (current_poolP, sym_name, now_seg,
-                (valueT) frag_now_fix (), frag_now);
-  symbol_table_insert (current_poolP);
-
-  ARM_SET_THUMB (current_poolP, thumb_mode);
-
-#if defined OBJ_COFF || defined OBJ_ELF
-  ARM_SET_INTERWORK (current_poolP, support_interwork);
-#endif
-
-  while (lit_count < next_literal_pool_place)
-    /* First output the expression in the instruction to the pool.  */
-    emit_expr (&(literals[lit_count++].exp), 4); /* .word  */
-
-  next_literal_pool_place = 0;
-  current_poolP = NULL;
-}
-
-/* Same as s_align_ptwo but align 0 => align 2.  */
-
-static void
-s_align (unused)
-     int unused ATTRIBUTE_UNUSED;
-{
-  register int temp;
-  register long temp_fill;
-  long max_alignment = 15;
-
-  temp = get_absolute_expression ();
-  if (temp > max_alignment)
-    as_bad (_("Alignment too large: %d. assumed."), temp = max_alignment);
-  else if (temp < 0)
-    {
-      as_bad (_("Alignment negative. 0 assumed."));
-      temp = 0;
-    }
-
-  if (*input_line_pointer == ',')
-    {
-      input_line_pointer++;
-      temp_fill = get_absolute_expression ();
-    }
-  else
-    temp_fill = 0;
-
-  if (!temp)
-    temp = 2;
-
-  /* Only make a frag if we HAVE to.  */
-  if (temp && !need_pass_2)
-    frag_align (temp, (int) temp_fill, 0);
-  demand_empty_rest_of_line ();
-
-  record_alignment (now_seg, temp);
-}
-
-static void
-s_force_thumb (ignore)
-     int ignore ATTRIBUTE_UNUSED;
-{
-  /* If we are not already in thumb mode go into it, EVEN if
-     the target processor does not support thumb instructions.
-     This is used by gcc/config/arm/lib1funcs.asm for example
-     to compile interworking support functions even if the
-     target processor should not support interworking.  */
-  if (! thumb_mode)
-    {
-      thumb_mode = 2;
-
-      record_alignment (now_seg, 1);
-    }
-
-  demand_empty_rest_of_line ();
-}
-
-static void
-s_thumb_func (ignore)
-     int ignore ATTRIBUTE_UNUSED;
-{
-  if (! thumb_mode)
-    opcode_select (16);
-
-  /* The following label is the name/address of the start of a Thumb function.
-     We need to know this for the interworking support.  */
-  label_is_thumb_function_name = true;
-
-  demand_empty_rest_of_line ();
-}
-
-/* Perform a .set directive, but also mark the alias as
-   being a thumb function.  */
-
-static void
-s_thumb_set (equiv)
-     int equiv;
-{
-  /* XXX the following is a duplicate of the code for s_set() in read.c
-     We cannot just call that code as we need to get at the symbol that
-     is created.  */
-  register char *    name;
-  register char      delim;
-  register char *    end_name;
-  register symbolS * symbolP;
-
-  /* Especial apologies for the random logic:
-     This just grew, and could be parsed much more simply!
-     Dean - in haste.  */
-  name      = input_line_pointer;
-  delim     = get_symbol_end ();
-  end_name  = input_line_pointer;
-  *end_name = delim;
-
-  SKIP_WHITESPACE ();
-
-  if (*input_line_pointer != ',')
-    {
-      *end_name = 0;
-      as_bad (_("Expected comma after name \"%s\""), name);
-      *end_name = delim;
-      ignore_rest_of_line ();
-      return;
-    }
-
-  input_line_pointer++;
-  *end_name = 0;
-
-  if (name[0] == '.' && name[1] == '\0')
-    {
-      /* XXX - this should not happen to .thumb_set.  */
-      abort ();
-    }
-
-  if ((symbolP = symbol_find (name)) == NULL
-      && (symbolP = md_undefined_symbol (name)) == NULL)
-    {
-#ifndef NO_LISTING
-      /* When doing symbol listings, play games with dummy fragments living
-        outside the normal fragment chain to record the file and line info
-         for this symbol.  */
-      if (listing & LISTING_SYMBOLS)
-       {
-         extern struct list_info_struct * listing_tail;
-         fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
-
-         memset (dummy_frag, 0, sizeof (fragS));
-         dummy_frag->fr_type = rs_fill;
-         dummy_frag->line = listing_tail;
-         symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
-         dummy_frag->fr_symbol = symbolP;
-       }
-      else
-#endif
-       symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
-
-#ifdef OBJ_COFF
-      /* "set" symbols are local unless otherwise specified.  */
-      SF_SET_LOCAL (symbolP);
-#endif /* OBJ_COFF  */
-    }                          /* Make a new symbol.  */
-
-  symbol_table_insert (symbolP);
-
-  * end_name = delim;
-
-  if (equiv
-      && S_IS_DEFINED (symbolP)
-      && S_GET_SEGMENT (symbolP) != reg_section)
-    as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
-
-  pseudo_set (symbolP);
-
-  demand_empty_rest_of_line ();
-
-  /* XXX Now we come to the Thumb specific bit of code.  */
-
-  THUMB_SET_FUNC (symbolP, 1);
-  ARM_SET_THUMB (symbolP, 1);
-#if defined OBJ_ELF || defined OBJ_COFF
-  ARM_SET_INTERWORK (symbolP, support_interwork);
-#endif
-}
-
-/* If we change section we must dump the literal pool first.  */
-
-static void
-arm_s_text (ignore)
-     int ignore;
-{
-  if (now_seg != text_section)
-    s_ltorg (0);
-
-#ifdef OBJ_ELF
-  obj_elf_text (ignore);
-#else
-  s_text (ignore);
-#endif
-}
-
-static void
-arm_s_data (ignore)
-     int ignore;
-{
-  if (flag_readonly_data_in_text)
-    {
-      if (now_seg != text_section)
-       s_ltorg (0);
-    }
-  else if (now_seg != data_section)
-    s_ltorg (0);
-
-#ifdef OBJ_ELF
-  obj_elf_data (ignore);
-#else
-  s_data (ignore);
-#endif
-}
-
-#ifdef OBJ_ELF
-static void
-arm_s_section (ignore)
-     int ignore;
-{
-  s_ltorg (0);
-
-  obj_elf_section (ignore);
-}
-#endif
-
-static void
-opcode_select (width)
-     int width;
-{
-  switch (width)
-    {
-    case 16:
-      if (! thumb_mode)
-       {
-         if (! (cpu_variant & ARM_EXT_THUMB))
-           as_bad (_("selected processor does not support THUMB opcodes"));
-
-         thumb_mode = 1;
-         /* No need to force the alignment, since we will have been
-             coming from ARM mode, which is word-aligned.  */
-         record_alignment (now_seg, 1);
-       }
-      break;
-
-    case 32:
-      if (thumb_mode)
-       {
-         if ((cpu_variant & ARM_ANY) == ARM_EXT_THUMB)
-           as_bad (_("selected processor does not support ARM opcodes"));
-
-         thumb_mode = 0;
-
-         if (!need_pass_2)
-            frag_align (2, 0, 0);
-
-          record_alignment (now_seg, 1);
-       }
-      break;
-
-    default:
-      as_bad (_("invalid instruction size selected (%d)"), width);
-    }
-}
-
-static void
-s_arm (ignore)
-     int ignore ATTRIBUTE_UNUSED;
-{
-  opcode_select (32);
-  demand_empty_rest_of_line ();
-}
-
-static void
-s_thumb (ignore)
-     int ignore ATTRIBUTE_UNUSED;
-{
-  opcode_select (16);
-  demand_empty_rest_of_line ();
-}
-
-static void
-s_code (unused)
-     int unused ATTRIBUTE_UNUSED;
-{
-  register int temp;
-
-  temp = get_absolute_expression ();
-  switch (temp)
-    {
-    case 16:
-    case 32:
-      opcode_select (temp);
-      break;
-
-    default:
-      as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
-    }
-}
-
-static void
-end_of_line (str)
-     char * str;
-{
-  skip_whitespace (str);
-
-  if (* str != '\0')
-    inst.error = _("Garbage following instruction");
-}
-
-static int
-skip_past_comma (str)
-     char ** str;
-{
-  char * p = * str, c;
-  int comma = 0;
-
-  while ((c = *p) == ' ' || c == ',')
-    {
-      p++;
-      if (c == ',' && comma++)
-       return FAIL;
-    }
-
-  if (c == '\0')
-    return FAIL;
-
-  *str = p;
-  return comma ? SUCCESS : FAIL;
-}
-
-/* A standard register must be given at this point.
-   SHIFT is the place to put it in inst.instruction.
-   Restores input start point on error.
-   Returns the reg#, or FAIL.  */
-
-static int
-reg_required_here (str, shift)
-     char ** str;
-     int     shift;
-{
-  static char buff [128]; /* XXX  */
-  int         reg;
-  char *      start = * str;
-
-  if ((reg = arm_reg_parse (str)) != FAIL && int_register (reg))
-    {
-      if (shift >= 0)
-       inst.instruction |= reg << shift;
-      return reg;
-    }
-
-  /* Restore the start point, we may have got a reg of the wrong class.  */
-  *str = start;
-
-  /* In the few cases where we might be able to accept something else
-     this error can be overridden.  */
-  sprintf (buff, _("Register expected, not '%.100s'"), start);
-  inst.error = buff;
-
-  return FAIL;
-}
-
-static CONST struct asm_psr *
-arm_psr_parse (ccp)
-     register char ** ccp;
-{
-  char * start = * ccp;
-  char   c;
-  char * p;
-  CONST struct asm_psr * psr;
-
-  p = start;
-
-  /* Skip to the end of the next word in the input stream.  */
-  do
-    {
-      c = *p++;
-    }
-  while (isalpha (c) || c == '_');
-
-  /* Terminate the word.  */
-  *--p = 0;
-
-  /* CPSR's and SPSR's can now be lowercase.  This is just a convenience
-     feature for ease of use and backwards compatibility.  */
-  if (!strncmp (start, "cpsr", 4))
-    strncpy (start, "CPSR", 4);
-  else if (!strncmp (start, "spsr", 4))
-    strncpy (start, "SPSR", 4);
-
-  /* Now locate the word in the psr hash table.  */
-  psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start);
-
-  /* Restore the input stream.  */
-  *p = c;
-
-  /* If we found a valid match, advance the
-     stream pointer past the end of the word.  */
-  *ccp = p;
-
-  return psr;
-}
-
-/* Parse the input looking for a PSR flag.  */
-
-static int
-psr_required_here (str)
-     char ** str;
-{
-  char * start = * str;
-  CONST struct asm_psr * psr;
-
-  psr = arm_psr_parse (str);
-
-  if (psr)
-    {
-      /* If this is the SPSR that is being modified, set the R bit.  */
-      if (! psr->cpsr)
-       inst.instruction |= SPSR_BIT;
-
-      /* Set the psr flags in the MSR instruction.  */
-      inst.instruction |= psr->field << PSR_SHIFT;
-
-      return SUCCESS;
-    }
-
-  /* In the few cases where we might be able to accept
-     something else this error can be overridden.  */
-  inst.error = _("flag for {c}psr instruction expected");
-
-  /* Restore the start point.  */
-  *str = start;
-  return FAIL;
-}
-
-static int
-co_proc_number (str)
-     char ** str;
-{
-  int processor, pchar;
-
-  skip_whitespace (* str);
-
-  /* The data sheet seems to imply that just a number on its own is valid
-     here, but the RISC iX assembler seems to accept a prefix 'p'.  We will
-     accept either.  */
-  if (**str == 'p' || **str == 'P')
-    (*str)++;
-
-  pchar = *(*str)++;
-  if (pchar >= '0' && pchar <= '9')
-    {
-      processor = pchar - '0';
-      if (**str >= '0' && **str <= '9')
-       {
-         processor = processor * 10 + *(*str)++ - '0';
-         if (processor > 15)
-           {
-             inst.error = _("Illegal co-processor number");
-             return FAIL;
-           }
-       }
-    }
-  else
-    {
-      inst.error = _("Bad or missing co-processor number");
-      return FAIL;
-    }
-
-  inst.instruction |= processor << 8;
-  return SUCCESS;
-}
-
-static int
-cp_opc_expr (str, where, length)
-     char ** str;
-     int where;
-     int length;
-{
-  expressionS expr;
-
-  skip_whitespace (* str);
-
-  memset (&expr, '\0', sizeof (expr));
-
-  if (my_get_expression (&expr, str))
-    return FAIL;
-  if (expr.X_op != O_constant)
-    {
-      inst.error = _("bad or missing expression");
-      return FAIL;
-    }
-
-  if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
-    {
-      inst.error = _("immediate co-processor expression too large");
-      return FAIL;
-    }
-
-  inst.instruction |= expr.X_add_number << where;
-  return SUCCESS;
-}
-
-static int
-cp_reg_required_here (str, where)
-     char ** str;
-     int     where;
-{
-  int    reg;
-  char * start = *str;
-
-  if ((reg = arm_reg_parse (str)) != FAIL && cp_register (reg))
-    {
-      reg &= 15;
-      inst.instruction |= reg << where;
-      return reg;
-    }
-
-  /* In the few cases where we might be able to accept something else
-     this error can be overridden.  */
-  inst.error = _("Co-processor register expected");
-
-  /* Restore the start point.  */
-  *str = start;
-  return FAIL;
-}
-
-static int
-fp_reg_required_here (str, where)
-     char ** str;
-     int     where;
-{
-  int    reg;
-  char * start = * str;
-
-  if ((reg = arm_reg_parse (str)) != FAIL && fp_register (reg))
-    {
-      reg &= 7;
-      inst.instruction |= reg << where;
-      return reg;
-    }
-
-  /* In the few cases where we might be able to accept something else
-     this error can be overridden.  */
-  inst.error = _("Floating point register expected");
-
-  /* Restore the start point.  */
-  *str = start;
-  return FAIL;
-}
-
-static int
-cp_address_offset (str)
-     char ** str;
-{
-  int offset;
-
-  skip_whitespace (* str);
-
-  if (! is_immediate_prefix (**str))
-    {
-      inst.error = _("immediate expression expected");
-      return FAIL;
-    }
-
-  (*str)++;
-
-  if (my_get_expression (& inst.reloc.exp, str))
-    return FAIL;
-
-  if (inst.reloc.exp.X_op == O_constant)
-    {
-      offset = inst.reloc.exp.X_add_number;
-
-      if (offset & 3)
-       {
-         inst.error = _("co-processor address must be word aligned");
-         return FAIL;
-       }
-
-      if (offset > 1023 || offset < -1023)
-       {
-         inst.error = _("offset too large");
-         return FAIL;
-       }
-
-      if (offset >= 0)
-       inst.instruction |= INDEX_UP;
-      else
-       offset = -offset;
-
-      inst.instruction |= offset >> 2;
-    }
-  else
-    inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
-
-  return SUCCESS;
-}
-
-static int
-cp_address_required_here (str)
-     char ** str;
-{
-  char * p = * str;
-  int    pre_inc = 0;
-  int    write_back = 0;
-
-  if (*p == '[')
-    {
-      int reg;
-
-      p++;
-      skip_whitespace (p);
-
-      if ((reg = reg_required_here (& p, 16)) == FAIL)
-       return FAIL;
-
-      skip_whitespace (p);
-
-      if (*p == ']')
-       {
-         p++;
-
-         if (skip_past_comma (& p) == SUCCESS)
-           {
-             /* [Rn], #expr  */
-             write_back = WRITE_BACK;
-
-             if (reg == REG_PC)
-               {
-                 inst.error = _("pc may not be used in post-increment");
-                 return FAIL;
-               }
-
-             if (cp_address_offset (& p) == FAIL)
-               return FAIL;
-           }
-         else
-           pre_inc = PRE_INDEX | INDEX_UP;
-       }
-      else
-       {
-         /* '['Rn, #expr']'[!]  */
-
-         if (skip_past_comma (& p) == FAIL)
-           {
-             inst.error = _("pre-indexed expression expected");
-             return FAIL;
-           }
-
-         pre_inc = PRE_INDEX;
-
-         if (cp_address_offset (& p) == FAIL)
-           return FAIL;
-
-         skip_whitespace (p);
-
-         if (*p++ != ']')
-           {
-             inst.error = _("missing ]");
-             return FAIL;
-           }
-
-         skip_whitespace (p);
-
-         if (*p == '!')
-           {
-             if (reg == REG_PC)
-               {
-                 inst.error = _("pc may not be used with write-back");
-                 return FAIL;
-               }
-
-             p++;
-             write_back = WRITE_BACK;
-           }
-       }
-    }
-  else
-    {
-      if (my_get_expression (&inst.reloc.exp, &p))
-       return FAIL;
-
-      inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
-      inst.reloc.exp.X_add_number -= 8;  /* PC rel adjust.  */
-      inst.reloc.pc_rel = 1;
-      inst.instruction |= (REG_PC << 16);
-      pre_inc = PRE_INDEX;
-    }
-
-  inst.instruction |= write_back | pre_inc;
-  *str = p;
-  return SUCCESS;
-}
-
-static void
-do_nop (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  /* Do nothing really.  */
-  inst.instruction |= flags; /* This is pointless.  */
-  end_of_line (str);
-  return;
-}
-
-static void
-do_mrs (str, flags)
-     char *str;
-     unsigned long flags;
-{
-  int skip = 0;
-
-  /* Only one syntax.  */
-  skip_whitespace (str);
-
-  if (reg_required_here (&str, 12) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL)
-    {
-      inst.error = _("comma expected after register name");
-      return;
-    }
-
-  skip_whitespace (str);
-
-  if (   strcmp (str, "CPSR") == 0
-      || strcmp (str, "SPSR") == 0
-        /* Lower case versions for backwards compatability.  */
-      || strcmp (str, "cpsr") == 0
-      || strcmp (str, "spsr") == 0)
-    skip = 4;
-
-  /* This is for backwards compatability with older toolchains.  */
-  else if (   strcmp (str, "cpsr_all") == 0
-          || strcmp (str, "spsr_all") == 0)
-    skip = 8;
-  else
-    {
-      inst.error = _("{C|S}PSR expected");
-      return;
-    }
-
-  if (* str == 's' || * str == 'S')
-    inst.instruction |= SPSR_BIT;
-  str += skip;
-
-  inst.instruction |= flags;
-  end_of_line (str);
-}
-
-/* Two possible forms:
-      "{C|S}PSR_<field>, Rm",
-      "{C|S}PSR_f, #expression".  */
-
-static void
-do_msr (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  if (psr_required_here (& str) == FAIL)
-    return;
-
-  if (skip_past_comma (& str) == FAIL)
-    {
-      inst.error = _("comma missing after psr flags");
-      return;
-    }
-
-  skip_whitespace (str);
-
-  if (reg_required_here (& str, 0) != FAIL)
-    {
-      inst.error = NULL;
-      inst.instruction |= flags;
-      end_of_line (str);
-      return;
-    }
-
-  if (! is_immediate_prefix (* str))
-    {
-      inst.error =
-       _("only a register or immediate value can follow a psr flag");
-      return;
-    }
-
-  str ++;
-  inst.error = NULL;
-
-  if (my_get_expression (& inst.reloc.exp, & str))
-    {
-      inst.error =
-       _("only a register or immediate value can follow a psr flag");
-      return;
-    }
-
-#if 0  /* The first edition of the ARM architecture manual stated that
-         writing anything other than the flags with an immediate operation
-         had UNPREDICTABLE effects.  This constraint was removed in the
-         second edition of the specification.  */
-  if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
-      && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
-    {
-      inst.error = _("immediate value cannot be used to set this field");
-      return;
-    }
-#endif
-
-  flags |= INST_IMMEDIATE;
-
-  if (inst.reloc.exp.X_add_symbol)
-    {
-      inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
-      inst.reloc.pc_rel = 0;
-    }
-  else
-    {
-      unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
-
-      if (value == (unsigned) FAIL)
-       {
-         inst.error = _("Invalid constant");
-         return;
-       }
-
-      inst.instruction |= value;
-    }
-
-  inst.error = NULL;
-  inst.instruction |= flags;
-  end_of_line (str);
-}
-
-/* Long Multiply Parser
-   UMULL RdLo, RdHi, Rm, Rs
-   SMULL RdLo, RdHi, Rm, Rs
-   UMLAL RdLo, RdHi, Rm, Rs
-   SMLAL RdLo, RdHi, Rm, Rs.  */
-
-static void
-do_mull (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  int rdlo, rdhi, rm, rs;
-
-  /* Only one format "rdlo, rdhi, rm, rs".  */
-  skip_whitespace (str);
-
-  if ((rdlo = reg_required_here (&str, 12)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || (rdhi = reg_required_here (&str, 16)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || (rm = reg_required_here (&str, 0)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  /* rdhi, rdlo and rm must all be different.  */
-  if (rdlo == rdhi || rdlo == rm || rdhi == rm)
-    as_tsktsk (_("rdhi, rdlo and rm must all be different"));
-
-  if (skip_past_comma (&str) == FAIL
-      || (rs = reg_required_here (&str, 8)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
-    {
-      inst.error = BAD_PC;
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-static void
-do_mul (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  int rd, rm;
-
-  /* Only one format "rd, rm, rs".  */
-  skip_whitespace (str);
-
-  if ((rd = reg_required_here (&str, 16)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (rd == REG_PC)
-    {
-      inst.error = BAD_PC;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || (rm = reg_required_here (&str, 0)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (rm == REG_PC)
-    {
-      inst.error = BAD_PC;
-      return;
-    }
-
-  if (rm == rd)
-    as_tsktsk (_("rd and rm should be different in mul"));
-
-  if (skip_past_comma (&str) == FAIL
-      || (rm = reg_required_here (&str, 8)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (rm == REG_PC)
-    {
-      inst.error = BAD_PC;
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-static void
-do_mla (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  int rd, rm;
-
-  /* Only one format "rd, rm, rs, rn".  */
-  skip_whitespace (str);
-
-  if ((rd = reg_required_here (&str, 16)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (rd == REG_PC)
-    {
-      inst.error = BAD_PC;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || (rm = reg_required_here (&str, 0)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (rm == REG_PC)
-    {
-      inst.error = BAD_PC;
-      return;
-    }
-
-  if (rm == rd)
-    as_tsktsk (_("rd and rm should be different in mla"));
-
-  if (skip_past_comma (&str) == FAIL
-      || (rd = reg_required_here (&str, 8)) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || (rm = reg_required_here (&str, 12)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (rd == REG_PC || rm == REG_PC)
-    {
-      inst.error = BAD_PC;
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-/* Expects *str -> the characters "acc0", possibly with leading blanks.
-   Advances *str to the next non-alphanumeric.
-   Returns 0, or else FAIL (in which case sets inst.error).
-
-  (In a future XScale, there may be accumulators other than zero.
-  At that time this routine and its callers can be upgraded to suit.)  */
-
-static int
-accum0_required_here (str)
-     char ** str;
-{
-  static char buff [128];      /* Note the address is taken.  Hence, static.  */
-  char * p = * str;
-  char   c;
-  int result = 0;              /* The accum number.  */
-
-  skip_whitespace (p);
-
-  *str = p;                    /* Advance caller's string pointer too.  */
-  c = *p++;
-  while (isalnum (c))
-    c = *p++;
-
-  *--p = 0;                    /* Aap nul into input buffer at non-alnum.  */
-
-  if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
-    {
-      sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
-      inst.error = buff;
-      result = FAIL;
-    }
-
-  *p = c;                      /* Unzap.  */
-  *str = p;                    /* Caller's string pointer to after match.  */
-  return result;
-}
-
-/* Expects **str -> after a comma. May be leading blanks.
-   Advances *str, recognizing a load  mode, and setting inst.instruction.
-   Returns rn, or else FAIL (in which case may set inst.error
-   and not advance str)
-
-   Note: doesn't know Rd, so no err checks that require such knowledge.  */
-
-static int
-ld_mode_required_here (string)
-     char ** string;
-{
-  char * str = * string;
-  int    rn;
-  int    pre_inc = 0;
-
-  skip_whitespace (str);
-
-  if (* str == '[')
-    {
-      str++;
-
-      skip_whitespace (str);
-
-      if ((rn = reg_required_here (& str, 16)) == FAIL)
-       return FAIL;
-
-      skip_whitespace (str);
-
-      if (* str == ']')
-       {
-         str ++;
-
-         if (skip_past_comma (& str) == SUCCESS)
-           {
-             /* [Rn],... (post inc) */
-             if (ldst_extend (& str, 1) == FAIL)
-               return FAIL;
-           }
-         else        /* [Rn] */
-           {
-              skip_whitespace (str);
-
-              if (* str == '!')
-               {
-                 str ++;
-                 inst.instruction |= WRITE_BACK;
-               }
-
-             inst.instruction |= INDEX_UP | HWOFFSET_IMM;
-             pre_inc = 1;
-           }
-       }
-      else       /* [Rn,...] */
-       {
-         if (skip_past_comma (& str) == FAIL)
-           {
-             inst.error = _("pre-indexed expression expected");
-             return FAIL;
-           }
-
-         pre_inc = 1;
-
-         if (ldst_extend (& str, 1) == FAIL)
-           return FAIL;
-
-         skip_whitespace (str);
-
-         if (* str ++ != ']')
-           {
-             inst.error = _("missing ]");
-             return FAIL;
-           }
-
-         skip_whitespace (str);
-
-         if (* str == '!')
-           {
-             str ++;
-             inst.instruction |= WRITE_BACK;
-           }
-       }
-    }
-  else if (* str == '=')       /* ldr's "r,=label" syntax */
-    /* We should never reach here, because <text> = <expression> is
-       caught gas/read.c read_a_source_file() as a .set operation.  */
-    return FAIL;
-  else                         /* PC +- 8 bit immediate offset.  */
-    {
-      if (my_get_expression (& inst.reloc.exp, & str))
-       return FAIL;
-
-      inst.instruction            |= HWOFFSET_IMM;     /* The I bit.  */
-      inst.reloc.type              = BFD_RELOC_ARM_OFFSET_IMM8;
-      inst.reloc.exp.X_add_number -= 8;                /* PC rel adjust.  */
-      inst.reloc.pc_rel            = 1;
-      inst.instruction            |= (REG_PC << 16);
-
-      rn = REG_PC;
-      pre_inc = 1;
-    }
-
-  inst.instruction |= (pre_inc ? PRE_INDEX : 0);
-  * string = str;
-
-  return rn;
-}
-
-/* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
-   SMLAxy{cond} Rd,Rm,Rs,Rn
-   SMLAWy{cond} Rd,Rm,Rs,Rn
-   Error if any register is R15.  */
-
-static void
-do_smla (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  int rd, rm, rs, rn;
-
-  skip_whitespace (str);
-
-  if ((rd = reg_required_here (& str, 16)) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || (rm = reg_required_here (& str, 0)) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || (rs = reg_required_here (& str, 8)) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || (rn = reg_required_here (& str, 12)) == FAIL)
-    inst.error = BAD_ARGS;
-
-  else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
-    inst.error = BAD_PC;
-
-  else if (flags)
-    inst.error = BAD_FLAGS;
-
-  else
-    end_of_line (str);
-}
-
-/* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
-   SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
-   Error if any register is R15.
-   Warning if Rdlo == Rdhi.  */
-
-static void
-do_smlal (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  int rdlo, rdhi, rm, rs;
-
-  skip_whitespace (str);
-
-  if ((rdlo = reg_required_here (& str, 12)) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || (rdhi = reg_required_here (& str, 16)) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || (rm = reg_required_here (& str, 0)) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || (rs = reg_required_here (& str, 8)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
-    {
-      inst.error = BAD_PC;
-      return;
-    }
-
-  if (rdlo == rdhi)
-    as_tsktsk (_("rdhi and rdlo must be different"));
-
-  if (flags)
-    inst.error = BAD_FLAGS;
-  else
-    end_of_line (str);
-}
-
-/* ARM V5E (El Segundo) signed-multiply (argument parse)
-   SMULxy{cond} Rd,Rm,Rs
-   Error if any register is R15.  */
-
-static void
-do_smul (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  int rd, rm, rs;
-
-  skip_whitespace (str);
-
-  if ((rd = reg_required_here (& str, 16)) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || (rm = reg_required_here (& str, 0)) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || (rs = reg_required_here (& str, 8)) == FAIL)
-    inst.error = BAD_ARGS;
-
-  else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
-    inst.error = BAD_PC;
-
-  else if (flags)
-    inst.error = BAD_FLAGS;
-
-  else
-    end_of_line (str);
-}
-
-/* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
-   Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
-   Error if any register is R15.  */
-
-static void
-do_qadd (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  int rd, rm, rn;
-
-  skip_whitespace (str);
-
-  if ((rd = reg_required_here (& str, 12)) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || (rm = reg_required_here (& str, 0)) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || (rn = reg_required_here (& str, 16)) == FAIL)
-    inst.error = BAD_ARGS;
-
-  else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
-    inst.error = BAD_PC;
-
-  else if (flags)
-    inst.error = BAD_FLAGS;
-
-  else
-    end_of_line (str);
-}
-
-/* ARM V5E (el Segundo)
-   MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
-   MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
-
-   These are equivalent to the XScale instructions MAR and MRA,
-   respectively, when coproc == 0, opcode == 0, and CRm == 0.
-
-   Result unpredicatable if Rd or Rn is R15.  */
-
-static void
-do_co_reg2c (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  int rd, rn;
-
-  skip_whitespace (str);
-
-  if (co_proc_number (& str) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || cp_opc_expr (& str, 4, 4) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || (rd = reg_required_here (& str, 12)) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || (rn = reg_required_here (& str, 16)) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  /* Unpredictable result if rd or rn is R15.  */
-  if (rd == REG_PC || rn == REG_PC)
-    as_tsktsk
-      (_("Warning: Instruction unpredictable when using r15"));
-
-  if (skip_past_comma (& str) == FAIL
-      || cp_reg_required_here (& str, 0) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (flags)
-    inst.error = BAD_COND;
-
-  end_of_line (str);
-}
-
-/* ARM V5 count-leading-zeroes instruction (argument parse)
-     CLZ{<cond>} <Rd>, <Rm>
-     Condition defaults to COND_ALWAYS.
-     Error if Rd or Rm are R15.  */
-
-static void
-do_clz (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  int rd, rm;
-
-  if (flags)
-    {
-      as_bad (BAD_FLAGS);
-      return;
-    }
-
-  skip_whitespace (str);
-
-  if (((rd = reg_required_here (& str, 12)) == FAIL)
-      || (skip_past_comma (& str) == FAIL)
-      || ((rm = reg_required_here (& str, 0)) == FAIL))
-    inst.error = BAD_ARGS;
-
-  else if (rd == REG_PC || rm == REG_PC )
-    inst.error = BAD_PC;
-
-  else
-    end_of_line (str);
-}
-
-/* ARM V5 (argument parse)
-     LDC2{L} <coproc>, <CRd>, <addressing mode>
-     STC2{L} <coproc>, <CRd>, <addressing mode>
-     Instruction is not conditional, and has 0xf in the codition field.
-     Otherwise, it's the same as LDC/STC.  */
-
-static void
-do_lstc2 (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  if (flags)
-    inst.error = BAD_COND;
-
-  skip_whitespace (str);
-
-  if (co_proc_number (& str) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-    }
-  else if (skip_past_comma (& str) == FAIL
-          || cp_reg_required_here (& str, 12) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-    }
-  else if (skip_past_comma (& str) == FAIL
-          || cp_address_required_here (& str) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-    }
-  else
-    end_of_line (str);
-}
-
-/* ARM V5 (argument parse)
-     CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
-     Instruction is not conditional, and has 0xf in the condition field.
-     Otherwise, it's the same as CDP.  */
-
-static void
-do_cdp2 (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  if (co_proc_number (& str) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || cp_opc_expr (& str, 20,4) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || cp_reg_required_here (& str, 12) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || cp_reg_required_here (& str, 16) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || cp_reg_required_here (& str, 0) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == SUCCESS)
-    {
-      if (cp_opc_expr (& str, 5, 3) == FAIL)
-       {
-         if (!inst.error)
-           inst.error = BAD_ARGS;
-         return;
-       }
-    }
-
-  if (flags)
-    inst.error = BAD_FLAGS;
-
-  end_of_line (str);
-}
-
-/* ARM V5 (argument parse)
-     MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
-     MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
-     Instruction is not conditional, and has 0xf in the condition field.
-     Otherwise, it's the same as MCR/MRC.  */
-
-static void
-do_co_reg2 (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  if (co_proc_number (& str) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || cp_opc_expr (& str, 21, 3) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || reg_required_here (& str, 12) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || cp_reg_required_here (& str, 16) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || cp_reg_required_here (& str, 0) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == SUCCESS)
-    {
-      if (cp_opc_expr (& str, 5, 3) == FAIL)
-       {
-         if (!inst.error)
-           inst.error = BAD_ARGS;
-         return;
-       }
-    }
-
-  if (flags)
-    inst.error = BAD_COND;
-
-  end_of_line (str);
-}
-
-/* THUMB V5 breakpoint instruction (argument parse)
-       BKPT <immed_8>.  */
-
-static void
-do_t_bkpt (str)
-     char * str;
-{
-  expressionS expr;
-  unsigned long number;
-
-  skip_whitespace (str);
-
-  /* Allow optional leading '#'.  */
-  if (is_immediate_prefix (*str))
-    str ++;
-
-  memset (& expr, '\0', sizeof (expr));
-  if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
-    {
-      inst.error = _("bad or missing expression");
-      return;
-    }
-
-  number = expr.X_add_number;
-
-  /* Check it fits an 8 bit unsigned.  */
-  if (number != (number & 0xff))
-    {
-      inst.error = _("immediate value out of range");
-      return;
-    }
-
-  inst.instruction |= number;
-
-  end_of_line (str);
-}
-
-/* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
-   Expects inst.instruction is set for BLX(1).
-   Note: this is cloned from do_branch, and the reloc changed to be a
-       new one that can cope with setting one extra bit (the H bit).  */
-
-static void
-do_branch25 (str, flags)
-     char *        str;
-     unsigned long flags ATTRIBUTE_UNUSED;
-{
-  if (my_get_expression (& inst.reloc.exp, & str))
-    return;
-
-#ifdef OBJ_ELF
-  {
-    char * save_in;
-
-    /* ScottB: February 5, 1998 */
-    /* Check to see of PLT32 reloc required for the instruction.  */
-
-    /* arm_parse_reloc() works on input_line_pointer.
-       We actually want to parse the operands to the branch instruction
-       passed in 'str'.  Save the input pointer and restore it later.  */
-    save_in = input_line_pointer;
-    input_line_pointer = str;
-
-    if (inst.reloc.exp.X_op == O_symbol
-       && *str == '('
-       && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
-      {
-       inst.reloc.type   = BFD_RELOC_ARM_PLT32;
-       inst.reloc.pc_rel = 0;
-       /* Modify str to point to after parsed operands, otherwise
-          end_of_line() will complain about the (PLT) left in str.  */
-       str = input_line_pointer;
-      }
-    else
-      {
-       inst.reloc.type   = BFD_RELOC_ARM_PCREL_BLX;
-       inst.reloc.pc_rel = 1;
-      }
-
-    input_line_pointer = save_in;
-  }
-#else
-  inst.reloc.type   = BFD_RELOC_ARM_PCREL_BLX;
-  inst.reloc.pc_rel = 1;
-#endif /* OBJ_ELF */
-
-  end_of_line (str);
-}
-
-/* ARM V5 branch-link-exchange instruction (argument parse)
-     BLX <target_addr>         ie BLX(1)
-     BLX{<condition>} <Rm>     ie BLX(2)
-   Unfortunately, there are two different opcodes for this mnemonic.
-   So, the insns[].value is not used, and the code here zaps values
-       into inst.instruction.
-   Also, the <target_addr> can be 25 bits, hence has its own reloc.  */
-
-static void
-do_blx (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  char * mystr = str;
-  int rm;
-
-  if (flags)
-    {
-      as_bad (BAD_FLAGS);
-      return;
-    }
-
-  skip_whitespace (mystr);
-  rm = reg_required_here (& mystr, 0);
-
-  /* The above may set inst.error.  Ignore his opinion.  */
-  inst.error = 0;
-
-  if (rm != FAIL)
-    {
-      /* Arg is a register.
-        Use the condition code our caller put in inst.instruction.
-        Pass ourselves off as a BX with a funny opcode.  */
-      inst.instruction |= 0x012fff30;
-      do_bx (str, flags);
-    }
-  else
-    {
-      /* This must be is BLX <target address>, no condition allowed.  */
-      if (inst.instruction != COND_ALWAYS)
-       {
-         inst.error = BAD_COND;
-         return;
-       }
-
-      inst.instruction = 0xfafffffe;
-
-      /* Process like a B/BL, but with a different reloc.
-        Note that B/BL expecte fffffe, not 0, offset in the opcode table.  */
-      do_branch25 (str, flags);
-    }
-}
-
-/* ARM V5 Thumb BLX (argument parse)
-       BLX <target_addr>       which is BLX(1)
-       BLX <Rm>                which is BLX(2)
-   Unfortunately, there are two different opcodes for this mnemonic.
-   So, the tinsns[].value is not used, and the code here zaps values
-       into inst.instruction.  */
-
-static void
-do_t_blx (str)
-     char * str;
-{
-  char * mystr = str;
-  int rm;
-
-  skip_whitespace (mystr);
-  inst.instruction = 0x4780;
-
-  /* Note that this call is to the ARM register recognizer.  BLX(2)
-     uses the ARM register space, not the Thumb one, so a call to
-     thumb_reg() would be wrong.  */
-  rm = reg_required_here (& mystr, 3);
-  inst.error = 0;
-
-  if (rm != FAIL)
-    {
-      /* It's BLX(2).  The .instruction was zapped with rm & is final.  */
-      inst.size = 2;
-    }
-  else
-    {
-      /* No ARM register.  This must be BLX(1).  Change the .instruction.  */
-      inst.instruction = 0xf7ffeffe;
-      inst.size = 4;
-
-      if (my_get_expression (& inst.reloc.exp, & mystr))
-       return;
-
-      inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BLX;
-      inst.reloc.pc_rel = 1;
-    }
-
-  end_of_line (mystr);
-}
-
-/* ARM V5 breakpoint instruction (argument parse)
-     BKPT <16 bit unsigned immediate>
-     Instruction is not conditional.
-       The bit pattern given in insns[] has the COND_ALWAYS condition,
-       and it is an error if the caller tried to override that.
-     Note "flags" is nonzero if a flag was supplied (which is an error).  */
-
-static void
-do_bkpt (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  expressionS expr;
-  unsigned long number;
-
-  skip_whitespace (str);
-
-  /* Allow optional leading '#'.  */
-  if (is_immediate_prefix (* str))
-    str++;
-
-  memset (& expr, '\0', sizeof (expr));
-
-  if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
-    {
-      inst.error = _("bad or missing expression");
-      return;
-    }
-
-  number = expr.X_add_number;
-
-  /* Check it fits a 16 bit unsigned.  */
-  if (number != (number & 0xffff))
-    {
-      inst.error = _("immediate value out of range");
-      return;
-    }
-
-  /* Top 12 of 16 bits to bits 19:8.  */
-  inst.instruction |= (number & 0xfff0) << 4;
-
-  /* Bottom 4 of 16 bits to bits 3:0.  */
-  inst.instruction |= number & 0xf;
-
-  end_of_line (str);
-
-  if (flags)
-    inst.error = BAD_FLAGS;
-}
-
-/* Xscale multiply-accumulate (argument parse)
-     MIAcc   acc0,Rm,Rs
-     MIAPHcc acc0,Rm,Rs
-     MIAxycc acc0,Rm,Rs.  */
-
-static void
-do_mia (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  int rs;
-  int rm;
-
-  if (flags)
-    as_bad (BAD_FLAGS);
-
-  else if (accum0_required_here (& str) == FAIL)
-    inst.error = ERR_NO_ACCUM;
-
-  else if (skip_past_comma (& str) == FAIL
-          || (rm = reg_required_here (& str, 0)) == FAIL)
-    inst.error = BAD_ARGS;
-
-  else if (skip_past_comma (& str) == FAIL
-          || (rs = reg_required_here (& str, 12)) == FAIL)
-    inst.error = BAD_ARGS;
-
-  /* inst.instruction has now been zapped with both rm and rs.  */
-  else if (rm == REG_PC || rs == REG_PC)
-    inst.error = BAD_PC;       /* Undefined result if rm or rs is R15.  */
-
-  else
-    end_of_line (str);
-}
-
-/* Xscale move-accumulator-register (argument parse)
-
-     MARcc   acc0,RdLo,RdHi.  */
-
-static void
-do_mar (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  int rdlo, rdhi;
-
-  if (flags)
-    as_bad (BAD_FLAGS);
-
-  else if (accum0_required_here (& str) == FAIL)
-    inst.error = ERR_NO_ACCUM;
-
-  else if (skip_past_comma (& str) == FAIL
-          || (rdlo = reg_required_here (& str, 12)) == FAIL)
-    inst.error = BAD_ARGS;
-
-  else if (skip_past_comma (& str) == FAIL
-          || (rdhi = reg_required_here (& str, 16)) == FAIL)
-    inst.error = BAD_ARGS;
-
-  /* inst.instruction has now been zapped with both rdlo and rdhi.  */
-  else if (rdlo == REG_PC || rdhi == REG_PC)
-    inst.error = BAD_PC;       /* Undefined result if rdlo or rdhi is R15.  */
-
-  else
-    end_of_line (str);
-}
-
-/* Xscale move-register-accumulator (argument parse)
-
-     MRAcc   RdLo,RdHi,acc0.  */
-
-static void
-do_mra (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  int rdlo;
-  int rdhi;
-
-  if (flags)
-    {
-      as_bad (BAD_FLAGS);
-      return;
-    }
-
-  skip_whitespace (str);
-
-  if ((rdlo = reg_required_here (& str, 12)) == FAIL)
-    inst.error = BAD_ARGS;
-
-  else if (skip_past_comma (& str) == FAIL
-          || (rdhi = reg_required_here (& str, 16)) == FAIL)
-    inst.error = BAD_ARGS;
-
-  else if  (skip_past_comma (& str) == FAIL
-           || accum0_required_here (& str) == FAIL)
-    inst.error = ERR_NO_ACCUM;
-
-  /* inst.instruction has now been zapped with both rdlo and rdhi.  */
-  else if (rdlo == rdhi)
-    inst.error = BAD_ARGS;     /* Undefined result if 2 writes to same reg.  */
-
-  else if (rdlo == REG_PC || rdhi == REG_PC)
-    inst.error = BAD_PC;       /* Undefined result if rdlo or rdhi is R15.  */
-  else
-    end_of_line (str);
-}
-
-/* Xscale: Preload-Cache
-
-    PLD <addr_mode>
-
-  Syntactically, like LDR with B=1, W=0, L=1.  */
-
-static void
-do_pld (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  int rd;
-
-  if (flags)
-    {
-      as_bad (BAD_FLAGS);
-      return;
-    }
-
-  skip_whitespace (str);
-
-  if (* str != '[')
-    {
-      inst.error = _("'[' expected after PLD mnemonic");
-      return;
-    }
-
-  ++ str;
-  skip_whitespace (str);
-
-  if ((rd = reg_required_here (& str, 16)) == FAIL)
-    return;
-
-  skip_whitespace (str);
-
-  if (* str == ']')
-    {
-      /* [Rn], ... ?  */
-      ++ str;
-      skip_whitespace (str);
-
-      if (skip_past_comma (& str) == SUCCESS)
-       {
-         if (ldst_extend (& str, 0) == FAIL)
-           return;
-       }
-      else if (* str == '!') /* [Rn]! */
-       {
-         inst.error = _("writeback used in preload instruction");
-         ++ str;
-       }
-      else /* [Rn] */
-       inst.instruction |= INDEX_UP | PRE_INDEX;
-    }
-  else /* [Rn, ...] */
-    {
-      if (skip_past_comma (& str) == FAIL)
-       {
-         inst.error = _("pre-indexed expression expected");
-         return;
-       }
-
-      if (ldst_extend (& str, 0) == FAIL)
-       return;
-
-      skip_whitespace (str);
-
-      if (* str != ']')
-       {
-         inst.error = _("missing ]");
-         return;
-       }
-
-      ++ str;
-      skip_whitespace (str);
-
-      if (* str == '!') /* [Rn]! */
-       {
-         inst.error = _("writeback used in preload instruction");
-         ++ str;
-       }
-
-      inst.instruction |= PRE_INDEX;
-    }
-
-  end_of_line (str);
-}
-
-/* Xscale load-consecutive (argument parse)
-   Mode is like LDRH.
-
-     LDRccD R, mode
-     STRccD R, mode.  */
-
-static void
-do_ldrd (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  int rd;
-  int rn;
-
-  if (flags != DOUBLE_LOAD_FLAG)
-    {
-      /* Change instruction pattern to normal ldr/str.  */
-      if (inst.instruction & 0x20)
-       inst.instruction = (inst.instruction & COND_MASK) | 0x04000000; /* str */
-      else
-       inst.instruction = (inst.instruction & COND_MASK) | 0x04100000; /* ldr */
-
-      /* Perform a normal load/store instruction parse.  */
-      do_ldst (str, flags);
-
-      return;
-    }
-
-  if ((cpu_variant & ARM_EXT_XSCALE) != ARM_EXT_XSCALE)
-    {
-      static char buff[128];
-
-      --str;
-      while (isspace (*str))
-       --str;
-      str -= 4;
-
-      /* Deny all knowledge.  */
-      sprintf (buff, _("bad instruction '%.100s'"), str);
-      inst.error = buff;
-      return;
-    }
-
-  skip_whitespace (str);
-
-  if ((rd = reg_required_here (& str, 12)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL
-      || (rn = ld_mode_required_here (& str)) == FAIL)
-    {
-      if (!inst.error)
-        inst.error = BAD_ARGS;
-      return;
-    }
-
-  /* inst.instruction has now been zapped with Rd and the addressing mode.  */
-  if (rd & 1)          /* Unpredictable result if Rd is odd.  */
-    {
-      inst.error = _("Destination register must be even");
-      return;
-    }
-
-  if (rd == REG_LR || rd == 12)
-    {
-      inst.error = _("r12 or r14 not allowed here");
-      return;
-    }
-
-  if (((rd == rn) || (rd + 1 == rn))
-      &&
-      ((inst.instruction & WRITE_BACK)
-       || (!(inst.instruction & PRE_INDEX))))
-    as_warn (_("pre/post-indexing used when modified address register is destination"));
-
-  end_of_line (str);
-}
-
-/* Returns the index into fp_values of a floating point number,
-   or -1 if not in the table.  */
-
-static int
-my_get_float_expression (str)
-     char ** str;
-{
-  LITTLENUM_TYPE words[MAX_LITTLENUMS];
-  char *         save_in;
-  expressionS    exp;
-  int            i;
-  int            j;
-
-  memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
-
-  /* Look for a raw floating point number.  */
-  if ((save_in = atof_ieee (*str, 'x', words)) != NULL
-      && is_end_of_line[(unsigned char) *save_in])
-    {
-      for (i = 0; i < NUM_FLOAT_VALS; i++)
-       {
-         for (j = 0; j < MAX_LITTLENUMS; j++)
-           {
-             if (words[j] != fp_values[i][j])
-               break;
-           }
-
-         if (j == MAX_LITTLENUMS)
-           {
-             *str = save_in;
-             return i;
-           }
-       }
-    }
-
-  /* Try and parse a more complex expression, this will probably fail
-     unless the code uses a floating point prefix (eg "0f").  */
-  save_in = input_line_pointer;
-  input_line_pointer = *str;
-  if (expression (&exp) == absolute_section
-      && exp.X_op == O_big
-      && exp.X_add_number < 0)
-    {
-      /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
-        Ditto for 15.  */
-      if (gen_to_words (words, 5, (long) 15) == 0)
-       {
-         for (i = 0; i < NUM_FLOAT_VALS; i++)
-           {
-             for (j = 0; j < MAX_LITTLENUMS; j++)
-               {
-                 if (words[j] != fp_values[i][j])
-                   break;
-               }
-
-             if (j == MAX_LITTLENUMS)
-               {
-                 *str = input_line_pointer;
-                 input_line_pointer = save_in;
-                 return i;
-               }
-           }
-       }
-    }
-
-  *str = input_line_pointer;
-  input_line_pointer = save_in;
-  return -1;
-}
-
-/* Return true if anything in the expression is a bignum.  */
-
-static int
-walk_no_bignums (sp)
-     symbolS * sp;
-{
-  if (symbol_get_value_expression (sp)->X_op == O_big)
-    return 1;
-
-  if (symbol_get_value_expression (sp)->X_add_symbol)
-    {
-      return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
-             || (symbol_get_value_expression (sp)->X_op_symbol
-                 && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
-    }
-
-  return 0;
-}
-
-static int
-my_get_expression (ep, str)
-     expressionS * ep;
-     char ** str;
-{
-  char * save_in;
-  segT   seg;
-
-  save_in = input_line_pointer;
-  input_line_pointer = *str;
-  seg = expression (ep);
-
-#ifdef OBJ_AOUT
-  if (seg != absolute_section
-      && seg != text_section
-      && seg != data_section
-      && seg != bss_section
-      && seg != undefined_section)
-    {
-      inst.error = _("bad_segment");
-      *str = input_line_pointer;
-      input_line_pointer = save_in;
-      return 1;
-    }
-#endif
-
-  /* Get rid of any bignums now, so that we don't generate an error for which
-     we can't establish a line number later on.  Big numbers are never valid
-     in instructions, which is where this routine is always called.  */
-  if (ep->X_op == O_big
-      || (ep->X_add_symbol
-         && (walk_no_bignums (ep->X_add_symbol)
-             || (ep->X_op_symbol
-                 && walk_no_bignums (ep->X_op_symbol)))))
-    {
-      inst.error = _("Invalid constant");
-      *str = input_line_pointer;
-      input_line_pointer = save_in;
-      return 1;
-    }
-
-  *str = input_line_pointer;
-  input_line_pointer = save_in;
-  return 0;
-}
-
-/* UNRESTRICT should be one if <shift> <register> is permitted for this
-   instruction.  */
-
-static int
-decode_shift (str, unrestrict)
-     char ** str;
-     int     unrestrict;
-{
-  const struct asm_shift_name * shift;
-  char * p;
-  char   c;
-
-  skip_whitespace (* str);
-
-  for (p = * str; isalpha (* p); p ++)
-    ;
-
-  if (p == * str)
-    {
-      inst.error = _("Shift expression expected");
-      return FAIL;
-    }
-
-  c = * p;
-  * p = '\0';
-  shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
-  * p = c;
-
-  if (shift == NULL)
-    {
-      inst.error = _("Shift expression expected");
-      return FAIL;
-    }
-
-  assert (shift->properties->index == shift_properties[shift->properties->index].index);
-
-  if (shift->properties->index == SHIFT_RRX)
-    {
-      * str = p;
-      inst.instruction |= shift->properties->bit_field;
-      return SUCCESS;
-    }
-
-  skip_whitespace (p);
-
-  if (unrestrict && reg_required_here (& p, 8) != FAIL)
-    {
-      inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
-      * str = p;
-      return SUCCESS;
-    }
-  else if (! is_immediate_prefix (* p))
-    {
-      inst.error = (unrestrict
-                   ? _("shift requires register or #expression")
-                   : _("shift requires #expression"));
-      * str = p;
-      return FAIL;
-    }
-
-  inst.error = NULL;
-  p ++;
-
-  if (my_get_expression (& inst.reloc.exp, & p))
-    return FAIL;
-
-  /* Validate some simple #expressions.  */
-  if (inst.reloc.exp.X_op == O_constant)
-    {
-      unsigned num = inst.reloc.exp.X_add_number;
-
-      /* Reject operations greater than 32.  */
-      if (num > 32
-         /* Reject a shift of 0 unless the mode allows it.  */
-         || (num == 0 && shift->properties->allows_0 == 0)
-         /* Reject a shift of 32 unless the mode allows it.  */
-         || (num == 32 && shift->properties->allows_32 == 0)
-         )
-       {
-         /* As a special case we allow a shift of zero for
-            modes that do not support it to be recoded as an
-            logical shift left of zero (ie nothing).  We warn
-            about this though.  */
-         if (num == 0)
-           {
-             as_warn (_("Shift of 0 ignored."));
-             shift = & shift_names[0];
-             assert (shift->properties->index == SHIFT_LSL);
-           }
-         else
-           {
-             inst.error = _("Invalid immediate shift");
-             return FAIL;
-           }
-       }
-
-      /* Shifts of 32 are encoded as 0, for those shifts that
-        support it.  */
-      if (num == 32)
-       num = 0;
-
-      inst.instruction |= (num << 7) | shift->properties->bit_field;
-    }
-  else
-    {
-      inst.reloc.type   = BFD_RELOC_ARM_SHIFT_IMM;
-      inst.reloc.pc_rel = 0;
-      inst.instruction |= shift->properties->bit_field;
-    }
-
-  * str = p;
-  return SUCCESS;
-}
-
-/* Do those data_ops which can take a negative immediate constant
-   by altering the instuction.  A bit of a hack really.
-        MOV <-> MVN
-        AND <-> BIC
-        ADC <-> SBC
-        by inverting the second operand, and
-        ADD <-> SUB
-        CMP <-> CMN
-        by negating the second operand.  */
-
-static int
-negate_data_op (instruction, value)
-     unsigned long * instruction;
-     unsigned long   value;
-{
-  int op, new_inst;
-  unsigned long negated, inverted;
-
-  negated = validate_immediate (-value);
-  inverted = validate_immediate (~value);
-
-  op = (*instruction >> DATA_OP_SHIFT) & 0xf;
-  switch (op)
-    {
-      /* First negates.  */
-    case OPCODE_SUB:             /* ADD <-> SUB  */
-      new_inst = OPCODE_ADD;
-      value = negated;
-      break;
-
-    case OPCODE_ADD:
-      new_inst = OPCODE_SUB;
-      value = negated;
-      break;
-
-    case OPCODE_CMP:             /* CMP <-> CMN  */
-      new_inst = OPCODE_CMN;
-      value = negated;
-      break;
-
-    case OPCODE_CMN:
-      new_inst = OPCODE_CMP;
-      value = negated;
-      break;
-
-      /* Now Inverted ops.  */
-    case OPCODE_MOV:             /* MOV <-> MVN  */
-      new_inst = OPCODE_MVN;
-      value = inverted;
-      break;
-
-    case OPCODE_MVN:
-      new_inst = OPCODE_MOV;
-      value = inverted;
-      break;
-
-    case OPCODE_AND:             /* AND <-> BIC  */
-      new_inst = OPCODE_BIC;
-      value = inverted;
-      break;
-
-    case OPCODE_BIC:
-      new_inst = OPCODE_AND;
-      value = inverted;
-      break;
-
-    case OPCODE_ADC:              /* ADC <-> SBC  */
-      new_inst = OPCODE_SBC;
-      value = inverted;
-      break;
-
-    case OPCODE_SBC:
-      new_inst = OPCODE_ADC;
-      value = inverted;
-      break;
-
-      /* We cannot do anything.  */
-    default:
-      return FAIL;
-    }
-
-  if (value == (unsigned) FAIL)
-    return FAIL;
-
-  *instruction &= OPCODE_MASK;
-  *instruction |= new_inst << DATA_OP_SHIFT;
-  return value;
-}
-
-static int
-data_op2 (str)
-     char ** str;
-{
-  int value;
-  expressionS expr;
-
-  skip_whitespace (* str);
-
-  if (reg_required_here (str, 0) != FAIL)
-    {
-      if (skip_past_comma (str) == SUCCESS)
-       /* Shift operation on register.  */
-       return decode_shift (str, NO_SHIFT_RESTRICT);
-
-      return SUCCESS;
-    }
-  else
-    {
-      /* Immediate expression.  */
-      if (is_immediate_prefix (**str))
-       {
-         (*str)++;
-         inst.error = NULL;
-
-         if (my_get_expression (&inst.reloc.exp, str))
-           return FAIL;
-
-         if (inst.reloc.exp.X_add_symbol)
-           {
-             inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
-             inst.reloc.pc_rel = 0;
-           }
-         else
-           {
-             if (skip_past_comma (str) == SUCCESS)
-               {
-                 /* #x, y -- ie explicit rotation by Y.  */
-                 if (my_get_expression (&expr, str))
-                   return FAIL;
-
-                 if (expr.X_op != O_constant)
-                   {
-                     inst.error = _("Constant expression expected");
-                     return FAIL;
-                   }
-
-                 /* Rotate must be a multiple of 2.  */
-                 if (((unsigned) expr.X_add_number) > 30
-                     || (expr.X_add_number & 1) != 0
-                     || ((unsigned) inst.reloc.exp.X_add_number) > 255)
-                   {
-                     inst.error = _("Invalid constant");
-                     return FAIL;
-                   }
-                 inst.instruction |= INST_IMMEDIATE;
-                 inst.instruction |= inst.reloc.exp.X_add_number;
-                 inst.instruction |= expr.X_add_number << 7;
-                 return SUCCESS;
-               }
-
-             /* Implicit rotation, select a suitable one.  */
-             value = validate_immediate (inst.reloc.exp.X_add_number);
-
-             if (value == FAIL)
-               {
-                 /* Can't be done.  Perhaps the code reads something like
-                    "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK.  */
-                 if ((value = negate_data_op (&inst.instruction,
-                                              inst.reloc.exp.X_add_number))
-                     == FAIL)
-                   {
-                     inst.error = _("Invalid constant");
-                     return FAIL;
-                   }
-               }
-
-             inst.instruction |= value;
-           }
-
-         inst.instruction |= INST_IMMEDIATE;
-         return SUCCESS;
-       }
-
-      (*str)++;
-      inst.error = _("Register or shift expression expected");
-      return FAIL;
-    }
-}
-
-static int
-fp_op2 (str)
-     char ** str;
-{
-  skip_whitespace (* str);
-
-  if (fp_reg_required_here (str, 0) != FAIL)
-    return SUCCESS;
-  else
-    {
-      /* Immediate expression.  */
-      if (*((*str)++) == '#')
-       {
-         int i;
-
-         inst.error = NULL;
-
-         skip_whitespace (* str);
-
-         /* First try and match exact strings, this is to guarantee
-            that some formats will work even for cross assembly.  */
-
-         for (i = 0; fp_const[i]; i++)
-           {
-             if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
-               {
-                 char *start = *str;
-
-                 *str += strlen (fp_const[i]);
-                 if (is_end_of_line[(unsigned char) **str])
-                   {
-                     inst.instruction |= i + 8;
-                     return SUCCESS;
-                   }
-                 *str = start;
-               }
-           }
-
-         /* Just because we didn't get a match doesn't mean that the
-            constant isn't valid, just that it is in a format that we
-            don't automatically recognize.  Try parsing it with
-            the standard expression routines.  */
-         if ((i = my_get_float_expression (str)) >= 0)
-           {
-             inst.instruction |= i + 8;
-             return SUCCESS;
-           }
-
-         inst.error = _("Invalid floating point immediate expression");
-         return FAIL;
-       }
-      inst.error =
-       _("Floating point register or immediate expression expected");
-      return FAIL;
-    }
-}
-
-static void
-do_arit (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  if (reg_required_here (&str, 12) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 16) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || data_op2 (&str) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-static void
-do_adr (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  /* This is a pseudo-op of the form "adr rd, label" to be converted
-     into a relative address of the form "add rd, pc, #label-.-8".  */
-  skip_whitespace (str);
-
-  if (reg_required_here (&str, 12) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || my_get_expression (&inst.reloc.exp, &str))
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  /* Frag hacking will turn this into a sub instruction if the offset turns
-     out to be negative.  */
-  inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
-  inst.reloc.exp.X_add_number -= 8; /* PC relative adjust.  */
-  inst.reloc.pc_rel = 1;
-  inst.instruction |= flags;
-
-  end_of_line (str);
-}
-
-static void
-do_adrl (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  /* This is a pseudo-op of the form "adrl rd, label" to be converted
-     into a relative address of the form:
-       add rd, pc, #low(label-.-8)"
-       add rd, rd, #high(label-.-8)"  */
-
-  skip_whitespace (str);
-
-  if (reg_required_here (& str, 12) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || my_get_expression (& inst.reloc.exp, & str))
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  end_of_line (str);
-
-  /* Frag hacking will turn this into a sub instruction if the offset turns
-     out to be negative.  */
-  inst.reloc.type              = BFD_RELOC_ARM_ADRL_IMMEDIATE;
-  inst.reloc.exp.X_add_number -= 8; /* PC relative adjust  */
-  inst.reloc.pc_rel            = 1;
-  inst.instruction            |= flags;
-  inst.size                    = INSN_SIZE * 2;
-
-  return;
-}
-
-static void
-do_cmp (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  if (reg_required_here (&str, 16) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || data_op2 (&str) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  inst.instruction |= flags;
-  if ((flags & 0x0000f000) == 0)
-    inst.instruction |= CONDS_BIT;
-
-  end_of_line (str);
-  return;
-}
-
-static void
-do_mov (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  if (reg_required_here (&str, 12) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || data_op2 (&str) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-static int
-ldst_extend (str, hwse)
-     char ** str;
-     int     hwse;
-{
-  int add = INDEX_UP;
-
-  switch (**str)
-    {
-    case '#':
-    case '$':
-      (*str)++;
-      if (my_get_expression (& inst.reloc.exp, str))
-       return FAIL;
-
-      if (inst.reloc.exp.X_op == O_constant)
-       {
-         int value = inst.reloc.exp.X_add_number;
-
-         if ((hwse && (value < -255 || value > 255))
-             || (value < -4095 || value > 4095))
-           {
-             inst.error = _("address offset too large");
-             return FAIL;
-           }
-
-         if (value < 0)
-           {
-             value = -value;
-             add = 0;
-           }
-
-         /* Halfword and signextension instructions have the
-             immediate value split across bits 11..8 and bits 3..0.  */
-         if (hwse)
-           inst.instruction |= (add | HWOFFSET_IMM
-                                | ((value >> 4) << 8) | (value & 0xF));
-         else
-           inst.instruction |= add | value;
-       }
-      else
-       {
-         if (hwse)
-           {
-             inst.instruction |= HWOFFSET_IMM;
-             inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
-           }
-         else
-           inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
-         inst.reloc.pc_rel = 0;
-       }
-      return SUCCESS;
-
-    case '-':
-      add = 0;
-      /* Fall through.  */
-
-    case '+':
-      (*str)++;
-      /* Fall through.  */
-
-    default:
-      if (reg_required_here (str, 0) == FAIL)
-       return FAIL;
-
-      if (hwse)
-       inst.instruction |= add;
-      else
-       {
-         inst.instruction |= add | OFFSET_REG;
-         if (skip_past_comma (str) == SUCCESS)
-           return decode_shift (str, SHIFT_RESTRICT);
-       }
-
-      return SUCCESS;
-    }
-}
-
-static void
-do_ldst (str, flags)
-     char *        str;
-     unsigned long flags;
-{
-  int halfword = 0;
-  int pre_inc = 0;
-  int conflict_reg;
-  int value;
-
-  /* This is not ideal, but it is the simplest way of dealing with the
-     ARM7T halfword instructions (since they use a different
-     encoding, but the same mnemonic):  */
-  halfword = (flags & 0x80000000) != 0;
-  if (halfword)
-    {
-      /* This is actually a load/store of a halfword, or a
-         signed-extension load.  */
-      if ((cpu_variant & ARM_EXT_HALFWORD) == 0)
-       {
-         inst.error
-           = _("Processor does not support halfwords or signed bytes");
-         return;
-       }
-
-      inst.instruction = ((inst.instruction & COND_MASK)
-                         | (flags & ~COND_MASK));
-
-      flags = 0;
-    }
-
-  skip_whitespace (str);
-
-  if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (& str) == FAIL)
-    {
-      inst.error = _("Address expected");
-      return;
-    }
-
-  if (*str == '[')
-    {
-      int reg;
-
-      str++;
-
-      skip_whitespace (str);
-
-      if ((reg = reg_required_here (&str, 16)) == FAIL)
-       return;
-
-      /* Conflicts can occur on stores as well as loads.  */
-      conflict_reg = (conflict_reg == reg);
-
-      skip_whitespace (str);
-
-      if (*str == ']')
-       {
-         str ++;
-
-         if (skip_past_comma (&str) == SUCCESS)
-           {
-             /* [Rn],... (post inc)  */
-             if (ldst_extend (&str, halfword) == FAIL)
-               return;
-             if (conflict_reg)
-               {
-                 if (flags & TRANS_BIT)
-                   as_warn (_("Rn and Rd must be different in %s"),
-                            ((inst.instruction & LOAD_BIT)
-                             ? "LDRT" : "STRT"));
-                 else
-                   as_warn (_("%s register same as write-back base"),
-                            ((inst.instruction & LOAD_BIT)
-                             ? _("destination") : _("source")));
-               }
-           }
-         else
-           {
-             /* [Rn]  */
-             if (halfword)
-               inst.instruction |= HWOFFSET_IMM;
-
-             skip_whitespace (str);
-
-             if (*str == '!')
-               {
-                 if (conflict_reg)
-                   as_warn (_("%s register same as write-back base"),
-                            ((inst.instruction & LOAD_BIT)
-                             ? _("destination") : _("source")));
-                 str++;
-                 inst.instruction |= WRITE_BACK;
-               }
-
-             flags |= INDEX_UP;
-             if (flags & TRANS_BIT)
-               {
-                 if (conflict_reg)
-                   as_warn (_("Rn and Rd must be different in %s"),
-                            ((inst.instruction & LOAD_BIT)
-                             ? "LDRT" : "STRT"));
-               }
-               else
-                 pre_inc = 1;
-           }
-       }
-      else
-       {
-         /* [Rn,...]  */
-         if (skip_past_comma (&str) == FAIL)
-           {
-             inst.error = _("pre-indexed expression expected");
-             return;
-           }
-
-         pre_inc = 1;
-         if (ldst_extend (&str, halfword) == FAIL)
-           return;
-
-         skip_whitespace (str);
-
-         if (*str++ != ']')
-           {
-             inst.error = _("missing ]");
-             return;
-           }
-
-         skip_whitespace (str);
-
-         if (*str == '!')
-           {
-             if (conflict_reg)
-               as_warn (_("%s register same as write-back base"),
-                        ((inst.instruction & LOAD_BIT)
-                         ? _("destination") : _("source")));
-             str++;
-             inst.instruction |= WRITE_BACK;
-           }
-       }
-    }
-  else if (*str == '=')
-    {
-      /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
-      str++;
-
-      skip_whitespace (str);
-
-      if (my_get_expression (&inst.reloc.exp, &str))
-       return;
-
-      if (inst.reloc.exp.X_op != O_constant
-         && inst.reloc.exp.X_op != O_symbol)
-       {
-         inst.error = _("Constant expression expected");
-         return;
-       }
-
-      if (inst.reloc.exp.X_op == O_constant
-         && (value = validate_immediate (inst.reloc.exp.X_add_number)) != FAIL)
-       {
-         /* This can be done with a mov instruction.  */
-         inst.instruction &= LITERAL_MASK;
-         inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
-         inst.instruction |= (flags & COND_MASK) | (value & 0xfff);
-         end_of_line (str);
-         return;
-       }
-      else
-       {
-         /* Insert into literal pool.  */
-         if (add_to_lit_pool () == FAIL)
-           {
-             if (!inst.error)
-               inst.error = _("literal pool insertion failed");
-             return;
-           }
-
-         /* Change the instruction exp to point to the pool.  */
-         if (halfword)
-           {
-             inst.instruction |= HWOFFSET_IMM;
-             inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
-           }
-         else
-           inst.reloc.type = BFD_RELOC_ARM_LITERAL;
-         inst.reloc.pc_rel = 1;
-         inst.instruction |= (REG_PC << 16);
-         pre_inc = 1;
-       }
-    }
-  else
-    {
-      if (my_get_expression (&inst.reloc.exp, &str))
-       return;
-
-      if (halfword)
-       {
-         inst.instruction |= HWOFFSET_IMM;
-         inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
-       }
-      else
-       inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
-#ifndef TE_WINCE
-      /* PC rel adjust.  */
-      inst.reloc.exp.X_add_number -= 8;
-#endif
-      inst.reloc.pc_rel = 1;
-      inst.instruction |= (REG_PC << 16);
-      pre_inc = 1;
-    }
-
-  if (pre_inc && (flags & TRANS_BIT))
-    inst.error = _("Pre-increment instruction with translate");
-
-  inst.instruction |= flags | (pre_inc ? PRE_INDEX : 0);
-  end_of_line (str);
-  return;
-}
-
-static long
-reg_list (strp)
-     char ** strp;
-{
-  char * str = * strp;
-  long   range = 0;
-  int    another_range;
-
-  /* We come back here if we get ranges concatenated by '+' or '|'.  */
-  do
-    {
-      another_range = 0;
-
-      if (*str == '{')
-       {
-         int in_range = 0;
-         int cur_reg = -1;
-
-         str++;
-         do
-           {
-             int reg;
-
-             skip_whitespace (str);
-
-             if ((reg = reg_required_here (& str, -1)) == FAIL)
-               return FAIL;
-
-             if (in_range)
-               {
-                 int i;
-
-                 if (reg <= cur_reg)
-                   {
-                     inst.error = _("Bad range in register list");
-                     return FAIL;
-                   }
-
-                 for (i = cur_reg + 1; i < reg; i++)
-                   {
-                     if (range & (1 << i))
-                       as_tsktsk
-                         (_("Warning: Duplicated register (r%d) in register list"),
-                          i);
-                     else
-                       range |= 1 << i;
-                   }
-                 in_range = 0;
-               }
-
-             if (range & (1 << reg))
-               as_tsktsk (_("Warning: Duplicated register (r%d) in register list"),
-                          reg);
-             else if (reg <= cur_reg)
-               as_tsktsk (_("Warning: Register range not in ascending order"));
-
-             range |= 1 << reg;
-             cur_reg = reg;
-           }
-         while (skip_past_comma (&str) != FAIL
-                || (in_range = 1, *str++ == '-'));
-         str--;
-         skip_whitespace (str);
-
-         if (*str++ != '}')
-           {
-             inst.error = _("Missing `}'");
-             return FAIL;
-           }
-       }
-      else
-       {
-         expressionS expr;
-
-         if (my_get_expression (&expr, &str))
-           return FAIL;
-
-         if (expr.X_op == O_constant)
-           {
-             if (expr.X_add_number
-                 != (expr.X_add_number & 0x0000ffff))
-               {
-                 inst.error = _("invalid register mask");
-                 return FAIL;
-               }
-
-             if ((range & expr.X_add_number) != 0)
-               {
-                 int regno = range & expr.X_add_number;
-
-                 regno &= -regno;
-                 regno = (1 << regno) - 1;
-                 as_tsktsk
-                   (_("Warning: Duplicated register (r%d) in register list"),
-                    regno);
-               }
-
-             range |= expr.X_add_number;
-           }
-         else
-           {
-             if (inst.reloc.type != 0)
-               {
-                 inst.error = _("expression too complex");
-                 return FAIL;
-               }
-
-             memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
-             inst.reloc.type = BFD_RELOC_ARM_MULTI;
-             inst.reloc.pc_rel = 0;
-           }
-       }
-
-      skip_whitespace (str);
-
-      if (*str == '|' || *str == '+')
-       {
-         str++;
-         another_range = 1;
-       }
-    }
-  while (another_range);
-
-  *strp = str;
-  return range;
-}
-
-static void
-do_ldmstm (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  int base_reg;
-  long range;
-
-  skip_whitespace (str);
-
-  if ((base_reg = reg_required_here (&str, 16)) == FAIL)
-    return;
-
-  if (base_reg == REG_PC)
-    {
-      inst.error = _("r15 not allowed as base register");
-      return;
-    }
-
-  skip_whitespace (str);
-
-  if (*str == '!')
-    {
-      flags |= WRITE_BACK;
-      str++;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || (range = reg_list (&str)) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (*str == '^')
-    {
-      str++;
-      flags |= LDM_TYPE_2_OR_3;
-    }
-
-  inst.instruction |= flags | range;
-  end_of_line (str);
-  return;
-}
-
-static void
-do_swi (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  /* Allow optional leading '#'.  */
-  if (is_immediate_prefix (*str))
-    str++;
-
-  if (my_get_expression (& inst.reloc.exp, & str))
-    return;
-
-  inst.reloc.type = BFD_RELOC_ARM_SWI;
-  inst.reloc.pc_rel = 0;
-  inst.instruction |= flags;
-
-  end_of_line (str);
-
-  return;
-}
-
-static void
-do_swap (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  int reg;
-
-  skip_whitespace (str);
-
-  if ((reg = reg_required_here (&str, 12)) == FAIL)
-    return;
-
-  if (reg == REG_PC)
-    {
-      inst.error = _("r15 not allowed in swap");
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || (reg = reg_required_here (&str, 0)) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (reg == REG_PC)
-    {
-      inst.error = _("r15 not allowed in swap");
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || *str++ != '[')
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  skip_whitespace (str);
-
-  if ((reg = reg_required_here (&str, 16)) == FAIL)
-    return;
-
-  if (reg == REG_PC)
-    {
-      inst.error = BAD_PC;
-      return;
-    }
-
-  skip_whitespace (str);
-
-  if (*str++ != ']')
-    {
-      inst.error = _("missing ]");
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-static void
-do_branch (str, flags)
-     char * str;
-     unsigned long flags ATTRIBUTE_UNUSED;
-{
-  if (my_get_expression (&inst.reloc.exp, &str))
-    return;
-
-#ifdef OBJ_ELF
-  {
-    char * save_in;
-
-    /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
-       required for the instruction.  */
-
-    /* arm_parse_reloc () works on input_line_pointer.
-       We actually want to parse the operands to the branch instruction
-       passed in 'str'.  Save the input pointer and restore it later.  */
-    save_in = input_line_pointer;
-    input_line_pointer = str;
-    if (inst.reloc.exp.X_op == O_symbol
-       && *str == '('
-       && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
-      {
-       inst.reloc.type   = BFD_RELOC_ARM_PLT32;
-       inst.reloc.pc_rel = 0;
-       /* Modify str to point to after parsed operands, otherwise
-          end_of_line() will complain about the (PLT) left in str.  */
-       str = input_line_pointer;
-      }
-    else
-      {
-       inst.reloc.type   = BFD_RELOC_ARM_PCREL_BRANCH;
-       inst.reloc.pc_rel = 1;
-      }
-    input_line_pointer = save_in;
-  }
-#else
-  inst.reloc.type   = BFD_RELOC_ARM_PCREL_BRANCH;
-  inst.reloc.pc_rel = 1;
-#endif /* OBJ_ELF  */
-
-  end_of_line (str);
-  return;
-}
-
-static void
-do_bx (str, flags)
-     char * str;
-     unsigned long flags ATTRIBUTE_UNUSED;
-{
-  int reg;
-
-  skip_whitespace (str);
-
-  if ((reg = reg_required_here (&str, 0)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  /* Note - it is not illegal to do a "bx pc".  Useless, but not illegal.  */
-  if (reg == REG_PC)
-    as_tsktsk (_("Use of r15 in bx in ARM mode is not really useful"));
-
-  end_of_line (str);
-}
-
-static void
-do_cdp (str, flags)
-     char * str;
-     unsigned long flags ATTRIBUTE_UNUSED;
-{
-  /* Co-processor data operation.
-     Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>}  */
-  skip_whitespace (str);
-
-  if (co_proc_number (&str) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || cp_opc_expr (&str, 20,4) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || cp_reg_required_here (&str, 12) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || cp_reg_required_here (&str, 16) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || cp_reg_required_here (&str, 0) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == SUCCESS)
-    {
-      if (cp_opc_expr (&str, 5, 3) == FAIL)
-       {
-         if (!inst.error)
-           inst.error = BAD_ARGS;
-         return;
-       }
-    }
-
-  end_of_line (str);
-  return;
-}
-
-static void
-do_lstc (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  /* Co-processor register load/store.
-     Format: <LDC|STC{cond}[L] CP#,CRd,<address>  */
-
-  skip_whitespace (str);
-
-  if (co_proc_number (&str) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || cp_reg_required_here (&str, 12) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || cp_address_required_here (&str) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-static void
-do_co_reg (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  /* Co-processor register transfer.
-     Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>}  */
-
-  skip_whitespace (str);
-
-  if (co_proc_number (&str) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || cp_opc_expr (&str, 21, 3) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 12) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || cp_reg_required_here (&str, 16) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || cp_reg_required_here (&str, 0) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == SUCCESS)
-    {
-      if (cp_opc_expr (&str, 5, 3) == FAIL)
-       {
-         if (!inst.error)
-           inst.error = BAD_ARGS;
-         return;
-       }
-    }
-  if (flags)
-    {
-      inst.error = BAD_COND;
-    }
-
-  end_of_line (str);
-  return;
-}
-
-static void
-do_fp_ctrl (str, flags)
-     char * str;
-     unsigned long flags ATTRIBUTE_UNUSED;
-{
-  /* FP control registers.
-     Format: <WFS|RFS|WFC|RFC>{cond} Rn  */
-
-  skip_whitespace (str);
-
-  if (reg_required_here (&str, 12) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  end_of_line (str);
-  return;
-}
-
-static void
-do_fp_ldst (str, flags)
-     char * str;
-     unsigned long flags ATTRIBUTE_UNUSED;
-{
-  skip_whitespace (str);
-
-  switch (inst.suffix)
-    {
-    case SUFF_S:
-      break;
-    case SUFF_D:
-      inst.instruction |= CP_T_X;
-      break;
-    case SUFF_E:
-      inst.instruction |= CP_T_Y;
-      break;
-    case SUFF_P:
-      inst.instruction |= CP_T_X | CP_T_Y;
-      break;
-    default:
-      abort ();
-    }
-
-  if (fp_reg_required_here (&str, 12) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || cp_address_required_here (&str) == FAIL)
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  end_of_line (str);
-}
-
-static void
-do_fp_ldmstm (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  int num_regs;
-
-  skip_whitespace (str);
-
-  if (fp_reg_required_here (&str, 12) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  /* Get Number of registers to transfer.  */
-  if (skip_past_comma (&str) == FAIL
-      || my_get_expression (&inst.reloc.exp, &str))
-    {
-      if (! inst.error)
-       inst.error = _("constant expression expected");
-      return;
-    }
-
-  if (inst.reloc.exp.X_op != O_constant)
-    {
-      inst.error = _("Constant value required for number of registers");
-      return;
-    }
-
-  num_regs = inst.reloc.exp.X_add_number;
-
-  if (num_regs < 1 || num_regs > 4)
-    {
-      inst.error = _("number of registers must be in the range [1:4]");
-      return;
-    }
-
-  switch (num_regs)
-    {
-    case 1:
-      inst.instruction |= CP_T_X;
-      break;
-    case 2:
-      inst.instruction |= CP_T_Y;
-      break;
-    case 3:
-      inst.instruction |= CP_T_Y | CP_T_X;
-      break;
-    case 4:
-      break;
-    default:
-      abort ();
-    }
-
-  if (flags)
-    {
-      int reg;
-      int write_back;
-      int offset;
-
-      /* The instruction specified "ea" or "fd", so we can only accept
-        [Rn]{!}.  The instruction does not really support stacking or
-        unstacking, so we have to emulate these by setting appropriate
-        bits and offsets.  */
-      if (skip_past_comma (&str) == FAIL
-         || *str != '[')
-       {
-         if (! inst.error)
-           inst.error = BAD_ARGS;
-         return;
-       }
-
-      str++;
-      skip_whitespace (str);
-
-      if ((reg = reg_required_here (&str, 16)) == FAIL)
-       return;
-
-      skip_whitespace (str);
-
-      if (*str != ']')
-       {
-         inst.error = BAD_ARGS;
-         return;
-       }
-
-      str++;
-      if (*str == '!')
-       {
-         write_back = 1;
-         str++;
-         if (reg == REG_PC)
-           {
-             inst.error =
-               _("R15 not allowed as base register with write-back");
-             return;
-           }
-       }
-      else
-       write_back = 0;
-
-      if (flags & CP_T_Pre)
-       {
-         /* Pre-decrement.  */
-         offset = 3 * num_regs;
-         if (write_back)
-           flags |= CP_T_WB;
-       }
-      else
-       {
-         /* Post-increment.  */
-         if (write_back)
-           {
-             flags |= CP_T_WB;
-             offset = 3 * num_regs;
-           }
-         else
-           {
-             /* No write-back, so convert this into a standard pre-increment
-                instruction -- aesthetically more pleasing.  */
-             flags = CP_T_Pre | CP_T_UD;
-             offset = 0;
-           }
-       }
-
-      inst.instruction |= flags | offset;
-    }
-  else if (skip_past_comma (&str) == FAIL
-          || cp_address_required_here (&str) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  end_of_line (str);
-}
-
-static void
-do_fp_dyadic (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  switch (inst.suffix)
-    {
-    case SUFF_S:
-      break;
-    case SUFF_D:
-      inst.instruction |= 0x00000080;
-      break;
-    case SUFF_E:
-      inst.instruction |= 0x00080000;
-      break;
-    default:
-      abort ();
-    }
-
-  if (fp_reg_required_here (&str, 12) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || fp_reg_required_here (&str, 16) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || fp_op2 (&str) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-static void
-do_fp_monadic (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  switch (inst.suffix)
-    {
-    case SUFF_S:
-      break;
-    case SUFF_D:
-      inst.instruction |= 0x00000080;
-      break;
-    case SUFF_E:
-      inst.instruction |= 0x00080000;
-      break;
-    default:
-      abort ();
-    }
-
-  if (fp_reg_required_here (&str, 12) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || fp_op2 (&str) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-static void
-do_fp_cmp (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  if (fp_reg_required_here (&str, 16) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || fp_op2 (&str) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-static void
-do_fp_from_reg (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  switch (inst.suffix)
-    {
-    case SUFF_S:
-      break;
-    case SUFF_D:
-      inst.instruction |= 0x00000080;
-      break;
-    case SUFF_E:
-      inst.instruction |= 0x00080000;
-      break;
-    default:
-      abort ();
-    }
-
-  if (fp_reg_required_here (&str, 16) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) == FAIL
-      || reg_required_here (&str, 12) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-static void
-do_fp_to_reg (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  skip_whitespace (str);
-
-  if (reg_required_here (&str, 12) == FAIL)
-    return;
-
-  if (skip_past_comma (&str) == FAIL
-      || fp_reg_required_here (&str, 0) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  inst.instruction |= flags;
-  end_of_line (str);
-  return;
-}
-
-/* Thumb specific routines.  */
-
-/* Parse and validate that a register is of the right form, this saves
-   repeated checking of this information in many similar cases.
-   Unlike the 32-bit case we do not insert the register into the opcode
-   here, since the position is often unknown until the full instruction
-   has been parsed.  */
-
-static int
-thumb_reg (strp, hi_lo)
-     char ** strp;
-     int     hi_lo;
-{
-  int reg;
-
-  if ((reg = reg_required_here (strp, -1)) == FAIL)
-    return FAIL;
-
-  switch (hi_lo)
-    {
-    case THUMB_REG_LO:
-      if (reg > 7)
-       {
-         inst.error = _("lo register required");
-         return FAIL;
-       }
-      break;
-
-    case THUMB_REG_HI:
-      if (reg < 8)
-       {
-         inst.error = _("hi register required");
-         return FAIL;
-       }
-      break;
-
-    default:
-      break;
-    }
-
-  return reg;
-}
-
-/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
-   was SUB.  */
-
-static void
-thumb_add_sub (str, subtract)
-     char * str;
-     int    subtract;
-{
-  int Rd, Rs, Rn = FAIL;
-
-  skip_whitespace (str);
-
-  if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
-      || skip_past_comma (&str) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (is_immediate_prefix (*str))
-    {
-      Rs = Rd;
-      str++;
-      if (my_get_expression (&inst.reloc.exp, &str))
-       return;
-    }
-  else
-    {
-      if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
-       return;
-
-      if (skip_past_comma (&str) == FAIL)
-       {
-         /* Two operand format, shuffle the registers
-            and pretend there are 3.  */
-         Rn = Rs;
-         Rs = Rd;
-       }
-      else if (is_immediate_prefix (*str))
-       {
-         str++;
-         if (my_get_expression (&inst.reloc.exp, &str))
-           return;
-       }
-      else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
-       return;
-    }
-
-  /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
-     for the latter case, EXPR contains the immediate that was found.  */
-  if (Rn != FAIL)
-    {
-      /* All register format.  */
-      if (Rd > 7 || Rs > 7 || Rn > 7)
-       {
-         if (Rs != Rd)
-           {
-             inst.error = _("dest and source1 must be the same register");
-             return;
-           }
-
-         /* Can't do this for SUB.  */
-         if (subtract)
-           {
-             inst.error = _("subtract valid only on lo regs");
-             return;
-           }
-
-         inst.instruction = (T_OPCODE_ADD_HI
-                             | (Rd > 7 ? THUMB_H1 : 0)
-                             | (Rn > 7 ? THUMB_H2 : 0));
-         inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
-       }
-      else
-       {
-         inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
-         inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
-       }
-    }
-  else
-    {
-      /* Immediate expression, now things start to get nasty.  */
-
-      /* First deal with HI regs, only very restricted cases allowed:
-        Adjusting SP, and using PC or SP to get an address.  */
-      if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
-         || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
-       {
-         inst.error = _("invalid Hi register with immediate");
-         return;
-       }
-
-      if (inst.reloc.exp.X_op != O_constant)
-       {
-         /* Value isn't known yet, all we can do is store all the fragments
-            we know about in the instruction and let the reloc hacking
-            work it all out.  */
-         inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
-         inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
-       }
-      else
-       {
-         int offset = inst.reloc.exp.X_add_number;
-
-         if (subtract)
-           offset = -offset;
-
-         if (offset < 0)
-           {
-             offset = -offset;
-             subtract = 1;
-
-             /* Quick check, in case offset is MIN_INT.  */
-             if (offset < 0)
-               {
-                 inst.error = _("immediate value out of range");
-                 return;
-               }
-           }
-         else
-           subtract = 0;
-
-         if (Rd == REG_SP)
-           {
-             if (offset & ~0x1fc)
-               {
-                 inst.error = _("invalid immediate value for stack adjust");
-                 return;
-               }
-             inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
-             inst.instruction |= offset >> 2;
-           }
-         else if (Rs == REG_PC || Rs == REG_SP)
-           {
-             if (subtract
-                 || (offset & ~0x3fc))
-               {
-                 inst.error = _("invalid immediate for address calculation");
-                 return;
-               }
-             inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
-                                 : T_OPCODE_ADD_SP);
-             inst.instruction |= (Rd << 8) | (offset >> 2);
-           }
-         else if (Rs == Rd)
-           {
-             if (offset & ~0xff)
-               {
-                 inst.error = _("immediate value out of range");
-                 return;
-               }
-             inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
-             inst.instruction |= (Rd << 8) | offset;
-           }
-         else
-           {
-             if (offset & ~0x7)
-               {
-                 inst.error = _("immediate value out of range");
-                 return;
-               }
-             inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
-             inst.instruction |= Rd | (Rs << 3) | (offset << 6);
-           }
-       }
-    }
-
-  end_of_line (str);
-}
-
-static void
-thumb_shift (str, shift)
-     char * str;
-     int    shift;
-{
-  int Rd, Rs, Rn = FAIL;
-
-  skip_whitespace (str);
-
-  if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
-      || skip_past_comma (&str) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (is_immediate_prefix (*str))
-    {
-      /* Two operand immediate format, set Rs to Rd.  */
-      Rs = Rd;
-      str ++;
-      if (my_get_expression (&inst.reloc.exp, &str))
-       return;
-    }
-  else
-    {
-      if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
-       return;
-
-      if (skip_past_comma (&str) == FAIL)
-       {
-         /* Two operand format, shuffle the registers
-            and pretend there are 3.  */
-         Rn = Rs;
-         Rs = Rd;
-       }
-      else if (is_immediate_prefix (*str))
-       {
-         str++;
-         if (my_get_expression (&inst.reloc.exp, &str))
-           return;
-       }
-      else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
-       return;
-    }
-
-  /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
-     for the latter case, EXPR contains the immediate that was found.  */
-
-  if (Rn != FAIL)
-    {
-      if (Rs != Rd)
-       {
-         inst.error = _("source1 and dest must be same register");
-         return;
-       }
-
-      switch (shift)
-       {
-       case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
-       case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
-       case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
-       }
-
-      inst.instruction |= Rd | (Rn << 3);
-    }
-  else
-    {
-      switch (shift)
-       {
-       case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
-       case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
-       case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
-       }
-
-      if (inst.reloc.exp.X_op != O_constant)
-       {
-         /* Value isn't known yet, create a dummy reloc and let reloc
-            hacking fix it up.  */
-         inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
-       }
-      else
-       {
-         unsigned shift_value = inst.reloc.exp.X_add_number;
-
-         if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
-           {
-             inst.error = _("Invalid immediate for shift");
-             return;
-           }
-
-         /* Shifts of zero are handled by converting to LSL.  */
-         if (shift_value == 0)
-           inst.instruction = T_OPCODE_LSL_I;
-
-         /* Shifts of 32 are encoded as a shift of zero.  */
-         if (shift_value == 32)
-           shift_value = 0;
-
-         inst.instruction |= shift_value << 6;
-       }
-
-      inst.instruction |= Rd | (Rs << 3);
-    }
-
-  end_of_line (str);
-}
-
-static void
-thumb_mov_compare (str, move)
-     char * str;
-     int    move;
-{
-  int Rd, Rs = FAIL;
-
-  skip_whitespace (str);
-
-  if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
-      || skip_past_comma (&str) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (is_immediate_prefix (*str))
-    {
-      str++;
-      if (my_get_expression (&inst.reloc.exp, &str))
-       return;
-    }
-  else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
-    return;
-
-  if (Rs != FAIL)
-    {
-      if (Rs < 8 && Rd < 8)
-       {
-         if (move == THUMB_MOVE)
-           /* A move of two lowregs is encoded as ADD Rd, Rs, #0
-              since a MOV instruction produces unpredictable results.  */
-           inst.instruction = T_OPCODE_ADD_I3;
-         else
-           inst.instruction = T_OPCODE_CMP_LR;
-         inst.instruction |= Rd | (Rs << 3);
-       }
-      else
-       {
-         if (move == THUMB_MOVE)
-           inst.instruction = T_OPCODE_MOV_HR;
-         else
-           inst.instruction = T_OPCODE_CMP_HR;
-
-         if (Rd > 7)
-           inst.instruction |= THUMB_H1;
-
-         if (Rs > 7)
-           inst.instruction |= THUMB_H2;
-
-         inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
-       }
-    }
-  else
-    {
-      if (Rd > 7)
-       {
-         inst.error = _("only lo regs allowed with immediate");
-         return;
-       }
-
-      if (move == THUMB_MOVE)
-       inst.instruction = T_OPCODE_MOV_I8;
-      else
-       inst.instruction = T_OPCODE_CMP_I8;
-
-      inst.instruction |= Rd << 8;
-
-      if (inst.reloc.exp.X_op != O_constant)
-       inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
-      else
-       {
-         unsigned value = inst.reloc.exp.X_add_number;
-
-         if (value > 255)
-           {
-             inst.error = _("invalid immediate");
-             return;
-           }
-
-         inst.instruction |= value;
-       }
-    }
-
-  end_of_line (str);
-}
-
-static void
-thumb_load_store (str, load_store, size)
-     char * str;
-     int    load_store;
-     int    size;
-{
-  int Rd, Rb, Ro = FAIL;
-
-  skip_whitespace (str);
-
-  if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
-      || skip_past_comma (&str) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (*str == '[')
-    {
-      str++;
-      if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
-       return;
-
-      if (skip_past_comma (&str) != FAIL)
-       {
-         if (is_immediate_prefix (*str))
-           {
-             str++;
-             if (my_get_expression (&inst.reloc.exp, &str))
-               return;
-           }
-         else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
-           return;
-       }
-      else
-       {
-         inst.reloc.exp.X_op = O_constant;
-         inst.reloc.exp.X_add_number = 0;
-       }
-
-      if (*str != ']')
-       {
-         inst.error = _("expected ']'");
-         return;
-       }
-      str++;
-    }
-  else if (*str == '=')
-    {
-      /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
-      str++;
-
-      skip_whitespace (str);
-
-      if (my_get_expression (& inst.reloc.exp, & str))
-       return;
-
-      end_of_line (str);
-
-      if (   inst.reloc.exp.X_op != O_constant
-         && inst.reloc.exp.X_op != O_symbol)
-       {
-         inst.error = "Constant expression expected";
-         return;
-       }
-
-      if (inst.reloc.exp.X_op == O_constant
-         && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
-       {
-         /* This can be done with a mov instruction.  */
-
-         inst.instruction  = T_OPCODE_MOV_I8 | (Rd << 8);
-         inst.instruction |= inst.reloc.exp.X_add_number;
-         return;
-       }
-
-      /* Insert into literal pool.  */
-      if (add_to_lit_pool () == FAIL)
-       {
-         if (!inst.error)
-           inst.error = "literal pool insertion failed";
-         return;
-       }
-
-      inst.reloc.type   = BFD_RELOC_ARM_THUMB_OFFSET;
-      inst.reloc.pc_rel = 1;
-      inst.instruction  = T_OPCODE_LDR_PC | (Rd << 8);
-      /* Adjust ARM pipeline offset to Thumb.  */
-      inst.reloc.exp.X_add_number += 4;
-
-      return;
-    }
-  else
-    {
-      if (my_get_expression (&inst.reloc.exp, &str))
-       return;
-
-      inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
-      inst.reloc.pc_rel = 1;
-      inst.reloc.exp.X_add_number -= 4; /* Pipeline offset.  */
-      inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
-      end_of_line (str);
-      return;
-    }
-
-  if (Rb == REG_PC || Rb == REG_SP)
-    {
-      if (size != THUMB_WORD)
-       {
-         inst.error = _("byte or halfword not valid for base register");
-         return;
-       }
-      else if (Rb == REG_PC && load_store != THUMB_LOAD)
-       {
-         inst.error = _("R15 based store not allowed");
-         return;
-       }
-      else if (Ro != FAIL)
-       {
-         inst.error = _("Invalid base register for register offset");
-         return;
-       }
-
-      if (Rb == REG_PC)
-       inst.instruction = T_OPCODE_LDR_PC;
-      else if (load_store == THUMB_LOAD)
-       inst.instruction = T_OPCODE_LDR_SP;
-      else
-       inst.instruction = T_OPCODE_STR_SP;
-
-      inst.instruction |= Rd << 8;
-      if (inst.reloc.exp.X_op == O_constant)
-       {
-         unsigned offset = inst.reloc.exp.X_add_number;
-
-         if (offset & ~0x3fc)
-           {
-             inst.error = _("invalid offset");
-             return;
-           }
-
-         inst.instruction |= offset >> 2;
-       }
-      else
-       inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
-    }
-  else if (Rb > 7)
-    {
-      inst.error = _("invalid base register in load/store");
-      return;
-    }
-  else if (Ro == FAIL)
-    {
-      /* Immediate offset.  */
-      if (size == THUMB_WORD)
-       inst.instruction = (load_store == THUMB_LOAD
-                           ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
-      else if (size == THUMB_HALFWORD)
-       inst.instruction = (load_store == THUMB_LOAD
-                           ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
-      else
-       inst.instruction = (load_store == THUMB_LOAD
-                           ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
-
-      inst.instruction |= Rd | (Rb << 3);
-
-      if (inst.reloc.exp.X_op == O_constant)
-       {
-         unsigned offset = inst.reloc.exp.X_add_number;
-
-         if (offset & ~(0x1f << size))
-           {
-             inst.error = _("Invalid offset");
-             return;
-           }
-         inst.instruction |= (offset >> size) << 6;
-       }
-      else
-       inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
-    }
-  else
-    {
-      /* Register offset.  */
-      if (size == THUMB_WORD)
-       inst.instruction = (load_store == THUMB_LOAD
-                           ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
-      else if (size == THUMB_HALFWORD)
-       inst.instruction = (load_store == THUMB_LOAD
-                           ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
-      else
-       inst.instruction = (load_store == THUMB_LOAD
-                           ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
-
-      inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
-    }
-
-  end_of_line (str);
-}
-
-static void
-do_t_nop (str)
-     char * str;
-{
-  /* Do nothing.  */
-  end_of_line (str);
-  return;
-}
-
-/* Handle the Format 4 instructions that do not have equivalents in other
-   formats.  That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
-   BIC and MVN.  */
-
-static void
-do_t_arit (str)
-     char * str;
-{
-  int Rd, Rs, Rn;
-
-  skip_whitespace (str);
-
-  if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
-    {
-      inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (skip_past_comma (&str) != FAIL)
-    {
-      /* Three operand format not allowed for TST, CMN, NEG and MVN.
-        (It isn't allowed for CMP either, but that isn't handled by this
-        function.)  */
-      if (inst.instruction == T_OPCODE_TST
-         || inst.instruction == T_OPCODE_CMN
-         || inst.instruction == T_OPCODE_NEG
-         || inst.instruction == T_OPCODE_MVN)
-       {
-         inst.error = BAD_ARGS;
-         return;
-       }
-
-      if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
-       return;
-
-      if (Rs != Rd)
-       {
-         inst.error = _("dest and source1 must be the same register");
-         return;
-       }
-      Rs = Rn;
-    }
-
-  if (inst.instruction == T_OPCODE_MUL
-      && Rs == Rd)
-    as_tsktsk (_("Rs and Rd must be different in MUL"));
-
-  inst.instruction |= Rd | (Rs << 3);
-  end_of_line (str);
-}
-
-static void
-do_t_add (str)
-     char * str;
-{
-  thumb_add_sub (str, 0);
-}
-
-static void
-do_t_asr (str)
-     char * str;
-{
-  thumb_shift (str, THUMB_ASR);
-}
-
-static void
-do_t_branch9 (str)
-     char * str;
-{
-  if (my_get_expression (&inst.reloc.exp, &str))
-    return;
-  inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
-  inst.reloc.pc_rel = 1;
-  end_of_line (str);
-}
-
-static void
-do_t_branch12 (str)
-     char * str;
-{
-  if (my_get_expression (&inst.reloc.exp, &str))
-    return;
-  inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
-  inst.reloc.pc_rel = 1;
-  end_of_line (str);
-}
-
-/* Find the real, Thumb encoded start of a Thumb function.  */
-
-static symbolS *
-find_real_start (symbolP)
-     symbolS * symbolP;
-{
-  char *       real_start;
-  const char * name = S_GET_NAME (symbolP);
-  symbolS *    new_target;
-
-  /* This definiton must agree with the one in gcc/config/arm/thumb.c.  */
-#define STUB_NAME ".real_start_of"
-
-  if (name == NULL)
-    abort ();
-
-  /* Names that start with '.' are local labels, not function entry points.
-     The compiler may generate BL instructions to these labels because it
-     needs to perform a branch to a far away location.  */
-  if (name[0] == '.')
-    return symbolP;
-
-  real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
-  sprintf (real_start, "%s%s", STUB_NAME, name);
-
-  new_target = symbol_find (real_start);
-
-  if (new_target == NULL)
-    {
-      as_warn ("Failed to find real start of function: %s\n", name);
-      new_target = symbolP;
-    }
-
-  free (real_start);
-
-  return new_target;
-}
-
-static void
-do_t_branch23 (str)
-     char * str;
-{
-  if (my_get_expression (& inst.reloc.exp, & str))
-    return;
-
-  inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BRANCH23;
-  inst.reloc.pc_rel = 1;
-  end_of_line (str);
-
-  /* If the destination of the branch is a defined symbol which does not have
-     the THUMB_FUNC attribute, then we must be calling a function which has
-     the (interfacearm) attribute.  We look for the Thumb entry point to that
-     function and change the branch to refer to that function instead.  */
-  if (   inst.reloc.exp.X_op == O_symbol
-      && inst.reloc.exp.X_add_symbol != NULL
-      && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
-      && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
-    inst.reloc.exp.X_add_symbol =
-      find_real_start (inst.reloc.exp.X_add_symbol);
-}
-
-static void
-do_t_bx (str)
-     char * str;
-{
-  int reg;
-
-  skip_whitespace (str);
-
-  if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
-    return;
-
-  /* This sets THUMB_H2 from the top bit of reg.  */
-  inst.instruction |= reg << 3;
-
-  /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC.  The reloc
-     should cause the alignment to be checked once it is known.  This is
-     because BX PC only works if the instruction is word aligned.  */
-
-  end_of_line (str);
-}
-
-static void
-do_t_compare (str)
-     char * str;
-{
-  thumb_mov_compare (str, THUMB_COMPARE);
-}
-
-static void
-do_t_ldmstm (str)
-     char * str;
-{
-  int Rb;
-  long range;
-
-  skip_whitespace (str);
-
-  if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
-    return;
-
-  if (*str != '!')
-    as_warn (_("Inserted missing '!': load/store multiple always writes back base register"));
-  else
-    str++;
-
-  if (skip_past_comma (&str) == FAIL
-      || (range = reg_list (&str)) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (inst.reloc.type != BFD_RELOC_NONE)
-    {
-      /* This really doesn't seem worth it.  */
-      inst.reloc.type = BFD_RELOC_NONE;
-      inst.error = _("Expression too complex");
-      return;
-    }
-
-  if (range & ~0xff)
-    {
-      inst.error = _("only lo-regs valid in load/store multiple");
-      return;
-    }
-
-  inst.instruction |= (Rb << 8) | range;
-  end_of_line (str);
-}
-
-static void
-do_t_ldr (str)
-     char * str;
-{
-  thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
-}
-
-static void
-do_t_ldrb (str)
-     char * str;
-{
-  thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
-}
-
-static void
-do_t_ldrh (str)
-     char * str;
-{
-  thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
-}
-
-static void
-do_t_lds (str)
-     char * str;
-{
-  int Rd, Rb, Ro;
-
-  skip_whitespace (str);
-
-  if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || *str++ != '['
-      || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
-      || skip_past_comma (&str) == FAIL
-      || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
-      || *str++ != ']')
-    {
-      if (! inst.error)
-       inst.error = _("Syntax: ldrs[b] Rd, [Rb, Ro]");
-      return;
-    }
-
-  inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
-  end_of_line (str);
-}
-
-static void
-do_t_lsl (str)
-     char * str;
-{
-  thumb_shift (str, THUMB_LSL);
-}
-
-static void
-do_t_lsr (str)
-     char * str;
-{
-  thumb_shift (str, THUMB_LSR);
-}
-
-static void
-do_t_mov (str)
-     char * str;
-{
-  thumb_mov_compare (str, THUMB_MOVE);
-}
-
-static void
-do_t_push_pop (str)
-     char * str;
-{
-  long range;
-
-  skip_whitespace (str);
-
-  if ((range = reg_list (&str)) == FAIL)
-    {
-      if (! inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  if (inst.reloc.type != BFD_RELOC_NONE)
-    {
-      /* This really doesn't seem worth it.  */
-      inst.reloc.type = BFD_RELOC_NONE;
-      inst.error = _("Expression too complex");
-      return;
-    }
-
-  if (range & ~0xff)
-    {
-      if ((inst.instruction == T_OPCODE_PUSH
-          && (range & ~0xff) == 1 << REG_LR)
-         || (inst.instruction == T_OPCODE_POP
-             && (range & ~0xff) == 1 << REG_PC))
-       {
-         inst.instruction |= THUMB_PP_PC_LR;
-         range &= 0xff;
-       }
-      else
-       {
-         inst.error = _("invalid register list to push/pop instruction");
-         return;
-       }
-    }
-
-  inst.instruction |= range;
-  end_of_line (str);
-}
-
-static void
-do_t_str (str)
-     char * str;
-{
-  thumb_load_store (str, THUMB_STORE, THUMB_WORD);
-}
-
-static void
-do_t_strb (str)
-     char * str;
-{
-  thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
-}
-
-static void
-do_t_strh (str)
-     char * str;
-{
-  thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
-}
-
-static void
-do_t_sub (str)
-     char * str;
-{
-  thumb_add_sub (str, 1);
-}
-
-static void
-do_t_swi (str)
-     char * str;
-{
-  skip_whitespace (str);
-
-  if (my_get_expression (&inst.reloc.exp, &str))
-    return;
-
-  inst.reloc.type = BFD_RELOC_ARM_SWI;
-  end_of_line (str);
-  return;
-}
-
-static void
-do_t_adr (str)
-     char * str;
-{
-  int reg;
-
-  /* This is a pseudo-op of the form "adr rd, label" to be converted
-     into a relative address of the form "add rd, pc, #label-.-4".  */
-  skip_whitespace (str);
-
-  /* Store Rd in temporary location inside instruction.  */
-  if ((reg = reg_required_here (&str, 4)) == FAIL
-      || (reg > 7)  /* For Thumb reg must be r0..r7.  */
-      || skip_past_comma (&str) == FAIL
-      || my_get_expression (&inst.reloc.exp, &str))
-    {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
-    }
-
-  inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
-  inst.reloc.exp.X_add_number -= 4; /* PC relative adjust.  */
-  inst.reloc.pc_rel = 1;
-  inst.instruction |= REG_PC; /* Rd is already placed into the instruction.  */
-
-  end_of_line (str);
-}
-
-static void
-insert_reg (entry)
-     int entry;
-{
-  int    len  = strlen (reg_table[entry].name) + 2;
-  char * buf  = (char *) xmalloc (len);
-  char * buf2 = (char *) xmalloc (len);
-  int    i    = 0;
-
-#ifdef REGISTER_PREFIX
-  buf[i++] = REGISTER_PREFIX;
-#endif
-
-  strcpy (buf + i, reg_table[entry].name);
-
-  for (i = 0; buf[i]; i++)
-    buf2[i] = islower (buf[i]) ? toupper (buf[i]) : buf[i];
-
-  buf2[i] = '\0';
-
-  hash_insert (arm_reg_hsh, buf,  (PTR) & reg_table[entry]);
-  hash_insert (arm_reg_hsh, buf2, (PTR) & reg_table[entry]);
-}
-
-static void
-insert_reg_alias (str, regnum)
-     char *str;
-     int regnum;
-{
-  struct reg_entry *new =
-    (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
-  char *name = xmalloc (strlen (str) + 1);
-  strcpy (name, str);
-
-  new->name = name;
-  new->number = regnum;
-
-  hash_insert (arm_reg_hsh, name, (PTR) new);
-}
-
-static void
-set_constant_flonums ()
-{
-  int i;
-
-  for (i = 0; i < NUM_FLOAT_VALS; i++)
-    if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
-      abort ();
-}
-
-void
-md_begin ()
-{
-  unsigned mach;
-  unsigned int i;
-
-  if (   (arm_ops_hsh = hash_new ()) == NULL
-      || (arm_tops_hsh = hash_new ()) == NULL
-      || (arm_cond_hsh = hash_new ()) == NULL
-      || (arm_shift_hsh = hash_new ()) == NULL
-      || (arm_reg_hsh = hash_new ()) == NULL
-      || (arm_psr_hsh = hash_new ()) == NULL)
-    as_fatal (_("Virtual memory exhausted"));
-
-  for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
-    hash_insert (arm_ops_hsh, insns[i].template, (PTR) (insns + i));
-  for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
-    hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
-  for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
-    hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
-  for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
-    hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
-  for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
-    hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
-
-  for (i = 0; reg_table[i].name; i++)
-    insert_reg (i);
-
-  set_constant_flonums ();
-
-#if defined OBJ_COFF || defined OBJ_ELF
-  {
-    unsigned int flags = 0;
-
-    /* Set the flags in the private structure.  */
-    if (uses_apcs_26)      flags |= F_APCS26;
-    if (support_interwork) flags |= F_INTERWORK;
-    if (uses_apcs_float)   flags |= F_APCS_FLOAT;
-    if (pic_code)          flags |= F_PIC;
-    if ((cpu_variant & FPU_ALL) == FPU_NONE) flags |= F_SOFT_FLOAT;
-
-    bfd_set_private_flags (stdoutput, flags);
-
-    /* We have run out flags in the COFF header to encode the
-       status of ATPCS support, so instead we create a dummy,
-       empty, debug section called .arm.atpcs.  */
-    if (atpcs)
-      {
-       asection * sec;
-
-       sec = bfd_make_section (stdoutput, ".arm.atpcs");
-
-       if (sec != NULL)
-         {
-           bfd_set_section_flags
-             (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
-           bfd_set_section_size (stdoutput, sec, 0);
-           bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
-         }
-      }
-  }
-#endif
-
-  /* Record the CPU type as well.  */
-  switch (cpu_variant & ARM_CPU_MASK)
-    {
-    case ARM_2:
-      mach = bfd_mach_arm_2;
-      break;
-
-    case ARM_3:                /* Also ARM_250.  */
-      mach = bfd_mach_arm_2a;
-      break;
-
-    default:
-    case ARM_6 | ARM_3 | ARM_2:        /* Actually no CPU type defined.  */
-      mach = bfd_mach_arm_4;
-      break;
-
-    case ARM_7:                /* Also ARM_6.  */
-      mach = bfd_mach_arm_3;
-      break;
-    }
-
-  /* Catch special cases.  */
-  if (cpu_variant & ARM_EXT_XSCALE)
-    mach = bfd_mach_arm_XScale;
-  else if (cpu_variant & ARM_EXT_V5E)
-    mach = bfd_mach_arm_5TE;
-  else if (cpu_variant & ARM_EXT_V5)
-    {
-      if (cpu_variant & ARM_EXT_THUMB)
-       mach = bfd_mach_arm_5T;
-      else
-       mach = bfd_mach_arm_5;
-    }
-  else if (cpu_variant & ARM_EXT_HALFWORD)
-    {
-      if (cpu_variant & ARM_EXT_THUMB)
-       mach = bfd_mach_arm_4T;
-      else
-       mach = bfd_mach_arm_4;
-    }
-  else if (cpu_variant & ARM_EXT_LONGMUL)
-    mach = bfd_mach_arm_3M;
-
-  bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
-}
-
-/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
-   for use in the a.out file, and stores them in the array pointed to by buf.
-   This knows about the endian-ness of the target machine and does
-   THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
-   2 (short) and 4 (long)  Floating numbers are put out as a series of
-   LITTLENUMS (shorts, here at least).  */
-
-void
-md_number_to_chars (buf, val, n)
-     char * buf;
-     valueT val;
-     int    n;
-{
-  if (target_big_endian)
-    number_to_chars_bigendian (buf, val, n);
-  else
-    number_to_chars_littleendian (buf, val, n);
-}
-
-static valueT
-md_chars_to_number (buf, n)
-     char * buf;
-     int    n;
-{
-  valueT result = 0;
-  unsigned char * where = (unsigned char *) buf;
-
-  if (target_big_endian)
-    {
-      while (n--)
-       {
-         result <<= 8;
-         result |= (*where++ & 255);
-       }
-    }
-  else
-    {
-      while (n--)
-       {
-         result <<= 8;
-         result |= (where[n] & 255);
-       }
-    }
-
-  return result;
-}
-
-/* Turn a string in input_line_pointer into a floating point constant
-   of type TYPE, and store the appropriate bytes in *LITP.  The number
-   of LITTLENUMS emitted is stored in *SIZEP.  An error message is
-   returned, or NULL on OK.
-
-   Note that fp constants aren't represent in the normal way on the ARM.
-   In big endian mode, things are as expected.  However, in little endian
-   mode fp constants are big-endian word-wise, and little-endian byte-wise
-   within the words.  For example, (double) 1.1 in big endian mode is
-   the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
-   the byte sequence 99 99 f1 3f 9a 99 99 99.
-
-   ??? The format of 12 byte floats is uncertain according to gcc's arm.h.  */
-
-char *
-md_atof (type, litP, sizeP)
-     char   type;
-     char * litP;
-     int *  sizeP;
-{
-  int prec;
-  LITTLENUM_TYPE words[MAX_LITTLENUMS];
-  char *t;
-  int i;
-
-  switch (type)
-    {
-    case 'f':
-    case 'F':
-    case 's':
-    case 'S':
-      prec = 2;
-      break;
-
-    case 'd':
-    case 'D':
-    case 'r':
-    case 'R':
-      prec = 4;
-      break;
-
-    case 'x':
-    case 'X':
-      prec = 6;
-      break;
-
-    case 'p':
-    case 'P':
-      prec = 6;
-      break;
-
-    default:
-      *sizeP = 0;
-      return _("Bad call to MD_ATOF()");
-    }
-
-  t = atof_ieee (input_line_pointer, type, words);
-  if (t)
-    input_line_pointer = t;
-  *sizeP = prec * 2;
-
-  if (target_big_endian)
-    {
-      for (i = 0; i < prec; i++)
-       {
-         md_number_to_chars (litP, (valueT) words[i], 2);
-         litP += 2;
-       }
-    }
-  else
-    {
-      /* For a 4 byte float the order of elements in `words' is 1 0.  For an
-        8 byte float the order is 1 0 3 2.  */
-      for (i = 0; i < prec; i += 2)
-       {
-         md_number_to_chars (litP, (valueT) words[i + 1], 2);
-         md_number_to_chars (litP + 2, (valueT) words[i], 2);
-         litP += 4;
-       }
-    }
-
-  return 0;
-}
-
-/* The knowledge of the PC's pipeline offset is built into the insns
-   themselves.  */
-
-long
-md_pcrel_from (fixP)
-     fixS * fixP;
-{
-  if (fixP->fx_addsy
-      && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
-      && fixP->fx_subsy == NULL)
-    return 0;
-
-  if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
-    {
-      /* PC relative addressing on the Thumb is slightly odd
-        as the bottom two bits of the PC are forced to zero
-        for the calculation.  */
-      return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
-    }
-
-#ifdef TE_WINCE
-  /* The pattern was adjusted to accomodate CE's off-by-one fixups,
-     so we un-adjust here to compensate for the accomodation.  */
-  return fixP->fx_where + fixP->fx_frag->fr_address + 8;
-#else
-  return fixP->fx_where + fixP->fx_frag->fr_address;
-#endif
-}
-
-/* Round up a section size to the appropriate boundary.  */
-
-valueT
-md_section_align (segment, size)
-     segT   segment ATTRIBUTE_UNUSED;
-     valueT size;
-{
-#ifdef OBJ_ELF
-  return size;
-#else
-  /* Round all sects to multiple of 4.  */
-  return (size + 3) & ~3;
-#endif
-}
-
-/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
-   Otherwise we have no need to default values of symbols.  */
-
-symbolS *
-md_undefined_symbol (name)
-     char * name ATTRIBUTE_UNUSED;
-{
-#ifdef OBJ_ELF
-  if (name[0] == '_' && name[1] == 'G'
-      && streq (name, GLOBAL_OFFSET_TABLE_NAME))
-    {
-      if (!GOT_symbol)
-       {
-         if (symbol_find (name))
-           as_bad ("GOT already in the symbol table");
-
-         GOT_symbol = symbol_new (name, undefined_section,
-                                  (valueT) 0, & zero_address_frag);
-       }
-
-      return GOT_symbol;
-    }
-#endif
-
-  return 0;
-}
-
-/* arm_reg_parse () := if it looks like a register, return its token and
-   advance the pointer.  */
-
-static int
-arm_reg_parse (ccp)
-     register char ** ccp;
-{
-  char * start = * ccp;
-  char   c;
-  char * p;
-  struct reg_entry * reg;
-
-#ifdef REGISTER_PREFIX
-  if (*start != REGISTER_PREFIX)
-    return FAIL;
-  p = start + 1;
-#else
-  p = start;
-#ifdef OPTIONAL_REGISTER_PREFIX
-  if (*p == OPTIONAL_REGISTER_PREFIX)
-    p++, start++;
-#endif
-#endif
-  if (!isalpha (*p) || !is_name_beginner (*p))
-    return FAIL;
-
-  c = *p++;
-  while (isalpha (c) || isdigit (c) || c == '_')
-    c = *p++;
-
-  *--p = 0;
-  reg = (struct reg_entry *) hash_find (arm_reg_hsh, start);
-  *p = c;
-
-  if (reg)
-    {
-      *ccp = p;
-      return reg->number;
-    }
-
-  return FAIL;
-}
-
-int
-md_apply_fix3 (fixP, val, seg)
-     fixS *   fixP;
-     valueT * val;
-     segT     seg;
-{
-  offsetT        value = * val;
-  offsetT        newval;
-  unsigned int   newimm;
-  unsigned long  temp;
-  int            sign;
-  char *         buf = fixP->fx_where + fixP->fx_frag->fr_literal;
-  arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
-
-  assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
-
-  /* Note whether this will delete the relocation.  */
-#if 0
-  /* Patch from REarnshaw to JDavis (disabled for the moment, since it
-     doesn't work fully.)  */
-  if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
-      && !fixP->fx_pcrel)
-#else
-  if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
-#endif
-    fixP->fx_done = 1;
-
-  /* If this symbol is in a different section then we need to leave it for
-     the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
-     so we have to undo it's effects here.  */
-  if (fixP->fx_pcrel)
-    {
-      if (fixP->fx_addsy != NULL
-         && S_IS_DEFINED (fixP->fx_addsy)
-         && S_GET_SEGMENT (fixP->fx_addsy) != seg)
-       {
-         if (target_oabi
-             && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
-                 || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
-                 ))
-           value = 0;
-         else
-           value += md_pcrel_from (fixP);
-       }
-    }
-
-  /* Remember value for emit_reloc.  */
-  fixP->fx_addnumber = value;
-
-  switch (fixP->fx_r_type)
-    {
-    case BFD_RELOC_ARM_IMMEDIATE:
-      newimm = validate_immediate (value);
-      temp = md_chars_to_number (buf, INSN_SIZE);
-
-      /* If the instruction will fail, see if we can fix things up by
-        changing the opcode.  */
-      if (newimm == (unsigned int) FAIL
-         && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
-       {
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("invalid constant (%lx) after fixup"),
-                       (unsigned long) value);
-         break;
-       }
-
-      newimm |= (temp & 0xfffff000);
-      md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
-      break;
-
-    case BFD_RELOC_ARM_ADRL_IMMEDIATE:
-      {
-       unsigned int highpart = 0;
-       unsigned int newinsn  = 0xe1a00000; /* nop.  */
-       newimm = validate_immediate (value);
-       temp = md_chars_to_number (buf, INSN_SIZE);
-
-       /* If the instruction will fail, see if we can fix things up by
-          changing the opcode.  */
-       if (newimm == (unsigned int) FAIL
-           && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
-         {
-           /* No ?  OK - try using two ADD instructions to generate
-               the value.  */
-           newimm = validate_immediate_twopart (value, & highpart);
-
-           /* Yes - then make sure that the second instruction is
-               also an add.  */
-           if (newimm != (unsigned int) FAIL)
-             newinsn = temp;
-           /* Still No ?  Try using a negated value.  */
-           else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
-             temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
-           /* Otherwise - give up.  */
-           else
-             {
-               as_bad_where (fixP->fx_file, fixP->fx_line,
-                             _("Unable to compute ADRL instructions for PC offset of 0x%lx"),
-                             value);
-               break;
-             }
-
-           /* Replace the first operand in the 2nd instruction (which
-              is the PC) with the destination register.  We have
-              already added in the PC in the first instruction and we
-              do not want to do it again.  */
-           newinsn &= ~ 0xf0000;
-           newinsn |= ((newinsn & 0x0f000) << 4);
-         }
-
-       newimm |= (temp & 0xfffff000);
-       md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
-
-       highpart |= (newinsn & 0xfffff000);
-       md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
-      }
-      break;
-
-    case BFD_RELOC_ARM_OFFSET_IMM:
-      sign = value >= 0;
-
-      if (value < 0)
-       value = - value;
-
-      if (validate_offset_imm (value, 0) == FAIL)
-       {
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("bad immediate value for offset (%ld)"),
-                       (long) value);
-         break;
-       }
-
-      newval = md_chars_to_number (buf, INSN_SIZE);
-      newval &= 0xff7ff000;
-      newval |= value | (sign ? INDEX_UP : 0);
-      md_number_to_chars (buf, newval, INSN_SIZE);
-      break;
-
-    case BFD_RELOC_ARM_OFFSET_IMM8:
-    case BFD_RELOC_ARM_HWLITERAL:
-      sign = value >= 0;
-
-      if (value < 0)
-       value = - value;
-
-      if (validate_offset_imm (value, 1) == FAIL)
-       {
-         if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("invalid literal constant: pool needs to be closer"));
-         else
-           as_bad (_("bad immediate value for half-word offset (%ld)"),
-                   (long) value);
-         break;
-       }
-
-      newval = md_chars_to_number (buf, INSN_SIZE);
-      newval &= 0xff7ff0f0;
-      newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
-      md_number_to_chars (buf, newval, INSN_SIZE);
-      break;
-
-    case BFD_RELOC_ARM_LITERAL:
-      sign = value >= 0;
-
-      if (value < 0)
-       value = - value;
-
-      if (validate_offset_imm (value, 0) == FAIL)
-       {
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("invalid literal constant: pool needs to be closer"));
-         break;
-       }
-
-      newval = md_chars_to_number (buf, INSN_SIZE);
-      newval &= 0xff7ff000;
-      newval |= value | (sign ? INDEX_UP : 0);
-      md_number_to_chars (buf, newval, INSN_SIZE);
-      break;
-
-    case BFD_RELOC_ARM_SHIFT_IMM:
-      newval = md_chars_to_number (buf, INSN_SIZE);
-      if (((unsigned long) value) > 32
-         || (value == 32
-             && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
-       {
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("shift expression is too large"));
-         break;
-       }
-
-      if (value == 0)
-       /* Shifts of zero must be done as lsl.  */
-       newval &= ~0x60;
-      else if (value == 32)
-       value = 0;
-      newval &= 0xfffff07f;
-      newval |= (value & 0x1f) << 7;
-      md_number_to_chars (buf, newval, INSN_SIZE);
-      break;
-
-    case BFD_RELOC_ARM_SWI:
-      if (arm_data->thumb_mode)
-       {
-         if (((unsigned long) value) > 0xff)
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("Invalid swi expression"));
-         newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
-         newval |= value;
-         md_number_to_chars (buf, newval, THUMB_SIZE);
-       }
-      else
-       {
-         if (((unsigned long) value) > 0x00ffffff)
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("Invalid swi expression"));
-         newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
-         newval |= value;
-         md_number_to_chars (buf, newval, INSN_SIZE);
-       }
-      break;
-
-    case BFD_RELOC_ARM_MULTI:
-      if (((unsigned long) value) > 0xffff)
-       as_bad_where (fixP->fx_file, fixP->fx_line,
-                     _("Invalid expression in load/store multiple"));
-      newval = value | md_chars_to_number (buf, INSN_SIZE);
-      md_number_to_chars (buf, newval, INSN_SIZE);
-      break;
-
-    case BFD_RELOC_ARM_PCREL_BRANCH:
-      newval = md_chars_to_number (buf, INSN_SIZE);
-
-      /* Sign-extend a 24-bit number.  */
-#define SEXT24(x)      ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
-
-#ifdef OBJ_ELF
-      if (! target_oabi)
-       value = fixP->fx_offset;
-#endif
-
-      /* We are going to store value (shifted right by two) in the
-        instruction, in a 24 bit, signed field.  Thus we need to check
-        that none of the top 8 bits of the shifted value (top 7 bits of
-         the unshifted, unsigned value) are set, or that they are all set.  */
-      if ((value & ~ ((offsetT) 0x1ffffff)) != 0
-         && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
-       {
-#ifdef OBJ_ELF
-         /* Normally we would be stuck at this point, since we cannot store
-            the absolute address that is the destination of the branch in the
-            24 bits of the branch instruction.  If however, we happen to know
-            that the destination of the branch is in the same section as the
-            branch instruciton itself, then we can compute the relocation for
-            ourselves and not have to bother the linker with it.
-
-            FIXME: The tests for OBJ_ELF and ! target_oabi are only here
-            because I have not worked out how to do this for OBJ_COFF or
-            target_oabi.  */
-         if (! target_oabi
-             && fixP->fx_addsy != NULL
-             && S_IS_DEFINED (fixP->fx_addsy)
-             && S_GET_SEGMENT (fixP->fx_addsy) == seg)
-           {
-             /* Get pc relative value to go into the branch.  */
-             value = * val;
-
-             /* Permit a backward branch provided that enough bits
-                are set.  Allow a forwards branch, provided that
-                enough bits are clear.  */
-             if (   (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
-                 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
-               fixP->fx_done = 1;
-           }
-
-         if (! fixP->fx_done)
-#endif
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("gas can't handle same-section branch dest >= 0x04000000"));
-       }
-
-      value >>= 2;
-      value += SEXT24 (newval);
-
-      if (    (value & ~ ((offsetT) 0xffffff)) != 0
-         && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
-       as_bad_where (fixP->fx_file, fixP->fx_line,
-                     _("out of range branch"));
-
-      newval = (value & 0x00ffffff) | (newval & 0xff000000);
-      md_number_to_chars (buf, newval, INSN_SIZE);
-      break;
-
-    case BFD_RELOC_ARM_PCREL_BLX:
-      {
-       offsetT hbit;
-       newval = md_chars_to_number (buf, INSN_SIZE);
-
-#ifdef OBJ_ELF
-       if (! target_oabi)
-         value = fixP->fx_offset;
-#endif
-       hbit   = (value >> 1) & 1;
-       value  = (value >> 2) & 0x00ffffff;
-       value  = (value + (newval & 0x00ffffff)) & 0x00ffffff;
-       newval = value | (newval & 0xfe000000) | (hbit << 24);
-       md_number_to_chars (buf, newval, INSN_SIZE);
-      }
-      break;
-
-    case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch.  */
-      newval = md_chars_to_number (buf, THUMB_SIZE);
-      {
-       addressT diff = (newval & 0xff) << 1;
-       if (diff & 0x100)
-         diff |= ~0xff;
-
-       value += diff;
-       if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("Branch out of range"));
-       newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
-      }
-      md_number_to_chars (buf, newval, THUMB_SIZE);
-      break;
-
-    case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch.  */
-      newval = md_chars_to_number (buf, THUMB_SIZE);
-      {
-       addressT diff = (newval & 0x7ff) << 1;
-       if (diff & 0x800)
-         diff |= ~0x7ff;
-
-       value += diff;
-       if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("Branch out of range"));
-       newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
-      }
-      md_number_to_chars (buf, newval, THUMB_SIZE);
-      break;
-
-    case BFD_RELOC_THUMB_PCREL_BLX:
-    case BFD_RELOC_THUMB_PCREL_BRANCH23:
-      {
-       offsetT newval2;
-       addressT diff;
-
-       newval  = md_chars_to_number (buf, THUMB_SIZE);
-       newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
-       diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
-       if (diff & 0x400000)
-         diff |= ~0x3fffff;
-#ifdef OBJ_ELF
-       value = fixP->fx_offset;
-#endif
-       value += diff;
-       if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("Branch with link out of range"));
-
-       newval  = (newval  & 0xf800) | ((value & 0x7fffff) >> 12);
-       newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
-       if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
-         /* Remove bit zero of the adjusted offset.  Bit zero can only be
-            set if the upper insn is at a half-word boundary, since the
-            destination address, an ARM instruction, must always be on a
-            word boundary.  The semantics of the BLX (1) instruction, however,
-            are that bit zero in the offset must always be zero, and the
-            corresponding bit one in the target address will be set from bit
-            one of the source address.  */
-         newval2 &= ~1;
-       md_number_to_chars (buf, newval, THUMB_SIZE);
-       md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
-      }
-      break;
-
-    case BFD_RELOC_8:
-      if (fixP->fx_done || fixP->fx_pcrel)
-       md_number_to_chars (buf, value, 1);
-#ifdef OBJ_ELF
-      else if (!target_oabi)
-       {
-         value = fixP->fx_offset;
-         md_number_to_chars (buf, value, 1);
-       }
-#endif
-      break;
-
-    case BFD_RELOC_16:
-      if (fixP->fx_done || fixP->fx_pcrel)
-       md_number_to_chars (buf, value, 2);
-#ifdef OBJ_ELF
-      else if (!target_oabi)
-       {
-         value = fixP->fx_offset;
-         md_number_to_chars (buf, value, 2);
-       }
-#endif
-      break;
-
-#ifdef OBJ_ELF
-    case BFD_RELOC_ARM_GOT32:
-    case BFD_RELOC_ARM_GOTOFF:
-      md_number_to_chars (buf, 0, 4);
-      break;
-#endif
-
-    case BFD_RELOC_RVA:
-    case BFD_RELOC_32:
-      if (fixP->fx_done || fixP->fx_pcrel)
-       md_number_to_chars (buf, value, 4);
-#ifdef OBJ_ELF
-      else if (!target_oabi)
-       {
-         value = fixP->fx_offset;
-         md_number_to_chars (buf, value, 4);
-       }
-#endif
-      break;
-
-#ifdef OBJ_ELF
-    case BFD_RELOC_ARM_PLT32:
-      /* It appears the instruction is fully prepared at this point.  */
-      break;
-#endif
-
-    case BFD_RELOC_ARM_GOTPC:
-      md_number_to_chars (buf, value, 4);
-      break;
-
-    case BFD_RELOC_ARM_CP_OFF_IMM:
-      sign = value >= 0;
-      if (value < -1023 || value > 1023 || (value & 3))
-       as_bad_where (fixP->fx_file, fixP->fx_line,
-                     _("Illegal value for co-processor offset"));
-      if (value < 0)
-       value = -value;
-      newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
-      newval |= (value >> 2) | (sign ? INDEX_UP : 0);
-      md_number_to_chars (buf, newval, INSN_SIZE);
-      break;
-
-    case BFD_RELOC_ARM_THUMB_OFFSET:
-      newval = md_chars_to_number (buf, THUMB_SIZE);
-      /* Exactly what ranges, and where the offset is inserted depends
-        on the type of instruction, we can establish this from the
-        top 4 bits.  */
-      switch (newval >> 12)
-       {
-       case 4: /* PC load.  */
-         /* Thumb PC loads are somewhat odd, bit 1 of the PC is
-            forced to zero for these loads, so we will need to round
-            up the offset if the instruction address is not word
-            aligned (since the final address produced must be, and
-            we can only describe word-aligned immediate offsets).  */
-
-         if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("Invalid offset, target not word aligned (0x%08X)"),
-                         (unsigned int) (fixP->fx_frag->fr_address
-                                         + fixP->fx_where + value));
-
-         if ((value + 2) & ~0x3fe)
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("Invalid offset, value too big (0x%08lX)"), value);
-
-         /* Round up, since pc will be rounded down.  */
-         newval |= (value + 2) >> 2;
-         break;
-
-       case 9: /* SP load/store.  */
-         if (value & ~0x3fc)
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("Invalid offset, value too big (0x%08lX)"), value);
-         newval |= value >> 2;
-         break;
-
-       case 6: /* Word load/store.  */
-         if (value & ~0x7c)
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("Invalid offset, value too big (0x%08lX)"), value);
-         newval |= value << 4; /* 6 - 2.  */
-         break;
-
-       case 7: /* Byte load/store.  */
-         if (value & ~0x1f)
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("Invalid offset, value too big (0x%08lX)"), value);
-         newval |= value << 6;
-         break;
-
-       case 8: /* Halfword load/store.  */
-         if (value & ~0x3e)
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("Invalid offset, value too big (0x%08lX)"), value);
-         newval |= value << 5; /* 6 - 1.  */
-         break;
-
-       default:
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       "Unable to process relocation for thumb opcode: %lx",
-                       (unsigned long) newval);
-         break;
-       }
-      md_number_to_chars (buf, newval, THUMB_SIZE);
-      break;
-
-    case BFD_RELOC_ARM_THUMB_ADD:
-      /* This is a complicated relocation, since we use it for all of
-         the following immediate relocations:
-
-           3bit ADD/SUB
-           8bit ADD/SUB
-           9bit ADD/SUB SP word-aligned
-          10bit ADD PC/SP word-aligned
-
-         The type of instruction being processed is encoded in the
-         instruction field:
-
-          0x8000  SUB
-          0x00F0  Rd
-          0x000F  Rs
-      */
-      newval = md_chars_to_number (buf, THUMB_SIZE);
-      {
-       int rd = (newval >> 4) & 0xf;
-       int rs = newval & 0xf;
-       int subtract = newval & 0x8000;
-
-       if (rd == REG_SP)
-         {
-           if (value & ~0x1fc)
-             as_bad_where (fixP->fx_file, fixP->fx_line,
-                           _("Invalid immediate for stack address calculation"));
-           newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
-           newval |= value >> 2;
-         }
-       else if (rs == REG_PC || rs == REG_SP)
-         {
-           if (subtract ||
-               value & ~0x3fc)
-             as_bad_where (fixP->fx_file, fixP->fx_line,
-                           _("Invalid immediate for address calculation (value = 0x%08lX)"),
-                           (unsigned long) value);
-           newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
-           newval |= rd << 8;
-           newval |= value >> 2;
-         }
-       else if (rs == rd)
-         {
-           if (value & ~0xff)
-             as_bad_where (fixP->fx_file, fixP->fx_line,
-                           _("Invalid 8bit immediate"));
-           newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
-           newval |= (rd << 8) | value;
-         }
-       else
-         {
-           if (value & ~0x7)
-             as_bad_where (fixP->fx_file, fixP->fx_line,
-                           _("Invalid 3bit immediate"));
-           newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
-           newval |= rd | (rs << 3) | (value << 6);
-         }
-      }
-      md_number_to_chars (buf, newval, THUMB_SIZE);
-      break;
-
-    case BFD_RELOC_ARM_THUMB_IMM:
-      newval = md_chars_to_number (buf, THUMB_SIZE);
-      switch (newval >> 11)
-       {
-       case 0x04: /* 8bit immediate MOV.  */
-       case 0x05: /* 8bit immediate CMP.  */
-         if (value < 0 || value > 255)
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("Invalid immediate: %ld is too large"),
-                         (long) value);
-         newval |= value;
-         break;
-
-       default:
-         abort ();
-       }
-      md_number_to_chars (buf, newval, THUMB_SIZE);
-      break;
-
-    case BFD_RELOC_ARM_THUMB_SHIFT:
-      /* 5bit shift value (0..31).  */
-      if (value < 0 || value > 31)
-       as_bad_where (fixP->fx_file, fixP->fx_line,
-                     _("Illegal Thumb shift value: %ld"), (long) value);
-      newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
-      newval |= value << 6;
-      md_number_to_chars (buf, newval, THUMB_SIZE);
-      break;
-
-    case BFD_RELOC_VTABLE_INHERIT:
-    case BFD_RELOC_VTABLE_ENTRY:
-      fixP->fx_done = 0;
-      return 1;
-
-    case BFD_RELOC_NONE:
-    default:
-      as_bad_where (fixP->fx_file, fixP->fx_line,
-                   _("Bad relocation fixup type (%d)"), fixP->fx_r_type);
-    }
-
-  return 1;
-}
-
-/* Translate internal representation of relocation info to BFD target
-   format.  */
-
-arelent *
-tc_gen_reloc (section, fixp)
-     asection * section ATTRIBUTE_UNUSED;
-     fixS * fixp;
-{
-  arelent * reloc;
-  bfd_reloc_code_real_type code;
-
-  reloc = (arelent *) xmalloc (sizeof (arelent));
-
-  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
-  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
-  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
-
-  /* @@ Why fx_addnumber sometimes and fx_offset other times?  */
-#ifndef OBJ_ELF
-  if (fixp->fx_pcrel == 0)
-    reloc->addend = fixp->fx_offset;
-  else
-    reloc->addend = fixp->fx_offset = reloc->address;
-#else  /* OBJ_ELF */
-  reloc->addend = fixp->fx_offset;
-#endif
-
-  switch (fixp->fx_r_type)
-    {
-    case BFD_RELOC_8:
-      if (fixp->fx_pcrel)
-       {
-         code = BFD_RELOC_8_PCREL;
-         break;
-       }
-
-    case BFD_RELOC_16:
-      if (fixp->fx_pcrel)
-       {
-         code = BFD_RELOC_16_PCREL;
-         break;
-       }
-
-    case BFD_RELOC_32:
-      if (fixp->fx_pcrel)
-       {
-         code = BFD_RELOC_32_PCREL;
-         break;
-       }
-
-    case BFD_RELOC_ARM_PCREL_BRANCH:
-    case BFD_RELOC_ARM_PCREL_BLX:
-    case BFD_RELOC_RVA:
-    case BFD_RELOC_THUMB_PCREL_BRANCH9:
-    case BFD_RELOC_THUMB_PCREL_BRANCH12:
-    case BFD_RELOC_THUMB_PCREL_BRANCH23:
-    case BFD_RELOC_THUMB_PCREL_BLX:
-    case BFD_RELOC_VTABLE_ENTRY:
-    case BFD_RELOC_VTABLE_INHERIT:
-      code = fixp->fx_r_type;
-      break;
-
-    case BFD_RELOC_ARM_LITERAL:
-    case BFD_RELOC_ARM_HWLITERAL:
-      /* If this is called then the a literal has been referenced across
-        a section boundary - possibly due to an implicit dump.  */
-      as_bad_where (fixp->fx_file, fixp->fx_line,
-                   _("Literal referenced across section boundary (Implicit dump?)"));
-      return NULL;
-
-#ifdef OBJ_ELF
-    case BFD_RELOC_ARM_GOT32:
-    case BFD_RELOC_ARM_GOTOFF:
-    case BFD_RELOC_ARM_PLT32:
-      code = fixp->fx_r_type;
-      break;
-#endif
-
-    case BFD_RELOC_ARM_IMMEDIATE:
-      as_bad_where (fixp->fx_file, fixp->fx_line,
-                   _("Internal_relocation (type %d) not fixed up (IMMEDIATE)"),
-                   fixp->fx_r_type);
-      return NULL;
-
-    case BFD_RELOC_ARM_ADRL_IMMEDIATE:
-      as_bad_where (fixp->fx_file, fixp->fx_line,
-                   _("ADRL used for a symbol not defined in the same file"));
-      return NULL;
-
-    case BFD_RELOC_ARM_OFFSET_IMM:
-      as_bad_where (fixp->fx_file, fixp->fx_line,
-                   _("Internal_relocation (type %d) not fixed up (OFFSET_IMM)"),
-                   fixp->fx_r_type);
-      return NULL;
-
-    default:
-      {
-       char * type;
-
-       switch (fixp->fx_r_type)
-         {
-         case BFD_RELOC_ARM_IMMEDIATE:    type = "IMMEDIATE";    break;
-         case BFD_RELOC_ARM_OFFSET_IMM:   type = "OFFSET_IMM";   break;
-         case BFD_RELOC_ARM_OFFSET_IMM8:  type = "OFFSET_IMM8";  break;
-         case BFD_RELOC_ARM_SHIFT_IMM:    type = "SHIFT_IMM";    break;
-         case BFD_RELOC_ARM_SWI:          type = "SWI";          break;
-         case BFD_RELOC_ARM_MULTI:        type = "MULTI";        break;
-         case BFD_RELOC_ARM_CP_OFF_IMM:   type = "CP_OFF_IMM";   break;
-         case BFD_RELOC_ARM_THUMB_ADD:    type = "THUMB_ADD";    break;
-         case BFD_RELOC_ARM_THUMB_SHIFT:  type = "THUMB_SHIFT";  break;
-         case BFD_RELOC_ARM_THUMB_IMM:    type = "THUMB_IMM";    break;
-         case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
-         default:                         type = _("<unknown>"); break;
-         }
-       as_bad_where (fixp->fx_file, fixp->fx_line,
-                     _("Cannot represent %s relocation in this object file format"),
-                     type);
-       return NULL;
-      }
-    }
-
-#ifdef OBJ_ELF
-  if (code == BFD_RELOC_32_PCREL
-      && GOT_symbol
-      && fixp->fx_addsy == GOT_symbol)
-    {
-      code = BFD_RELOC_ARM_GOTPC;
-      reloc->addend = fixp->fx_offset = reloc->address;
-    }
-#endif
-
-  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
-
-  if (reloc->howto == NULL)
-    {
-      as_bad_where (fixp->fx_file, fixp->fx_line,
-                   _("Can not represent %s relocation in this object file format"),
-                   bfd_get_reloc_code_name (code));
-      return NULL;
-    }
-
-  /* HACK: Since arm ELF uses Rel instead of Rela, encode the
-     vtable entry to be used in the relocation's section offset.  */
-  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
-    reloc->address = fixp->fx_offset;
-
-  return reloc;
-}
-
-int
-md_estimate_size_before_relax (fragP, segtype)
-     fragS * fragP ATTRIBUTE_UNUSED;
-     segT    segtype ATTRIBUTE_UNUSED;
-{
-  as_fatal (_("md_estimate_size_before_relax\n"));
-  return 1;
-}
-
-static void
-output_inst PARAMS ((void))
-{
-  char * to = NULL;
-
-  if (inst.error)
-    {
-      as_bad (inst.error);
-      return;
-    }
-
-  to = frag_more (inst.size);
-
-  if (thumb_mode && (inst.size > THUMB_SIZE))
-    {
-      assert (inst.size == (2 * THUMB_SIZE));
-      md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
-      md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
-    }
-  else if (inst.size > INSN_SIZE)
-    {
-      assert (inst.size == (2 * INSN_SIZE));
-      md_number_to_chars (to, inst.instruction, INSN_SIZE);
-      md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
-    }
-  else
-    md_number_to_chars (to, inst.instruction, inst.size);
-
-  if (inst.reloc.type != BFD_RELOC_NONE)
-    fix_new_arm (frag_now, to - frag_now->fr_literal,
-                inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
-                inst.reloc.type);
-
-#ifdef OBJ_ELF
-  dwarf2_emit_insn (inst.size);
-#endif
-}
-
-void
-md_assemble (str)
-     char * str;
-{
-  char   c;
-  char * p;
-  char * q;
-  char * start;
-
-  /* Align the instruction.
-     This may not be the right thing to do but ...  */
-#if 0
-  arm_align (2, 0);
-#endif
-  listing_prev_line (); /* Defined in listing.h.  */
-
-  /* Align the previous label if needed.  */
-  if (last_label_seen != NULL)
-    {
-      symbol_set_frag (last_label_seen, frag_now);
-      S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
-      S_SET_SEGMENT (last_label_seen, now_seg);
-    }
-
-  memset (&inst, '\0', sizeof (inst));
-  inst.reloc.type = BFD_RELOC_NONE;
-
-  skip_whitespace (str);
-
-  /* Scan up to the end of the op-code, which must end in white space or
-     end of string.  */
-  for (start = p = str; *p != '\0'; p++)
-    if (*p == ' ')
-      break;
-
-  if (p == str)
-    {
-      as_bad (_("No operator -- statement `%s'\n"), str);
-      return;
-    }
-
-  if (thumb_mode)
-    {
-      CONST struct thumb_opcode * opcode;
-
-      c = *p;
-      *p = '\0';
-      opcode = (CONST struct thumb_opcode *) hash_find (arm_tops_hsh, str);
-      *p = c;
-
-      if (opcode)
-       {
-         /* Check that this instruction is supported for this CPU.  */
-         if (thumb_mode == 1 && (opcode->variants & cpu_variant) == 0)
-           {
-             as_bad (_("selected processor does not support this opcode"));
-             return;
-           }
-
-         inst.instruction = opcode->value;
-         inst.size = opcode->size;
-         (*opcode->parms) (p);
-         output_inst ();
-         return;
-       }
-    }
-  else
-    {
-      CONST struct asm_opcode * opcode;
-      unsigned long cond_code;
-
-      inst.size = INSN_SIZE;
-      /* P now points to the end of the opcode, probably white space, but we
-        have to break the opcode up in case it contains condionals and flags;
-        keep trying with progressively smaller basic instructions until one
-        matches, or we run out of opcode.  */
-      q = (p - str > LONGEST_INST) ? str + LONGEST_INST : p;
-
-      for (; q != str; q--)
-       {
-         c = *q;
-         *q = '\0';
-
-         opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
-         *q = c;
-
-         if (opcode && opcode->template)
-           {
-             unsigned long flag_bits = 0;
-             char * r;
-
-             /* Check that this instruction is supported for this CPU.  */
-             if ((opcode->variants & cpu_variant) == 0)
-               goto try_shorter;
-
-             inst.instruction = opcode->value;
-             if (q == p)               /* Just a simple opcode.  */
-               {
-                 if (opcode->comp_suffix)
-                   {
-                     if (*opcode->comp_suffix != '\0')
-                       as_bad (_("Opcode `%s' must have suffix from list: <%s>"),
-                               str, opcode->comp_suffix);
-                     else
-                       /* Not a conditional instruction.  */
-                       (*opcode->parms) (q, 0);
-                   }
-                 else
-                   {
-                     /* A conditional instruction with default condition.  */
-                     inst.instruction |= COND_ALWAYS;
-                     (*opcode->parms) (q, 0);
-                   }
-                 output_inst ();
-                 return;
-               }
-
-             /* Not just a simple opcode.  Check if extra is a
-                 conditional.  */
-             r = q;
-             if (p - r >= 2)
-               {
-                 CONST struct asm_cond *cond;
-                 char d = *(r + 2);
-
-                 *(r + 2) = '\0';
-                 cond = (CONST struct asm_cond *) hash_find (arm_cond_hsh, r);
-                 *(r + 2) = d;
-                 if (cond)
-                   {
-                     if (cond->value == 0xf0000000)
-                       as_tsktsk (
-_("Warning: Use of the 'nv' conditional is deprecated\n"));
-
-                     cond_code = cond->value;
-                     r += 2;
-                   }
-                 else
-                   cond_code = COND_ALWAYS;
-               }
-             else
-               cond_code = COND_ALWAYS;
-
-             /* Apply the conditional, or complain it's not allowed.  */
-             if (opcode->comp_suffix && *opcode->comp_suffix == '\0')
-               {
-                 /* Instruction isn't conditional.  */
-                 if (cond_code != COND_ALWAYS)
-                   {
-                     as_bad (_("Opcode `%s' is unconditional\n"), str);
-                     return;
-                   }
-               }
-             else
-               /* Instruction is conditional: set the condition into it.  */
-               inst.instruction |= cond_code;
-
-             /* If there is a compulsory suffix, it should come here
-                before any optional flags.  */
-             if (opcode->comp_suffix && *opcode->comp_suffix != '\0')
-               {
-                 CONST char *s = opcode->comp_suffix;
-
-                 while (*s)
-                   {
-                     inst.suffix++;
-                     if (*r == *s)
-                       break;
-                     s++;
-                   }
-
-                 if (*s == '\0')
-                   {
-                     as_bad (_("Opcode `%s' must have suffix from <%s>\n"),
-                             str, opcode->comp_suffix);
-                     return;
-                   }
-
-                 r++;
-               }
-
-             /* The remainder, if any should now be flags for the instruction;
-                Scan these checking each one found with the opcode.  */
-             if (r != p)
-               {
-                 char d;
-                 CONST struct asm_flg *flag = opcode->flags;
-
-                 if (flag)
-                   {
-                     int flagno;
-
-                     d = *p;
-                     *p = '\0';
-
-                     for (flagno = 0; flag[flagno].template; flagno++)
-                       {
-                         if (streq (r, flag[flagno].template))
-                           {
-                             flag_bits |= flag[flagno].set_bits;
-                             break;
-                           }
-                       }
-
-                     *p = d;
-                     if (! flag[flagno].template)
-                       goto try_shorter;
-                   }
-                 else
-                   goto try_shorter;
-               }
-
-             (*opcode->parms) (p, flag_bits);
-             output_inst ();
-             return;
-           }
-
-       try_shorter:
-         ;
-       }
-    }
-
-  /* It wasn't an instruction, but it might be a register alias of the form
-     alias .req reg.  */
-  q = p;
-  skip_whitespace (q);
-
-  c = *p;
-  *p = '\0';
-
-  if (*q && !strncmp (q, ".req ", 4))
-    {
-      int    reg;
-      char * copy_of_str;
-      char * r;
-
-#ifdef IGNORE_OPCODE_CASE
-      str = original_case_string;
-#endif
-      copy_of_str = str;
-
-      q += 4;
-      skip_whitespace (q);
-
-      for (r = q; *r != '\0'; r++)
-       if (*r == ' ')
-         break;
-
-      if (r != q)
-       {
-         int regnum;
-         char d = *r;
-
-         *r = '\0';
-         regnum = arm_reg_parse (& q);
-         *r = d;
-
-         reg = arm_reg_parse (& str);
-
-         if (reg == FAIL)
-           {
-             if (regnum != FAIL)
-               insert_reg_alias (str, regnum);
-             else
-               as_warn (_("register '%s' does not exist\n"), q);
-           }
-         else if (regnum != FAIL)
-           {
-             if (reg != regnum)
-               as_warn (_("ignoring redefinition of register alias '%s'"),
-                        copy_of_str);
-
-             /* Do not warn about redefinitions to the same alias.  */
-           }
-         else
-           as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
-                    copy_of_str, q);
-       }
-      else
-       as_warn (_("ignoring incomplete .req pseuso op"));
-
-      *p = c;
-      return;
-    }
-
-  *p = c;
-  as_bad (_("bad instruction `%s'"), start);
-}
-
-/* md_parse_option
-      Invocation line includes a switch not recognized by the base assembler.
-      See if it's a processor-specific option.  These are:
-      Cpu variants, the arm part is optional:
-              -m[arm]1                Currently not supported.
-              -m[arm]2, -m[arm]250    Arm 2 and Arm 250 processor
-              -m[arm]3                Arm 3 processor
-              -m[arm]6[xx],           Arm 6 processors
-              -m[arm]7[xx][t][[d]m]   Arm 7 processors
-              -m[arm]8[10]            Arm 8 processors
-              -m[arm]9[20][tdmi]      Arm 9 processors
-              -mstrongarm[110[0]]     StrongARM processors
-              -mxscale                XScale processors
-              -m[arm]v[2345[t[e]]]    Arm architectures
-              -mall                   All (except the ARM1)
-      FP variants:
-              -mfpa10, -mfpa11        FPA10 and 11 co-processor instructions
-              -mfpe-old               (No float load/store multiples)
-              -mno-fpu                Disable all floating point instructions
-      Run-time endian selection:
-              -EB                     big endian cpu
-              -EL                     little endian cpu
-      ARM Procedure Calling Standard:
-             -mapcs-32               32 bit APCS
-             -mapcs-26               26 bit APCS
-             -mapcs-float            Pass floats in float regs
-             -mapcs-reentrant        Position independent code
-              -mthumb-interwork       Code supports Arm/Thumb interworking
-              -matpcs                 ARM/Thumb Procedure Call Standard
-              -moabi                  Old ELF ABI  */
-
-CONST char * md_shortopts = "m:k";
-
-struct option md_longopts[] =
-{
-#ifdef ARM_BI_ENDIAN
-#define OPTION_EB (OPTION_MD_BASE + 0)
-  {"EB", no_argument, NULL, OPTION_EB},
-#define OPTION_EL (OPTION_MD_BASE + 1)
-  {"EL", no_argument, NULL, OPTION_EL},
-#ifdef OBJ_ELF
-#define OPTION_OABI (OPTION_MD_BASE +2)
-  {"oabi", no_argument, NULL, OPTION_OABI},
-#endif
-#endif
-  {NULL, no_argument, NULL, 0}
-};
-
-size_t md_longopts_size = sizeof (md_longopts);
-
-int
-md_parse_option (c, arg)
-     int    c;
-     char * arg;
-{
-  char * str = arg;
-
-  switch (c)
-    {
-#ifdef ARM_BI_ENDIAN
-    case OPTION_EB:
-      target_big_endian = 1;
-      break;
-    case OPTION_EL:
-      target_big_endian = 0;
-      break;
-#endif
-
-    case 'm':
-      switch (*str)
-       {
-       case 'f':
-         if (streq (str, "fpa10"))
-           cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA10;
-         else if (streq (str, "fpa11"))
-           cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA11;
-         else if (streq (str, "fpe-old"))
-           cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_CORE;
-         else
-           goto bad;
-         break;
-
-       case 'n':
-         if (streq (str, "no-fpu"))
-           cpu_variant &= ~FPU_ALL;
-         break;
-
-#ifdef OBJ_ELF
-       case 'o':
-         if (streq (str, "oabi"))
-           target_oabi = true;
-         break;
-#endif
-
-       case 't':
-         /* Limit assembler to generating only Thumb instructions:  */
-         if (streq (str, "thumb"))
-           {
-             cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_EXT_THUMB;
-             cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_NONE;
-             thumb_mode = 1;
-           }
-         else if (streq (str, "thumb-interwork"))
-           {
-             if ((cpu_variant & ARM_EXT_THUMB) == 0)
-               cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V4T;
-#if defined OBJ_COFF || defined OBJ_ELF
-             support_interwork = true;
-#endif
-           }
-         else
-           goto bad;
-         break;
-
-       default:
-         if (streq (str, "all"))
-           {
-             cpu_variant = ARM_ALL | FPU_ALL;
-             return 1;
-           }
-#if defined OBJ_COFF || defined OBJ_ELF
-         if (! strncmp (str, "apcs-", 5))
-           {
-             /* GCC passes on all command line options starting "-mapcs-..."
-                to us, so we must parse them here.  */
-
-             str += 5;
-
-             if (streq (str, "32"))
-               {
-                 uses_apcs_26 = false;
-                 return 1;
-               }
-             else if (streq (str, "26"))
-               {
-                 uses_apcs_26 = true;
-                 return 1;
-               }
-             else if (streq (str, "frame"))
-               {
-                 /* Stack frames are being generated - does not affect
-                    linkage of code.  */
-                 return 1;
-               }
-             else if (streq (str, "stack-check"))
-               {
-                 /* Stack checking is being performed - does not affect
-                    linkage, but does require that the functions
-                    __rt_stkovf_split_small and __rt_stkovf_split_big be
-                    present in the final link.  */
-
-                 return 1;
-               }
-             else if (streq (str, "float"))
-               {
-                 /* Floating point arguments are being passed in the floating
-                    point registers.  This does affect linking, since this
-                    version of the APCS is incompatible with the version that
-                    passes floating points in the integer registers.  */
-
-                 uses_apcs_float = true;
-                 return 1;
-               }
-             else if (streq (str, "reentrant"))
-               {
-                 /* Reentrant code has been generated.  This does affect
-                    linking, since there is no point in linking reentrant/
-                    position independent code with absolute position code.  */
-                 pic_code = true;
-                 return 1;
-               }
-
-             as_bad (_("Unrecognised APCS switch -m%s"), arg);
-             return 0;
-           }
-
-         if (! strcmp (str, "atpcs"))
-           {
-             atpcs = true;
-             return 1;
-           }
-#endif
-         /* Strip off optional "arm".  */
-         if (! strncmp (str, "arm", 3))
-           str += 3;
-
-         switch (*str)
-           {
-           case '1':
-             if (streq (str, "1"))
-               cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_1;
-             else
-               goto bad;
-             break;
-
-           case '2':
-             if (streq (str, "2"))
-               cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
-             else if (streq (str, "250"))
-               cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_250;
-             else
-               goto bad;
-             break;
-
-           case '3':
-             if (streq (str, "3"))
-               cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
-             else
-               goto bad;
-             break;
-
-           case '6':
-             switch (strtol (str, NULL, 10))
-               {
-               case 6:
-               case 60:
-               case 600:
-               case 610:
-               case 620:
-                 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
-                 break;
-               default:
-                 goto bad;
-               }
-             break;
-
-           case '7':
-             /* Eat the processor name.  */
-             switch (strtol (str, & str, 10))
-               {
-               case 7:
-               case 70:
-               case 700:
-               case 710:
-               case 720:
-               case 7100:
-               case 7500:
-                 break;
-               default:
-                 goto bad;
-               }
-             cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
-             for (; *str; str++)
-               {
-                 switch (*str)
-                   {
-                   case 't':
-                     cpu_variant |= ARM_ARCH_V4T;
-                     break;
-
-                   case 'm':
-                     cpu_variant |= ARM_EXT_LONGMUL;
-                     break;
-
-                   case 'f': /* fe => fp enabled cpu.  */
-                     if (str[1] == 'e')
-                       ++ str;
-                     else
-                       goto bad;
-
-                   case 'c': /* Left over from 710c processor name.  */
-                   case 'd': /* Debug.  */
-                   case 'i': /* Embedded ICE.  */
-                     /* Included for completeness in ARM processor naming.  */
-                     break;
-
-                   default:
-                     goto bad;
-                   }
-               }
-             break;
-
-           case '8':
-             if (streq (str, "8") || streq (str, "810"))
-               cpu_variant = (cpu_variant & ~ARM_ANY)
-                 | ARM_8 | ARM_ARCH_V4;
-             else
-               goto bad;
-             break;
-
-           case '9':
-             if (streq (str, "9"))
-               cpu_variant = (cpu_variant & ~ARM_ANY)
-                 | ARM_9 | ARM_ARCH_V4T;
-             else if (streq (str, "920"))
-               cpu_variant = (cpu_variant & ~ARM_ANY)
-                 | ARM_9 | ARM_ARCH_V4;
-             else if (streq (str, "920t"))
-               cpu_variant = (cpu_variant & ~ARM_ANY)
-                 | ARM_9 | ARM_ARCH_V4T;
-             else if (streq (str, "9tdmi"))
-               cpu_variant = (cpu_variant & ~ARM_ANY)
-                 | ARM_9 | ARM_ARCH_V4T;
-             else
-               goto bad;
-             break;
-
-           case 's':
-             if (streq (str, "strongarm")
-                 || streq (str, "strongarm110")
-                 || streq (str, "strongarm1100"))
-               cpu_variant = (cpu_variant & ~ARM_ANY)
-                 | ARM_8 | ARM_ARCH_V4;
-             else
-               goto bad;
-             break;
-
-            case 'x':
-             if (streq (str, "xscale"))
-               cpu_variant = ARM_9 | ARM_ARCH_XSCALE;
-             else
-               goto bad;
-             break;
-
-           case 'v':
-             /* Select variant based on architecture rather than
-                 processor.  */
-             switch (*++str)
-               {
-               case '2':
-                 switch (*++str)
-                   {
-                   case 'a':
-                     cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
-                     break;
-                   case 0:
-                     cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
-                     break;
-                   default:
-                     as_bad (_("Invalid architecture variant -m%s"), arg);
-                     break;
-                   }
-                 break;
-
-               case '3':
-                 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
-
-                 switch (*++str)
-                   {
-                   case 'm': cpu_variant |= ARM_EXT_LONGMUL; break;
-                   case 0:   break;
-                   default:
-                     as_bad (_("Invalid architecture variant -m%s"), arg);
-                     break;
-                   }
-                 break;
-
-               case '4':
-                 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7 | ARM_ARCH_V4;
-
-                 switch (*++str)
-                   {
-                   case 't': cpu_variant |= ARM_EXT_THUMB; break;
-                   case 0:   break;
-                   default:
-                     as_bad (_("Invalid architecture variant -m%s"), arg);
-                     break;
-                   }
-                 break;
-
-               case '5':
-                 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_9 | ARM_ARCH_V5;
-                 switch (*++str)
-                   {
-                   case 't': cpu_variant |= ARM_EXT_THUMB; break;
-                   case 'e': cpu_variant |= ARM_EXT_V5E; break;
-                   case 0:   break;
-                   default:
-                     as_bad (_("Invalid architecture variant -m%s"), arg);
-                     break;
-                   }
-                 break;
-
-               default:
-                 as_bad (_("Invalid architecture variant -m%s"), arg);
-                 break;
-               }
-             break;
-
-           default:
-           bad:
-             as_bad (_("Invalid processor variant -m%s"), arg);
-             return 0;
-           }
-       }
-      break;
-
-#if defined OBJ_ELF || defined OBJ_COFF
-    case 'k':
-      pic_code = 1;
-      break;
-#endif
-
-    default:
-      return 0;
-    }
-
-  return 1;
-}
-
-void
-md_show_usage (fp)
-     FILE * fp;
-{
-  fprintf (fp, _("\
- ARM Specific Assembler Options:\n\
-  -m[arm][<processor name>] select processor variant\n\
-  -m[arm]v[2|2a|3|3m|4|4t|5[t][e]] select architecture variant\n\
-  -mthumb                   only allow Thumb instructions\n\
-  -mthumb-interwork         mark the assembled code as supporting interworking\n\
-  -mall                     allow any instruction\n\
-  -mfpa10, -mfpa11          select floating point architecture\n\
-  -mfpe-old                 don't allow floating-point multiple instructions\n\
-  -mno-fpu                  don't allow any floating-point instructions.\n\
-  -k                        generate PIC code.\n"));
-#if defined OBJ_COFF || defined OBJ_ELF
-  fprintf (fp, _("\
-  -mapcs-32, -mapcs-26      specify which ARM Procedure Calling Standard to use\n\
-  -matpcs                   use ARM/Thumb Procedure Calling Standard\n\
-  -mapcs-float              floating point args are passed in FP regs\n\
-  -mapcs-reentrant          the code is position independent/reentrant\n"));
-#endif
-#ifdef OBJ_ELF
-  fprintf (fp, _("\
-  -moabi                    support the old ELF ABI\n"));
-#endif
-#ifdef ARM_BI_ENDIAN
-  fprintf (fp, _("\
-  -EB                       assemble code for a big endian cpu\n\
-  -EL                       assemble code for a little endian cpu\n"));
-#endif
-}
-
-/* We need to be able to fix up arbitrary expressions in some statements.
-   This is so that we can handle symbols that are an arbitrary distance from
-   the pc.  The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
-   which returns part of an address in a form which will be valid for
-   a data instruction.  We do this by pushing the expression into a symbol
-   in the expr_section, and creating a fix for that.  */
-
-static void
-fix_new_arm (frag, where, size, exp, pc_rel, reloc)
-     fragS *       frag;
-     int           where;
-     short int     size;
-     expressionS * exp;
-     int           pc_rel;
-     int           reloc;
-{
-  fixS *           new_fix;
-  arm_fix_data *   arm_data;
-
-  switch (exp->X_op)
-    {
-    case O_constant:
-    case O_symbol:
-    case O_add:
-    case O_subtract:
-      new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
-      break;
-
-    default:
-      new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
-                        pc_rel, reloc);
-      break;
-    }
-
-  /* Mark whether the fix is to a THUMB instruction, or an ARM
-     instruction.  */
-  arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
-  new_fix->tc_fix_data = (PTR) arm_data;
-  arm_data->thumb_mode = thumb_mode;
-
-  return;
-}
-
-/* This fix_new is called by cons via TC_CONS_FIX_NEW.  */
-
-void
-cons_fix_new_arm (frag, where, size, exp)
-     fragS *       frag;
-     int           where;
-     int           size;
-     expressionS * exp;
-{
-  bfd_reloc_code_real_type type;
-  int pcrel = 0;
-
-  /* Pick a reloc.
-     FIXME: @@ Should look at CPU word size.  */
-  switch (size)
-    {
-    case 1:
-      type = BFD_RELOC_8;
-      break;
-    case 2:
-      type = BFD_RELOC_16;
-      break;
-    case 4:
-    default:
-      type = BFD_RELOC_32;
-      break;
-    case 8:
-      type = BFD_RELOC_64;
-      break;
-    }
-
-  fix_new_exp (frag, where, (int) size, exp, pcrel, type);
-}
-
-/* A good place to do this, although this was probably not intended
-   for this kind of use.  We need to dump the literal pool before
-   references are made to a null symbol pointer.  */
-
-void
-arm_cleanup ()
-{
-  if (current_poolP == NULL)
-    return;
-
-  /* Put it at the end of text section.  */
-  subseg_set (text_section, 0);
-  s_ltorg (0);
-  listing_prev_line ();
-}
-
-void
-arm_start_line_hook ()
-{
-  last_label_seen = NULL;
-}
-
-void
-arm_frob_label (sym)
-     symbolS * sym;
-{
-  last_label_seen = sym;
-
-  ARM_SET_THUMB (sym, thumb_mode);
-
-#if defined OBJ_COFF || defined OBJ_ELF
-  ARM_SET_INTERWORK (sym, support_interwork);
-#endif
-
-  /* Note - do not allow local symbols (.Lxxx) to be labeled
-     as Thumb functions.  This is because these labels, whilst
-     they exist inside Thumb code, are not the entry points for
-     possible ARM->Thumb calls.  Also, these labels can be used
-     as part of a computed goto or switch statement.  eg gcc
-     can generate code that looks like this:
-
-                ldr  r2, [pc, .Laaa]
-                lsl  r3, r3, #2
-                ldr  r2, [r3, r2]
-                mov  pc, r2
-               
-       .Lbbb:  .word .Lxxx
-       .Lccc:  .word .Lyyy
-       ..etc...
-       .Laaa:   .word Lbbb
-
-     The first instruction loads the address of the jump table.
-     The second instruction converts a table index into a byte offset.
-     The third instruction gets the jump address out of the table.
-     The fourth instruction performs the jump.
-     
-     If the address stored at .Laaa is that of a symbol which has the
-     Thumb_Func bit set, then the linker will arrange for this address
-     to have the bottom bit set, which in turn would mean that the
-     address computation performed by the third instruction would end
-     up with the bottom bit set.  Since the ARM is capable of unaligned
-     word loads, the instruction would then load the incorrect address
-     out of the jump table, and chaos would ensue.  */
-  if (label_is_thumb_function_name
-      && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
-      && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
-    {
-      /* When the address of a Thumb function is taken the bottom
-        bit of that address should be set.  This will allow
-        interworking between Arm and Thumb functions to work
-        correctly.  */
-
-      THUMB_SET_FUNC (sym, 1);
-
-      label_is_thumb_function_name = false;
-    }
-}
-
-/* Adjust the symbol table.  This marks Thumb symbols as distinct from
-   ARM ones.  */
-
-void
-arm_adjust_symtab ()
-{
-#ifdef OBJ_COFF
-  symbolS * sym;
-
-  for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
-    {
-      if (ARM_IS_THUMB (sym))
-       {
-         if (THUMB_IS_FUNC (sym))
-           {
-             /* Mark the symbol as a Thumb function.  */
-             if (   S_GET_STORAGE_CLASS (sym) == C_STAT
-                 || S_GET_STORAGE_CLASS (sym) == C_LABEL)  /* This can happen!  */
-               S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
-
-             else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
-               S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
-             else
-               as_bad (_("%s: unexpected function type: %d"),
-                       S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
-           }
-          else switch (S_GET_STORAGE_CLASS (sym))
-           {
-           case C_EXT:
-             S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
-             break;
-           case C_STAT:
-             S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
-             break;
-           case C_LABEL:
-             S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
-             break;
-           default:
-             /* Do nothing.  */
-             break;
-           }
-       }
-
-      if (ARM_IS_INTERWORK (sym))
-       coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
-    }
-#endif
-#ifdef OBJ_ELF
-  symbolS * sym;
-  char      bind;
-
-  for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
-    {
-      if (ARM_IS_THUMB (sym))
-       {
-         elf_symbol_type * elf_sym;
-
-         elf_sym = elf_symbol (symbol_get_bfdsym (sym));
-         bind = ELF_ST_BIND (elf_sym);
-
-         /* If it's a .thumb_func, declare it as so,
-            otherwise tag label as .code 16.  */
-         if (THUMB_IS_FUNC (sym))
-           elf_sym->internal_elf_sym.st_info =
-             ELF_ST_INFO (bind, STT_ARM_TFUNC);
-         else
-           elf_sym->internal_elf_sym.st_info =
-             ELF_ST_INFO (bind, STT_ARM_16BIT);
-       }
-    }
-#endif
-}
-
-int
-arm_data_in_code ()
-{
-  if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
-    {
-      *input_line_pointer = '/';
-      input_line_pointer += 5;
-      *input_line_pointer = 0;
-      return 1;
-    }
-
-  return 0;
-}
-
-char *
-arm_canonicalize_symbol_name (name)
-     char * name;
-{
-  int len;
-
-  if (thumb_mode && (len = strlen (name)) > 5
-      && streq (name + len - 5, "/data"))
-    *(name + len - 5) = 0;
-
-  return name;
-}
-
-boolean
-arm_validate_fix (fixP)
-     fixS * fixP;
-{
-  /* If the destination of the branch is a defined symbol which does not have
-     the THUMB_FUNC attribute, then we must be calling a function which has
-     the (interfacearm) attribute.  We look for the Thumb entry point to that
-     function and change the branch to refer to that function instead.  */
-  if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
-      && fixP->fx_addsy != NULL
-      && S_IS_DEFINED (fixP->fx_addsy)
-      && ! THUMB_IS_FUNC (fixP->fx_addsy))
-    {
-      fixP->fx_addsy = find_real_start (fixP->fx_addsy);
-      return true;
-    }
-
-  return false;
-}
-
-#ifdef OBJ_COFF
-/* This is a little hack to help the gas/arm/adrl.s test.  It prevents
-   local labels from being added to the output symbol table when they
-   are used with the ADRL pseudo op.  The ADRL relocation should always
-   be resolved before the binbary is emitted, so it is safe to say that
-   it is adjustable.  */
-
-boolean
-arm_fix_adjustable (fixP)
-   fixS * fixP;
-{
-  if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
-    return 1;
-  return 0;
-}
-#endif
-#ifdef OBJ_ELF
-/* Relocations against Thumb function names must be left unadjusted,
-   so that the linker can use this information to correctly set the
-   bottom bit of their addresses.  The MIPS version of this function
-   also prevents relocations that are mips-16 specific, but I do not
-   know why it does this.
-
-   FIXME:
-   There is one other problem that ought to be addressed here, but
-   which currently is not:  Taking the address of a label (rather
-   than a function) and then later jumping to that address.  Such
-   addresses also ought to have their bottom bit set (assuming that
-   they reside in Thumb code), but at the moment they will not.  */
-
-boolean
-arm_fix_adjustable (fixP)
-   fixS * fixP;
-{
-  if (fixP->fx_addsy == NULL)
-    return 1;
-
-  /* Prevent all adjustments to global symbols.  */
-  if (S_IS_EXTERN (fixP->fx_addsy))
-    return 0;
-
-  if (S_IS_WEAK (fixP->fx_addsy))
-    return 0;
-
-  if (THUMB_IS_FUNC (fixP->fx_addsy)
-      && fixP->fx_subsy == NULL)
-    return 0;
-
-  /* We need the symbol name for the VTABLE entries.  */
-  if (   fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
-      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
-    return 0;
-
-  return 1;
-}
-
-const char *
-elf32_arm_target_format ()
-{
-  if (target_big_endian)
-    {
-      if (target_oabi)
-       return "elf32-bigarm-oabi";
-      else
-       return "elf32-bigarm";
-    }
-  else
-    {
-      if (target_oabi)
-       return "elf32-littlearm-oabi";
-      else
-       return "elf32-littlearm";
-    }
-}
-
-void
-armelf_frob_symbol (symp, puntp)
-     symbolS * symp;
-     int *     puntp;
-{
-  elf_frob_symbol (symp, puntp);
-}
-
-int
-arm_force_relocation (fixp)
-     struct fix * fixp;
-{
-  if (   fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
-      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
-      || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
-      || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
-      || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
-      || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
-    return 1;
-
-  return 0;
-}
-
-static bfd_reloc_code_real_type
-arm_parse_reloc ()
-{
-  char         id [16];
-  char *       ip;
-  unsigned int i;
-  static struct
-  {
-    char * str;
-    int    len;
-    bfd_reloc_code_real_type reloc;
-  }
-  reloc_map[] =
-  {
-#define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
-    MAP ("(got)",    BFD_RELOC_ARM_GOT32),
-    MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
-    /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
-       branch instructions generated by GCC for PLT relocs.  */
-    MAP ("(plt)",    BFD_RELOC_ARM_PLT32),
-    { NULL, 0,         BFD_RELOC_UNUSED }
-#undef MAP
-  };
-
-  for (i = 0, ip = input_line_pointer;
-       i < sizeof (id) && (isalnum (*ip) || ispunct (*ip));
-       i++, ip++)
-    id[i] = tolower (*ip);
-
-  for (i = 0; reloc_map[i].str; i++)
-    if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
-      break;
-
-  input_line_pointer += reloc_map[i].len;
-
-  return reloc_map[i].reloc;
-}
-
-static void
-s_arm_elf_cons (nbytes)
-     int nbytes;
-{
-  expressionS exp;
-
-#ifdef md_flush_pending_output
-  md_flush_pending_output ();
-#endif
-
-  if (is_it_end_of_statement ())
-    {
-      demand_empty_rest_of_line ();
-      return;
-    }
-
-#ifdef md_cons_align
-  md_cons_align (nbytes);
-#endif
-
-  do
-    {
-      bfd_reloc_code_real_type reloc;
-
-      expression (& exp);
-
-      if (exp.X_op == O_symbol
-         && * input_line_pointer == '('
-         && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
-       {
-         reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
-         int size = bfd_get_reloc_size (howto);
-
-         if (size > nbytes)
-           as_bad ("%s relocations do not fit in %d bytes",
-                   howto->name, nbytes);
-         else
-           {
-             register char *p = frag_more ((int) nbytes);
-             int offset = nbytes - size;
-
-             fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
-                          &exp, 0, reloc);
-           }
-       }
-      else
-       emit_expr (&exp, (unsigned int) nbytes);
-    }
-  while (*input_line_pointer++ == ',');
-
-  /* Put terminator back into stream.  */
-  input_line_pointer --;
-  demand_empty_rest_of_line ();
-}
-
-#endif /* OBJ_ELF */
-
-/* This is called from HANDLE_ALIGN in write.c.  Fill in the contents
-   of an rs_align_code fragment.  */
-
-void
-arm_handle_align (fragP)
-     fragS *fragP;
-{
-  static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
-  static char const thumb_noop[2] = { 0xc0, 0x46 };
-  static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
-  static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
-
-  int bytes, fix, noop_size;
-  char * p;
-  const char * noop;
-  
-  if (fragP->fr_type != rs_align_code)
-    return;
-
-  bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
-  p = fragP->fr_literal + fragP->fr_fix;
-  fix = 0;
-  
-  if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
-    bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
-  
-  if (fragP->tc_frag_data)
-    {
-      if (target_big_endian)
-       noop = thumb_bigend_noop;
-      else
-       noop = thumb_noop;
-      noop_size = sizeof (thumb_noop);
-    }
-  else
-    {
-      if (target_big_endian)
-       noop = arm_bigend_noop;
-      else
-       noop = arm_noop;
-      noop_size = sizeof (arm_noop);
-    }
-  
-  if (bytes & (noop_size - 1))
-    {
-      fix = bytes & (noop_size - 1);
-      memset (p, 0, fix);
-      p += fix;
-      bytes -= fix;
-    }
-
-  while (bytes >= noop_size)
-    {
-      memcpy (p, noop, noop_size);
-      p += noop_size;
-      bytes -= noop_size;
-      fix += noop_size;
-    }
-  
-  fragP->fr_fix += fix;
-  fragP->fr_var = noop_size;
-}
-
-/* Called from md_do_align.  Used to create an alignment
-   frag in a code section.  */
-
-void
-arm_frag_align_code (n, max)
-     int n;
-     int max;
-{
-  char * p;
-
-  /* We assume that there will never be a requirment
-     to support alignments greater than 32 bytes.  */
-  if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
-    as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
-  
-  p = frag_var (rs_align_code,
-               MAX_MEM_FOR_RS_ALIGN_CODE,
-               1,
-               (relax_substateT) max,
-               (symbolS *) NULL,
-               (offsetT) n,
-               (char *) NULL);
-  *p = 0;
-
-}
-
-/* Perform target specific initialisation of a frag.  */
-
-void
-arm_init_frag (fragP)
-     fragS *fragP;
-{
-  /* Record whether this frag is in an ARM or a THUMB area.  */
-  fragP->tc_frag_data = thumb_mode;
-}