Add mangled names to addr2line -i output.
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
index a0804f3a05d54f5c7b94d2147a5b6c9fec2ca4d5..c11e149b45969039e8bc7f9c38fb1debca6bf9a1 100644 (file)
@@ -175,9 +175,6 @@ static int meabi_flags = EF_ARM_EABI_UNKNOWN;
 symbolS * GOT_symbol;
 #endif
 
-/* Size of relocation record.  */
-const int md_reloc_size = 8;
-
 /* 0: assemble for ARM,
    1: assemble for Thumb,
    2: assemble for Thumb even though target CPU does not support thumb
@@ -216,6 +213,9 @@ struct arm_it
   int          size;
   int          size_req;
   int          cond;
+  /* Set to the opcode if the instruction needs relaxation.
+     Zero if the instruction is not relaxed.  */
+  unsigned long        relax;
   struct
   {
     bfd_reloc_code_real_type type;
@@ -226,17 +226,17 @@ struct arm_it
   struct
   {
     unsigned reg;
-    unsigned imm;
-    unsigned present   : 1;  /* operand present */
-    unsigned isreg     : 1;  /* operand was a register */
-    unsigned immisreg  : 1;  /* .imm field is a second register */
-    unsigned hasreloc  : 1;  /* operand has relocation suffix */
-    unsigned writeback : 1;  /* operand has trailing ! */
-    unsigned preind    : 1;  /* preindexed address */
-    unsigned postind   : 1;  /* postindexed address */
-    unsigned negative  : 1;  /* index register was negated */
-    unsigned shifted   : 1;  /* shift applied to operation */
-    unsigned shift_kind : 3;  /* shift operation (enum shift_kind) */
+    signed int imm;
+    unsigned present   : 1;  /* Operand present.  */
+    unsigned isreg     : 1;  /* Operand was a register.  */
+    unsigned immisreg  : 1;  /* .imm field is a second register */
+    unsigned hasreloc  : 1;  /* Operand has relocation suffix.  */
+    unsigned writeback : 1;  /* Operand has trailing !  */
+    unsigned preind    : 1;  /* Preindexed address.  */
+    unsigned postind   : 1;  /* Postindexed address.  */
+    unsigned negative  : 1;  /* Index register was negated.  */
+    unsigned shifted   : 1;  /* Shift applied to operation.  */
+    unsigned shift_kind : 3;  /* Shift operation (enum shift_kind).  */
   } operands[6];
 };
 
@@ -485,7 +485,7 @@ struct asm_opcode
 #define T_OPCODE_PUSH  0xb400
 #define T_OPCODE_POP   0xbc00
 
-#define T_OPCODE_BRANCH 0xe7fe
+#define T_OPCODE_BRANCH 0xe000
 
 #define THUMB_SIZE     2       /* Size of thumb instruction.  */
 #define THUMB_PP_PC_LR 0x0100
@@ -535,6 +535,11 @@ typedef struct literal_pool
 
 /* Pointer to a linked list of literal pools.  */
 literal_pool * list_of_pools = NULL;
+
+/* State variables for IT block handling.  */
+static bfd_boolean current_it_mask = 0;
+static int current_cc;
+
 \f
 /* Pure syntax.         */
 
@@ -1035,7 +1040,7 @@ parse_reg_list (char ** strp)
    register.  Double precision registers are matched if DP is nonzero. */
 
 static int
-parse_vfp_reg_list (char **str, int *pbase, int dp)
+parse_vfp_reg_list (char **str, unsigned int *pbase, int dp)
 {
   int base_reg;
   int new_base;
@@ -1414,15 +1419,15 @@ find_real_start (symbolS * symbolP)
   if (name == NULL)
     abort ();
 
-  /* Names that start with '.' are local labels, not function entry points.
-     The compiler may generate BL instructions to these labels because it
-     needs to perform a branch to a far away location. */
-  if (name[0] == '.')
+  /* The compiler may generate BL instructions to local labels because
+     it needs to perform a branch to a far away location. These labels
+     do not have a corresponding ".real_start_of" label.  We check
+     both for S_IS_LOCAL and for a leading dot, to give a way to bypass
+     the ".real_start_of" convention for nonlocal branches.  */
+  if (S_IS_LOCAL (symbolP) || name[0] == '.')
     return symbolP;
 
-  real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
-  sprintf (real_start, "%s%s", STUB_NAME, name);
-
+  real_start = ACONCAT ((STUB_NAME, name, NULL));
   new_target = symbol_find (real_start);
 
   if (new_target == NULL)
@@ -1431,8 +1436,6 @@ find_real_start (symbolS * symbolP)
       new_target = symbolP;
     }
 
-  free (real_start);
-
   return new_target;
 }
 
@@ -1972,8 +1975,15 @@ s_arm_elf_cons (int nbytes)
              reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
              int size = bfd_get_reloc_size (howto);
 
+             if (reloc == BFD_RELOC_ARM_PLT32)
+               {
+                 as_bad (_("(plt) is only valid on branch targets"));
+                 reloc = BFD_RELOC_UNUSED;
+                 size = 0;
+               }
+
              if (size > nbytes)
-               as_bad ("%s relocations do not fit in %d bytes",
+               as_bad (_("%s relocations do not fit in %d bytes"),
                        howto->name, nbytes);
              else
                {
@@ -2330,7 +2340,7 @@ static void
 s_arm_unwind_save_vfp (void)
 {
   int count;
-  int reg;
+  unsigned int reg;
   valueT op;
 
   count = parse_vfp_reg_list (&input_line_pointer, &reg, 1);
@@ -3071,7 +3081,7 @@ parse_shift (char **str, int i, enum parse_shift_mode mode)
 
    where <shift> is defined by parse_shift above, and <rotate> is a
    multiple of 2 between 0 and 30.  Validation of immediate operands
-   is deferred to md_apply_fix3.  */
+   is deferred to md_apply_fix.  */
 
 static int
 parse_shifter_operand (char **str, int i)
@@ -3122,7 +3132,7 @@ parse_shifter_operand (char **str, int i)
          return FAIL;
        }
 
-      /* Convert to decoded value.  md_apply_fix3 will put it back.  */
+      /* Convert to decoded value.  md_apply_fix will put it back.  */
       inst.reloc.exp.X_add_number
        = (((inst.reloc.exp.X_add_number << (32 - value))
            | (inst.reloc.exp.X_add_number >> value)) & 0xffffffff);
@@ -3241,7 +3251,7 @@ parse_address (char **str, int i)
        {
          /* [Rn], {expr} - unindexed, with option */
          if (parse_immediate (&p, &inst.operands[i].imm,
-                                      0, 255, TRUE) == FAIL)
+                              0, 255, TRUE) == FAIL)
            return FAIL;
 
          if (skip_past_char (&p, '}') == FAIL)
@@ -3486,6 +3496,55 @@ parse_cond (char **str)
   return c->value;
 }
 
+/* Parse the operands of a table branch instruction.  Similar to a memory
+   operand.  */
+static int
+parse_tb (char **str)
+{
+  char * p = *str;
+  int reg;
+
+  if (skip_past_char (&p, '[') == FAIL)
+    return FAIL;
+
+  if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) == FAIL)
+    {
+      inst.error = _(reg_expected_msgs[REG_TYPE_RN]);
+      return FAIL;
+    }
+  inst.operands[0].reg = reg;
+
+  if (skip_past_comma (&p) == FAIL)
+    return FAIL;
+  
+  if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) == FAIL)
+    {
+      inst.error = _(reg_expected_msgs[REG_TYPE_RN]);
+      return FAIL;
+    }
+  inst.operands[0].imm = reg;
+
+  if (skip_past_comma (&p) == SUCCESS)
+    {
+      if (parse_shift (&p, 0, SHIFT_LSL_IMMEDIATE) == FAIL)
+       return FAIL;
+      if (inst.reloc.exp.X_add_number != 1)
+       {
+         inst.error = _("invalid shift");
+         return FAIL;
+       }
+      inst.operands[0].shifted = 1;
+    }
+
+  if (skip_past_char (&p, ']') == FAIL)
+    {
+      inst.error = _("']' expected");
+      return FAIL;
+    }
+  *str = p;
+  return SUCCESS;
+}
+
 /* Matcher codes for parse_operands.  */
 enum operand_parse_code
 {
@@ -3541,6 +3600,7 @@ enum operand_parse_code
   OP_ENDI,     /* Endianness specifier */
   OP_PSR,      /* CPSR/SPSR mask for msr */
   OP_COND,     /* conditional code */
+  OP_TB,       /* Table branch.  */
 
   OP_RRnpc_I0, /* ARM register or literal 0 */
   OP_RR_EXr,   /* ARM register or expression with opt. reloc suff. */
@@ -3569,7 +3629,7 @@ enum operand_parse_code
    structure.  Returns SUCCESS or FAIL depending on whether the
    specified grammar matched.  */
 static int
-parse_operands (char *str, const char *pattern)
+parse_operands (char *str, const unsigned char *pattern)
 {
   unsigned const char *upat = pattern;
   char *backtrack_pos = 0;
@@ -3782,6 +3842,10 @@ parse_operands (char *str, const char *pattern)
        case OP_PSR:     val = parse_psr (&str);                break;
        case OP_COND:    val = parse_cond (&str);               break;
 
+       case OP_TB:
+         po_misc_or_fail (parse_tb (&str));
+         break;
+
          /* Register lists */
        case OP_REGLST:
          val = parse_reg_list (&str);
@@ -3930,14 +3994,14 @@ encode_thumb32_immediate (unsigned int val)
 {
   unsigned int a, i;
 
-  if (val <= 255)
+  if (val <= 0xff)
     return val;
 
-  for (i = 0; i < 32; i++)
+  for (i = 1; i <= 24; i++)
     {
-      a = rotate_left (val, i);
-      if (a >= 128 && a <= 255)
-       return (a & 0x7f) | (i << 7);
+      a = val >> i;
+      if ((val & ~(0xff << i)) == 0)
+       return ((val >> i) & 0x7f) | ((32 - i) << 7);
     }
 
   a = val & 0xff;
@@ -3977,7 +4041,7 @@ encode_arm_vfp_sp_reg (int reg, enum vfp_sp_reg_pos pos)
 }
 
 /* Encode a <shift> in an ARM-format instruction.  The immediate,
-   if any, is handled by md_apply_fix3.         */
+   if any, is handled by md_apply_fix.  */
 static void
 encode_arm_shift (int i)
 {
@@ -4077,8 +4141,6 @@ encode_arm_addr_mode_2 (int i, bfd_boolean is_t)
     {
       if (inst.reloc.type == BFD_RELOC_UNUSED)
        inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
-      if (inst.reloc.pc_rel)
-       inst.reloc.exp.X_add_number -= 8;  /* pipeline offset */
     }
 }
 
@@ -4109,8 +4171,6 @@ encode_arm_addr_mode_3 (int i, bfd_boolean is_t)
       inst.instruction |= HWOFFSET_IMM;
       if (inst.reloc.type == BFD_RELOC_UNUSED)
        inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
-      if (inst.reloc.pc_rel)
-       inst.reloc.exp.X_add_number -= 8;  /* pipeline offset */
     }
 }
 
@@ -4161,10 +4221,10 @@ encode_arm_cp_address (int i, int wb_ok, int unind_ok, int reloc_override)
 
   if (reloc_override)
     inst.reloc.type = reloc_override;
+  else if (thumb_mode)
+    inst.reloc.type = BFD_RELOC_ARM_T32_CP_OFF_IMM;
   else
     inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
-  if (inst.reloc.pc_rel)
-    inst.reloc.exp.X_add_number -= 8;
   return SUCCESS;
 }
 
@@ -4282,9 +4342,14 @@ do_rn_rd (void)
 static void
 do_rd_rm_rn (void)
 {
+  unsigned Rn = inst.operands[2].reg;
+  /* Enforce resutrictions on SWP instruction.  */
+  if ((inst.instruction & 0x0fbfffff) == 0x01000090)
+    constraint (Rn == inst.operands[0].reg || Rn == inst.operands[1].reg,
+               _("Rn must not overlap other operands"));
   inst.instruction |= inst.operands[0].reg << 12;
   inst.instruction |= inst.operands[1].reg;
-  inst.instruction |= inst.operands[2].reg << 16;
+  inst.instruction |= Rn << 16;
 }
 
 static void
@@ -4331,10 +4396,8 @@ do_adr (void)
   /* Frag hacking will turn this into a sub instruction if the offset turns
      out to be negative.  */
   inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
-#ifndef TE_WINCE
-  inst.reloc.exp.X_add_number -= 8; /* PC relative adjust.  */
-#endif
   inst.reloc.pc_rel = 1;
+  inst.reloc.exp.X_add_number -= 8;
 }
 
 /* This is a pseudo-op of the form "adrl rd, label" to be converted
@@ -4350,11 +4413,9 @@ do_adrl (void)
   /* 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;
-#ifndef TE_WINCE
-  inst.reloc.exp.X_add_number -= 8; /* PC relative adjust  */
-#endif
   inst.reloc.pc_rel           = 1;
   inst.size                   = INSN_SIZE * 2;
+  inst.reloc.exp.X_add_number -= 8;
 }
 
 static void
@@ -4434,13 +4495,12 @@ encode_branch (int default_reloc)
       constraint (inst.operands[0].imm != BFD_RELOC_ARM_PLT32,
                  _("the only suffix valid here is '(plt)'"));
       inst.reloc.type  = BFD_RELOC_ARM_PLT32;
-      inst.reloc.pc_rel = 0;
     }
   else
     {
       inst.reloc.type = default_reloc;
-      inst.reloc.pc_rel = 1;
     }
+  inst.reloc.pc_rel = 1;
 }
 
 static void
@@ -4474,7 +4534,7 @@ do_blx (void)
       /* Arg is an address; this instruction cannot be executed
         conditionally, and the opcode must be adjusted.  */
       constraint (inst.cond != COND_ALWAYS, BAD_COND);
-      inst.instruction = 0xfafffffe;
+      inst.instruction = 0xfa000000;
       encode_branch (BFD_RELOC_ARM_PCREL_BLX);
     }
 }
@@ -4651,8 +4711,8 @@ do_ldrd (void)
       /* For an index-register load, the index register must not overlap the
         destination (even if not write-back).  */
       else if (inst.operands[2].immisreg
-              && (inst.operands[2].imm == inst.operands[0].reg
-                  || inst.operands[2].imm == inst.operands[1].reg))
+              && ((unsigned) inst.operands[2].imm == inst.operands[0].reg
+                  || (unsigned) inst.operands[2].imm == inst.operands[1].reg))
        as_warn (_("index register overlaps destination register"));
     }
 
@@ -5035,9 +5095,9 @@ do_shift (void)
 }
 
 static void
-do_smi (void)
+do_smc (void)
 {
-  inst.reloc.type = BFD_RELOC_ARM_SMI;
+  inst.reloc.type = BFD_RELOC_ARM_SMC;
   inst.reloc.pc_rel = 0;
 }
 
@@ -5445,9 +5505,14 @@ do_iwmmxt_wmov (void)
 static void
 do_iwmmxt_wldstbh (void)
 {
+  int reloc;
   inst.instruction |= inst.operands[0].reg << 12;
   inst.reloc.exp.X_add_number *= 4;
-  encode_arm_cp_address (1, TRUE, FALSE, BFD_RELOC_ARM_CP_OFF_IMM_S2);
+  if (thumb_mode)
+    reloc = BFD_RELOC_ARM_T32_CP_OFF_IMM_S2;
+  else
+    reloc = BFD_RELOC_ARM_CP_OFF_IMM_S2;
+  encode_arm_cp_address (1, TRUE, FALSE, reloc);
 }
 
 static void
@@ -5468,7 +5533,7 @@ static void
 do_iwmmxt_wldstd (void)
 {
   inst.instruction |= inst.operands[0].reg << 12;
-  encode_arm_cp_address (1, TRUE, FALSE, BFD_RELOC_ARM_CP_OFF_IMM_S2);
+  encode_arm_cp_address (1, TRUE, FALSE, 0);
 }
 
 static void
@@ -5589,6 +5654,8 @@ encode_thumb32_shifted_operand (int i)
   unsigned int value = inst.reloc.exp.X_add_number;
   unsigned int shift = inst.operands[i].shift_kind;
 
+  constraint (inst.operands[i].immisreg,
+             _("shift by register not allowed in thumb mode"));
   inst.instruction |= inst.operands[i].reg;
   if (shift == SHIFT_RRX)
     inst.instruction |= SHIFT_ROR << 4;
@@ -5647,9 +5714,10 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
        {
          constraint (inst.reloc.exp.X_op != O_constant,
                      _("expression too complex"));
-         constraint (inst.reloc.exp.X_add_number < 0 || inst.reloc.exp.X_add_number > 3,
+         constraint (inst.reloc.exp.X_add_number < 0
+                     || inst.reloc.exp.X_add_number > 3,
                      _("shift out of range"));
-         inst.instruction |= inst.reloc.exp.X_op << 4;
+         inst.instruction |= inst.reloc.exp.X_add_number << 4;
        }
       inst.reloc.type = BFD_RELOC_UNUSED;
     }
@@ -5673,7 +5741,6 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
            inst.instruction |= 0x00000100;
        }
       inst.reloc.type = BFD_RELOC_ARM_T32_OFFSET_IMM;
-      inst.reloc.pc_rel = is_pc;
     }
   else if (inst.operands[i].postind)
     {
@@ -5695,16 +5762,24 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
    encodings (the latter only in post-V6T2 cores).  The index is the
    value used in the insns table below.  When there is more than one
    possible 16-bit encoding for the instruction, this table always
-   holds variant (1).  */
+   holds variant (1).
+   Also contains several pseudo-instructions used during relaxation.  */
 #define T16_32_TAB                             \
   X(adc,   4140, eb400000),                    \
   X(adcs,  4140, eb500000),                    \
   X(add,   1c00, eb000000),                    \
   X(adds,  1c00, eb100000),                    \
+  X(addi,  0000, f1000000),                    \
+  X(addis, 0000, f1100000),                    \
+  X(add_pc,000f, f20f0000),                    \
+  X(add_sp,000d, f10d0000),                    \
+  X(adr,   000f, f20f0000),                    \
   X(and,   4000, ea000000),                    \
   X(ands,  4000, ea100000),                    \
   X(asr,   1000, fa40f000),                    \
   X(asrs,  1000, fa50f000),                    \
+  X(b,     e000, f000b000),                    \
+  X(bcond, d000, f0008000),                    \
   X(bic,   4380, ea200000),                    \
   X(bics,  4380, ea300000),                    \
   X(cmn,   42c0, eb100f00),                    \
@@ -5712,14 +5787,19 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
   X(cpsie, b660, f3af8400),                    \
   X(cpsid, b670, f3af8600),                    \
   X(cpy,   4600, ea4f0000),                    \
+  X(dec_sp,80dd, f1bd0d00),                    \
   X(eor,   4040, ea800000),                    \
   X(eors,  4040, ea900000),                    \
+  X(inc_sp,00dd, f10d0d00),                    \
   X(ldmia, c800, e8900000),                    \
   X(ldr,   6800, f8500000),                    \
   X(ldrb,  7800, f8100000),                    \
   X(ldrh,  8800, f8300000),                    \
   X(ldrsb, 5600, f9100000),                    \
   X(ldrsh, 5e00, f9300000),                    \
+  X(ldr_pc,4800, f85f0000),                    \
+  X(ldr_pc2,4800, f85f0000),                   \
+  X(ldr_sp,9800, f85d0000),                    \
   X(lsl,   0000, fa00f000),                    \
   X(lsls,  0000, fa10f000),                    \
   X(lsr,   0800, fa20f000),                    \
@@ -5734,8 +5814,8 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
   X(negs,  4240, f1d00000), /* rsbs #0 */      \
   X(orr,   4300, ea400000),                    \
   X(orrs,  4300, ea500000),                    \
-  X(pop,   bc00, e8ad0000), /* ldmia sp!,... */        \
-  X(push,  b400, e8bd0000), /* stmia sp!,... */        \
+  X(pop,   bc00, e8bd0000), /* ldmia sp!,... */        \
+  X(push,  b400, e92d0000), /* stmdb sp!,... */        \
   X(rev,   ba00, fa90f080),                    \
   X(rev16, ba40, fa90f090),                    \
   X(revsh, bac0, fa90f0b0),                    \
@@ -5747,8 +5827,11 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
   X(str,   6000, f8400000),                    \
   X(strb,  7000, f8000000),                    \
   X(strh,  8000, f8200000),                    \
+  X(str_sp,9000, f84d0000),                    \
   X(sub,   1e00, eba00000),                    \
   X(subs,  1e00, ebb00000),                    \
+  X(subi,  8000, f1a00000),                    \
+  X(subis, 8000, f1b00000),                    \
   X(sxtb,  b240, fa4ff080),                    \
   X(sxth,  b200, fa0ff080),                    \
   X(tst,   4200, ea100f00),                    \
@@ -5781,6 +5864,20 @@ static const unsigned int thumb_op32[] = { T16_32_TAB };
 
 /* Thumb instruction encoders, in alphabetical order.  */
 
+/* ADDW or SUBW.  */
+static void
+do_t_add_sub_w (void)
+{
+  int Rd, Rn;
+
+  Rd = inst.operands[0].reg;
+  Rn = inst.operands[1].reg;
+
+  constraint (Rd == 15, _("PC not allowed as destination"));
+  inst.instruction |= (Rn << 16) | (Rd << 8);
+  inst.reloc.type = BFD_RELOC_ARM_T32_IMM12;
+}
+
 /* Parse an add or subtract instruction.  We get here with inst.instruction
    equalling any of THUMB_OPCODE_add, adds, sub, or subs.  */
 
@@ -5796,15 +5893,61 @@ do_t_add_sub (void)
 
   if (unified_syntax)
     {
+      bfd_boolean flags;
+      bfd_boolean narrow;
+      int opcode;
+
+      flags = (inst.instruction == T_MNEM_adds
+              || inst.instruction == T_MNEM_subs);
+      if (flags)
+       narrow = (current_it_mask == 0);
+      else
+       narrow = (current_it_mask != 0);
       if (!inst.operands[2].isreg)
        {
-         /* For an immediate, we always generate a 32-bit opcode;
-            section relaxation will shrink it later if possible.  */
-         inst.instruction = THUMB_OP32 (inst.instruction);
-         inst.instruction = (inst.instruction & 0xe1ffffff) | 0x10000000;
-         inst.instruction |= inst.operands[0].reg << 8;
-         inst.instruction |= inst.operands[1].reg << 16;
-         inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE;
+         opcode = 0;
+         if (inst.size_req != 4)
+           {
+             int add;
+
+             add = (inst.instruction == T_MNEM_add
+                    || inst.instruction == T_MNEM_adds);
+             /* Attempt to use a narrow opcode, with relaxation if
+                appropriate.  */
+             if (Rd == REG_SP && Rs == REG_SP && !flags)
+               opcode = add ? T_MNEM_inc_sp : T_MNEM_dec_sp;
+             else if (Rd <= 7 && Rs == REG_SP && add && !flags)
+               opcode = T_MNEM_add_sp;
+             else if (Rd <= 7 && Rs == REG_PC && add && !flags)
+               opcode = T_MNEM_add_pc;
+             else if (Rd <= 7 && Rs <= 7 && narrow)
+               {
+                 if (flags)
+                   opcode = add ? T_MNEM_addis : T_MNEM_subis;
+                 else
+                   opcode = add ? T_MNEM_addi : T_MNEM_subi;
+               }
+             if (opcode)
+               {
+                 inst.instruction = THUMB_OP16(opcode);
+                 inst.instruction |= (Rd << 4) | Rs;
+                 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
+                 if (inst.size_req != 2)
+                   inst.relax = opcode;
+               }
+             else
+               constraint (inst.size_req == 2, BAD_HIREG);
+           }
+         if (inst.size_req == 4
+             || (inst.size_req != 2 && !opcode))
+           {
+             /* ??? Convert large immediates to addw/subw.  */
+             inst.instruction = THUMB_OP32 (inst.instruction);
+             inst.instruction = (inst.instruction & 0xe1ffffff) | 0x10000000;
+             inst.instruction |= inst.operands[0].reg << 8;
+             inst.instruction |= inst.operands[1].reg << 16;
+             inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE;
+           }
        }
       else
        {
@@ -5812,11 +5955,13 @@ do_t_add_sub (void)
          /* See if we can do this with a 16-bit instruction.  */
          if (!inst.operands[2].shifted && inst.size_req != 4)
            {
-             if (Rd <= 7 && Rn <= 7 && Rn <= 7
-                 && (inst.instruction == T_MNEM_adds
-                     || inst.instruction == T_MNEM_subs))
+             if (Rd > 7 || Rs > 7 || Rn > 7)
+               narrow = FALSE;
+
+             if (narrow)
                {
-                 inst.instruction = (inst.instruction == T_MNEM_adds
+                 inst.instruction = ((inst.instruction == T_MNEM_adds
+                                      || inst.instruction == T_MNEM_add)
                                      ? T_OPCODE_ADD_R3
                                      : T_OPCODE_SUB_R3);
                  inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
@@ -5902,11 +6047,31 @@ do_t_add_sub (void)
 static void
 do_t_adr (void)
 {
-  inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
-  inst.reloc.exp.X_add_number -= 4; /* PC relative adjust.  */
-  inst.reloc.pc_rel = 1;
+  if (unified_syntax && inst.size_req == 0 && inst.operands[0].reg <= 7)
+    {
+      /* Defer to section relaxation.  */
+      inst.relax = inst.instruction;
+      inst.instruction = THUMB_OP16 (inst.instruction);
+      inst.instruction |= inst.operands[0].reg << 4;
+    }
+  else if (unified_syntax && inst.size_req != 2)
+    {
+      /* Generate a 32-bit opcode.  */
+      inst.instruction = THUMB_OP32 (inst.instruction);
+      inst.instruction |= inst.operands[0].reg << 8;
+      inst.reloc.type = BFD_RELOC_ARM_T32_ADD_PC12;
+      inst.reloc.pc_rel = 1;
+    }
+  else
+    {
+      /* Generate a 16-bit opcode.  */
+      inst.instruction = THUMB_OP16 (inst.instruction);
+      inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
+      inst.reloc.exp.X_add_number -= 4; /* PC relative adjust.  */
+      inst.reloc.pc_rel = 1;
 
-  inst.instruction |= inst.operands[0].reg << 4;
+      inst.instruction |= inst.operands[0].reg << 4;
+    }
 }
 
 /* Arithmetic instructions for which there is just one 16-bit
@@ -5940,10 +6105,22 @@ do_t_arit3 (void)
        }
       else
        {
+         bfd_boolean narrow;
+
          /* See if we can do this with a 16-bit instruction.  */
-         if (THUMB_SETS_FLAGS (inst.instruction)
-             && !inst.operands[2].shifted
-             && inst.size_req != 4
+         if (THUMB_SETS_FLAGS (inst.instruction))
+           narrow = current_it_mask == 0;
+         else
+           narrow = current_it_mask != 0;
+
+         if (Rd > 7 || Rn > 7 || Rs > 7)
+           narrow = FALSE;
+         if (inst.operands[2].shifted)
+           narrow = FALSE;
+         if (inst.size_req == 4)
+           narrow = FALSE;
+
+         if (narrow
              && Rd == Rs)
            {
              inst.instruction = THUMB_OP16 (inst.instruction);
@@ -6011,10 +6188,22 @@ do_t_arit3c (void)
        }
       else
        {
+         bfd_boolean narrow;
+
          /* See if we can do this with a 16-bit instruction.  */
-         if (THUMB_SETS_FLAGS (inst.instruction)
-             && !inst.operands[2].shifted
-             && inst.size_req != 4)
+         if (THUMB_SETS_FLAGS (inst.instruction))
+           narrow = current_it_mask == 0;
+         else
+           narrow = current_it_mask != 0;
+
+         if (Rd > 7 || Rn > 7 || Rs > 7)
+           narrow = FALSE;
+         if (inst.operands[2].shifted)
+           narrow = FALSE;
+         if (inst.size_req == 4)
+           narrow = FALSE;
+
+         if (narrow)
            {
              if (Rd == Rs)
                {
@@ -6130,7 +6319,7 @@ do_t_blx (void)
   else
     {
       /* No register.  This must be BLX(1).  */
-      inst.instruction = 0xf7ffeffe;
+      inst.instruction = 0xf000e800;
       inst.reloc.type  = BFD_RELOC_THUMB_PCREL_BLX;
       inst.reloc.pc_rel = 1;
     }
@@ -6139,29 +6328,37 @@ do_t_blx (void)
 static void
 do_t_branch (void)
 {
-  if (unified_syntax && inst.size_req != 2)
+  int opcode;
+  if (inst.cond != COND_ALWAYS)
+    opcode = T_MNEM_bcond;
+  else
+    opcode = inst.instruction;
+
+  if (unified_syntax && inst.size_req == 4)
     {
+      inst.instruction = THUMB_OP32(opcode);
       if (inst.cond == COND_ALWAYS)
-       {
-         inst.instruction = 0xf7ffbffe;
-         inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH25;
-       }
+       inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH25;
       else
        {
          assert (inst.cond != 0xF);
-         inst.instruction = (inst.cond << 22) | 0xf43faffe;
+         inst.instruction |= inst.cond << 22;
          inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH20;
        }
     }
   else
     {
+      inst.instruction = THUMB_OP16(opcode);
       if (inst.cond == COND_ALWAYS)
        inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
       else
        {
-         inst.instruction = 0xd0fe | (inst.cond << 8);
+         inst.instruction |= inst.cond << 8;
          inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
        }
+      /* Allow section relaxation.  */
+      if (unified_syntax && inst.size_req != 2)
+       inst.relax = opcode;
     }
 
   inst.reloc.pc_rel = 1;
@@ -6285,21 +6482,26 @@ static void
 do_t_it (void)
 {
   unsigned int cond = inst.operands[0].imm;
+
+  current_it_mask = (inst.instruction & 0xf) | 0x10;
+  current_cc = cond;
+
+  /* If the condition is a negative condition, invert the mask.  */
   if ((cond & 0x1) == 0x0)
     {
       unsigned int mask = inst.instruction & 0x000f;
-      inst.instruction &= 0xfff0;
 
       if ((mask & 0x7) == 0)
        /* no conversion needed */;
       else if ((mask & 0x3) == 0)
-       mask = (~(mask & 0x8) & 0x8) | 0x4;
-      else if ((mask & 1) == 0)
-       mask = (~(mask & 0xC) & 0xC) | 0x2;
+       mask ^= 0x8;
+      else if ((mask & 0x1) == 0)
+       mask ^= 0xC;
       else
-       mask = (~(mask & 0xE) & 0xE) | 0x1;
+       mask ^= 0xE;
 
-      inst.instruction |= (mask & 0xF);
+      inst.instruction &= 0xfff0;
+      inst.instruction |= mask;
     }
 
   inst.instruction |= cond << 4;
@@ -6430,21 +6632,67 @@ do_t_ldrexd (void)
 static void
 do_t_ldst (void)
 {
+  unsigned long opcode;
+  int Rn;
+
+  opcode = inst.instruction;
   if (unified_syntax)
     {
-      /* Generation of 16-bit instructions for anything other than
-        Rd, [Rn, Ri] is deferred to section relaxation time.  */
-      if (inst.operands[1].isreg && inst.operands[1].immisreg
+      if (inst.operands[1].isreg
+         && !inst.operands[1].writeback
          && !inst.operands[1].shifted && !inst.operands[1].postind
          && !inst.operands[1].negative && inst.operands[0].reg <= 7
-         && inst.operands[1].reg <= 7 && inst.operands[1].imm <= 7
-         && inst.instruction <= 0xffff)
+         && opcode <= 0xffff
+         && inst.size_req != 4)
        {
-         inst.instruction = THUMB_OP16 (inst.instruction);
-         goto op16;
+         /* Insn may have a 16-bit form.  */
+         Rn = inst.operands[1].reg;
+         if (inst.operands[1].immisreg)
+           {
+             inst.instruction = THUMB_OP16 (opcode);
+             /* [Rn, Ri] */
+             if (Rn <= 7 && inst.operands[1].imm <= 7)
+               goto op16;
+           }
+         else if ((Rn <= 7 && opcode != T_MNEM_ldrsh
+                   && opcode != T_MNEM_ldrsb)
+                  || ((Rn == REG_PC || Rn == REG_SP) && opcode == T_MNEM_ldr)
+                  || (Rn == REG_SP && opcode == T_MNEM_str))
+           {
+             /* [Rn, #const] */
+             if (Rn > 7)
+               {
+                 if (Rn == REG_PC)
+                   {
+                     if (inst.reloc.pc_rel)
+                       opcode = T_MNEM_ldr_pc2;
+                     else
+                       opcode = T_MNEM_ldr_pc;
+                   }
+                 else
+                   {
+                     if (opcode == T_MNEM_ldr)
+                       opcode = T_MNEM_ldr_sp;
+                     else
+                       opcode = T_MNEM_str_sp;
+                   }
+                 inst.instruction = inst.operands[0].reg << 8;
+               }
+             else
+               {
+                 inst.instruction = inst.operands[0].reg;
+                 inst.instruction |= inst.operands[1].reg << 3;
+               }
+             inst.instruction |= THUMB_OP16 (opcode);
+             if (inst.size_req == 2)
+               inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
+             else
+               inst.relax = opcode;
+             return;
+           }
        }
-
-      inst.instruction = THUMB_OP32 (inst.instruction);
+      /* Definitely a 32-bit variant.  */
+      inst.instruction = THUMB_OP32 (opcode);
       inst.instruction |= inst.operands[0].reg << 12;
       encode_thumb32_addr_mode (1, /*is_t=*/FALSE, /*is_d=*/FALSE);
       return;
@@ -6576,19 +6824,43 @@ do_t_mov_cmp (void)
     {
       int r0off = (inst.instruction == T_MNEM_mov
                   || inst.instruction == T_MNEM_movs) ? 8 : 16;
+      unsigned long opcode;
+      bfd_boolean narrow;
+      bfd_boolean low_regs;
+
+      low_regs = (inst.operands[0].reg <= 7 && inst.operands[1].reg <= 7);
+      opcode = inst.instruction;
+      if (current_it_mask)
+       narrow = opcode != T_MNEM_movs;
+      else
+       narrow = opcode != T_MNEM_movs || low_regs;
+      if (inst.size_req == 4
+         || inst.operands[1].shifted)
+       narrow = FALSE;
+
       if (!inst.operands[1].isreg)
        {
-         /* For an immediate, we always generate a 32-bit opcode;
-            section relaxation will shrink it later if possible.  */
-         inst.instruction = THUMB_OP32 (inst.instruction);
-         inst.instruction = (inst.instruction & 0xe1ffffff) | 0x10000000;
-         inst.instruction |= inst.operands[0].reg << r0off;
-         inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE;
+         /* Immediate operand.  */
+         if (current_it_mask == 0 && opcode == T_MNEM_mov)
+           narrow = 0;
+         if (low_regs && narrow)
+           {
+             inst.instruction = THUMB_OP16 (opcode);
+             inst.instruction |= inst.operands[0].reg << 8;
+             if (inst.size_req == 2)
+               inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
+             else
+               inst.relax = opcode;
+           }
+         else
+           {
+             inst.instruction = THUMB_OP32 (inst.instruction);
+             inst.instruction = (inst.instruction & 0xe1ffffff) | 0x10000000;
+             inst.instruction |= inst.operands[0].reg << r0off;
+             inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE;
+           }
        }
-      else if (inst.size_req == 4
-              || inst.operands[1].shifted
-              || (inst.instruction == T_MNEM_movs
-                  && (inst.operands[0].reg > 7 || inst.operands[1].reg > 7)))
+      else if (!narrow)
        {
          inst.instruction = THUMB_OP32 (inst.instruction);
          inst.instruction |= inst.operands[0].reg << r0off;
@@ -6613,7 +6885,7 @@ do_t_mov_cmp (void)
            break;
 
          case T_MNEM_cmp:
-           if (inst.operands[0].reg <= 7 && inst.operands[1].reg <= 7)
+           if (low_regs)
              {
                inst.instruction = T_OPCODE_CMP_LR;
                inst.instruction |= inst.operands[0].reg;
@@ -6681,6 +6953,20 @@ do_t_mvn_tst (void)
     {
       int r0off = (inst.instruction == T_MNEM_mvn
                   || inst.instruction == T_MNEM_mvns) ? 8 : 16;
+      bfd_boolean narrow;
+
+      if (inst.size_req == 4
+         || inst.instruction > 0xffff
+         || inst.operands[1].shifted
+         || inst.operands[0].reg > 7 || inst.operands[1].reg > 7)
+       narrow = FALSE;
+      else if (inst.instruction == T_MNEM_cmn)
+       narrow = TRUE;
+      else if (THUMB_SETS_FLAGS (inst.instruction))
+       narrow = (current_it_mask == 0);
+      else
+       narrow = (current_it_mask != 0);
+
       if (!inst.operands[1].isreg)
        {
          /* For an immediate, we always generate a 32-bit opcode;
@@ -6694,12 +6980,7 @@ do_t_mvn_tst (void)
       else
        {
          /* See if we can do this with a 16-bit instruction.  */
-         if (inst.instruction < 0xffff
-             && THUMB_SETS_FLAGS (inst.instruction)
-             && !inst.operands[1].shifted
-             && inst.operands[0].reg <= 7
-             && inst.operands[1].reg <= 7
-             && inst.size_req != 4)
+         if (narrow)
            {
              inst.instruction = THUMB_OP16 (inst.instruction);
              inst.instruction |= inst.operands[0].reg;
@@ -6827,9 +7108,18 @@ do_t_neg (void)
 {
   if (unified_syntax)
     {
-      if (inst.operands[0].reg > 7 || inst.operands[1].reg > 7
-         || !THUMB_SETS_FLAGS (inst.instruction)
-         || inst.size_req == 4)
+      bfd_boolean narrow;
+
+      if (THUMB_SETS_FLAGS (inst.instruction))
+       narrow = (current_it_mask == 0);
+      else
+       narrow = (current_it_mask != 0);
+      if (inst.operands[0].reg > 7 || inst.operands[1].reg > 7)
+       narrow = FALSE;
+      if (inst.size_req == 4)
+       narrow = FALSE;
+
+      if (!narrow)
        {
          inst.instruction = THUMB_OP32 (inst.instruction);
          inst.instruction |= inst.operands[0].reg << 8;
@@ -6887,39 +7177,52 @@ do_t_pld (void)
 static void
 do_t_push_pop (void)
 {
+  unsigned mask;
+  
   constraint (inst.operands[0].writeback,
              _("push/pop do not support {reglist}^"));
   constraint (inst.reloc.type != BFD_RELOC_UNUSED,
              _("expression too complex"));
 
-  if ((inst.operands[0].imm & ~0xff) == 0)
+  mask = inst.operands[0].imm;
+  if ((mask & ~0xff) == 0)
     inst.instruction = THUMB_OP16 (inst.instruction);
   else if ((inst.instruction == T_MNEM_push
-           && (inst.operands[0].imm & ~0xff) == 1 << REG_LR)
+           && (mask & ~0xff) == 1 << REG_LR)
           || (inst.instruction == T_MNEM_pop
-              && (inst.operands[0].imm & ~0xff) == 1 << REG_PC))
+              && (mask & ~0xff) == 1 << REG_PC))
     {
       inst.instruction = THUMB_OP16 (inst.instruction);
       inst.instruction |= THUMB_PP_PC_LR;
-      inst.operands[0].imm &= 0xff;
+      mask &= 0xff;
     }
   else if (unified_syntax)
     {
-      if (inst.operands[1].imm & (1 << 13))
-       as_warn (_("SP should not be in register list"));
+      if (mask & (1 << 13))
+       inst.error =  _("SP not allowed in register list");
       if (inst.instruction == T_MNEM_push)
        {
-         if (inst.operands[1].imm & (1 << 15))
-           as_warn (_("PC should not be in register list"));
+         if (mask & (1 << 15))
+           inst.error = _("PC not allowed in register list");
        }
       else
        {
-         if (inst.operands[1].imm & (1 << 14)
-             && inst.operands[1].imm & (1 << 15))
-           as_warn (_("LR and PC should not both be in register list"));
+         if (mask & (1 << 14)
+             && mask & (1 << 15))
+           inst.error = _("LR and PC should not both be in register list");
        }
-
-      inst.instruction = THUMB_OP32 (inst.instruction);
+      if ((mask & (mask - 1)) == 0)
+       {
+         /* Single register push/pop implemented as str/ldr.  */
+         if (inst.instruction == T_MNEM_push)
+           inst.instruction = 0xf84d0d04; /* str reg, [sp, #-4]! */
+         else
+           inst.instruction = 0xf85d0b04; /* ldr reg, [sp], #4 */
+         mask = ffs(mask) - 1;
+         mask <<= 12;
+       }
+      else
+       inst.instruction = THUMB_OP32 (inst.instruction);
     }
   else
     {
@@ -6927,7 +7230,7 @@ do_t_push_pop (void)
       return;
     }
 
-  inst.instruction |= inst.operands[0].imm;
+  inst.instruction |= mask;
 }
 
 static void
@@ -6994,12 +7297,38 @@ do_t_shift (void)
 
   if (unified_syntax)
     {
-      if (inst.operands[0].reg > 7
-         || inst.operands[1].reg > 7
-         || !THUMB_SETS_FLAGS (inst.instruction)
-         || (!inst.operands[2].isreg && inst.instruction == T_MNEM_rors)
-         || (inst.operands[2].isreg && inst.operands[1].reg != inst.operands[0].reg)
-         || inst.size_req == 4)
+      bfd_boolean narrow;
+      int shift_kind;
+
+      switch (inst.instruction)
+       {
+       case T_MNEM_asr:
+       case T_MNEM_asrs: shift_kind = SHIFT_ASR; break;
+       case T_MNEM_lsl:
+       case T_MNEM_lsls: shift_kind = SHIFT_LSL; break;
+       case T_MNEM_lsr:
+       case T_MNEM_lsrs: shift_kind = SHIFT_LSR; break;
+       case T_MNEM_ror:
+       case T_MNEM_rors: shift_kind = SHIFT_ROR; break;
+       default: abort ();
+       }
+
+      if (THUMB_SETS_FLAGS (inst.instruction))
+       narrow = (current_it_mask == 0);
+      else
+       narrow = (current_it_mask != 0);
+      if (inst.operands[0].reg > 7 || inst.operands[1].reg > 7)
+       narrow = FALSE;
+      if (!inst.operands[2].isreg && shift_kind == SHIFT_ROR)
+       narrow = FALSE;
+      if (inst.operands[2].isreg
+         && (inst.operands[1].reg != inst.operands[0].reg
+             || inst.operands[2].reg > 7))
+       narrow = FALSE;
+      if (inst.size_req == 4)
+       narrow = FALSE;
+
+      if (!narrow)
        {
          if (inst.operands[2].isreg)
            {
@@ -7011,19 +7340,7 @@ do_t_shift (void)
          else
            {
              inst.operands[1].shifted = 1;
-             switch (inst.instruction)
-               {
-               case T_MNEM_asr:
-               case T_MNEM_asrs: inst.operands[1].shift_kind = SHIFT_ASR; break;
-               case T_MNEM_lsl:
-               case T_MNEM_lsls: inst.operands[1].shift_kind = SHIFT_LSL; break;
-               case T_MNEM_lsr:
-               case T_MNEM_lsrs: inst.operands[1].shift_kind = SHIFT_LSR; break;
-               case T_MNEM_ror:
-               case T_MNEM_rors: inst.operands[1].shift_kind = SHIFT_ROR; break;
-               default: abort ();
-               }
-             
+             inst.operands[1].shift_kind = shift_kind;
              inst.instruction = THUMB_OP32 (THUMB_SETS_FLAGS (inst.instruction)
                                             ? T_MNEM_movs : T_MNEM_mov);
              inst.instruction |= inst.operands[0].reg << 8;
@@ -7036,12 +7353,12 @@ do_t_shift (void)
        {
          if (inst.operands[2].isreg)
            {
-             switch (inst.instruction)
+             switch (shift_kind)
                {
-               case T_MNEM_asrs: inst.instruction = T_OPCODE_ASR_R; break;
-               case T_MNEM_lsls: inst.instruction = T_OPCODE_LSL_R; break;
-               case T_MNEM_lsrs: inst.instruction = T_OPCODE_LSR_R; break;
-               case T_MNEM_rors: inst.instruction = T_OPCODE_ROR_R; break;
+               case SHIFT_ASR: inst.instruction = T_OPCODE_ASR_R; break;
+               case SHIFT_LSL: inst.instruction = T_OPCODE_LSL_R; break;
+               case SHIFT_LSR: inst.instruction = T_OPCODE_LSR_R; break;
+               case SHIFT_ROR: inst.instruction = T_OPCODE_ROR_R; break;
                default: abort ();
                }
          
@@ -7050,11 +7367,11 @@ do_t_shift (void)
            }
          else
            {
-             switch (inst.instruction)
+             switch (shift_kind)
                {
-               case T_MNEM_asrs: inst.instruction = T_OPCODE_ASR_I; break;
-               case T_MNEM_lsls: inst.instruction = T_OPCODE_LSL_I; break;
-               case T_MNEM_lsrs: inst.instruction = T_OPCODE_LSR_I; break;
+               case SHIFT_ASR: inst.instruction = T_OPCODE_ASR_I; break;
+               case SHIFT_LSL: inst.instruction = T_OPCODE_LSL_I; break;
+               case SHIFT_LSR: inst.instruction = T_OPCODE_LSR_I; break;
                default: abort ();
                }
              inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
@@ -7113,7 +7430,7 @@ do_t_simd (void)
 }
 
 static void
-do_t_smi (void)
+do_t_smc (void)
 {
   unsigned int value = inst.reloc.exp.X_add_number;
   constraint (inst.reloc.exp.X_op != O_constant,
@@ -7230,6 +7547,21 @@ do_t_swi (void)
   inst.reloc.type = BFD_RELOC_ARM_SWI;
 }
 
+static void
+do_t_tb (void)
+{
+  int half;
+
+  half = (inst.instruction & 0x10) != 0;
+  constraint (inst.operands[0].imm == 15,
+             _("PC is not a valid index register"));
+  constraint (!half && inst.operands[0].shifted,
+             _("instruction does not allow shifted index"));
+  constraint (half && !inst.operands[0].shifted,
+             _("instruction requires shifted index"));
+  inst.instruction |= (inst.operands[0].reg << 16) | inst.operands[0].imm;
+}
+
 static void
 do_t_usat (void)
 {
@@ -7297,7 +7629,47 @@ fix_new_arm (fragS *        frag,
 
   /* Mark whether the fix is to a THUMB instruction, or an ARM
      instruction.  */
-  new_fix->tc_fix_data = (PTR) thumb_mode;
+  new_fix->tc_fix_data = thumb_mode;
+}
+
+/* Create a frg for an instruction requiring relaxation.  */
+static void
+output_relax_insn (void)
+{
+  char * to;
+  symbolS *sym;
+  int offset;
+
+  switch (inst.reloc.exp.X_op)
+    {
+    case O_symbol:
+      sym = inst.reloc.exp.X_add_symbol;
+      offset = inst.reloc.exp.X_add_number;
+      break;
+    case O_constant:
+      sym = NULL;
+      offset = inst.reloc.exp.X_add_number;
+      break;
+    default:
+      sym = make_expr_symbol (&inst.reloc.exp);
+      offset = 0;
+      break;
+  }
+  to = frag_var (rs_machine_dependent, INSN_SIZE, THUMB_SIZE,
+                inst.relax, sym, offset, NULL/*offset, opcode*/);
+  md_number_to_chars (to, inst.instruction, THUMB_SIZE);
+
+#ifdef OBJ_ELF
+  dwarf2_emit_insn (INSN_SIZE);
+#endif
+}
+
+/* Write a 32-bit thumb instruction to buf.  */
+static void
+put_thumb32_insn (char * buf, unsigned long insn)
+{
+  md_number_to_chars (buf, insn >> 16, THUMB_SIZE);
+  md_number_to_chars (buf + THUMB_SIZE, insn, THUMB_SIZE);
 }
 
 static void
@@ -7310,6 +7682,10 @@ output_inst (const char * str)
       as_bad ("%s -- `%s'", inst.error, str);
       return;
     }
+  if (inst.relax) {
+      output_relax_insn();
+      return;
+  }
   if (inst.size == 0)
     return;
 
@@ -7318,8 +7694,7 @@ output_inst (const char * str)
   if (thumb_mode && (inst.size > THUMB_SIZE))
     {
       assert (inst.size == (2 * THUMB_SIZE));
-      md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
-      md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
+      put_thumb32_insn (to, inst.instruction);
     }
   else if (inst.size > INSN_SIZE)
     {
@@ -7487,8 +7862,10 @@ opcode_lookup (char **str)
        {
        case OT_cinfix3:
        case OT_odd_infix_unc:
+         /* Some mnemonics are ambiguous between infix and suffix
+            conditions.  Disambiguate based on assembly syntax.  */
          if (!unified_syntax)
-           return 0;
+           break;
          /* else fall through */
 
        case OT_csuffix:
@@ -7568,8 +7945,14 @@ md_assemble (char *str)
 
   if (thumb_mode)
     {
+      unsigned long variant;
+
+      variant = cpu_variant;
+      /* Only allow coprocessor instructions on Thumb-2 capable devices.  */
+      if ((variant & ARM_EXT_V6T2) == 0)
+       variant &= ARM_ANY;
       /* Check that this instruction is supported for this CPU.  */
-      if (thumb_mode == 1 && (opcode->tvariant & cpu_variant) == 0)
+      if (thumb_mode == 1 && (opcode->tvariant & variant) == 0)
        {
          as_bad (_("selected processor does not support `%s'"), str);
          return;
@@ -7581,13 +7964,36 @@ md_assemble (char *str)
          return;
        }
 
+      /* Check conditional suffixes.  */
+      if (current_it_mask)
+       {
+         int cond;
+         cond = current_cc ^ ((current_it_mask >> 4) & 1) ^ 1;
+         if (cond != inst.cond)
+           {
+             as_bad (_("incorrect condition in IT block"));
+             return;
+           }
+         current_it_mask <<= 1;
+         current_it_mask &= 0x1f;
+       }
+      else if (inst.cond != COND_ALWAYS && opcode->tencode != do_t_branch)
+       {
+         as_bad (_("thumb conditional instrunction not in IT block"));
+         return;
+       }
+
       mapping_state (MAP_THUMB);
       inst.instruction = opcode->tvalue;
 
       if (!parse_operands (p, opcode->operands))
        opcode->tencode ();
 
-      if (!inst.error)
+      /* Clear current_it_mask at the end of an IT block.  */
+      if (current_it_mask == 0x10)
+       current_it_mask = 0;
+
+      if (!(inst.error || inst.relax))
        {
          assert (inst.instruction < 0xe800 || inst.instruction > 0xffff);
          inst.size = (inst.instruction > 0xffff ? 4 : 2);
@@ -7963,7 +8369,7 @@ static const struct asm_cond conds[] =
 /* The normal sort of mnemonic; has a Thumb variant; takes a conditional suffix.  */
 #define TxCE(mnem, op, top, nops, ops, ae, te) \
   { #mnem, OPS##nops ops, OT_csuffix, 0x##op, top, ARM_VARIANT, \
-    do_##te ? THUMB_VARIANT : 0, do_##ae, do_##te }
+    THUMB_VARIANT, do_##ae, do_##te }
 
 /* Two variants of the above - TCE for a numeric Thumb opcode, tCE for
    a T_MNEM_xyz enumerator.  */
@@ -7976,7 +8382,7 @@ static const struct asm_cond conds[] =
    infix after the third character.  */
 #define TxC3(mnem, op, top, nops, ops, ae, te) \
   { #mnem, OPS##nops ops, OT_cinfix3, 0x##op, top, ARM_VARIANT, \
-    do_##te ? THUMB_VARIANT : 0, do_##ae, do_##te }
+    THUMB_VARIANT, do_##ae, do_##te }
 #define TC3(mnem, aop, top, nops, ops, ae, te) \
        TxC3(mnem, aop, 0x##top, nops, ops, ae, te)
 #define tC3(mnem, aop, top, nops, ops, ae, te) \
@@ -7986,7 +8392,7 @@ static const struct asm_cond conds[] =
    appear in the condition table.  */
 #define TxCM_(m1, m2, m3, op, top, nops, ops, ae, te)  \
   { #m1 #m2 #m3, OPS##nops ops, sizeof(#m2) == 1 ? OT_odd_infix_unc : OT_odd_infix_0 + sizeof(#m1) - 1, \
-    0x##op, top, ARM_VARIANT, do_##te ? THUMB_VARIANT : 0, do_##ae, do_##te }
+    0x##op, top, ARM_VARIANT, THUMB_VARIANT, do_##ae, do_##te }
 
 #define TxCM(m1, m2, op, top, nops, ops, ae, te)       \
   TxCM_(m1,   , m2, op, top, nops, ops, ae, te),       \
@@ -8018,20 +8424,60 @@ static const struct asm_cond conds[] =
    field is still 0xE.  */
 #define TUE(mnem, op, top, nops, ops, ae, te)                          \
   { #mnem, OPS##nops ops, OT_unconditional, 0x##op, 0x##top, ARM_VARIANT, \
-    do_##te ? THUMB_VARIANT : 0, do_##ae, do_##te }
+    THUMB_VARIANT, do_##ae, do_##te }
 
 /* Mnemonic that cannot be conditionalized, and bears 0xF in its ARM
    condition code field.  */
 #define TUF(mnem, op, top, nops, ops, ae, te)                          \
   { #mnem, OPS##nops ops, OT_unconditionalF, 0x##op, 0x##top, ARM_VARIANT, \
-    do_##te ? THUMB_VARIANT : 0, do_##ae, do_##te }
+    THUMB_VARIANT, do_##ae, do_##te }
 
 /* ARM-only variants of all the above.  */
-#define CE(mnem,  op, nops, ops, ae) TCE(mnem,  op, 0, nops, ops, ae, 0)
-#define C3(mnem,  op, nops, ops, ae) TC3(mnem,  op, 0, nops, ops, ae, 0)
-#define CM(m1,m2, op, nops, ops, ae) TCM(m1,m2, op, 0, nops, ops, ae, 0)
-#define UE(mnem,  op, nops, ops, ae) TUE(mnem,  op, 0, nops, ops, ae, 0)
-#define UF(mnem,  op, nops, ops, ae) TUF(mnem,  op, 0, nops, ops, ae, 0)
+#define CE(mnem,  op, nops, ops, ae)   \
+  { #mnem, OPS##nops ops, OT_csuffix, 0x##op, 0x0, ARM_VARIANT, 0, do_##ae, NULL }
+
+#define C3(mnem, op, nops, ops, ae)    \
+  { #mnem, OPS##nops ops, OT_cinfix3, 0x##op, 0x0, ARM_VARIANT, 0, do_##ae, NULL }
+
+/* Coprocessor instructions.  Isomorphic between Arm and Thumb-2.  */
+#define cCE(mnem,  op, nops, ops, ae)  \
+  { #mnem, OPS##nops ops, OT_csuffix, 0x##op, 0xe##op, ARM_VARIANT, ARM_VARIANT, do_##ae, do_##ae }
+
+#define cC3(mnem, op, nops, ops, ae)   \
+  { #mnem, OPS##nops ops, OT_cinfix3, 0x##op, 0xe##op, ARM_VARIANT, ARM_VARIANT, do_##ae, do_##ae }
+
+#define xCM_(m1, m2, m3, op, nops, ops, ae)    \
+  { #m1 #m2 #m3, OPS##nops ops, \
+    sizeof(#m2) == 1 ? OT_odd_infix_unc : OT_odd_infix_0 + sizeof(#m1) - 1, \
+    0x##op, 0x0, ARM_VARIANT, 0, do_##ae, NULL }
+
+#define CM(m1, m2, op, nops, ops, ae)  \
+  xCM_(m1,   , m2, op, nops, ops, ae), \
+  xCM_(m1, eq, m2, op, nops, ops, ae), \
+  xCM_(m1, ne, m2, op, nops, ops, ae), \
+  xCM_(m1, cs, m2, op, nops, ops, ae), \
+  xCM_(m1, hs, m2, op, nops, ops, ae), \
+  xCM_(m1, cc, m2, op, nops, ops, ae), \
+  xCM_(m1, ul, m2, op, nops, ops, ae), \
+  xCM_(m1, lo, m2, op, nops, ops, ae), \
+  xCM_(m1, mi, m2, op, nops, ops, ae), \
+  xCM_(m1, pl, m2, op, nops, ops, ae), \
+  xCM_(m1, vs, m2, op, nops, ops, ae), \
+  xCM_(m1, vc, m2, op, nops, ops, ae), \
+  xCM_(m1, hi, m2, op, nops, ops, ae), \
+  xCM_(m1, ls, m2, op, nops, ops, ae), \
+  xCM_(m1, ge, m2, op, nops, ops, ae), \
+  xCM_(m1, lt, m2, op, nops, ops, ae), \
+  xCM_(m1, gt, m2, op, nops, ops, ae), \
+  xCM_(m1, le, m2, op, nops, ops, ae), \
+  xCM_(m1, al, m2, op, nops, ops, ae)
+
+#define UE(mnem, op, nops, ops, ae)    \
+  { #mnem, OPS##nops ops, OT_unconditional, 0x##op, 0, ARM_VARIANT, 0, do_##ae, NULL }
+
+#define UF(mnem, op, nops, ops, ae)    \
+  { #mnem, OPS##nops ops, OT_unconditionalF, 0x##op, 0, ARM_VARIANT, 0, do_##ae, NULL }
+
 #define do_0 0
 
 /* Thumb-only, unconditional.  */
@@ -8092,19 +8538,13 @@ static const struct asm_opcode insns[] =
  tC3(ldmfd,    8900000, ldmia,    2, (RRw, REGLST), ldmstm, t_ldmstm),
 
  TCE(swi,      f000000, df00,     1, (EXPi),        swi, t_swi),
-#ifdef TE_WINCE
-  /* XXX This is the wrong place to do this.  Think multi-arch.         */
- TCE(b,                a000000, e7fe,       1, (EXPr),     branch, t_branch),
- TCE(bl,       b000000, f7fffffe,   1, (EXPr),     branch, t_branch23),
-#else
- TCE(b,                afffffe, e7fe,       1, (EXPr),     branch, t_branch),
- TCE(bl,       bfffffe, f7fffffe,   1, (EXPr),     branch, t_branch23),
-#endif
+ tCE(b,                a000000, b,        1, (EXPr),        branch, t_branch),
+ TCE(bl,       b000000, f000f800, 1, (EXPr),        branch, t_branch23),
 
   /* Pseudo ops.  */
TCE(adr,      28f0000, 000f,     2, (RR, EXP),    adr,  t_adr),
-  C3(adrl,     28f0000,           2, (RR, EXP),    adrl),
- tCE(nop,      1a00000, nop,      1, (oI255c),     nop,  t_nop),
tCE(adr,      28f0000, adr,      2, (RR, EXP),     adr,  t_adr),
+  C3(adrl,     28f0000,           2, (RR, EXP),     adrl),
+ tCE(nop,      1a00000, nop,      1, (oI255c),      nop,  t_nop),
 
   /* Thumb-compatibility pseudo ops.  */
  tCE(lsl,      1a00000, lsl,      3, (RR, oRR, SH), shift, t_shift),
@@ -8112,7 +8552,7 @@ static const struct asm_opcode insns[] =
  tCE(lsr,      1a00020, lsr,      3, (RR, oRR, SH), shift, t_shift),
  tC3(lsrs,     1b00020, lsrs,     3, (RR, oRR, SH), shift, t_shift),
  tCE(asr,      1a00040, asr,      3, (RR, oRR, SH), shift, t_shift),
- tC3(asrs,     1b00040, asrs,     3, (RR, oRR, SH), shift, t_shift),
+ tC3(asrs,      1b00040, asrs,     3, (RR, oRR, SH), shift, t_shift),
  tCE(ror,      1a00060, ror,      3, (RR, oRR, SH), shift, t_shift),
  tC3(rors,     1b00060, rors,     3, (RR, oRR, SH), shift, t_shift),
  tCE(neg,      2600000, neg,      2, (RR, RR),      rd_rn, t_neg),
@@ -8122,7 +8562,7 @@ static const struct asm_opcode insns[] =
 
 #undef THUMB_VARIANT
 #define THUMB_VARIANT ARM_EXT_V6
- TCE(cpy,       1a00000, 4600,     2, (RR, RR),          rd_rm, t_cpy),
+ TCE(cpy,       1a00000, 4600,     2, (RR, RR),      rd_rm, t_cpy),
 
  /* V1 instructions with no Thumb analogue prior to V6T2.  */
 #undef THUMB_VARIANT
@@ -8138,11 +8578,11 @@ static const struct asm_opcode insns[] =
  TC3(strt,     4200000, f8400e00, 2, (RR, ADDR),    ldstt, t_ldstt),
  TC3(strbt,    4600000, f8200e00, 2, (RR, ADDR),    ldstt, t_ldstt),
 
- TC3(stmdb,    9000000, e9100000, 2, (RRw, REGLST), ldmstm, t_ldmstm),
- TC3(stmfd,    9000000, e9100000, 2, (RRw, REGLST), ldmstm, t_ldmstm),
+ TC3(stmdb,    9000000, e9000000, 2, (RRw, REGLST), ldmstm, t_ldmstm),
+ TC3(stmfd,     9000000, e9000000, 2, (RRw, REGLST), ldmstm, t_ldmstm),
 
- TC3(ldmdb,    9100000, e9000000, 2, (RRw, REGLST), ldmstm, t_ldmstm),
- TC3(ldmea,    9100000, e9000000, 2, (RRw, REGLST), ldmstm, t_ldmstm),
+ TC3(ldmdb,    9100000, e9100000, 2, (RRw, REGLST), ldmstm, t_ldmstm),
+ TC3(ldmea,    9100000, e9100000, 2, (RRw, REGLST), ldmstm, t_ldmstm),
 
  /* V1 instructions with no Thumb analogue at all.  */
   CE(rsc,      0e00000,           3, (RR, oRR, SH), arit),
@@ -8406,7 +8846,7 @@ static const struct asm_opcode insns[] =
 
 #undef ARM_VARIANT
 #define ARM_VARIANT ARM_EXT_V6Z
- TCE(smi,      1600070, f7f08000, 1, (EXPi), smi, t_smi),
+ TCE(smc,      1600070, f7f08000, 1, (EXPi), smc, t_smc),
 
 #undef ARM_VARIANT
 #define ARM_VARIANT ARM_EXT_V6T2
@@ -8444,817 +8884,826 @@ static const struct asm_opcode insns[] =
  TUE(ittee,     0, bf09, 1, (COND),    it, t_it),
  TUE(iteee,     0, bf01, 1, (COND),    it, t_it),
 
+ /* Thumb2 only instructions.  */
+#undef ARM_VARIANT
+#define ARM_VARIANT 0
+
+ TCE(addw,     0, f2000000, 3, (RR, RR, EXPi), 0, t_add_sub_w),
+ TCE(subw,     0, f2a00000, 3, (RR, RR, EXPi), 0, t_add_sub_w),
+ TCE(tbb,       0, e8d0f000, 1, (TB), 0, t_tb),
+ TCE(tbh,       0, e8d0f010, 1, (TB), 0, t_tb),
+
 #undef ARM_VARIANT
 #define ARM_VARIANT FPU_FPA_EXT_V1  /* Core FPA instruction set (V1).  */
 CE(wfs,      e200110, 1, (RR),            rd),
 CE(rfs,      e300110, 1, (RR),            rd),
 CE(wfc,      e400110, 1, (RR),            rd),
 CE(rfc,      e500110, 1, (RR),            rd),
-
 C3(ldfs,     c100100, 2, (RF, ADDR),      rd_cpaddr),
 C3(ldfd,     c108100, 2, (RF, ADDR),      rd_cpaddr),
 C3(ldfe,     c500100, 2, (RF, ADDR),      rd_cpaddr),
 C3(ldfp,     c508100, 2, (RF, ADDR),      rd_cpaddr),
-
 C3(stfs,     c000100, 2, (RF, ADDR),      rd_cpaddr),
 C3(stfd,     c008100, 2, (RF, ADDR),      rd_cpaddr),
 C3(stfe,     c400100, 2, (RF, ADDR),      rd_cpaddr),
 C3(stfp,     c408100, 2, (RF, ADDR),      rd_cpaddr),
-
 C3(mvfs,     e008100, 2, (RF, RF_IF),     rd_rm),
 C3(mvfsp,    e008120, 2, (RF, RF_IF),     rd_rm),
 C3(mvfsm,    e008140, 2, (RF, RF_IF),     rd_rm),
 C3(mvfsz,    e008160, 2, (RF, RF_IF),     rd_rm),
 C3(mvfd,     e008180, 2, (RF, RF_IF),     rd_rm),
 C3(mvfdp,    e0081a0, 2, (RF, RF_IF),     rd_rm),
 C3(mvfdm,    e0081c0, 2, (RF, RF_IF),     rd_rm),
 C3(mvfdz,    e0081e0, 2, (RF, RF_IF),     rd_rm),
 C3(mvfe,     e088100, 2, (RF, RF_IF),     rd_rm),
 C3(mvfep,    e088120, 2, (RF, RF_IF),     rd_rm),
 C3(mvfem,    e088140, 2, (RF, RF_IF),     rd_rm),
 C3(mvfez,    e088160, 2, (RF, RF_IF),     rd_rm),
-
 C3(mnfs,     e108100, 2, (RF, RF_IF),     rd_rm),
 C3(mnfsp,    e108120, 2, (RF, RF_IF),     rd_rm),
 C3(mnfsm,    e108140, 2, (RF, RF_IF),     rd_rm),
 C3(mnfsz,    e108160, 2, (RF, RF_IF),     rd_rm),
 C3(mnfd,     e108180, 2, (RF, RF_IF),     rd_rm),
 C3(mnfdp,    e1081a0, 2, (RF, RF_IF),     rd_rm),
 C3(mnfdm,    e1081c0, 2, (RF, RF_IF),     rd_rm),
 C3(mnfdz,    e1081e0, 2, (RF, RF_IF),     rd_rm),
 C3(mnfe,     e188100, 2, (RF, RF_IF),     rd_rm),
 C3(mnfep,    e188120, 2, (RF, RF_IF),     rd_rm),
 C3(mnfem,    e188140, 2, (RF, RF_IF),     rd_rm),
 C3(mnfez,    e188160, 2, (RF, RF_IF),     rd_rm),
-
 C3(abss,     e208100, 2, (RF, RF_IF),     rd_rm),
 C3(abssp,    e208120, 2, (RF, RF_IF),     rd_rm),
 C3(abssm,    e208140, 2, (RF, RF_IF),     rd_rm),
 C3(abssz,    e208160, 2, (RF, RF_IF),     rd_rm),
 C3(absd,     e208180, 2, (RF, RF_IF),     rd_rm),
 C3(absdp,    e2081a0, 2, (RF, RF_IF),     rd_rm),
 C3(absdm,    e2081c0, 2, (RF, RF_IF),     rd_rm),
 C3(absdz,    e2081e0, 2, (RF, RF_IF),     rd_rm),
 C3(abse,     e288100, 2, (RF, RF_IF),     rd_rm),
 C3(absep,    e288120, 2, (RF, RF_IF),     rd_rm),
 C3(absem,    e288140, 2, (RF, RF_IF),     rd_rm),
 C3(absez,    e288160, 2, (RF, RF_IF),     rd_rm),
-
 C3(rnds,     e308100, 2, (RF, RF_IF),     rd_rm),
 C3(rndsp,    e308120, 2, (RF, RF_IF),     rd_rm),
 C3(rndsm,    e308140, 2, (RF, RF_IF),     rd_rm),
 C3(rndsz,    e308160, 2, (RF, RF_IF),     rd_rm),
 C3(rndd,     e308180, 2, (RF, RF_IF),     rd_rm),
 C3(rnddp,    e3081a0, 2, (RF, RF_IF),     rd_rm),
 C3(rnddm,    e3081c0, 2, (RF, RF_IF),     rd_rm),
 C3(rnddz,    e3081e0, 2, (RF, RF_IF),     rd_rm),
 C3(rnde,     e388100, 2, (RF, RF_IF),     rd_rm),
 C3(rndep,    e388120, 2, (RF, RF_IF),     rd_rm),
 C3(rndem,    e388140, 2, (RF, RF_IF),     rd_rm),
 C3(rndez,    e388160, 2, (RF, RF_IF),     rd_rm),
-
 C3(sqts,     e408100, 2, (RF, RF_IF),     rd_rm),
 C3(sqtsp,    e408120, 2, (RF, RF_IF),     rd_rm),
 C3(sqtsm,    e408140, 2, (RF, RF_IF),     rd_rm),
 C3(sqtsz,    e408160, 2, (RF, RF_IF),     rd_rm),
 C3(sqtd,     e408180, 2, (RF, RF_IF),     rd_rm),
 C3(sqtdp,    e4081a0, 2, (RF, RF_IF),     rd_rm),
 C3(sqtdm,    e4081c0, 2, (RF, RF_IF),     rd_rm),
 C3(sqtdz,    e4081e0, 2, (RF, RF_IF),     rd_rm),
 C3(sqte,     e488100, 2, (RF, RF_IF),     rd_rm),
 C3(sqtep,    e488120, 2, (RF, RF_IF),     rd_rm),
 C3(sqtem,    e488140, 2, (RF, RF_IF),     rd_rm),
 C3(sqtez,    e488160, 2, (RF, RF_IF),     rd_rm),
-
 C3(logs,     e508100, 2, (RF, RF_IF),     rd_rm),
 C3(logsp,    e508120, 2, (RF, RF_IF),     rd_rm),
 C3(logsm,    e508140, 2, (RF, RF_IF),     rd_rm),
 C3(logsz,    e508160, 2, (RF, RF_IF),     rd_rm),
 C3(logd,     e508180, 2, (RF, RF_IF),     rd_rm),
 C3(logdp,    e5081a0, 2, (RF, RF_IF),     rd_rm),
 C3(logdm,    e5081c0, 2, (RF, RF_IF),     rd_rm),
 C3(logdz,    e5081e0, 2, (RF, RF_IF),     rd_rm),
 C3(loge,     e588100, 2, (RF, RF_IF),     rd_rm),
 C3(logep,    e588120, 2, (RF, RF_IF),     rd_rm),
 C3(logem,    e588140, 2, (RF, RF_IF),     rd_rm),
 C3(logez,    e588160, 2, (RF, RF_IF),     rd_rm),
-
 C3(lgns,     e608100, 2, (RF, RF_IF),     rd_rm),
 C3(lgnsp,    e608120, 2, (RF, RF_IF),     rd_rm),
 C3(lgnsm,    e608140, 2, (RF, RF_IF),     rd_rm),
 C3(lgnsz,    e608160, 2, (RF, RF_IF),     rd_rm),
 C3(lgnd,     e608180, 2, (RF, RF_IF),     rd_rm),
 C3(lgndp,    e6081a0, 2, (RF, RF_IF),     rd_rm),
 C3(lgndm,    e6081c0, 2, (RF, RF_IF),     rd_rm),
 C3(lgndz,    e6081e0, 2, (RF, RF_IF),     rd_rm),
 C3(lgne,     e688100, 2, (RF, RF_IF),     rd_rm),
 C3(lgnep,    e688120, 2, (RF, RF_IF),     rd_rm),
 C3(lgnem,    e688140, 2, (RF, RF_IF),     rd_rm),
 C3(lgnez,    e688160, 2, (RF, RF_IF),     rd_rm),
-
 C3(exps,     e708100, 2, (RF, RF_IF),     rd_rm),
 C3(expsp,    e708120, 2, (RF, RF_IF),     rd_rm),
 C3(expsm,    e708140, 2, (RF, RF_IF),     rd_rm),
 C3(expsz,    e708160, 2, (RF, RF_IF),     rd_rm),
 C3(expd,     e708180, 2, (RF, RF_IF),     rd_rm),
 C3(expdp,    e7081a0, 2, (RF, RF_IF),     rd_rm),
 C3(expdm,    e7081c0, 2, (RF, RF_IF),     rd_rm),
 C3(expdz,    e7081e0, 2, (RF, RF_IF),     rd_rm),
 C3(expe,     e788100, 2, (RF, RF_IF),     rd_rm),
 C3(expep,    e788120, 2, (RF, RF_IF),     rd_rm),
 C3(expem,    e788140, 2, (RF, RF_IF),     rd_rm),
 C3(expdz,    e788160, 2, (RF, RF_IF),     rd_rm),
-
 C3(sins,     e808100, 2, (RF, RF_IF),     rd_rm),
 C3(sinsp,    e808120, 2, (RF, RF_IF),     rd_rm),
 C3(sinsm,    e808140, 2, (RF, RF_IF),     rd_rm),
 C3(sinsz,    e808160, 2, (RF, RF_IF),     rd_rm),
 C3(sind,     e808180, 2, (RF, RF_IF),     rd_rm),
 C3(sindp,    e8081a0, 2, (RF, RF_IF),     rd_rm),
 C3(sindm,    e8081c0, 2, (RF, RF_IF),     rd_rm),
 C3(sindz,    e8081e0, 2, (RF, RF_IF),     rd_rm),
 C3(sine,     e888100, 2, (RF, RF_IF),     rd_rm),
 C3(sinep,    e888120, 2, (RF, RF_IF),     rd_rm),
 C3(sinem,    e888140, 2, (RF, RF_IF),     rd_rm),
 C3(sinez,    e888160, 2, (RF, RF_IF),     rd_rm),
-
 C3(coss,     e908100, 2, (RF, RF_IF),     rd_rm),
 C3(cossp,    e908120, 2, (RF, RF_IF),     rd_rm),
 C3(cossm,    e908140, 2, (RF, RF_IF),     rd_rm),
 C3(cossz,    e908160, 2, (RF, RF_IF),     rd_rm),
 C3(cosd,     e908180, 2, (RF, RF_IF),     rd_rm),
 C3(cosdp,    e9081a0, 2, (RF, RF_IF),     rd_rm),
 C3(cosdm,    e9081c0, 2, (RF, RF_IF),     rd_rm),
 C3(cosdz,    e9081e0, 2, (RF, RF_IF),     rd_rm),
 C3(cose,     e988100, 2, (RF, RF_IF),     rd_rm),
 C3(cosep,    e988120, 2, (RF, RF_IF),     rd_rm),
 C3(cosem,    e988140, 2, (RF, RF_IF),     rd_rm),
 C3(cosez,    e988160, 2, (RF, RF_IF),     rd_rm),
-
 C3(tans,     ea08100, 2, (RF, RF_IF),     rd_rm),
 C3(tansp,    ea08120, 2, (RF, RF_IF),     rd_rm),
 C3(tansm,    ea08140, 2, (RF, RF_IF),     rd_rm),
 C3(tansz,    ea08160, 2, (RF, RF_IF),     rd_rm),
 C3(tand,     ea08180, 2, (RF, RF_IF),     rd_rm),
 C3(tandp,    ea081a0, 2, (RF, RF_IF),     rd_rm),
 C3(tandm,    ea081c0, 2, (RF, RF_IF),     rd_rm),
 C3(tandz,    ea081e0, 2, (RF, RF_IF),     rd_rm),
 C3(tane,     ea88100, 2, (RF, RF_IF),     rd_rm),
 C3(tanep,    ea88120, 2, (RF, RF_IF),     rd_rm),
 C3(tanem,    ea88140, 2, (RF, RF_IF),     rd_rm),
 C3(tanez,    ea88160, 2, (RF, RF_IF),     rd_rm),
-
 C3(asns,     eb08100, 2, (RF, RF_IF),     rd_rm),
 C3(asnsp,    eb08120, 2, (RF, RF_IF),     rd_rm),
 C3(asnsm,    eb08140, 2, (RF, RF_IF),     rd_rm),
 C3(asnsz,    eb08160, 2, (RF, RF_IF),     rd_rm),
 C3(asnd,     eb08180, 2, (RF, RF_IF),     rd_rm),
 C3(asndp,    eb081a0, 2, (RF, RF_IF),     rd_rm),
 C3(asndm,    eb081c0, 2, (RF, RF_IF),     rd_rm),
 C3(asndz,    eb081e0, 2, (RF, RF_IF),     rd_rm),
 C3(asne,     eb88100, 2, (RF, RF_IF),     rd_rm),
 C3(asnep,    eb88120, 2, (RF, RF_IF),     rd_rm),
 C3(asnem,    eb88140, 2, (RF, RF_IF),     rd_rm),
 C3(asnez,    eb88160, 2, (RF, RF_IF),     rd_rm),
-
 C3(acss,     ec08100, 2, (RF, RF_IF),     rd_rm),
 C3(acssp,    ec08120, 2, (RF, RF_IF),     rd_rm),
 C3(acssm,    ec08140, 2, (RF, RF_IF),     rd_rm),
 C3(acssz,    ec08160, 2, (RF, RF_IF),     rd_rm),
 C3(acsd,     ec08180, 2, (RF, RF_IF),     rd_rm),
 C3(acsdp,    ec081a0, 2, (RF, RF_IF),     rd_rm),
 C3(acsdm,    ec081c0, 2, (RF, RF_IF),     rd_rm),
 C3(acsdz,    ec081e0, 2, (RF, RF_IF),     rd_rm),
 C3(acse,     ec88100, 2, (RF, RF_IF),     rd_rm),
 C3(acsep,    ec88120, 2, (RF, RF_IF),     rd_rm),
 C3(acsem,    ec88140, 2, (RF, RF_IF),     rd_rm),
 C3(acsez,    ec88160, 2, (RF, RF_IF),     rd_rm),
-
 C3(atns,     ed08100, 2, (RF, RF_IF),     rd_rm),
 C3(atnsp,    ed08120, 2, (RF, RF_IF),     rd_rm),
 C3(atnsm,    ed08140, 2, (RF, RF_IF),     rd_rm),
 C3(atnsz,    ed08160, 2, (RF, RF_IF),     rd_rm),
 C3(atnd,     ed08180, 2, (RF, RF_IF),     rd_rm),
 C3(atndp,    ed081a0, 2, (RF, RF_IF),     rd_rm),
 C3(atndm,    ed081c0, 2, (RF, RF_IF),     rd_rm),
 C3(atndz,    ed081e0, 2, (RF, RF_IF),     rd_rm),
 C3(atne,     ed88100, 2, (RF, RF_IF),     rd_rm),
 C3(atnep,    ed88120, 2, (RF, RF_IF),     rd_rm),
 C3(atnem,    ed88140, 2, (RF, RF_IF),     rd_rm),
 C3(atnez,    ed88160, 2, (RF, RF_IF),     rd_rm),
-
 C3(urds,     ee08100, 2, (RF, RF_IF),     rd_rm),
 C3(urdsp,    ee08120, 2, (RF, RF_IF),     rd_rm),
 C3(urdsm,    ee08140, 2, (RF, RF_IF),     rd_rm),
 C3(urdsz,    ee08160, 2, (RF, RF_IF),     rd_rm),
 C3(urdd,     ee08180, 2, (RF, RF_IF),     rd_rm),
 C3(urddp,    ee081a0, 2, (RF, RF_IF),     rd_rm),
 C3(urddm,    ee081c0, 2, (RF, RF_IF),     rd_rm),
 C3(urddz,    ee081e0, 2, (RF, RF_IF),     rd_rm),
 C3(urde,     ee88100, 2, (RF, RF_IF),     rd_rm),
 C3(urdep,    ee88120, 2, (RF, RF_IF),     rd_rm),
 C3(urdem,    ee88140, 2, (RF, RF_IF),     rd_rm),
 C3(urdez,    ee88160, 2, (RF, RF_IF),     rd_rm),
-
 C3(nrms,     ef08100, 2, (RF, RF_IF),     rd_rm),
 C3(nrmsp,    ef08120, 2, (RF, RF_IF),     rd_rm),
 C3(nrmsm,    ef08140, 2, (RF, RF_IF),     rd_rm),
 C3(nrmsz,    ef08160, 2, (RF, RF_IF),     rd_rm),
 C3(nrmd,     ef08180, 2, (RF, RF_IF),     rd_rm),
 C3(nrmdp,    ef081a0, 2, (RF, RF_IF),     rd_rm),
 C3(nrmdm,    ef081c0, 2, (RF, RF_IF),     rd_rm),
 C3(nrmdz,    ef081e0, 2, (RF, RF_IF),     rd_rm),
 C3(nrme,     ef88100, 2, (RF, RF_IF),     rd_rm),
 C3(nrmep,    ef88120, 2, (RF, RF_IF),     rd_rm),
 C3(nrmem,    ef88140, 2, (RF, RF_IF),     rd_rm),
 C3(nrmez,    ef88160, 2, (RF, RF_IF),     rd_rm),
-
 C3(adfs,     e000100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(adfsp,    e000120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(adfsm,    e000140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(adfsz,    e000160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(adfd,     e000180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(adfdp,    e0001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(adfdm,    e0001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(adfdz,    e0001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(adfe,     e080100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(adfep,    e080120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(adfem,    e080140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(adfez,    e080160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(sufs,     e200100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(sufsp,    e200120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(sufsm,    e200140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(sufsz,    e200160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(sufd,     e200180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(sufdp,    e2001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(sufdm,    e2001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(sufdz,    e2001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(sufe,     e280100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(sufep,    e280120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(sufem,    e280140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(sufez,    e280160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(rsfs,     e300100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rsfsp,    e300120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rsfsm,    e300140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rsfsz,    e300160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rsfd,     e300180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rsfdp,    e3001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rsfdm,    e3001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rsfdz,    e3001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rsfe,     e380100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rsfep,    e380120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rsfem,    e380140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rsfez,    e380160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(mufs,     e100100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(mufsp,    e100120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(mufsm,    e100140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(mufsz,    e100160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(mufd,     e100180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(mufdp,    e1001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(mufdm,    e1001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(mufdz,    e1001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(mufe,     e180100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(mufep,    e180120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(mufem,    e180140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(mufez,    e180160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(dvfs,     e400100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(dvfsp,    e400120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(dvfsm,    e400140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(dvfsz,    e400160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(dvfd,     e400180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(dvfdp,    e4001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(dvfdm,    e4001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(dvfdz,    e4001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(dvfe,     e480100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(dvfep,    e480120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(dvfem,    e480140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(dvfez,    e480160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(rdfs,     e500100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rdfsp,    e500120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rdfsm,    e500140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rdfsz,    e500160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rdfd,     e500180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rdfdp,    e5001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rdfdm,    e5001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rdfdz,    e5001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rdfe,     e580100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rdfep,    e580120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rdfem,    e580140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rdfez,    e580160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(pows,     e600100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(powsp,    e600120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(powsm,    e600140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(powsz,    e600160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(powd,     e600180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(powdp,    e6001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(powdm,    e6001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(powdz,    e6001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(powe,     e680100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(powep,    e680120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(powem,    e680140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(powez,    e680160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(rpws,     e700100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rpwsp,    e700120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rpwsm,    e700140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rpwsz,    e700160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rpwd,     e700180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rpwdp,    e7001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rpwdm,    e7001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rpwdz,    e7001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rpwe,     e780100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rpwep,    e780120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rpwem,    e780140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rpwez,    e780160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(rmfs,     e800100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rmfsp,    e800120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rmfsm,    e800140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rmfsz,    e800160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rmfd,     e800180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rmfdp,    e8001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rmfdm,    e8001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rmfdz,    e8001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rmfe,     e880100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rmfep,    e880120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rmfem,    e880140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(rmfez,    e880160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(fmls,     e900100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fmlsp,    e900120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fmlsm,    e900140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fmlsz,    e900160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fmld,     e900180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fmldp,    e9001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fmldm,    e9001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fmldz,    e9001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fmle,     e980100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fmlep,    e980120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fmlem,    e980140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fmlez,    e980160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(fdvs,     ea00100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fdvsp,    ea00120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fdvsm,    ea00140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fdvsz,    ea00160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fdvd,     ea00180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fdvdp,    ea001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fdvdm,    ea001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fdvdz,    ea001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fdve,     ea80100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fdvep,    ea80120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fdvem,    ea80140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(fdvez,    ea80160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(frds,     eb00100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(frdsp,    eb00120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(frdsm,    eb00140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(frdsz,    eb00160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(frdd,     eb00180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(frddp,    eb001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(frddm,    eb001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(frddz,    eb001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(frde,     eb80100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(frdep,    eb80120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(frdem,    eb80140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(frdez,    eb80160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 C3(pols,     ec00100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(polsp,    ec00120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(polsm,    ec00140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(polsz,    ec00160, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(pold,     ec00180, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(poldp,    ec001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(poldm,    ec001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(poldz,    ec001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(pole,     ec80100, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(polep,    ec80120, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(polem,    ec80140, 3, (RF, RF, RF_IF), rd_rn_rm),
 C3(polez,    ec80160, 3, (RF, RF, RF_IF), rd_rn_rm),
-
 CE(cmf,      e90f110, 2, (RF, RF_IF),     fpa_cmp),
cCE(wfs,      e200110, 1, (RR),            rd),
cCE(rfs,      e300110, 1, (RR),            rd),
cCE(wfc,      e400110, 1, (RR),            rd),
cCE(rfc,      e500110, 1, (RR),            rd),
+
cC3(ldfs,     c100100, 2, (RF, ADDR),      rd_cpaddr),
cC3(ldfd,     c108100, 2, (RF, ADDR),      rd_cpaddr),
cC3(ldfe,     c500100, 2, (RF, ADDR),      rd_cpaddr),
cC3(ldfp,     c508100, 2, (RF, ADDR),      rd_cpaddr),
+
cC3(stfs,     c000100, 2, (RF, ADDR),      rd_cpaddr),
cC3(stfd,     c008100, 2, (RF, ADDR),      rd_cpaddr),
cC3(stfe,     c400100, 2, (RF, ADDR),      rd_cpaddr),
cC3(stfp,     c408100, 2, (RF, ADDR),      rd_cpaddr),
+
cC3(mvfs,     e008100, 2, (RF, RF_IF),     rd_rm),
cC3(mvfsp,    e008120, 2, (RF, RF_IF),     rd_rm),
cC3(mvfsm,    e008140, 2, (RF, RF_IF),     rd_rm),
cC3(mvfsz,    e008160, 2, (RF, RF_IF),     rd_rm),
cC3(mvfd,     e008180, 2, (RF, RF_IF),     rd_rm),
cC3(mvfdp,    e0081a0, 2, (RF, RF_IF),     rd_rm),
cC3(mvfdm,    e0081c0, 2, (RF, RF_IF),     rd_rm),
cC3(mvfdz,    e0081e0, 2, (RF, RF_IF),     rd_rm),
cC3(mvfe,     e088100, 2, (RF, RF_IF),     rd_rm),
cC3(mvfep,    e088120, 2, (RF, RF_IF),     rd_rm),
cC3(mvfem,    e088140, 2, (RF, RF_IF),     rd_rm),
cC3(mvfez,    e088160, 2, (RF, RF_IF),     rd_rm),
+
cC3(mnfs,     e108100, 2, (RF, RF_IF),     rd_rm),
cC3(mnfsp,    e108120, 2, (RF, RF_IF),     rd_rm),
cC3(mnfsm,    e108140, 2, (RF, RF_IF),     rd_rm),
cC3(mnfsz,    e108160, 2, (RF, RF_IF),     rd_rm),
cC3(mnfd,     e108180, 2, (RF, RF_IF),     rd_rm),
cC3(mnfdp,    e1081a0, 2, (RF, RF_IF),     rd_rm),
cC3(mnfdm,    e1081c0, 2, (RF, RF_IF),     rd_rm),
cC3(mnfdz,    e1081e0, 2, (RF, RF_IF),     rd_rm),
cC3(mnfe,     e188100, 2, (RF, RF_IF),     rd_rm),
cC3(mnfep,    e188120, 2, (RF, RF_IF),     rd_rm),
cC3(mnfem,    e188140, 2, (RF, RF_IF),     rd_rm),
cC3(mnfez,    e188160, 2, (RF, RF_IF),     rd_rm),
+
cC3(abss,     e208100, 2, (RF, RF_IF),     rd_rm),
cC3(abssp,    e208120, 2, (RF, RF_IF),     rd_rm),
cC3(abssm,    e208140, 2, (RF, RF_IF),     rd_rm),
cC3(abssz,    e208160, 2, (RF, RF_IF),     rd_rm),
cC3(absd,     e208180, 2, (RF, RF_IF),     rd_rm),
cC3(absdp,    e2081a0, 2, (RF, RF_IF),     rd_rm),
cC3(absdm,    e2081c0, 2, (RF, RF_IF),     rd_rm),
cC3(absdz,    e2081e0, 2, (RF, RF_IF),     rd_rm),
cC3(abse,     e288100, 2, (RF, RF_IF),     rd_rm),
cC3(absep,    e288120, 2, (RF, RF_IF),     rd_rm),
cC3(absem,    e288140, 2, (RF, RF_IF),     rd_rm),
cC3(absez,    e288160, 2, (RF, RF_IF),     rd_rm),
+
cC3(rnds,     e308100, 2, (RF, RF_IF),     rd_rm),
cC3(rndsp,    e308120, 2, (RF, RF_IF),     rd_rm),
cC3(rndsm,    e308140, 2, (RF, RF_IF),     rd_rm),
cC3(rndsz,    e308160, 2, (RF, RF_IF),     rd_rm),
cC3(rndd,     e308180, 2, (RF, RF_IF),     rd_rm),
cC3(rnddp,    e3081a0, 2, (RF, RF_IF),     rd_rm),
cC3(rnddm,    e3081c0, 2, (RF, RF_IF),     rd_rm),
cC3(rnddz,    e3081e0, 2, (RF, RF_IF),     rd_rm),
cC3(rnde,     e388100, 2, (RF, RF_IF),     rd_rm),
cC3(rndep,    e388120, 2, (RF, RF_IF),     rd_rm),
cC3(rndem,    e388140, 2, (RF, RF_IF),     rd_rm),
cC3(rndez,    e388160, 2, (RF, RF_IF),     rd_rm),
+
cC3(sqts,     e408100, 2, (RF, RF_IF),     rd_rm),
cC3(sqtsp,    e408120, 2, (RF, RF_IF),     rd_rm),
cC3(sqtsm,    e408140, 2, (RF, RF_IF),     rd_rm),
cC3(sqtsz,    e408160, 2, (RF, RF_IF),     rd_rm),
cC3(sqtd,     e408180, 2, (RF, RF_IF),     rd_rm),
cC3(sqtdp,    e4081a0, 2, (RF, RF_IF),     rd_rm),
cC3(sqtdm,    e4081c0, 2, (RF, RF_IF),     rd_rm),
cC3(sqtdz,    e4081e0, 2, (RF, RF_IF),     rd_rm),
cC3(sqte,     e488100, 2, (RF, RF_IF),     rd_rm),
cC3(sqtep,    e488120, 2, (RF, RF_IF),     rd_rm),
cC3(sqtem,    e488140, 2, (RF, RF_IF),     rd_rm),
cC3(sqtez,    e488160, 2, (RF, RF_IF),     rd_rm),
+
cC3(logs,     e508100, 2, (RF, RF_IF),     rd_rm),
cC3(logsp,    e508120, 2, (RF, RF_IF),     rd_rm),
cC3(logsm,    e508140, 2, (RF, RF_IF),     rd_rm),
cC3(logsz,    e508160, 2, (RF, RF_IF),     rd_rm),
cC3(logd,     e508180, 2, (RF, RF_IF),     rd_rm),
cC3(logdp,    e5081a0, 2, (RF, RF_IF),     rd_rm),
cC3(logdm,    e5081c0, 2, (RF, RF_IF),     rd_rm),
cC3(logdz,    e5081e0, 2, (RF, RF_IF),     rd_rm),
cC3(loge,     e588100, 2, (RF, RF_IF),     rd_rm),
cC3(logep,    e588120, 2, (RF, RF_IF),     rd_rm),
cC3(logem,    e588140, 2, (RF, RF_IF),     rd_rm),
cC3(logez,    e588160, 2, (RF, RF_IF),     rd_rm),
+
cC3(lgns,     e608100, 2, (RF, RF_IF),     rd_rm),
cC3(lgnsp,    e608120, 2, (RF, RF_IF),     rd_rm),
cC3(lgnsm,    e608140, 2, (RF, RF_IF),     rd_rm),
cC3(lgnsz,    e608160, 2, (RF, RF_IF),     rd_rm),
cC3(lgnd,     e608180, 2, (RF, RF_IF),     rd_rm),
cC3(lgndp,    e6081a0, 2, (RF, RF_IF),     rd_rm),
cC3(lgndm,    e6081c0, 2, (RF, RF_IF),     rd_rm),
cC3(lgndz,    e6081e0, 2, (RF, RF_IF),     rd_rm),
cC3(lgne,     e688100, 2, (RF, RF_IF),     rd_rm),
cC3(lgnep,    e688120, 2, (RF, RF_IF),     rd_rm),
cC3(lgnem,    e688140, 2, (RF, RF_IF),     rd_rm),
cC3(lgnez,    e688160, 2, (RF, RF_IF),     rd_rm),
+
cC3(exps,     e708100, 2, (RF, RF_IF),     rd_rm),
cC3(expsp,    e708120, 2, (RF, RF_IF),     rd_rm),
cC3(expsm,    e708140, 2, (RF, RF_IF),     rd_rm),
cC3(expsz,    e708160, 2, (RF, RF_IF),     rd_rm),
cC3(expd,     e708180, 2, (RF, RF_IF),     rd_rm),
cC3(expdp,    e7081a0, 2, (RF, RF_IF),     rd_rm),
cC3(expdm,    e7081c0, 2, (RF, RF_IF),     rd_rm),
cC3(expdz,    e7081e0, 2, (RF, RF_IF),     rd_rm),
cC3(expe,     e788100, 2, (RF, RF_IF),     rd_rm),
cC3(expep,    e788120, 2, (RF, RF_IF),     rd_rm),
cC3(expem,    e788140, 2, (RF, RF_IF),     rd_rm),
cC3(expdz,    e788160, 2, (RF, RF_IF),     rd_rm),
+
cC3(sins,     e808100, 2, (RF, RF_IF),     rd_rm),
cC3(sinsp,    e808120, 2, (RF, RF_IF),     rd_rm),
cC3(sinsm,    e808140, 2, (RF, RF_IF),     rd_rm),
cC3(sinsz,    e808160, 2, (RF, RF_IF),     rd_rm),
cC3(sind,     e808180, 2, (RF, RF_IF),     rd_rm),
cC3(sindp,    e8081a0, 2, (RF, RF_IF),     rd_rm),
cC3(sindm,    e8081c0, 2, (RF, RF_IF),     rd_rm),
cC3(sindz,    e8081e0, 2, (RF, RF_IF),     rd_rm),
cC3(sine,     e888100, 2, (RF, RF_IF),     rd_rm),
cC3(sinep,    e888120, 2, (RF, RF_IF),     rd_rm),
cC3(sinem,    e888140, 2, (RF, RF_IF),     rd_rm),
cC3(sinez,    e888160, 2, (RF, RF_IF),     rd_rm),
+
cC3(coss,     e908100, 2, (RF, RF_IF),     rd_rm),
cC3(cossp,    e908120, 2, (RF, RF_IF),     rd_rm),
cC3(cossm,    e908140, 2, (RF, RF_IF),     rd_rm),
cC3(cossz,    e908160, 2, (RF, RF_IF),     rd_rm),
cC3(cosd,     e908180, 2, (RF, RF_IF),     rd_rm),
cC3(cosdp,    e9081a0, 2, (RF, RF_IF),     rd_rm),
cC3(cosdm,    e9081c0, 2, (RF, RF_IF),     rd_rm),
cC3(cosdz,    e9081e0, 2, (RF, RF_IF),     rd_rm),
cC3(cose,     e988100, 2, (RF, RF_IF),     rd_rm),
cC3(cosep,    e988120, 2, (RF, RF_IF),     rd_rm),
cC3(cosem,    e988140, 2, (RF, RF_IF),     rd_rm),
cC3(cosez,    e988160, 2, (RF, RF_IF),     rd_rm),
+
cC3(tans,     ea08100, 2, (RF, RF_IF),     rd_rm),
cC3(tansp,    ea08120, 2, (RF, RF_IF),     rd_rm),
cC3(tansm,    ea08140, 2, (RF, RF_IF),     rd_rm),
cC3(tansz,    ea08160, 2, (RF, RF_IF),     rd_rm),
cC3(tand,     ea08180, 2, (RF, RF_IF),     rd_rm),
cC3(tandp,    ea081a0, 2, (RF, RF_IF),     rd_rm),
cC3(tandm,    ea081c0, 2, (RF, RF_IF),     rd_rm),
cC3(tandz,    ea081e0, 2, (RF, RF_IF),     rd_rm),
cC3(tane,     ea88100, 2, (RF, RF_IF),     rd_rm),
cC3(tanep,    ea88120, 2, (RF, RF_IF),     rd_rm),
cC3(tanem,    ea88140, 2, (RF, RF_IF),     rd_rm),
cC3(tanez,    ea88160, 2, (RF, RF_IF),     rd_rm),
+
cC3(asns,     eb08100, 2, (RF, RF_IF),     rd_rm),
cC3(asnsp,    eb08120, 2, (RF, RF_IF),     rd_rm),
cC3(asnsm,    eb08140, 2, (RF, RF_IF),     rd_rm),
cC3(asnsz,    eb08160, 2, (RF, RF_IF),     rd_rm),
cC3(asnd,     eb08180, 2, (RF, RF_IF),     rd_rm),
cC3(asndp,    eb081a0, 2, (RF, RF_IF),     rd_rm),
cC3(asndm,    eb081c0, 2, (RF, RF_IF),     rd_rm),
cC3(asndz,    eb081e0, 2, (RF, RF_IF),     rd_rm),
cC3(asne,     eb88100, 2, (RF, RF_IF),     rd_rm),
cC3(asnep,    eb88120, 2, (RF, RF_IF),     rd_rm),
cC3(asnem,    eb88140, 2, (RF, RF_IF),     rd_rm),
cC3(asnez,    eb88160, 2, (RF, RF_IF),     rd_rm),
+
cC3(acss,     ec08100, 2, (RF, RF_IF),     rd_rm),
cC3(acssp,    ec08120, 2, (RF, RF_IF),     rd_rm),
cC3(acssm,    ec08140, 2, (RF, RF_IF),     rd_rm),
cC3(acssz,    ec08160, 2, (RF, RF_IF),     rd_rm),
cC3(acsd,     ec08180, 2, (RF, RF_IF),     rd_rm),
cC3(acsdp,    ec081a0, 2, (RF, RF_IF),     rd_rm),
cC3(acsdm,    ec081c0, 2, (RF, RF_IF),     rd_rm),
cC3(acsdz,    ec081e0, 2, (RF, RF_IF),     rd_rm),
cC3(acse,     ec88100, 2, (RF, RF_IF),     rd_rm),
cC3(acsep,    ec88120, 2, (RF, RF_IF),     rd_rm),
cC3(acsem,    ec88140, 2, (RF, RF_IF),     rd_rm),
cC3(acsez,    ec88160, 2, (RF, RF_IF),     rd_rm),
+
cC3(atns,     ed08100, 2, (RF, RF_IF),     rd_rm),
cC3(atnsp,    ed08120, 2, (RF, RF_IF),     rd_rm),
cC3(atnsm,    ed08140, 2, (RF, RF_IF),     rd_rm),
cC3(atnsz,    ed08160, 2, (RF, RF_IF),     rd_rm),
cC3(atnd,     ed08180, 2, (RF, RF_IF),     rd_rm),
cC3(atndp,    ed081a0, 2, (RF, RF_IF),     rd_rm),
cC3(atndm,    ed081c0, 2, (RF, RF_IF),     rd_rm),
cC3(atndz,    ed081e0, 2, (RF, RF_IF),     rd_rm),
cC3(atne,     ed88100, 2, (RF, RF_IF),     rd_rm),
cC3(atnep,    ed88120, 2, (RF, RF_IF),     rd_rm),
cC3(atnem,    ed88140, 2, (RF, RF_IF),     rd_rm),
cC3(atnez,    ed88160, 2, (RF, RF_IF),     rd_rm),
+
cC3(urds,     ee08100, 2, (RF, RF_IF),     rd_rm),
cC3(urdsp,    ee08120, 2, (RF, RF_IF),     rd_rm),
cC3(urdsm,    ee08140, 2, (RF, RF_IF),     rd_rm),
cC3(urdsz,    ee08160, 2, (RF, RF_IF),     rd_rm),
cC3(urdd,     ee08180, 2, (RF, RF_IF),     rd_rm),
cC3(urddp,    ee081a0, 2, (RF, RF_IF),     rd_rm),
cC3(urddm,    ee081c0, 2, (RF, RF_IF),     rd_rm),
cC3(urddz,    ee081e0, 2, (RF, RF_IF),     rd_rm),
cC3(urde,     ee88100, 2, (RF, RF_IF),     rd_rm),
cC3(urdep,    ee88120, 2, (RF, RF_IF),     rd_rm),
cC3(urdem,    ee88140, 2, (RF, RF_IF),     rd_rm),
cC3(urdez,    ee88160, 2, (RF, RF_IF),     rd_rm),
+
cC3(nrms,     ef08100, 2, (RF, RF_IF),     rd_rm),
cC3(nrmsp,    ef08120, 2, (RF, RF_IF),     rd_rm),
cC3(nrmsm,    ef08140, 2, (RF, RF_IF),     rd_rm),
cC3(nrmsz,    ef08160, 2, (RF, RF_IF),     rd_rm),
cC3(nrmd,     ef08180, 2, (RF, RF_IF),     rd_rm),
cC3(nrmdp,    ef081a0, 2, (RF, RF_IF),     rd_rm),
cC3(nrmdm,    ef081c0, 2, (RF, RF_IF),     rd_rm),
cC3(nrmdz,    ef081e0, 2, (RF, RF_IF),     rd_rm),
cC3(nrme,     ef88100, 2, (RF, RF_IF),     rd_rm),
cC3(nrmep,    ef88120, 2, (RF, RF_IF),     rd_rm),
cC3(nrmem,    ef88140, 2, (RF, RF_IF),     rd_rm),
cC3(nrmez,    ef88160, 2, (RF, RF_IF),     rd_rm),
+
cC3(adfs,     e000100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(adfsp,    e000120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(adfsm,    e000140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(adfsz,    e000160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(adfd,     e000180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(adfdp,    e0001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(adfdm,    e0001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(adfdz,    e0001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(adfe,     e080100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(adfep,    e080120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(adfem,    e080140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(adfez,    e080160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(sufs,     e200100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(sufsp,    e200120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(sufsm,    e200140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(sufsz,    e200160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(sufd,     e200180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(sufdp,    e2001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(sufdm,    e2001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(sufdz,    e2001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(sufe,     e280100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(sufep,    e280120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(sufem,    e280140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(sufez,    e280160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(rsfs,     e300100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rsfsp,    e300120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rsfsm,    e300140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rsfsz,    e300160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rsfd,     e300180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rsfdp,    e3001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rsfdm,    e3001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rsfdz,    e3001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rsfe,     e380100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rsfep,    e380120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rsfem,    e380140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rsfez,    e380160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(mufs,     e100100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(mufsp,    e100120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(mufsm,    e100140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(mufsz,    e100160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(mufd,     e100180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(mufdp,    e1001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(mufdm,    e1001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(mufdz,    e1001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(mufe,     e180100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(mufep,    e180120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(mufem,    e180140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(mufez,    e180160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(dvfs,     e400100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(dvfsp,    e400120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(dvfsm,    e400140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(dvfsz,    e400160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(dvfd,     e400180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(dvfdp,    e4001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(dvfdm,    e4001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(dvfdz,    e4001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(dvfe,     e480100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(dvfep,    e480120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(dvfem,    e480140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(dvfez,    e480160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(rdfs,     e500100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rdfsp,    e500120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rdfsm,    e500140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rdfsz,    e500160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rdfd,     e500180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rdfdp,    e5001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rdfdm,    e5001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rdfdz,    e5001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rdfe,     e580100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rdfep,    e580120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rdfem,    e580140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rdfez,    e580160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(pows,     e600100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(powsp,    e600120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(powsm,    e600140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(powsz,    e600160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(powd,     e600180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(powdp,    e6001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(powdm,    e6001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(powdz,    e6001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(powe,     e680100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(powep,    e680120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(powem,    e680140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(powez,    e680160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(rpws,     e700100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rpwsp,    e700120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rpwsm,    e700140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rpwsz,    e700160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rpwd,     e700180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rpwdp,    e7001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rpwdm,    e7001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rpwdz,    e7001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rpwe,     e780100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rpwep,    e780120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rpwem,    e780140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rpwez,    e780160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(rmfs,     e800100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rmfsp,    e800120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rmfsm,    e800140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rmfsz,    e800160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rmfd,     e800180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rmfdp,    e8001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rmfdm,    e8001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rmfdz,    e8001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rmfe,     e880100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rmfep,    e880120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rmfem,    e880140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(rmfez,    e880160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(fmls,     e900100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fmlsp,    e900120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fmlsm,    e900140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fmlsz,    e900160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fmld,     e900180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fmldp,    e9001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fmldm,    e9001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fmldz,    e9001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fmle,     e980100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fmlep,    e980120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fmlem,    e980140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fmlez,    e980160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(fdvs,     ea00100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fdvsp,    ea00120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fdvsm,    ea00140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fdvsz,    ea00160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fdvd,     ea00180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fdvdp,    ea001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fdvdm,    ea001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fdvdz,    ea001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fdve,     ea80100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fdvep,    ea80120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fdvem,    ea80140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(fdvez,    ea80160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(frds,     eb00100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(frdsp,    eb00120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(frdsm,    eb00140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(frdsz,    eb00160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(frdd,     eb00180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(frddp,    eb001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(frddm,    eb001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(frddz,    eb001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(frde,     eb80100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(frdep,    eb80120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(frdem,    eb80140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(frdez,    eb80160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cC3(pols,     ec00100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(polsp,    ec00120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(polsm,    ec00140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(polsz,    ec00160, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(pold,     ec00180, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(poldp,    ec001a0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(poldm,    ec001c0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(poldz,    ec001e0, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(pole,     ec80100, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(polep,    ec80120, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(polem,    ec80140, 3, (RF, RF, RF_IF), rd_rn_rm),
cC3(polez,    ec80160, 3, (RF, RF, RF_IF), rd_rn_rm),
+
cCE(cmf,      e90f110, 2, (RF, RF_IF),     fpa_cmp),
  C3E(cmfe,     ed0f110, 2, (RF, RF_IF),     fpa_cmp),
 CE(cnf,      eb0f110, 2, (RF, RF_IF),     fpa_cmp),
cCE(cnf,      eb0f110, 2, (RF, RF_IF),     fpa_cmp),
  C3E(cnfe,     ef0f110, 2, (RF, RF_IF),     fpa_cmp),
 
 C3(flts,     e000110, 2, (RF, RR),        rn_rd),
 C3(fltsp,    e000130, 2, (RF, RR),        rn_rd),
 C3(fltsm,    e000150, 2, (RF, RR),        rn_rd),
 C3(fltsz,    e000170, 2, (RF, RR),        rn_rd),
 C3(fltd,     e000190, 2, (RF, RR),        rn_rd),
 C3(fltdp,    e0001b0, 2, (RF, RR),        rn_rd),
 C3(fltdm,    e0001d0, 2, (RF, RR),        rn_rd),
 C3(fltdz,    e0001f0, 2, (RF, RR),        rn_rd),
 C3(flte,     e080110, 2, (RF, RR),        rn_rd),
 C3(fltep,    e080130, 2, (RF, RR),        rn_rd),
 C3(fltem,    e080150, 2, (RF, RR),        rn_rd),
 C3(fltez,    e080170, 2, (RF, RR),        rn_rd),
cC3(flts,     e000110, 2, (RF, RR),        rn_rd),
cC3(fltsp,    e000130, 2, (RF, RR),        rn_rd),
cC3(fltsm,    e000150, 2, (RF, RR),        rn_rd),
cC3(fltsz,    e000170, 2, (RF, RR),        rn_rd),
cC3(fltd,     e000190, 2, (RF, RR),        rn_rd),
cC3(fltdp,    e0001b0, 2, (RF, RR),        rn_rd),
cC3(fltdm,    e0001d0, 2, (RF, RR),        rn_rd),
cC3(fltdz,    e0001f0, 2, (RF, RR),        rn_rd),
cC3(flte,     e080110, 2, (RF, RR),        rn_rd),
cC3(fltep,    e080130, 2, (RF, RR),        rn_rd),
cC3(fltem,    e080150, 2, (RF, RR),        rn_rd),
cC3(fltez,    e080170, 2, (RF, RR),        rn_rd),
 
   /* 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.  */
 CE(fix,      e100110, 2, (RR, RF),        rd_rm),
 C3(fixp,     e100130, 2, (RR, RF),        rd_rm),
 C3(fixm,     e100150, 2, (RR, RF),        rd_rm),
 C3(fixz,     e100170, 2, (RR, RF),        rd_rm),
 C3(fixsp,    e100130, 2, (RR, RF),        rd_rm),
 C3(fixsm,    e100150, 2, (RR, RF),        rd_rm),
 C3(fixsz,    e100170, 2, (RR, RF),        rd_rm),
 C3(fixdp,    e100130, 2, (RR, RF),        rd_rm),
 C3(fixdm,    e100150, 2, (RR, RF),        rd_rm),
 C3(fixdz,    e100170, 2, (RR, RF),        rd_rm),
 C3(fixep,    e100130, 2, (RR, RF),        rd_rm),
 C3(fixem,    e100150, 2, (RR, RF),        rd_rm),
 C3(fixez,    e100170, 2, (RR, RF),        rd_rm),
cCE(fix,      e100110, 2, (RR, RF),        rd_rm),
cC3(fixp,     e100130, 2, (RR, RF),        rd_rm),
cC3(fixm,     e100150, 2, (RR, RF),        rd_rm),
cC3(fixz,     e100170, 2, (RR, RF),        rd_rm),
cC3(fixsp,    e100130, 2, (RR, RF),        rd_rm),
cC3(fixsm,    e100150, 2, (RR, RF),        rd_rm),
cC3(fixsz,    e100170, 2, (RR, RF),        rd_rm),
cC3(fixdp,    e100130, 2, (RR, RF),        rd_rm),
cC3(fixdm,    e100150, 2, (RR, RF),        rd_rm),
cC3(fixdz,    e100170, 2, (RR, RF),        rd_rm),
cC3(fixep,    e100130, 2, (RR, RF),        rd_rm),
cC3(fixem,    e100150, 2, (RR, RF),        rd_rm),
cC3(fixez,    e100170, 2, (RR, RF),        rd_rm),
 
   /* Instructions that were new with the real FPA, call them V2.  */
 #undef ARM_VARIANT
 #define ARM_VARIANT FPU_FPA_EXT_V2
 CE(lfm,      c100200, 3, (RF, I4b, ADDR), fpa_ldmstm),
 C3(lfmfd,    c900200, 3, (RF, I4b, ADDR), fpa_ldmstm),
 C3(lfmea,    d100200, 3, (RF, I4b, ADDR), fpa_ldmstm),
 CE(sfm,      c000200, 3, (RF, I4b, ADDR), fpa_ldmstm),
 C3(sfmfd,    d000200, 3, (RF, I4b, ADDR), fpa_ldmstm),
 C3(sfmea,    c800200, 3, (RF, I4b, ADDR), fpa_ldmstm),
cCE(lfm,      c100200, 3, (RF, I4b, ADDR), fpa_ldmstm),
cC3(lfmfd,    c900200, 3, (RF, I4b, ADDR), fpa_ldmstm),
cC3(lfmea,    d100200, 3, (RF, I4b, ADDR), fpa_ldmstm),
cCE(sfm,      c000200, 3, (RF, I4b, ADDR), fpa_ldmstm),
cC3(sfmfd,    d000200, 3, (RF, I4b, ADDR), fpa_ldmstm),
cC3(sfmea,    c800200, 3, (RF, I4b, ADDR), fpa_ldmstm),
 
 #undef ARM_VARIANT
 #define ARM_VARIANT FPU_VFP_EXT_V1xD  /* VFP V1xD (single precision).  */
   /* Moves and type conversions.  */
 CE(fcpys,    eb00a40, 2, (RVS, RVS),       vfp_sp_monadic),
 CE(fmrs,     e100a10, 2, (RR, RVS),        vfp_reg_from_sp),
 CE(fmsr,     e000a10, 2, (RVS, RR),        vfp_sp_from_reg),
 CE(fmstat,   ef1fa10, 0, (),               noargs),
 CE(fsitos,   eb80ac0, 2, (RVS, RVS),       vfp_sp_monadic),
 CE(fuitos,   eb80a40, 2, (RVS, RVS),       vfp_sp_monadic),
 CE(ftosis,   ebd0a40, 2, (RVS, RVS),       vfp_sp_monadic),
 CE(ftosizs,  ebd0ac0, 2, (RVS, RVS),       vfp_sp_monadic),
 CE(ftouis,   ebc0a40, 2, (RVS, RVS),       vfp_sp_monadic),
 CE(ftouizs,  ebc0ac0, 2, (RVS, RVS),       vfp_sp_monadic),
 CE(fmrx,     ef00a10, 2, (RR, RVC),        rd_rn),
 CE(fmxr,     ee00a10, 2, (RVC, RR),        rn_rd),
cCE(fcpys,    eb00a40, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(fmrs,     e100a10, 2, (RR, RVS),        vfp_reg_from_sp),
cCE(fmsr,     e000a10, 2, (RVS, RR),        vfp_sp_from_reg),
cCE(fmstat,   ef1fa10, 0, (),               noargs),
cCE(fsitos,   eb80ac0, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(fuitos,   eb80a40, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(ftosis,   ebd0a40, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(ftosizs,  ebd0ac0, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(ftouis,   ebc0a40, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(ftouizs,  ebc0ac0, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(fmrx,     ef00a10, 2, (RR, RVC),        rd_rn),
cCE(fmxr,     ee00a10, 2, (RVC, RR),        rn_rd),
 
   /* Memory operations.         */
 CE(flds,     d100a00, 2, (RVS, ADDR),      vfp_sp_ldst),
 CE(fsts,     d000a00, 2, (RVS, ADDR),      vfp_sp_ldst),
 CE(fldmias,  c900a00, 2, (RRw, VRSLST),    vfp_sp_ldstmia),
 CE(fldmfds,  c900a00, 2, (RRw, VRSLST),    vfp_sp_ldstmia),
 CE(fldmdbs,  d300a00, 2, (RRw, VRSLST),    vfp_sp_ldstmdb),
 CE(fldmeas,  d300a00, 2, (RRw, VRSLST),    vfp_sp_ldstmdb),
 CE(fldmiax,  c900b00, 2, (RRw, VRDLST),    vfp_xp_ldstmia),
 CE(fldmfdx,  c900b00, 2, (RRw, VRDLST),    vfp_xp_ldstmia),
 CE(fldmdbx,  d300b00, 2, (RRw, VRDLST),    vfp_xp_ldstmdb),
 CE(fldmeax,  d300b00, 2, (RRw, VRDLST),    vfp_xp_ldstmdb),
 CE(fstmias,  c800a00, 2, (RRw, VRSLST),    vfp_sp_ldstmia),
 CE(fstmeas,  c800a00, 2, (RRw, VRSLST),    vfp_sp_ldstmia),
 CE(fstmdbs,  d200a00, 2, (RRw, VRSLST),    vfp_sp_ldstmdb),
 CE(fstmfds,  d200a00, 2, (RRw, VRSLST),    vfp_sp_ldstmdb),
 CE(fstmiax,  c800b00, 2, (RRw, VRDLST),    vfp_xp_ldstmia),
 CE(fstmeax,  c800b00, 2, (RRw, VRDLST),    vfp_xp_ldstmia),
 CE(fstmdbx,  d200b00, 2, (RRw, VRDLST),    vfp_xp_ldstmdb),
 CE(fstmfdx,  d200b00, 2, (RRw, VRDLST),    vfp_xp_ldstmdb),
cCE(flds,     d100a00, 2, (RVS, ADDR),      vfp_sp_ldst),
cCE(fsts,     d000a00, 2, (RVS, ADDR),      vfp_sp_ldst),
cCE(fldmias,  c900a00, 2, (RRw, VRSLST),    vfp_sp_ldstmia),
cCE(fldmfds,  c900a00, 2, (RRw, VRSLST),    vfp_sp_ldstmia),
cCE(fldmdbs,  d300a00, 2, (RRw, VRSLST),    vfp_sp_ldstmdb),
cCE(fldmeas,  d300a00, 2, (RRw, VRSLST),    vfp_sp_ldstmdb),
cCE(fldmiax,  c900b00, 2, (RRw, VRDLST),    vfp_xp_ldstmia),
cCE(fldmfdx,  c900b00, 2, (RRw, VRDLST),    vfp_xp_ldstmia),
cCE(fldmdbx,  d300b00, 2, (RRw, VRDLST),    vfp_xp_ldstmdb),
cCE(fldmeax,  d300b00, 2, (RRw, VRDLST),    vfp_xp_ldstmdb),
cCE(fstmias,  c800a00, 2, (RRw, VRSLST),    vfp_sp_ldstmia),
cCE(fstmeas,  c800a00, 2, (RRw, VRSLST),    vfp_sp_ldstmia),
cCE(fstmdbs,  d200a00, 2, (RRw, VRSLST),    vfp_sp_ldstmdb),
cCE(fstmfds,  d200a00, 2, (RRw, VRSLST),    vfp_sp_ldstmdb),
cCE(fstmiax,  c800b00, 2, (RRw, VRDLST),    vfp_xp_ldstmia),
cCE(fstmeax,  c800b00, 2, (RRw, VRDLST),    vfp_xp_ldstmia),
cCE(fstmdbx,  d200b00, 2, (RRw, VRDLST),    vfp_xp_ldstmdb),
cCE(fstmfdx,  d200b00, 2, (RRw, VRDLST),    vfp_xp_ldstmdb),
 
   /* Monadic operations.  */
 CE(fabss,    eb00ac0, 2, (RVS, RVS),       vfp_sp_monadic),
 CE(fnegs,    eb10a40, 2, (RVS, RVS),       vfp_sp_monadic),
 CE(fsqrts,   eb10ac0, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(fabss,    eb00ac0, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(fnegs,    eb10a40, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(fsqrts,   eb10ac0, 2, (RVS, RVS),       vfp_sp_monadic),
 
   /* Dyadic operations.         */
 CE(fadds,    e300a00, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
 CE(fsubs,    e300a40, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
 CE(fmuls,    e200a00, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
 CE(fdivs,    e800a00, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
 CE(fmacs,    e000a00, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
 CE(fmscs,    e100a00, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
 CE(fnmuls,   e200a40, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
 CE(fnmacs,   e000a40, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
 CE(fnmscs,   e100a40, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
cCE(fadds,    e300a00, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
cCE(fsubs,    e300a40, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
cCE(fmuls,    e200a00, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
cCE(fdivs,    e800a00, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
cCE(fmacs,    e000a00, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
cCE(fmscs,    e100a00, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
cCE(fnmuls,   e200a40, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
cCE(fnmacs,   e000a40, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
cCE(fnmscs,   e100a40, 3, (RVS, RVS, RVS),  vfp_sp_dyadic),
 
   /* Comparisons.  */
 CE(fcmps,    eb40a40, 2, (RVS, RVS),       vfp_sp_monadic),
 CE(fcmpzs,   eb50a40, 1, (RVS),            vfp_sp_compare_z),
 CE(fcmpes,   eb40ac0, 2, (RVS, RVS),       vfp_sp_monadic),
 CE(fcmpezs,  eb50ac0, 1, (RVS),            vfp_sp_compare_z),
cCE(fcmps,    eb40a40, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(fcmpzs,   eb50a40, 1, (RVS),            vfp_sp_compare_z),
cCE(fcmpes,   eb40ac0, 2, (RVS, RVS),       vfp_sp_monadic),
cCE(fcmpezs,  eb50ac0, 1, (RVS),            vfp_sp_compare_z),
 
 #undef ARM_VARIANT
 #define ARM_VARIANT FPU_VFP_EXT_V1 /* VFP V1 (Double precision).  */
   /* Moves and type conversions.  */
 CE(fcpyd,    eb00b40, 2, (RVD, RVD),       rd_rm),
 CE(fcvtds,   eb70ac0, 2, (RVD, RVS),       vfp_dp_sp_cvt),
 CE(fcvtsd,   eb70bc0, 2, (RVS, RVD),       vfp_sp_dp_cvt),
 CE(fmdhr,    e200b10, 2, (RVD, RR),        rn_rd),
 CE(fmdlr,    e000b10, 2, (RVD, RR),        rn_rd),
 CE(fmrdh,    e300b10, 2, (RR, RVD),        rd_rn),
 CE(fmrdl,    e100b10, 2, (RR, RVD),        rd_rn),
 CE(fsitod,   eb80bc0, 2, (RVD, RVS),       vfp_dp_sp_cvt),
 CE(fuitod,   eb80b40, 2, (RVD, RVS),       vfp_dp_sp_cvt),
 CE(ftosid,   ebd0b40, 2, (RVS, RVD),       vfp_sp_dp_cvt),
 CE(ftosizd,  ebd0bc0, 2, (RVS, RVD),       vfp_sp_dp_cvt),
 CE(ftouid,   ebc0b40, 2, (RVS, RVD),       vfp_sp_dp_cvt),
 CE(ftouizd,  ebc0bc0, 2, (RVS, RVD),       vfp_sp_dp_cvt),
cCE(fcpyd,    eb00b40, 2, (RVD, RVD),       rd_rm),
cCE(fcvtds,   eb70ac0, 2, (RVD, RVS),       vfp_dp_sp_cvt),
cCE(fcvtsd,   eb70bc0, 2, (RVS, RVD),       vfp_sp_dp_cvt),
cCE(fmdhr,    e200b10, 2, (RVD, RR),        rn_rd),
cCE(fmdlr,    e000b10, 2, (RVD, RR),        rn_rd),
cCE(fmrdh,    e300b10, 2, (RR, RVD),        rd_rn),
cCE(fmrdl,    e100b10, 2, (RR, RVD),        rd_rn),
cCE(fsitod,   eb80bc0, 2, (RVD, RVS),       vfp_dp_sp_cvt),
cCE(fuitod,   eb80b40, 2, (RVD, RVS),       vfp_dp_sp_cvt),
cCE(ftosid,   ebd0b40, 2, (RVS, RVD),       vfp_sp_dp_cvt),
cCE(ftosizd,  ebd0bc0, 2, (RVS, RVD),       vfp_sp_dp_cvt),
cCE(ftouid,   ebc0b40, 2, (RVS, RVD),       vfp_sp_dp_cvt),
cCE(ftouizd,  ebc0bc0, 2, (RVS, RVD),       vfp_sp_dp_cvt),
 
   /* Memory operations.         */
 CE(fldd,     d100b00, 2, (RVD, ADDR),      vfp_dp_ldst),
 CE(fstd,     d000b00, 2, (RVD, ADDR),      vfp_dp_ldst),
 CE(fldmiad,  c900b00, 2, (RRw, VRDLST),    vfp_dp_ldstmia),
 CE(fldmfdd,  c900b00, 2, (RRw, VRDLST),    vfp_dp_ldstmia),
 CE(fldmdbd,  d300b00, 2, (RRw, VRDLST),    vfp_dp_ldstmdb),
 CE(fldmead,  d300b00, 2, (RRw, VRDLST),    vfp_dp_ldstmdb),
 CE(fstmiad,  c800b00, 2, (RRw, VRDLST),    vfp_dp_ldstmia),
 CE(fstmead,  c800b00, 2, (RRw, VRDLST),    vfp_dp_ldstmia),
 CE(fstmdbd,  d200b00, 2, (RRw, VRDLST),    vfp_dp_ldstmdb),
 CE(fstmfdd,  d200b00, 2, (RRw, VRDLST),    vfp_dp_ldstmdb),
cCE(fldd,     d100b00, 2, (RVD, ADDR),      vfp_dp_ldst),
cCE(fstd,     d000b00, 2, (RVD, ADDR),      vfp_dp_ldst),
cCE(fldmiad,  c900b00, 2, (RRw, VRDLST),    vfp_dp_ldstmia),
cCE(fldmfdd,  c900b00, 2, (RRw, VRDLST),    vfp_dp_ldstmia),
cCE(fldmdbd,  d300b00, 2, (RRw, VRDLST),    vfp_dp_ldstmdb),
cCE(fldmead,  d300b00, 2, (RRw, VRDLST),    vfp_dp_ldstmdb),
cCE(fstmiad,  c800b00, 2, (RRw, VRDLST),    vfp_dp_ldstmia),
cCE(fstmead,  c800b00, 2, (RRw, VRDLST),    vfp_dp_ldstmia),
cCE(fstmdbd,  d200b00, 2, (RRw, VRDLST),    vfp_dp_ldstmdb),
cCE(fstmfdd,  d200b00, 2, (RRw, VRDLST),    vfp_dp_ldstmdb),
 
   /* Monadic operations.  */
 CE(fabsd,    eb00bc0, 2, (RVD, RVD),       rd_rm),
 CE(fnegd,    eb10b40, 2, (RVD, RVD),       rd_rm),
 CE(fsqrtd,   eb10bc0, 2, (RVD, RVD),       rd_rm),
cCE(fabsd,    eb00bc0, 2, (RVD, RVD),       rd_rm),
cCE(fnegd,    eb10b40, 2, (RVD, RVD),       rd_rm),
cCE(fsqrtd,   eb10bc0, 2, (RVD, RVD),       rd_rm),
 
   /* Dyadic operations.         */
 CE(faddd,    e300b00, 3, (RVD, RVD, RVD),  rd_rn_rm),
 CE(fsubd,    e300b40, 3, (RVD, RVD, RVD),  rd_rn_rm),
 CE(fmuld,    e200b00, 3, (RVD, RVD, RVD),  rd_rn_rm),
 CE(fdivd,    e800b00, 3, (RVD, RVD, RVD),  rd_rn_rm),
 CE(fmacd,    e000b00, 3, (RVD, RVD, RVD),  rd_rn_rm),
 CE(fmscd,    e100b00, 3, (RVD, RVD, RVD),  rd_rn_rm),
 CE(fnmuld,   e200b40, 3, (RVD, RVD, RVD),  rd_rn_rm),
 CE(fnmacd,   e000b40, 3, (RVD, RVD, RVD),  rd_rn_rm),
 CE(fnmscd,   e100b40, 3, (RVD, RVD, RVD),  rd_rn_rm),
cCE(faddd,    e300b00, 3, (RVD, RVD, RVD),  rd_rn_rm),
cCE(fsubd,    e300b40, 3, (RVD, RVD, RVD),  rd_rn_rm),
cCE(fmuld,    e200b00, 3, (RVD, RVD, RVD),  rd_rn_rm),
cCE(fdivd,    e800b00, 3, (RVD, RVD, RVD),  rd_rn_rm),
cCE(fmacd,    e000b00, 3, (RVD, RVD, RVD),  rd_rn_rm),
cCE(fmscd,    e100b00, 3, (RVD, RVD, RVD),  rd_rn_rm),
cCE(fnmuld,   e200b40, 3, (RVD, RVD, RVD),  rd_rn_rm),
cCE(fnmacd,   e000b40, 3, (RVD, RVD, RVD),  rd_rn_rm),
cCE(fnmscd,   e100b40, 3, (RVD, RVD, RVD),  rd_rn_rm),
 
   /* Comparisons.  */
 CE(fcmpd,    eb40b40, 2, (RVD, RVD),       rd_rm),
 CE(fcmpzd,   eb50b40, 1, (RVD),            rd),
 CE(fcmped,   eb40bc0, 2, (RVD, RVD),       rd_rm),
 CE(fcmpezd,  eb50bc0, 1, (RVD),            rd),
cCE(fcmpd,    eb40b40, 2, (RVD, RVD),       rd_rm),
cCE(fcmpzd,   eb50b40, 1, (RVD),            rd),
cCE(fcmped,   eb40bc0, 2, (RVD, RVD),       rd_rm),
cCE(fcmpezd,  eb50bc0, 1, (RVD),            rd),
 
 #undef ARM_VARIANT
 #define ARM_VARIANT FPU_VFP_EXT_V2
 CE(fmsrr,    c400a10, 3, (VRSLST, RR, RR), vfp_sp2_from_reg2),
 CE(fmrrs,    c500a10, 3, (RR, RR, VRSLST), vfp_reg2_from_sp2),
 CE(fmdrr,    c400b10, 3, (RVD, RR, RR),    rm_rd_rn),
 CE(fmrrd,    c500b10, 3, (RR, RR, RVD),    rd_rn_rm),
cCE(fmsrr,    c400a10, 3, (VRSLST, RR, RR), vfp_sp2_from_reg2),
cCE(fmrrs,    c500a10, 3, (RR, RR, VRSLST), vfp_reg2_from_sp2),
cCE(fmdrr,    c400b10, 3, (RVD, RR, RR),    rm_rd_rn),
cCE(fmrrd,    c500b10, 3, (RR, RR, RVD),    rd_rn_rm),
 
 #undef ARM_VARIANT
 #define ARM_VARIANT ARM_CEXT_XSCALE /* Intel XScale extensions.         */
 CE(mia,      e200010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
 CE(miaph,    e280010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
 CE(miabb,    e2c0010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
 CE(miabt,    e2d0010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
 CE(miatb,    e2e0010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
 CE(miatt,    e2f0010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
 CE(mar,      c400000, 3, (RXA, RRnpc, RRnpc), xsc_mar),
 CE(mra,      c500000, 3, (RRnpc, RRnpc, RXA), xsc_mra),
cCE(mia,      e200010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
cCE(miaph,    e280010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
cCE(miabb,    e2c0010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
cCE(miabt,    e2d0010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
cCE(miatb,    e2e0010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
cCE(miatt,    e2f0010, 3, (RXA, RRnpc, RRnpc), xsc_mia),
cCE(mar,      c400000, 3, (RXA, RRnpc, RRnpc), xsc_mar),
cCE(mra,      c500000, 3, (RRnpc, RRnpc, RXA), xsc_mra),
 
 #undef ARM_VARIANT
 #define ARM_VARIANT ARM_CEXT_IWMMXT /* Intel Wireless MMX technology.  */
 CE(tandcb,   e13f130, 1, (RR),                   iwmmxt_tandorc),
 CE(tandch,   e53f130, 1, (RR),                   iwmmxt_tandorc),
 CE(tandcw,   e93f130, 1, (RR),                   iwmmxt_tandorc),
 CE(tbcstb,   e400010, 2, (RIWR, RR),             rn_rd),
 CE(tbcsth,   e400050, 2, (RIWR, RR),             rn_rd),
 CE(tbcstw,   e400090, 2, (RIWR, RR),             rn_rd),
 CE(textrcb,  e130170, 2, (RR, I7),               iwmmxt_textrc),
 CE(textrch,  e530170, 2, (RR, I7),               iwmmxt_textrc),
 CE(textrcw,  e930170, 2, (RR, I7),               iwmmxt_textrc),
 CE(textrmub, e100070, 3, (RR, RIWR, I7),         iwmmxt_textrm),
 CE(textrmuh, e500070, 3, (RR, RIWR, I7),         iwmmxt_textrm),
 CE(textrmuw, e900070, 3, (RR, RIWR, I7),         iwmmxt_textrm),
 CE(textrmsb, e100078, 3, (RR, RIWR, I7),         iwmmxt_textrm),
 CE(textrmsh, e500078, 3, (RR, RIWR, I7),         iwmmxt_textrm),
 CE(textrmsw, e900078, 3, (RR, RIWR, I7),         iwmmxt_textrm),
 CE(tinsrb,   e600010, 3, (RIWR, RR, I7),         iwmmxt_tinsr),
 CE(tinsrh,   e600050, 3, (RIWR, RR, I7),         iwmmxt_tinsr),
 CE(tinsrw,   e600090, 3, (RIWR, RR, I7),         iwmmxt_tinsr),
 CE(tmcr,     e000110, 2, (RIWC, RR),             rn_rd),
 CE(tmcrr,    c400000, 3, (RIWR, RR, RR),         rm_rd_rn),
 CE(tmia,     e200010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
 CE(tmiaph,   e280010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
 CE(tmiabb,   e2c0010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
 CE(tmiabt,   e2d0010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
 CE(tmiatb,   e2e0010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
 CE(tmiatt,   e2f0010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
 CE(tmovmskb, e100030, 2, (RR, RIWR),             rd_rn),
 CE(tmovmskh, e500030, 2, (RR, RIWR),             rd_rn),
 CE(tmovmskw, e900030, 2, (RR, RIWR),             rd_rn),
 CE(tmrc,     e100110, 2, (RR, RIWC),             rd_rn),
 CE(tmrrc,    c500000, 3, (RR, RR, RIWR),         rd_rn_rm),
 CE(torcb,    e13f150, 1, (RR),                   iwmmxt_tandorc),
 CE(torch,    e53f150, 1, (RR),                   iwmmxt_tandorc),
 CE(torcw,    e93f150, 1, (RR),                   iwmmxt_tandorc),
 CE(waccb,    e0001c0, 2, (RIWR, RIWR),           rd_rn),
 CE(wacch,    e4001c0, 2, (RIWR, RIWR),           rd_rn),
 CE(waccw,    e8001c0, 2, (RIWR, RIWR),           rd_rn),
 CE(waddbss,  e300180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(waddb,    e000180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(waddbus,  e100180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(waddhss,  e700180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(waddh,    e400180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(waddhus,  e500180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(waddwss,  eb00180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(waddw,    e800180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(waddwus,  e900180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(waligni,  e000020, 4, (RIWR, RIWR, RIWR, I7), iwmmxt_waligni),
 CE(walignr0, e800020, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(walignr1, e900020, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(walignr2, ea00020, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(walignr3, eb00020, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wand,     e200000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wandn,    e300000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wavg2b,   e800000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wavg2br,  e900000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wavg2h,   ec00000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wavg2hr,  ed00000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wcmpeqb,  e000060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wcmpeqh,  e400060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wcmpeqw,  e800060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wcmpgtub, e100060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wcmpgtuh, e500060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wcmpgtuw, e900060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wcmpgtsb, e300060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wcmpgtsh, e700060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wcmpgtsw, eb00060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wldrb,    c100000, 2, (RIWR, ADDR),           iwmmxt_wldstbh),
 CE(wldrh,    c500000, 2, (RIWR, ADDR),           iwmmxt_wldstbh),
 CE(wldrw,    c100100, 2, (RIWR_RIWC, ADDR),      iwmmxt_wldstw),
 CE(wldrd,    c500100, 2, (RIWR, ADDR),           iwmmxt_wldstd),
 CE(wmacs,    e600100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmacsz,   e700100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmacu,    e400100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmacuz,   e500100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmadds,   ea00100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmaddu,   e800100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmaxsb,   e200160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmaxsh,   e600160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmaxsw,   ea00160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmaxub,   e000160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmaxuh,   e400160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmaxuw,   e800160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wminsb,   e300160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wminsh,   e700160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wminsw,   eb00160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wminub,   e100160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wminuh,   e500160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wminuw,   e900160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmov,     e000000, 2, (RIWR, RIWR),           iwmmxt_wmov),
 CE(wmulsm,   e300100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmulsl,   e200100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmulum,   e100100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wmulul,   e000100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wor,      e000000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wpackhss, e700080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wpackhus, e500080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wpackwss, eb00080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wpackwus, e900080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wpackdss, ef00080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wpackdus, ed00080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wrorh,    e700040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wrorhg,   e700148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wrorw,    eb00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wrorwg,   eb00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wrord,    ef00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wrordg,   ef00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wsadb,    e000120, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsadbz,   e100120, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsadh,    e400120, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsadhz,   e500120, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wshufh,   e0001e0, 3, (RIWR, RIWR, I255),     iwmmxt_wshufh),
 CE(wsllh,    e500040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsllhg,   e500148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wsllw,    e900040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsllwg,   e900148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wslld,    ed00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wslldg,   ed00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wsrah,    e400040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsrahg,   e400148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wsraw,    e800040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsrawg,   e800148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wsrad,    ec00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsradg,   ec00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wsrlh,    e600040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsrlhg,   e600148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wsrlw,    ea00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsrlwg,   ea00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wsrld,    ee00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsrldg,   ee00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
 CE(wstrb,    c000000, 2, (RIWR, ADDR),           iwmmxt_wldstbh),
 CE(wstrh,    c400000, 2, (RIWR, ADDR),           iwmmxt_wldstbh),
 CE(wstrw,    c000100, 2, (RIWR_RIWC, ADDR),      iwmmxt_wldstw),
 CE(wstrd,    c400100, 2, (RIWR, ADDR),           iwmmxt_wldstd),
 CE(wsubbss,  e3001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsubb,    e0001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsubbus,  e1001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsubhss,  e7001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsubh,    e4001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsubhus,  e5001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsubwss,  eb001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsubw,    e8001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wsubwus,  e9001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wunpckehub,e0000c0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckehuh,e4000c0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckehuw,e8000c0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckehsb,e2000c0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckehsh,e6000c0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckehsw,ea000c0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckihb, e1000c0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
 CE(wunpckihh, e5000c0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
 CE(wunpckihw, e9000c0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
 CE(wunpckelub,e0000e0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckeluh,e4000e0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckeluw,e8000e0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckelsb,e2000e0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckelsh,e6000e0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckelsw,ea000e0, 2, (RIWR, RIWR),          rd_rn),
 CE(wunpckilb, e1000e0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
 CE(wunpckilh, e5000e0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
 CE(wunpckilw, e9000e0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
 CE(wxor,     e100000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
 CE(wzero,    e300000, 1, (RIWR),                 iwmmxt_wzero),
cCE(tandcb,   e13f130, 1, (RR),                   iwmmxt_tandorc),
cCE(tandch,   e53f130, 1, (RR),                   iwmmxt_tandorc),
cCE(tandcw,   e93f130, 1, (RR),                   iwmmxt_tandorc),
cCE(tbcstb,   e400010, 2, (RIWR, RR),             rn_rd),
cCE(tbcsth,   e400050, 2, (RIWR, RR),             rn_rd),
cCE(tbcstw,   e400090, 2, (RIWR, RR),             rn_rd),
cCE(textrcb,  e130170, 2, (RR, I7),               iwmmxt_textrc),
cCE(textrch,  e530170, 2, (RR, I7),               iwmmxt_textrc),
cCE(textrcw,  e930170, 2, (RR, I7),               iwmmxt_textrc),
cCE(textrmub, e100070, 3, (RR, RIWR, I7),         iwmmxt_textrm),
cCE(textrmuh, e500070, 3, (RR, RIWR, I7),         iwmmxt_textrm),
cCE(textrmuw, e900070, 3, (RR, RIWR, I7),         iwmmxt_textrm),
cCE(textrmsb, e100078, 3, (RR, RIWR, I7),         iwmmxt_textrm),
cCE(textrmsh, e500078, 3, (RR, RIWR, I7),         iwmmxt_textrm),
cCE(textrmsw, e900078, 3, (RR, RIWR, I7),         iwmmxt_textrm),
cCE(tinsrb,   e600010, 3, (RIWR, RR, I7),         iwmmxt_tinsr),
cCE(tinsrh,   e600050, 3, (RIWR, RR, I7),         iwmmxt_tinsr),
cCE(tinsrw,   e600090, 3, (RIWR, RR, I7),         iwmmxt_tinsr),
cCE(tmcr,     e000110, 2, (RIWC, RR),             rn_rd),
cCE(tmcrr,    c400000, 3, (RIWR, RR, RR),         rm_rd_rn),
cCE(tmia,     e200010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
cCE(tmiaph,   e280010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
cCE(tmiabb,   e2c0010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
cCE(tmiabt,   e2d0010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
cCE(tmiatb,   e2e0010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
cCE(tmiatt,   e2f0010, 3, (RIWR, RR, RR),         iwmmxt_tmia),
cCE(tmovmskb, e100030, 2, (RR, RIWR),             rd_rn),
cCE(tmovmskh, e500030, 2, (RR, RIWR),             rd_rn),
cCE(tmovmskw, e900030, 2, (RR, RIWR),             rd_rn),
cCE(tmrc,     e100110, 2, (RR, RIWC),             rd_rn),
cCE(tmrrc,    c500000, 3, (RR, RR, RIWR),         rd_rn_rm),
cCE(torcb,    e13f150, 1, (RR),                   iwmmxt_tandorc),
cCE(torch,    e53f150, 1, (RR),                   iwmmxt_tandorc),
cCE(torcw,    e93f150, 1, (RR),                   iwmmxt_tandorc),
cCE(waccb,    e0001c0, 2, (RIWR, RIWR),           rd_rn),
cCE(wacch,    e4001c0, 2, (RIWR, RIWR),           rd_rn),
cCE(waccw,    e8001c0, 2, (RIWR, RIWR),           rd_rn),
cCE(waddbss,  e300180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(waddb,    e000180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(waddbus,  e100180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(waddhss,  e700180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(waddh,    e400180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(waddhus,  e500180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(waddwss,  eb00180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(waddw,    e800180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(waddwus,  e900180, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(waligni,  e000020, 4, (RIWR, RIWR, RIWR, I7), iwmmxt_waligni),
cCE(walignr0, e800020, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(walignr1, e900020, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(walignr2, ea00020, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(walignr3, eb00020, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wand,     e200000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wandn,    e300000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wavg2b,   e800000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wavg2br,  e900000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wavg2h,   ec00000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wavg2hr,  ed00000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wcmpeqb,  e000060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wcmpeqh,  e400060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wcmpeqw,  e800060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wcmpgtub, e100060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wcmpgtuh, e500060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wcmpgtuw, e900060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wcmpgtsb, e300060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wcmpgtsh, e700060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wcmpgtsw, eb00060, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wldrb,    c100000, 2, (RIWR, ADDR),           iwmmxt_wldstbh),
cCE(wldrh,    c500000, 2, (RIWR, ADDR),           iwmmxt_wldstbh),
cCE(wldrw,    c100100, 2, (RIWR_RIWC, ADDR),      iwmmxt_wldstw),
cCE(wldrd,    c500100, 2, (RIWR, ADDR),           iwmmxt_wldstd),
cCE(wmacs,    e600100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmacsz,   e700100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmacu,    e400100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmacuz,   e500100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmadds,   ea00100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmaddu,   e800100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmaxsb,   e200160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmaxsh,   e600160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmaxsw,   ea00160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmaxub,   e000160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmaxuh,   e400160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmaxuw,   e800160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wminsb,   e300160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wminsh,   e700160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wminsw,   eb00160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wminub,   e100160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wminuh,   e500160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wminuw,   e900160, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmov,     e000000, 2, (RIWR, RIWR),           iwmmxt_wmov),
cCE(wmulsm,   e300100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmulsl,   e200100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmulum,   e100100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wmulul,   e000100, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wor,      e000000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wpackhss, e700080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wpackhus, e500080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wpackwss, eb00080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wpackwus, e900080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wpackdss, ef00080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wpackdus, ed00080, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wrorh,    e700040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wrorhg,   e700148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wrorw,    eb00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wrorwg,   eb00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wrord,    ef00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wrordg,   ef00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wsadb,    e000120, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsadbz,   e100120, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsadh,    e400120, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsadhz,   e500120, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wshufh,   e0001e0, 3, (RIWR, RIWR, I255),     iwmmxt_wshufh),
cCE(wsllh,    e500040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsllhg,   e500148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wsllw,    e900040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsllwg,   e900148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wslld,    ed00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wslldg,   ed00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wsrah,    e400040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsrahg,   e400148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wsraw,    e800040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsrawg,   e800148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wsrad,    ec00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsradg,   ec00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wsrlh,    e600040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsrlhg,   e600148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wsrlw,    ea00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsrlwg,   ea00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wsrld,    ee00040, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsrldg,   ee00148, 3, (RIWR, RIWR, RIWG),     rd_rn_rm),
cCE(wstrb,    c000000, 2, (RIWR, ADDR),           iwmmxt_wldstbh),
cCE(wstrh,    c400000, 2, (RIWR, ADDR),           iwmmxt_wldstbh),
cCE(wstrw,    c000100, 2, (RIWR_RIWC, ADDR),      iwmmxt_wldstw),
cCE(wstrd,    c400100, 2, (RIWR, ADDR),           iwmmxt_wldstd),
cCE(wsubbss,  e3001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsubb,    e0001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsubbus,  e1001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsubhss,  e7001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsubh,    e4001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsubhus,  e5001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsubwss,  eb001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsubw,    e8001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wsubwus,  e9001a0, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wunpckehub,e0000c0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckehuh,e4000c0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckehuw,e8000c0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckehsb,e2000c0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckehsh,e6000c0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckehsw,ea000c0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckihb, e1000c0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
cCE(wunpckihh, e5000c0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
cCE(wunpckihw, e9000c0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
cCE(wunpckelub,e0000e0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckeluh,e4000e0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckeluw,e8000e0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckelsb,e2000e0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckelsh,e6000e0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckelsw,ea000e0, 2, (RIWR, RIWR),          rd_rn),
cCE(wunpckilb, e1000e0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
cCE(wunpckilh, e5000e0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
cCE(wunpckilw, e9000e0, 3, (RIWR, RIWR, RIWR),            rd_rn_rm),
cCE(wxor,     e100000, 3, (RIWR, RIWR, RIWR),     rd_rn_rm),
cCE(wzero,    e300000, 1, (RIWR),                 iwmmxt_wzero),
 
 #undef ARM_VARIANT
 #define ARM_VARIANT ARM_CEXT_MAVERICK /* Cirrus Maverick instructions. */
 CE(cfldrs,   c100400, 2, (RMF, ADDR),              rd_cpaddr),
 CE(cfldrd,   c500400, 2, (RMD, ADDR),              rd_cpaddr),
 CE(cfldr32,  c100500, 2, (RMFX, ADDR),             rd_cpaddr),
 CE(cfldr64,  c500500, 2, (RMDX, ADDR),             rd_cpaddr),
 CE(cfstrs,   c000400, 2, (RMF, ADDR),              rd_cpaddr),
 CE(cfstrd,   c400400, 2, (RMD, ADDR),              rd_cpaddr),
 CE(cfstr32,  c000500, 2, (RMFX, ADDR),             rd_cpaddr),
 CE(cfstr64,  c400500, 2, (RMDX, ADDR),             rd_cpaddr),
 CE(cfmvsr,   e000450, 2, (RMF, RR),                rn_rd),
 CE(cfmvrs,   e100450, 2, (RR, RMF),                rd_rn),
 CE(cfmvdlr,  e000410, 2, (RMD, RR),                rn_rd),
 CE(cfmvrdl,  e100410, 2, (RR, RMD),                rd_rn),
 CE(cfmvdhr,  e000430, 2, (RMD, RR),                rn_rd),
 CE(cfmvrdh,  e100430, 2, (RR, RMD),                rd_rn),
 CE(cfmv64lr, e000510, 2, (RMDX, RR),               rn_rd),
 CE(cfmvr64l, e100510, 2, (RR, RMDX),               rd_rn),
 CE(cfmv64hr, e000530, 2, (RMDX, RR),               rn_rd),
 CE(cfmvr64h, e100530, 2, (RR, RMDX),               rd_rn),
 CE(cfmval32, e200440, 2, (RMAX, RMFX),             rd_rn),
 CE(cfmv32al, e100440, 2, (RMFX, RMAX),             rd_rn),
 CE(cfmvam32, e200460, 2, (RMAX, RMFX),             rd_rn),
 CE(cfmv32am, e100460, 2, (RMFX, RMAX),             rd_rn),
 CE(cfmvah32, e200480, 2, (RMAX, RMFX),             rd_rn),
 CE(cfmv32ah, e100480, 2, (RMFX, RMAX),             rd_rn),
 CE(cfmva32,  e2004a0, 2, (RMAX, RMFX),             rd_rn),
 CE(cfmv32a,  e1004a0, 2, (RMFX, RMAX),             rd_rn),
 CE(cfmva64,  e2004c0, 2, (RMAX, RMDX),             rd_rn),
 CE(cfmv64a,  e1004c0, 2, (RMDX, RMAX),             rd_rn),
 CE(cfmvsc32, e2004e0, 2, (RMDS, RMDX),             mav_dspsc),
 CE(cfmv32sc, e1004e0, 2, (RMDX, RMDS),             rd),
 CE(cfcpys,   e000400, 2, (RMF, RMF),               rd_rn),
 CE(cfcpyd,   e000420, 2, (RMD, RMD),               rd_rn),
 CE(cfcvtsd,  e000460, 2, (RMD, RMF),               rd_rn),
 CE(cfcvtds,  e000440, 2, (RMF, RMD),               rd_rn),
 CE(cfcvt32s, e000480, 2, (RMF, RMFX),              rd_rn),
 CE(cfcvt32d, e0004a0, 2, (RMD, RMFX),              rd_rn),
 CE(cfcvt64s, e0004c0, 2, (RMF, RMDX),              rd_rn),
 CE(cfcvt64d, e0004e0, 2, (RMD, RMDX),              rd_rn),
 CE(cfcvts32, e100580, 2, (RMFX, RMF),              rd_rn),
 CE(cfcvtd32, e1005a0, 2, (RMFX, RMD),              rd_rn),
 CE(cftruncs32,e1005c0, 2, (RMFX, RMF),             rd_rn),
 CE(cftruncd32,e1005e0, 2, (RMFX, RMD),             rd_rn),
 CE(cfrshl32, e000550, 3, (RMFX, RMFX, RR),         mav_triple),
 CE(cfrshl64, e000570, 3, (RMDX, RMDX, RR),         mav_triple),
 CE(cfsh32,   e000500, 3, (RMFX, RMFX, I63s),       mav_shift),
 CE(cfsh64,   e200500, 3, (RMDX, RMDX, I63s),       mav_shift),
 CE(cfcmps,   e100490, 3, (RR, RMF, RMF),           rd_rn_rm),
 CE(cfcmpd,   e1004b0, 3, (RR, RMD, RMD),           rd_rn_rm),
 CE(cfcmp32,  e100590, 3, (RR, RMFX, RMFX),         rd_rn_rm),
 CE(cfcmp64,  e1005b0, 3, (RR, RMDX, RMDX),         rd_rn_rm),
 CE(cfabss,   e300400, 2, (RMF, RMF),               rd_rn),
 CE(cfabsd,   e300420, 2, (RMD, RMD),               rd_rn),
 CE(cfnegs,   e300440, 2, (RMF, RMF),               rd_rn),
 CE(cfnegd,   e300460, 2, (RMD, RMD),               rd_rn),
 CE(cfadds,   e300480, 3, (RMF, RMF, RMF),          rd_rn_rm),
 CE(cfaddd,   e3004a0, 3, (RMD, RMD, RMD),          rd_rn_rm),
 CE(cfsubs,   e3004c0, 3, (RMF, RMF, RMF),          rd_rn_rm),
 CE(cfsubd,   e3004e0, 3, (RMD, RMD, RMD),          rd_rn_rm),
 CE(cfmuls,   e100400, 3, (RMF, RMF, RMF),          rd_rn_rm),
 CE(cfmuld,   e100420, 3, (RMD, RMD, RMD),          rd_rn_rm),
 CE(cfabs32,  e300500, 2, (RMFX, RMFX),             rd_rn),
 CE(cfabs64,  e300520, 2, (RMDX, RMDX),             rd_rn),
 CE(cfneg32,  e300540, 2, (RMFX, RMFX),             rd_rn),
 CE(cfneg64,  e300560, 2, (RMDX, RMDX),             rd_rn),
 CE(cfadd32,  e300580, 3, (RMFX, RMFX, RMFX),       rd_rn_rm),
 CE(cfadd64,  e3005a0, 3, (RMDX, RMDX, RMDX),       rd_rn_rm),
 CE(cfsub32,  e3005c0, 3, (RMFX, RMFX, RMFX),       rd_rn_rm),
 CE(cfsub64,  e3005e0, 3, (RMDX, RMDX, RMDX),       rd_rn_rm),
 CE(cfmul32,  e100500, 3, (RMFX, RMFX, RMFX),       rd_rn_rm),
 CE(cfmul64,  e100520, 3, (RMDX, RMDX, RMDX),       rd_rn_rm),
 CE(cfmac32,  e100540, 3, (RMFX, RMFX, RMFX),       rd_rn_rm),
 CE(cfmsc32,  e100560, 3, (RMFX, RMFX, RMFX),       rd_rn_rm),
 CE(cfmadd32, e000600, 4, (RMAX, RMFX, RMFX, RMFX), mav_quad),
 CE(cfmsub32, e100600, 4, (RMAX, RMFX, RMFX, RMFX), mav_quad),
 CE(cfmadda32, e200600, 4, (RMAX, RMAX, RMFX, RMFX), mav_quad),
 CE(cfmsuba32, e300600, 4, (RMAX, RMAX, RMFX, RMFX), mav_quad),
cCE(cfldrs,   c100400, 2, (RMF, ADDR),              rd_cpaddr),
cCE(cfldrd,   c500400, 2, (RMD, ADDR),              rd_cpaddr),
cCE(cfldr32,  c100500, 2, (RMFX, ADDR),             rd_cpaddr),
cCE(cfldr64,  c500500, 2, (RMDX, ADDR),             rd_cpaddr),
cCE(cfstrs,   c000400, 2, (RMF, ADDR),              rd_cpaddr),
cCE(cfstrd,   c400400, 2, (RMD, ADDR),              rd_cpaddr),
cCE(cfstr32,  c000500, 2, (RMFX, ADDR),             rd_cpaddr),
cCE(cfstr64,  c400500, 2, (RMDX, ADDR),             rd_cpaddr),
cCE(cfmvsr,   e000450, 2, (RMF, RR),                rn_rd),
cCE(cfmvrs,   e100450, 2, (RR, RMF),                rd_rn),
cCE(cfmvdlr,  e000410, 2, (RMD, RR),                rn_rd),
cCE(cfmvrdl,  e100410, 2, (RR, RMD),                rd_rn),
cCE(cfmvdhr,  e000430, 2, (RMD, RR),                rn_rd),
cCE(cfmvrdh,  e100430, 2, (RR, RMD),                rd_rn),
cCE(cfmv64lr, e000510, 2, (RMDX, RR),               rn_rd),
cCE(cfmvr64l, e100510, 2, (RR, RMDX),               rd_rn),
cCE(cfmv64hr, e000530, 2, (RMDX, RR),               rn_rd),
cCE(cfmvr64h, e100530, 2, (RR, RMDX),               rd_rn),
cCE(cfmval32, e200440, 2, (RMAX, RMFX),             rd_rn),
cCE(cfmv32al, e100440, 2, (RMFX, RMAX),             rd_rn),
cCE(cfmvam32, e200460, 2, (RMAX, RMFX),             rd_rn),
cCE(cfmv32am, e100460, 2, (RMFX, RMAX),             rd_rn),
cCE(cfmvah32, e200480, 2, (RMAX, RMFX),             rd_rn),
cCE(cfmv32ah, e100480, 2, (RMFX, RMAX),             rd_rn),
cCE(cfmva32,  e2004a0, 2, (RMAX, RMFX),             rd_rn),
cCE(cfmv32a,  e1004a0, 2, (RMFX, RMAX),             rd_rn),
cCE(cfmva64,  e2004c0, 2, (RMAX, RMDX),             rd_rn),
cCE(cfmv64a,  e1004c0, 2, (RMDX, RMAX),             rd_rn),
cCE(cfmvsc32, e2004e0, 2, (RMDS, RMDX),             mav_dspsc),
cCE(cfmv32sc, e1004e0, 2, (RMDX, RMDS),             rd),
cCE(cfcpys,   e000400, 2, (RMF, RMF),               rd_rn),
cCE(cfcpyd,   e000420, 2, (RMD, RMD),               rd_rn),
cCE(cfcvtsd,  e000460, 2, (RMD, RMF),               rd_rn),
cCE(cfcvtds,  e000440, 2, (RMF, RMD),               rd_rn),
cCE(cfcvt32s, e000480, 2, (RMF, RMFX),              rd_rn),
cCE(cfcvt32d, e0004a0, 2, (RMD, RMFX),              rd_rn),
cCE(cfcvt64s, e0004c0, 2, (RMF, RMDX),              rd_rn),
cCE(cfcvt64d, e0004e0, 2, (RMD, RMDX),              rd_rn),
cCE(cfcvts32, e100580, 2, (RMFX, RMF),              rd_rn),
cCE(cfcvtd32, e1005a0, 2, (RMFX, RMD),              rd_rn),
cCE(cftruncs32,e1005c0, 2, (RMFX, RMF),             rd_rn),
cCE(cftruncd32,e1005e0, 2, (RMFX, RMD),             rd_rn),
cCE(cfrshl32, e000550, 3, (RMFX, RMFX, RR),         mav_triple),
cCE(cfrshl64, e000570, 3, (RMDX, RMDX, RR),         mav_triple),
cCE(cfsh32,   e000500, 3, (RMFX, RMFX, I63s),       mav_shift),
cCE(cfsh64,   e200500, 3, (RMDX, RMDX, I63s),       mav_shift),
cCE(cfcmps,   e100490, 3, (RR, RMF, RMF),           rd_rn_rm),
cCE(cfcmpd,   e1004b0, 3, (RR, RMD, RMD),           rd_rn_rm),
cCE(cfcmp32,  e100590, 3, (RR, RMFX, RMFX),         rd_rn_rm),
cCE(cfcmp64,  e1005b0, 3, (RR, RMDX, RMDX),         rd_rn_rm),
cCE(cfabss,   e300400, 2, (RMF, RMF),               rd_rn),
cCE(cfabsd,   e300420, 2, (RMD, RMD),               rd_rn),
cCE(cfnegs,   e300440, 2, (RMF, RMF),               rd_rn),
cCE(cfnegd,   e300460, 2, (RMD, RMD),               rd_rn),
cCE(cfadds,   e300480, 3, (RMF, RMF, RMF),          rd_rn_rm),
cCE(cfaddd,   e3004a0, 3, (RMD, RMD, RMD),          rd_rn_rm),
cCE(cfsubs,   e3004c0, 3, (RMF, RMF, RMF),          rd_rn_rm),
cCE(cfsubd,   e3004e0, 3, (RMD, RMD, RMD),          rd_rn_rm),
cCE(cfmuls,   e100400, 3, (RMF, RMF, RMF),          rd_rn_rm),
cCE(cfmuld,   e100420, 3, (RMD, RMD, RMD),          rd_rn_rm),
cCE(cfabs32,  e300500, 2, (RMFX, RMFX),             rd_rn),
cCE(cfabs64,  e300520, 2, (RMDX, RMDX),             rd_rn),
cCE(cfneg32,  e300540, 2, (RMFX, RMFX),             rd_rn),
cCE(cfneg64,  e300560, 2, (RMDX, RMDX),             rd_rn),
cCE(cfadd32,  e300580, 3, (RMFX, RMFX, RMFX),       rd_rn_rm),
cCE(cfadd64,  e3005a0, 3, (RMDX, RMDX, RMDX),       rd_rn_rm),
cCE(cfsub32,  e3005c0, 3, (RMFX, RMFX, RMFX),       rd_rn_rm),
cCE(cfsub64,  e3005e0, 3, (RMDX, RMDX, RMDX),       rd_rn_rm),
cCE(cfmul32,  e100500, 3, (RMFX, RMFX, RMFX),       rd_rn_rm),
cCE(cfmul64,  e100520, 3, (RMDX, RMDX, RMDX),       rd_rn_rm),
cCE(cfmac32,  e100540, 3, (RMFX, RMFX, RMFX),       rd_rn_rm),
cCE(cfmsc32,  e100560, 3, (RMFX, RMFX, RMFX),       rd_rn_rm),
cCE(cfmadd32, e000600, 4, (RMAX, RMFX, RMFX, RMFX), mav_quad),
cCE(cfmsub32, e100600, 4, (RMAX, RMFX, RMFX, RMFX), mav_quad),
cCE(cfmadda32, e200600, 4, (RMAX, RMAX, RMFX, RMFX), mav_quad),
cCE(cfmsuba32, e300600, 4, (RMAX, RMAX, RMFX, RMFX), mav_quad),
 };
 #undef ARM_VARIANT
 #undef THUMB_VARIANT
@@ -9263,6 +9712,8 @@ static const struct asm_opcode insns[] =
 #undef TUE
 #undef TUF
 #undef TCC
+#undef cCE
+#undef cC3
 #undef CE
 #undef CM
 #undef UE
@@ -9323,47 +9774,379 @@ md_chars_to_number (char * buf, int n)
 
 /* MD interface: Sections.  */
 
+/* Estimate the size of a frag before relaxing.  Assume everything fits in
+   2 bytes.  */
+
 int
-md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
+md_estimate_size_before_relax (fragS * fragp,
                               segT    segtype ATTRIBUTE_UNUSED)
 {
-  as_fatal (_("md_estimate_size_before_relax\n"));
-  return 1;
-}
-
-/* Round up a section size to the appropriate boundary.         */
-
-valueT
-md_section_align (segT  segment ATTRIBUTE_UNUSED,
-                 valueT size)
-{
-#ifdef OBJ_ELF
-  return size;
-#else
-  /* Round all sects to multiple of 4. */
-  return (size + 3) & ~3;
-#endif
+  fragp->fr_var = 2;
+  return 2;
 }
 
-/* This is called from HANDLE_ALIGN in write.c.         Fill in the contents
-   of an rs_align_code fragment.  */
+/* Convert a machine dependent frag.  */
 
 void
-arm_handle_align (fragS * fragP)
+md_convert_frag (bfd *abfd, segT asec ATTRIBUTE_UNUSED, fragS *fragp)
 {
-  static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
-  static char const thumb_noop[2] = { 0xc0, 0x46 };
-  static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
-  static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
-
-  int bytes, fix, noop_size;
-  char * p;
-  const char * noop;
-
-  if (fragP->fr_type != rs_align_code)
-    return;
-
-  bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
+  unsigned long insn;
+  unsigned long old_op;
+  char *buf;
+  expressionS exp;
+  fixS *fixp;
+  int reloc_type;
+  int pc_rel;
+  int opcode;
+
+  buf = fragp->fr_literal + fragp->fr_fix;
+
+  old_op = bfd_get_16(abfd, buf);
+  if (fragp->fr_symbol) {
+      exp.X_op = O_symbol;
+      exp.X_add_symbol = fragp->fr_symbol;
+  } else {
+      exp.X_op = O_constant;
+  }
+  exp.X_add_number = fragp->fr_offset;
+  opcode = fragp->fr_subtype;
+  switch (opcode)
+    {
+    case T_MNEM_ldr_pc:
+    case T_MNEM_ldr_pc2:
+    case T_MNEM_ldr_sp:
+    case T_MNEM_str_sp:
+    case T_MNEM_ldr:
+    case T_MNEM_ldrb:
+    case T_MNEM_ldrh:
+    case T_MNEM_str:
+    case T_MNEM_strb:
+    case T_MNEM_strh:
+      if (fragp->fr_var == 4)
+       {
+         insn = THUMB_OP32(opcode);
+         if ((old_op >> 12) == 4 || (old_op >> 12) == 9)
+           {
+             insn |= (old_op & 0x700) << 4;
+           }
+         else
+           {
+             insn |= (old_op & 7) << 12;
+             insn |= (old_op & 0x38) << 13;
+           }
+         insn |= 0x00000c00;
+         put_thumb32_insn (buf, insn);
+         reloc_type = BFD_RELOC_ARM_T32_OFFSET_IMM;
+       }
+      else
+       {
+         reloc_type = BFD_RELOC_ARM_THUMB_OFFSET;
+       }
+      pc_rel = (opcode == T_MNEM_ldr_pc2);
+      break;
+    case T_MNEM_adr:
+      if (fragp->fr_var == 4)
+       {
+         insn = THUMB_OP32 (opcode);
+         insn |= (old_op & 0xf0) << 4;
+         put_thumb32_insn (buf, insn);
+         reloc_type = BFD_RELOC_ARM_T32_ADD_PC12;
+       }
+      else
+       {
+         reloc_type = BFD_RELOC_ARM_THUMB_ADD;
+         exp.X_add_number -= 4;
+       }
+      pc_rel = 1;
+      break;
+    case T_MNEM_mov:
+    case T_MNEM_movs:
+    case T_MNEM_cmp:
+    case T_MNEM_cmn:
+      if (fragp->fr_var == 4)
+       {
+         int r0off = (opcode == T_MNEM_mov
+                      || opcode == T_MNEM_movs) ? 0 : 8;
+         insn = THUMB_OP32 (opcode);
+         insn = (insn & 0xe1ffffff) | 0x10000000;
+         insn |= (old_op & 0x700) << r0off;
+         put_thumb32_insn (buf, insn);
+         reloc_type = BFD_RELOC_ARM_T32_IMMEDIATE;
+       }
+      else
+       {
+         reloc_type = BFD_RELOC_ARM_THUMB_IMM;
+       }
+      pc_rel = 0;
+      break;
+    case T_MNEM_b:
+      if (fragp->fr_var == 4)
+       {
+         insn = THUMB_OP32(opcode);
+         put_thumb32_insn (buf, insn);
+         reloc_type = BFD_RELOC_THUMB_PCREL_BRANCH25;
+       }
+      else
+       reloc_type = BFD_RELOC_THUMB_PCREL_BRANCH12;
+      pc_rel = 1;
+      break;
+    case T_MNEM_bcond:
+      if (fragp->fr_var == 4)
+       {
+         insn = THUMB_OP32(opcode);
+         insn |= (old_op & 0xf00) << 14;
+         put_thumb32_insn (buf, insn);
+         reloc_type = BFD_RELOC_THUMB_PCREL_BRANCH20;
+       }
+      else
+       reloc_type = BFD_RELOC_THUMB_PCREL_BRANCH9;
+      pc_rel = 1;
+      break;
+    case T_MNEM_add_sp:
+    case T_MNEM_add_pc:
+    case T_MNEM_inc_sp:
+    case T_MNEM_dec_sp:
+      if (fragp->fr_var == 4)
+       {
+         /* ??? Choose between add and addw.  */
+         insn = THUMB_OP32 (opcode);
+         insn |= (old_op & 0xf0) << 4;
+         put_thumb32_insn (buf, insn);
+         reloc_type = BFD_RELOC_ARM_T32_IMMEDIATE;
+       }
+      else
+       reloc_type = BFD_RELOC_ARM_THUMB_ADD;
+      pc_rel = 0;
+      break;
+
+    case T_MNEM_addi:
+    case T_MNEM_addis:
+    case T_MNEM_subi:
+    case T_MNEM_subis:
+      if (fragp->fr_var == 4)
+       {
+         insn = THUMB_OP32 (opcode);
+         insn |= (old_op & 0xf0) << 4;
+         insn |= (old_op & 0xf) << 16;
+         put_thumb32_insn (buf, insn);
+         reloc_type = BFD_RELOC_ARM_T32_IMMEDIATE;
+       }
+      else
+       reloc_type = BFD_RELOC_ARM_THUMB_ADD;
+      pc_rel = 0;
+      break;
+    default:
+      abort();
+    }
+  fixp = fix_new_exp (fragp, fragp->fr_fix, fragp->fr_var, &exp, pc_rel,
+                     reloc_type);
+  fixp->fx_file = fragp->fr_file;
+  fixp->fx_line = fragp->fr_line;
+  fragp->fr_fix += fragp->fr_var;
+}
+
+/* Return the size of a relaxable immediate operand instruction.
+   SHIFT and SIZE specify the form of the allowable immediate.  */
+static int
+relax_immediate (fragS *fragp, int size, int shift)
+{
+  offsetT offset;
+  offsetT mask;
+  offsetT low;
+
+  /* ??? Should be able to do better than this.  */
+  if (fragp->fr_symbol)
+    return 4;
+
+  low = (1 << shift) - 1;
+  mask = (1 << (shift + size)) - (1 << shift);
+  offset = fragp->fr_offset;
+  /* Force misaligned offsets to 32-bit variant.  */
+  if (offset & low)
+    return -4;
+  if (offset & ~mask)
+    return 4;
+  return 2;
+}
+
+/* Return the size of a relaxable adr pseudo-instruction or PC-relative
+   load.  */
+static int
+relax_adr (fragS *fragp, asection *sec)
+{
+  addressT addr;
+  offsetT val;
+
+  /* Assume worst case for symbols not known to be in the same section.  */
+  if (!S_IS_DEFINED(fragp->fr_symbol)
+      || sec != S_GET_SEGMENT (fragp->fr_symbol))
+    return 4;
+
+  val = S_GET_VALUE(fragp->fr_symbol) + fragp->fr_offset;
+  addr = fragp->fr_address + fragp->fr_fix;
+  addr = (addr + 4) & ~3;
+  /* Fix the insn as the 4-byte version if the target address is not
+     sufficiently aligned.  This is prevents an infinite loop when two
+     instructions have contradictory range/alignment requirements.  */
+  if (val & 3)
+    return -4;
+  val -= addr;
+  if (val < 0 || val > 1020)
+    return 4;
+  return 2;
+}
+
+/* Return the size of a relaxable add/sub immediate instruction.  */
+static int
+relax_addsub (fragS *fragp, asection *sec)
+{
+  char *buf;
+  int op;
+
+  buf = fragp->fr_literal + fragp->fr_fix;
+  op = bfd_get_16(sec->owner, buf);
+  if ((op & 0xf) == ((op >> 4) & 0xf))
+    return relax_immediate (fragp, 8, 0);
+  else
+    return relax_immediate (fragp, 3, 0);
+}
+
+
+/* Return the size of a relaxable branch instruction.  BITS is the
+   size of the offset field in the narrow instruction.  */
+
+static int
+relax_branch (fragS *fragp, asection *sec, int bits)
+{
+  addressT addr;
+  offsetT val;
+  offsetT limit;
+
+  /* Assume worst case for symbols not known to be in the same section.  */
+  if (!S_IS_DEFINED(fragp->fr_symbol)
+      || sec != S_GET_SEGMENT (fragp->fr_symbol))
+    return 4;
+
+  val = S_GET_VALUE(fragp->fr_symbol) + fragp->fr_offset;
+  addr = fragp->fr_address + fragp->fr_fix + 4;
+  val -= addr;
+
+  /* Offset is a signed value *2 */
+  limit = 1 << bits;
+  if (val >= limit || val < -limit)
+    return 4;
+  return 2;
+}
+
+
+/* Relax a machine dependent frag.  This returns the amount by which
+   the current size of the frag should change.  */
+
+int
+arm_relax_frag (asection *sec, fragS *fragp, long stretch ATTRIBUTE_UNUSED)
+{
+  int oldsize;
+  int newsize;
+
+  oldsize = fragp->fr_var;
+  switch (fragp->fr_subtype)
+    {
+    case T_MNEM_ldr_pc2:
+      newsize = relax_adr(fragp, sec);
+      break;
+    case T_MNEM_ldr_pc:
+    case T_MNEM_ldr_sp:
+    case T_MNEM_str_sp:
+      newsize = relax_immediate(fragp, 8, 2);
+      break;
+    case T_MNEM_ldr:
+    case T_MNEM_str:
+      newsize = relax_immediate(fragp, 5, 2);
+      break;
+    case T_MNEM_ldrh:
+    case T_MNEM_strh:
+      newsize = relax_immediate(fragp, 5, 1);
+      break;
+    case T_MNEM_ldrb:
+    case T_MNEM_strb:
+      newsize = relax_immediate(fragp, 5, 0);
+      break;
+    case T_MNEM_adr:
+      newsize = relax_adr(fragp, sec);
+      break;
+    case T_MNEM_mov:
+    case T_MNEM_movs:
+    case T_MNEM_cmp:
+    case T_MNEM_cmn:
+      newsize = relax_immediate(fragp, 8, 0);
+      break;
+    case T_MNEM_b:
+      newsize = relax_branch(fragp, sec, 11);
+      break;
+    case T_MNEM_bcond:
+      newsize = relax_branch(fragp, sec, 8);
+      break;
+    case T_MNEM_add_sp:
+    case T_MNEM_add_pc:
+      newsize = relax_immediate (fragp, 8, 2);
+      break;
+    case T_MNEM_inc_sp:
+    case T_MNEM_dec_sp:
+      newsize = relax_immediate (fragp, 7, 2);
+      break;
+    case T_MNEM_addi:
+    case T_MNEM_addis:
+    case T_MNEM_subi:
+    case T_MNEM_subis:
+      newsize = relax_addsub (fragp, sec);
+      break;
+    default:
+      abort();
+    }
+  if (newsize < 0)
+    {
+      fragp->fr_var = -newsize;
+      md_convert_frag (sec->owner, sec, fragp);
+      frag_wane(fragp);
+      return -(newsize + oldsize);
+    }
+  fragp->fr_var = newsize;
+  return newsize - oldsize;
+}
+
+/* Round up a section size to the appropriate boundary.         */
+
+valueT
+md_section_align (segT  segment ATTRIBUTE_UNUSED,
+                 valueT size)
+{
+#ifdef OBJ_ELF
+  return size;
+#else
+  /* Round all sects to multiple of 4. */
+  return (size + 3) & ~3;
+#endif
+}
+
+/* This is called from HANDLE_ALIGN in write.c.         Fill in the contents
+   of an rs_align_code fragment.  */
+
+void
+arm_handle_align (fragS * fragP)
+{
+  static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
+  static char const thumb_noop[2] = { 0xc0, 0x46 };
+  static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
+  static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
+
+  int bytes, fix, noop_size;
+  char * p;
+  const char * noop;
+
+  if (fragP->fr_type != rs_align_code)
+    return;
+
+  bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
   p = fragP->fr_literal + fragP->fr_fix;
   fix = 0;
 
@@ -9867,41 +10650,77 @@ tc_arm_frame_initial_instructions (void)
 
 /* MD interface: Symbol and relocation handling.  */
 
-/* The knowledge of the PC's pipeline offset is built into the insns
-   themselves. */
+/* Return the address within the segment that a PC-relative fixup is
+   relative to.  For ARM, PC-relative fixups applied to instructions
+   are generally relative to the location of the fixup plus 8 bytes.
+   Thumb branches are offset by 4, and Thumb loads relative to PC
+   require special handling.  */
 
 long
-md_pcrel_from (fixS * fixP)
+md_pcrel_from_section (fixS * fixP, segT seg)
 {
-  if (fixP->fx_addsy
-      && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
-      && fixP->fx_subsy == NULL)
-    return 0;
+  offsetT base = fixP->fx_where + fixP->fx_frag->fr_address;
+
+  /* If this is pc-relative and we are going to emit a relocation
+     then we just want to put out any pipeline compensation that the linker
+     will need.  Otherwise we want to use the calculated base.  */
+  if (fixP->fx_pcrel 
+      && ((fixP->fx_addsy && S_GET_SEGMENT (fixP->fx_addsy) != seg)
+         || arm_force_relocation (fixP)))
+    base = 0;
 
-  /* PC relative addressing on the Thumb is slightly odd as the bottom
-     two bits of the PC are forced to zero for the calculation.  This
-     happens *after* application of the pipeline offset.  However,
-     Thumb adrl already adjusts for this, so we need not do it again.  */
   switch (fixP->fx_r_type)
     {
+      /* PC relative addressing on the Thumb is slightly odd as the
+        bottom two bits of the PC are forced to zero for the
+        calculation.  This happens *after* application of the
+        pipeline offset.  However, Thumb adrl already adjusts for
+        this, so we need not do it again.  */
     case BFD_RELOC_ARM_THUMB_ADD:
-      return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
+      return base & ~3;
 
     case BFD_RELOC_ARM_THUMB_OFFSET:
     case BFD_RELOC_ARM_T32_OFFSET_IMM:
-      return (fixP->fx_where + fixP->fx_frag->fr_address + 4) & ~3;
+    case BFD_RELOC_ARM_T32_ADD_PC12:
+    case BFD_RELOC_ARM_T32_CP_OFF_IMM:
+      return (base + 4) & ~3;
 
-    default:
-      break;
-    }
+      /* Thumb branches are simply offset by +4.  */
+    case BFD_RELOC_THUMB_PCREL_BRANCH7:
+    case BFD_RELOC_THUMB_PCREL_BRANCH9:
+    case BFD_RELOC_THUMB_PCREL_BRANCH12:
+    case BFD_RELOC_THUMB_PCREL_BRANCH20:
+    case BFD_RELOC_THUMB_PCREL_BRANCH23:
+    case BFD_RELOC_THUMB_PCREL_BRANCH25:
+    case BFD_RELOC_THUMB_PCREL_BLX:
+      return base + 4;
 
+      /* ARM mode branches are offset by +8.  However, the Windows CE
+        loader expects the relocation not to take this into account.  */
+    case BFD_RELOC_ARM_PCREL_BRANCH:
+    case BFD_RELOC_ARM_PCREL_BLX:
+    case BFD_RELOC_ARM_PLT32:
 #ifdef TE_WINCE
-  /* The pattern was adjusted to accommodate CE's off-by-one fixups,
-     so we un-adjust here to compensate for the accommodation. */
-  return fixP->fx_where + fixP->fx_frag->fr_address + 8;
+      return base;
 #else
-  return fixP->fx_where + fixP->fx_frag->fr_address;
+      return base + 8;
 #endif
+
+      /* ARM mode loads relative to PC are also offset by +8.  Unlike
+        branches, the Windows CE loader *does* expect the relocation
+        to take this into account.  */
+    case BFD_RELOC_ARM_OFFSET_IMM:
+    case BFD_RELOC_ARM_OFFSET_IMM8:
+    case BFD_RELOC_ARM_HWLITERAL:
+    case BFD_RELOC_ARM_LITERAL:
+    case BFD_RELOC_ARM_CP_OFF_IMM:
+      return base + 8;
+
+
+      /* Other PC-relative relocations are un-offset.  */
+    default:
+      return base;
+    }
 }
 
 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
@@ -9930,7 +10749,7 @@ md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
   return 0;
 }
 
-/* Subroutine of md_apply_fix3.         Check to see if an immediate can be
+/* Subroutine of md_apply_fix.  Check to see if an immediate can be
    computed as two separate immediate values, added together.  We
    already know that this value cannot be computed by just one ARM
    instruction.         */
@@ -9977,7 +10796,7 @@ validate_offset_imm (unsigned int val, int hwse)
   return val;
 }
 
-/* Subroutine of md_apply_fix3.         Do those data_ops which can take a
+/* Subroutine of md_apply_fix.  Do those data_ops which can take a
    negative immediate constant by altering the instruction.  A bit of
    a hack really.
        MOV <-> MVN
@@ -10066,8 +10885,19 @@ negate_data_op (unsigned long * instruction,
   return value;
 }
 
+/* Read a 32-bit thumb instruction from buf.  */
+static unsigned long
+get_thumb32_insn (char * buf)
+{
+  unsigned long insn;
+  insn = md_chars_to_number (buf, THUMB_SIZE) << 16;
+  insn |= md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
+
+  return insn;
+}
+
 void
-md_apply_fix3 (fixS *  fixP,
+md_apply_fix (fixS *   fixP,
               valueT * valP,
               segT     seg)
 {
@@ -10077,9 +10907,6 @@ md_apply_fix3 (fixS *   fixP,
   unsigned long         temp;
   int           sign;
   char *        buf = fixP->fx_where + fixP->fx_frag->fr_literal;
-  /* The double cast here prevents warnings about converting a pointer
-     to an integer of different size.  We know the value is 0, 1, or 2.         */
-  int           fix_is_thumb = (int) (size_t) fixP->tc_fix_data;
 
   assert (fixP->fx_r_type <= BFD_RELOC_UNUSED);
 
@@ -10087,20 +10914,21 @@ md_apply_fix3 (fixS * fixP,
   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
     fixP->fx_done = 1;
 
-  /* If this symbol is in a different section then we need to leave it for
-     the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
-     so we have to undo its effects here.  */
-  if (fixP->fx_pcrel)
-    {
-      if (fixP->fx_addsy != NULL
-         && S_IS_DEFINED (fixP->fx_addsy)
-         && S_GET_SEGMENT (fixP->fx_addsy) != seg)
-       value += md_pcrel_from (fixP);
-    }
+  /* On a 64-bit host, silently truncate 'value' to 32 bits for
+     consistency with the behavior on 32-bit hosts.  Remember value
+     for emit_reloc.  */
+  value &= 0xffffffff;
+  value ^= 0x80000000;
+  value -= 0x80000000; 
 
-  /* Remember value for emit_reloc.  */
+  *valP = value;
   fixP->fx_addnumber = value;
 
+  /* Same treatment for fixP->fx_offset.  */
+  fixP->fx_offset &= 0xffffffff;
+  fixP->fx_offset ^= 0x80000000;
+  fixP->fx_offset -= 0x80000000;
+
   switch (fixP->fx_r_type)
     {
     case BFD_RELOC_NONE:
@@ -10246,7 +11074,6 @@ md_apply_fix3 (fixS *   fixP,
       value /= 4;
 
       newval = md_chars_to_number (buf+2, THUMB_SIZE);
-      newval &= 0xff00;
       newval |= value;
       md_number_to_chars (buf+2, newval, THUMB_SIZE);
       break;
@@ -10388,6 +11215,8 @@ md_apply_fix3 (fixS *   fixP,
       break;
 
     case BFD_RELOC_ARM_T32_IMMEDIATE:
+    case BFD_RELOC_ARM_T32_IMM12:
+    case BFD_RELOC_ARM_T32_ADD_PC12:
       /* We claim that this fixup has been processed here,
         even if in fact we generate an error because we do
         not have a reloc for it, so tc_gen_reloc will reject it.  */
@@ -10406,9 +11235,23 @@ md_apply_fix3 (fixS *  fixP,
       newval <<= 16;
       newval |= md_chars_to_number (buf+2, THUMB_SIZE);
 
-      newimm = encode_thumb32_immediate (value);
-
       /* FUTURE: Implement analogue of negate_data_op for T32.  */
+      if (fixP->fx_r_type == BFD_RELOC_ARM_T32_IMMEDIATE)
+       newimm = encode_thumb32_immediate (value);
+      else
+       {
+         /* 12 bit immediate for addw/subw.  */
+         if (value < 0)
+           {
+             value = -value;
+             newval ^= 0x00a00000;
+           }
+         if (value > 0xfff)
+           newimm = (unsigned int) FAIL;
+         else
+           newimm = value;
+       }
+
       if (newimm == (unsigned int)FAIL)
        {
          as_bad_where (fixP->fx_file, fixP->fx_line,
@@ -10417,7 +11260,6 @@ md_apply_fix3 (fixS *   fixP,
          break;
        }
 
-      newval &= 0xfbff8f00;
       newval |= (newimm & 0x800) << 15;
       newval |= (newimm & 0x700) << 4;
       newval |= (newimm & 0x0ff);
@@ -10426,22 +11268,22 @@ md_apply_fix3 (fixS * fixP,
       md_number_to_chars (buf+2, (valueT) (newval & 0xffff), THUMB_SIZE);
       break;
 
-    case BFD_RELOC_ARM_SMI:
+    case BFD_RELOC_ARM_SMC:
       if (((unsigned long) value) > 0xffff)
        as_bad_where (fixP->fx_file, fixP->fx_line,
-                     _("invalid smi expression"));
-      newval = md_chars_to_number (buf, INSN_SIZE) & 0xfff000f0;
+                     _("invalid smc expression"));
+      newval = md_chars_to_number (buf, INSN_SIZE);
       newval |= (value & 0xf) | ((value & 0xfff0) << 4);
       md_number_to_chars (buf, newval, INSN_SIZE);
       break;
 
     case BFD_RELOC_ARM_SWI:
-      if (fix_is_thumb)
+      if (fixP->tc_fix_data != 0)
        {
          if (((unsigned long) value) > 0xff)
            as_bad_where (fixP->fx_file, fixP->fx_line,
                          _("invalid swi expression"));
-         newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
+         newval = md_chars_to_number (buf, THUMB_SIZE);
          newval |= value;
          md_number_to_chars (buf, newval, THUMB_SIZE);
        }
@@ -10450,7 +11292,7 @@ md_apply_fix3 (fixS *   fixP,
          if (((unsigned long) value) > 0x00ffffff)
            as_bad_where (fixP->fx_file, fixP->fx_line,
                          _("invalid swi expression"));
-         newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
+         newval = md_chars_to_number (buf, INSN_SIZE);
          newval |= value;
          md_number_to_chars (buf, newval, INSN_SIZE);
        }
@@ -10465,355 +11307,180 @@ md_apply_fix3 (fixS *       fixP,
       break;
 
     case BFD_RELOC_ARM_PCREL_BRANCH:
-      newval = md_chars_to_number (buf, INSN_SIZE);
-
-      /* Sign-extend a 24-bit number.  */
-#define SEXT24(x)      ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
-
 #ifdef OBJ_ELF
-      value = fixP->fx_offset;
+    case BFD_RELOC_ARM_PLT32:
 #endif
 
       /* We are going to store value (shifted right by two) in the
-        instruction, in a 24 bit, signed field  Thus we need to check
-        that none of the top 8 bits of the shifted value (top 7 bits of
-        the unshifted, unsigned value) are set, or that they are all set.  */
-      if ((value & ~ ((offsetT) 0x1ffffff)) != 0
-         && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
-       {
-#ifdef OBJ_ELF
-         /* Normally we would be stuck at this point, since we cannot store
-            the absolute address that is the destination of the branch in the
-            24 bits of the branch instruction.  If however, we happen to know
-            that the destination of the branch is in the same section as the
-            branch instruction itself, then we can compute the relocation for
-            ourselves and not have to bother the linker with it.
-
-            FIXME: The test for OBJ_ELF is only here because I have not
-            worked out how to do this for OBJ_COFF.  */
-         if (fixP->fx_addsy != NULL
-             && S_IS_DEFINED (fixP->fx_addsy)
-             && S_GET_SEGMENT (fixP->fx_addsy) == seg)
-           {
-             /* Get pc relative value to go into the branch.  */
-             value = * valP;
-
-             /* Permit a backward branch provided that enough bits
-                are set.  Allow a forwards branch, provided that
-                enough bits are clear.  */
-             if (   (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
-                 || (value & ~ ((offsetT) 0x1ffffff)) == 0)
-               fixP->fx_done = 1;
-           }
-
-         if (! fixP->fx_done)
-#endif
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("GAS can't handle same-section branch dest >= 0x04000000"));
-       }
-
-      value >>= 2;
-      value += SEXT24 (newval);
-
-      if (    (value & ~ ((offsetT) 0xffffff)) != 0
-         && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
+        instruction, in a 24 bit, signed field.  Bits 0 and 1 must be
+        clear, and bits 26 through 32 either all clear or all set. */
+      if (value & 0x00000003)
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                     _("misaligned branch destination"));
+      if ((value & (offsetT)0xfe000000) != (offsetT)0
+         && (value & (offsetT)0xfe000000) != (offsetT)0xfe000000)
        as_bad_where (fixP->fx_file, fixP->fx_line,
-                     _("out of range branch"));
+                     _("branch out of range"));
 
-      if (seg->use_rela_p && !fixP->fx_done)
+      if (fixP->fx_done || !seg->use_rela_p)
        {
-         /* Must unshift the value before storing it in the addend.  */
-         value <<= 2;
-#ifdef OBJ_ELF
-         fixP->fx_offset = value;
-#endif
-         fixP->fx_addnumber = value;
-         newval = newval & 0xff000000;
+         newval = md_chars_to_number (buf, INSN_SIZE);
+         newval |= (value >> 2) & 0x00ffffff;
+         md_number_to_chars (buf, newval, INSN_SIZE);
        }
-      else
-         newval = (value & 0x00ffffff) | (newval & 0xff000000);
-      md_number_to_chars (buf, newval, INSN_SIZE);
       break;
 
     case BFD_RELOC_ARM_PCREL_BLX:
-      {
-       offsetT hbit;
-       newval = md_chars_to_number (buf, INSN_SIZE);
+      /* BLX allows bit 1 to be set in the branch destination, since
+        it targets a Thumb instruction which is only required to be
+        aligned modulo 2.  Other constraints are as for B/BL.  */
+      if (value & 0x00000001)
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                     _("misaligned BLX destination"));
+      if ((value & (offsetT)0xfe000000) != (offsetT)0
+         && (value & (offsetT)0xfe000000) != (offsetT)0xfe000000)
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                     _("branch out of range"));
 
-#ifdef OBJ_ELF
-       value = fixP->fx_offset;
-#endif
-       hbit   = (value >> 1) & 1;
-       value  = (value >> 2) & 0x00ffffff;
-       value  = (value + (newval & 0x00ffffff)) & 0x00ffffff;
+      if (fixP->fx_done || !seg->use_rela_p)
+       {
+         offsetT hbit;
+         hbit   = (value >> 1) & 1;
+         value  = (value >> 2) & 0x00ffffff;
 
-       if (seg->use_rela_p && !fixP->fx_done)
-         {
-           /* Must sign-extend and unshift the value before storing
-              it in the addend.  */
-           value = SEXT24 (value);
-           value = (value << 2) | hbit;
-#ifdef OBJ_ELF
-           fixP->fx_offset = value;
-#endif
-           fixP->fx_addnumber = value;
-           newval = newval & 0xfe000000;
-         }
-       else
-         newval = value | (newval & 0xfe000000) | (hbit << 24);
-       md_number_to_chars (buf, newval, INSN_SIZE);
-      }
+         newval = md_chars_to_number (buf, INSN_SIZE);
+         newval |= value | hbit << 24;
+         md_number_to_chars (buf, newval, INSN_SIZE);
+       }
       break;
 
     case BFD_RELOC_THUMB_PCREL_BRANCH7: /* CZB */
-      newval = md_chars_to_number (buf, THUMB_SIZE);
-      {
-       addressT diff = ((newval & 0x00f8) >> 2) | (newval & 0x0200) >> 3;
-       /* This one does not have the offset encoded in the pattern.  */
-       value = value + diff - 4;
-       /* CZB can only branch forward.  */
-       if (value & ~0x7e)
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("branch out of range"));
+      /* CZB can only branch forward.  */
+      if (value & ~0x7e)
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                     _("branch out of range"));
 
-       newval &= 0xfd07;
-       if (seg->use_rela_p && !fixP->fx_done)
-         {
-#ifdef OBJ_ELF
-           fixP->fx_offset = value;
-#endif
-           fixP->fx_addnumber = value;
-         }
-       else
+      if (fixP->fx_done || !seg->use_rela_p)
+       {
+         newval = md_chars_to_number (buf, THUMB_SIZE);
          newval |= ((value & 0x2e) << 2) | ((value & 0x40) << 3);
-      }
-      md_number_to_chars (buf, newval, THUMB_SIZE);
+         md_number_to_chars (buf, newval, THUMB_SIZE);
+       }
       break;
 
     case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
-      newval = md_chars_to_number (buf, THUMB_SIZE);
-      {
-       addressT diff = (newval & 0xff) << 1;
-       if (diff & 0x100)
-         diff |= ~0xff;
+      if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                     _("branch out of range"));
 
-       value += diff;
-       if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("branch out of range"));
-       if (seg->use_rela_p && !fixP->fx_done)
-         {
-#ifdef OBJ_ELF
-           fixP->fx_offset = value;
-#endif
-           fixP->fx_addnumber = value;
-           newval = newval & 0xff00;
-         }
-       else
-         newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
-      }
-      md_number_to_chars (buf, newval, THUMB_SIZE);
+      if (fixP->fx_done || !seg->use_rela_p)
+       {
+         newval = md_chars_to_number (buf, THUMB_SIZE);
+         newval |= (value & 0x1ff) >> 1;
+         md_number_to_chars (buf, newval, THUMB_SIZE);
+       }
       break;
 
     case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch.  */
-      newval = md_chars_to_number (buf, THUMB_SIZE);
-      {
-       addressT diff = (newval & 0x7ff) << 1;
-       if (diff & 0x800)
-         diff |= ~0x7ff;
+      if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                     _("branch out of range"));
 
-       value += diff;
-       if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("branch out of range"));
-       if (seg->use_rela_p && !fixP->fx_done)
-         {
-#ifdef OBJ_ELF
-           fixP->fx_offset = value;
-#endif
-           fixP->fx_addnumber = value;
-           newval = newval & 0xf800;
-         }
-       else
-         newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
-      }
-      md_number_to_chars (buf, newval, THUMB_SIZE);
+      if (fixP->fx_done || !seg->use_rela_p)
+       {
+         newval = md_chars_to_number (buf, THUMB_SIZE);
+         newval |= (value & 0xfff) >> 1;
+         md_number_to_chars (buf, newval, THUMB_SIZE);
+       }
       break;
 
     case BFD_RELOC_THUMB_PCREL_BRANCH20:
-      {
-       offsetT newval2;
-       addressT diff, S, J1, J2, lo, hi;
-
-       newval  = md_chars_to_number (buf, THUMB_SIZE);
-       newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
-
-       S  = !(newval & 0x0400);  /* flipped - 0=negative */
-       hi = (newval  & 0x003f);
-       J1 = (newval2 & 0x2000) >> 13;
-       J2 = (newval2 & 0x0800) >> 11;
-       lo = (newval2 & 0x07ff);
-
-       diff = ((S << 20) | (J2 << 19) | (J1 << 18) | (hi << 12) | (lo << 1));
-       diff -= (1 << 20);  /* sign extend */
-       value += diff;
+      if ((value & ~0x1fffff) && ((value & ~0x1fffff) != ~0x1fffff))
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                     _("conditional branch out of range"));
 
-       if ((value & ~0x1fffff) && ((value & ~0x1fffff) != ~0x1fffff))
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("conditional branch out of range"));
+      if (fixP->fx_done || !seg->use_rela_p)
+       {
+         offsetT newval2;
+         addressT S, J1, J2, lo, hi;
 
-       newval  = newval  & 0xfbc0;
-       newval2 = newval2 & 0xd000;
-       if (seg->use_rela_p && !fixP->fx_done)
-         {
-#ifdef OBJ_ELF
-           fixP->fx_offset = value;
-#endif
-           fixP->fx_addnumber = value;
-         }
-       else
-         {
-           S  = (value & 0x00100000) >> 20;
-           J2 = (value & 0x00080000) >> 19;
-           J1 = (value & 0x00040000) >> 18;
-           hi = (value & 0x0003f000) >> 12;
-           lo = (value & 0x00000ffe) >> 1;
-
-           newval  = newval  | (S << 10) | hi;
-           newval2 = newval2 | (J1 << 13) | (J2 << 11) | lo;
-         }
+         S  = (value & 0x00100000) >> 20;
+         J2 = (value & 0x00080000) >> 19;
+         J1 = (value & 0x00040000) >> 18;
+         hi = (value & 0x0003f000) >> 12;
+         lo = (value & 0x00000ffe) >> 1;
 
-       md_number_to_chars (buf, newval, THUMB_SIZE);
-       md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
-      }
+         newval   = md_chars_to_number (buf, THUMB_SIZE);
+         newval2  = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
+         newval  |= (S << 10) | hi;
+         newval2 |= (J1 << 13) | (J2 << 11) | lo;
+         md_number_to_chars (buf, newval, THUMB_SIZE);
+         md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
+       }
       break;
 
     case BFD_RELOC_THUMB_PCREL_BLX:
     case BFD_RELOC_THUMB_PCREL_BRANCH23:
-      {
-       offsetT newval2;
-       addressT diff;
-
-       newval  = md_chars_to_number (buf, THUMB_SIZE);
-       newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
-       diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
-       if (diff & 0x400000)
-         diff |= ~0x3fffff;
-#ifdef OBJ_ELF
-       value = fixP->fx_offset;
-#endif
-       value += diff;
-
-       if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("branch with link out of range"));
+      if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                     _("branch out of range"));
 
-       if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
-         /* For a BLX instruction, make sure that the relocation is rounded up
-            to a word boundary.  This follows the semantics of the instruction
-            which specifies that bit 1 of the target address will come from bit
-            1 of the base address.  */
-         value = (value + 1) & ~ 1;
+      if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
+       /* For a BLX instruction, make sure that the relocation is rounded up
+          to a word boundary.  This follows the semantics of the instruction
+          which specifies that bit 1 of the target address will come from bit
+          1 of the base address.  */
+       value = (value + 1) & ~ 1;
 
-       if (seg->use_rela_p && !fixP->fx_done)
-         {
-#ifdef OBJ_ELF
-           fixP->fx_offset = value;
-#endif
-           fixP->fx_addnumber = value;
-           newval = newval & 0xf800;
-           newval2 = newval2 & 0xf800;
-         }
-       else
-         {
-           newval  = (newval  & 0xf800) | ((value & 0x7fffff) >> 12);
-           newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
-         }
-       md_number_to_chars (buf, newval, THUMB_SIZE);
-       md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
-      }
-      break;
-
-    case BFD_RELOC_8:
-      if (seg->use_rela_p && !fixP->fx_done)
-       break;
-      if (fixP->fx_done || fixP->fx_pcrel)
-       md_number_to_chars (buf, value, 1);
-#ifdef OBJ_ELF
-      else
+      if (fixP->fx_done || !seg->use_rela_p)
        {
-         value = fixP->fx_offset;
-         md_number_to_chars (buf, value, 1);
+         offsetT newval2;
+
+         newval   = md_chars_to_number (buf, THUMB_SIZE);
+         newval2  = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
+         newval  |= (value & 0x7fffff) >> 12;
+         newval2 |= (value & 0xfff) >> 1;
+         md_number_to_chars (buf, newval, THUMB_SIZE);
+         md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
        }
-#endif
       break;
 
     case BFD_RELOC_THUMB_PCREL_BRANCH25:
-      {
-       offsetT newval2;
-       addressT diff, S, I1, I2, lo, hi;
-
-       newval  = md_chars_to_number (buf, THUMB_SIZE);
-       newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
-
-       S  = (newval  & 0x0400) >> 10;
-       hi = (newval  & 0x03ff);
-       I1 = (newval2 & 0x2000) >> 13;
-       I2 = (newval2 & 0x0800) >> 11;
-       lo = (newval2 & 0x07ff);
+      if ((value & ~0x1ffffff) && ((value & ~0x1ffffff) != ~0x1ffffff))
+       as_bad_where (fixP->fx_file, fixP->fx_line,
+                     _("branch out of range"));
 
-       I1 = !(I1 ^ S);
-       I2 = !(I2 ^ S);
-       S  = !S;
+      if (fixP->fx_done || !seg->use_rela_p)
+       {
+         offsetT newval2;
+         addressT S, I1, I2, lo, hi;
 
-       diff = ((S << 24) | (I1 << 23) | (I2 << 22) | (hi << 12) | (lo << 1));
-       diff -= (1 << 24);  /* sign extend */
-       value += diff;
+         S  = (value & 0x01000000) >> 24;
+         I1 = (value & 0x00800000) >> 23;
+         I2 = (value & 0x00400000) >> 22;
+         hi = (value & 0x003ff000) >> 12;
+         lo = (value & 0x00000ffe) >> 1;
 
-       if ((value & ~0x1ffffff) && ((value & ~0x1ffffff) != ~0x1ffffff))
-         as_bad_where (fixP->fx_file, fixP->fx_line,
-                       _("branch out of range"));
+         I1 = !(I1 ^ S);
+         I2 = !(I2 ^ S);
 
-       newval  = newval  & 0xf800;
-       newval2 = newval2 & 0xd000;
-       if (seg->use_rela_p && !fixP->fx_done)
-         {
-#ifdef OBJ_ELF
-           fixP->fx_offset = value;
-#endif
-           fixP->fx_addnumber = value;
-         }
-       else
-         {
-           S  = (value & 0x01000000) >> 24;
-           I1 = (value & 0x00800000) >> 23;
-           I2 = (value & 0x00400000) >> 22;
-           hi = (value & 0x003ff000) >> 12;
-           lo = (value & 0x00000ffe) >> 1;
-
-           I1 = !(I1 ^ S);
-           I2 = !(I2 ^ S);
+         newval   = md_chars_to_number (buf, THUMB_SIZE);
+         newval2  = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
+         newval  |= (S << 10) | hi;
+         newval2 |= (I1 << 13) | (I2 << 11) | lo;
+         md_number_to_chars (buf, newval, THUMB_SIZE);
+         md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
+       }
+      break;
 
-           newval  = newval  | (S << 10) | hi;
-           newval2 = newval2 | (I1 << 13) | (I2 << 11) | lo;
-         }
-       md_number_to_chars (buf, newval, THUMB_SIZE);
-       md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
-      }
+    case BFD_RELOC_8:
+      if (fixP->fx_done || !seg->use_rela_p)
+       md_number_to_chars (buf, value, 1);
       break;
 
     case BFD_RELOC_16:
-      if (seg->use_rela_p && !fixP->fx_done)
-       break;
-      if (fixP->fx_done || fixP->fx_pcrel)
+      if (fixP->fx_done || !seg->use_rela_p)
        md_number_to_chars (buf, value, 2);
-#ifdef OBJ_ELF
-      else
-       {
-         value = fixP->fx_offset;
-         md_number_to_chars (buf, value, 2);
-       }
-#endif
       break;
 
 #ifdef OBJ_ELF
@@ -10828,9 +11495,8 @@ md_apply_fix3 (fixS *   fixP,
     case BFD_RELOC_ARM_GOT32:
     case BFD_RELOC_ARM_GOTOFF:
     case BFD_RELOC_ARM_TARGET2:
-      if (seg->use_rela_p && !fixP->fx_done)
-       break;
-      md_number_to_chars (buf, 0, 4);
+      if (fixP->fx_done || !seg->use_rela_p)
+       md_number_to_chars (buf, 0, 4);
       break;
 #endif
 
@@ -10840,22 +11506,13 @@ md_apply_fix3 (fixS * fixP,
     case BFD_RELOC_ARM_ROSEGREL32:
     case BFD_RELOC_ARM_SBREL32:
     case BFD_RELOC_32_PCREL:
-      if (seg->use_rela_p && !fixP->fx_done)
-       break;
-      if (fixP->fx_done || fixP->fx_pcrel)
+      if (fixP->fx_done || !seg->use_rela_p)
        md_number_to_chars (buf, value, 4);
-#ifdef OBJ_ELF
-      else
-       {
-         value = fixP->fx_offset;
-         md_number_to_chars (buf, value, 4);
-       }
-#endif
       break;
 
 #ifdef OBJ_ELF
     case BFD_RELOC_ARM_PREL31:
-      if (fixP->fx_done || fixP->fx_pcrel)
+      if (fixP->fx_done || !seg->use_rela_p)
        {
          newval = md_chars_to_number (buf, 4) & 0x80000000;
          if ((value ^ (value >> 1)) & 0x40000000)
@@ -10867,13 +11524,10 @@ md_apply_fix3 (fixS * fixP,
          md_number_to_chars (buf, newval, 4);
        }
       break;
-
-    case BFD_RELOC_ARM_PLT32:
-      /* It appears the instruction is fully prepared at this point.  */
-      break;
 #endif
 
     case BFD_RELOC_ARM_CP_OFF_IMM:
+    case BFD_RELOC_ARM_T32_CP_OFF_IMM:
       if (value < -1023 || value > 1023 || (value & 3))
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("co-processor offset out of range"));
@@ -10881,14 +11535,24 @@ md_apply_fix3 (fixS * fixP,
       sign = value >= 0;
       if (value < 0)
        value = -value;
-      newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
+      if (fixP->fx_r_type == BFD_RELOC_ARM_CP_OFF_IMM
+         || fixP->fx_r_type == BFD_RELOC_ARM_CP_OFF_IMM_S2)
+       newval = md_chars_to_number (buf, INSN_SIZE);
+      else
+       newval = get_thumb32_insn (buf);
+      newval &= 0xff7fff00;
       newval |= (value >> 2) | (sign ? INDEX_UP : 0);
       if (value == 0)
        newval &= ~WRITE_BACK;
-      md_number_to_chars (buf, newval, INSN_SIZE);
+      if (fixP->fx_r_type == BFD_RELOC_ARM_CP_OFF_IMM
+         || fixP->fx_r_type == BFD_RELOC_ARM_CP_OFF_IMM_S2)
+       md_number_to_chars (buf, newval, INSN_SIZE);
+      else
+       put_thumb32_insn (buf, newval);
       break;
 
     case BFD_RELOC_ARM_CP_OFF_IMM_S2:
+    case BFD_RELOC_ARM_T32_CP_OFF_IMM_S2:
       if (value < -255 || value > 255)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("co-processor offset out of range"));
@@ -11092,15 +11756,9 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
 
-  /* @@ Why fx_addnumber sometimes and fx_offset other times?  */
-#ifndef OBJ_ELF
-  if (fixp->fx_pcrel == 0)
-    reloc->addend = fixp->fx_offset;
-  else
-    reloc->addend = fixp->fx_offset = reloc->address;
-#else  /* OBJ_ELF */
+  if (fixp->fx_pcrel)
+    fixp->fx_offset = reloc->address;
   reloc->addend = fixp->fx_offset;
-#endif
 
   switch (fixp->fx_r_type)
     {
@@ -11208,10 +11866,11 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED,
          case BFD_RELOC_NONE:             type = "NONE";         break;
          case BFD_RELOC_ARM_OFFSET_IMM8:  type = "OFFSET_IMM8";  break;
          case BFD_RELOC_ARM_SHIFT_IMM:    type = "SHIFT_IMM";    break;
-         case BFD_RELOC_ARM_SMI:          type = "SMI";          break;
+         case BFD_RELOC_ARM_SMC:          type = "SMC";          break;
          case BFD_RELOC_ARM_SWI:          type = "SWI";          break;
          case BFD_RELOC_ARM_MULTI:        type = "MULTI";        break;
          case BFD_RELOC_ARM_CP_OFF_IMM:   type = "CP_OFF_IMM";   break;
+         case BFD_RELOC_ARM_T32_CP_OFF_IMM: type = "T32_CP_OFF_IMM"; break;
          case BFD_RELOC_ARM_THUMB_ADD:    type = "THUMB_ADD";    break;
          case BFD_RELOC_ARM_THUMB_SHIFT:  type = "THUMB_SHIFT";  break;
          case BFD_RELOC_ARM_THUMB_IMM:    type = "THUMB_IMM";    break;
@@ -11311,18 +11970,14 @@ arm_force_relocation (struct fix * fixp)
   if (fixp->fx_r_type == BFD_RELOC_RVA)
     return 1;
 #endif
-#ifdef OBJ_ELF
-  if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
-      || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
-      || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
-      || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
-    return 1;
-#endif
 
   /* Resolve these relocations even if the symbol is extern or weak.  */
   if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
       || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
-      || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
+      || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE
+      || fixp->fx_r_type == BFD_RELOC_ARM_T32_IMMEDIATE
+      || fixp->fx_r_type == BFD_RELOC_ARM_T32_IMM12
+      || fixp->fx_r_type == BFD_RELOC_ARM_T32_ADD_PC12)
     return 0;
 
   return generic_force_reloc (fixp);
This page took 0.102503 seconds and 4 git commands to generate.