[PATCH] MIPS/opcodes: Streamline disassembler's operand processing

Maciej W. Rozycki macro@codesourcery.com
Tue Aug 14 00:54:00 GMT 2012


Hi,

 This change updates standard-MIPS and MIPS16 instruction operand 
processing internals of the disassembler in line with the microMIPS 
version -- this includes the addition of the GET_OP macro and local 
variables for frequently accessed struct member references, all to improve 
readability and make maintenance easier, and perhaps to aid the compiler 
in making slightly better code.  Additionally a GET_OP_S macro is added to 
simplify processing of sign extension across all the three instruction set 
handlers.

 No regressions across the 23 MIPS targets.  OK to apply?

  Maciej

2012-08-14  Maciej W. Rozycki  <macro@codesourcery.com>

	opcodes/
	* mips-dis.c (print_insn_args): Add GET_OP and GET_OP_S local
	macros, use local variables for info struct member accesses, 
	update the type of the variable used to hold the instruction
	word.
	(print_insn_mips, print_mips16_insn_arg): Likewise.
	(print_insn_mips16): Add GET_OP and GET_OP_S local macros, use 
	local variables for info struct member accesses.
	(print_insn_micromips): Add GET_OP_S local macro.
	(_print_insn_mips): Update the type of the variable used to hold
	the instruction word.

binutils-mips-dis-op.diff
Index: binutils-fsf-trunk-quilt/opcodes/mips-dis.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/opcodes/mips-dis.c	2012-07-19 12:49:14.061767944 +0100
+++ binutils-fsf-trunk-quilt/opcodes/mips-dis.c	2012-07-19 12:49:34.431502283 +0100
@@ -930,16 +930,23 @@ lookup_mips_cp0sel_name (const struct mi
 
 static void
 print_insn_args (const char *d,
-		 register unsigned long int l,
+		 int l,
 		 bfd_vma pc,
 		 struct disassemble_info *info,
 		 const struct mips_opcode *opp)
 {
-  int op, delta;
+  const fprintf_ftype infprintf = info->fprintf_func;
   unsigned int lsb, msb, msbd;
+  void *is = info->stream;
+  int op;
 
   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)
@@ -949,7 +956,7 @@ print_insn_args (const char *d,
 	case ')':
 	case '[':
 	case ']':
-	  (*info->fprintf_func) (info->stream, "%c", *d);
+	  infprintf (is, "%c", *d);
 	  break;
 
 	case '+':
@@ -959,44 +966,41 @@ print_insn_args (const char *d,
 	    {
 	    case '\0':
 	      /* xgettext:c-format */
-	      (*info->fprintf_func) (info->stream,
-				     _("# internal error, incomplete extension sequence (+)"));
+	      infprintf (is,
+			 _("# internal error, "
+			   "incomplete extension sequence (+)"));
 	      return;
 
 	    case 'A':
-	      lsb = (l >> OP_SH_SHAMT) & OP_MASK_SHAMT;
-	      (*info->fprintf_func) (info->stream, "0x%x", lsb);
+	      lsb = GET_OP (l, SHAMT);
+	      infprintf (is, "0x%x", lsb);
 	      break;
 	
 	    case 'B':
-	      msb = (l >> OP_SH_INSMSB) & OP_MASK_INSMSB;
-	      (*info->fprintf_func) (info->stream, "0x%x", msb - lsb + 1);
+	      msb = GET_OP (l, INSMSB);
+	      infprintf (is, "0x%x", msb - lsb + 1);
 	      break;
 
 	    case '1':
-	      (*info->fprintf_func) (info->stream, "0x%lx",
-				     (l >> OP_SH_UDI1) & OP_MASK_UDI1);
+	      infprintf (is, "0x%x", GET_OP (l, UDI1));
 	      break;
 	      
 	    case '2':
-	      (*info->fprintf_func) (info->stream, "0x%lx",
-				     (l >> OP_SH_UDI2) & OP_MASK_UDI2);
+	      infprintf (is, "0x%x", GET_OP (l, UDI2));
 	      break;
 	      
 	    case '3':
-	      (*info->fprintf_func) (info->stream, "0x%lx",
-				     (l >> OP_SH_UDI3) & OP_MASK_UDI3);
+	      infprintf (is, "0x%x", GET_OP (l, UDI3));
 	      break;
       
 	    case '4':
-	      (*info->fprintf_func) (info->stream, "0x%lx",
-				     (l >> OP_SH_UDI4) & OP_MASK_UDI4);
+	      infprintf (is, "0x%x", GET_OP (l, UDI4));
 	      break;
 	      
 	    case 'C':
 	    case 'H':
-	      msbd = (l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD;
-	      (*info->fprintf_func) (info->stream, "0x%x", msbd + 1);
+	      msbd = GET_OP (l, EXTMSBD);
+	      infprintf (is, "0x%x", msbd + 1);
 	      break;
 
 	    case 'D':
@@ -1004,8 +1008,8 @@ print_insn_args (const char *d,
 		const struct mips_cp0sel_name *n;
 		unsigned int cp0reg, sel;
 
-		cp0reg = (l >> OP_SH_RD) & OP_MASK_RD;
-		sel = (l >> OP_SH_SEL) & OP_MASK_SEL;
+		cp0reg = GET_OP (l, RD);
+		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
@@ -1015,31 +1019,29 @@ print_insn_args (const char *d,
 		n = lookup_mips_cp0sel_name(mips_cp0sel_names,
 					    mips_cp0sel_names_len, cp0reg, sel);
 		if (n != NULL)
-		  (*info->fprintf_func) (info->stream, "%s", n->name);
+		  infprintf (is, "%s", n->name);
 		else
-		  (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel);
+		  infprintf (is, "$%d,%d", cp0reg, sel);
 		break;
 	      }
 
 	    case 'E':
-	      lsb = ((l >> OP_SH_SHAMT) & OP_MASK_SHAMT) + 32;
-	      (*info->fprintf_func) (info->stream, "0x%x", lsb);
+	      lsb = GET_OP (l, SHAMT) + 32;
+	      infprintf (is, "0x%x", lsb);
 	      break;
 	
 	    case 'F':
-	      msb = ((l >> OP_SH_INSMSB) & OP_MASK_INSMSB) + 32;
-	      (*info->fprintf_func) (info->stream, "0x%x", msb - lsb + 1);
+	      msb = GET_OP (l, INSMSB) + 32;
+	      infprintf (is, "0x%x", msb - lsb + 1);
 	      break;
 
 	    case 'G':
-	      msbd = ((l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD) + 32;
-	      (*info->fprintf_func) (info->stream, "0x%x", msbd + 1);
+	      msbd = GET_OP (l, EXTMSBD) + 32;
+	      infprintf (is, "0x%x", msbd + 1);
 	      break;
 
 	    case 't': /* Coprocessor 0 reg name */
-	      (*info->fprintf_func) (info->stream, "%s",
-				     mips_cp0_names[(l >> OP_SH_RT) &
-						     OP_MASK_RT]);
+	      infprintf (is, "%s", mips_cp0_names[GET_OP (l, RT)]);
 	      break;
 
 	    case 'T': /* Coprocessor 0 reg name */
@@ -1047,8 +1049,8 @@ print_insn_args (const char *d,
 		const struct mips_cp0sel_name *n;
 		unsigned int cp0reg, sel;
 
-		cp0reg = (l >> OP_SH_RT) & OP_MASK_RT;
-		sel = (l >> OP_SH_SEL) & OP_MASK_SEL;
+		cp0reg = GET_OP (l, RT);
+		sel = GET_OP (l, SEL);
 
 		/* CP0 register including 'sel' code for mftc0, to be
 		   printed textually if known.  If not known, print both
@@ -1058,228 +1060,173 @@ print_insn_args (const char *d,
 		n = lookup_mips_cp0sel_name(mips_cp0sel_names,
 					    mips_cp0sel_names_len, cp0reg, sel);
 		if (n != NULL)
-		  (*info->fprintf_func) (info->stream, "%s", n->name);
+		  infprintf (is, "%s", n->name);
 		else
-		  (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel);
+		  infprintf (is, "$%d,%d", cp0reg, sel);
 		break;
 	      }
 
 	    case 'x':		/* bbit bit index */
-	      (*info->fprintf_func) (info->stream, "0x%lx",
-				     (l >> OP_SH_BBITIND) & OP_MASK_BBITIND);
+	      infprintf (is, "0x%x", GET_OP (l, BBITIND));
 	      break;
 
 	    case 'p':		/* cins, cins32, exts and exts32 position */
-	      (*info->fprintf_func) (info->stream, "0x%lx",
-				     (l >> OP_SH_CINSPOS) & OP_MASK_CINSPOS);
+	      infprintf (is, "0x%x", GET_OP (l, CINSPOS));
 	      break;
 
 	    case 's':		/* cins and exts length-minus-one */
-	      (*info->fprintf_func) (info->stream, "0x%lx",
-				     (l >> OP_SH_CINSLM1) & OP_MASK_CINSLM1);
+	      infprintf (is, "0x%x", GET_OP (l, CINSLM1));
 	      break;
 
 	    case 'S':		/* cins32 and exts32 length-minus-one field */
-	      (*info->fprintf_func) (info->stream, "0x%lx",
-				     (l >> OP_SH_CINSLM1) & OP_MASK_CINSLM1);
+	      infprintf (is, "0x%x", GET_OP (l, CINSLM1));
 	      break;
 
 	    case 'Q':		/* seqi/snei immediate field */
-	      op = (l >> OP_SH_SEQI) & OP_MASK_SEQI;
-	      /* Sign-extend it.  */
-	      op = (op ^ 512) - 512;
-	      (*info->fprintf_func) (info->stream, "%d", op);
+	      infprintf (is, "%d", GET_OP_S (l, SEQI));
 	      break;
 
 	    case 'a':		/* 8-bit signed offset in bit 6 */
-	      delta = (l >> OP_SH_OFFSET_A) & OP_MASK_OFFSET_A;
-	      if (delta & 0x80)
-		delta |= ~OP_MASK_OFFSET_A;
-	      (*info->fprintf_func) (info->stream, "%d", delta);
+	      infprintf (is, "%d", GET_OP_S (l, OFFSET_A));
 	      break;
 
 	    case 'b':		/* 8-bit signed offset in bit 3 */
-	      delta = (l >> OP_SH_OFFSET_B) & OP_MASK_OFFSET_B;
-	      if (delta & 0x80)
-		delta |= ~OP_MASK_OFFSET_B;
-	      (*info->fprintf_func) (info->stream, "%d", delta);
+	      infprintf (is, "%d", GET_OP_S (l, OFFSET_B));
 	      break;
 
 	    case 'c':		/* 9-bit signed offset in bit 6 */
-	      delta = (l >> OP_SH_OFFSET_C) & OP_MASK_OFFSET_C;
-	      if (delta & 0x100)
-		delta |= ~OP_MASK_OFFSET_C;
 	      /* Left shift 4 bits to print the real offset.  */
-	      (*info->fprintf_func) (info->stream, "%d", delta << 4);
+	      infprintf (is, "%d", GET_OP_S (l, OFFSET_C) << 4);
 	      break;
 
 	    case 'z':
-	      (*info->fprintf_func) (info->stream, "%s",
-				     mips_gpr_names[(l >> OP_SH_RZ) & OP_MASK_RZ]);
+	      infprintf (is, "%s", mips_gpr_names[GET_OP (l, RZ)]);
 	      break;
 
 	    case 'Z':
-	      (*info->fprintf_func) (info->stream, "%s",
-				     mips_fpr_names[(l >> OP_SH_FZ) & OP_MASK_FZ]);
+	      infprintf (is, "%s", mips_fpr_names[GET_OP (l, FZ)]);
 	      break;
 
 	    default:
 	      /* xgettext:c-format */
-	      (*info->fprintf_func) (info->stream,
-				     _("# internal error, undefined extension sequence (+%c)"),
-				     *d);
+	      infprintf (is,
+			 _("# internal error, "
+			   "undefined extension sequence (+%c)"),
+			 *d);
 	      return;
 	    }
 	  break;
 
 	case '2':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_BP) & OP_MASK_BP);
+	  infprintf (is, "0x%x", GET_OP (l, BP));
 	  break;
 
 	case '3':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_SA3) & OP_MASK_SA3);
+	  infprintf (is, "0x%x", GET_OP (l, SA3));
 	  break;
 
 	case '4':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_SA4) & OP_MASK_SA4);
+	  infprintf (is, "0x%x", GET_OP (l, SA4));
 	  break;
 
 	case '5':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_IMM8) & OP_MASK_IMM8);
+	  infprintf (is, "0x%x", GET_OP (l, IMM8));
 	  break;
 
 	case '6':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_RS) & OP_MASK_RS);
+	  infprintf (is, "0x%x", GET_OP (l, RS));
 	  break;
 
 	case '7':
-	  (*info->fprintf_func) (info->stream, "$ac%ld",
-				 (l >> OP_SH_DSPACC) & OP_MASK_DSPACC);
+	  infprintf (is, "$ac%d", GET_OP (l, DSPACC));
 	  break;
 
 	case '8':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_WRDSP) & OP_MASK_WRDSP);
+	  infprintf (is, "0x%x", GET_OP (l, WRDSP));
 	  break;
 
 	case '9':
-	  (*info->fprintf_func) (info->stream, "$ac%ld",
-				 (l >> OP_SH_DSPACC_S) & OP_MASK_DSPACC_S);
+	  infprintf (is, "$ac%d", GET_OP (l, DSPACC_S));
 	  break;
 
 	case '0': /* dsp 6-bit signed immediate in bit 20 */
-	  delta = ((l >> OP_SH_DSPSFT) & OP_MASK_DSPSFT);
-	  if (delta & 0x20) /* test sign bit */
-	    delta |= ~OP_MASK_DSPSFT;
-	  (*info->fprintf_func) (info->stream, "%d", delta);
+	  infprintf (is, "%d", GET_OP_S (l, DSPSFT));
 	  break;
 
 	case ':': /* dsp 7-bit signed immediate in bit 19 */
-	  delta = ((l >> OP_SH_DSPSFT_7) & OP_MASK_DSPSFT_7);
-	  if (delta & 0x40) /* test sign bit */
-	    delta |= ~OP_MASK_DSPSFT_7;
-	  (*info->fprintf_func) (info->stream, "%d", delta);
+	  infprintf (is, "%d", GET_OP_S (l, DSPSFT_7));
 	  break;
 
 	case '~':
-	  delta = (l >> OP_SH_OFFSET12) & OP_MASK_OFFSET12;
-	  if (delta & 0x800)
-	    delta |= ~0x7ff;
-	  (*info->fprintf_func) (info->stream, "%d", delta);
+	  infprintf (is, "%d", GET_OP_S (l, OFFSET12));
 	  break;
 
 	case '\\':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_3BITPOS) & OP_MASK_3BITPOS);
+	  infprintf (is, "0x%x", GET_OP (l, 3BITPOS));
 	  break;
 
 	case '\'':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_RDDSP) & OP_MASK_RDDSP);
+	  infprintf (is, "0x%x", GET_OP (l, RDDSP));
 	  break;
 
 	case '@': /* dsp 10-bit signed immediate in bit 16 */
-	  delta = ((l >> OP_SH_IMM10) & OP_MASK_IMM10);
-	  if (delta & 0x200) /* test sign bit */
-	    delta |= ~OP_MASK_IMM10;
-	  (*info->fprintf_func) (info->stream, "%d", delta);
+	  infprintf (is, "%d", GET_OP_S (l, IMM10));
 	  break;
 
 	case '!':
-	  (*info->fprintf_func) (info->stream, "%ld",
-				 (l >> OP_SH_MT_U) & OP_MASK_MT_U);
+	  infprintf (is, "%d", GET_OP (l, MT_U));
 	  break;
 
 	case '$':
-	  (*info->fprintf_func) (info->stream, "%ld",
-				 (l >> OP_SH_MT_H) & OP_MASK_MT_H);
+	  infprintf (is, "%d", GET_OP (l, MT_H));
 	  break;
 
 	case '*':
-	  (*info->fprintf_func) (info->stream, "$ac%ld",
-				 (l >> OP_SH_MTACC_T) & OP_MASK_MTACC_T);
+	  infprintf (is, "$ac%d", GET_OP (l, MTACC_T));
 	  break;
 
 	case '&':
-	  (*info->fprintf_func) (info->stream, "$ac%ld",
-				 (l >> OP_SH_MTACC_D) & OP_MASK_MTACC_D);
+	  infprintf (is, "$ac%d", GET_OP (l, MTACC_D));
 	  break;
 
 	case 'g':
 	  /* Coprocessor register for CTTC1, MTTC2, MTHC2, CTTC2.  */
-	  (*info->fprintf_func) (info->stream, "$%ld",
-				 (l >> OP_SH_RD) & OP_MASK_RD);
+	  infprintf (is, "$%d", GET_OP (l, RD));
 	  break;
 
 	case 's':
 	case 'b':
 	case 'r':
 	case 'v':
-	  (*info->fprintf_func) (info->stream, "%s",
-				 mips_gpr_names[(l >> OP_SH_RS) & OP_MASK_RS]);
+	  infprintf (is, "%s", mips_gpr_names[GET_OP (l, RS)]);
 	  break;
 
 	case 't':
 	case 'w':
-	  (*info->fprintf_func) (info->stream, "%s",
-				 mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
+	  infprintf (is, "%s", mips_gpr_names[GET_OP (l, RT)]);
 	  break;
 
 	case 'i':
 	case 'u':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
+	  infprintf (is, "0x%x", GET_OP (l, IMMEDIATE));
 	  break;
 
 	case 'j': /* Same as i, but sign-extended.  */
 	case 'o':
-	  delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
-	  if (delta & 0x8000)
-	    delta |= ~0xffff;
-	  (*info->fprintf_func) (info->stream, "%d",
-				 delta);
+	  infprintf (is, "%d", GET_OP_S (l, DELTA));
 	  break;
 
 	case 'h':
-	  (*info->fprintf_func) (info->stream, "0x%x",
-				 (unsigned int) ((l >> OP_SH_PREFX)
-						 & OP_MASK_PREFX));
+	  infprintf (is, "0x%x", GET_OP (l, PREFX));
 	  break;
 
 	case 'k':
-	  (*info->fprintf_func) (info->stream, "0x%x",
-				 (unsigned int) ((l >> OP_SH_CACHE)
-						 & OP_MASK_CACHE));
+	  infprintf (is, "0x%x", GET_OP (l, CACHE));
 	  break;
 
 	case 'a':
 	  info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
-			  | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2));
+			  | (GET_OP (l, TARGET) << 2));
 	  /* For gdb disassembler, force odd address on jalx.  */
 	  if (info->flavour == bfd_target_unknown_flavour
 	      && strcmp (opp->name, "jalx") == 0)
@@ -1289,97 +1236,80 @@ print_insn_args (const char *d,
 
 	case 'p':
 	  /* Sign extend the displacement.  */
-	  delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
-	  if (delta & 0x8000)
-	    delta |= ~0xffff;
-	  info->target = (delta << 2) + pc + INSNLEN;
+	  info->target = (GET_OP_S (l, DELTA) << 2) + pc + INSNLEN;
 	  (*info->print_address_func) (info->target, info);
 	  break;
 
 	case 'd':
-	  (*info->fprintf_func) (info->stream, "%s",
-				 mips_gpr_names[(l >> OP_SH_RD) & OP_MASK_RD]);
+	  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 = (l >> OP_SH_RD) & OP_MASK_RD;
-	    if (reg == ((l >> OP_SH_RT) & OP_MASK_RT))
-	      (*info->fprintf_func) (info->stream, "%s",
-				     mips_gpr_names[reg]);
+	    unsigned int 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)
-		  (*info->fprintf_func) (info->stream, "%s",
-					 mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
-		else if (((l >> OP_SH_RT) & OP_MASK_RT) == 0)
-		  (*info->fprintf_func) (info->stream, "%s",
-					 mips_gpr_names[reg]);
+		  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.  */
-		  (*info->fprintf_func) (info->stream, "%s or %s",
-					 mips_gpr_names[reg],
-					 mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
+		  infprintf (is, "%s or %s",
+			     mips_gpr_names[reg],
+			     mips_gpr_names[GET_OP (l, RT)]);
 	      }
 	  }
 	  break;
 
 	case 'z':
-	  (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]);
+	  infprintf (is, "%s", mips_gpr_names[0]);
 	  break;
 
 	case '<':
 	case '1':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
+	  infprintf (is, "0x%x", GET_OP (l, SHAMT));
 	  break;
 
 	case 'c':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_CODE) & OP_MASK_CODE);
+	  infprintf (is, "0x%x", GET_OP (l, CODE));
 	  break;
 
 	case 'q':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_CODE2) & OP_MASK_CODE2);
+	  infprintf (is, "0x%x", GET_OP (l, CODE2));
 	  break;
 
 	case 'C':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_COPZ) & OP_MASK_COPZ);
+	  infprintf (is, "0x%x", GET_OP (l, COPZ));
 	  break;
 
 	case 'B':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_CODE20) & OP_MASK_CODE20);
+	  infprintf (is, "0x%x", GET_OP (l, CODE20));
 	  break;
 
 	case 'J':
-	  (*info->fprintf_func) (info->stream, "0x%lx",
-				 (l >> OP_SH_CODE19) & OP_MASK_CODE19);
+	  infprintf (is, "0x%x", GET_OP (l, CODE19));
 	  break;
 
 	case 'S':
 	case 'V':
-	  (*info->fprintf_func) (info->stream, "%s",
-				 mips_fpr_names[(l >> OP_SH_FS) & OP_MASK_FS]);
+	  infprintf (is, "%s", mips_fpr_names[GET_OP (l, FS)]);
 	  break;
 
 	case 'T':
 	case 'W':
-	  (*info->fprintf_func) (info->stream, "%s",
-				 mips_fpr_names[(l >> OP_SH_FT) & OP_MASK_FT]);
+	  infprintf (is, "%s", mips_fpr_names[GET_OP (l, FT)]);
 	  break;
 
 	case 'D':
-	  (*info->fprintf_func) (info->stream, "%s",
-				 mips_fpr_names[(l >> OP_SH_FD) & OP_MASK_FD]);
+	  infprintf (is, "%s", mips_fpr_names[GET_OP (l, FD)]);
 	  break;
 
 	case 'R':
-	  (*info->fprintf_func) (info->stream, "%s",
-				 mips_fpr_names[(l >> OP_SH_FR) & OP_MASK_FR]);
+	  infprintf (is, "%s", mips_fpr_names[GET_OP (l, FR)]);
 	  break;
 
 	case 'E':
@@ -1390,8 +1320,7 @@ print_insn_args (const char *d,
 	     'T' format.  Therefore, until we gain understanding of
 	     cp2 register names, we can simply print the register
 	     numbers.  */
-	  (*info->fprintf_func) (info->stream, "$%ld",
-				 (l >> OP_SH_RT) & OP_MASK_RT);
+	  infprintf (is, "$%d", GET_OP (l, RT));
 	  break;
 
 	case 'G':
@@ -1399,60 +1328,50 @@ print_insn_args (const char *d,
 	     that FPU (cp1) instructions disassemble this field using
 	     'S' format.  Therefore, we only need to worry about cp0,
 	     cp2, and cp3.  */
-	  op = (l >> OP_SH_OP) & OP_MASK_OP;
+	  op = GET_OP (l, OP);
 	  if (op == OP_OP_COP0)
-	    (*info->fprintf_func) (info->stream, "%s",
-				   mips_cp0_names[(l >> OP_SH_RD) & OP_MASK_RD]);
+	    infprintf (is, "%s", mips_cp0_names[GET_OP (l, RD)]);
 	  else
-	    (*info->fprintf_func) (info->stream, "$%ld",
-				   (l >> OP_SH_RD) & OP_MASK_RD);
+	    infprintf (is, "$%d", GET_OP (l, RD));
 	  break;
 
 	case 'K':
-	  (*info->fprintf_func) (info->stream, "%s",
-				 mips_hwr_names[(l >> OP_SH_RD) & OP_MASK_RD]);
+	  infprintf (is, "%s", mips_hwr_names[GET_OP (l, RD)]);
 	  break;
 
 	case 'N':
-	  (*info->fprintf_func) (info->stream,
-				 ((opp->pinfo & (FP_D | FP_S)) != 0
-				  ? "$fcc%ld" : "$cc%ld"),
-				 (l >> OP_SH_BCC) & OP_MASK_BCC);
+	  infprintf (is,
+		     (opp->pinfo & (FP_D | FP_S)) != 0 ? "$fcc%d" : "$cc%d",
+		     GET_OP (l, BCC));
 	  break;
 
 	case 'M':
-	  (*info->fprintf_func) (info->stream, "$fcc%ld",
-				 (l >> OP_SH_CCC) & OP_MASK_CCC);
+	  infprintf (is, "$fcc%d", GET_OP (l, CCC));
 	  break;
 
 	case 'P':
-	  (*info->fprintf_func) (info->stream, "%ld",
-				 (l >> OP_SH_PERFREG) & OP_MASK_PERFREG);
+	  infprintf (is, "%d", GET_OP (l, PERFREG));
 	  break;
 
 	case 'e':
-	  (*info->fprintf_func) (info->stream, "%ld",
-				 (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE);
+	  infprintf (is, "%d", GET_OP (l, VECBYTE));
 	  break;
 
 	case '%':
-	  (*info->fprintf_func) (info->stream, "%ld",
-				 (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN);
+	  infprintf (is, "%d", GET_OP (l, VECALIGN));
 	  break;
 
 	case 'H':
-	  (*info->fprintf_func) (info->stream, "%ld",
-				 (l >> OP_SH_SEL) & OP_MASK_SEL);
+	  infprintf (is, "%d", GET_OP (l, SEL));
 	  break;
 
 	case 'O':
-	  (*info->fprintf_func) (info->stream, "%ld",
-				 (l >> OP_SH_ALN) & OP_MASK_ALN);
+	  infprintf (is, "%d", GET_OP (l, ALN));
 	  break;
 
 	case 'Q':
 	  {
-	    unsigned int vsel = (l >> OP_SH_VSEL) & OP_MASK_VSEL;
+	    unsigned int vsel = GET_OP (l, VSEL);
 
 	    if ((vsel & 0x10) == 0)
 	      {
@@ -1462,43 +1381,34 @@ print_insn_args (const char *d,
 		for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
 		  if ((vsel & 1) == 0)
 		    break;
-		(*info->fprintf_func) (info->stream, "$v%ld[%d]",
-				       (l >> OP_SH_FT) & OP_MASK_FT,
-				       vsel >> 1);
+		infprintf (is, "$v%d[%d]", GET_OP (l, FT), vsel >> 1);
 	      }
 	    else if ((vsel & 0x08) == 0)
 	      {
-		(*info->fprintf_func) (info->stream, "$v%ld",
-				       (l >> OP_SH_FT) & OP_MASK_FT);
+		infprintf (is, "$v%d", GET_OP (l, FT));
 	      }
 	    else
 	      {
-		(*info->fprintf_func) (info->stream, "0x%lx",
-				       (l >> OP_SH_FT) & OP_MASK_FT);
+		infprintf (is, "0x%x", GET_OP (l, FT));
 	      }
 	  }
 	  break;
 
 	case 'X':
-	  (*info->fprintf_func) (info->stream, "$v%ld",
-				 (l >> OP_SH_FD) & OP_MASK_FD);
+	  infprintf (is, "$v%d", GET_OP (l, FD));
 	  break;
 
 	case 'Y':
-	  (*info->fprintf_func) (info->stream, "$v%ld",
-				 (l >> OP_SH_FS) & OP_MASK_FS);
+	  infprintf (is, "$v%d", GET_OP (l, FS));
 	  break;
 
 	case 'Z':
-	  (*info->fprintf_func) (info->stream, "$v%ld",
-				 (l >> OP_SH_FT) & OP_MASK_FT);
+	  infprintf (is, "$v%d", GET_OP (l, FT));
 	  break;
 
 	default:
 	  /* xgettext:c-format */
-	  (*info->fprintf_func) (info->stream,
-				 _("# internal error, undefined modifier (%c)"),
-				 *d);
+	  infprintf (is, _("# internal error, undefined modifier (%c)"), *d);
 	  return;
 	}
     }
@@ -1511,12 +1421,14 @@ print_insn_args (const char *d,
 
 static int
 print_insn_mips (bfd_vma memaddr,
-		 unsigned long int word,
+		 int word,
 		 struct disassemble_info *info)
 {
+  static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
+  const fprintf_ftype infprintf = info->fprintf_func;
   const struct mips_opcode *op;
   static bfd_boolean init = 0;
-  static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
+  void *is = info->stream;
 
   /* Build a hash table to shorten the search time.  */
   if (! init)
@@ -1530,7 +1442,7 @@ print_insn_mips (bfd_vma memaddr,
 	      if (op->pinfo == INSN_MACRO
 		  || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
 		continue;
-	      if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
+	      if (i == GET_OP (op->match, OP))
 		{
 		  mips_hash[i] = op;
 		  break;
@@ -1550,7 +1462,7 @@ print_insn_mips (bfd_vma memaddr,
   info->target = 0;
   info->target2 = 0;
 
-  op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
+  op = mips_hash[GET_OP (word, OP)];
   if (op != NULL)
     {
       for (; op < &mips_opcodes[NUMOPCODES]; op++)
@@ -1589,12 +1501,12 @@ print_insn_mips (bfd_vma memaddr,
 				     | INSN_LOAD_MEMORY_DELAY)) != 0)
 		info->insn_type = dis_dref;
 
-	      (*info->fprintf_func) (info->stream, "%s", op->name);
+	      infprintf (is, "%s", op->name);
 
 	      d = op->args;
 	      if (d != NULL && *d != '\0')
 		{
-		  (*info->fprintf_func) (info->stream, "\t");
+		  infprintf (is, "\t");
 		  print_insn_args (d, word, memaddr, info, op);
 		}
 
@@ -1602,10 +1514,12 @@ print_insn_mips (bfd_vma memaddr,
 	    }
 	}
     }
+#undef GET_OP_S
+#undef GET_OP
 
   /* Handle undefined instructions.  */
   info->insn_type = dis_noninsn;
-  (*info->fprintf_func) (info->stream, "0x%lx", word);
+  infprintf (is, "0x%x", word);
   return INSNLEN;
 }
 
@@ -1620,65 +1534,62 @@ print_mips16_insn_arg (char type,
 		       bfd_vma memaddr,
 		       struct disassemble_info *info)
 {
+  const fprintf_ftype infprintf = info->fprintf_func;
+  void *is = info->stream;
+
+#define GET_OP(insn, field) \
+  (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
+#define GET_OP_S(insn, field) \
+  ((GET_OP (insn, field) ^ ((MIPS16OP_MASK_##field >> 1) + 1)) \
+   - ((MIPS16OP_MASK_##field >> 1) + 1))
   switch (type)
     {
     case ',':
     case '(':
     case ')':
-      (*info->fprintf_func) (info->stream, "%c", type);
+      infprintf (is, "%c", type);
       break;
 
     case 'y':
     case 'w':
-      (*info->fprintf_func) (info->stream, "%s",
-			     mips16_reg_names(((l >> MIPS16OP_SH_RY)
-					       & MIPS16OP_MASK_RY)));
+      infprintf (is, "%s", mips16_reg_names (GET_OP (l, RY)));
       break;
 
     case 'x':
     case 'v':
-      (*info->fprintf_func) (info->stream, "%s",
-			     mips16_reg_names(((l >> MIPS16OP_SH_RX)
-					       & MIPS16OP_MASK_RX)));
+      infprintf (is, "%s", mips16_reg_names (GET_OP (l, RX)));
       break;
 
     case 'z':
-      (*info->fprintf_func) (info->stream, "%s",
-			     mips16_reg_names(((l >> MIPS16OP_SH_RZ)
-					       & MIPS16OP_MASK_RZ)));
+      infprintf (is, "%s", mips16_reg_names (GET_OP (l, RZ)));
       break;
 
     case 'Z':
-      (*info->fprintf_func) (info->stream, "%s",
-			     mips16_reg_names(((l >> MIPS16OP_SH_MOVE32Z)
-					       & MIPS16OP_MASK_MOVE32Z)));
+      infprintf (is, "%s", mips16_reg_names (GET_OP (l, MOVE32Z)));
       break;
 
     case '0':
-      (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]);
+      infprintf (is, "%s", mips_gpr_names[0]);
       break;
 
     case 'S':
-      (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[29]);
+      infprintf (is, "%s", mips_gpr_names[29]);
       break;
 
     case 'P':
-      (*info->fprintf_func) (info->stream, "$pc");
+      infprintf (is, "$pc");
       break;
 
     case 'R':
-      (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[31]);
+      infprintf (is, "%s", mips_gpr_names[31]);
       break;
 
     case 'X':
-      (*info->fprintf_func) (info->stream, "%s",
-			     mips_gpr_names[((l >> MIPS16OP_SH_REGR32)
-					    & MIPS16OP_MASK_REGR32)]);
+      infprintf (is, "%s", mips_gpr_names[GET_OP (l, REGR32)]);
       break;
 
     case 'Y':
-      (*info->fprintf_func) (info->stream, "%s",
-			     mips_gpr_names[MIPS16OP_EXTRACT_REG32R (l)]);
+      infprintf (is, "%s", mips_gpr_names[MIPS16OP_EXTRACT_REG32R (l)]);
       break;
 
     case '<':
@@ -1716,51 +1627,51 @@ print_mips16_insn_arg (char type,
 	  {
 	  case '<':
 	    nbits = 3;
-	    immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
+	    immed = GET_OP (l, RZ);
 	    extbits = 5;
 	    extu = 1;
 	    break;
 	  case '>':
 	    nbits = 3;
-	    immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
+	    immed = GET_OP (l, RX);
 	    extbits = 5;
 	    extu = 1;
 	    break;
 	  case '[':
 	    nbits = 3;
-	    immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
+	    immed = GET_OP (l, RZ);
 	    extbits = 6;
 	    extu = 1;
 	    break;
 	  case ']':
 	    nbits = 3;
-	    immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
+	    immed = GET_OP (l, RX);
 	    extbits = 6;
 	    extu = 1;
 	    break;
 	  case '4':
 	    nbits = 4;
-	    immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
+	    immed = GET_OP (l, IMM4);
 	    signedp = 1;
 	    extbits = 15;
 	    break;
 	  case '5':
 	    nbits = 5;
-	    immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
+	    immed = GET_OP (l, IMM5);
 	    info->insn_type = dis_dref;
 	    info->data_size = 1;
 	    break;
 	  case 'H':
 	    nbits = 5;
 	    shift = 1;
-	    immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
+	    immed = GET_OP (l, IMM5);
 	    info->insn_type = dis_dref;
 	    info->data_size = 2;
 	    break;
 	  case 'W':
 	    nbits = 5;
 	    shift = 2;
-	    immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
+	    immed = GET_OP (l, IMM5);
 	    if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
 		&& (op->pinfo & MIPS16_INSN_READ_SP) == 0)
 	      {
@@ -1771,27 +1682,27 @@ print_mips16_insn_arg (char type,
 	  case 'D':
 	    nbits = 5;
 	    shift = 3;
-	    immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
+	    immed = GET_OP (l, IMM5);
 	    info->insn_type = dis_dref;
 	    info->data_size = 8;
 	    break;
 	  case 'j':
 	    nbits = 5;
-	    immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
+	    immed = GET_OP (l, IMM5);
 	    signedp = 1;
 	    break;
 	  case '6':
 	    nbits = 6;
-	    immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
+	    immed = GET_OP (l, IMM6);
 	    break;
 	  case '8':
 	    nbits = 8;
-	    immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
+	    immed = GET_OP (l, IMM8);
 	    break;
 	  case 'V':
 	    nbits = 8;
 	    shift = 2;
-	    immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
+	    immed = GET_OP (l, IMM8);
 	    /* FIXME: This might be lw, or it might be addiu to $sp or
                $pc.  We assume it's load.  */
 	    info->insn_type = dis_dref;
@@ -1800,36 +1711,36 @@ print_mips16_insn_arg (char type,
 	  case 'C':
 	    nbits = 8;
 	    shift = 3;
-	    immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
+	    immed = GET_OP (l, IMM8);
 	    info->insn_type = dis_dref;
 	    info->data_size = 8;
 	    break;
 	  case 'U':
 	    nbits = 8;
-	    immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
+	    immed = GET_OP (l, IMM8);
 	    extu = 1;
 	    break;
 	  case 'k':
 	    nbits = 8;
-	    immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
+	    immed = GET_OP (l, IMM8);
 	    signedp = 1;
 	    break;
 	  case 'K':
 	    nbits = 8;
 	    shift = 3;
-	    immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
+	    immed = GET_OP (l, IMM8);
 	    signedp = 1;
 	    break;
 	  case 'p':
 	    nbits = 8;
-	    immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
+	    immed = GET_OP (l, IMM8);
 	    signedp = 1;
 	    pcrel = 1;
 	    branch = 1;
 	    break;
 	  case 'q':
 	    nbits = 11;
-	    immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
+	    immed = GET_OP (l, IMM11);
 	    signedp = 1;
 	    pcrel = 1;
 	    branch = 1;
@@ -1837,7 +1748,7 @@ print_mips16_insn_arg (char type,
 	  case 'A':
 	    nbits = 8;
 	    shift = 2;
-	    immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
+	    immed = GET_OP (l, IMM8);
 	    pcrel = 1;
 	    /* FIXME: This can be lw or la.  We assume it is lw.  */
 	    info->insn_type = dis_dref;
@@ -1846,7 +1757,7 @@ print_mips16_insn_arg (char type,
 	  case 'B':
 	    nbits = 5;
 	    shift = 3;
-	    immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
+	    immed = GET_OP (l, IMM5);
 	    pcrel = 1;
 	    info->insn_type = dis_dref;
 	    info->data_size = 8;
@@ -1854,7 +1765,7 @@ print_mips16_insn_arg (char type,
 	  case 'E':
 	    nbits = 5;
 	    shift = 2;
-	    immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
+	    immed = GET_OP (l, IMM5);
 	    pcrel = 1;
 	    break;
 	  default:
@@ -1884,7 +1795,7 @@ print_mips16_insn_arg (char type,
 	  }
 
 	if (! pcrel)
-	  (*info->fprintf_func) (info->stream, "%d", immed);
+	  infprintf (is, "%d", immed);
 	else
 	  {
 	    bfd_vma baseaddr;
@@ -1962,51 +1873,43 @@ print_mips16_insn_arg (char type,
 
 	need_comma = 0;
 
-	l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
+	l = GET_OP (l, IMM6);
 
 	amask = (l >> 3) & 7;
 
 	if (amask > 0 && amask < 5)
 	  {
-	    (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]);
+	    infprintf (is, "%s", mips_gpr_names[4]);
 	    if (amask > 1)
-	      (*info->fprintf_func) (info->stream, "-%s",
-				     mips_gpr_names[amask + 3]);
+	      infprintf (is, "-%s", mips_gpr_names[amask + 3]);
 	    need_comma = 1;
 	  }
 
 	smask = (l >> 1) & 3;
 	if (smask == 3)
 	  {
-	    (*info->fprintf_func) (info->stream, "%s??",
-				   need_comma ? "," : "");
+	    infprintf (is, "%s??", need_comma ? "," : "");
 	    need_comma = 1;
 	  }
 	else if (smask > 0)
 	  {
-	    (*info->fprintf_func) (info->stream, "%s%s",
-				   need_comma ? "," : "",
-				   mips_gpr_names[16]);
+	    infprintf (is, "%s%s", need_comma ? "," : "", mips_gpr_names[16]);
 	    if (smask > 1)
-	      (*info->fprintf_func) (info->stream, "-%s",
-				     mips_gpr_names[smask + 15]);
+	      infprintf (is, "-%s", mips_gpr_names[smask + 15]);
 	    need_comma = 1;
 	  }
 
 	if (l & 1)
 	  {
-	    (*info->fprintf_func) (info->stream, "%s%s",
-				   need_comma ? "," : "",
-				   mips_gpr_names[31]);
+	    infprintf (is, "%s%s", need_comma ? "," : "", mips_gpr_names[31]);
 	    need_comma = 1;
 	  }
 
 	if (amask == 5 || amask == 6)
 	  {
-	    (*info->fprintf_func) (info->stream, "%s$f0",
-				   need_comma ? "," : "");
+	    infprintf (is, "%s$f0", need_comma ? "," : "");
 	    if (amask == 6)
-	      (*info->fprintf_func) (info->stream, "-$f1");
+	      infprintf (is, "-$f1");
 	  }
       }
       break;
@@ -2043,10 +1946,9 @@ print_mips16_insn_arg (char type,
         }
 
       if (args > 0) {
-          (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]);
+	  infprintf (is, "%s", mips_gpr_names[4]);
           if (args > 1)
-            (*info->fprintf_func) (info->stream, "-%s",
-                                   mips_gpr_names[4 + args - 1]);
+	    infprintf (is, "-%s", mips_gpr_names[4 + args - 1]);
           need_comma = 1;
       }
 
@@ -2054,12 +1956,10 @@ print_mips16_insn_arg (char type,
       if (framesz == 0 && !use_extend)
         framesz = 128;
 
-      (*info->fprintf_func) (info->stream, "%s%d", 
-                             need_comma ? "," : "",
-                             framesz);
+      infprintf (is, "%s%d", need_comma ? "," : "", framesz);
 
       if (l & 0x40)                   /* $ra */
-        (*info->fprintf_func) (info->stream, ",%s", mips_gpr_names[31]);
+	infprintf (is, ",%s", mips_gpr_names[31]);
 
       nsreg = (l >> 24) & 0x7;
       smask = 0;
@@ -2075,34 +1975,32 @@ print_mips16_insn_arg (char type,
         {
           if (smask & (1 << i))
             {
-              (*info->fprintf_func) (info->stream, ",%s",
-                                     mips_gpr_names[i == 8 ? 30 : (16 + i)]);
+	      infprintf (is, ",%s", mips_gpr_names[i == 8 ? 30 : (16 + i)]);
               /* Skip over string of set bits.  */
               for (j = i; smask & (2 << j); j++)
                 continue;
               if (j > i)
-                (*info->fprintf_func) (info->stream, "-%s",
-                                       mips_gpr_names[j == 8 ? 30 : (16 + j)]);
+		infprintf (is, "-%s", mips_gpr_names[j == 8 ? 30 : (16 + j)]);
               i = j + 1;
             }
         }
 
       /* Statics $ax - $a3.  */
       if (statics == 1)
-        (*info->fprintf_func) (info->stream, ",%s", mips_gpr_names[7]);
+	infprintf (is, ",%s", mips_gpr_names[7]);
       else if (statics > 0) 
-        (*info->fprintf_func) (info->stream, ",%s-%s", 
-                               mips_gpr_names[7 - statics + 1],
-                               mips_gpr_names[7]);
+	infprintf (is, ",%s-%s",
+		   mips_gpr_names[7 - statics + 1],
+		   mips_gpr_names[7]);
       }
       break;
 
     default:
       /* xgettext:c-format */
-      (*info->fprintf_func)
-	(info->stream,
-	 _("# internal disassembler error, unrecognised modifier (%c)"),
-	 type);
+      infprintf (is,
+		 _("# internal disassembler error, "
+		   "unrecognised modifier (%c)"),
+		 type);
       abort ();
     }
 }
@@ -2112,6 +2010,7 @@ print_mips16_insn_arg (char type,
 static int
 print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
 {
+  const fprintf_ftype infprintf = info->fprintf_func;
   int status;
   bfd_byte buffer[2];
   int length;
@@ -2119,6 +2018,7 @@ print_insn_mips16 (bfd_vma memaddr, stru
   bfd_boolean use_extend;
   int extend = 0;
   const struct mips_opcode *op, *opend;
+  void *is = info->stream;
 
   info->bytes_per_chunk = 2;
   info->display_endian = info->endian;
@@ -2155,8 +2055,7 @@ print_insn_mips16 (bfd_vma memaddr, stru
       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
       if (status != 0)
 	{
-	  (*info->fprintf_func) (info->stream, "extend 0x%x",
-				 (unsigned int) extend);
+	  infprintf (is, "extend 0x%x", (unsigned int) extend);
 	  (*info->memory_error_func) (status, memaddr, info);
 	  return -1;
 	}
@@ -2169,8 +2068,7 @@ print_insn_mips16 (bfd_vma memaddr, stru
       /* Check for an extend opcode followed by an extend opcode.  */
       if ((insn & 0xf800) == 0xf000)
 	{
-	  (*info->fprintf_func) (info->stream, "extend 0x%x",
-				 (unsigned int) extend);
+	  infprintf (is, "extend 0x%x", (unsigned int) extend);
 	  info->insn_type = dis_noninsn;
 	  return length;
 	}
@@ -2193,8 +2091,7 @@ print_insn_mips16 (bfd_vma memaddr, stru
 	    {
 	      if (use_extend)
 		{
-		  (*info->fprintf_func) (info->stream, "extend 0x%x",
-					 (unsigned int) extend);
+		  infprintf (is, "extend 0x%x", (unsigned int) extend);
 		  info->insn_type = dis_noninsn;
 		  return length - 2;
 		}
@@ -2216,16 +2113,15 @@ print_insn_mips16 (bfd_vma memaddr, stru
 		}
 	    }
 
-	  (*info->fprintf_func) (info->stream, "%s", op->name);
+	  infprintf (is, "%s", op->name);
 	  if (op->args[0] != '\0')
-	    (*info->fprintf_func) (info->stream, "\t");
+	    infprintf (is, "\t");
 
 	  for (s = op->args; *s != '\0'; s++)
 	    {
 	      if (*s == ','
 		  && s[1] == 'w'
-		  && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
-		      == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
+		  && GET_OP (insn, RX) == GET_OP (insn, RY))
 		{
 		  /* Skip the register and the comma.  */
 		  ++s;
@@ -2233,8 +2129,7 @@ print_insn_mips16 (bfd_vma memaddr, stru
 		}
 	      if (*s == ','
 		  && s[1] == 'v'
-		  && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
-		      == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
+		  && GET_OP (insn, RZ) == GET_OP (insn, RX))
 		{
 		  /* Skip the register and the comma.  */
 		  ++s;
@@ -2261,10 +2156,12 @@ print_insn_mips16 (bfd_vma memaddr, stru
 	  return length;
 	}
     }
+#undef GET_OP_S
+#undef GET_OP
 
   if (use_extend)
-    (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
-  (*info->fprintf_func) (info->stream, "0x%x", insn);
+    infprintf (is, "0x%x", extend | 0xf000);
+  infprintf (is, "0x%x", insn);
   info->insn_type = dis_noninsn;
 
   return length;
@@ -2375,6 +2272,9 @@ print_insn_micromips (bfd_vma memaddr, s
 
 #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++)
     {
@@ -2401,10 +2301,7 @@ print_insn_micromips (bfd_vma memaddr, s
 		  break;
 
 		case '.':
-		  delta = GET_OP (insn, OFFSET10);
-		  if (delta & 0x200)
-		    delta |= ~0x3ff;
-		  infprintf (is, "%d", delta);
+		  infprintf (is, "%d", GET_OP_S (insn, OFFSET10));
 		  break;
 
 		case '1':
@@ -2461,10 +2358,7 @@ print_insn_micromips (bfd_vma memaddr, s
 		  break;
 
 		case '~':
-		  delta = GET_OP (insn, OFFSET12);
-		  if (delta & 0x800)
-		    delta |= ~0x7ff;
-		  infprintf (is, "%d", delta);
+		  infprintf (is, "%d", GET_OP_S (insn, OFFSET12));
 		  break;
 
 		case 'a':
@@ -2473,7 +2367,7 @@ print_insn_micromips (bfd_vma memaddr, s
 				    | (GET_OP (insn, TARGET) << 2));
 		  else
 		    info->target = (((memaddr + 4) & ~(bfd_vma) 0x07ffffff)
-				    | ((GET_OP (insn, TARGET)) << 1));
+				    | (GET_OP (insn, TARGET) << 1));
 		  /* For gdb disassembler, force odd address on jalx.  */
 		  if (info->flavour == bfd_target_unknown_flavour
 		      && strcmp (op->name, "jalx") == 0)
@@ -2507,8 +2401,7 @@ print_insn_micromips (bfd_vma memaddr, s
 
 		case 'j': /* Same as i, but sign-extended.  */
 		case 'o':
-		  delta = (GET_OP (insn, DELTA) ^ 0x8000) - 0x8000;
-		  infprintf (is, "%d", delta);
+		  infprintf (is, "%d", GET_OP_S (insn, DELTA));
 		  break;
 
 		case 'k':
@@ -2550,7 +2443,7 @@ print_insn_micromips (bfd_vma memaddr, s
 
 		case 'p':
 		  /* Sign-extend the displacement.  */
-		  delta = (GET_OP (insn, DELTA) ^ 0x8000) - 0x8000;
+		  delta = GET_OP_S (insn, DELTA);
 		  info->target = (delta << 1) + memaddr + length;
 		  (*info->print_address_func) (info->target, info);
 		  break;
@@ -2824,7 +2717,7 @@ print_insn_micromips (bfd_vma memaddr, s
 
 		    case 'A':
 		      /* Sign-extend the immediate.  */
-		      immed = ((GET_OP (insn, IMMA) ^ 0x40) - 0x40) << 2;
+		      immed = GET_OP_S (insn, IMMA) << 2;
 		      infprintf (is, "%d", immed);
 		      break;
 
@@ -2840,14 +2733,14 @@ print_insn_micromips (bfd_vma memaddr, s
 
 		    case 'D':
 		      /* Sign-extend the displacement.  */
-		      delta = (GET_OP (insn, IMMD) ^ 0x200) - 0x200;
+		      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 (insn, IMME) ^ 0x40) - 0x40;
+		      delta = GET_OP_S (insn, IMME);
 		      info->target = (delta << 1) + memaddr + length;
 		      (*info->print_address_func) (info->target, info);
 		      break;
@@ -2915,8 +2808,7 @@ print_insn_micromips (bfd_vma memaddr, s
 
 		    case 'Q':
 		      /* Sign-extend the immediate.  */
-		      immed = (GET_OP (insn, IMMQ) ^ 0x400000) - 0x400000;
-		      immed <<= 2;
+		      immed = GET_OP_S (insn, IMMQ) << 2;
 		      infprintf (is, "%d", immed);
 		      break;
 
@@ -2932,16 +2824,15 @@ print_insn_micromips (bfd_vma memaddr, s
 
 		    case 'X':
 		      /* Sign-extend the immediate.  */
-		      immed = (GET_OP (insn, IMMX) ^ 0x8) - 0x8;
+		      immed = GET_OP_S (insn, IMMX);
 		      infprintf (is, "%d", immed);
 		      break;
 
 		    case 'Y':
 		      /* Sign-extend the immediate.  */
-		      immed = (GET_OP (insn, IMMY) ^ 0x100) - 0x100;
-		      if (immed >= -2 && immed <= 1)
-			immed ^= 0x100;
-		      immed = immed << 2;
+		      immed = GET_OP_S (insn, IMMY) << 2;
+		      if ((unsigned int) (immed + 8) < 16)
+			immed ^= 0x400;
 		      infprintf (is, "%d", immed);
 		      break;
 
@@ -2992,6 +2883,7 @@ print_insn_micromips (bfd_vma memaddr, s
 	  return length;
 	}
     }
+#undef GET_OP_S
 #undef GET_OP
 
   infprintf (is, "0x%x", insn);
@@ -3073,12 +2965,12 @@ _print_insn_mips (bfd_vma memaddr,
   status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
   if (status == 0)
     {
-      unsigned long insn;
+      int insn;
 
       if (endianness == BFD_ENDIAN_BIG)
-	insn = (unsigned long) bfd_getb32 (buffer);
+	insn = bfd_getb32 (buffer);
       else
-	insn = (unsigned long) bfd_getl32 (buffer);
+	insn = bfd_getl32 (buffer);
 
       return print_insn_mips (memaddr, insn, info);
     }



More information about the Binutils mailing list