This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gas/ARM parser rewrite


Ok, here's the main part of the parser re-write for the ARM assembler.  In 
the past we used to try to construct possibly conditional instructions on 
the fly if we failed to find a match for the insn.  This was

1) Probably somewhat error prone
2) Fairly slow, since it wasn't always clear where the condition operation 
could go we had to search the entire instruction
3) Required a further hack for those few instructions that aren't 
conditional.
4) Caused major problems for instructions such as ldr/ldrb/ldrsb/ldrd etc, 
where the basic insn code changed depending on the precise mnemonic.  This 
was made worse by the fact that the availability of these instructions 
depends on the processor we are assembling for.

The new parser solves these problems by constructing all possible 
conditional instructions and entering them in the hash table during 
initialization.  This makes the run-time parsing much more 
straight-forward: a simple hash-table look-up.

The hack in the instruction table, that I introduced in my previous patch 
is no-longer needed, and has been removed.

I've also taken the opportunity with this change to fix the assembly of 
pld instructions -- these instructions shouldn't accept any post-indexed 
type operations.  The testsuite is also fixed for this.

R.

PS. there are a few warnings introduced by this patch about the argument 
"flags" to some functions being unused.  I've deliberately not fixed 
these; the next patch will remove this argument entirely as it is now 
redundant.

gas:
<date>  Richard Earnshaw  (rearnsha@arm.com)

	* tc-arm.c (struct asm_opcode): Delete comp_suffix and flags.  Add
	cond_offset.  Rename variants->variant.
	(insns): Adjust for new format.  Explicitly code each variant that
	takes flags.  Remove temporary instructions.
	(struct arm_it): Remove redundant field suffix.
	(s_flag, ldr_flags, str_flags, byte_flag, cmp_flags, ldm_flags)
	(stm_flags, lfm_flags, sfm_flags, round_flags, fix_flags, except_flag)
	(long_flag): Delete.
	(struct asm_flg): Delete.
	(LONGEST_INST): Delete.
	(V4_STR_BIT): Define.
	(struct thumb_opcode): Rename variants->variant.
	(do_empty): Renamed from do_nop.
	(ldst_extend): Delete argument hwse.  Split code for half-word and
	signed byte instructions to ...
	(ldst_extend_v4): ... here.
	(ld_mode_required_here): Use ldst_extend_v4.
	(do_ldrd): Simplify now that this is only called for ldrd.  No
	need to test for XScale, which was wrong anyway.  Don't reject r12
	as a target register.  Add test that ldrd doesn't update an index
	register.
	(do_pld): Don't allow post-indexed or write-back addressing modes.
	Adjust call to ldst_extend.
	(do_adr): Split code for adrl to ...
	(do_adrl): ... here.
	(do_cmp): No need to fold in COND_BIT.
	(do_ldst): Simplify.  Split code for ldrt/strt into do_ldstt.  Split
	code to handle half-word and signed byte instructions to ...
	(do_ldstv4): ... here.
	(do_ldstt): New function.  Handle load/store with translate.
	(do_ldmstm): Write feature modification bits directly into
	inst.instruction.
	(do_fpa_ldst): Remove suffix handling code.
	(do_fpa_dyadic, do_fpa_monadic, do_fpa_from_reg): Likewise.
	(do_fpa_ldmstm): Type of access is now held in inst.instruction.
	(build_arm_ops_hsh): New function.
	(md_begin): Call it.  Don't build the ARM opcode directly.
	(md_assemble): Simplify ARM instruction handling.

gas/testsuite:
<date>  Richard Earnshaw  (rearnsha@arm.com)

	* gas/arm/xscale.s, arm/xscale.s (pld tests): pld instruction has no
	post-indexed addressing modes.

Index: config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.103
diff -p -r1.103 tc-arm.c
*** tc-arm.c	2001/12/04 11:28:29	1.103
--- tc-arm.c	2001/12/05 10:05:52
***************
*** 80,86 ****
  
  /* Some useful combinations:  */
  #define ARM_ANY		0x00ffffff
- #define ARM_2UP		(ARM_ANY - ARM_1)
  #define ARM_ALL		ARM_ANY
  
  #define FPU_FPA_EXT_V1	0x80000000	/* Base FPA instruction set.  */
--- 80,85 ----
*************** struct arm_it
*** 188,194 ****
  {
    const char *  error;
    unsigned long instruction;
-   int           suffix;
    int           size;
    struct
    {
--- 187,192 ----
*************** LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS]
*** 279,285 ****
  
  #define CONDS_BIT        0x00100000
  #define LOAD_BIT         0x00100000
- #define TRANS_BIT	 0x00200000
  
  #define DOUBLE_LOAD_FLAG 0x00000001
  
--- 277,282 ----
*************** struct asm_cond
*** 289,296 ****
    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[] =
  {
--- 286,293 ----
    unsigned long value;
  };
  
  #define COND_ALWAYS 0xe0000000
+ #define COND_MASK   0xf0000000
  
  static const struct asm_cond conds[] =
  {
*************** static const struct asm_cond conds[] =
*** 312,448 ****
    {"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 long_flag[] =
- {
-   {"l", 0x00400000},
-   {NULL, 0}
- };
- 
  struct asm_psr
  {
    const char *  template;
--- 309,314 ----
*************** static void do_arit		PARAMS ((char *, un
*** 619,631 ****
  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_nop		PARAMS ((char *, unsigned long));
  
  /* ARM v2.  */
  static void do_mul		PARAMS ((char *, unsigned long));
--- 485,499 ----
  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_ldstt		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_empty		PARAMS ((char *, unsigned long));
  
  /* ARM v2.  */
  static void do_mul		PARAMS ((char *, unsigned long));
*************** static void do_mrs		PARAMS ((char *, uns
*** 641,650 ****
  /* ARM v3M.  */
  static void do_mull		PARAMS ((char *, unsigned long));
  
  /* ARM v4T.  */
  static void do_bx               PARAMS ((char *, unsigned long));
  
! /* ARM_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));
--- 509,521 ----
  /* ARM v3M.  */
  static void do_mull		PARAMS ((char *, unsigned long));
  
+ /* ARM v4.  */
+ static void do_ldstv4		PARAMS ((char *, unsigned long));
+ 
  /* ARM v4T.  */
  static void do_bx               PARAMS ((char *, unsigned long));
  
! /* ARM 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_c_ldst_1		PARAMS ((char *
*** 704,720 ****
  static void do_c_ldst_2		PARAMS ((char *, unsigned long));
  static void do_c_ldst_3		PARAMS ((char *, unsigned long));
  static void do_c_ldst_4		PARAMS ((char *, unsigned long));
! static int cirrus_reg_required_here	PARAMS ((char **, int, enum cirrus_regtype));
  static int cirrus_valid_reg	PARAMS ((int, enum cirrus_regtype));
  static int cirrus_parse_offset	PARAMS ((char **, int *));
  
! 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 *));
--- 575,595 ----
  static void do_c_ldst_2		PARAMS ((char *, unsigned long));
  static void do_c_ldst_3		PARAMS ((char *, unsigned long));
  static void do_c_ldst_4		PARAMS ((char *, unsigned long));
! static int cirrus_reg_required_here	PARAMS ((char **, int,
! 						 enum cirrus_regtype));
  static int cirrus_valid_reg	PARAMS ((int, enum cirrus_regtype));
  static int cirrus_parse_offset	PARAMS ((char **, int *));
  
! 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 fp_op2		PARAMS ((char **));
*** 735,741 ****
  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));
--- 610,617 ----
  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 **));
! static int ldst_extend_v4		PARAMS ((char **));
  static void thumb_add_sub	PARAMS ((char *, int));
  static void insert_reg		PARAMS ((int));
  static void thumb_shift		PARAMS ((char *, int));
*************** static bfd_reloc_code_real_type	arm_pars
*** 756,766 ****
     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 10
- 
  /* "INSN<cond> X,Y" where X:bit12, Y:bit16.  */
  #define CIRRUS_MODE1	0x100c
  
--- 632,637 ----
*************** struct asm_opcode
*** 786,801 ****
  
    /* 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));
--- 657,669 ----
  
    /* Basic instruction code.  */
    unsigned long value;
  
!   /* Offset into the template where the condition code (if any) will be.
!      If zero, then the instruction is never conditional.  */
!   unsigned cond_offset;
  
!   /* Which architecture variant provides this instruction.  */
!   unsigned long variant;
  
    /* Function to call to parse args.  */
    void (* parms) PARAMS ((char *, unsigned long));
*************** struct asm_opcode
*** 803,1062 ****
  
  static const struct asm_opcode insns[] =
  {
-   /* XXX Temporary hack.  Override the normal load/store entry points.  */
-   {"ldr",   0x000000d0, NULL,   ldr_flags,   ARM_EXT_V1,        do_ldrd},
-   {"str",   0x000000f0, NULL,   str_flags,   ARM_EXT_V1,        do_ldrd},
- 
    /* Core ARM Instructions.  */
!   {"and",   0x00000000, NULL,   s_flag,      ARM_EXT_V1,      do_arit},
!   {"eor",   0x00200000, NULL,   s_flag,      ARM_EXT_V1,      do_arit},
!   {"sub",   0x00400000, NULL,   s_flag,      ARM_EXT_V1,      do_arit},
!   {"rsb",   0x00600000, NULL,   s_flag,      ARM_EXT_V1,      do_arit},
!   {"add",   0x00800000, NULL,   s_flag,      ARM_EXT_V1,      do_arit},
!   {"adc",   0x00a00000, NULL,   s_flag,      ARM_EXT_V1,      do_arit},
!   {"sbc",   0x00c00000, NULL,   s_flag,      ARM_EXT_V1,      do_arit},
!   {"rsc",   0x00e00000, NULL,   s_flag,      ARM_EXT_V1,      do_arit},
!   {"orr",   0x01800000, NULL,   s_flag,      ARM_EXT_V1,      do_arit},
!   {"bic",   0x01c00000, NULL,   s_flag,      ARM_EXT_V1,      do_arit},
!   {"tst",   0x01000000, NULL,   cmp_flags,   ARM_EXT_V1,      do_cmp},
!   {"teq",   0x01200000, NULL,   cmp_flags,   ARM_EXT_V1,      do_cmp},
!   {"cmp",   0x01400000, NULL,   cmp_flags,   ARM_EXT_V1,      do_cmp},
!   {"cmn",   0x01600000, NULL,   cmp_flags,   ARM_EXT_V1,      do_cmp},
!   {"mov",   0x01a00000, NULL,   s_flag,      ARM_EXT_V1,      do_mov},
!   {"mvn",   0x01e00000, NULL,   s_flag,      ARM_EXT_V1,      do_mov},
!   {"str",   0x04000000, NULL,   str_flags,   ARM_EXT_V1,      do_ldst},
!   {"ldr",   0x04100000, NULL,   ldr_flags,   ARM_EXT_V1,      do_ldst},
!   {"stm",   0x08000000, NULL,   stm_flags,   ARM_EXT_V1,      do_ldmstm},
!   {"ldm",   0x08100000, NULL,   ldm_flags,   ARM_EXT_V1,      do_ldmstm},
!   {"swi",   0x0f000000, NULL,   NULL,        ARM_EXT_V1,      do_swi},
  #ifdef TE_WINCE
    /* XXX This is the wrong place to do this.  Think multi-arch.  */
!   {"bl",    0x0b000000, NULL,   NULL,        ARM_EXT_V1,      do_branch},
!   {"b",     0x0a000000, NULL,   NULL,        ARM_EXT_V1,      do_branch},
  #else
!   {"bl",    0x0bfffffe, NULL,   NULL,        ARM_EXT_V1,      do_branch},
!   {"b",     0x0afffffe, NULL,   NULL,        ARM_EXT_V1,      do_branch},
  #endif
  
    /* Pseudo ops.  */
!   {"adr",   0x028f0000, NULL,   long_flag,   ARM_EXT_V1,      do_adr},
!   {"nop",   0x01a00000, NULL,   NULL,        ARM_EXT_V1,      do_nop},
  
    /* ARM 2 multiplies.  */
!   {"mul",   0x00000090, NULL,   s_flag,      ARM_EXT_V2,      do_mul},
!   {"mla",   0x00200090, NULL,   s_flag,      ARM_EXT_V2,      do_mla},
  
    /* Generic copressor instructions.  */
!   {"cdp",   0x0e000000, NULL,  NULL,         ARM_EXT_V2,      do_cdp},
!   {"ldc",   0x0c100000, NULL,  long_flag,    ARM_EXT_V2,      do_lstc},
!   {"stc",   0x0c000000, NULL,  long_flag,    ARM_EXT_V2,      do_lstc},
!   {"mcr",   0x0e000010, NULL,  NULL,         ARM_EXT_V2,      do_co_reg},
!   {"mrc",   0x0e100010, NULL,  NULL,         ARM_EXT_V2,      do_co_reg},
  
    /* ARM 3 - swp instructions.  */
!   {"swp",   0x01000090, NULL,   byte_flag,   ARM_EXT_V2S,      do_swap},
  
    /* ARM 6 Status register instructions.  */
!   {"mrs",   0x010f0000, NULL,   NULL,        ARM_EXT_V3,      do_mrs},
!   {"msr",   0x0120f000, NULL,   NULL,        ARM_EXT_V3,      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_V3M,  do_mull},
!   {"umull", 0x00800090, NULL,   s_flag,      ARM_EXT_V3M,  do_mull},
!   {"smlal", 0x00e00090, NULL,   s_flag,      ARM_EXT_V3M,  do_mull},
!   {"umlal", 0x00a00090, NULL,   s_flag,      ARM_EXT_V3M,  do_mull},
  
    /* ARM Architecture 4T.  */
!   /* Note: bx (and blx) are required on V5, even if the processor does
!      not support Thumb.   */
!   {"bx",    0x012fff10, NULL,   NULL,        ARM_EXT_V4T | ARM_EXT_V5, do_bx},
! 
!   /*  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, "",  	long_flag,   ARM_EXT_V5, do_lstc2},
!   {"stc2",  0xfc000000, "",  	long_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 Architecture 5ExP.  */
!   {"smlabb", 0x01000080, NULL,   NULL,        ARM_EXT_V5ExP, do_smla},
!   {"smlatb", 0x010000a0, NULL,   NULL,        ARM_EXT_V5ExP, do_smla},
!   {"smlabt", 0x010000c0, NULL,   NULL,        ARM_EXT_V5ExP, do_smla},
!   {"smlatt", 0x010000e0, NULL,   NULL,        ARM_EXT_V5ExP, do_smla},
! 
!   {"smlawb", 0x01200080, NULL,   NULL,        ARM_EXT_V5ExP, do_smla},
!   {"smlawt", 0x012000c0, NULL,   NULL,        ARM_EXT_V5ExP, do_smla},
! 
!   {"smlalbb",0x01400080, NULL,   NULL,        ARM_EXT_V5ExP, do_smlal},
!   {"smlaltb",0x014000a0, NULL,   NULL,        ARM_EXT_V5ExP, do_smlal},
!   {"smlalbt",0x014000c0, NULL,   NULL,        ARM_EXT_V5ExP, do_smlal},
!   {"smlaltt",0x014000e0, NULL,   NULL,        ARM_EXT_V5ExP, do_smlal},
! 
!   {"smulbb", 0x01600080, NULL,   NULL,        ARM_EXT_V5ExP, do_smul},
!   {"smultb", 0x016000a0, NULL,   NULL,        ARM_EXT_V5ExP, do_smul},
!   {"smulbt", 0x016000c0, NULL,   NULL,        ARM_EXT_V5ExP, do_smul},
!   {"smultt", 0x016000e0, NULL,   NULL,        ARM_EXT_V5ExP, do_smul},
! 
!   {"smulwb", 0x012000a0, NULL,   NULL,        ARM_EXT_V5ExP, do_smul},
!   {"smulwt", 0x012000e0, NULL,   NULL,        ARM_EXT_V5ExP, do_smul},
! 
!   {"qadd",   0x01000050, NULL,   NULL,        ARM_EXT_V5ExP, do_qadd},
!   {"qdadd",  0x01400050, NULL,   NULL,        ARM_EXT_V5ExP, do_qadd},
!   {"qsub",   0x01200050, NULL,   NULL,        ARM_EXT_V5ExP, do_qadd},
!   {"qdsub",  0x01600050, NULL,   NULL,        ARM_EXT_V5ExP, do_qadd},
  
    /*  ARM Architecture 5E.  */
!   {"pld",   0xf450f000, "",     NULL,         ARM_EXT_V5E, do_pld},
!   {"ldr",   0x000000d0, NULL,   ldr_flags,    ARM_EXT_V5E, do_ldrd},
!   {"str",   0x000000f0, NULL,   str_flags,    ARM_EXT_V5E, do_ldrd},
!   {"mcrr",  0x0c400000, NULL,   NULL,         ARM_EXT_V5E, do_co_reg2c},
!   {"mrrc",  0x0c500000, NULL,   NULL,         ARM_EXT_V5E, do_co_reg2c},
  
    /* Core FPA instruction set (V1).  */
!   {"wfs",   0x0e200110, NULL,   NULL,        FPU_FPA_EXT_V1,      do_fpa_ctrl},
!   {"rfs",   0x0e300110, NULL,   NULL,        FPU_FPA_EXT_V1,      do_fpa_ctrl},
!   {"wfc",   0x0e400110, NULL,   NULL,        FPU_FPA_EXT_V1,      do_fpa_ctrl},
!   {"rfc",   0x0e500110, NULL,   NULL,        FPU_FPA_EXT_V1,      do_fpa_ctrl},
!   {"ldf",   0x0c100100, "sdep", NULL,        FPU_FPA_EXT_V1,      do_fpa_ldst},
!   {"stf",   0x0c000100, "sdep", NULL,        FPU_FPA_EXT_V1,      do_fpa_ldst},
!   {"mvf",   0x0e008100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"mnf",   0x0e108100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"abs",   0x0e208100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"rnd",   0x0e308100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"sqt",   0x0e408100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"log",   0x0e508100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"lgn",   0x0e608100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"exp",   0x0e708100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"sin",   0x0e808100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"cos",   0x0e908100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"tan",   0x0ea08100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"asn",   0x0eb08100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"acs",   0x0ec08100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"atn",   0x0ed08100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"urd",   0x0ee08100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"nrm",   0x0ef08100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_monadic},
!   {"adf",   0x0e000100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"suf",   0x0e200100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"rsf",   0x0e300100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"muf",   0x0e100100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"dvf",   0x0e400100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"rdf",   0x0e500100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"pow",   0x0e600100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"rpw",   0x0e700100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"rmf",   0x0e800100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"fml",   0x0e900100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"fdv",   0x0ea00100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"frd",   0x0eb00100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"pol",   0x0ec00100, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_dyadic},
!   {"cmf",   0x0e90f110, NULL,   except_flag, FPU_FPA_EXT_V1,      do_fpa_cmp},
!   {"cnf",   0x0eb0f110, NULL,   except_flag, FPU_FPA_EXT_V1,      do_fpa_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_FPA_EXT_V1,      do_fpa_cmp},
!   {"cnfe",  0x0ef0f110, NULL,   NULL,        FPU_FPA_EXT_V1,      do_fpa_cmp},
!   {"flt",   0x0e000110, "sde",  round_flags, FPU_FPA_EXT_V1,      do_fpa_from_reg},
!   {"fix",   0x0e100110, NULL,   fix_flags,   FPU_FPA_EXT_V1,      do_fpa_to_reg},
  
    /* Instructions that were new with the real FPA, call them V2.  */
!   {"lfm",   0x0c100200, NULL,   lfm_flags,   FPU_FPA_EXT_V2, do_fpa_ldmstm},
!   {"sfm",   0x0c000200, NULL,   sfm_flags,   FPU_FPA_EXT_V2, do_fpa_ldmstm},
  
    /* Intel XScale extensions to ARM V5 ISA.  (All use CP0).  */
!   {"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},
  
    /* Cirrus DSP instructions.  */
!   {"cfldrs",	0x0c100400,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_ldst_1},
!   {"cfldrd",	0x0c500400,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_ldst_2},
!   {"cfldr32",	0x0c100500,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_ldst_3},
!   {"cfldr64",	0x0c500500,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_ldst_4},
!   {"cfstrs",	0x0c000400,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_ldst_1},
!   {"cfstrd",	0x0c400400,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_ldst_2},
!   {"cfstr32",	0x0c000500,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_ldst_3},
!   {"cfstr64",	0x0c400500,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_ldst_4},
!   {"cfmvsr",	0x0e000450,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_2},
!   {"cfmvrs",	0x0e100450,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfmvdlr",	0x0e000410,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_2},
!   {"cfmvrdl",	0x0e100410,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfmvdhr",	0x0e000430,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_2},
!   {"cfmvrdh",	0x0e100430,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfmv64lr",	0x0e000510,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_2},
!   {"cfmvr64l",	0x0e100510,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfmv64hr",	0x0e000530,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_2},
!   {"cfmvr64h",	0x0e100530,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfmval32",	0x0e100610,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmv32al",	0x0e000610,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmvam32",	0x0e100630,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmv32am",	0x0e000630,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmvah32",	0x0e100650,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmv32ah",	0x0e000650,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmv32a",	0x0e000670,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmva32",	0x0e100670,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmv64a",	0x0e000690,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmva64",	0x0e100690,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmvsc32",	0x0e1006b0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_dspsc_1},
!   {"cfmv32sc",	0x0e0006b0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_dspsc_2},
!   {"cfcpys",	0x0e000400,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcpyd",	0x0e000420,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvtsd",	0x0e000460,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvtds",	0x0e000440,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvt32s",	0x0e000480,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvt32d",	0x0e0004a0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvt64s",	0x0e0004c0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvt64d",	0x0e0004e0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvts32",	0x0e100580,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvtd32",	0x0e1005a0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cftruncs32",0x0e1005c0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cftruncd32",0x0e1005e0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfrshl32",	0x0e000550,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_4},
!   {"cfrshl64",	0x0e000570,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_4},
!   {"cfsh32",	0x0e000500,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_shift_1},
!   {"cfsh64",	0x0e200500,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_shift_2},
!   {"cfcmps",	0x0e100490,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfcmpd",	0x0e1004b0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfcmp32",	0x0e100590,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfcmp64",	0x0e1005b0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfabss",	0x0e300400,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfabsd",	0x0e300420,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfnegs",	0x0e300440,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfnegd",	0x0e300460,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfadds",	0x0e300480,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfaddd",	0x0e3004a0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfsubs",	0x0e3004c0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfsubd",	0x0e3004e0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmuls",	0x0e100400,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmuld",	0x0e100420,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfabs32",	0x0e300500,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfabs64",	0x0e300520,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfneg32",	0x0e300540,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfneg64",	0x0e300560,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfadd32",	0x0e300580,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfadd64",	0x0e3005a0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfsub32",	0x0e3005c0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfsub64",	0x0e3005e0,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmul32",	0x0e100500,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmul64",	0x0e100520,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmac32",	0x0e100540,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmsc32",	0x0e100560,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmadd32",	0x0e000600,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_quad_6},
!   {"cfmsub32",	0x0e100600,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_quad_6},
!   {"cfmadda32",	0x0e200600,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_quad_6},
!   {"cfmsuba32",	0x0e300600,	NULL,	NULL,	ARM_EXT_MAVERICK, do_c_quad_6},
  };
  
  /* Defines for various bits that we will want to toggle.  */
--- 671,1384 ----
  
  static const struct asm_opcode insns[] =
  {
    /* Core ARM Instructions.  */
!   {"and",        0xe0000000, 3,  ARM_EXT_V1,       do_arit},
!   {"ands",       0xe0100000, 3,  ARM_EXT_V1,       do_arit},
!   {"eor",        0xe0200000, 3,  ARM_EXT_V1,       do_arit},
!   {"eors",       0xe0300000, 3,  ARM_EXT_V1,       do_arit},
!   {"sub",        0xe0400000, 3,  ARM_EXT_V1,       do_arit},
!   {"subs",       0xe0500000, 3,  ARM_EXT_V1,       do_arit},
!   {"rsb",        0xe0600000, 3,  ARM_EXT_V1,       do_arit},
!   {"rsbs",       0xe0700000, 3,  ARM_EXT_V1,       do_arit},
!   {"add",        0xe0800000, 3,  ARM_EXT_V1,       do_arit},
!   {"adds",       0xe0900000, 3,  ARM_EXT_V1,       do_arit},
!   {"adc",        0xe0a00000, 3,  ARM_EXT_V1,       do_arit},
!   {"adcs",       0xe0b00000, 3,  ARM_EXT_V1,       do_arit},
!   {"sbc",        0xe0c00000, 3,  ARM_EXT_V1,       do_arit},
!   {"sbcs",       0xe0d00000, 3,  ARM_EXT_V1,       do_arit},
!   {"rsc",        0xe0e00000, 3,  ARM_EXT_V1,       do_arit},
!   {"rscs",       0xe0f00000, 3,  ARM_EXT_V1,       do_arit},
!   {"orr",        0xe1800000, 3,  ARM_EXT_V1,       do_arit},
!   {"orrs",       0xe1900000, 3,  ARM_EXT_V1,       do_arit},
!   {"bic",        0xe1c00000, 3,  ARM_EXT_V1,       do_arit},
!   {"bics",       0xe1d00000, 3,  ARM_EXT_V1,       do_arit},
! 
!   {"tst",        0xe1100000, 3,  ARM_EXT_V1,       do_cmp},
!   {"tsts",       0xe1100000, 3,  ARM_EXT_V1,       do_cmp},
!   {"tstp",       0xe110f000, 3,  ARM_EXT_V1,       do_cmp},
!   {"teq",        0xe1300000, 3,  ARM_EXT_V1,       do_cmp},
!   {"teqs",       0xe1300000, 3,  ARM_EXT_V1,       do_cmp},
!   {"teqp",       0xe130f000, 3,  ARM_EXT_V1,       do_cmp},
!   {"cmp",        0xe1500000, 3,  ARM_EXT_V1,       do_cmp},
!   {"cmps",       0xe1500000, 3,  ARM_EXT_V1,       do_cmp},
!   {"cmpp",       0xe150f000, 3,  ARM_EXT_V1,       do_cmp},
!   {"cmn",        0xe1700000, 3,  ARM_EXT_V1,       do_cmp},
!   {"cmns",       0xe1700000, 3,  ARM_EXT_V1,       do_cmp},
!   {"cmnp",       0xe170f000, 3,  ARM_EXT_V1,       do_cmp},
! 
!   {"mov",        0xe1a00000, 3,  ARM_EXT_V1,       do_mov},
!   {"movs",       0xe1b00000, 3,  ARM_EXT_V1,       do_mov},
!   {"mvn",        0xe1e00000, 3,  ARM_EXT_V1,       do_mov},
!   {"mvns",       0xe1f00000, 3,  ARM_EXT_V1,       do_mov},
! 
!   {"ldr",        0xe4100000, 3,  ARM_EXT_V1,       do_ldst},
!   {"ldrb",       0xe4500000, 3,  ARM_EXT_V1,       do_ldst},
!   {"ldrt",       0xe4300000, 3,  ARM_EXT_V1,       do_ldstt},
!   {"ldrbt",      0xe4700000, 3,  ARM_EXT_V1,       do_ldstt},
!   {"str",        0xe4000000, 3,  ARM_EXT_V1,       do_ldst},
!   {"strb",       0xe4400000, 3,  ARM_EXT_V1,       do_ldst},
!   {"strt",       0xe4200000, 3,  ARM_EXT_V1,       do_ldstt},
!   {"strbt",      0xe4600000, 3,  ARM_EXT_V1,       do_ldstt},
! 
!   {"stmia",      0xe8800000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"stmib",      0xe9800000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"stmda",      0xe8000000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"stmdb",      0xe9000000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"stmfd",      0xe9000000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"stmfa",      0xe9800000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"stmea",      0xe8800000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"stmed",      0xe8000000, 3,  ARM_EXT_V1,       do_ldmstm},
! 
!   {"ldmia",      0xe8900000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"ldmib",      0xe9900000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"ldmda",      0xe8100000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"ldmdb",      0xe9100000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"ldmfd",      0xe8900000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"ldmfa",      0xe8100000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"ldmea",      0xe9100000, 3,  ARM_EXT_V1,       do_ldmstm},
!   {"ldmed",      0xe9900000, 3,  ARM_EXT_V1,       do_ldmstm},
! 
!   {"swi",        0xef000000, 3,  ARM_EXT_V1,       do_swi},
  #ifdef TE_WINCE
    /* XXX This is the wrong place to do this.  Think multi-arch.  */
!   {"bl",         0xeb000000, 2,  ARM_EXT_V1,       do_branch},
!   {"b",          0xea000000, 1,  ARM_EXT_V1,       do_branch},
  #else
!   {"bl",         0xebfffffe, 2,  ARM_EXT_V1,       do_branch},
!   {"b",          0xeafffffe, 1,  ARM_EXT_V1,       do_branch},
  #endif
  
    /* Pseudo ops.  */
!   {"adr",        0xe28f0000, 3,  ARM_EXT_V1,       do_adr},
!   {"adrl",       0xe28f0000, 3,  ARM_EXT_V1,       do_adrl},
!   {"nop",        0xe1a00000, 3,  ARM_EXT_V1,       do_empty},
  
    /* ARM 2 multiplies.  */
!   {"mul",        0xe0000090, 3,  ARM_EXT_V2,       do_mul},
!   {"muls",       0xe0100090, 3,  ARM_EXT_V2,       do_mul},
!   {"mla",        0xe0200090, 3,  ARM_EXT_V2,       do_mla},
!   {"mlas",       0xe0300090, 3,  ARM_EXT_V2,       do_mla},
  
    /* Generic copressor instructions.  */
!   {"cdp",        0xee000000, 3,  ARM_EXT_V2,       do_cdp},
!   {"ldc",        0xec100000, 3,  ARM_EXT_V2,       do_lstc},
!   {"ldcl",       0xec500000, 3,  ARM_EXT_V2,       do_lstc},
!   {"stc",        0xec000000, 3,  ARM_EXT_V2,       do_lstc},
!   {"stcl",       0xec400000, 3,  ARM_EXT_V2,       do_lstc},
!   {"mcr",        0xee000010, 3,  ARM_EXT_V2,       do_co_reg},
!   {"mrc",        0xee100010, 3,  ARM_EXT_V2,       do_co_reg},
  
    /* ARM 3 - swp instructions.  */
!   {"swp",        0xe1000090, 3,  ARM_EXT_V2S,      do_swap},
!   {"swpb",       0xe1400090, 3,  ARM_EXT_V2S,      do_swap},
  
    /* ARM 6 Status register instructions.  */
!   {"mrs",        0xe10f0000, 3,  ARM_EXT_V3,       do_mrs},
!   {"msr",        0xe120f000, 3,  ARM_EXT_V3,       do_msr},
!   /* ScottB: our code uses     0xe128f000 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",      0xe0c00090, 5,  ARM_EXT_V3M,      do_mull},
!   {"smulls",     0xe0d00090, 5,  ARM_EXT_V3M,      do_mull},
!   {"umull",      0xe0800090, 5,  ARM_EXT_V3M,      do_mull},
!   {"umulls",     0xe0900090, 5,  ARM_EXT_V3M,      do_mull},
!   {"smlal",      0xe0e00090, 5,  ARM_EXT_V3M,      do_mull},
!   {"smlals",     0xe0f00090, 5,  ARM_EXT_V3M,      do_mull},
!   {"umlal",      0xe0a00090, 5,  ARM_EXT_V3M,      do_mull},
!   {"umlals",     0xe0b00090, 5,  ARM_EXT_V3M,      do_mull},
! 
!   /* ARM Architecture 4.  */
!   {"ldrh",       0xe01000b0, 3,  ARM_EXT_V4,       do_ldstv4},
!   {"ldrsh",      0xe01000f0, 3,  ARM_EXT_V4,       do_ldstv4},
!   {"ldrsb",      0xe01000d0, 3,  ARM_EXT_V4,       do_ldstv4},
!   {"strh",       0xe00000b0, 3,  ARM_EXT_V4,       do_ldstv4},
  
    /* ARM Architecture 4T.  */
!   /* Note: bx (and blx) are required on V5, even if the processor does 
!      not support Thumb.  */
!   {"bx",         0xe12fff10, 2,  ARM_EXT_V4T | ARM_EXT_V5, do_bx},
! 
!   /*  ARM Architecture 5.  */
!   /* Note: blx has 2 variants, so the .value is set dynamically.
!      Only one of the variants has conditional execution.  */
!   {"blx",        0xe0000000, 3,  ARM_EXT_V5,       do_blx},
!   {"clz",        0xe16f0f10, 3,  ARM_EXT_V5,       do_clz},
!   {"bkpt",       0xe1200070, 0,  ARM_EXT_V5,       do_bkpt},
!   {"ldc2",       0xfc100000, 0,  ARM_EXT_V5,       do_lstc2},
!   {"ldc2l",      0xfc500000, 0,  ARM_EXT_V5,       do_lstc2},
!   {"stc2",       0xfc000000, 0,  ARM_EXT_V5,       do_lstc2},
!   {"stc2l",      0xfc400000, 0,  ARM_EXT_V5,       do_lstc2},
!   {"cdp2",       0xfe000000, 0,  ARM_EXT_V5,       do_cdp2},
!   {"mcr2",       0xfe000010, 0,  ARM_EXT_V5,       do_co_reg2},
!   {"mrc2",       0xfe100010, 0,  ARM_EXT_V5,       do_co_reg2},
! 
!   /*  ARM Architecture 5ExP.  */
!   {"smlabb",     0xe1000080, 6,  ARM_EXT_V5ExP,    do_smla},
!   {"smlatb",     0xe10000a0, 6,  ARM_EXT_V5ExP,    do_smla},
!   {"smlabt",     0xe10000c0, 6,  ARM_EXT_V5ExP,    do_smla},
!   {"smlatt",     0xe10000e0, 6,  ARM_EXT_V5ExP,    do_smla},
! 
!   {"smlawb",     0xe1200080, 6,  ARM_EXT_V5ExP,    do_smla},
!   {"smlawt",     0xe12000c0, 6,  ARM_EXT_V5ExP,    do_smla},
! 
!   {"smlalbb",    0xe1400080, 7,  ARM_EXT_V5ExP,    do_smlal},
!   {"smlaltb",    0xe14000a0, 7,  ARM_EXT_V5ExP,    do_smlal},
!   {"smlalbt",    0xe14000c0, 7,  ARM_EXT_V5ExP,    do_smlal},
!   {"smlaltt",    0xe14000e0, 7,  ARM_EXT_V5ExP,    do_smlal},
! 
!   {"smulbb",     0xe1600080, 6,  ARM_EXT_V5ExP,    do_smul},
!   {"smultb",     0xe16000a0, 6,  ARM_EXT_V5ExP,    do_smul},
!   {"smulbt",     0xe16000c0, 6,  ARM_EXT_V5ExP,    do_smul},
!   {"smultt",     0xe16000e0, 6,  ARM_EXT_V5ExP,    do_smul},
! 
!   {"smulwb",     0xe12000a0, 6,  ARM_EXT_V5ExP,    do_smul},
!   {"smulwt",     0xe12000e0, 6,  ARM_EXT_V5ExP,    do_smul},
! 
!   {"qadd",       0xe1000050, 4,  ARM_EXT_V5ExP,    do_qadd},
!   {"qdadd",      0xe1400050, 5,  ARM_EXT_V5ExP,    do_qadd},
!   {"qsub",       0xe1200050, 4,  ARM_EXT_V5ExP,    do_qadd},
!   {"qdsub",      0xe1600050, 5,  ARM_EXT_V5ExP,    do_qadd},
  
    /*  ARM Architecture 5E.  */
!   {"pld",        0xf450f000, 0,  ARM_EXT_V5E,      do_pld},
!   {"ldrd",       0xe00000d0, 3,  ARM_EXT_V5E,      do_ldrd},
!   {"strd",       0xe00000f0, 3,  ARM_EXT_V5E,      do_ldrd},
! 
!   {"mcrr",       0xec400000, 4,  ARM_EXT_V5E,      do_co_reg2c},
!   {"mrrc",       0xec500000, 4,  ARM_EXT_V5E,      do_co_reg2c},
  
    /* Core FPA instruction set (V1).  */
!   {"wfs",        0xee200110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
!   {"rfs",        0xee300110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
!   {"wfc",        0xee400110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
!   {"rfc",        0xee500110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
! 
!   {"ldfs",       0xec100100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
!   {"ldfd",       0xec108100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
!   {"ldfe",       0xec500100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
!   {"ldfp",       0xec508100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
! 
!   {"stfs",       0xec000100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
!   {"stfd",       0xec008100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
!   {"stfe",       0xec400100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
!   {"stfp",       0xec408100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
! 
!   {"mvfs",       0xee008100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mvfsp",      0xee008120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mvfsm",      0xee008140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mvfsz",      0xee008160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mvfd",       0xee008180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mvfdp",      0xee0081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mvfdm",      0xee0081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mvfdz",      0xee0081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mvfe",       0xee088100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mvfep",      0xee088120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mvfem",      0xee088140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mvfez",      0xee088160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"mnfs",       0xee108100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mnfsp",      0xee108120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mnfsm",      0xee108140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mnfsz",      0xee108160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mnfd",       0xee108180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mnfdp",      0xee1081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mnfdm",      0xee1081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mnfdz",      0xee1081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mnfe",       0xee188100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mnfep",      0xee188120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mnfem",      0xee188140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"mnfez",      0xee188160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"abss",       0xee208100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"abssp",      0xee208120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"abssm",      0xee208140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"abssz",      0xee208160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"absd",       0xee208180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"absdp",      0xee2081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"absdm",      0xee2081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"absdz",      0xee2081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"abse",       0xee288100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"absep",      0xee288120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"absem",      0xee288140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"absez",      0xee288160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"rnds",       0xee308100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"rndsp",      0xee308120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"rndsm",      0xee308140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"rndsz",      0xee308160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"rndd",       0xee308180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"rnddp",      0xee3081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"rnddm",      0xee3081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"rnddz",      0xee3081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"rnde",       0xee388100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"rndep",      0xee388120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"rndem",      0xee388140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"rndez",      0xee388160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"sqts",       0xee408100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sqtsp",      0xee408120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sqtsm",      0xee408140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sqtsz",      0xee408160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sqtd",       0xee408180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sqtdp",      0xee4081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sqtdm",      0xee4081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sqtdz",      0xee4081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sqte",       0xee488100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sqtep",      0xee488120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sqtem",      0xee488140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sqtez",      0xee488160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"logs",       0xee508100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"logsp",      0xee508120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"logsm",      0xee508140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"logsz",      0xee508160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"logd",       0xee508180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"logdp",      0xee5081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"logdm",      0xee5081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"logdz",      0xee5081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"loge",       0xee588100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"logep",      0xee588120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"logem",      0xee588140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"logez",      0xee588160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"lgns",       0xee608100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"lgnsp",      0xee608120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"lgnsm",      0xee608140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"lgnsz",      0xee608160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"lgnd",       0xee608180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"lgndp",      0xee6081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"lgndm",      0xee6081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"lgndz",      0xee6081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"lgne",       0xee688100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"lgnep",      0xee688120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"lgnem",      0xee688140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"lgnez",      0xee688160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"exps",       0xee708100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"expsp",      0xee708120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"expsm",      0xee708140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"expsz",      0xee708160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"expd",       0xee708180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"expdp",      0xee7081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"expdm",      0xee7081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"expdz",      0xee7081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"expe",       0xee788100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"expep",      0xee788120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"expem",      0xee788140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"expdz",      0xee788160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"sins",       0xee808100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sinsp",      0xee808120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sinsm",      0xee808140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sinsz",      0xee808160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sind",       0xee808180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sindp",      0xee8081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sindm",      0xee8081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sindz",      0xee8081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sine",       0xee888100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sinep",      0xee888120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sinem",      0xee888140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"sinez",      0xee888160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"coss",       0xee908100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"cossp",      0xee908120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"cossm",      0xee908140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"cossz",      0xee908160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"cosd",       0xee908180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"cosdp",      0xee9081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"cosdm",      0xee9081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"cosdz",      0xee9081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"cose",       0xee988100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"cosep",      0xee988120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"cosem",      0xee988140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"cosez",      0xee988160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"tans",       0xeea08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"tansp",      0xeea08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"tansm",      0xeea08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"tansz",      0xeea08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"tand",       0xeea08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"tandp",      0xeea081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"tandm",      0xeea081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"tandz",      0xeea081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"tane",       0xeea88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"tanep",      0xeea88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"tanem",      0xeea88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"tanez",      0xeea88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"asns",       0xeeb08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"asnsp",      0xeeb08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"asnsm",      0xeeb08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"asnsz",      0xeeb08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"asnd",       0xeeb08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"asndp",      0xeeb081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"asndm",      0xeeb081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"asndz",      0xeeb081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"asne",       0xeeb88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"asnep",      0xeeb88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"asnem",      0xeeb88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"asnez",      0xeeb88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"acss",       0xeec08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"acssp",      0xeec08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"acssm",      0xeec08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"acssz",      0xeec08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"acsd",       0xeec08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"acsdp",      0xeec081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"acsdm",      0xeec081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"acsdz",      0xeec081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"acse",       0xeec88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"acsep",      0xeec88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"acsem",      0xeec88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"acsez",      0xeec88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"atns",       0xeed08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"atnsp",      0xeed08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"atnsm",      0xeed08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"atnsz",      0xeed08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"atnd",       0xeed08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"atndp",      0xeed081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"atndm",      0xeed081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"atndz",      0xeed081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"atne",       0xeed88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"atnep",      0xeed88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"atnem",      0xeed88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"atnez",      0xeed88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"urds",       0xeee08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"urdsp",      0xeee08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"urdsm",      0xeee08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"urdsz",      0xeee08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"urdd",       0xeee08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"urddp",      0xeee081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"urddm",      0xeee081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"urddz",      0xeee081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"urde",       0xeee88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"urdep",      0xeee88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"urdem",      0xeee88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"urdez",      0xeee88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"nrms",       0xeef08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"nrmsp",      0xeef08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"nrmsm",      0xeef08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"nrmsz",      0xeef08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"nrmd",       0xeef08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"nrmdp",      0xeef081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"nrmdm",      0xeef081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"nrmdz",      0xeef081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"nrme",       0xeef88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"nrmep",      0xeef88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"nrmem",      0xeef88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
!   {"nrmez",      0xeef88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
! 
!   {"adfs",       0xee000100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"adfsp",      0xee000120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"adfsm",      0xee000140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"adfsz",      0xee000160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"adfd",       0xee000180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"adfdp",      0xee0001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"adfdm",      0xee0001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"adfdz",      0xee0001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"adfe",       0xee080100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"adfep",      0xee080120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"adfem",      0xee080140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"adfez",      0xee080160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"sufs",       0xee200100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"sufsp",      0xee200120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"sufsm",      0xee200140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"sufsz",      0xee200160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"sufd",       0xee200180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"sufdp",      0xee2001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"sufdm",      0xee2001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"sufdz",      0xee2001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"sufe",       0xee280100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"sufep",      0xee280120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"sufem",      0xee280140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"sufez",      0xee280160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"rsfs",       0xee300100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rsfsp",      0xee300120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rsfsm",      0xee300140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rsfsz",      0xee300160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rsfd",       0xee300180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rsfdp",      0xee3001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rsfdm",      0xee3001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rsfdz",      0xee3001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rsfe",       0xee380100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rsfep",      0xee380120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rsfem",      0xee380140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rsfez",      0xee380160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"mufs",       0xee100100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"mufsp",      0xee100120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"mufsm",      0xee100140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"mufsz",      0xee100160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"mufd",       0xee100180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"mufdp",      0xee1001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"mufdm",      0xee1001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"mufdz",      0xee1001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"mufe",       0xee180100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"mufep",      0xee180120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"mufem",      0xee180140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"mufez",      0xee180160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"dvfs",       0xee400100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"dvfsp",      0xee400120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"dvfsm",      0xee400140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"dvfsz",      0xee400160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"dvfd",       0xee400180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"dvfdp",      0xee4001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"dvfdm",      0xee4001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"dvfdz",      0xee4001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"dvfe",       0xee480100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"dvfep",      0xee480120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"dvfem",      0xee480140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"dvfez",      0xee480160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"rdfs",       0xee500100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rdfsp",      0xee500120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rdfsm",      0xee500140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rdfsz",      0xee500160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rdfd",       0xee500180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rdfdp",      0xee5001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rdfdm",      0xee5001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rdfdz",      0xee5001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rdfe",       0xee580100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rdfep",      0xee580120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rdfem",      0xee580140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rdfez",      0xee580160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"pows",       0xee600100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"powsp",      0xee600120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"powsm",      0xee600140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"powsz",      0xee600160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"powd",       0xee600180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"powdp",      0xee6001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"powdm",      0xee6001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"powdz",      0xee6001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"powe",       0xee680100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"powep",      0xee680120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"powem",      0xee680140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"powez",      0xee680160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"rpws",       0xee700100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rpwsp",      0xee700120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rpwsm",      0xee700140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rpwsz",      0xee700160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rpwd",       0xee700180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rpwdp",      0xee7001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rpwdm",      0xee7001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rpwdz",      0xee7001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rpwe",       0xee780100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rpwep",      0xee780120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rpwem",      0xee780140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rpwez",      0xee780160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"rmfs",       0xee800100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rmfsp",      0xee800120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rmfsm",      0xee800140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rmfsz",      0xee800160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rmfd",       0xee800180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rmfdp",      0xee8001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rmfdm",      0xee8001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rmfdz",      0xee8001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rmfe",       0xee880100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rmfep",      0xee880120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rmfem",      0xee880140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"rmfez",      0xee880160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"fmls",       0xee900100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fmlsp",      0xee900120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fmlsm",      0xee900140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fmlsz",      0xee900160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fmld",       0xee900180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fmldp",      0xee9001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fmldm",      0xee9001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fmldz",      0xee9001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fmle",       0xee980100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fmlep",      0xee980120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fmlem",      0xee980140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fmlez",      0xee980160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"fdvs",       0xeea00100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fdvsp",      0xeea00120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fdvsm",      0xeea00140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fdvsz",      0xeea00160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fdvd",       0xeea00180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fdvdp",      0xeea001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fdvdm",      0xeea001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fdvdz",      0xeea001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fdve",       0xeea80100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fdvep",      0xeea80120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fdvem",      0xeea80140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"fdvez",      0xeea80160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"frds",       0xeeb00100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"frdsp",      0xeeb00120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"frdsm",      0xeeb00140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"frdsz",      0xeeb00160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"frdd",       0xeeb00180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"frddp",      0xeeb001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"frddm",      0xeeb001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"frddz",      0xeeb001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"frde",       0xeeb80100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"frdep",      0xeeb80120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"frdem",      0xeeb80140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"frdez",      0xeeb80160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"pols",       0xeec00100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"polsp",      0xeec00120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"polsm",      0xeec00140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"polsz",      0xeec00160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"pold",       0xeec00180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"poldp",      0xeec001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"poldm",      0xeec001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"poldz",      0xeec001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"pole",       0xeec80100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"polep",      0xeec80120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"polem",      0xeec80140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
!   {"polez",      0xeec80160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
! 
!   {"cmf",        0xee90f110, 3,  FPU_FPA_EXT_V1,   do_fpa_cmp},
!   {"cmfe",       0xeed0f110, 3,  FPU_FPA_EXT_V1,   do_fpa_cmp},
!   {"cnf",        0xeeb0f110, 3,  FPU_FPA_EXT_V1,   do_fpa_cmp},
!   {"cnfe",       0xeef0f110, 3,  FPU_FPA_EXT_V1,   do_fpa_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",       0xeed0f110, 4,  FPU_FPA_EXT_V1,   do_fpa_cmp},
!   {"cnfe",       0xeef0f110, 4,  FPU_FPA_EXT_V1,   do_fpa_cmp},
! 
!   {"flts",       0xee000110, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
!   {"fltsp",      0xee000130, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
!   {"fltsm",      0xee000150, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
!   {"fltsz",      0xee000170, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
!   {"fltd",       0xee000190, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
!   {"fltdp",      0xee0001b0, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
!   {"fltdm",      0xee0001d0, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
!   {"fltdz",      0xee0001f0, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
!   {"flte",       0xee080110, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
!   {"fltep",      0xee080130, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
!   {"fltem",      0xee080150, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
!   {"fltez",      0xee080170, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
! 
!   /* 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.  */
!   {"fix",        0xee100110, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixp",       0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixm",       0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixz",       0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixsp",      0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixsm",      0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixsz",      0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixdp",      0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixdm",      0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixdz",      0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixep",      0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixem",      0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
!   {"fixez",      0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
  
    /* Instructions that were new with the real FPA, call them V2.  */
!   {"lfm",        0xec100200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
!   {"lfmfd",      0xec900200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
!   {"lfmea",      0xed100200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
!   {"sfm",        0xec000200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
!   {"sfmfd",      0xed000200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
!   {"sfmea",      0xec800200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
  
    /* Intel XScale extensions to ARM V5 ISA.  (All use CP0).  */
!   {"mia",        0xee200010, 3,  ARM_EXT_XSCALE,   do_mia},
!   {"miaph",      0xee280010, 5,  ARM_EXT_XSCALE,   do_mia},
!   {"miabb",      0xee2c0010, 5,  ARM_EXT_XSCALE,   do_mia},
!   {"miabt",      0xee2d0010, 5,  ARM_EXT_XSCALE,   do_mia},
!   {"miatb",      0xee2e0010, 5,  ARM_EXT_XSCALE,   do_mia},
!   {"miatt",      0xee2f0010, 5,  ARM_EXT_XSCALE,   do_mia},
!   {"mar",        0xec400000, 3,  ARM_EXT_XSCALE,   do_mar},
!   {"mra",        0xec500000, 3,  ARM_EXT_XSCALE,   do_mra},
  
    /* Cirrus DSP instructions.  */
!   {"cfldrs",     0xec100400, 6,  ARM_EXT_MAVERICK, do_c_ldst_1},
!   {"cfldrd",     0xec500400, 6,  ARM_EXT_MAVERICK, do_c_ldst_2},
!   {"cfldr32",    0xec100500, 7,  ARM_EXT_MAVERICK, do_c_ldst_3},
!   {"cfldr64",    0xec500500, 7,  ARM_EXT_MAVERICK, do_c_ldst_4},
!   {"cfstrs",     0xec000400, 6,  ARM_EXT_MAVERICK, do_c_ldst_1},
!   {"cfstrd",     0xec400400, 6,  ARM_EXT_MAVERICK, do_c_ldst_2},
!   {"cfstr32",    0xec000500, 7,  ARM_EXT_MAVERICK, do_c_ldst_3},
!   {"cfstr64",    0xec400500, 7,  ARM_EXT_MAVERICK, do_c_ldst_4},
!   {"cfmvsr",     0xee000450, 6,  ARM_EXT_MAVERICK, do_c_binops_2},
!   {"cfmvrs",     0xee100450, 6,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfmvdlr",    0xee000410, 7,  ARM_EXT_MAVERICK, do_c_binops_2},
!   {"cfmvrdl",    0xee100410, 7,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfmvdhr",    0xee000430, 7,  ARM_EXT_MAVERICK, do_c_binops_2},
!   {"cfmvrdh",    0xee100430, 7,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfmv64lr",   0xee000510, 8,  ARM_EXT_MAVERICK, do_c_binops_2},
!   {"cfmvr64l",   0xee100510, 8,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfmv64hr",   0xee000530, 8,  ARM_EXT_MAVERICK, do_c_binops_2},
!   {"cfmvr64h",   0xee100530, 8,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfmval32",   0xee100610, 8,  ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmv32al",   0xee000610, 8,  ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmvam32",   0xee100630, 8,  ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmv32am",   0xee000630, 8,  ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmvah32",   0xee100650, 8,  ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmv32ah",   0xee000650, 8,  ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmv32a",    0xee000670, 7,  ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmva32",    0xee100670, 7,  ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmv64a",    0xee000690, 7,  ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmva64",    0xee100690, 7,  ARM_EXT_MAVERICK, do_c_binops_3},
!   {"cfmvsc32",   0xee1006b0, 8,  ARM_EXT_MAVERICK, do_c_dspsc_1},
!   {"cfmv32sc",   0xee0006b0, 8,  ARM_EXT_MAVERICK, do_c_dspsc_2},
!   {"cfcpys",     0xee000400, 6,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcpyd",     0xee000420, 6,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvtsd",    0xee000460, 7,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvtds",    0xee000440, 7,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvt32s",   0xee000480, 8,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvt32d",   0xee0004a0, 8,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvt64s",   0xee0004c0, 8,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvt64d",   0xee0004e0, 8,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvts32",   0xee100580, 8,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfcvtd32",   0xee1005a0, 8,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cftruncs32", 0xee1005c0, 10, ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cftruncd32", 0xee1005e0, 10, ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfrshl32",   0xee000550, 8,  ARM_EXT_MAVERICK, do_c_triple_4},
!   {"cfrshl64",   0xee000570, 8,  ARM_EXT_MAVERICK, do_c_triple_4},
!   {"cfsh32",     0xee000500, 6,  ARM_EXT_MAVERICK, do_c_shift_1},
!   {"cfsh64",     0xee200500, 6,  ARM_EXT_MAVERICK, do_c_shift_2},
!   {"cfcmps",     0xee100490, 6,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfcmpd",     0xee1004b0, 6,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfcmp32",    0xee100590, 7,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfcmp64",    0xee1005b0, 7,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfabss",     0xee300400, 6,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfabsd",     0xee300420, 6,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfnegs",     0xee300440, 6,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfnegd",     0xee300460, 6,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfadds",     0xee300480, 6,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfaddd",     0xee3004a0, 6,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfsubs",     0xee3004c0, 6,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfsubd",     0xee3004e0, 6,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmuls",     0xee100400, 6,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmuld",     0xee100420, 6,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfabs32",    0xee300500, 7,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfabs64",    0xee300520, 7,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfneg32",    0xee300540, 7,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfneg64",    0xee300560, 7,  ARM_EXT_MAVERICK, do_c_binops_1},
!   {"cfadd32",    0xee300580, 7,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfadd64",    0xee3005a0, 7,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfsub32",    0xee3005c0, 7,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfsub64",    0xee3005e0, 7,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmul32",    0xee100500, 7,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmul64",    0xee100520, 7,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmac32",    0xee100540, 7,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmsc32",    0xee100560, 7,  ARM_EXT_MAVERICK, do_c_triple_5},
!   {"cfmadd32",   0xee000600, 8,  ARM_EXT_MAVERICK, do_c_quad_6},
!   {"cfmsub32",   0xee100600, 8,  ARM_EXT_MAVERICK, do_c_quad_6},
!   {"cfmadda32",  0xee200600, 9,  ARM_EXT_MAVERICK, do_c_quad_6},
!   {"cfmsuba32",  0xee300600, 9,  ARM_EXT_MAVERICK, do_c_quad_6},
  };
  
  /* Defines for various bits that we will want to toggle.  */
*************** static const struct asm_opcode insns[] =
*** 1070,1077 ****
  #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.  */
--- 1392,1400 ----
  #define LDM_TYPE_2_OR_3	0x00400000
  
  #define LITERAL_MASK	0xf000f000
  #define OPCODE_MASK	0xfe1fffff
+ #define V4_STR_BIT	0x00000020
+ 
  #define DATA_OP_SHIFT	21
  
  /* Codes to distinguish the arithmetic instructions.  */
*************** struct thumb_opcode
*** 1212,1218 ****
    int size;
  
    /* Which CPU variants this exists for.  */
!   unsigned long variants;
  
    /* Function to call to parse args.  */
    void (* parms) PARAMS ((char *));
--- 1535,1541 ----
    int size;
  
    /* Which CPU variants this exists for.  */
!   unsigned long variant;
  
    /* Function to call to parse args.  */
    void (* parms) PARAMS ((char *));
*************** cp_address_required_here (str)
*** 2393,2399 ****
  }
  
  static void
! do_nop (str, flags)
       char * str;
       unsigned long flags;
  {
--- 2716,2722 ----
  }
  
  static void
! do_empty (str, flags)
       char * str;
       unsigned long flags;
  {
*************** ld_mode_required_here (string)
*** 2780,2786 ****
  	  if (skip_past_comma (& str) == SUCCESS)
  	    {
  	      /* [Rn],... (post inc) */
! 	      if (ldst_extend (& str, 1) == FAIL)
  		return FAIL;
  	    }
  	  else 	      /* [Rn] */
--- 3103,3109 ----
  	  if (skip_past_comma (& str) == SUCCESS)
  	    {
  	      /* [Rn],... (post inc) */
! 	      if (ldst_extend_v4 (&str) == FAIL)
  		return FAIL;
  	    }
  	  else 	      /* [Rn] */
*************** ld_mode_required_here (string)
*** 2807,2813 ****
  
  	  pre_inc = 1;
  
! 	  if (ldst_extend (& str, 1) == FAIL)
  	    return FAIL;
  
  	  skip_whitespace (str);
--- 3130,3136 ----
  
  	  pre_inc = 1;
  
! 	  if (ldst_extend_v4 (&str) == FAIL)
  	    return FAIL;
  
  	  skip_whitespace (str);
*************** do_pld (str, flags)
*** 3630,3636 ****
        return;
      }
  
!   ++ str;
    skip_whitespace (str);
  
    if ((rd = reg_required_here (& str, 16)) == FAIL)
--- 3953,3959 ----
        return;
      }
  
!   ++str;
    skip_whitespace (str);
  
    if ((rd = reg_required_here (& str, 16)) == FAIL)
*************** do_pld (str, flags)
*** 3638,3658 ****
  
    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;
--- 3961,3983 ----
  
    skip_whitespace (str);
  
!   if (*str == ']')
      {
        /* [Rn], ... ?  */
!       ++str;
        skip_whitespace (str);
  
!       /* Post-indexed addressing is not allowed with PLD.  */
!       if (skip_past_comma (&str) == SUCCESS)
  	{
! 	  inst.error
! 	    = _("post-indexed expression used in preload instruction");
! 	  return;
  	}
!       else if (*str == '!') /* [Rn]! */
  	{
  	  inst.error = _("writeback used in preload instruction");
! 	  ++str;
  	}
        else /* [Rn] */
  	inst.instruction |= INDEX_UP | PRE_INDEX;
*************** do_pld (str, flags)
*** 3665,3671 ****
  	  return;
  	}
  
!       if (ldst_extend (& str, 0) == FAIL)
  	return;
  
        skip_whitespace (str);
--- 3990,3996 ----
  	  return;
  	}
  
!       if (ldst_extend (&str) == FAIL)
  	return;
  
        skip_whitespace (str);
*************** do_ldrd (str, flags)
*** 3705,3739 ****
    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)
--- 4030,4035 ----
*************** do_ldrd (str, flags)
*** 3757,3774 ****
        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);
  }
  
--- 4053,4080 ----
        return;
      }
  
!   if (rd == REG_LR)
      {
        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"));
  
+   /* For an index-register load, the index register must not overlap the
+      destination (even if not write-back).  */
+   if ((inst.instruction & V4_STR_BIT) == 0
+       && (inst.instruction & HWOFFSET_IMM) == 0)
+     {
+       int rm = inst.instruction & 0x0000000f;
+ 
+       if (rm == rd || (rm == rd + 1))
+ 	as_warn (_("ldrd destination registers must not overlap index register"));
+     }
+ 
    end_of_line (str);
  }
  
*************** do_adr (str, flags)
*** 4285,4391 ****
       char * str;
       unsigned long flags;
  {
    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;
!     }
  
!   if (flags & 0x00400000)
!     {
!       /* 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)"  */
!       /* 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 & ~0x00400000;
!       inst.size                    = INSN_SIZE * 2;
      }
    else
      {
!       /* 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".  */
!       /* 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_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;
  
--- 4591,5020 ----
       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;
+ 
+   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.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;
+   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)
+      char ** str;
+ {
+   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 (value < -4095 || value > 4095)
+ 	    {
+ 	      inst.error = _("address offset too large");
+ 	      return FAIL;
+ 	    }
+ 
+ 	  if (value < 0)
+ 	    {
+ 	      value = -value;
+ 	      add = 0;
+ 	    }
+ 
+ 	  inst.instruction |= add | value;
+ 	}
+       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;
+ 
+       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 pre_inc = 0;
+   int conflict_reg;
+   int value;
+ 
    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;
+     }
+ 
+   flags = 0;
+ 
+   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) == FAIL)
+ 		return;
+ 	      if (conflict_reg)
+ 		as_warn (_("%s register same as write-back base"),
+ 			 ((inst.instruction & LOAD_BIT)
+ 			  ? _("destination") : _("source")));
+ 	    }
+ 	  else
+ 	    {
+ 	      /* [Rn]  */
+ 	      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;
+ 		}
+ 
+ 	      inst.instruction |= INDEX_UP;
+ 	      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) == 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 |= (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.  */
! 	  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;
! 
!       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;
      }
  
+   inst.instruction |= (pre_inc ? PRE_INDEX : 0);
    end_of_line (str);
+   return;
  }
  
  static void
! do_ldstt (str, flags)
!      char *        str;
       unsigned long flags;
  {
+   int conflict_reg;
+ 
    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;
  
!       /* ldrt/strt always use post-indexed addressing, so if the base is
! 	 the same as Rd, we warn.  */
!       if (conflict_reg == reg)
! 	as_warn (_("%s register same as write-back base"),
! 		 ((inst.instruction & LOAD_BIT)
! 		  ? _("destination") : _("source")));
! 
!       skip_whitespace (str);
! 
!       if (*str == ']')
! 	{
! 	  str ++;
! 
! 	  if (skip_past_comma (&str) == SUCCESS)
! 	    {
! 	      /* [Rn],... (post inc)  */
! 	      if (ldst_extend (&str) == FAIL)
! 		return;
! 	    }
! 	  else
! 	    {
! 	      /* [Rn]  */
! 	      skip_whitespace (str);
! 
! 	      /* Skip a write-back '!'.  */
! 	      if (*str == '!')
! 		str++;
! 
! 	      inst.instruction |= INDEX_UP;
! 	    }
! 	}
!       else
! 	{
! 	  inst.error = _("post-indexed expression expected");
! 	  return;
! 	}
!     }
!   else
      {
!       inst.error = _("post-indexed expression expected");
        return;
      }
  
    end_of_line (str);
    return;
  }
  
  static int
! ldst_extend_v4 (str)
       char ** str;
  {
    int add = INDEX_UP;
  
*************** ldst_extend (str, hwse)
*** 4401,4408 ****
  	{
  	  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;
--- 5030,5036 ----
  	{
  	  int value = inst.reloc.exp.X_add_number;
  
! 	  if (value < -255 || value > 255)
  	    {
  	      inst.error = _("address offset too large");
  	      return FAIL;
*************** ldst_extend (str, hwse)
*** 4416,4436 ****
  
  	  /* 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;
--- 5044,5056 ----
  
  	  /* Halfword and signextension instructions have the
               immediate value split across bits 11..8 and bits 3..0.  */
! 	  inst.instruction |= (add | HWOFFSET_IMM
! 			       | ((value >> 4) << 8) | (value & 0xF));
  	}
        else
  	{
! 	  inst.instruction |= HWOFFSET_IMM;
! 	  inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
  	  inst.reloc.pc_rel = 0;
  	}
        return SUCCESS;
*************** ldst_extend (str, hwse)
*** 4446,4496 ****
      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_V4) == 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)
--- 5066,5087 ----
      default:
        if (reg_required_here (str, 0) == FAIL)
  	return FAIL;
  
+       inst.instruction |= add;
        return SUCCESS;
      }
  }
  
+ /* Halfword and signed-byte load/store operations.  */
  static void
! do_ldstv4 (str, flags)
       char *        str;
       unsigned long flags;
  {
    int pre_inc = 0;
    int conflict_reg;
    int value;
  
    skip_whitespace (str);
  
    if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
*************** do_ldst (str, flags)
*** 4529,4553 ****
  	  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);
  
--- 5120,5136 ----
  	  if (skip_past_comma (&str) == SUCCESS)
  	    {
  	      /* [Rn],... (post inc)  */
! 	      if (ldst_extend_v4 (&str) == FAIL)
  		return;
  	      if (conflict_reg)
! 		as_warn (_("%s register same as write-back base"),
! 			 ((inst.instruction & LOAD_BIT)
! 			  ? _("destination") : _("source")));
  	    }
  	  else
  	    {
  	      /* [Rn]  */
! 	      inst.instruction |= HWOFFSET_IMM;
  
  	      skip_whitespace (str);
  
*************** do_ldst (str, flags)
*** 4561,4576 ****
  		  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
--- 5144,5151 ----
  		  inst.instruction |= WRITE_BACK;
  		}
  
! 	      inst.instruction |= INDEX_UP;
! 	      pre_inc = 1;
  	    }
  	}
        else
*************** do_ldst (str, flags)
*** 4583,4589 ****
  	    }
  
  	  pre_inc = 1;
! 	  if (ldst_extend (&str, halfword) == FAIL)
  	    return;
  
  	  skip_whitespace (str);
--- 5158,5164 ----
  	    }
  
  	  pre_inc = 1;
! 	  if (ldst_extend_v4 (&str) == FAIL)
  	    return;
  
  	  skip_whitespace (str);
*************** do_ldst (str, flags)
*** 4609,4614 ****
--- 5184,5190 ----
      }
    else if (*str == '=')
      {
+       /* XXX Does this work correctly for half-word/byte ops?  */
        /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
        str++;
  
*************** do_ldst (str, flags)
*** 4633,4639 ****
  	      /* 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;
  	    }
--- 5209,5215 ----
  	      /* This can be done with a mov instruction.  */
  	      inst.instruction &= LITERAL_MASK;
  	      inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
! 	      inst.instruction |= value & 0xfff;
  	      end_of_line (str);
  	      return;
  	    }
*************** do_ldst (str, flags)
*** 4645,4651 ****
  	      /* This can be done with a mvn instruction.  */
  	      inst.instruction &= LITERAL_MASK;
  	      inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
! 	      inst.instruction |= (flags & COND_MASK) | (value & 0xfff);
  	      end_of_line (str);
  	      return;
  	    }
--- 5221,5227 ----
  	      /* This can be done with a mvn instruction.  */
  	      inst.instruction &= LITERAL_MASK;
  	      inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
! 	      inst.instruction |= value & 0xfff;
  	      end_of_line (str);
  	      return;
  	    }
*************** do_ldst (str, flags)
*** 4660,4673 ****
  	}
  
        /* 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;
--- 5236,5243 ----
  	}
  
        /* Change the instruction exp to point to the pool.  */
!       inst.instruction |= HWOFFSET_IMM;
!       inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
        inst.reloc.pc_rel = 1;
        inst.instruction |= (REG_PC << 16);
        pre_inc = 1;
*************** do_ldst (str, flags)
*** 4677,4689 ****
        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;
--- 5247,5254 ----
        if (my_get_expression (&inst.reloc.exp, &str))
  	return;
  
!       inst.instruction |= HWOFFSET_IMM;
!       inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
  #ifndef TE_WINCE
        /* PC rel adjust.  */
        inst.reloc.exp.X_add_number -= 8;
*************** do_ldst (str, flags)
*** 4693,4702 ****
        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;
  }
--- 5258,5264 ----
        pre_inc = 1;
      }
  
!   inst.instruction |= (pre_inc ? PRE_INDEX : 0);
    end_of_line (str);
    return;
  }
*************** do_ldmstm (str, flags)
*** 4851,4857 ****
  
    if (*str == '!')
      {
!       flags |= WRITE_BACK;
        str++;
      }
  
--- 5413,5419 ----
  
    if (*str == '!')
      {
!       inst.instruction |= WRITE_BACK;
        str++;
      }
  
*************** do_ldmstm (str, flags)
*** 4866,4872 ****
    if (*str == '^')
      {
        str++;
!       flags |= LDM_TYPE_2_OR_3;
      }
  
    inst.instruction |= flags | range;
--- 5428,5434 ----
    if (*str == '^')
      {
        str++;
!       inst.instruction |= LDM_TYPE_2_OR_3;
      }
  
    inst.instruction |= flags | range;
*************** do_fpa_ldst (str, flags)
*** 5223,5245 ****
  {
    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)
--- 5785,5790 ----
*************** do_fpa_ldmstm (str, flags)
*** 5314,5320 ****
        abort ();
      }
  
!   if (flags)
      {
        int reg;
        int write_back;
--- 5859,5865 ----
        abort ();
      }
  
!   if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ed/fd format.  */
      {
        int reg;
        int write_back;
*************** do_fpa_ldmstm (str, flags)
*** 5361,5386 ****
        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;
  	    }
  	}
--- 5906,5931 ----
        else
  	write_back = 0;
  
!       if (inst.instruction & CP_T_Pre)
  	{
  	  /* Pre-decrement.  */
  	  offset = 3 * num_regs;
  	  if (write_back)
! 	    inst.instruction |= CP_T_WB;
  	}
        else
  	{
  	  /* Post-increment.  */
  	  if (write_back)
  	    {
! 	      inst.instruction |= CP_T_WB;
  	      offset = 3 * num_regs;
  	    }
  	  else
  	    {
  	      /* No write-back, so convert this into a standard pre-increment
  		 instruction -- aesthetically more pleasing.  */
! 	      inst.instruction |= CP_T_Pre | CP_T_UD;
  	      offset = 0;
  	    }
  	}
*************** do_fpa_dyadic (str, flags)
*** 5405,5424 ****
  {
    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)
--- 5950,5955 ----
*************** do_fpa_monadic (str, flags)
*** 5454,5473 ****
  {
    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)
--- 5985,5990 ----
*************** do_fpa_from_reg (str, flags)
*** 5522,5541 ****
  {
    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)
--- 6039,6044 ----
*************** set_constant_flonums ()
*** 7227,7232 ****
--- 7730,7783 ----
        abort ();
  }
  
+ /* Iterate over the base tables to create the instruction patterns.  */
+ static void
+ build_arm_ops_hsh ()
+ {
+   unsigned int i;
+   unsigned int j;
+   static struct obstack insn_obstack;
+ 
+   obstack_begin (&insn_obstack, 4000);
+ 
+   for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
+     {
+       CONST struct asm_opcode *insn = insns + i;
+ 
+       if (insn->cond_offset != 0)
+ 	{
+ 	  /* Insn supports conditional execution.  Build the varaints
+ 	     and insert them in the hash table.  */
+ 	  for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
+ 	    {
+ 	      unsigned len = strlen (insn->template);
+ 	      struct asm_opcode *new;
+ 	      char *template;
+ 
+ 	      new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
+ 	      /* All condition codes are two characters.  */
+ 	      template = obstack_alloc (&insn_obstack, len + 3);
+ 
+ 	      strncpy (template, insn->template, insn->cond_offset);
+ 	      strcpy (template + insn->cond_offset, conds[j].template);
+ 	      if (len > insn->cond_offset)
+ 		strcpy (template + insn->cond_offset + 2,
+ 			insn->template + insn->cond_offset);
+ 	      new->template = template;
+ 	      new->cond_offset = 0;
+ 	      new->variant = insn->variant;
+ 	      new->parms = insn->parms;
+ 	      new->value = (insn->value & ~COND_MASK) | conds[j].value;
+ 
+ 	      hash_insert (arm_ops_hsh, new->template, (PTR) new);
+ 	    }
+ 	}
+       /* Finally, insert the unconditional insn in the table directly;
+ 	 no need to build a copy.  */
+       hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
+     }
+ }
+ 
  void
  md_begin ()
  {
*************** md_begin ()
*** 7241,7248 ****
        || (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++)
--- 7792,7798 ----
        || (arm_psr_hsh = hash_new ()) == NULL)
      as_fatal (_("Virtual memory exhausted"));
  
!   build_arm_ops_hsh ();
    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++)
*************** md_assemble (str)
*** 8441,8447 ****
        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;
--- 8991,8997 ----
        if (opcode)
  	{
  	  /* Check that this instruction is supported for this CPU.  */
! 	  if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
  	    {
  	      as_bad (_("selected processor does not support this opcode"));
  	      return;
*************** md_assemble (str)
*** 8457,8612 ****
    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:
! 	  ;
  	}
      }
  
--- 9007,9032 ----
    else
      {
        const struct asm_opcode * opcode;
  
!       c = *p;
!       *p = '\0';
!       opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
!       *p = c;
  
!       if (opcode)
  	{
! 	  /* Check that this instruction is supported for this CPU.  */
! 	  if ((opcode->variant & cpu_variant) == 0)
  	    {
! 	      as_bad (_("selected processor does not support this opcode"));
  	      return;
  	    }
  
! 	  inst.instruction = opcode->value;
! 	  inst.size = INSN_SIZE;
! 	  (*opcode->parms) (p, 0);
! 	  output_inst ();
! 	  return;
  	}
      }
  
Index: testsuite/gas/arm/xscale.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/xscale.d,v
retrieving revision 1.3
diff -p -r1.3 xscale.d
*** xscale.d	2001/05/24 20:02:15	1.3
--- xscale.d	2001/12/05 10:05:54
*************** Disassembly of section .text:
*** 23,38 ****
  0+34 <[^>]*> f5d1f789 	pld	\[r1, #1929\]
  0+38 <[^>]*> f7d2f003 	pld	\[r2, r3\]
  0+3c <[^>]*> f754f285 	pld	\[r4, -r5, lsl #5\]
! 0+40 <[^>]*> f456f456 	pld	\[r6\], -#1110
! 0+44 <[^>]*> f6d7f008 	pld	\[r7\], r8
! 0+48 <[^>]*> f659f06a 	pld	\[r9\], -sl, rrx
! 0+4c <[^>]*> e1c100d0 	ldrd	r0, \[r1\]
! 0+50 <[^>]*> 01c327d8 	ldreqd	r2, \[r3, #120\]
! 0+54 <[^>]*> b10540d6 	ldrltd	r4, \[r5, -r6\]
! 0+58 <[^>]*> e16a88f9 	strd	r8, \[sl, -#137\]!
! 0+5c <[^>]*> e1ac00fd 	strd	r0, \[ip, sp\]!
! 0+60 <[^>]*> 30ce21f0 	strccd	r2, \[lr\], #16
! 0+64 <[^>]*> 708640f8 	strvcd	r4, \[r6\], r8
! 0+68 <[^>]*> e5910000 	ldr	r0, \[r1\]
! 0+6c <[^>]*> e5832000 	str	r2, \[r3\]
! 0+70 <[^>]*> e321f011 	msr	CPSR_c, #17	; 0x11
--- 23,35 ----
  0+34 <[^>]*> f5d1f789 	pld	\[r1, #1929\]
  0+38 <[^>]*> f7d2f003 	pld	\[r2, r3\]
  0+3c <[^>]*> f754f285 	pld	\[r4, -r5, lsl #5\]
! 0+40 <[^>]*> e1c100d0 	ldrd	r0, \[r1\]
! 0+44 <[^>]*> 01c327d8 	ldreqd	r2, \[r3, #120\]
! 0+48 <[^>]*> b10540d6 	ldrltd	r4, \[r5, -r6\]
! 0+4c <[^>]*> e16a88f9 	strd	r8, \[sl, -#137\]!
! 0+50 <[^>]*> e1ac00fd 	strd	r0, \[ip, sp\]!
! 0+54 <[^>]*> 30ce21f0 	strccd	r2, \[lr\], #16
! 0+58 <[^>]*> 708640f8 	strvcd	r4, \[r6\], r8
! 0+5c <[^>]*> e5910000 	ldr	r0, \[r1\]
! 0+60 <[^>]*> e5832000 	str	r2, \[r3\]
! 0+64 <[^>]*> e321f011 	msr	CPSR_c, #17	; 0x11
Index: testsuite/gas/arm/xscale.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/xscale.s,v
retrieving revision 1.1
diff -p -r1.1 xscale.s
*** xscale.s	2000/11/25 00:21:39	1.1
--- xscale.s	2001/12/05 10:05:54
*************** foo:
*** 22,30 ****
  	pld	[r1, #0x789]
  	pld	[r2, r3]
  	pld	[r4, -r5, lsl #5]
- 	pld	[r6], #-0x456
- 	pld	[r7], +r8
- 	pld	[r9], -r10, RRX
  
  	ldrd	r0, [r1]
  	ldreqd	r2, [r3, #0x78]
--- 22,27 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]