This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


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

[committed] Add structures to describe MIPS operands


This patch adds some enums and structures to classify MIPS operands.
It also adds functions for decoding the text operands used in mips-opc.c
and micromips-opc.c into structure form.  (The next patch will handle
MIPS16.)

As a first step, the patch uses the structures when disassembling
(mips-dis.c) and when checking the integrity of the opcode table
(tc-mips.c).  Later patches use them for other things too.

Tested on various targets and applied.

Richard


include/opcode/
	* mips.h (mips_operand_type, mips_reg_operand_type): New enums.
	(mips_operand, mips_int_operand, mips_mapped_int_operand)
	(mips_msb_operand, mips_reg_operand, mips_reg_pair_operand)
	(mips_pcrel_operand): New structures.
	(mips_insert_operand, mips_extract_operand, mips_signed_operand)
	(mips_decode_int_operand, mips_decode_pcrel_operand): New functions.
	(decode_mips_operand, decode_micromips_operand): Declare.

opcodes/
	* mips-formats.h: New file.
	* mips-opc.c: Include mips-formats.h.
	(reg_0_map): New static array.
	(decode_mips_operand): New function.
	* micromips-opc.c: Remove <stdio.h> include.  Include mips-formats.h.
	(reg_0_map, reg_28_map, reg_29_map, reg_31_map, reg_m16_map)
	(reg_mn_map, reg_q_map, reg_h_map1, reg_h_map2, int_b_map)
	(int_c_map): New static arrays.
	(decode_micromips_operand): New function.
	* mips-dis.c (micromips_to_32_reg_b_map, micromips_to_32_reg_c_map)
	(micromips_to_32_reg_d_map, micromips_to_32_reg_e_map)
	(micromips_to_32_reg_f_map, micromips_to_32_reg_g_map)
	(micromips_to_32_reg_h_map1, micromips_to_32_reg_h_map2)
	(micromips_to_32_reg_l_map, micromips_to_32_reg_m_map)
	(micromips_to_32_reg_n_map, micromips_to_32_reg_q_map)
	(micromips_imm_b_map, micromips_imm_c_map): Delete.
	(print_reg): New function.
	(mips_print_arg_state): New structure.
	(init_print_arg_state, print_insn_arg): New functions.
	(print_insn_args): Change interface and use mips_operand structures.
	Delete GET_OP_S.  Move GET_OP definition to...
	(print_insn_mips): ...here.  Update the call to print_insn_args.
	(print_insn_micromips): Use print_insn_args.

gas/
	* config/tc-mips.c (validate_mips_insn): Move further up file.
	Add insn_bits and decode_operand arguments.  Use the mips_operand
	fields to work out which bits an operand occupies.  Detect double
	definitions.
	(validate_micromips_insn): Move further up file.  Call into
	validate_mips_insn.

Index: include/opcode/mips.h
===================================================================
*** include/opcode/mips.h	2013-07-14 10:33:21.087809400 +0100
--- include/opcode/mips.h	2013-07-14 10:43:31.113619048 +0100
*************** #define OP_SH_IMMY		0
*** 332,337 ****
--- 332,623 ----
  #define OP_SH_EVAOFFSET		7
  #define OP_MASK_EVAOFFSET	0x1ff
  
+ /* Enumerates the various types of MIPS operand.  */
+ enum mips_operand_type {
+   /* Described by mips_int_operand.  */
+   OP_INT,
+ 
+   /* Described by mips_mapped_int_operand.  */
+   OP_MAPPED_INT,
+ 
+   /* Described by mips_msb_operand.  */
+   OP_MSB,
+ 
+   /* Described by mips_reg_operand.  */
+   OP_REG,
+ 
+   /* Described by mips_reg_pair_operand.  */
+   OP_REG_PAIR,
+ 
+   /* Described by mips_pcrel_operand.  */
+   OP_PCREL,
+ 
+   /* A performance register.  The field is 5 bits in size, but the supported
+      values are much more restricted.  */
+   OP_PERF_REG,
+ 
+   /* The final operand in a microMIPS ADDIUSP instruction.  It mostly acts
+      as a normal 9-bit signed offset that is multiplied by four, but there
+      are four special cases:
+ 
+      -2 * 4 => -258 * 4
+      -1 * 4 => -257 * 4
+       0 * 4 =>  256 * 4
+       1 * 4 =>  257 * 4.  */
+   OP_ADDIUSP_INT,
+ 
+   /* The target of a (D)CLO or (D)CLZ instruction.  The operand spans two
+      5-bit register fields, both of which must be set to the destination
+      register.  */
+   OP_CLO_CLZ_DEST,
+ 
+   /* A register list for a microMIPS LWM or SWM instruction.  The operand
+      size determines whether the 16-bit or 32-bit encoding is required.  */
+   OP_LWM_SWM_LIST,
+ 
+   /* A 10-bit field VVVVVNNNNN used for octobyte and quadhalf instructions:
+ 
+      V      Meaning
+      -----  -------
+      0EEE0  8 copies of $vN[E], OB format
+      0EE01  4 copies of $vN[E], QH format
+      10110  all 8 elements of $vN, OB format
+      10101  all 4 elements of $vN, QH format
+      11110  8 copies of immediate N, OB format
+      11101  4 copies of immediate N, QH format.  */
+   OP_MDMX_IMM_REG,
+ 
+   /* A register operand that must match the destination register.  */
+   OP_REPEAT_DEST_REG,
+ 
+   /* A register operand that must match the previous register.  */
+   OP_REPEAT_PREV_REG,
+ 
+   /* $pc, which has no encoding in the architectural instruction.  */
+   OP_PC
+ };
+ 
+ /* Enumerates the types of MIPS register.  */
+ enum mips_reg_operand_type {
+   /* General registers $0-$31.  Software names like $at can also be used.  */
+   OP_REG_GP,
+ 
+   /* Floating-point registers $f0-$f31.  */
+   OP_REG_FP,
+ 
+   /* Coprocessor condition code registers $cc0-$cc7.  FPU condition codes
+      can also be written $fcc0-$fcc7.  */
+   OP_REG_CCC,
+ 
+   /* FPRs used in a vector capacity.  They can be written $f0-$f31
+      or $v0-$v31, although the latter form is not used for the VR5400
+      vector instructions.  */
+   OP_REG_VEC,
+ 
+   /* DSP accumulator registers $ac0-$ac3.  */
+   OP_REG_ACC,
+ 
+   /* Coprocessor registers $0-$31.  Mnemonic names like c0_cause can
+      also be used in some contexts.  */
+   OP_REG_COPRO,
+ 
+   /* Hardware registers $0-$31.  Mnemonic names like hwr_cpunum can
+      also be used in some contexts.  */
+   OP_REG_HW
+ };
+ 
+ /* Base class for all operands.  */
+ struct mips_operand
+ {
+   /* The type of the operand.  */
+   enum mips_operand_type type;
+ 
+   /* The operand occupies SIZE bits of the instruction, starting at LSB.  */
+   unsigned short size;
+   unsigned short lsb;
+ };
+ 
+ /* Describes an integer operand with a regular encoding pattern.  */
+ struct mips_int_operand
+ {
+   struct mips_operand root;
+ 
+   /* The low ROOT.SIZE bits of MAX_VAL encodes (MAX_VAL + BIAS) << SHIFT.
+      The cyclically previous field value encodes 1 << SHIFT less than that,
+      and so on.  E.g.
+ 
+      - for { { T, 4, L }, 14, 0, 0 }, field values 0...14 encode themselves,
+        but 15 encodes -1.
+ 
+      - { { T, 8, L }, 127, 0, 2 } is a normal signed 8-bit operand that is
+        shifted left two places.
+ 
+      - { { T, 3, L }, 8, 0, 0 } is a normal unsigned 3-bit operand except
+        that 0 encodes 8.
+ 
+      - { { ... }, 0, 1, 3 } means that N encodes (N + 1) << 3.  */
+   unsigned int max_val;
+   int bias;
+   unsigned int shift;
+ 
+   /* True if the operand should be printed as hex rather than decimal.  */
+   bfd_boolean print_hex;
+ };
+ 
+ /* Uses a lookup table to describe a small integer operand.  */
+ struct mips_mapped_int_operand
+ {
+   struct mips_operand root;
+ 
+   /* Maps each encoding value to the integer that it represents.  */
+   const int *int_map;
+ 
+   /* True if the operand should be printed as hex rather than decimal.  */
+   bfd_boolean print_hex;
+ };
+ 
+ /* An operand that encodes the most significant bit position of a bitfield.
+    Given a bitfield that spans bits [MSB, LSB], some operands of this type
+    encode MSB directly while others encode MSB - LSB.  Each operand of this
+    type is preceded by an integer operand that specifies LSB.
+ 
+    The assembly form varies between instructions.  For some instructions,
+    such as EXT, the operand is written as the bitfield size.  For others,
+    such as EXTS, it is written in raw MSB - LSB form.  */
+ struct mips_msb_operand
+ {
+   struct mips_operand root;
+ 
+   /* The assembly-level operand encoded by a field value of 0.  */
+   int bias;
+ 
+   /* True if the operand encodes MSB directly, false if it encodes
+      MSB - LSB.  */
+   bfd_boolean add_lsb;
+ 
+   /* The maximum value of MSB + 1.  */
+   unsigned int opsize;
+ };
+ 
+ /* Describes a single register operand.  */
+ struct mips_reg_operand
+ {
+   struct mips_operand root;
+ 
+   /* The type of register.  */
+   enum mips_reg_operand_type reg_type;
+ 
+   /* If nonnull, REG_MAP[N] gives the register associated with encoding N,
+      otherwise the encoding is the same as the register number.  */
+   const unsigned char *reg_map;
+ };
+ 
+ /* Describes an operand that encodes a pair of registers.  */
+ struct mips_reg_pair_operand
+ {
+   struct mips_operand root;
+ 
+   /* The type of register.  */
+   enum mips_reg_operand_type reg_type;
+ 
+   /* Encoding N represents REG1_MAP[N], REG2_MAP[N].  */
+   unsigned char *reg1_map;
+   unsigned char *reg2_map;
+ };
+ 
+ /* Describes an operand that is calculated relative to a base PC.
+    The base PC is usually the address of the following instruction,
+    but the rules for MIPS16 instructions like ADDIUPC are more complicated.  */
+ struct mips_pcrel_operand
+ {
+   struct mips_operand root;
+ 
+   /* The low ALIGN_LOG2 bits of the base PC are cleared to give PC'.  */
+   unsigned int align_log2 : 8;
+ 
+   /* The operand is shifted left SHIFT places and added to PC'.
+      The operand is signed if IS_SIGNED.  */
+   unsigned int shift : 8;
+   unsigned int is_signed : 1;
+ 
+   /* If INCLUDE_ISA_BIT, the ISA bit of the original base PC is then
+      reinstated.  This is true for jumps and branches and false for
+      PC-relative data instructions.  */
+   unsigned int include_isa_bit : 1;
+ 
+   /* If FLIP_ISA_BIT, the ISA bit of the result is inverted.
+      This is true for JALX and false otherwise.  */
+   unsigned int flip_isa_bit : 1;
+ };
+ 
+ /* Return a version of INSN in which the field specified by OPERAND
+    has value UVAL.  */
+ 
+ static inline unsigned int
+ mips_insert_operand (const struct mips_operand *operand, unsigned int insn,
+ 		     unsigned int uval)
+ {
+   unsigned int mask;
+ 
+   mask = (1 << operand->size) - 1;
+   insn &= ~(mask << operand->lsb);
+   insn |= (uval & mask) << operand->lsb;
+   return insn;
+ }
+ 
+ /* Extract OPERAND from instruction INSN.  */
+ 
+ static inline unsigned int
+ mips_extract_operand (const struct mips_operand *operand, unsigned int insn)
+ {
+   return (insn >> operand->lsb) & ((1 << operand->size) - 1);
+ }
+ 
+ /* UVAL is the value encoded by OPERAND.  Return it in signed form.  */
+ 
+ static inline int
+ mips_signed_operand (const struct mips_operand *operand, unsigned int uval)
+ {
+   unsigned int sign_bit, mask;
+ 
+   mask = (1 << operand->size) - 1;
+   sign_bit = 1 << (operand->size - 1);
+   return ((uval + sign_bit) & mask) - sign_bit;
+ }
+ 
+ /* Return the integer that OPERAND encodes as UVAL.  */
+ 
+ static inline int
+ mips_decode_int_operand (const struct mips_int_operand *operand,
+ 			 unsigned int uval)
+ {
+   uval |= (operand->max_val - uval) & -(1 << operand->root.size);
+   uval += operand->bias;
+   uval <<= operand->shift;
+   return uval;
+ }
+ 
+ /* PC-relative operand OPERAND has value UVAL and is relative to BASE_PC.
+    Return the address that it encodes.  */
+ 
+ static inline bfd_vma
+ mips_decode_pcrel_operand (const struct mips_pcrel_operand *operand,
+ 			   bfd_vma base_pc, unsigned int uval)
+ {
+   bfd_vma addr;
+ 
+   addr = base_pc & -(1 << operand->align_log2);
+   if (operand->is_signed)
+     addr += mips_signed_operand (&operand->root, uval) * (1 << operand->shift);
+   else
+     addr += uval << operand->shift;
+   if (operand->include_isa_bit)
+     addr |= base_pc & 1;
+   if (operand->flip_isa_bit)
+     addr ^= 1;
+   return addr;
+ }
+ 
  /* This structure holds information for a particular instruction.  */
  
  struct mips_opcode
*************** enum
*** 1215,1220 ****
--- 1501,1507 ----
     Many instructions are short hand for other instructions (i.e., The
     jal <register> instruction is short for jalr <register>).  */
  
+ extern const struct mips_operand *decode_mips_operand (const char *);
  extern const struct mips_opcode mips_builtin_opcodes[];
  extern const int bfd_mips_num_builtin_opcodes;
  extern struct mips_opcode *mips_opcodes;
*************** #define MICROMIPSOP_MASK_EVAOFFSET	0x1ff
*** 1780,1785 ****
--- 2067,2073 ----
     " bcdefghij lmn pq st   xyz"
  */
  
+ extern const struct mips_operand *decode_micromips_operand (const char *);
  extern const struct mips_opcode micromips_opcodes[];
  extern const int bfd_micromips_num_opcodes;
  
Index: opcodes/mips-formats.h
===================================================================
*** /dev/null	2013-07-07 08:24:27.294569946 +0100
--- opcodes/mips-formats.h	2013-07-14 10:35:55.849156274 +0100
***************
*** 0 ****
--- 1,113 ----
+ /* mips-formats.h
+    Copyright 2013 Free Software Foundation, Inc.
+ 
+    This library is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3, or (at your option)
+    any later version.
+ 
+    It is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+    License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING3. If not,
+    see <http://www.gnu.org/licenses/>.  */
+ 
+ /* For ARRAY_SIZE.  */
+ #include "libiberty.h"
+ 
+ #define INT_ADJ(SIZE, LSB, MAX_VAL, SHIFT, PRINT_HEX) \
+   { \
+     static const struct mips_int_operand op = { \
+       { OP_INT, SIZE, LSB }, MAX_VAL, 0, SHIFT, PRINT_HEX \
+     }; \
+     return &op.root; \
+   }
+ 
+ #define UINT(SIZE, LSB) \
+   INT_ADJ(SIZE, LSB, (1 << (SIZE)) - 1, 0, FALSE)
+ 
+ #define SINT(SIZE, LSB) \
+   INT_ADJ(SIZE, LSB, (1 << ((SIZE) - 1)) - 1, 0, FALSE)
+ 
+ #define HINT(SIZE, LSB) \
+   INT_ADJ(SIZE, LSB, (1 << (SIZE)) - 1, 0, TRUE)
+ 
+ #define BIT(SIZE, LSB, BIAS) \
+   { \
+     static const struct mips_int_operand op = { \
+       { OP_INT, SIZE, LSB }, (1 << (SIZE)) - 1, BIAS, 0, TRUE \
+     }; \
+     return &op.root; \
+   }
+ 
+ #define MAPPED_INT(SIZE, LSB, MAP, PRINT_HEX) \
+   { \
+     typedef char static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \
+     static const struct mips_mapped_int_operand op = { \
+       { OP_MAPPED_INT, SIZE, LSB }, MAP, PRINT_HEX \
+     }; \
+     return &op.root; \
+   }
+ 
+ #define MSB(SIZE, LSB, BIAS, ADD_LSB, OPSIZE) \
+   { \
+     static const struct mips_msb_operand op = { \
+       { OP_MSB, SIZE, LSB }, BIAS, ADD_LSB, OPSIZE \
+     }; \
+     return &op.root; \
+   }
+ 
+ #define REG(SIZE, LSB, BANK) \
+   { \
+     static const struct mips_reg_operand op = { \
+       { OP_REG, SIZE, LSB }, OP_REG_##BANK, 0 \
+     }; \
+     return &op.root; \
+   }
+ 
+ #define MAPPED_REG(SIZE, LSB, BANK, MAP) \
+   { \
+     typedef char static_assert[(1 << (SIZE)) == ARRAY_SIZE (MAP)]; \
+     static const struct mips_reg_operand op = { \
+       { OP_REG, SIZE, LSB }, OP_REG_##BANK, MAP \
+     }; \
+     return &op.root; \
+   }
+ 
+ #define REG_PAIR(SIZE, LSB, BANK, MAP) \
+   { \
+     typedef char static_assert1[(1 << (SIZE)) == ARRAY_SIZE (MAP##1)]; \
+     typedef char static_assert2[(1 << (SIZE)) == ARRAY_SIZE (MAP##2)]; \
+     static const struct mips_reg_pair_operand op = { \
+       { OP_REG_PAIR, SIZE, LSB }, OP_REG_##BANK, MAP##1, MAP##2 \
+     }; \
+     return &op.root; \
+   }
+ 
+ #define PCREL(SIZE, LSB, ALIGN_LOG2, SHIFT, IS_SIGNED, INCLUDE_ISA_BIT, \
+               FLIP_ISA_BIT) \
+   { \
+     static const struct mips_pcrel_operand op = { \
+       { OP_PCREL, SIZE, LSB }, ALIGN_LOG2, SHIFT, IS_SIGNED, \
+       INCLUDE_ISA_BIT, FLIP_ISA_BIT \
+     }; \
+     return &op.root; \
+   }
+ 
+ #define JUMP(SIZE, LSB, SHIFT) \
+   PCREL (SIZE, LSB, SIZE + SHIFT, SHIFT, FALSE, TRUE, FALSE)
+ 
+ #define JALX(SIZE, LSB, SHIFT) \
+   PCREL (SIZE, LSB, SIZE + SHIFT, SHIFT, FALSE, TRUE, TRUE)
+ 
+ #define BRANCH(SIZE, LSB, SHIFT) \
+   PCREL (SIZE, LSB, 0, SHIFT, TRUE, TRUE, FALSE)
+ 
+ #define SPECIAL(SIZE, LSB, TYPE) \
+   { \
+     static const struct mips_operand op = { OP_##TYPE, SIZE, LSB }; \
+     return &op; \
+   }
Index: opcodes/mips-opc.c
===================================================================
*** opcodes/mips-opc.c	2013-07-14 10:33:21.087809400 +0100
--- opcodes/mips-opc.c	2013-07-14 10:35:55.851156293 +0100
***************
*** 28,33 ****
--- 28,150 ----
  #include "sysdep.h"
  #include <stdio.h>
  #include "opcode/mips.h"
+ #include "mips-formats.h"
+ 
+ static unsigned char reg_0_map[] = { 0 };
+ 
+ /* Return the mips_operand structure for the operand at the beginning of P.  */
+ 
+ const struct mips_operand *
+ decode_mips_operand (const char *p)
+ {
+   switch (p[0])
+     {
+     case '+':
+       switch (p[1])
+ 	{
+ 	case '1': HINT (5, 6);
+ 	case '2': HINT (10, 6);
+ 	case '3': HINT (15, 6);
+ 	case '4': HINT (20, 6);
+ 
+ 	case 'A': BIT (5, 6, 0);		/* (0 .. 31) */
+ 	case 'B': MSB (5, 11, 1, TRUE, 32);	/* (1 .. 32), 32-bit op */
+ 	case 'C': MSB (5, 11, 1, FALSE, 32);	/* (1 .. 32), 32-bit op */
+ 	case 'E': BIT (5, 6, 32);		/* (32 .. 63) */
+ 	case 'F': MSB (5, 11, 33, TRUE, 64);	/* (33 .. 64), 64-bit op */
+ 	case 'G': MSB (5, 11, 33, FALSE, 64);	/* (33 .. 64), 64-bit op */
+ 	case 'H': MSB (5, 11, 1, FALSE, 64);	/* (1 .. 32), 64-bit op */
+ 	case 'J': HINT (10, 11);
+ 	case 'P': BIT (5, 6, 32);		/* (32 .. 63) */
+ 	case 'Q': SINT (10, 6);
+ 	case 'S': MSB (5, 11, 0, FALSE, 63);	/* (0 .. 31), 64-bit op */
+ 	case 'X': BIT (5, 16, 32);		/* (32 .. 63) */
+ 	case 'Z': REG (5, 0, FP);
+ 
+ 	case 'a': SINT (8, 6);
+ 	case 'b': SINT (8, 3);
+ 	case 'c': INT_ADJ (9, 6, 255, 4, FALSE); /* (-256 .. 255) << 4 */
+ 	case 'i': JALX (26, 0, 2);
+ 	case 'j': SINT (9, 7);
+ 	case 'p': BIT (5, 6, 0);		/* (0 .. 31), 32-bit op */
+ 	case 's': MSB (5, 11, 0, FALSE, 31);	/* (0 .. 31) */
+ 	case 't': REG (5, 16, COPRO);
+ 	case 'x': BIT (5, 16, 0);		/* (0 .. 31) */
+ 	case 'z': REG (5, 0, GP);
+ 	}
+       break;
+ 
+     case '<': BIT (5, 6, 0);			/* (0 .. 31) */
+     case '>': BIT (5, 6, 32);			/* (32 .. 63) */
+     case '%': UINT (3, 21);
+     case ':': SINT (7, 19);
+     case '\'': HINT (6, 16);
+     case '@': SINT (10, 16);
+     case '!': UINT (1, 5);
+     case '$': UINT (1, 4);
+     case '*': REG (2, 18, ACC);
+     case '&': REG (2, 13, ACC);
+     case '~': SINT (12, 0);
+     case '\\': BIT (3, 12, 0);			/* (0 .. 7) */
+ 
+     case '0': SINT (6, 20);
+     case '1': HINT (5, 6);
+     case '2': HINT (2, 11);
+     case '3': HINT (3, 21);
+     case '4': HINT (4, 21);
+     case '5': HINT (8, 16);
+     case '6': HINT (5, 21);
+     case '7': REG (2, 11, ACC);
+     case '8': HINT (6, 11);
+     case '9': REG (2, 21, ACC);
+ 
+     case 'B': HINT (20, 6);
+     case 'C': HINT (25, 0);
+     case 'D': REG (5, 6, FP);
+     case 'E': REG (5, 16, COPRO);
+     case 'G': REG (5, 11, COPRO);
+     case 'H': UINT (3, 0);
+     case 'J': HINT (19, 6);
+     case 'K': REG (5, 11, HW);
+     case 'M': REG (3, 8, CCC);
+     case 'N': REG (3, 18, CCC);
+     case 'O': UINT (3, 21);
+     case 'P': SPECIAL (5, 1, PERF_REG);
+     case 'Q': SPECIAL (10, 16, MDMX_IMM_REG);
+     case 'R': REG (5, 21, FP);
+     case 'S': REG (5, 11, FP);
+     case 'T': REG (5, 16, FP);
+     case 'U': SPECIAL (10, 11, CLO_CLZ_DEST);
+     case 'V': REG (5, 11, FP);
+     case 'W': REG (5, 16, FP);
+     case 'X': REG (5, 6, VEC);
+     case 'Y': REG (5, 11, VEC);
+     case 'Z': REG (5, 16, VEC);
+ 
+     case 'a': JUMP (26, 0, 2);
+     case 'b': REG (5, 21, GP);
+     case 'c': HINT (10, 16);
+     case 'd': REG (5, 11, GP);
+     case 'e': UINT (3, 22)
+     case 'g': REG (5, 11, COPRO);
+     case 'h': HINT (5, 11);
+     case 'i': HINT (16, 0);
+     case 'j': SINT (16, 0);
+     case 'k': HINT (5, 16);
+     case 'o': SINT (16, 0);
+     case 'p': BRANCH (16, 0, 2);
+     case 'q': HINT (10, 6);
+     case 'r': REG (5, 21, GP);
+     case 's': REG (5, 21, GP);
+     case 't': REG (5, 16, GP);
+     case 'u': HINT (16, 0);
+     case 'v': REG (5, 21, GP);
+     case 'w': REG (5, 16, GP);
+     case 'x': REG (0, 0, GP);
+     case 'z': MAPPED_REG (0, 0, GP, reg_0_map);
+     }
+   return 0;
+ }
  
  /* Short hand so the lines aren't too long.  */
  
Index: opcodes/micromips-opc.c
===================================================================
*** opcodes/micromips-opc.c	2013-07-14 10:33:21.087809400 +0100
--- opcodes/micromips-opc.c	2013-07-14 10:35:55.849156274 +0100
***************
*** 20,27 ****
     MA 02110-1301, USA.  */
  
  #include "sysdep.h"
- #include <stdio.h>
  #include "opcode/mips.h"
  
  #define UBD	INSN_UNCOND_BRANCH_DELAY
  #define CBD	INSN_COND_BRANCH_DELAY
--- 20,174 ----
     MA 02110-1301, USA.  */
  
  #include "sysdep.h"
  #include "opcode/mips.h"
+ #include "mips-formats.h"
+ 
+ static unsigned char reg_0_map[] = { 0 };
+ static unsigned char reg_28_map[] = { 28 };
+ static unsigned char reg_29_map[] = { 29 };
+ static unsigned char reg_31_map[] = { 31 };
+ static unsigned char reg_m16_map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
+ static unsigned char reg_mn_map[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
+ static unsigned char reg_q_map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
+ 
+ static unsigned char reg_h_map1[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
+ static unsigned char reg_h_map2[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
+ 
+ static int int_b_map[] = {
+   1, 4, 8, 12, 16, 20, 24, -1
+ };
+ static int int_c_map[] = {
+   128, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 255, 32768, 65535
+ };
+ 
+ /* Return the mips_operand structure for the operand at the beginning of P.  */
+ 
+ const struct mips_operand *
+ decode_micromips_operand (const char *p)
+ {
+   switch (p[0])
+     {
+     case 'm':
+       switch (p[1])
+ 	{
+ 	case 'a': MAPPED_REG (0, 0, GP, reg_28_map);
+ 	case 'b': MAPPED_REG (3, 23, GP, reg_m16_map);
+ 	case 'c': MAPPED_REG (3, 4, GP, reg_m16_map);
+ 	case 'd': MAPPED_REG (3, 7, GP, reg_m16_map);
+ 	case 'e': MAPPED_REG (3, 1, GP, reg_m16_map);
+ 	case 'f': MAPPED_REG (3, 3, GP, reg_m16_map);
+ 	case 'g': MAPPED_REG (3, 0, GP, reg_m16_map);
+ 	case 'h': REG_PAIR (3, 7, GP, reg_h_map);
+ 	case 'j': REG (5, 0, GP);
+ 	case 'l': MAPPED_REG (3, 4, GP, reg_m16_map);
+ 	case 'm': MAPPED_REG (3, 1, GP, reg_mn_map);
+ 	case 'n': MAPPED_REG (3, 4, GP, reg_mn_map);
+ 	case 'p': REG (5, 5, GP);
+ 	case 'q': MAPPED_REG (3, 7, GP, reg_q_map);
+ 	case 'r': SPECIAL (0, 0, PC);
+ 	case 's': MAPPED_REG (0, 0, GP, reg_29_map);
+ 	case 't': SPECIAL (0, 0, REPEAT_PREV_REG);
+ 	case 'x': SPECIAL (0, 0, REPEAT_DEST_REG);
+ 	case 'y': MAPPED_REG (0, 0, GP, reg_31_map);
+ 	case 'z': MAPPED_REG (0, 0, GP, reg_0_map);
+ 
+ 	case 'A': INT_ADJ (7, 0, 63, 2, FALSE);	 /* (-64 .. 63) << 2 */
+ 	case 'B': MAPPED_INT (3, 1, int_b_map, FALSE);
+ 	case 'C': MAPPED_INT (4, 0, int_c_map, TRUE);
+ 	case 'D': BRANCH (10, 0, 1);
+ 	case 'E': BRANCH (7, 0, 1);
+ 	case 'F': HINT (4, 0);
+ 	case 'G': INT_ADJ (4, 0, 14, 0, FALSE);	 /* (-1 .. 14) */
+ 	case 'H': INT_ADJ (4, 0, 15, 1, FALSE);	 /* (0 .. 15) << 1 */
+ 	case 'I': INT_ADJ (7, 0, 126, 0, FALSE); /* (-1 .. 126) */
+ 	case 'J': INT_ADJ (4, 0, 15, 2, FALSE);	 /* (0 .. 15) << 2 */
+ 	case 'L': INT_ADJ (4, 0, 15, 0, FALSE);	 /* (0 .. 15) */
+ 	case 'M': INT_ADJ (3, 1, 8, 0, FALSE);   /* (1 .. 8) */
+ 	case 'N': SPECIAL (2, 4, LWM_SWM_LIST);
+ 	case 'O': HINT (4, 0);
+ 	case 'P': INT_ADJ (5, 0, 31, 2, FALSE);	 /* (0 .. 31) << 2 */
+ 	case 'Q': INT_ADJ (23, 0, 4194303, 2, FALSE);
+ 	  					 /* (-4194304 .. 4194303) */
+ 	case 'U': INT_ADJ (5, 0, 31, 2, FALSE);	 /* (0 .. 31) << 2 */
+ 	case 'W': INT_ADJ (6, 1, 63, 2, FALSE);	 /* (0 .. 63) << 2 */
+ 	case 'X': SINT (4, 1);
+ 	case 'Y': SPECIAL (9, 1, ADDIUSP_INT);
+ 	case 'Z': UINT (0, 0);			 /* 0 only */
+ 	}
+       break;
+ 
+     case '+':
+       switch (p[1])
+ 	{
+ 	case 'A': BIT (5, 6, 0);		 /* (0 .. 31) */
+ 	case 'B': MSB (5, 11, 1, TRUE, 32);	 /* (1 .. 32), 32-bit op */
+ 	case 'C': MSB (5, 11, 1, FALSE, 32);	 /* (1 .. 32), 32-bit op */
+ 	case 'E': BIT (5, 6, 32);		 /* (32 .. 63) */
+ 	case 'F': MSB (5, 11, 33, TRUE, 64);	 /* (33 .. 64), 64-bit op */
+ 	case 'G': MSB (5, 11, 33, FALSE, 64);	 /* (33 .. 64), 64-bit op */
+ 	case 'H': MSB (5, 11, 1, FALSE, 64);	 /* (1 .. 32), 64-bit op */
+ 
+ 	case 'i': JALX (26, 0, 2);
+ 	case 'j': SINT (9, 0);
+ 	}
+       break;
+ 
+     case '.': SINT (10, 6);
+     case '<': BIT (5, 11, 0);			 /* (0 .. 31) */
+     case '>': BIT (5, 11, 32);			 /* (32 .. 63) */
+     case '\\': BIT (3, 21, 0);			 /* (0 .. 7) */
+     case '|': HINT (4, 12);
+     case '~': SINT (12, 0);
+     case '@': SINT (10, 16);
+     case '^': HINT (5, 11);
+ 
+     case '0': SINT (6, 16);
+     case '1': HINT (5, 16);
+     case '2': HINT (2, 14);
+     case '3': HINT (3, 13);
+     case '4': HINT (4, 12);
+     case '5': HINT (8, 13);
+     case '6': HINT (5, 16);
+     case '7': REG (2, 14, ACC);
+     case '8': HINT (6, 14);
+ 
+     case 'B': HINT (10, 16);
+     case 'C': HINT (23, 3);
+     case 'D': REG (5, 11, FP);
+     case 'E': REG (5, 21, COPRO);
+     case 'G': REG (5, 16, COPRO);
+     case 'K': REG (5, 16, HW);
+     case 'H': UINT (3, 11);
+     case 'M': REG (3, 13, CCC);
+     case 'N': REG (3, 18, CCC);
+     case 'R': REG (5, 6, FP);
+     case 'S': REG (5, 16, FP);
+     case 'T': REG (5, 21, FP);
+     case 'V': REG (5, 16, FP);
+ 
+     case 'a': JUMP (26, 0, 1);
+     case 'b': REG (5, 16, GP);
+     case 'c': HINT (10, 16);
+     case 'd': REG (5, 11, GP);
+     case 'h': HINT (5, 11);
+     case 'i': HINT (16, 0);
+     case 'j': SINT (16, 0);
+     case 'k': HINT (5, 21);
+     case 'n': SPECIAL (5, 21, LWM_SWM_LIST);
+     case 'o': SINT (16, 0);
+     case 'p': BRANCH (16, 0, 1);
+     case 'q': HINT (10, 6);
+     case 'r': REG (5, 16, GP);
+     case 's': REG (5, 16, GP);
+     case 't': REG (5, 21, GP);
+     case 'u': HINT (16, 0);
+     case 'v': REG (5, 16, GP);
+     case 'w': REG (5, 21, GP);
+     case 'y': REG (5, 6, GP);
+     case 'z': MAPPED_REG (0, 0, GP, reg_0_map);
+     }
+   return 0;
+ }
  
  #define UBD	INSN_UNCOND_BRANCH_DELAY
  #define CBD	INSN_COND_BRANCH_DELAY
Index: opcodes/mips-dis.c
===================================================================
*** opcodes/mips-dis.c	2013-07-14 10:33:21.087809400 +0100
--- opcodes/mips-dis.c	2013-07-14 10:53:46.281482544 +0100
*************** static const unsigned int mips16_to_32_r
*** 57,145 ****
    16, 17, 2, 3, 4, 5, 6, 7
  };
  
- /* The microMIPS registers with type b.  */
- #define micromips_to_32_reg_b_map	mips16_to_32_reg_map
- 
- /* The microMIPS registers with type c.  */
- #define micromips_to_32_reg_c_map	mips16_to_32_reg_map
- 
- /* The microMIPS registers with type d.  */
- #define micromips_to_32_reg_d_map	mips16_to_32_reg_map
- 
- /* The microMIPS registers with type e.  */
- #define micromips_to_32_reg_e_map	mips16_to_32_reg_map
- 
- /* The microMIPS registers with type f.  */
- #define micromips_to_32_reg_f_map	mips16_to_32_reg_map
- 
- /* The microMIPS registers with type g.  */
- #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_map1[] =
- {
-   5, 5, 6, 4, 4, 4, 4, 4
- };
- static const unsigned int micromips_to_32_reg_h_map2[] =
- {
-   6, 7, 7, 21, 22, 5, 6, 7
- };
- 
- /* The microMIPS registers with type j: 32 registers.  */
- 
- /* The microMIPS registers with type l.  */
- #define micromips_to_32_reg_l_map	mips16_to_32_reg_map
- 
- /* The microMIPS registers with type m.  */
- static const unsigned int micromips_to_32_reg_m_map[] =
- {
-   0, 17, 2, 3, 16, 18, 19, 20
- };
- 
- /* The microMIPS registers with type n.  */
- #define micromips_to_32_reg_n_map      micromips_to_32_reg_m_map
- 
- /* The microMIPS registers with type p: 32 registers.  */
- 
- /* The microMIPS registers with type q.  */
- static const unsigned int micromips_to_32_reg_q_map[] =
- {
-   0, 17, 2, 3, 4, 5, 6, 7
- };
- 
- /* reg type s is $29.  */
- 
- /* reg type t is the same as the last register.  */
- 
- /* reg type y is $31.  */
- 
- /* reg type z is $0.  */
- 
- /* micromips imm B type.  */
- static const int micromips_imm_b_map[8] =
- {
-   1, 4, 8, 12, 16, 20, 24, -1
- };
- 
- /* micromips imm C type.  */
- static const int micromips_imm_c_map[16] =
- {
-   128, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 255, 32768, 65535
- };
- 
- /* micromips imm D type: (-512..511)<<1.  */
- /* micromips imm E type: (-64..63)<<1.  */
- /* micromips imm F type: (0..63).  */
- /* micromips imm G type: (-1..14).  */
- /* micromips imm H type: (0..15)<<1.  */
- /* micromips imm I type: (-1..126).  */
- /* micromips imm J type: (0..15)<<2.  */
- /* micromips imm L type: (0..15).  */
- /* micromips imm M type: (1..8).  */
- /* micromips imm W type: (0..63)<<2.  */
- /* micromips imm X type: (-8..7).  */
- /* micromips imm Y type: (-258..-3, 2..257)<<2.  */
- 
  #define mips16_reg_names(rn)	mips_gpr_names[mips16_to_32_reg_map[rn]]
  
  
--- 57,62 ----
*************** lookup_mips_cp0sel_name (const struct mi
*** 964,1439 ****
        return &names[i];
    return NULL;
  }
! 
! /* Print insn arguments for 32/64-bit code.  */
  
  static void
! print_insn_args (const char *d,
! 		 int l,
! 		 bfd_vma pc,
! 		 struct disassemble_info *info,
! 		 const struct mips_opcode *opp)
  {
!   const fprintf_ftype infprintf = info->fprintf_func;
!   unsigned int lsb, msb, msbd, cpreg;
!   void *is = info->stream;
! 
!   lsb = 0;
! 
! #define GET_OP(insn, field) \
!   (((insn) >> OP_SH_##field) & OP_MASK_##field)
! #define GET_OP_S(insn, field) \
!   ((GET_OP (insn, field) ^ ((OP_MASK_##field >> 1) + 1)) \
!    - ((OP_MASK_##field >> 1) + 1))
!   for (; *d != '\0'; d++)
      {
!       switch (*d)
! 	{
! 	case ',':
! 	case '(':
! 	case ')':
! 	  infprintf (is, "%c", *d);
! 	  break;
! 
! 	case '+':
! 	  /* Extension character; switch for second char.  */
! 	  d++;
! 	  switch (*d)
! 	    {
! 	    case '\0':
! 	      /* xgettext:c-format */
! 	      infprintf (is,
! 			 _("# internal error, "
! 			   "incomplete extension sequence (+)"));
! 	      return;
  
! 	    case 'A':
! 	      lsb = GET_OP (l, SHAMT);
! 	      infprintf (is, "0x%x", lsb);
! 	      break;
! 	
! 	    case 'B':
! 	      msb = GET_OP (l, INSMSB);
! 	      infprintf (is, "0x%x", msb - lsb + 1);
! 	      break;
! 
! 	    case '1':
! 	      infprintf (is, "0x%x", GET_OP (l, UDI1));
! 	      break;
! 	      
! 	    case '2':
! 	      infprintf (is, "0x%x", GET_OP (l, UDI2));
! 	      break;
! 	      
! 	    case '3':
! 	      infprintf (is, "0x%x", GET_OP (l, UDI3));
! 	      break;
!       
! 	    case '4':
! 	      infprintf (is, "0x%x", GET_OP (l, UDI4));
! 	      break;
! 	      
! 	    case 'C':
! 	    case 'H':
! 	      msbd = GET_OP (l, EXTMSBD);
! 	      infprintf (is, "0x%x", msbd + 1);
! 	      break;
! 
! 	    case 'E':
! 	      lsb = GET_OP (l, SHAMT) + 32;
! 	      infprintf (is, "0x%x", lsb);
! 	      break;
! 	
! 	    case 'F':
! 	      msb = GET_OP (l, INSMSB) + 32;
! 	      infprintf (is, "0x%x", msb - lsb + 1);
! 	      break;
! 
! 	    case 'G':
! 	      msbd = GET_OP (l, EXTMSBD) + 32;
! 	      infprintf (is, "0x%x", msbd + 1);
! 	      break;
! 
! 	    case 'J':		/* hypcall operand */
! 	      infprintf (is, "0x%x", GET_OP (l, CODE10));
! 	      break;
! 
! 	    case 't': /* Coprocessor 0 reg name */
! 	      infprintf (is, "%s", mips_cp0_names[GET_OP (l, RT)]);
! 	      break;
! 
! 	    case 'x':		/* bbit bit index */
! 	      infprintf (is, "0x%x", GET_OP (l, BBITIND));
! 	      break;
! 
! 	    case 'p':		/* cins, cins32, exts and exts32 position */
! 	      infprintf (is, "0x%x", GET_OP (l, CINSPOS));
! 	      break;
! 
! 	    case 's':		/* cins32 and exts32 length-minus-one */
! 	    case 'S':		/* cins and exts length-minus-one field */
! 	      infprintf (is, "0x%x", GET_OP (l, CINSLM1));
! 	      break;
! 
! 	    case 'Q':		/* seqi/snei immediate field */
! 	      infprintf (is, "%d", GET_OP_S (l, SEQI));
! 	      break;
! 
! 	    case 'a':		/* 8-bit signed offset in bit 6 */
! 	      infprintf (is, "%d", GET_OP_S (l, OFFSET_A));
! 	      break;
! 
! 	    case 'b':		/* 8-bit signed offset in bit 3 */
! 	      infprintf (is, "%d", GET_OP_S (l, OFFSET_B));
! 	      break;
! 
! 	    case 'c':		/* 9-bit signed offset in bit 6 */
! 	      /* Left shift 4 bits to print the real offset.  */
! 	      infprintf (is, "%d", GET_OP_S (l, OFFSET_C) << 4);
! 	      break;
! 
! 	    case 'z':
! 	      infprintf (is, "%s", mips_gpr_names[GET_OP (l, RZ)]);
! 	      break;
! 
! 	    case 'Z':
! 	      infprintf (is, "%s", mips_fpr_names[GET_OP (l, FZ)]);
! 	      break;
! 
! 	    case 'i': /* JALX destination */
! 	      info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
! 			      | (GET_OP (l, TARGET) << 2));
! 	      /* For gdb disassembler, force odd address on jalx.  */
! 	      if (info->flavour == bfd_target_unknown_flavour)
! 		info->target |= 1;
! 	      (*info->print_address_func) (info->target, info);
! 	      break;
! 
! 	    case 'j':	/* 9-bit signed offset in bit 7.  */
! 	      infprintf (is, "%d", GET_OP_S (l, EVAOFFSET));
! 	      break;
  
! 	    default:
! 	      /* xgettext:c-format */
! 	      infprintf (is,
! 			 _("# internal error, "
! 			   "undefined extension sequence (+%c)"),
! 			 *d);
! 	      return;
! 	    }
! 	  break;
  
! 	case '2':
! 	  infprintf (is, "0x%x", GET_OP (l, BP));
! 	  break;
  
! 	case '3':
! 	  infprintf (is, "0x%x", GET_OP (l, SA3));
! 	  break;
  
! 	case '4':
! 	  infprintf (is, "0x%x", GET_OP (l, SA4));
! 	  break;
  
! 	case '5':
! 	  infprintf (is, "0x%x", GET_OP (l, IMM8));
! 	  break;
  
! 	case '6':
! 	  infprintf (is, "0x%x", GET_OP (l, RS));
! 	  break;
  
! 	case '7':
! 	  infprintf (is, "$ac%d", GET_OP (l, DSPACC));
! 	  break;
  
! 	case '8':
! 	  infprintf (is, "0x%x", GET_OP (l, WRDSP));
! 	  break;
  
! 	case '9':
! 	  infprintf (is, "$ac%d", GET_OP (l, DSPACC_S));
! 	  break;
  
! 	case '0': /* dsp 6-bit signed immediate in bit 20 */
! 	  infprintf (is, "%d", GET_OP_S (l, DSPSFT));
! 	  break;
  
! 	case ':': /* dsp 7-bit signed immediate in bit 19 */
! 	  infprintf (is, "%d", GET_OP_S (l, DSPSFT_7));
! 	  break;
  
! 	case '~':
! 	  infprintf (is, "%d", GET_OP_S (l, OFFSET12));
! 	  break;
  
! 	case '\\':
! 	  infprintf (is, "0x%x", GET_OP (l, 3BITPOS));
! 	  break;
  
! 	case '\'':
! 	  infprintf (is, "0x%x", GET_OP (l, RDDSP));
! 	  break;
  
! 	case '@': /* dsp 10-bit signed immediate in bit 16 */
! 	  infprintf (is, "%d", GET_OP_S (l, IMM10));
! 	  break;
  
! 	case '!':
! 	  infprintf (is, "%d", GET_OP (l, MT_U));
! 	  break;
  
! 	case '$':
! 	  infprintf (is, "%d", GET_OP (l, MT_H));
! 	  break;
  
! 	case '*':
! 	  infprintf (is, "$ac%d", GET_OP (l, MTACC_T));
! 	  break;
  
! 	case '&':
! 	  infprintf (is, "$ac%d", GET_OP (l, MTACC_D));
! 	  break;
  
! 	case 'g':
! 	  /* Coprocessor register for CTTC1, MTTC2, MTHC2, CTTC2.  */
! 	  infprintf (is, "$%d", GET_OP (l, RD));
! 	  break;
  
! 	case 's':
! 	case 'b':
! 	case 'r':
! 	case 'v':
! 	  infprintf (is, "%s", mips_gpr_names[GET_OP (l, RS)]);
! 	  break;
  
! 	case 't':
! 	case 'w':
! 	  infprintf (is, "%s", mips_gpr_names[GET_OP (l, RT)]);
! 	  break;
  
! 	case 'i':
! 	case 'u':
! 	  infprintf (is, "0x%x", GET_OP (l, IMMEDIATE));
! 	  break;
  
! 	case 'j': /* Same as i, but sign-extended.  */
! 	case 'o':
! 	  infprintf (is, "%d", GET_OP_S (l, DELTA));
! 	  break;
  
! 	case 'h':
! 	  infprintf (is, "0x%x", GET_OP (l, PREFX));
! 	  break;
  
! 	case 'k':
! 	  infprintf (is, "0x%x", GET_OP (l, CACHE));
! 	  break;
  
! 	case 'a':
! 	  info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
! 			  | (GET_OP (l, TARGET) << 2));
! 	  (*info->print_address_func) (info->target, info);
! 	  break;
  
! 	case 'p':
! 	  /* Sign extend the displacement.  */
! 	  info->target = (GET_OP_S (l, DELTA) << 2) + pc + INSNLEN;
! 	  (*info->print_address_func) (info->target, info);
! 	  break;
  
! 	case 'd':
! 	  infprintf (is, "%s", mips_gpr_names[GET_OP (l, RD)]);
! 	  break;
  
! 	case 'U':
! 	  {
! 	    /* First check for both rd and rt being equal.  */
! 	    unsigned int reg;
  
! 	    reg = GET_OP (l, RD);
! 	    if (reg == GET_OP (l, RT))
! 	      infprintf (is, "%s", mips_gpr_names[reg]);
! 	    else
! 	      {
! 		/* If one is zero use the other.  */
! 		if (reg == 0)
! 		  infprintf (is, "%s", mips_gpr_names[GET_OP (l, RT)]);
! 		else if (GET_OP (l, RT) == 0)
! 		  infprintf (is, "%s", mips_gpr_names[reg]);
! 		else /* Bogus, result depends on processor.  */
! 		  infprintf (is, "%s or %s",
! 			     mips_gpr_names[reg],
! 			     mips_gpr_names[GET_OP (l, RT)]);
! 	      }
! 	  }
! 	  break;
  
! 	case 'z':
! 	  infprintf (is, "%s", mips_gpr_names[0]);
! 	  break;
  
! 	case '<':
! 	case '1':
! 	  infprintf (is, "0x%x", GET_OP (l, SHAMT));
! 	  break;
  
! 	case 'c':
! 	  infprintf (is, "0x%x", GET_OP (l, CODE));
! 	  break;
  
! 	case 'q':
! 	  infprintf (is, "0x%x", GET_OP (l, CODE2));
! 	  break;
  
! 	case 'C':
! 	  infprintf (is, "0x%x", GET_OP (l, COPZ));
! 	  break;
  
! 	case 'B':
! 	  infprintf (is, "0x%x", GET_OP (l, CODE20));
! 	  break;
  
! 	case 'J':
! 	  infprintf (is, "0x%x", GET_OP (l, CODE19));
! 	  break;
  
! 	case 'S':
! 	case 'V':
! 	  infprintf (is, "%s", mips_fpr_names[GET_OP (l, FS)]);
! 	  break;
  
! 	case 'T':
! 	case 'W':
! 	  infprintf (is, "%s", mips_fpr_names[GET_OP (l, FT)]);
! 	  break;
  
! 	case 'D':
! 	  infprintf (is, "%s", mips_fpr_names[GET_OP (l, FD)]);
! 	  break;
  
! 	case 'R':
! 	  infprintf (is, "%s", mips_fpr_names[GET_OP (l, FR)]);
  	  break;
  
! 	case 'E':
! 	  cpreg = GET_OP (l, RT);
! 	  goto copro;
! 
! 	case 'G':
! 	  cpreg = GET_OP (l, RD);
! 	copro:
! 	  /* Coprocessor register for mtcN instructions, et al.  Note
! 	     that FPU (cp1) instructions disassemble this field using
! 	     'S' format.  Therefore, we only need to worry about cp0,
! 	     cp2, and cp3.  */
! 	  if (opp->name[strlen (opp->name) - 1] == '0')
  	    {
! 	      if (d[1] == ',' && d[2] == 'H')
! 		{
! 		  const struct mips_cp0sel_name *n;
! 		  unsigned int sel;
! 
! 		  sel = GET_OP (l, SEL);
! 
! 		  /* CP0 register including 'sel' code for mtcN (et al.), to be
! 		     printed textually if known.  If not known, print both
! 		     CP0 register name and sel numerically since CP0 register
! 		     with sel 0 may have a name unrelated to register being
! 		     printed.  */
! 		  n = lookup_mips_cp0sel_name (mips_cp0sel_names,
! 					       mips_cp0sel_names_len,
! 					       cpreg, sel);
! 		  if (n != NULL)
! 		    infprintf (is, "%s", n->name);
! 		  else
! 		    infprintf (is, "$%d,%d", cpreg, sel);
! 		  d += 2;
! 		}
  	      else
! 		infprintf (is, "%s", mips_cp0_names[cpreg]);
  	    }
  	  else
! 	    infprintf (is, "$%d", cpreg);
! 	  break;
! 
! 	case 'K':
! 	  infprintf (is, "%s", mips_hwr_names[GET_OP (l, RD)]);
! 	  break;
! 
! 	case 'N':
! 	  infprintf (is,
! 		     (opp->pinfo & (FP_D | FP_S)) != 0 ? "$fcc%d" : "$cc%d",
! 		     GET_OP (l, BCC));
! 	  break;
! 
! 	case 'M':
! 	  infprintf (is, "$fcc%d", GET_OP (l, CCC));
! 	  break;
! 
! 	case 'P':
! 	  infprintf (is, "%d", GET_OP (l, PERFREG));
! 	  break;
! 
! 	case 'e':
! 	  infprintf (is, "%d", GET_OP (l, VECBYTE));
! 	  break;
! 
! 	case '%':
! 	  infprintf (is, "%d", GET_OP (l, VECALIGN));
! 	  break;
! 
! 	case 'H':
! 	  infprintf (is, "%d", GET_OP (l, SEL));
! 	  break;
! 
! 	case 'O':
! 	  infprintf (is, "%d", GET_OP (l, ALN));
! 	  break;
! 
! 	case 'Q':
! 	  {
! 	    unsigned int vsel = GET_OP (l, VSEL);
! 	    char prefix;
! 
! 	    prefix = opp->membership & INSN_5400 ? 'f' : 'v';
! 	    if ((vsel & 0x10) == 0)
! 	      {
! 		int fmt;
! 
! 		vsel &= 0x0f;
! 		for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
! 		  if ((vsel & 1) == 0)
! 		    break;
! 		infprintf (is, "$%c%d[%d]", prefix, GET_OP (l, FT), vsel >> 1);
! 	      }
! 	    else if ((vsel & 0x08) == 0)
! 	      {
! 		infprintf (is, "$%c%d", prefix, GET_OP (l, FT));
! 	      }
! 	    else
! 	      {
! 		infprintf (is, "0x%x", GET_OP (l, FT));
! 	      }
! 	  }
! 	  break;
! 
! 	case 'X':
! 	  infprintf (is, "$v%d", GET_OP (l, FD));
  	  break;
- 
- 	case 'Y':
- 	  infprintf (is, "$v%d", GET_OP (l, FS));
- 	  break;
- 
- 	case 'Z':
- 	  infprintf (is, "$v%d", GET_OP (l, FT));
- 	  break;
- 
- 	default:
- 	  /* xgettext:c-format */
- 	  infprintf (is, _("# internal error, undefined modifier (%c)"), *d);
- 	  return;
  	}
      }
  }
--- 881,1241 ----
        return &names[i];
    return NULL;
  }
! 
! /* Print register REGNO, of type TYPE, for instruction OPCODE.  */
  
  static void
! print_reg (struct disassemble_info *info, const struct mips_opcode *opcode,
! 	   enum mips_reg_operand_type type, int regno)
  {
!   switch (type)
      {
!     case OP_REG_GP:
!       info->fprintf_func (info->stream, "%s", mips_gpr_names[regno]);
!       break;
  
!     case OP_REG_FP:
!       info->fprintf_func (info->stream, "%s", mips_fpr_names[regno]);
!       break;
  
!     case OP_REG_CCC:
!       if (opcode->pinfo & (FP_D | FP_S))
! 	info->fprintf_func (info->stream, "$fcc%d", regno);
!       else
! 	info->fprintf_func (info->stream, "$cc%d", regno);
!       break;
  
!     case OP_REG_VEC:
!       if (opcode->membership & INSN_5400)
! 	info->fprintf_func (info->stream, "$f%d", regno);
!       else
! 	info->fprintf_func (info->stream, "$v%d", regno);
!       break;
  
!     case OP_REG_ACC:
!       info->fprintf_func (info->stream, "$ac%d", regno);
!       break;
  
!     case OP_REG_COPRO:
!       if (opcode->name[strlen (opcode->name) - 1] == '0')
! 	info->fprintf_func (info->stream, "%s", mips_cp0_names[regno]);
!       else
! 	info->fprintf_func (info->stream, "$%d", regno);
!       break;
  
!     case OP_REG_HW:
!       info->fprintf_func (info->stream, "%s", mips_hwr_names[regno]);
!       break;
!     }
! }
! 
! /* Used to track the state carried over from previous operands in
!    an instruction.  */
! struct mips_print_arg_state {
!   /* The value of the last OP_INT seen.  We only use this for OP_MSB,
!      where the value is known to be unsigned and small.  */
!   unsigned int last_int;
  
!   /* The type and number of the last OP_REG seen.  We only use this for
!      OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG.  */
!   enum mips_reg_operand_type last_reg_type;
!   unsigned int last_regno;
! };
  
! /* Initialize STATE for the start of an instruction.  */
  
! static inline void
! init_print_arg_state (struct mips_print_arg_state *state)
! {
!   memset (state, 0, sizeof (*state));
! }
  
! /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
!    UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
!    the base address for OP_PCREL operands.  */
  
! static void
! print_insn_arg (struct disassemble_info *info,
! 		struct mips_print_arg_state *state,
! 		const struct mips_opcode *opcode,
! 		const struct mips_operand *operand,
! 		bfd_vma base_pc,
! 		unsigned int uval)
! {
!   const fprintf_ftype infprintf = info->fprintf_func;
!   void *is = info->stream;
  
!   switch (operand->type)
!     {
!     case OP_INT:
!       {
! 	const struct mips_int_operand *int_op;
  
! 	int_op = (const struct mips_int_operand *) operand;
! 	uval = mips_decode_int_operand (int_op, uval);
! 	state->last_int = uval;
! 	if (int_op->print_hex)
! 	  infprintf (is, "0x%x", uval);
! 	else
! 	  infprintf (is, "%d", uval);
!       }
!       break;
  
!     case OP_MAPPED_INT:
!       {
! 	const struct mips_mapped_int_operand *mint_op;
  
! 	mint_op = (const struct mips_mapped_int_operand *) operand;
! 	uval = mint_op->int_map[uval];
! 	state->last_int = uval;
! 	if (mint_op->print_hex)
! 	  infprintf (is, "0x%x", uval);
! 	else
! 	  infprintf (is, "%d", uval);
!       }
!       break;
  
!     case OP_MSB:
!       {
! 	const struct mips_msb_operand *msb_op;
  
! 	msb_op = (const struct mips_msb_operand *) operand;
! 	uval += msb_op->bias;
! 	if (msb_op->add_lsb)
! 	  uval -= state->last_int;
! 	infprintf (is, "0x%x", uval);
!       }
!       break;
  
!     case OP_REG:
!       {
! 	const struct mips_reg_operand *reg_op;
  
! 	reg_op = (const struct mips_reg_operand *) operand;
! 	if (reg_op->reg_map)
! 	  uval = reg_op->reg_map[uval];
! 	print_reg (info, opcode, reg_op->reg_type, uval);
  
! 	state->last_reg_type = reg_op->reg_type;
! 	state->last_regno = uval;
!       }
!       break;
  
!     case OP_REG_PAIR:
!       {
! 	const struct mips_reg_pair_operand *pair_op;
  
! 	pair_op = (const struct mips_reg_pair_operand *) operand;
! 	print_reg (info, opcode, pair_op->reg_type,
! 		   pair_op->reg1_map[uval]);
! 	infprintf (is, ",");
! 	print_reg (info, opcode, pair_op->reg_type,
! 		   pair_op->reg2_map[uval]);
!       }
!       break;
  
!     case OP_PCREL:
!       {
! 	const struct mips_pcrel_operand *pcrel_op;
  
! 	pcrel_op = (const struct mips_pcrel_operand *) operand;
! 	info->target = mips_decode_pcrel_operand (pcrel_op, base_pc, uval);
  
! 	/* Preserve the ISA bit for the GDB disassembler,
! 	   otherwise clear it.  */
! 	if (info->flavour != bfd_target_unknown_flavour)
! 	  info->target &= -2;
  
! 	(*info->print_address_func) (info->target, info);
!       }
!       break;
  
!     case OP_PERF_REG:
!       infprintf (is, "%d", uval);
!       break;
  
!     case OP_ADDIUSP_INT:
!       {
! 	int sval;
  
! 	sval = mips_signed_operand (operand, uval) * 4;
! 	if (sval >= -8 && sval < 8)
! 	  sval ^= 0x400;
! 	infprintf (is, "%d", sval);
! 	break;
!       }
  
!     case OP_CLO_CLZ_DEST:
!       {
! 	unsigned int reg1, reg2;
  
! 	reg1 = uval & 31;
! 	reg2 = uval >> 5;
! 	/* If one is zero use the other.  */
! 	if (reg1 == reg2 || reg2 == 0)
! 	  infprintf (is, "%s", mips_gpr_names[reg1]);
! 	else if (reg1 == 0)
! 	  infprintf (is, "%s", mips_gpr_names[reg2]);
! 	else
! 	  /* Bogus, result depends on processor.  */
! 	  infprintf (is, "%s or %s", mips_gpr_names[reg1],
! 		     mips_gpr_names[reg2]);
!       }
!       break;
  
!     case OP_LWM_SWM_LIST:
!       if (operand->size == 2)
! 	{
! 	  if (uval == 0)
! 	    infprintf (is, "%s,%s",
! 		       mips_gpr_names[16],
! 		       mips_gpr_names[31]);
! 	  else
! 	    infprintf (is, "%s-%s,%s",
! 		       mips_gpr_names[16],
! 		       mips_gpr_names[16 + uval],
! 		       mips_gpr_names[31]);
! 	}
!       else
! 	{
! 	  int s_reg_encode;
  
! 	  s_reg_encode = uval & 0xf;
! 	  if (s_reg_encode != 0)
! 	    {
! 	      if (s_reg_encode == 1)
! 		infprintf (is, "%s", mips_gpr_names[16]);
! 	      else if (s_reg_encode < 9)
! 		infprintf (is, "%s-%s",
! 			   mips_gpr_names[16],
! 			   mips_gpr_names[15 + s_reg_encode]);
! 	      else if (s_reg_encode == 9)
! 		infprintf (is, "%s-%s,%s",
! 			   mips_gpr_names[16],
! 			   mips_gpr_names[23],
! 			   mips_gpr_names[30]);
! 	      else
! 		infprintf (is, "UNKNOWN");
! 	    }
  
! 	  if (uval & 0x10) /* For ra.  */
! 	    {
! 	      if (s_reg_encode == 0)
! 		infprintf (is, "%s", mips_gpr_names[31]);
! 	      else
! 		infprintf (is, ",%s", mips_gpr_names[31]);
! 	    }
! 	}
!       break;
  
!     case OP_MDMX_IMM_REG:
!       {
! 	unsigned int vsel;
  
! 	vsel = uval >> 5;
! 	uval &= 31;
! 	if ((vsel & 0x10) == 0)
! 	  {
! 	    int fmt;
  
! 	    vsel &= 0x0f;
! 	    for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
! 	      if ((vsel & 1) == 0)
! 		break;
! 	    print_reg (info, opcode, OP_REG_VEC, uval);
! 	    infprintf (is, "[%d]", vsel >> 1);
! 	  }
! 	else if ((vsel & 0x08) == 0)
! 	  print_reg (info, opcode, OP_REG_VEC, uval);
! 	else
! 	  infprintf (is, "0x%x", uval);
!       }
!       break;
  
!     case OP_REPEAT_PREV_REG:
!       print_reg (info, opcode, state->last_reg_type, state->last_regno);
!       break;
  
!     case OP_REPEAT_DEST_REG:
!       /* Should always match OP_REPEAT_PREV_REG first.  */
!       abort ();
  
!     case OP_PC:
!       infprintf (is, "$pc");
!       break;
!     }
! }
  
! /* Print the arguments for INSN, which is described by OPCODE.
!    Use DECODE_OPERAND to get the encoding of each operand.  Use BASE_PC
!    as the base of OP_PCREL operands.  */
  
! static void
! print_insn_args (struct disassemble_info *info,
! 		 const struct mips_opcode *opcode,
! 		 const struct mips_operand *(*decode_operand) (const char *),
! 		 unsigned int insn, bfd_vma base_pc)
! {
!   const fprintf_ftype infprintf = info->fprintf_func;
!   void *is = info->stream;
!   struct mips_print_arg_state state;
!   const struct mips_operand *operand;
!   const char *s;
  
!   init_print_arg_state (&state);
!   for (s = opcode->args; *s; ++s)
!     {
!       switch (*s)
! 	{
! 	case ',':
! 	case '(':
! 	case ')':
! 	  infprintf (is, "%c", *s);
  	  break;
  
! 	default:
! 	  operand = decode_operand (s);
! 	  if (!operand)
  	    {
! 	      /* xgettext:c-format */
! 	      infprintf (is,
! 			 _("# internal error, undefined operand in `%s %s'"),
! 			 opcode->name, opcode->args);
! 	      return;
! 	    }
! 	  if (operand->type == OP_REG
! 	      && s[1] == ','
! 	      && s[2] == 'H'
! 	      && opcode->name[strlen (opcode->name) - 1] == '0')
! 	    {
! 	      /* Coprocessor register 0 with sel field (MT ASE).  */
! 	      const struct mips_cp0sel_name *n;
! 	      unsigned int reg, sel;
! 
! 	      reg = mips_extract_operand (operand, insn);
! 	      s += 2;
! 	      operand = decode_operand (s);
! 	      sel = mips_extract_operand (operand, insn);
! 
! 	      /* CP0 register including 'sel' code for mftc0, to be
! 		 printed textually if known.  If not known, print both
! 		 CP0 register name and sel numerically since CP0 register
! 		 with sel 0 may have a name unrelated to register being
! 		 printed.  */
! 	      n = lookup_mips_cp0sel_name (mips_cp0sel_names,
! 					   mips_cp0sel_names_len,
! 					   reg, sel);
! 	      if (n != NULL)
! 		infprintf (is, "%s", n->name);
  	      else
! 		infprintf (is, "$%d,%d", reg, sel);
  	    }
  	  else
! 	    print_insn_arg (info, &state, opcode, operand, base_pc,
! 			    mips_extract_operand (operand, insn));
! 	  if (*s == 'm' || *s == '+')
! 	    ++s;
  	  break;
  	}
      }
  }
*************** print_insn_mips (bfd_vma memaddr,
*** 1448,1453 ****
--- 1250,1257 ----
  		 int word,
  		 struct disassemble_info *info)
  {
+ #define GET_OP(insn, field)			\
+   (((insn) >> OP_SH_##field) & OP_MASK_##field)
    static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
    const fprintf_ftype infprintf = info->fprintf_func;
    const struct mips_opcode *op;
*************** print_insn_mips (bfd_vma memaddr,
*** 1495,1502 ****
  	      && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
  	      && (word & op->mask) == op->match)
  	    {
- 	      const char *d;
- 
  	      /* We always allow to disassemble the jalx instruction.  */
  	      if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
  		  && strcmp (op->name, "jalx"))
--- 1299,1304 ----
*************** print_insn_mips (bfd_vma memaddr,
*** 1527,1544 ****
  
  	      infprintf (is, "%s", op->name);
  
! 	      d = op->args;
! 	      if (d != NULL && *d != '\0')
  		{
  		  infprintf (is, "\t");
! 		  print_insn_args (d, word, memaddr, info, op);
  		}
  
  	      return INSNLEN;
  	    }
  	}
      }
- #undef GET_OP_S
  #undef GET_OP
  
    /* Handle undefined instructions.  */
--- 1329,1345 ----
  
  	      infprintf (is, "%s", op->name);
  
! 	      if (op->args[0])
  		{
  		  infprintf (is, "\t");
! 		  print_insn_args (info, op, decode_mips_operand, word,
! 				   memaddr + 4);
  		}
  
  	      return INSNLEN;
  	    }
  	}
      }
  #undef GET_OP
  
    /* Handle undefined instructions.  */
*************** print_insn_micromips (bfd_vma memaddr, s
*** 2235,2253 ****
  {
    const fprintf_ftype infprintf = info->fprintf_func;
    const struct mips_opcode *op, *opend;
-   unsigned int lsb, msbd, msb;
    void *is = info->stream;
-   unsigned int regno;
    bfd_byte buffer[2];
!   int lastregno = 0;
!   int higher;
!   int length;
    int status;
!   int delta;
!   int immed;
!   int insn;
! 
!   lsb = 0;
  
    info->bytes_per_chunk = 2;
    info->display_endian = info->endian;
--- 2036,2047 ----
  {
    const fprintf_ftype infprintf = info->fprintf_func;
    const struct mips_opcode *op, *opend;
    void *is = info->stream;
    bfd_byte buffer[2];
!   unsigned int higher;
!   unsigned int length;
    int status;
!   unsigned int insn;
  
    info->bytes_per_chunk = 2;
    info->display_endian = info->endian;
*************** print_insn_micromips (bfd_vma memaddr, s
*** 2331,2341 ****
  
    /* FIXME: Should probably use a hash table on the major opcode here.  */
  
- #define GET_OP(insn, field) \
-   (((insn) >> MICROMIPSOP_SH_##field) & MICROMIPSOP_MASK_##field)
- #define GET_OP_S(insn, field) \
-   ((GET_OP (insn, field) ^ ((MICROMIPSOP_MASK_##field >> 1) + 1)) \
-    - ((MICROMIPSOP_MASK_##field >> 1) + 1))
    opend = micromips_opcodes + bfd_micromips_num_opcodes;
    for (op = micromips_opcodes; op < opend; op++)
      {
--- 2125,2130 ----
*************** #define GET_OP_S(insn, field) \
*** 2345,2913 ****
  	  && ((length == 2 && (op->mask & 0xffff0000) == 0)
  	      || (length == 4 && (op->mask & 0xffff0000) != 0)))
  	{
- 	  const char *s;
- 
  	  infprintf (is, "%s", op->name);
- 	  if (op->args[0] != '\0')
- 	    infprintf (is, "\t");
  
! 	  for (s = op->args; *s != '\0'; s++)
  	    {
! 	      switch (*s)
! 		{
! 		case ',':
! 		case '(':
! 		case ')':
! 		  infprintf (is, "%c", *s);
! 		  break;
! 
! 		case '.':
! 		  infprintf (is, "%d", GET_OP_S (insn, OFFSET10));
! 		  break;
! 
! 		case '1':
! 		  infprintf (is, "0x%x", GET_OP (insn, STYPE));
! 		  break;
! 
! 		case '2':
! 		  infprintf (is, "0x%x", GET_OP (insn, BP));
! 		  break;
! 
! 		case '3':
! 		  infprintf (is, "0x%x", GET_OP (insn, SA3));
! 		  break;
! 
! 		case '4':
! 		  infprintf (is, "0x%x", GET_OP (insn, SA4));
! 		  break;
! 
! 		case '5':
! 		  infprintf (is, "0x%x", GET_OP (insn, IMM8));
! 		  break;
! 
! 		case '6':
! 		  infprintf (is, "0x%x", GET_OP (insn, RS));
! 		  break;
! 
! 		case '7':
! 		  infprintf (is, "$ac%d", GET_OP (insn, DSPACC));
! 		  break;
! 
! 		case '8':
! 		  infprintf (is, "0x%x", GET_OP (insn, WRDSP));
! 		  break;
! 
! 		case '0': /* DSP 6-bit signed immediate in bit 16.  */
! 		  delta = (GET_OP (insn, DSPSFT) ^ 0x20) - 0x20;
! 		  infprintf (is, "%d", delta);
! 		  break;
! 
! 		case '<':
! 		  infprintf (is, "0x%x", GET_OP (insn, SHAMT));
! 		  break;
! 
! 		case '\\':
! 		  infprintf (is, "0x%x", GET_OP (insn, 3BITPOS));
! 		  break;
! 
! 		case '^':
! 		  infprintf (is, "0x%x", GET_OP (insn, RD));
! 		  break;
! 
! 		case '|':
! 		  infprintf (is, "0x%x", GET_OP (insn, TRAP));
! 		  break;
! 
! 		case '~':
! 		  infprintf (is, "%d", GET_OP_S (insn, OFFSET12));
! 		  break;
! 
! 		case 'a':
! 		  info->target = (((memaddr + 4) & ~(bfd_vma) 0x07ffffff)
! 				  | (GET_OP (insn, TARGET) << 1));
! 		  /* For gdb disassembler, maintain odd address.  */
! 		  if (info->flavour == bfd_target_unknown_flavour)
! 		    info->target |= 1;
! 		  (*info->print_address_func) (info->target, info);
! 		  break;
! 
! 		case 'b':
! 		case 'r':
! 		case 's':
! 		case 'v':
! 		  infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RS)]);
! 		  break;
! 
! 		case 'c':
! 		  infprintf (is, "0x%x", GET_OP (insn, CODE));
! 		  break;
! 
! 		case 'd':
! 		  infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RD)]);
! 		  break;
! 
! 		case 'h':
! 		  infprintf (is, "0x%x", GET_OP (insn, PREFX));
! 		  break;
! 
! 		case 'i':
! 		case 'u':
! 		  infprintf (is, "0x%x", GET_OP (insn, IMMEDIATE));
! 		  break;
! 
! 		case 'j': /* Same as i, but sign-extended.  */
! 		case 'o':
! 		  infprintf (is, "%d", GET_OP_S (insn, DELTA));
! 		  break;
! 
! 		case 'k':
! 		  infprintf (is, "0x%x", GET_OP (insn, CACHE));
! 		  break;
! 
! 		case 'n':
! 		  {
! 		    int s_reg_encode;
! 
! 		    immed = GET_OP (insn, RT);
! 		    s_reg_encode = immed & 0xf;
! 		    if (s_reg_encode != 0)
! 		      {
! 			if (s_reg_encode == 1)
! 			  infprintf (is, "%s", mips_gpr_names[16]);
! 			else if (s_reg_encode < 9)
! 			  infprintf (is, "%s-%s",
! 				   mips_gpr_names[16],
! 				   mips_gpr_names[15 + s_reg_encode]);
! 			else if (s_reg_encode == 9)
! 			  infprintf (is, "%s-%s,%s",
! 				   mips_gpr_names[16],
! 				   mips_gpr_names[23],
! 				   mips_gpr_names[30]);
! 			else
! 			  infprintf (is, "UNKNOWN");
! 		      }
! 
! 		    if (immed & 0x10) /* For ra.  */
! 		      {
! 			if (s_reg_encode == 0)
! 			  infprintf (is, "%s", mips_gpr_names[31]);
! 			else
! 			  infprintf (is, ",%s", mips_gpr_names[31]);
! 		      }
! 		    break;
! 		  }
! 
! 		case 'p':
! 		  /* Sign-extend the displacement.  */
! 		  delta = GET_OP_S (insn, DELTA);
! 		  info->target = (delta << 1) + memaddr + length;
! 		  (*info->print_address_func) (info->target, info);
! 		  break;
! 
! 		case 'q':
! 		  infprintf (is, "0x%x", GET_OP (insn, CODE2));
! 		  break;
! 
! 		case 't':
! 		case 'w':
! 		  infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RT)]);
! 		  break;
! 
! 		case 'y':
! 		  infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RS3)]);
! 		  break;
! 
! 		case 'z':
! 		  infprintf (is, "%s", mips_gpr_names[0]);
! 		  break;
! 
! 		case '@': /* DSP 10-bit signed immediate in bit 16.  */
! 		  delta = (GET_OP (insn, IMM10) ^ 0x200) - 0x200;
! 		  infprintf (is, "%d", delta);
! 		  break;
! 
! 		case 'B':
! 		  infprintf (is, "0x%x", GET_OP (insn, CODE10));
! 		  break;
! 
! 		case 'C':
! 		  infprintf (is, "0x%x", GET_OP (insn, COPZ));
! 		  break;
! 
! 		case 'D':
! 		  infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FD)]);
! 		  break;
! 
! 		case 'E':
! 		  /* Coprocessor register for lwcN instructions, et al.
! 
! 		    Note that there is no load/store cp0 instructions, and
! 		    that FPU (cp1) instructions disassemble this field using
! 		    'T' format.  Therefore, until we gain understanding of
! 		    cp2 register names, we can simply print the register
! 		    numbers.  */
! 		  infprintf (is, "$%d", GET_OP (insn, RT));
! 		  break;
! 
! 		case 'G':
! 		  /* Coprocessor register for mtcN instructions, et al.  Note
! 		     that FPU (cp1) instructions disassemble this field using
! 		     'S' format.  Therefore, we only need to worry about cp0,
! 		     cp2, and cp3.  */
! 		  if (op->name[strlen (op->name) - 1] == '0')
! 		    {
! 		      if (s[1] == ',' && s[2] == 'H')
! 			{
! 			  const struct mips_cp0sel_name *n;
! 			  unsigned int cp0reg, sel;
! 
! 			  cp0reg = GET_OP (insn, RS);
! 			  sel = GET_OP (insn, SEL);
! 
! 			  /* CP0 register including 'sel' code for mtcN
! 			     (et al.), to be printed textually if known.
! 			     If not known, print both CP0 register name and
! 			     sel numerically since CP0 register with sel 0 may
! 			     have a name unrelated to register being
! 			     printed.  */
! 			  n = lookup_mips_cp0sel_name (mips_cp0sel_names,
! 						       mips_cp0sel_names_len,
! 						       cp0reg, sel);
! 			  if (n != NULL)
! 			    infprintf (is, "%s", n->name);
! 			  else
! 			    infprintf (is, "$%d,%d", cp0reg, sel);
! 			  s += 2;
! 			}
! 		      else
! 			infprintf (is, "%s", mips_cp0_names[GET_OP (insn, RS)]);
! 		    }
! 		  else
! 		    infprintf (is, "$%d", GET_OP (insn, RS));
! 		  break;
! 
! 		case 'H':
! 		  infprintf (is, "%d", GET_OP (insn, SEL));
! 		  break;
! 
! 		case 'K':
! 		  infprintf (is, "%s", mips_hwr_names[GET_OP (insn, RS)]);
! 		  break;
! 
! 		case 'M':
! 		  infprintf (is, "$fcc%d", GET_OP (insn, CCC));
! 		  break;
! 
! 		case 'N':
! 		  infprintf (is,
! 			   (op->pinfo & (FP_D | FP_S)) != 0
! 			   ? "$fcc%d" : "$cc%d",
! 			   GET_OP (insn, BCC));
! 		  break;
! 
! 		case 'R':
! 		  infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FR)]);
! 		  break;
! 
! 		case 'S':
! 		case 'V':
! 		  infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FS)]);
! 		  break;
! 
! 		case 'T':
! 		  infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FT)]);
! 		  break;
! 
! 		case '+':
! 		  /* Extension character; switch for second char.  */
! 		  s++;
! 		  switch (*s)
! 		    {
! 		    case 'A':
! 		      lsb = GET_OP (insn, EXTLSB);
! 		      infprintf (is, "0x%x", lsb);
! 		      break;
! 
! 		    case 'B':
! 		      msb = GET_OP (insn, INSMSB);
! 		      infprintf (is, "0x%x", msb - lsb + 1);
! 		      break;
! 
! 		    case 'C':
! 		    case 'H':
! 		      msbd = GET_OP (insn, EXTMSBD);
! 		      infprintf (is, "0x%x", msbd + 1);
! 		      break;
! 
! 		    case 'E':
! 		      lsb = GET_OP (insn, EXTLSB) + 32;
! 		      infprintf (is, "0x%x", lsb);
! 		      break;
! 
! 		    case 'F':
! 		      msb = GET_OP (insn, INSMSB) + 32;
! 		      infprintf (is, "0x%x", msb - lsb + 1);
! 		      break;
! 
! 		    case 'G':
! 		      msbd = GET_OP (insn, EXTMSBD) + 32;
! 		      infprintf (is, "0x%x", msbd + 1);
! 		      break;
! 
! 		    case 'i':
! 		      info->target = (((memaddr + 4) & ~(bfd_vma) 0x0fffffff)
! 				      | (GET_OP (insn, TARGET) << 2));
! 		      (*info->print_address_func) (info->target, info);
! 		      break;
! 
! 		    case 'j':   /* 9-bit signed offset in bit 0. */
! 		      delta = GET_OP_S (insn, EVAOFFSET);
! 		      infprintf (is, "%d", delta);
! 		      break;
! 
! 		    default:
! 		      /* xgettext:c-format */
! 		      infprintf (is,
! 			       _("# internal disassembler error, "
! 				 "unrecognized modifier (+%c)"),
! 			       *s);
! 		      abort ();
! 		    }
! 		  break;
! 
! 		case 'm':
! 		  /* Extension character; switch for second char.  */
! 		  s++;
! 		  switch (*s)
! 		    {
! 		    case 'a':	/* global pointer.  */
! 		      infprintf (is, "%s", mips_gpr_names[28]);
! 		      break;
! 
! 		    case 'b':
! 		      regno = micromips_to_32_reg_b_map[GET_OP (insn, MB)];
! 		      infprintf (is, "%s", mips_gpr_names[regno]);
! 		      break;
! 
! 		    case 'c':
! 		      regno = micromips_to_32_reg_c_map[GET_OP (insn, MC)];
! 		      infprintf (is, "%s", mips_gpr_names[regno]);
! 		      break;
! 
! 		    case 'd':
! 		      regno = micromips_to_32_reg_d_map[GET_OP (insn, MD)];
! 		      infprintf (is, "%s", mips_gpr_names[regno]);
! 		      break;
! 
! 		    case 'e':
! 		      regno = micromips_to_32_reg_e_map[GET_OP (insn, ME)];
! 		      infprintf (is, "%s", mips_gpr_names[regno]);
! 		      break;
! 
! 		    case 'f':
! 		      /* Save lastregno for "mt" to print out later.  */
! 		      lastregno = micromips_to_32_reg_f_map[GET_OP (insn, MF)];
! 		      infprintf (is, "%s", mips_gpr_names[lastregno]);
! 		      break;
! 
! 		    case 'g':
! 		      regno = micromips_to_32_reg_g_map[GET_OP (insn, MG)];
! 		      infprintf (is, "%s", mips_gpr_names[regno]);
! 		      break;
! 
! 		    case 'h':
! 		      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':
! 		      infprintf (is, "%s", mips_gpr_names[GET_OP (insn, MJ)]);
! 		      break;
! 
! 		    case 'l':
! 		      regno = micromips_to_32_reg_l_map[GET_OP (insn, ML)];
! 		      infprintf (is, "%s", mips_gpr_names[regno]);
! 		      break;
! 
! 		    case 'm':
! 		      regno = micromips_to_32_reg_m_map[GET_OP (insn, MM)];
! 		      infprintf (is, "%s", mips_gpr_names[regno]);
! 		      break;
! 
! 		    case 'n':
! 		      regno = micromips_to_32_reg_n_map[GET_OP (insn, MN)];
! 		      infprintf (is, "%s", mips_gpr_names[regno]);
! 		      break;
! 
! 		    case 'p':
! 		      /* Save lastregno for "mt" to print out later.  */
! 		      lastregno = GET_OP (insn, MP);
! 		      infprintf (is, "%s", mips_gpr_names[lastregno]);
! 		      break;
! 
! 		    case 'q':
! 		      regno = micromips_to_32_reg_q_map[GET_OP (insn, MQ)];
! 		      infprintf (is, "%s", mips_gpr_names[regno]);
! 		      break;
! 
! 		    case 'r':	/* program counter.  */
! 		      infprintf (is, "$pc");
! 		      break;
! 
! 		    case 's':	/* stack pointer.  */
! 		      lastregno = 29;
! 		      infprintf (is, "%s", mips_gpr_names[29]);
! 		      break;
! 
! 		    case 't':
! 		      infprintf (is, "%s", mips_gpr_names[lastregno]);
! 		      break;
! 
! 		    case 'z':	/* $0.  */
! 		      infprintf (is, "%s", mips_gpr_names[0]);
! 		      break;
! 
! 		    case 'A':
! 		      /* Sign-extend the immediate.  */
! 		      immed = GET_OP_S (insn, IMMA) << 2;
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'B':
! 		      immed = micromips_imm_b_map[GET_OP (insn, IMMB)];
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'C':
! 		      immed = micromips_imm_c_map[GET_OP (insn, IMMC)];
! 		      infprintf (is, "0x%x", immed);
! 		      break;
! 
! 		    case 'D':
! 		      /* Sign-extend the displacement.  */
! 		      delta = GET_OP_S (insn, IMMD);
! 		      info->target = (delta << 1) + memaddr + length;
! 		      (*info->print_address_func) (info->target, info);
! 		      break;
! 
! 		    case 'E':
! 		      /* Sign-extend the displacement.  */
! 		      delta = GET_OP_S (insn, IMME);
! 		      info->target = (delta << 1) + memaddr + length;
! 		      (*info->print_address_func) (info->target, info);
! 		      break;
! 
! 		    case 'F':
! 		      immed = GET_OP (insn, IMMF);
! 		      infprintf (is, "0x%x", immed);
! 		      break;
! 
! 		    case 'G':
! 		      immed = (insn >> MICROMIPSOP_SH_IMMG) + 1;
! 		      immed = (immed & MICROMIPSOP_MASK_IMMG) - 1;
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'H':
! 		      immed = GET_OP (insn, IMMH) << 1;
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'I':
! 		      immed = (insn >> MICROMIPSOP_SH_IMMI) + 1;
! 		      immed = (immed & MICROMIPSOP_MASK_IMMI) - 1;
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'J':
! 		      immed = GET_OP (insn, IMMJ) << 2;
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'L':
! 		      immed = GET_OP (insn, IMML);
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'M':
! 		      immed = (insn >> MICROMIPSOP_SH_IMMM) - 1;
! 		      immed = (immed & MICROMIPSOP_MASK_IMMM) + 1;
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'N':
! 		      immed = GET_OP (insn, IMMN);
! 		      if (immed == 0)
! 			infprintf (is, "%s,%s",
! 				 mips_gpr_names[16],
! 				 mips_gpr_names[31]);
! 		      else
! 			infprintf (is, "%s-%s,%s",
! 				 mips_gpr_names[16],
! 				 mips_gpr_names[16 + immed],
! 				 mips_gpr_names[31]);
! 		      break;
! 
! 		    case 'O':
! 		      immed = GET_OP (insn, IMMO);
! 		      infprintf (is, "0x%x", immed);
! 		      break;
! 
! 		    case 'P':
! 		      immed = GET_OP (insn, IMMP) << 2;
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'Q':
! 		      /* Sign-extend the immediate.  */
! 		      immed = GET_OP_S (insn, IMMQ) << 2;
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'U':
! 		      immed = GET_OP (insn, IMMU) << 2;
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'W':
! 		      immed = GET_OP (insn, IMMW) << 2;
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'X':
! 		      /* Sign-extend the immediate.  */
! 		      immed = GET_OP_S (insn, IMMX);
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    case 'Y':
! 		      /* Sign-extend the immediate.  */
! 		      immed = GET_OP_S (insn, IMMY) << 2;
! 		      if ((unsigned int) (immed + 8) < 16)
! 			immed ^= 0x400;
! 		      infprintf (is, "%d", immed);
! 		      break;
! 
! 		    default:
! 		      /* xgettext:c-format */
! 		      infprintf (is,
! 			       _("# internal disassembler error, "
! 				 "unrecognized modifier (m%c)"),
! 			       *s);
! 		      abort ();
! 		    }
! 		  break;
! 
! 		default:
! 		  /* xgettext:c-format */
! 		  infprintf (is,
! 			   _("# internal disassembler error, "
! 			     "unrecognized modifier (%c)"),
! 			   *s);
! 		  abort ();
! 		}
  	    }
  
  	  /* Figure out instruction type and branch delay information.  */
--- 2134,2146 ----
  	  && ((length == 2 && (op->mask & 0xffff0000) == 0)
  	      || (length == 4 && (op->mask & 0xffff0000) != 0)))
  	{
  	  infprintf (is, "%s", op->name);
  
! 	  if (op->args[0])
  	    {
! 	      infprintf (is, "\t");
! 	      print_insn_args (info, op, decode_micromips_operand, insn,
! 			       memaddr + length + 1);
  	    }
  
  	  /* Figure out instruction type and branch delay information.  */
*************** #define GET_OP_S(insn, field) \
*** 2937,2944 ****
  	  return length;
  	}
      }
- #undef GET_OP_S
- #undef GET_OP
  
    infprintf (is, "0x%x", insn);
    info->insn_type = dis_noninsn;
--- 2170,2175 ----
Index: gas/config/tc-mips.c
===================================================================
*** gas/config/tc-mips.c	2013-07-14 10:33:21.087809400 +0100
--- gas/config/tc-mips.c	2013-07-14 10:56:24.409981309 +0100
*************** static void s_mips_file (int);
*** 1326,1333 ****
  static void s_mips_loc (int);
  static bfd_boolean pic_need_relax (symbolS *, asection *);
  static int relaxed_branch_length (fragS *, asection *, int);
- static int validate_mips_insn (const struct mips_opcode *);
- static int validate_micromips_insn (const struct mips_opcode *);
  static int relaxed_micromips_16bit_branch_length (fragS *, asection *, int);
  static int relaxed_micromips_32bit_branch_length (fragS *, asection *, int);
  
--- 1326,1331 ----
*************** is_delay_slot_valid (const struct mips_o
*** 2707,2712 ****
--- 2705,2815 ----
    return TRUE;
  }
  
+ /* For consistency checking, verify that all bits of OPCODE are
+    specified either by the match/mask part of the instruction
+    definition, or by the operand list.  INSN_BITS says which
+    bits of the instruction are significant and DECODE_OPERAND
+    provides the mips_operand description of each operand.  */
+ 
+ static int
+ validate_mips_insn (const struct mips_opcode *opcode,
+ 		    unsigned long insn_bits,
+ 		    const struct mips_operand *(*decode_operand) (const char *))
+ {
+   const char *s;
+   unsigned long used_bits, doubled, undefined;
+   const struct mips_operand *operand;
+ 
+   if ((opcode->mask & opcode->match) != opcode->match)
+     {
+       as_bad (_("internal: bad mips opcode (mask error): %s %s"),
+ 	      opcode->name, opcode->args);
+       return 0;
+     }
+   used_bits = 0;
+   for (s = opcode->args; *s; ++s)
+     switch (*s)
+       {
+       case ',':
+       case '(':
+       case ')':
+ 	break;
+ 
+       default:
+ 	operand = decode_operand (s);
+ 	if (!operand)
+ 	  {
+ 	    as_bad (_("internal: unknown operand type: %s %s"),
+ 		    opcode->name, opcode->args);
+ 	    return 0;
+ 	  }
+ 	used_bits |= ((1 << operand->size) - 1) << operand->lsb;
+ 	if (operand->type == OP_MDMX_IMM_REG)
+ 	  /* Bit 5 is the format selector (OB vs QH).  The opcode table
+ 	     has separate entries for each format.  */
+ 	  used_bits &= ~(1 << (operand->lsb + 5));
+ 	/* Skip prefix characters.  */
+ 	if (*s == '+' || *s == 'm')
+ 	  ++s;
+ 	break;
+       }
+   doubled = used_bits & opcode->mask & insn_bits;
+   if (doubled)
+     {
+       as_bad (_("internal: bad mips opcode (bits 0x%08lx doubly defined):"
+ 		" %s %s"), doubled, opcode->name, opcode->args);
+       return 0;
+     }
+   used_bits |= opcode->mask;
+   undefined = ~used_bits & insn_bits;
+   if (undefined)
+     {
+       as_bad (_("internal: bad mips opcode (bits 0x%08lx undefined): %s %s"),
+ 	      undefined, opcode->name, opcode->args);
+       return 0;
+     }
+   used_bits &= ~insn_bits;
+   if (used_bits)
+     {
+       as_bad (_("internal: bad mips opcode (bits 0x%08lx defined): %s %s"),
+ 	      used_bits, opcode->name, opcode->args);
+       return 0;
+     }
+   return 1;
+ }
+ 
+ /* The microMIPS version of validate_mips_insn.  */
+ 
+ static int
+ validate_micromips_insn (const struct mips_opcode *opc)
+ {
+   unsigned long insn_bits;
+   unsigned long major;
+   unsigned int length;
+ 
+   length = micromips_insn_length (opc);
+   if (length != 2 && length != 4)
+     {
+       as_bad (_("Internal error: bad microMIPS opcode (incorrect length: %u): "
+ 		"%s %s"), length, opc->name, opc->args);
+       return 0;
+     }
+   major = opc->match >> (10 + 8 * (length - 2));
+   if ((length == 2 && (major & 7) != 1 && (major & 6) != 2)
+       || (length == 4 && (major & 7) != 0 && (major & 4) != 4))
+     {
+       as_bad (_("Internal error: bad microMIPS opcode "
+ 		"(opcode/length mismatch): %s %s"), opc->name, opc->args);
+       return 0;
+     }
+ 
+   /* Shift piecewise to avoid an overflow where unsigned long is 32-bit.  */
+   insn_bits = 1 << 4 * length;
+   insn_bits <<= 4 * length;
+   insn_bits -= 1;
+   return validate_mips_insn (opc, insn_bits, decode_micromips_operand);
+ }
+ 
  /* This function is called once, at assembler startup time.  It should set up
     all the tables, etc. that the MD part of the assembler will need.  */
  
*************** md_begin (void)
*** 2745,2751 ****
  	{
  	  if (mips_opcodes[i].pinfo != INSN_MACRO)
  	    {
! 	      if (!validate_mips_insn (&mips_opcodes[i]))
  		broken = 1;
  	      if (nop_insn.insn_mo == NULL && strcmp (name, "nop") == 0)
  		{
--- 2848,2855 ----
  	{
  	  if (mips_opcodes[i].pinfo != INSN_MACRO)
  	    {
! 	      if (!validate_mips_insn (&mips_opcodes[i], 0xffffffff,
! 				       decode_mips_operand))
  		broken = 1;
  	      if (nop_insn.insn_mo == NULL && strcmp (name, "nop") == 0)
  		{
*************** mips16_macro (struct mips_cl_insn *ip)
*** 10748,11098 ****
      }
  }
  
- /* For consistency checking, verify that all bits are specified either
-    by the match/mask part of the instruction definition, or by the
-    operand list.  */
- static int
- validate_mips_insn (const struct mips_opcode *opc)
- {
-   const char *p = opc->args;
-   char c;
-   unsigned long used_bits = opc->mask;
- 
-   if ((used_bits & opc->match) != opc->match)
-     {
-       as_bad (_("internal: bad mips opcode (mask error): %s %s"),
- 	      opc->name, opc->args);
-       return 0;
-     }
- #define USE_BITS(mask,shift)	(used_bits |= ((mask) << (shift)))
-   while (*p)
-     switch (c = *p++)
-       {
-       case ',': break;
-       case '(': break;
-       case ')': break;
-       case '+':
-     	switch (c = *p++)
- 	  {
- 	  case '1': USE_BITS (OP_MASK_UDI1,     OP_SH_UDI1); 	break;
- 	  case '2': USE_BITS (OP_MASK_UDI2,	OP_SH_UDI2); 	break;
- 	  case '3': USE_BITS (OP_MASK_UDI3,	OP_SH_UDI3); 	break;
- 	  case '4': USE_BITS (OP_MASK_UDI4,	OP_SH_UDI4); 	break;
- 	  case 'A': USE_BITS (OP_MASK_SHAMT,	OP_SH_SHAMT);	break;
- 	  case 'B': USE_BITS (OP_MASK_INSMSB,	OP_SH_INSMSB);	break;
- 	  case 'C': USE_BITS (OP_MASK_EXTMSBD,	OP_SH_EXTMSBD);	break;
- 	  case 'E': USE_BITS (OP_MASK_SHAMT,	OP_SH_SHAMT);	break;
- 	  case 'F': USE_BITS (OP_MASK_INSMSB,	OP_SH_INSMSB);	break;
- 	  case 'G': USE_BITS (OP_MASK_EXTMSBD,	OP_SH_EXTMSBD);	break;
- 	  case 'H': USE_BITS (OP_MASK_EXTMSBD,	OP_SH_EXTMSBD);	break;
- 	  case 'I': break;
- 	  case 'J': USE_BITS (OP_MASK_CODE10,	OP_SH_CODE10);	break;
- 	  case 't': USE_BITS (OP_MASK_RT,	OP_SH_RT);	break;
- 	  case 'x': USE_BITS (OP_MASK_BBITIND,	OP_SH_BBITIND);	break;
- 	  case 'X': USE_BITS (OP_MASK_BBITIND,	OP_SH_BBITIND);	break;
- 	  case 'p': USE_BITS (OP_MASK_CINSPOS,	OP_SH_CINSPOS);	break;
- 	  case 'P': USE_BITS (OP_MASK_CINSPOS,	OP_SH_CINSPOS);	break;
- 	  case 'Q': USE_BITS (OP_MASK_SEQI,	OP_SH_SEQI);	break;
- 	  case 's': USE_BITS (OP_MASK_CINSLM1,	OP_SH_CINSLM1);	break;
- 	  case 'S': USE_BITS (OP_MASK_CINSLM1,	OP_SH_CINSLM1);	break;
- 	  case 'z': USE_BITS (OP_MASK_RZ,	OP_SH_RZ);	break;
- 	  case 'Z': USE_BITS (OP_MASK_FZ,	OP_SH_FZ);	break;
- 	  case 'a': USE_BITS (OP_MASK_OFFSET_A,	OP_SH_OFFSET_A); break;
- 	  case 'b': USE_BITS (OP_MASK_OFFSET_B,	OP_SH_OFFSET_B); break;
- 	  case 'c': USE_BITS (OP_MASK_OFFSET_C,	OP_SH_OFFSET_C); break;
- 	  case 'i': USE_BITS (OP_MASK_TARGET,	OP_SH_TARGET);	break;
- 	  case 'j': USE_BITS (OP_MASK_EVAOFFSET, OP_SH_EVAOFFSET); break;
- 
- 	  default:
- 	    as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"),
- 		    c, opc->name, opc->args);
- 	    return 0;
- 	  }
- 	break;
-       case '<': USE_BITS (OP_MASK_SHAMT,	OP_SH_SHAMT);	break;
-       case '>':	USE_BITS (OP_MASK_SHAMT,	OP_SH_SHAMT);	break;
-       case 'A': break;
-       case 'B': USE_BITS (OP_MASK_CODE20,       OP_SH_CODE20);  break;
-       case 'C':	USE_BITS (OP_MASK_COPZ,		OP_SH_COPZ);	break;
-       case 'D':	USE_BITS (OP_MASK_FD,		OP_SH_FD);	break;
-       case 'E':	USE_BITS (OP_MASK_RT,		OP_SH_RT);	break;
-       case 'F': break;
-       case 'G':	USE_BITS (OP_MASK_RD,		OP_SH_RD);	break;
-       case 'H': USE_BITS (OP_MASK_SEL,		OP_SH_SEL);	break;
-       case 'I': break;
-       case 'J': USE_BITS (OP_MASK_CODE19,       OP_SH_CODE19);  break;
-       case 'K':	USE_BITS (OP_MASK_RD,		OP_SH_RD);	break;
-       case 'L': break;
-       case 'M':	USE_BITS (OP_MASK_CCC,		OP_SH_CCC);	break;
-       case 'N':	USE_BITS (OP_MASK_BCC,		OP_SH_BCC);	break;
-       case 'O':	USE_BITS (OP_MASK_ALN,		OP_SH_ALN);	break;
-       case 'Q':	USE_BITS (OP_MASK_VSEL,		OP_SH_VSEL);
- 		USE_BITS (OP_MASK_FT,		OP_SH_FT);	break;
-       case 'R':	USE_BITS (OP_MASK_FR,		OP_SH_FR);	break;
-       case 'S':	USE_BITS (OP_MASK_FS,		OP_SH_FS);	break;
-       case 'T':	USE_BITS (OP_MASK_FT,		OP_SH_FT);	break;
-       case 'V':	USE_BITS (OP_MASK_FS,		OP_SH_FS);	break;
-       case 'W':	USE_BITS (OP_MASK_FT,		OP_SH_FT);	break;
-       case 'X':	USE_BITS (OP_MASK_FD,		OP_SH_FD);	break;
-       case 'Y':	USE_BITS (OP_MASK_FS,		OP_SH_FS);	break;
-       case 'Z':	USE_BITS (OP_MASK_FT,		OP_SH_FT);	break;
-       case 'a':	USE_BITS (OP_MASK_TARGET,	OP_SH_TARGET);	break;
-       case 'b':	USE_BITS (OP_MASK_RS,		OP_SH_RS);	break;
-       case 'c':	USE_BITS (OP_MASK_CODE,		OP_SH_CODE);	break;
-       case 'd':	USE_BITS (OP_MASK_RD,		OP_SH_RD);	break;
-       case 'f': break;
-       case 'h':	USE_BITS (OP_MASK_PREFX,	OP_SH_PREFX);	break;
-       case 'i':	USE_BITS (OP_MASK_IMMEDIATE,	OP_SH_IMMEDIATE); break;
-       case 'j':	USE_BITS (OP_MASK_DELTA,	OP_SH_DELTA);	break;
-       case 'k':	USE_BITS (OP_MASK_CACHE,	OP_SH_CACHE);	break;
-       case 'l': break;
-       case 'o': USE_BITS (OP_MASK_DELTA,	OP_SH_DELTA);	break;
-       case 'p':	USE_BITS (OP_MASK_DELTA,	OP_SH_DELTA);	break;
-       case 'q':	USE_BITS (OP_MASK_CODE2,	OP_SH_CODE2);	break;
-       case 'r': USE_BITS (OP_MASK_RS,		OP_SH_RS);	break;
-       case 's':	USE_BITS (OP_MASK_RS,		OP_SH_RS);	break;
-       case 't':	USE_BITS (OP_MASK_RT,		OP_SH_RT);	break;
-       case 'u':	USE_BITS (OP_MASK_IMMEDIATE,	OP_SH_IMMEDIATE); break;
-       case 'v':	USE_BITS (OP_MASK_RS,		OP_SH_RS);	break;
-       case 'w':	USE_BITS (OP_MASK_RT,		OP_SH_RT);	break;
-       case 'x': break;
-       case 'z': break;
-       case 'P': USE_BITS (OP_MASK_PERFREG,	OP_SH_PERFREG);	break;
-       case 'U': USE_BITS (OP_MASK_RD,           OP_SH_RD);
- 	        USE_BITS (OP_MASK_RT,           OP_SH_RT);	break;
-       case 'e': USE_BITS (OP_MASK_VECBYTE,	OP_SH_VECBYTE);	break;
-       case '%': USE_BITS (OP_MASK_VECALIGN,	OP_SH_VECALIGN); break;
-       case '1': USE_BITS (OP_MASK_STYPE,	OP_SH_STYPE);	break;
-       case '2': USE_BITS (OP_MASK_BP,		OP_SH_BP);	break;
-       case '3': USE_BITS (OP_MASK_SA3,  	OP_SH_SA3);	break;
-       case '4': USE_BITS (OP_MASK_SA4,  	OP_SH_SA4);	break;
-       case '5': USE_BITS (OP_MASK_IMM8, 	OP_SH_IMM8);	break;
-       case '6': USE_BITS (OP_MASK_RS,		OP_SH_RS);	break;
-       case '7': USE_BITS (OP_MASK_DSPACC,	OP_SH_DSPACC);	break;
-       case '8': USE_BITS (OP_MASK_WRDSP,	OP_SH_WRDSP);	break;
-       case '9': USE_BITS (OP_MASK_DSPACC_S,	OP_SH_DSPACC_S);break;
-       case '0': USE_BITS (OP_MASK_DSPSFT,	OP_SH_DSPSFT);	break;
-       case '\'': USE_BITS (OP_MASK_RDDSP,	OP_SH_RDDSP);	break;
-       case ':': USE_BITS (OP_MASK_DSPSFT_7,	OP_SH_DSPSFT_7);break;
-       case '@': USE_BITS (OP_MASK_IMM10,	OP_SH_IMM10);	break;
-       case '!': USE_BITS (OP_MASK_MT_U,		OP_SH_MT_U);	break;
-       case '$': USE_BITS (OP_MASK_MT_H,		OP_SH_MT_H);	break;
-       case '*': USE_BITS (OP_MASK_MTACC_T,	OP_SH_MTACC_T);	break;
-       case '&': USE_BITS (OP_MASK_MTACC_D,	OP_SH_MTACC_D);	break;
-       case '\\': USE_BITS (OP_MASK_3BITPOS,	OP_SH_3BITPOS);	break;
-       case '~': USE_BITS (OP_MASK_OFFSET12,	OP_SH_OFFSET12); break;
-       case 'g': USE_BITS (OP_MASK_RD,		OP_SH_RD);	break;
-       default:
- 	as_bad (_("internal: bad mips opcode (unknown operand type `%c'): %s %s"),
- 		c, opc->name, opc->args);
- 	return 0;
-       }
- #undef USE_BITS
-   if (used_bits != 0xffffffff)
-     {
-       as_bad (_("internal: bad mips opcode (bits 0x%lx undefined): %s %s"),
- 	      ~used_bits & 0xffffffff, opc->name, opc->args);
-       return 0;
-     }
-   return 1;
- }
- 
- /* For consistency checking, verify that the length implied matches the
-    major opcode and that all bits are specified either by the match/mask
-    part of the instruction definition, or by the operand list.  */
- 
- static int
- validate_micromips_insn (const struct mips_opcode *opc)
- {
-   unsigned long match = opc->match;
-   unsigned long mask = opc->mask;
-   const char *p = opc->args;
-   unsigned long insn_bits;
-   unsigned long used_bits;
-   unsigned long major;
-   unsigned int length;
-   char e;
-   char c;
- 
-   if ((mask & match) != match)
-     {
-       as_bad (_("Internal error: bad microMIPS opcode (mask error): %s %s"),
- 	      opc->name, opc->args);
-       return 0;
-     }
-   length = micromips_insn_length (opc);
-   if (length != 2 && length != 4)
-     {
-       as_bad (_("Internal error: bad microMIPS opcode (incorrect length: %u): "
- 		"%s %s"), length, opc->name, opc->args);
-       return 0;
-     }
-   major = match >> (10 + 8 * (length - 2));
-   if ((length == 2 && (major & 7) != 1 && (major & 6) != 2)
-       || (length == 4 && (major & 7) != 0 && (major & 4) != 4))
-     {
-       as_bad (_("Internal error: bad microMIPS opcode "
- 		"(opcode/length mismatch): %s %s"), opc->name, opc->args);
-       return 0;
-     }
- 
-   /* Shift piecewise to avoid an overflow where unsigned long is 32-bit.  */
-   insn_bits = 1 << 4 * length;
-   insn_bits <<= 4 * length;
-   insn_bits -= 1;
-   used_bits = mask;
- #define USE_BITS(field) \
-   (used_bits |= MICROMIPSOP_MASK_##field << MICROMIPSOP_SH_##field)
-   while (*p)
-     switch (c = *p++)
-       {
-       case ',': break;
-       case '(': break;
-       case ')': break;
-       case '+':
- 	e = c;
-     	switch (c = *p++)
- 	  {
- 	  case 'A': USE_BITS (EXTLSB);	break;
- 	  case 'B': USE_BITS (INSMSB);	break;
- 	  case 'C': USE_BITS (EXTMSBD);	break;
- 	  case 'E': USE_BITS (EXTLSB);	break;
- 	  case 'F': USE_BITS (INSMSB);	break;
- 	  case 'G': USE_BITS (EXTMSBD);	break;
- 	  case 'H': USE_BITS (EXTMSBD);	break;
- 	  case 'i': USE_BITS (TARGET);	break;
- 	  case 'j': USE_BITS (EVAOFFSET);	break;
- 	  default:
- 	    as_bad (_("Internal error: bad mips opcode "
- 		      "(unknown extension operand type `%c%c'): %s %s"),
- 		    e, c, opc->name, opc->args);
- 	    return 0;
- 	  }
- 	break;
-       case 'm':
- 	e = c;
-     	switch (c = *p++)
- 	  {
- 	  case 'A': USE_BITS (IMMA);	break;
- 	  case 'B': USE_BITS (IMMB);	break;
- 	  case 'C': USE_BITS (IMMC);	break;
- 	  case 'D': USE_BITS (IMMD);	break;
- 	  case 'E': USE_BITS (IMME);	break;
- 	  case 'F': USE_BITS (IMMF);	break;
- 	  case 'G': USE_BITS (IMMG);	break;
- 	  case 'H': USE_BITS (IMMH);	break;
- 	  case 'I': USE_BITS (IMMI);	break;
- 	  case 'J': USE_BITS (IMMJ);	break;
- 	  case 'L': USE_BITS (IMML);	break;
- 	  case 'M': USE_BITS (IMMM);	break;
- 	  case 'N': USE_BITS (IMMN);	break;
- 	  case 'O': USE_BITS (IMMO);	break;
- 	  case 'P': USE_BITS (IMMP);	break;
- 	  case 'Q': USE_BITS (IMMQ);	break;
- 	  case 'U': USE_BITS (IMMU);	break;
- 	  case 'W': USE_BITS (IMMW);	break;
- 	  case 'X': USE_BITS (IMMX);	break;
- 	  case 'Y': USE_BITS (IMMY);	break;
- 	  case 'Z': break;
- 	  case 'a': break;
- 	  case 'b': USE_BITS (MB);	break;
- 	  case 'c': USE_BITS (MC);	break;
- 	  case 'd': USE_BITS (MD);	break;
- 	  case 'e': USE_BITS (ME);	break;
- 	  case 'f': USE_BITS (MF);	break;
- 	  case 'g': USE_BITS (MG);	break;
- 	  case 'h': USE_BITS (MH);	break;
- 	  case 'j': USE_BITS (MJ);	break;
- 	  case 'l': USE_BITS (ML);	break;
- 	  case 'm': USE_BITS (MM);	break;
- 	  case 'n': USE_BITS (MN);	break;
- 	  case 'p': USE_BITS (MP);	break;
- 	  case 'q': USE_BITS (MQ);	break;
- 	  case 'r': break;
- 	  case 's': break;
- 	  case 't': break;
- 	  case 'x': break;
- 	  case 'y': break;
- 	  case 'z': break;
- 	  default:
- 	    as_bad (_("Internal error: bad mips opcode "
- 		      "(unknown extension operand type `%c%c'): %s %s"),
- 		    e, c, opc->name, opc->args);
- 	    return 0;
- 	  }
- 	break;
-       case '.': USE_BITS (OFFSET10);	break;
-       case '1': USE_BITS (STYPE);	break;
-       case '2': USE_BITS (BP);		break;
-       case '3': USE_BITS (SA3);		break;
-       case '4': USE_BITS (SA4);		break;
-       case '5': USE_BITS (IMM8);	break;
-       case '6': USE_BITS (RS);		break;
-       case '7': USE_BITS (DSPACC);	break;
-       case '8': USE_BITS (WRDSP);	break;
-       case '0': USE_BITS (DSPSFT);	break;
-       case '<': USE_BITS (SHAMT);	break;
-       case '>': USE_BITS (SHAMT);	break;
-       case '@': USE_BITS (IMM10);	break;
-       case 'B': USE_BITS (CODE10);	break;
-       case 'C': USE_BITS (COPZ);	break;
-       case 'D': USE_BITS (FD);		break;
-       case 'E': USE_BITS (RT);		break;
-       case 'G': USE_BITS (RS);		break;
-       case 'H': USE_BITS (SEL);		break;
-       case 'K': USE_BITS (RS);		break;
-       case 'M': USE_BITS (CCC);		break;
-       case 'N': USE_BITS (BCC);		break;
-       case 'R': USE_BITS (FR);		break;
-       case 'S': USE_BITS (FS);		break;
-       case 'T': USE_BITS (FT);		break;
-       case 'V': USE_BITS (FS);		break;
-       case '\\': USE_BITS (3BITPOS);	break;
-       case '^': USE_BITS (RD);		break;
-       case 'a': USE_BITS (TARGET);	break;
-       case 'b': USE_BITS (RS);		break;
-       case 'c': USE_BITS (CODE);	break;
-       case 'd': USE_BITS (RD);		break;
-       case 'h': USE_BITS (PREFX);	break;
-       case 'i': USE_BITS (IMMEDIATE);	break;
-       case 'j': USE_BITS (DELTA);	break;
-       case 'k': USE_BITS (CACHE);	break;
-       case 'n': USE_BITS (RT);		break;
-       case 'o': USE_BITS (DELTA);	break;
-       case 'p': USE_BITS (DELTA);	break;
-       case 'q': USE_BITS (CODE2);	break;
-       case 'r': USE_BITS (RS);		break;
-       case 's': USE_BITS (RS);		break;
-       case 't': USE_BITS (RT);		break;
-       case 'u': USE_BITS (IMMEDIATE);	break;
-       case 'v': USE_BITS (RS);		break;
-       case 'w': USE_BITS (RT);		break;
-       case 'y': USE_BITS (RS3);		break;
-       case 'z': break;
-       case '|': USE_BITS (TRAP);	break;
-       case '~': USE_BITS (OFFSET12);	break;
-       default:
- 	as_bad (_("Internal error: bad microMIPS opcode "
- 		  "(unknown operand type `%c'): %s %s"),
- 		c, opc->name, opc->args);
- 	return 0;
-       }
- #undef USE_BITS
-   if (used_bits != insn_bits)
-     {
-       if (~used_bits & insn_bits)
- 	as_bad (_("Internal error: bad microMIPS opcode "
- 		  "(bits 0x%lx undefined): %s %s"),
- 		~used_bits & insn_bits, opc->name, opc->args);
-       if (used_bits & ~insn_bits)
- 	as_bad (_("Internal error: bad microMIPS opcode "
- 		  "(bits 0x%lx defined): %s %s"),
- 		used_bits & ~insn_bits, opc->name, opc->args);
-       return 0;
-     }
-   return 1;
- }
- 
  /* UDI immediates.  */
  struct mips_immed {
    char		type;
--- 10852,10857 ----


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