* mips.h: Remove "mi" documentation.  Update "mh" documentation.
	(OP_MASK_MI, OP_SH_MI, MICROMIPSOP_MASK_MI, MICROMIPSOP_MASK_MI):
	Delete.
	(INSN2_WRITE_GPR_MHI): Rename to...
	(INSN2_WRITE_GPR_MH): ...this.
opcodes/
	* micromips-opc.c (WR_mhi): Rename to..
	(WR_mh): ...this.
	(micromips_opcodes): Update "movep" entry accordingly.  Replace
	"mh,mi" with "mh".
	* mips-dis.c (micromips_to_32_reg_h_map): Rename to...
	(micromips_to_32_reg_h_map1): ...this.
	(micromips_to_32_reg_i_map): Rename to...
	(micromips_to_32_reg_h_map2): ...this.
	(print_micromips_insn): Remove "mi" case.  Print both registers
	in the pair for "mh".
gas/
	* config/tc-mips.c (mips32_to_micromips_reg_h_map): Delete.
	(micromips_to_32_reg_h_map): Rename to...
	(micromips_to_32_reg_h_map1): ...this.
	(micromips_to_32_reg_i_map): Rename to...
	(micromips_to_32_reg_h_map2): ...this.
	(mips_lookup_reg_pair): New function.
	(gpr_write_mask, macro): Adjust after above renaming.
	(validate_micromips_insn): Remove "mi" handling.
	(mips_ip): Likewise.  Parse both registers in a pair for "mh".
+2013-07-07  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * config/tc-mips.c (mips32_to_micromips_reg_h_map): Delete.
+       (micromips_to_32_reg_h_map): Rename to...
+       (micromips_to_32_reg_h_map1): ...this.
+       (micromips_to_32_reg_i_map): Rename to...
+       (micromips_to_32_reg_h_map2): ...this.
+       (mips_lookup_reg_pair): New function.
+       (gpr_write_mask, macro): Adjust after above renaming.
+       (validate_micromips_insn): Remove "mi" handling.
+       (mips_ip): Likewise.  Parse both registers in a pair for "mh".
+
 2013-07-07  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * config/tc-mips.c (validate_mips_insn, validate_micromips_insn)
 
 #define mips32_to_micromips_reg_l_map  mips32_to_16_reg_map
 
 #define X ILLEGAL_REG
-/* reg type h: 4, 5, 6.  */
-static const int mips32_to_micromips_reg_h_map[] =
-{
-  X, X, X, X, 4, 5, 6, X,
-  X, X, X, X, X, X, X, X,
-  X, X, X, X, X, X, X, X,
-  X, X, X, X, X, X, X, X
-};
-
 /* reg type m: 0, 17, 2, 3, 16, 18, 19, 20.  */
 static const int mips32_to_micromips_reg_m_map[] =
 {
 #define micromips_to_32_reg_g_map      mips16_to_32_reg_map
 
 /* The microMIPS registers with type h.  */
-static const unsigned int micromips_to_32_reg_h_map[] =
+static const unsigned int micromips_to_32_reg_h_map1[] =
 {
   5, 5, 6, 4, 4, 4, 4, 4
 };
-
-/* The microMIPS registers with type i.  */
-static const unsigned int micromips_to_32_reg_i_map[] =
+static const unsigned int micromips_to_32_reg_h_map2[] =
 {
   6, 7, 7, 21, 22, 5, 6, 7
 };
   return ok && reglist != 0;
 }
 
+static unsigned int
+mips_lookup_reg_pair (unsigned int regno1, unsigned int regno2,
+                     const unsigned int *map1, const unsigned int *map2,
+                     unsigned int count)
+{
+  unsigned int i;
+
+  for (i = 0; i < count; i++)
+    if (map1[i] == regno1 && map2[i] == regno2)
+      return i;
+  return ILLEGAL_REG;
+}
+
 /* Return TRUE if opcode MO is valid on the currently selected ISA, ASE
    and architecture.  Use is_opcode_valid_16 for MIPS16 opcodes.  */
 
     {
       if (pinfo2 & INSN2_WRITE_GPR_MB)
        mask |= 1 << micromips_to_32_reg_b_map[EXTRACT_OPERAND (1, MB, *ip)];
-      if (pinfo2 & INSN2_WRITE_GPR_MHI)
+      if (pinfo2 & INSN2_WRITE_GPR_MH)
        {
-         mask |= 1 << micromips_to_32_reg_h_map[EXTRACT_OPERAND (1, MH, *ip)];
-         mask |= 1 << micromips_to_32_reg_i_map[EXTRACT_OPERAND (1, MI, *ip)];
+         mask |= 1 << micromips_to_32_reg_h_map1[EXTRACT_OPERAND (1, MH, *ip)];
+         mask |= 1 << micromips_to_32_reg_h_map2[EXTRACT_OPERAND (1, MH, *ip)];
        }
       if (pinfo2 & INSN2_WRITE_GPR_MJ)
        mask |= 1 << EXTRACT_OPERAND (1, MJ, *ip);
     case M_MOVEP:
       gas_assert (mips_opts.micromips);
       gas_assert (mips_opts.insn32);
-      dreg = micromips_to_32_reg_h_map[EXTRACT_OPERAND (1, MH, *ip)];
-      breg = micromips_to_32_reg_i_map[EXTRACT_OPERAND (1, MI, *ip)];
+      dreg = micromips_to_32_reg_h_map1[EXTRACT_OPERAND (1, MH, *ip)];
+      breg = micromips_to_32_reg_h_map2[EXTRACT_OPERAND (1, MH, *ip)];
       sreg = micromips_to_32_reg_m_map[EXTRACT_OPERAND (1, MM, *ip)];
       treg = micromips_to_32_reg_n_map[EXTRACT_OPERAND (1, MN, *ip)];
       move_register (dreg, sreg);
          case 'f': USE_BITS (MF);      break;
          case 'g': USE_BITS (MG);      break;
          case 'h': USE_BITS (MH);      break;
-         case 'i': USE_BITS (MI);      break;
          case 'j': USE_BITS (MJ);      break;
          case 'l': USE_BITS (ML);      break;
          case 'm': USE_BITS (MM);      break;
   char c = 0;
   struct mips_opcode *insn;
   char *argsStart;
-  unsigned int regno;
+  unsigned int regno, regno2;
   unsigned int lastregno;
   unsigned int destregno = 0;
   unsigned int lastpos = 0;
                case 'f':
                case 'g':
                case 'h':
-               case 'i':
                case 'j':
                case 'l':
                case 'm':
                        break;
 
                      case 'h':
-                       regno = mips32_to_micromips_reg_h_map[regno];
-                       break;
-
-                     case 'i':
-                       switch (EXTRACT_OPERAND (1, MI, *ip))
+                       s += strspn (s, " \t");
+                       if (*s != ',')
                          {
-                           case 4:
-                             if (regno == 21)
-                               regno = 3;
-                             else if (regno == 22)
-                               regno = 4;
-                             else if (regno == 5)
-                               regno = 5;
-                             else if (regno == 6)
-                               regno = 6;
-                             else if (regno == 7)
-                               regno = 7;
-                             else
-                               regno = ILLEGAL_REG;
-                             break;
-
-                           case 5:
-                             if (regno == 6)
-                               regno = 0;
-                             else if (regno == 7)
-                               regno = 1;
-                             else
-                               regno = ILLEGAL_REG;
-                             break;
-
-                           case 6:
-                             if (regno == 7)
-                               regno = 2;
-                             else
-                               regno = ILLEGAL_REG;
-                             break;
-
-                           default:
-                             regno = ILLEGAL_REG;
-                             break;
+                           regno = ILLEGAL_REG;
+                           break;
                          }
+                       ++s;
+                       s += strspn (s, " \t");
+                       ok = reg_lookup (&s, RTYPE_NUM | RTYPE_GP, ®no2);
+                       if (!ok)
+                         {
+                           regno = ILLEGAL_REG;
+                           break;
+                         }
+                       if (regno2 == AT && mips_opts.at)
+                         {
+                           if (mips_opts.at == ATREG)
+                             as_warn (_("Used $at without \".set noat\""));
+                           else
+                             as_warn (_("Used $%u with \".set at=$%u\""),
+                                      regno2, mips_opts.at);
+                         }
+                       regno = (mips_lookup_reg_pair
+                                (regno, regno2,
+                                 micromips_to_32_reg_h_map1,
+                                 micromips_to_32_reg_h_map2, 8));
                        break;
 
                      case 'l':
                        INSERT_OPERAND (1, MH, *ip, regno);
                        break;
 
-                     case 'i':
-                       INSERT_OPERAND (1, MI, *ip, regno);
-                       break;
-
                      case 'j':
                        INSERT_OPERAND (1, MJ, *ip, regno);
                        break;
 
+2013-07-07  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * mips.h: Remove "mi" documentation.  Update "mh" documentation.
+       (OP_MASK_MI, OP_SH_MI, MICROMIPSOP_MASK_MI, MICROMIPSOP_MASK_MI):
+       Delete.
+       (INSN2_WRITE_GPR_MHI): Rename to...
+       (INSN2_WRITE_GPR_MH): ...this.
+
 2013-07-07  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * mips.h: Remove documentation of "+D" and "+T".
 
 #define OP_SH_MG               0
 #define OP_MASK_MH             0
 #define OP_SH_MH               0
-#define OP_MASK_MI             0
-#define OP_SH_MI               0
 #define OP_MASK_MJ             0
 #define OP_SH_MJ               0
 #define OP_MASK_ML             0
 #define INSN2_UNCOND_BRANCH        0x10000000
 /* Is a conditional branch insn. */
 #define INSN2_COND_BRANCH          0x20000000
-/* Modifies the general purpose registers in MICROMIPSOP_*_MH/I.  */
-#define INSN2_WRITE_GPR_MHI        0x40000000
+/* Modifies the general purpose registers in MICROMIPSOP_*_MH.  */
+#define INSN2_WRITE_GPR_MH         0x40000000
 /* Reads the general purpose registers in MICROMIPSOP_*_MM/N.  */
 #define INSN2_READ_GPR_MMN         0x80000000
 
 #define MICROMIPSOP_SH_MG              0
 #define MICROMIPSOP_MASK_MH            0x7
 #define MICROMIPSOP_SH_MH              7
-#define MICROMIPSOP_MASK_MI            0x7
-#define MICROMIPSOP_SH_MI              7
 #define MICROMIPSOP_MASK_MJ            0x1f
 #define MICROMIPSOP_SH_MJ              0
 #define MICROMIPSOP_MASK_ML            0x7
         The same register used as both source and target.
    "mf" 3-bit MIPS registers 2-7, 16, 17 (MICROMIPSOP_*_MF) at bit 3
    "mg" 3-bit MIPS registers 2-7, 16, 17 (MICROMIPSOP_*_MG) at bit 0
-   "mh" MIPS registers 4, 5, 6 (MICROMIPSOP_*_MH) at bit 7
-   "mi" MIPS registers 5, 6, 7, 21, 22 (MICROMIPSOP_*_MI) at bit 7
-       ("mh" and "mi" form a valid 3-bit register pair)
+   "mh" 3-bit MIPS register pair (MICROMIPSOP_*_MH) at bit 7
    "mj" 5-bit MIPS registers (MICROMIPSOP_*_MJ) at bit 0
    "ml" 3-bit MIPS registers 2-7, 16, 17 (MICROMIPSOP_*_ML) at bit 4
    "mm" 3-bit MIPS registers 0, 2, 3, 16-20 (MICROMIPSOP_*_MM) at bit 1
 
+2013-07-07  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * micromips-opc.c (WR_mhi): Rename to..
+       (WR_mh): ...this.
+       (micromips_opcodes): Update "movep" entry accordingly.  Replace
+       "mh,mi" with "mh".
+       * mips-dis.c (micromips_to_32_reg_h_map): Rename to...
+       (micromips_to_32_reg_h_map1): ...this.
+       (micromips_to_32_reg_i_map): Rename to...
+       (micromips_to_32_reg_h_map2): ...this.
+       (print_micromips_insn): Remove "mi" case.  Print both registers
+       in the pair for "mh".
+
 2013-07-07  Richard Sandiford  <rdsandiford@googlemail.com>
 
        * mips-opc.c (mips_builtin_opcodes): Remove "+D" and "+T" entries.
 
 #define RD_mf  INSN2_MOD_GPR_MF
 #define WR_mf  INSN2_MOD_GPR_MF
 #define RD_mg  INSN2_READ_GPR_MG
-#define WR_mhi INSN2_WRITE_GPR_MHI
+#define WR_mh  INSN2_WRITE_GPR_MH
 #define RD_mj  INSN2_READ_GPR_MJ
 #define WR_mj  INSN2_WRITE_GPR_MJ
 #define RD_ml  RD_mc   /* Reuse, since the bit position is the same.  */
 {"mov.d",   "T,S",     0x5400207b, 0xfc00ffff, WR_T|RD_S|FP_D,         0,              I1      },
 {"mov.s",   "T,S",     0x5400007b, 0xfc00ffff, WR_T|RD_S|FP_S,         0,              I1      },
 {"mov.ps",  "T,S",     0x5400407b, 0xfc00ffff, WR_T|RD_S|FP_D,         0,              I1      },
-{"movep",   "mh,mi,mm,mn",  0x8400,     0xfc01,        NODS,                   WR_mhi|RD_mmn,  I1      },
+{"movep",   "mh,mm,mn",     0x8400,     0xfc01,        NODS,                   WR_mh|RD_mmn,   I1      },
 /* This macro is after the real instruction so that it only matches with
    -minsn32.  */
-{"movep",   "mh,mi,mm,mn", 0, (int) M_MOVEP,   INSN_MACRO,             0,              I1      },
+{"movep",   "mh,mm,mn", 0, (int) M_MOVEP,      INSN_MACRO,             0,              I1      },
 {"movf",    "t,s,M",   0x5400017b, 0xfc001fff, WR_t|RD_s|RD_CC|FP_S|FP_D, 0,           I1      },
 {"movf.d",  "T,S,M",   0x54000220, 0xfc001fff, WR_T|RD_S|RD_CC|FP_D,   0,              I1      },
 {"movf.s",  "T,S,M",   0x54000020, 0xfc001fff, WR_T|RD_S|RD_CC|FP_S,   0,              I1      },
 
 #define micromips_to_32_reg_g_map      mips16_to_32_reg_map
 
 /* The microMIPS registers with type h.  */
-static const unsigned int micromips_to_32_reg_h_map[] =
+static const unsigned int micromips_to_32_reg_h_map1[] =
 {
   5, 5, 6, 4, 4, 4, 4, 4
 };
-
-/* The microMIPS registers with type i.  */
-static const unsigned int micromips_to_32_reg_i_map[] =
+static const unsigned int micromips_to_32_reg_h_map2[] =
 {
   6, 7, 7, 21, 22, 5, 6, 7
 };
                      break;
 
                    case 'h':
-                     regno = micromips_to_32_reg_h_map[GET_OP (insn, MH)];
-                     infprintf (is, "%s", mips_gpr_names[regno]);
-                     break;
-
-                   case 'i':
-                     regno = micromips_to_32_reg_i_map[GET_OP (insn, MI)];
+                     regno = micromips_to_32_reg_h_map1[GET_OP (insn, MH)];
                      infprintf (is, "%s", mips_gpr_names[regno]);
+                     regno = micromips_to_32_reg_h_map2[GET_OP (insn, MH)];
+                     infprintf (is, ",%s", mips_gpr_names[regno]);
                      break;
 
                    case 'j':