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


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

[mips patch RFA] mips32r2 support.


The patch below adds support for MIPS32 Release 2, a.k.a. mips32r2.

Things to note:

* the syntax for m[tf]hc2 follows the manual, not the existing
  implementation of m[tf]c2.  There's a reasonable argument that says
  given the intent of cp2, the current implementation is not really
  correct for the other cp2 ops, but i don't really care to go there.

* i don't attempt to generally implement support for the 64-bit FP ops
  on mips32r2 CPUs.  There's a big ball of hair there.  (ABI issues,
  and probably lots of assumptions.)  Really, I don't care about that
  case, so I don't want to be the victim who gets to implement that.
  "Hey, if somebody cares, they'll pay to have it done, right?"

* the ELF header flags value used is what the MIPS/Algorithmics folks
  like, and it also happens to be what makes sense to me.

* the disassembly cp0 and hwr array names imply that MIPS32r2 and
  MIPS64r2 (which has been mentioned previously on public tool lists
  by MIPS folks, in case anybody's keeping score 8-) will use the same
  cp0 and register names.  This is a guess, not a statement of fact,
  and is solely based on the fact that MIPS32 and MIPS64 used a common
  set of names.  Given that they did, I would hope that the *r2
  variants will as well.  8-)

* There's an obvious top level config.sub patch that goes with this.
  Once this is approved, I'll submit that to the appropriate
  maintainers.

* I did the "+" operand stuff because i'm hoping to use some more
  operands soon, and would rather make the big diff now.  Plus, I
  don't want to be the guy that runs us out of operand names.  8-)



chris
--
Chris Demetriou                                            Broadcom Corporation
Principal Design Engineer                     Broadband Processor Business Unit
  Any opinions expressed in this message are mine, not necessarily Broadcom's.
--
[ bfd/ChangeLog ]
2002-12-29  Chris Demetriou  <cgd@broadcom.com>

	* aoutx.h (NAME(aout,machine_type)): Add bfd_mach_mipsisa32r2 case.
	* archures.c (bfd_mach_mipsisa32r2): New define.
	* bfd-in2.h: Regenerate.
	* cpu-mips.c (I_mipsisa32r2): New enum value.
	(arch_info_struct): Add entry for I_mipsisa32r2.
	* elfxx-mips.c (elf_mips_isa, _bfd_elf_mips_mach)
	(_bfd_mips_elf_print_private_bfd_data): Handle E_MIPS_ARCH_32R2.
	(_bfd_mips_elf_final_write_processing): Add
	bfd_mach_mipsisa32r2 case.
	(_bfd_mips_elf_merge_private_bfd_data): Handle merging of
	binaries marked as using MIPS32 Release 2.

[ binutils/ChangeLog ]
2002-12-29  Chris Demetriou  <cgd@broadcom.com>

	* doc/binutils.texi (objdump): Note MIPS HWR (Hardware Register)
	changes in MIPS -M options.

[ gas/ChangeLog ]
2002-12-29  Chris Demetriou  <cgd@broadcom.com>

	* configure.in: Recognize mipsisa32r2, mipsisa32r2el, and
	CPU variants.
	* configure: Regenerate.
	* config/tc-mips.c (ISA_HAS_DROR, ISA_HAS_ROR): New defines.
	(macro_build): Handle "K" operand.
	(macro2): Use ISA_HAS_DROR and ISA_HAS_ROR in the places where
	CPU_HAS_DROR and CPU_HAS_ROR are currently used.
	(mips_ip): New variable "lastpos", and implement "+A", "+B",
	and "+C" operands for MIPS32 Release 2 ins/ext instructions.
	Implement "K" operand for MIPS32 Release 2 rdhwr instruction.
	(validate_mips_insn): Implement "+" as a way to extend the
	allowed operands, and implement "K", "+A", "+B", and "+C"
	operands.
	(OPTION_MIPS32R2): New define.
	(md_longopts): Add entry for OPTION_MIPS32R2.
	(OPTION_ELF_BASE): Adjust to accomodate OPTIONS_MIPS32R2.
	(md_parse_option): Handle OPTION_MIPS32R2.
	(s_mipsset): Reimplement handling of ".set mipsN" options
	and add support for ".set mips32r2".
	(mips_cpu_info_table): Add entry for "mips32r2" (MIPS32 Release 2).
	(md_show_usage): Document "-mips32r2" option.
	* doc/as.texinfo: Document "-mips32r2" option.
	* doc/c-mips.texi: Likewise.

[ gas/testsuite/ChangeLog ]
2002-12-29  Chris Demetriou  <cgd@broadcom.com>

	* gas/mips/cp0-names-mips32r2.d: New test.
	* gas/mips/hwr-names-mips32r2.d: New test.
	* gas/mips/hwr-names-numeric.d: New test.
	* gas/mips/hwr-names.s: New test source file.
	* gas/mips/mips32r2.d: New test.
	* gas/mips/mips32r2.s: New test source file.
	* gas/mips/mips32r2-ill.l: New test.
	* gas/mips/mips32r2-ill.s: New test source file.
	* gas/mips/mips.exp: Add mips32r2 architecture data array
	entry.  Run new tests mentioned above.

[ include/elf/ChangeLog ]
2002-12-29  Chris Demetriou  <cgd@broadcom.com>

	* mips.h (E_MIPS_ARCH_32R2): New define.

[ include/opcode/ChangeLog ]
2002-12-29  Chris Demetriou  <cgd@broadcom.com>

	* mips.h: Document "+" as the start of two-character option
	names, and add new "K", "+A", "+B", and "+C" options.
	(OP_MASK_INSMSB, OP_SH_INSMSB, OP_MASK_EXTMSB)
	(OP_SH_EXTMSB, INSN_ISA32R2, ISA_MIPS32R2, CPU_MIPS32R2): New
	defines.

[ opcodes/ChangeLog ]
2002-12-29  Chris Demetriou  <cgd@broadcom.com>

	* mips-dis.c (mips_cp0_names_mips3264r2, mips_hwr_names_numeric)
	(mips_hwr_names_mips3264r2): New arrays.
	(mips_arch_choice): New "hwr_names" member.
	(mips_arch_choices): Adjust for structure change, and add a new
	entry for "mips32r2" ISA.
	(mips_hwr_names): New variable.
	(set_default_mips_dis_options): Set mips_hwr_names.
	(parse_mips_dis_option): New "hwr-names" option which sets
	mips_hwr_names, and adjust "reg-names=ARCH" to set mips_hwr_names.
	(print_insn_arg): Change return type to "int"
	and use that to indicate number of characters consumed.
	Add support for "+" operand extension character, "+A", "+B",
	"+C", and "K" operands.
	(print_insn_mips): Adjust for changes to print_insn_arg.
	(print_mips_disassembler_options): Adjust for "hwr-names"
	addition and "reg-names" change.
	* mips-opc (I33): New define (shorthand for INSN_ISA32R2).
	(mips_builtin_opcodes): Note that "nop" and "ssnop" are special
	forms of "sll".  Add new MIPS32 Release 2 instructions: ehb,
	di, ei, ext, ins, jr.hb, jalr.hb, mfhc1, mfhc2, mthc1, mthc2,
	rdhwr, rdpgpr, seb, seh, synci, wrpgpr, wsbh.
	Note that hardware rotate instructions (ror, rorv) can be
	used on MIPS32 Release 2, and add the official mnemonics
	for them (rotr, rotrv) and the similar "rotl" mnemonic for
	left-rotate.

Index: bfd/aoutx.h
===================================================================
RCS file: /cvs/src/src/bfd/aoutx.h,v
retrieving revision 1.38
diff -u -p -r1.38 aoutx.h
--- bfd/aoutx.h	10 Dec 2002 16:15:27 -0000	1.38
+++ bfd/aoutx.h	29 Dec 2002 08:38:42 -0000
@@ -800,6 +800,7 @@ NAME(aout,machine_type) (arch, machine, 
 	case bfd_mach_mips12000:
 	case bfd_mach_mips16:
 	case bfd_mach_mipsisa32:
+	case bfd_mach_mipsisa32r2:
 	case bfd_mach_mips5:
 	case bfd_mach_mipsisa64:
 	case bfd_mach_mips_sb1:
Index: bfd/archures.c
===================================================================
RCS file: /cvs/src/src/bfd/archures.c,v
retrieving revision 1.61
diff -u -p -r1.61 archures.c
--- bfd/archures.c	23 Dec 2002 10:45:01 -0000	1.61
+++ bfd/archures.c	29 Dec 2002 08:38:42 -0000
@@ -145,6 +145,7 @@ DESCRIPTION
 .#define bfd_mach_mips5                 5
 .#define bfd_mach_mips_sb1              12310201 {* octal 'SB', 01 *}
 .#define bfd_mach_mipsisa32             32
+.#define bfd_mach_mipsisa32r2           33
 .#define bfd_mach_mipsisa64             64
 .  bfd_arch_i386,      {* Intel 386 *}
 .#define bfd_mach_i386_i386 1
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.187
diff -u -p -r1.187 bfd-in2.h
--- bfd/bfd-in2.h	23 Dec 2002 10:45:01 -0000	1.187
+++ bfd/bfd-in2.h	29 Dec 2002 08:38:42 -0000
@@ -1572,6 +1572,7 @@ enum bfd_architecture
 #define bfd_mach_mips5                 5
 #define bfd_mach_mips_sb1              12310201 /* octal 'SB', 01 */
 #define bfd_mach_mipsisa32             32
+#define bfd_mach_mipsisa32r2           33
 #define bfd_mach_mipsisa64             64
   bfd_arch_i386,      /* Intel 386 */
 #define bfd_mach_i386_i386 1
Index: bfd/cpu-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/cpu-mips.c,v
retrieving revision 1.16
diff -u -p -r1.16 cpu-mips.c
--- bfd/cpu-mips.c	30 Nov 2002 08:39:36 -0000	1.16
+++ bfd/cpu-mips.c	29 Dec 2002 08:38:42 -0000
@@ -82,6 +82,7 @@ enum
   I_mips16,
   I_mips5,
   I_mipsisa32,
+  I_mipsisa32r2,
   I_mipsisa64,
   I_sb1,
 };
@@ -111,6 +112,7 @@ static const bfd_arch_info_type arch_inf
   N (64, 64, bfd_mach_mips16,   "mips:16",        FALSE, NN(I_mips16)),
   N (64, 64, bfd_mach_mips5,    "mips:mips5",     FALSE, NN(I_mips5)),
   N (32, 32, bfd_mach_mipsisa32,  "mips:isa32",   FALSE, NN(I_mipsisa32)),
+  N (32, 32, bfd_mach_mipsisa32r2,"mips:isa32r2", FALSE, NN(I_mipsisa32r2)),
   N (64, 64, bfd_mach_mipsisa64,  "mips:isa64",   FALSE, NN(I_mipsisa64)),
   N (64, 64, bfd_mach_mips_sb1, "mips:sb1",       FALSE, 0),
 };
Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.35
diff -u -p -r1.35 elfxx-mips.c
--- bfd/elfxx-mips.c	12 Dec 2002 04:42:06 -0000	1.35
+++ bfd/elfxx-mips.c	29 Dec 2002 08:38:43 -0000
@@ -3102,6 +3102,8 @@ elf_mips_isa (flags)
       return 32;
     case E_MIPS_ARCH_64:
       return 64;
+    case E_MIPS_ARCH_32R2:
+      return 33;
     }
   return 4;
 }
@@ -3172,6 +3174,10 @@ _bfd_elf_mips_mach (flags)
 	case E_MIPS_ARCH_64:
 	  return bfd_mach_mipsisa64;
 	  break;
+
+	case E_MIPS_ARCH_32R2:
+	  return bfd_mach_mipsisa32r2;
+	  break;
 	}
     }
 
@@ -6047,6 +6053,11 @@ _bfd_mips_elf_final_write_processing (ab
 
     case bfd_mach_mipsisa64:
       val = E_MIPS_ARCH_64;
+      break;
+
+    case bfd_mach_mipsisa32r2:
+      val = E_MIPS_ARCH_32R2;
+      break;
     }
 
   elf_elfheader (abfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
@@ -7854,8 +7865,10 @@ _bfd_mips_elf_merge_private_bfd_data (ib
 	     using 64-bit ISAs.  They will normally use the same data sizes
 	     and calling conventions.  */
 
-	  if ((  (new_isa == 1 || new_isa == 2 || new_isa == 32)
-	       ^ (old_isa == 1 || old_isa == 2 || old_isa == 32)) != 0)
+	  if ((  (new_isa == 1 || new_isa == 2 || new_isa == 32
+		  || new_isa == 33)
+	       ^ (old_isa == 1 || old_isa == 2 || old_isa == 32
+		  || old_isa == 33)) != 0)
 	    {
 	      (*_bfd_error_handler)
 	       (_("%s: ISA mismatch (-mips%d) with previous modules (-mips%d)"),
@@ -8005,6 +8018,8 @@ _bfd_mips_elf_print_private_bfd_data (ab
     fprintf (file, _(" [mips32]"));
   else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64)
     fprintf (file, _(" [mips64]"));
+  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2)
+    fprintf (file, _(" [mips32r2]"));
   else
     fprintf (file, _(" [unknown ISA]"));
 
Index: binutils/doc/binutils.texi
===================================================================
RCS file: /cvs/src/src/binutils/doc/binutils.texi,v
retrieving revision 1.27
diff -u -p -r1.27 binutils.texi
--- binutils/doc/binutils.texi	27 Dec 2002 08:00:29 -0000	1.27
+++ binutils/doc/binutils.texi	29 Dec 2002 08:38:44 -0000
@@ -1621,12 +1621,18 @@ as appropriate for the CPU or architectu
 @var{ARCH}.  By default, CP0 register names are selected according to
 the architecture and CPU of the binary being disassembled.
 
+@item hwr-names=@var{ARCH}
+Print HWR (hardware register, used by the @code{rdhwr} instruction) names
+as appropriate for the CPU or architecture specified by
+@var{ARCH}.  By default, HWR names are selected according to
+the architecture and CPU of the binary being disassembled.
+
 @item reg-names=@var{ABI}
 Print GPR and FPR names as appropriate for the selected ABI.
 
 @item reg-names=@var{ARCH}
-Print CPU-specific register names (i.e., only the CP0 register names,
-for now) as appropriate for the selected CPU or architecture.
+Print CPU-specific register names (CP0 register and HWR names)
+as appropriate for the selected CPU or architecture.
 @end table
 
 For any of the options listed above, @var{ABI} or
Index: gas/configure.in
===================================================================
RCS file: /cvs/src/src/gas/configure.in,v
retrieving revision 1.121
diff -u -p -r1.121 configure.in
--- gas/configure.in	11 Nov 2002 17:21:33 -0000	1.121
+++ gas/configure.in	29 Dec 2002 08:38:44 -0000
@@ -518,6 +518,9 @@ changequote([,])dnl
 	  mipsisa32 | mipsisa32el)
 	    mips_cpu=mips32
 	    ;;
+	  mipsisa32r2 | mipsisa32r2el)
+	    mips_cpu=mips32r2
+	    ;;
 	  mipsisa64 | mipsisa64el)
 	    mips_cpu=mips64
 	    ;;
@@ -526,6 +529,11 @@ changequote([,])dnl
 	    ;;
 	  mips64vr | mips64vrel)
 	    mips_cpu=vr4100
+	    ;;
+	  mipsisa32r2*)
+changequote(,)dnl
+	    mips_cpu=`echo $target_cpu | sed -e 's/[a-z]*..r2//' -e 's/el$//'`
+changequote([,])dnl
 	    ;;
 	  mips64* | mipsisa64* | mipsisa32*)
 changequote(,)dnl
Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.184
diff -u -p -r1.184 tc-mips.c
--- gas/config/tc-mips.c	18 Dec 2002 22:52:46 -0000	1.184
+++ gas/config/tc-mips.c	29 Dec 2002 08:38:45 -0000
@@ -260,6 +260,18 @@ static int mips_32bitmode = 0;
    || (ISA) == ISA_MIPS64            \
    )
 
+/* Return true if ISA supports 64-bit right rotate (dror et al.)
+   instructions.  */
+#define ISA_HAS_DROR(ISA) (	\
+   0				\
+   )
+
+/* Return true if ISA supports 32-bit right rotate (ror et al.)
+   instructions.  */
+#define ISA_HAS_ROR(ISA) (	\
+   (ISA) == ISA_MIPS32R2	\
+   )
+
 #define HAVE_32BIT_GPRS		                   \
     (mips_opts.gp32 || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
 
@@ -3010,6 +3022,7 @@ macro_build (place, counter, ep, name, f
 
 	case 'd':
 	case 'G':
+	case 'K':
 	  insn.insn_opcode |= va_arg (args, int) << OP_SH_RD;
 	  continue;
 
@@ -6940,7 +6953,7 @@ macro2 (ip)
       break;
 
     case M_DROL:
-      if (CPU_HAS_DROR (mips_arch))
+      if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
 	{
 	  if (dreg == sreg)
 	    {
@@ -6971,7 +6984,7 @@ macro2 (ip)
       break;
 
     case M_ROL:
-      if (CPU_HAS_ROR (mips_arch))
+      if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
 	{
 	  if (dreg == sreg)
 	    {
@@ -7009,7 +7022,7 @@ macro2 (ip)
 	if (imm_expr.X_op != O_constant)
 	  as_bad (_("Improper rotate count"));
 	rot = imm_expr.X_add_number & 0x3f;
-	if (CPU_HAS_DROR (mips_arch))
+	if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
 	  {
 	    rot = (64 - rot) & 0x3f;
 	    if (rot >= 32)
@@ -7045,7 +7058,7 @@ macro2 (ip)
 	if (imm_expr.X_op != O_constant)
 	  as_bad (_("Improper rotate count"));
 	rot = imm_expr.X_add_number & 0x1f;
-	if (CPU_HAS_ROR (mips_arch))
+	if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
 	  {
 	    macro_build ((char *) NULL, &icnt, NULL, "ror",
 			 "d,w,<", dreg, sreg, (32 - rot) & 0x1f);
@@ -7067,7 +7080,7 @@ macro2 (ip)
       break;
 
     case M_DROR:
-      if (CPU_HAS_DROR (mips_arch))
+      if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
 	{
 	  macro_build ((char *) NULL, &icnt, NULL, "drorv",
 		       "d,t,s", dreg, sreg, treg);
@@ -7084,7 +7097,7 @@ macro2 (ip)
       break;
 
     case M_ROR:
-      if (CPU_HAS_ROR (mips_arch))
+      if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
 	{
 	  macro_build ((char *) NULL, &icnt, NULL, "rorv",
 		       "d,t,s", dreg, sreg, treg);
@@ -7108,7 +7121,7 @@ macro2 (ip)
 	if (imm_expr.X_op != O_constant)
 	  as_bad (_("Improper rotate count"));
 	rot = imm_expr.X_add_number & 0x3f;
-	if (CPU_HAS_DROR (mips_arch))
+	if (ISA_HAS_DROR (mips_opts.isa) || CPU_HAS_DROR (mips_arch))
 	  {
 	    if (rot >= 32)
 	      macro_build ((char *) NULL, &icnt, NULL, "dror32",
@@ -7143,7 +7156,7 @@ macro2 (ip)
 	if (imm_expr.X_op != O_constant)
 	  as_bad (_("Improper rotate count"));
 	rot = imm_expr.X_add_number & 0x1f;
-	if (CPU_HAS_ROR (mips_arch))
+	if (ISA_HAS_ROR (mips_opts.isa) || CPU_HAS_ROR (mips_arch))
 	  {
 	    macro_build ((char *) NULL, &icnt, NULL, "ror",
 			 "d,w,<", dreg, sreg, rot);
@@ -8003,6 +8016,18 @@ validate_mips_insn (opc)
       case ',': break;
       case '(': break;
       case ')': break;
+      case '+':
+    	switch (c = *p++)
+	  {
+	  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;
+	  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;
@@ -8015,6 +8040,7 @@ validate_mips_insn (opc)
       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;
@@ -8089,6 +8115,7 @@ mips_ip (str, ip)
   char *argsStart;
   unsigned int regno;
   unsigned int lastregno = 0;
+  unsigned int lastpos = 0;
   char *s_reset;
   char save_c = 0;
 
@@ -8254,6 +8281,70 @@ mips_ip (str, ip)
 		continue;
 	      break;
 
+	    case '+':		/* Opcode extension character.  */
+	      switch (*++args)
+		{
+		  case 'A':		/* ins/ext "pos".  */
+		    my_getExpression (&imm_expr, s);
+		    check_absolute_expr (ip, &imm_expr);
+		    if ((unsigned long) imm_expr.X_add_number > 31)
+		      {
+			as_bad (_("Improper position (%lu)"),
+				(unsigned long) imm_expr.X_add_number);
+			imm_expr.X_add_number = 0;
+		      }
+		    lastpos = imm_expr.X_add_number;
+		    ip->insn_opcode |= lastpos << OP_SH_SHAMT;
+		    imm_expr.X_op = O_absent;
+		    s = expr_end;
+		    continue;
+
+		  case 'B':		/* "ins" size spec (becomes MSB).  */
+		    my_getExpression (&imm_expr, s);
+		    check_absolute_expr (ip, &imm_expr);
+		    if (imm_expr.X_add_number == 0
+			|| (unsigned long) imm_expr.X_add_number > 32
+			|| ((unsigned long) imm_expr.X_add_number
+			    + lastpos) > 32)
+		      {
+			as_bad (_("Improper insert size (%lu, position %lu)"),
+				(unsigned long) imm_expr.X_add_number,
+				(unsigned long) lastpos);
+			imm_expr.X_add_number &= OP_MASK_INSMSB;
+		      }
+		    ip->insn_opcode |= (lastpos + imm_expr.X_add_number
+					- 1) << OP_SH_INSMSB;
+		    imm_expr.X_op = O_absent;
+		    s = expr_end;
+		    continue;
+
+		  case 'C':		/* "ext" size spec (becomes MSBD).  */
+		    my_getExpression (&imm_expr, s);
+		    check_absolute_expr (ip, &imm_expr);
+		    if (imm_expr.X_add_number == 0
+			|| (unsigned long) imm_expr.X_add_number > 32
+			|| ((unsigned long) imm_expr.X_add_number
+			    + lastpos) > 32)
+		      {
+			as_bad (_("Improper extract size (%lu, position %lu)"),
+				(unsigned long) imm_expr.X_add_number,
+				(unsigned long) lastpos);
+			imm_expr.X_add_number &= OP_MASK_EXTMSBD;
+		      }
+		    ip->insn_opcode |= (imm_expr.X_add_number
+					- 1) << OP_SH_EXTMSBD;
+		    imm_expr.X_op = O_absent;
+		    s = expr_end;
+		    continue;
+
+		default:
+		  as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"),
+		    *args, insn->name, insn->args);
+		  /* Further processing is fruitless.  */
+		  return;
+		}
+	      break;
+
 	    case '<':		/* must be at least one digit */
 	      /*
 	       * According to the manual, if the shift amount is greater
@@ -8391,6 +8482,7 @@ mips_ip (str, ip)
 	    case 'w':		/* both dest and target */
 	    case 'E':		/* coprocessor target register */
 	    case 'G':		/* coprocessor destination register */
+	    case 'K':		/* 'rdhwr' destination register */
 	    case 'x':		/* ignore register name */
 	    case 'z':		/* must be zero register */
 	    case 'U':           /* destination register (clo/clz).  */
@@ -8412,7 +8504,7 @@ mips_ip (str, ip)
 		      if (regno > 31)
 			as_bad (_("Invalid register number (%d)"), regno);
 		    }
-		  else if (*args == 'E' || *args == 'G')
+		  else if (*args == 'E' || *args == 'G' || *args == 'K')
 		    goto notreg;
 		  else
 		    {
@@ -8486,7 +8578,8 @@ mips_ip (str, ip)
 		  if (regno == AT
 		      && ! mips_opts.noat
 		      && *args != 'E'
-		      && *args != 'G')
+		      && *args != 'G'
+		      && *args != 'K')
 		    as_warn (_("Used $at without \".set noat\""));
 		  c = *args;
 		  if (*s == ' ')
@@ -8516,6 +8609,7 @@ mips_ip (str, ip)
 		      break;
 		    case 'd':
 		    case 'G':
+		    case 'K':
 		      ip->insn_opcode |= regno << OP_SH_RD;
 		      break;
 		    case 'U':
@@ -10377,8 +10471,10 @@ struct option md_longopts[] =
 #define OPTION_NO_RELAX_BRANCH (OPTION_MD_BASE + 40)
   {"relax-branch", no_argument, NULL, OPTION_RELAX_BRANCH},
   {"no-relax-branch", no_argument, NULL, OPTION_NO_RELAX_BRANCH},
+#define OPTION_MIPS32R2 (OPTION_MD_BASE + 41)
+  {"mips32r2", no_argument, NULL, OPTION_MIPS32R2},
 #ifdef OBJ_ELF
-#define OPTION_ELF_BASE    (OPTION_MD_BASE + 41)
+#define OPTION_ELF_BASE    (OPTION_MD_BASE + 42)
 #define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0)
   {"KPIC",        no_argument, NULL, OPTION_CALL_SHARED},
   {"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
@@ -10499,6 +10595,10 @@ md_parse_option (c, arg)
       file_mips_isa = ISA_MIPS32;
       break;
 
+    case OPTION_MIPS32R2:
+      file_mips_isa = ISA_MIPS32R2;
+      break;
+
     case OPTION_MIPS64:
       file_mips_isa = ISA_MIPS64;
       break;
@@ -12019,27 +12119,49 @@ s_mipsset (x)
     mips_opts.ase_mdmx = 0;
   else if (strncmp (name, "mips", 4) == 0)
     {
-      int isa;
+      int reset = 0;
 
       /* Permit the user to change the ISA on the fly.  Needless to
 	 say, misuse can cause serious problems.  */
-      isa = atoi (name + 4);
-      switch (isa)
+      if (strcmp (name, "mips0") == 0)
+	{
+	  reset = 1;
+	  mips_opts.isa = file_mips_isa;
+	}
+      else if (strcmp (name, "mips1") == 0)
+	mips_opts.isa = ISA_MIPS1;
+      else if (strcmp (name, "mips2") == 0)
+	mips_opts.isa = ISA_MIPS2;
+      else if (strcmp (name, "mips3") == 0)
+	mips_opts.isa = ISA_MIPS3;
+      else if (strcmp (name, "mips4") == 0)
+	mips_opts.isa = ISA_MIPS4;
+      else if (strcmp (name, "mips5") == 0)
+	mips_opts.isa = ISA_MIPS5;
+      else if (strcmp (name, "mips32") == 0)
+	mips_opts.isa = ISA_MIPS32;
+      else if (strcmp (name, "mips32r2") == 0)
+	mips_opts.isa = ISA_MIPS32R2;
+      else if (strcmp (name, "mips64") == 0)
+	mips_opts.isa = ISA_MIPS64;
+      else
+	as_bad (_("unknown ISA level %s"), name + 4);
+
+      switch (mips_opts.isa)
 	{
 	case  0:
-	  mips_opts.gp32 = file_mips_gp32;
-	  mips_opts.fp32 = file_mips_fp32;
 	  break;
-	case  1:
-	case  2:
-	case 32:
+	case ISA_MIPS1:
+	case ISA_MIPS2:
+	case ISA_MIPS32:
+	case ISA_MIPS32R2:
 	  mips_opts.gp32 = 1;
 	  mips_opts.fp32 = 1;
 	  break;
-	case  3:
-	case  4:
-	case  5:
-	case 64:
+	case ISA_MIPS3:
+	case ISA_MIPS4:
+	case ISA_MIPS5:
+	case ISA_MIPS64:
 	  mips_opts.gp32 = 0;
 	  mips_opts.fp32 = 0;
 	  break;
@@ -12047,18 +12169,10 @@ s_mipsset (x)
 	  as_bad (_("unknown ISA level %s"), name + 4);
 	  break;
 	}
-
-      switch (isa)
+      if (reset)
 	{
-	case  0: mips_opts.isa = file_mips_isa;   break;
-	case  1: mips_opts.isa = ISA_MIPS1;       break;
-	case  2: mips_opts.isa = ISA_MIPS2;       break;
-	case  3: mips_opts.isa = ISA_MIPS3;       break;
-	case  4: mips_opts.isa = ISA_MIPS4;       break;
-	case  5: mips_opts.isa = ISA_MIPS5;       break;
-	case 32: mips_opts.isa = ISA_MIPS32;      break;
-	case 64: mips_opts.isa = ISA_MIPS64;      break;
-	default: as_bad (_("unknown ISA level %s"), name + 4); break;
+	  mips_opts.gp32 = file_mips_gp32;
+	  mips_opts.fp32 = file_mips_fp32;
 	}
     }
   else if (strcmp (name, "autoextend") == 0)
@@ -14360,6 +14474,7 @@ static const struct mips_cpu_info mips_c
   { "mips4",          1,      ISA_MIPS4,      CPU_R8000 },
   { "mips5",          1,      ISA_MIPS5,      CPU_MIPS5 },
   { "mips32",         1,      ISA_MIPS32,     CPU_MIPS32 },
+  { "mips32r2",       1,      ISA_MIPS32R2,   CPU_MIPS32R2 },
   { "mips64",         1,      ISA_MIPS64,     CPU_MIPS64 },
 
   /* MIPS I */
@@ -14586,6 +14701,7 @@ MIPS options:\n\
 -mips4			generate MIPS ISA IV instructions\n\
 -mips5                  generate MIPS ISA V instructions\n\
 -mips32                 generate MIPS32 ISA instructions\n\
+-mips32r2               generate MIPS32 release 2 ISA instructions\n\
 -mips64                 generate MIPS64 ISA instructions\n\
 -march=CPU/-mtune=CPU	generate code/schedule for CPU, where CPU is one of:\n"));
 
Index: gas/doc/as.texinfo
===================================================================
RCS file: /cvs/src/src/gas/doc/as.texinfo,v
retrieving revision 1.72
diff -u -p -r1.72 as.texinfo
--- gas/doc/as.texinfo	19 Dec 2002 05:47:44 -0000	1.72
+++ gas/doc/as.texinfo	29 Dec 2002 08:38:46 -0000
@@ -383,7 +383,8 @@ gcc(1), ld(1), and the Info entries for 
    [@b{-non_shared}] [@b{-xgot}] [@b{--membedded-pic}]
    [@b{-mabi}=@var{ABI}] [@b{-32}] [@b{-n32}] [@b{-64}] [@b{-mfp32}] [@b{-mgp32}]
    [@b{-march}=@var{CPU}] [@b{-mtune}=@var{CPU}] [@b{-mips1}] [@b{-mips2}]
-   [@b{-mips3}] [@b{-mips4}] [@b{-mips5}] [@b{-mips32}] [@b{-mips64}]
+   [@b{-mips3}] [@b{-mips4}] [@b{-mips5}] [@b{-mips32}] [@b{-mips32r2}]
+   [@b{-mips64}]
    [@b{-construct-floats}] [@b{-no-construct-floats}]
    [@b{-trap}] [@b{-no-break}] [@b{-break}] [@b{-no-trap}]
    [@b{-mfix7000}] [@b{-mno-fix7000}]
@@ -909,13 +910,16 @@ Generate ``little endian'' format output
 @itemx -mips4
 @itemx -mips5
 @itemx -mips32
+@itemx -mips32r2
 @itemx -mips64
 Generate code for a particular @sc{mips} Instruction Set Architecture level.
 @samp{-mips1} is an alias for @samp{-march=r3000}, @samp{-mips2} is an
 alias for @samp{-march=r6000}, @samp{-mips3} is an alias for
 @samp{-march=r4000} and @samp{-mips4} is an alias for @samp{-march=r8000}.
-@samp{-mips5}, @samp{-mips32}, and @samp{-mips64} correspond to generic
-@samp{MIPS V}, @samp{MIPS32}, and @samp{MIPS64} ISA processors,
+@samp{-mips5}, @samp{-mips32}, @samp{-mips32r2}, and @samp{-mips64}
+correspond to generic
+@samp{MIPS V}, @samp{MIPS32}, @samp{MIPS32 Release 2}, and
+@samp{MIPS64} ISA processors,
 respectively.
 
 @item -march=@var{CPU}
Index: gas/doc/c-mips.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-mips.texi,v
retrieving revision 1.24
diff -u -p -r1.24 c-mips.texi
--- gas/doc/c-mips.texi	30 Sep 2002 12:04:31 -0000	1.24
+++ gas/doc/c-mips.texi	29 Dec 2002 08:38:46 -0000
@@ -65,13 +65,15 @@ to select big-endian output, and @samp{-
 @itemx -mips4
 @itemx -mips5
 @itemx -mips32
+@itemx -mips32r2
 @itemx -mips64
 Generate code for a particular MIPS Instruction Set Architecture level.
 @samp{-mips1} corresponds to the @sc{r2000} and @sc{r3000} processors,
 @samp{-mips2} to the @sc{r6000} processor, @samp{-mips3} to the
 @sc{r4000} processor, and @samp{-mips4} to the @sc{r8000} and
-@sc{r10000} processors.  @samp{-mips5}, @samp{-mips32}, and
-@samp{-mips64} correspond to generic @sc{MIPS V}, @sc{MIPS32}, and
+@sc{r10000} processors.  @samp{-mips5}, @samp{-mips32}, @samp{-mips32r2}, and
+@samp{-mips64} correspond to generic @sc{MIPS V}, @sc{MIPS32},
+@sc{MIPS32 Release 2}, and
 @sc{MIPS64} ISA processors, respectively.  You can also switch
 instruction sets during the assembly; see @ref{MIPS ISA, Directives to
 override the ISA level}.
Index: gas/testsuite/gas/mips/cp0-names-mips32r2.d
===================================================================
RCS file: gas/testsuite/gas/mips/cp0-names-mips32r2.d
diff -N gas/testsuite/gas/mips/cp0-names-mips32r2.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/cp0-names-mips32r2.d	29 Dec 2002 08:38:48 -0000
@@ -0,0 +1,42 @@
+#objdump: -dr --prefix-addresses --show-raw-insn -M gpr-names=numeric,cp0-names=mips32r2
+#name: MIPS CP0 register disassembly (mips32r2)
+#source: cp0-names.s
+
+# Check objdump's handling of -M cp0-names=foo options.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> 40800000 	mtc0	\$0,c0_index
+0+0004 <[^>]*> 40800800 	mtc0	\$0,c0_random
+0+0008 <[^>]*> 40801000 	mtc0	\$0,c0_entrylo0
+0+000c <[^>]*> 40801800 	mtc0	\$0,c0_entrylo1
+0+0010 <[^>]*> 40802000 	mtc0	\$0,c0_context
+0+0014 <[^>]*> 40802800 	mtc0	\$0,c0_pagemask
+0+0018 <[^>]*> 40803000 	mtc0	\$0,c0_wired
+0+001c <[^>]*> 40803800 	mtc0	\$0,c0_hwrena
+0+0020 <[^>]*> 40804000 	mtc0	\$0,c0_badvaddr
+0+0024 <[^>]*> 40804800 	mtc0	\$0,c0_count
+0+0028 <[^>]*> 40805000 	mtc0	\$0,c0_entryhi
+0+002c <[^>]*> 40805800 	mtc0	\$0,c0_compare
+0+0030 <[^>]*> 40806000 	mtc0	\$0,c0_status
+0+0034 <[^>]*> 40806800 	mtc0	\$0,c0_cause
+0+0038 <[^>]*> 40807000 	mtc0	\$0,c0_epc
+0+003c <[^>]*> 40807800 	mtc0	\$0,c0_prid
+0+0040 <[^>]*> 40808000 	mtc0	\$0,c0_config
+0+0044 <[^>]*> 40808800 	mtc0	\$0,c0_lladdr
+0+0048 <[^>]*> 40809000 	mtc0	\$0,c0_watchlo
+0+004c <[^>]*> 40809800 	mtc0	\$0,c0_watchhi
+0+0050 <[^>]*> 4080a000 	mtc0	\$0,c0_xcontext
+0+0054 <[^>]*> 4080a800 	mtc0	\$0,\$21
+0+0058 <[^>]*> 4080b000 	mtc0	\$0,\$22
+0+005c <[^>]*> 4080b800 	mtc0	\$0,c0_debug
+0+0060 <[^>]*> 4080c000 	mtc0	\$0,c0_depc
+0+0064 <[^>]*> 4080c800 	mtc0	\$0,c0_perfcnt
+0+0068 <[^>]*> 4080d000 	mtc0	\$0,c0_errctl
+0+006c <[^>]*> 4080d800 	mtc0	\$0,c0_cacheerr
+0+0070 <[^>]*> 4080e000 	mtc0	\$0,c0_taglo
+0+0074 <[^>]*> 4080e800 	mtc0	\$0,c0_taghi
+0+0078 <[^>]*> 4080f000 	mtc0	\$0,c0_errorepc
+0+007c <[^>]*> 4080f800 	mtc0	\$0,c0_desave
+	\.\.\.
Index: gas/testsuite/gas/mips/hwr-names-mips32r2.d
===================================================================
RCS file: gas/testsuite/gas/mips/hwr-names-mips32r2.d
diff -N gas/testsuite/gas/mips/hwr-names-mips32r2.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/hwr-names-mips32r2.d	29 Dec 2002 08:38:48 -0000
@@ -0,0 +1,43 @@
+#objdump: -dr --prefix-addresses --show-raw-insn -mmips:isa32r2 -M gpr-names=numeric,hwr-names=mips32r2
+#name: MIPS HWR disassembly (mips32r2)
+#as: -mips32r2
+#source: hwr-names.s
+
+# Check objdump's handling of -M hwr-names=foo options.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> 7c00003b 	rdhwr	\$0,hwr_cpunum
+0+0004 <[^>]*> 7c00083b 	rdhwr	\$0,hwr_synci_step
+0+0008 <[^>]*> 7c00103b 	rdhwr	\$0,hwr_cc
+0+000c <[^>]*> 7c00183b 	rdhwr	\$0,hwr_ccres
+0+0010 <[^>]*> 7c00203b 	rdhwr	\$0,\$4
+0+0014 <[^>]*> 7c00283b 	rdhwr	\$0,\$5
+0+0018 <[^>]*> 7c00303b 	rdhwr	\$0,\$6
+0+001c <[^>]*> 7c00383b 	rdhwr	\$0,\$7
+0+0020 <[^>]*> 7c00403b 	rdhwr	\$0,\$8
+0+0024 <[^>]*> 7c00483b 	rdhwr	\$0,\$9
+0+0028 <[^>]*> 7c00503b 	rdhwr	\$0,\$10
+0+002c <[^>]*> 7c00583b 	rdhwr	\$0,\$11
+0+0030 <[^>]*> 7c00603b 	rdhwr	\$0,\$12
+0+0034 <[^>]*> 7c00683b 	rdhwr	\$0,\$13
+0+0038 <[^>]*> 7c00703b 	rdhwr	\$0,\$14
+0+003c <[^>]*> 7c00783b 	rdhwr	\$0,\$15
+0+0040 <[^>]*> 7c00803b 	rdhwr	\$0,\$16
+0+0044 <[^>]*> 7c00883b 	rdhwr	\$0,\$17
+0+0048 <[^>]*> 7c00903b 	rdhwr	\$0,\$18
+0+004c <[^>]*> 7c00983b 	rdhwr	\$0,\$19
+0+0050 <[^>]*> 7c00a03b 	rdhwr	\$0,\$20
+0+0054 <[^>]*> 7c00a83b 	rdhwr	\$0,\$21
+0+0058 <[^>]*> 7c00b03b 	rdhwr	\$0,\$22
+0+005c <[^>]*> 7c00b83b 	rdhwr	\$0,\$23
+0+0060 <[^>]*> 7c00c03b 	rdhwr	\$0,\$24
+0+0064 <[^>]*> 7c00c83b 	rdhwr	\$0,\$25
+0+0068 <[^>]*> 7c00d03b 	rdhwr	\$0,\$26
+0+006c <[^>]*> 7c00d83b 	rdhwr	\$0,\$27
+0+0070 <[^>]*> 7c00e03b 	rdhwr	\$0,\$28
+0+0074 <[^>]*> 7c00e83b 	rdhwr	\$0,\$29
+0+0078 <[^>]*> 7c00f03b 	rdhwr	\$0,\$30
+0+007c <[^>]*> 7c00f83b 	rdhwr	\$0,\$31
+	\.\.\.
Index: gas/testsuite/gas/mips/hwr-names-numeric.d
===================================================================
RCS file: gas/testsuite/gas/mips/hwr-names-numeric.d
diff -N gas/testsuite/gas/mips/hwr-names-numeric.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/hwr-names-numeric.d	29 Dec 2002 08:38:48 -0000
@@ -0,0 +1,43 @@
+#objdump: -dr --prefix-addresses --show-raw-insn -mmips:isa32r2 -M gpr-names=numeric,hwr-names=numeric
+#name: MIPS HWR disassembly (numeric)
+#as: -mips32r2
+#source: hwr-names.s
+
+# Check objdump's handling of -M hwr-names=foo options.
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> 7c00003b 	rdhwr	\$0,\$0
+0+0004 <[^>]*> 7c00083b 	rdhwr	\$0,\$1
+0+0008 <[^>]*> 7c00103b 	rdhwr	\$0,\$2
+0+000c <[^>]*> 7c00183b 	rdhwr	\$0,\$3
+0+0010 <[^>]*> 7c00203b 	rdhwr	\$0,\$4
+0+0014 <[^>]*> 7c00283b 	rdhwr	\$0,\$5
+0+0018 <[^>]*> 7c00303b 	rdhwr	\$0,\$6
+0+001c <[^>]*> 7c00383b 	rdhwr	\$0,\$7
+0+0020 <[^>]*> 7c00403b 	rdhwr	\$0,\$8
+0+0024 <[^>]*> 7c00483b 	rdhwr	\$0,\$9
+0+0028 <[^>]*> 7c00503b 	rdhwr	\$0,\$10
+0+002c <[^>]*> 7c00583b 	rdhwr	\$0,\$11
+0+0030 <[^>]*> 7c00603b 	rdhwr	\$0,\$12
+0+0034 <[^>]*> 7c00683b 	rdhwr	\$0,\$13
+0+0038 <[^>]*> 7c00703b 	rdhwr	\$0,\$14
+0+003c <[^>]*> 7c00783b 	rdhwr	\$0,\$15
+0+0040 <[^>]*> 7c00803b 	rdhwr	\$0,\$16
+0+0044 <[^>]*> 7c00883b 	rdhwr	\$0,\$17
+0+0048 <[^>]*> 7c00903b 	rdhwr	\$0,\$18
+0+004c <[^>]*> 7c00983b 	rdhwr	\$0,\$19
+0+0050 <[^>]*> 7c00a03b 	rdhwr	\$0,\$20
+0+0054 <[^>]*> 7c00a83b 	rdhwr	\$0,\$21
+0+0058 <[^>]*> 7c00b03b 	rdhwr	\$0,\$22
+0+005c <[^>]*> 7c00b83b 	rdhwr	\$0,\$23
+0+0060 <[^>]*> 7c00c03b 	rdhwr	\$0,\$24
+0+0064 <[^>]*> 7c00c83b 	rdhwr	\$0,\$25
+0+0068 <[^>]*> 7c00d03b 	rdhwr	\$0,\$26
+0+006c <[^>]*> 7c00d83b 	rdhwr	\$0,\$27
+0+0070 <[^>]*> 7c00e03b 	rdhwr	\$0,\$28
+0+0074 <[^>]*> 7c00e83b 	rdhwr	\$0,\$29
+0+0078 <[^>]*> 7c00f03b 	rdhwr	\$0,\$30
+0+007c <[^>]*> 7c00f83b 	rdhwr	\$0,\$31
+	\.\.\.
Index: gas/testsuite/gas/mips/hwr-names.s
===================================================================
RCS file: gas/testsuite/gas/mips/hwr-names.s
diff -N gas/testsuite/gas/mips/hwr-names.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/hwr-names.s	29 Dec 2002 08:38:48 -0000
@@ -0,0 +1,44 @@
+# source file to test objdump's disassembly using various styles of
+# HWR (hardware register) names.
+
+	.set noreorder
+	.set noat
+
+	.globl text_label .text
+text_label:
+
+	rdhwr	$0, $0
+	rdhwr	$0, $1
+	rdhwr	$0, $2
+	rdhwr	$0, $3
+	rdhwr	$0, $4
+	rdhwr	$0, $5
+	rdhwr	$0, $6
+	rdhwr	$0, $7
+	rdhwr	$0, $8
+	rdhwr	$0, $9
+	rdhwr	$0, $10
+	rdhwr	$0, $11
+	rdhwr	$0, $12
+	rdhwr	$0, $13
+	rdhwr	$0, $14
+	rdhwr	$0, $15
+	rdhwr	$0, $16
+	rdhwr	$0, $17
+	rdhwr	$0, $18
+	rdhwr	$0, $19
+	rdhwr	$0, $20
+	rdhwr	$0, $21
+	rdhwr	$0, $22
+	rdhwr	$0, $23
+	rdhwr	$0, $24
+	rdhwr	$0, $25
+	rdhwr	$0, $26
+	rdhwr	$0, $27
+	rdhwr	$0, $28
+	rdhwr	$0, $29
+	rdhwr	$0, $30
+	rdhwr	$0, $31
+
+# Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...
+      .space  8
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.54
diff -u -p -r1.54 mips.exp
--- gas/testsuite/gas/mips/mips.exp	27 Dec 2002 23:51:48 -0000	1.54
+++ gas/testsuite/gas/mips/mips.exp	29 Dec 2002 08:38:48 -0000
@@ -343,6 +343,10 @@ mips_arch_create mips5 	64	mips4	{} \
 mips_arch_create mips32	32	mips2	{} \
 			{ -march=mips32 -mtune=mips32 } { -mmips:isa32 } \
 			{ mipsisa32-*-* mipsisa32el-*-* }
+mips_arch_create mips32r2 32	mips32	{ ror } \
+			{ -march=mips32r2 -mtune=mips32r2 } \
+			{ -mmips:isa32r2 } \
+			{ mipsisa32r2-*-* mipsisa32r2el-*-* }
 mips_arch_create mips64	64	mips5	{ mips32 } \
 			{ -march=mips64 -mtune=mips64 } { -mmips:isa64 } \
 			{ mipsisa64-*-* mipsisa64el-*-* }
@@ -522,6 +526,9 @@ if { [istarget mips*-*-*] } then {
 
     run_dump_test_arches "mips32"	[mips_arch_list_matching mips32]
 
+    run_dump_test_arches "mips32r2"	[mips_arch_list_matching mips32r2]
+    run_list_test_arches "mips32r2-ill" "" [mips_arch_list_matching mips32r2]
+
     run_dump_test_arches "mips64"	[mips_arch_list_matching mips64]
 
     run_dump_test "mips64-mips3d"
@@ -610,6 +617,10 @@ if { [istarget mips*-*-*] } then {
 
     run_dump_test "cp0-names-numeric"
     run_dump_test "cp0-names-mips32"
+    run_dump_test "cp0-names-mips32r2"
     run_dump_test "cp0-names-mips64"
     run_dump_test "cp0-names-sb1"
+
+    run_dump_test "hwr-names-numeric"
+    run_dump_test "hwr-names-mips32r2"
 }
Index: gas/testsuite/gas/mips/mips32r2-ill.l
===================================================================
RCS file: gas/testsuite/gas/mips/mips32r2-ill.l
diff -N gas/testsuite/gas/mips/mips32r2-ill.l
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips32r2-ill.l	29 Dec 2002 08:38:48 -0000
@@ -0,0 +1,15 @@
+.*: Assembler messages:
+.*:12: Error: Improper position \([0-9]*\)
+.*:15: Error: Improper position \(32\)
+.*:18: Error: Improper extract size \(0, position 0\)
+.*:21: Error: Improper extract size \(33, position 0\)
+.*:24: Error: Improper extract size \(0, position 0\)
+.*:27: Error: Improper extract size \(2, position 31\)
+.*:30: Error: Improper position \([0-9]*\)
+.*:33: Error: Improper position \(32\)
+.*:36: Error: Improper insert size \(0, position 0\)
+.*:39: Error: Improper insert size \(33, position 0\)
+.*:42: Error: Improper insert size \(0, position 0\)
+.*:45: Error: Improper insert size \(2, position 31\)
+.*:54: Warning: Float register should be even, was 1
+.*:57: Warning: Float register should be even, was 1
Index: gas/testsuite/gas/mips/mips32r2-ill.s
===================================================================
RCS file: gas/testsuite/gas/mips/mips32r2-ill.s
diff -N gas/testsuite/gas/mips/mips32r2-ill.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips32r2-ill.s	29 Dec 2002 08:38:48 -0000
@@ -0,0 +1,60 @@
+# source file to test illegal mips32r2 instructions
+
+        .set noreorder
+      .set noat
+
+      .text
+text_label:
+
+      # insert and extract position/size checks:
+
+	# ext constraint: 0 <= pos < 32
+	ext	$4, $5, -1, 1		# error
+	ext	$4, $5, 0, 1
+	ext	$4, $5, 31, 1
+	ext	$4, $5, 32, 1		# error
+
+	# ext constraint: 0 < size <= 32
+	ext	$4, $5, 0, 0		# error
+	ext	$4, $5, 0, 1
+	ext	$4, $5, 0, 32
+	ext	$4, $5, 0, 33		# error
+
+	# ext constraint: 0 < (pos+size) <= 32
+	ext	$4, $5, 0, 0		# error
+	ext	$4, $5, 0, 1
+	ext	$4, $5, 31, 1
+	ext	$4, $5, 31, 2		# error
+
+	# ins constraint: 0 <= pos < 32
+	ins	$4, $5, -1, 1		# error
+	ins	$4, $5, 0, 1
+	ins	$4, $5, 31, 1
+	ins	$4, $5, 32, 1		# error
+
+	# ins constraint: 0 < size <= 32
+	ins	$4, $5, 0, 0		# error
+	ins	$4, $5, 0, 1
+	ins	$4, $5, 0, 32
+	ins	$4, $5, 0, 33		# error
+
+	# ins constraint: 0 < (pos+size) <= 32
+	ins	$4, $5, 0, 0		# error
+	ins	$4, $5, 0, 1
+	ins	$4, $5, 31, 1
+	ins	$4, $5, 31, 2		# error
+
+      # FP register checks.
+      #
+      # Even registers are supported w/ 32-bit FPU, odd
+      # registers supported only for 64-bit FPU.
+      # This file tests 32-bit FPU.
+     
+	mfhc1	$17, $f0
+	mfhc1	$17, $f1		# warn
+
+	mthc1	$17, $f0
+	mthc1	$17, $f1		# warn
+
+# Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...
+	.space  8
Index: gas/testsuite/gas/mips/mips32r2.d
===================================================================
RCS file: gas/testsuite/gas/mips/mips32r2.d
diff -N gas/testsuite/gas/mips/mips32r2.d
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips32r2.d	29 Dec 2002 08:38:48 -0000
@@ -0,0 +1,46 @@
+#objdump: -dr --prefix-addresses --show-raw-insn -M reg-names=numeric
+#name: MIPS MIPS32r2 instructions
+
+# Check MIPS32 instruction assembly
+
+.*: +file format .*mips.*
+
+Disassembly of section .text:
+0+0000 <[^>]*> 000000c0 	ehb
+0+0004 <[^>]*> 7ca43980 	ext	\$4,\$5,0x6,0x8
+0+0008 <[^>]*> 7ca46984 	ins	\$4,\$5,0x6,0x8
+0+000c <[^>]*> 0100fc09 	jalr.hb	\$8
+0+0010 <[^>]*> 0120a409 	jalr.hb	\$20,\$9
+0+0014 <[^>]*> 01000408 	jr.hb	\$8
+0+0018 <[^>]*> 7c0a003b 	rdhwr	\$10,\$0
+0+001c <[^>]*> 7c0b083b 	rdhwr	\$11,\$1
+0+0020 <[^>]*> 7c0c103b 	rdhwr	\$12,\$2
+0+0024 <[^>]*> 7c0d183b 	rdhwr	\$13,\$3
+0+0028 <[^>]*> 7c0e203b 	rdhwr	\$14,\$4
+0+002c <[^>]*> 7c0f283b 	rdhwr	\$15,\$5
+0+0030 <[^>]*> 002acf02 	ror	\$25,\$10,0x1c
+0+0034 <[^>]*> 002ac902 	ror	\$25,\$10,0x4
+0+0038 <[^>]*> 0004c823 	negu	\$25,\$4
+0+003c <[^>]*> 032ac846 	rorv	\$25,\$10,\$25
+0+0040 <[^>]*> 008ac846 	rorv	\$25,\$10,\$4
+0+0044 <[^>]*> 008ac846 	rorv	\$25,\$10,\$4
+0+0048 <[^>]*> 7c073c20 	seb	\$7,\$7
+0+004c <[^>]*> 7c0a4420 	seb	\$8,\$10
+0+0050 <[^>]*> 7c073e20 	seh	\$7,\$7
+0+0054 <[^>]*> 7c0a4620 	seh	\$8,\$10
+0+0058 <[^>]*> 055f5555 	synci	21845\(\$10\)
+0+005c <[^>]*> 7c0738a0 	wsbh	\$7,\$7
+0+0060 <[^>]*> 7c0a40a0 	wsbh	\$8,\$10
+0+0064 <[^>]*> 41606000 	di
+0+0068 <[^>]*> 41606000 	di
+0+006c <[^>]*> 416a6000 	di	\$10
+0+0070 <[^>]*> 41606020 	ei
+0+0074 <[^>]*> 41606020 	ei
+0+0078 <[^>]*> 416a6020 	ei	\$10
+0+007c <[^>]*> 41595000 	rdpgpr	\$10,\$25
+0+0080 <[^>]*> 41d95000 	wrpgpr	\$10,\$25
+0+0084 <[^>]*> 44710000 	mfhc1	\$17,\$f0
+0+0088 <[^>]*> 44f10000 	mthc1	\$17,\$f0
+0+008c <[^>]*> 48715555 	mfhc2	\$17,0x5555
+0+0090 <[^>]*> 48f15555 	mthc2	\$17,0x5555
+	...
Index: gas/testsuite/gas/mips/mips32r2.s
===================================================================
RCS file: gas/testsuite/gas/mips/mips32r2.s
diff -N gas/testsuite/gas/mips/mips32r2.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/mips/mips32r2.s	29 Dec 2002 08:38:48 -0000
@@ -0,0 +1,81 @@
+# source file to test assembly of mips32r2 instructions
+
+        .set noreorder
+	.set noat
+
+	.text
+text_label:
+
+      # unprivileged CPU instructions
+
+	ehb
+
+	ext	$4, $5, 6, 8
+
+	ins	$4, $5, 6, 8
+
+	jalr.hb	$8
+	jalr.hb $20, $9
+
+	jr.hb	$8
+
+	# Note, further testing of rdhwr is done in hwr-names-mips32r2.d
+	rdhwr	$10, $0
+	rdhwr	$11, $1
+	rdhwr	$12, $2
+	rdhwr	$13, $3
+	rdhwr	$14, $4
+	rdhwr	$15, $5
+
+	# This file checks that in fact HW rotate will
+	# be used for this arch, and checks assembly
+	# of the official MIPS mnemonics.  (Note that disassembly
+	# uses the traditional "ror" and "rorv" mnemonics.)
+	# Additional rotate tests are done by rol-hw.d.
+	rotl	$25, $10, 4
+	rotr	$25, $10, 4
+	rotl	$25, $10, $4
+	rotr	$25, $10, $4
+	rotrv	$25, $10, $4
+
+	seb	$7
+	seb	$8, $10
+
+	seh	$7
+	seh	$8, $10
+
+	synci	0x5555($10)
+
+	wsbh	$7
+	wsbh	$8, $10
+
+      # cp0 instructions
+
+	di
+	di	$0
+	di	$10
+
+	ei
+	ei	$0
+	ei	$10
+
+	rdpgpr	$10, $25
+
+	wrpgpr	$10, $25
+
+      # FPU (cp1) instructions
+      #
+      # Even registers are supported w/ 32-bit FPU, odd
+      # registers supported only for 64-bit FPU.
+      # Only the 32-bit FPU instructions are tested here.
+     
+	mfhc1	$17, $f0
+	mthc1	$17, $f0
+
+      # cp2 instructions
+
+	mfhc2	$17, 0x5555
+	mthc2	$17, 0x5555
+
+# Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...
+	.space  8
Index: include/elf/mips.h
===================================================================
RCS file: /cvs/src/src/include/elf/mips.h,v
retrieving revision 1.17
diff -u -p -r1.17 mips.h
--- include/elf/mips.h	30 Sep 2002 11:53:55 -0000	1.17
+++ include/elf/mips.h	29 Dec 2002 08:38:50 -0000
@@ -145,6 +145,9 @@ END_RELOC_NUMBERS (R_MIPS_maxext)
 /* -mips64 code.  */
 #define E_MIPS_ARCH_64          0x60000000
 
+/* -mips32r2 code.  */
+#define E_MIPS_ARCH_32R2        0x70000000
+
 /* The ABI of the file.  Also see EF_MIPS_ABI2 above. */
 #define EF_MIPS_ABI		0x0000F000
 
Index: include/opcode/mips.h
===================================================================
RCS file: /cvs/src/src/include/opcode/mips.h,v
retrieving revision 1.30
diff -u -p -r1.30 mips.h
--- include/opcode/mips.h	27 Dec 2002 08:00:31 -0000	1.30
+++ include/opcode/mips.h	29 Dec 2002 08:38:50 -0000
@@ -142,6 +142,10 @@ Software Foundation, 59 Temple Place - S
 #define OP_SH_VECBYTE		22
 #define OP_MASK_VECALIGN	0x7	/* Vector byte-align (alni.ob) op.  */
 #define OP_SH_VECALIGN		21
+#define OP_MASK_INSMSB		0x1f	/* "ins" MSB.  */
+#define OP_SH_INSMSB		11
+#define OP_MASK_EXTMSBD		0x1f	/* "ext" MSBD.  */
+#define OP_SH_EXTMSBD		11
 
 #define	OP_OP_COP0		0x10
 #define	OP_OP_COP1		0x11
@@ -228,6 +232,12 @@ struct mips_opcode
    "J" 19 bit wait function code (OP_*_CODE19)
    "x" accept and ignore register name
    "z" must be zero register
+   "K" 5 bit Hardware Register (rdhwr instruction) (OP_*_RD)
+   "+A" 5 bit ins/ext position/lsb (OP_*_SHAMT)
+   "+B" 5 bit "ins" size spec (OP_*_INSMSB).  Requires that "+A"
+	occur first!
+   "+C" 5 bit "ext" msbd spec (OP_*_EXTMSBD).  Requires that "+A"
+	occur first!
 
    Floating point instructions:
    "D" 5 bit destination register (OP_*_FD)
@@ -268,11 +278,16 @@ struct mips_opcode
    "()" parens surrounding optional value
    ","  separates operands
    "[]" brackets around index for vector-op scalar operand specifier (vr5400)
+   "+"  Start of extension sequence.
 
    Characters used so far, for quick reference when adding more:
-   "%[]<>(),"
-   "ABCDEFGHIJLMNOPQRSTUVWXYZ"
+   "%[]<>(),+"
+   "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefhijklopqrstuvwxz"
+
+   Extension character sequences used so far ("+" followed by the
+   following), for quick reference when adding more:
+   "ABC"
 */
 
 /* These are the bits which may be set in the pinfo field of an
@@ -364,6 +379,7 @@ struct mips_opcode
 #define INSN_ISA5                 0x00000100
 #define INSN_ISA32                0x00000200
 #define INSN_ISA64                0x00000400
+#define INSN_ISA32R2              0x00000800
 
 /* Masks used for MIPS-defined ASEs.  */
 #define INSN_ASE_MASK		  0x0000f000
@@ -406,9 +422,12 @@ struct mips_opcode
 #define       ISA_MIPS3       (ISA_MIPS2 | INSN_ISA3)
 #define       ISA_MIPS4       (ISA_MIPS3 | INSN_ISA4)
 #define       ISA_MIPS5       (ISA_MIPS4 | INSN_ISA5)
+
 #define       ISA_MIPS32      (ISA_MIPS2 | INSN_ISA32)
 #define       ISA_MIPS64      (ISA_MIPS5 | INSN_ISA32 | INSN_ISA64)
 
+#define       ISA_MIPS32R2    (ISA_MIPS32 | INSN_ISA32R2)
+
 /* CPU defines, use instead of hardcoding processor number. Keep this
    in sync with bfd/archures.c in order for machine selection to work.  */
 #define CPU_UNKNOWN	0               /* Gas internal use.  */
@@ -432,6 +451,7 @@ struct mips_opcode
 #define CPU_R12000	12000
 #define CPU_MIPS16	16
 #define CPU_MIPS32	32
+#define CPU_MIPS32R2	33
 #define CPU_MIPS5       5
 #define CPU_MIPS64      64
 #define CPU_SB1         12310201        /* octal 'SB', 01.  */
Index: opcodes/mips-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/mips-dis.c,v
retrieving revision 1.36
diff -u -p -r1.36 mips-dis.c
--- opcodes/mips-dis.c	27 Dec 2002 08:00:31 -0000	1.36
+++ opcodes/mips-dis.c	29 Dec 2002 08:38:53 -0000
@@ -50,7 +50,7 @@ static int _print_insn_mips
   PARAMS ((bfd_vma, struct disassemble_info *, enum bfd_endian));
 static int print_insn_mips
   PARAMS ((bfd_vma, unsigned long int, struct disassemble_info *));
-static void print_insn_arg
+static int print_insn_arg
   PARAMS ((const char *, unsigned long, bfd_vma, struct disassemble_info *));
 static int print_insn_mips16
   PARAMS ((bfd_vma, struct disassemble_info *));
@@ -134,6 +134,17 @@ static const char * const mips_cp0_names
   "c0_taglo",     "c0_taghi",     "c0_errorepc",  "c0_desave",
 };
 
+static const char * const mips_cp0_names_mips3264r2[32] = {
+  "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
+  "c0_context",   "c0_pagemask",  "c0_wired",     "c0_hwrena",
+  "c0_badvaddr",  "c0_count",     "c0_entryhi",   "c0_compare",
+  "c0_status",    "c0_cause",     "c0_epc",       "c0_prid",
+  "c0_config",    "c0_lladdr",    "c0_watchlo",   "c0_watchhi",
+  "c0_xcontext",  "$21",          "$22",          "c0_debug",
+  "c0_depc",      "c0_perfcnt",   "c0_errctl",    "c0_cacheerr",
+  "c0_taglo",     "c0_taghi",     "c0_errorepc",  "c0_desave",
+};
+
 /* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods.  */
 static const char * const mips_cp0_names_sb1[32] = {
   "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
@@ -146,6 +157,21 @@ static const char * const mips_cp0_names
   "c0_taglo_i",   "c0_taghi_i",   "c0_errorepc",  "c0_desave",
 };
 
+static const char * const mips_hwr_names_numeric[32] = {
+  "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7",
+  "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
+  "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
+  "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
+};
+
+static const char * const mips_hwr_names_mips3264r2[32] = {
+  "hwr_cpunum",   "hwr_synci_step", "hwr_cc",     "hwr_ccres",
+  "$4",          "$5",            "$6",           "$7",
+  "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
+  "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
+  "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
+};
+
 struct mips_abi_choice {
   const char *name;
   const char * const *gpr_names;
@@ -166,49 +192,50 @@ struct mips_arch_choice {
   int processor;
   int isa;
   const char * const *cp0_names;
+  const char * const *hwr_names;
 };
 
 struct mips_arch_choice mips_arch_choices[] = {
   { "numeric",	0, 0, 0, 0,
-    mips_cp0_names_numeric },
+    mips_cp0_names_numeric, mips_hwr_names_numeric },
   { "r3000",	1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1,
-    NULL },
+    NULL, NULL },
   { "r3900",	1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1,
-    NULL },
+    NULL, NULL },
   { "r4000",	1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3,
-    NULL },
+    NULL, NULL },
   { "r4010",	1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2,
-    NULL },
+    NULL, NULL },
   { "vr4100",	1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3,
-    NULL },
+    NULL, NULL },
   { "vr4111",	1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3,
-    NULL },
+    NULL, NULL },
   { "vr4120",	1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3,
-    NULL },
+    NULL, NULL },
   { "r4300",	1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3,
-    NULL },
+    NULL, NULL },
   { "r4400",	1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3,
-    NULL },
+    NULL, NULL },
   { "r4600",	1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3,
-    NULL },
+    NULL, NULL },
   { "r4650",	1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3,
-    NULL },
+    NULL, NULL },
   { "r5000",	1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4,
-    NULL },
+    NULL, NULL },
   { "vr5400",	1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4,
-    NULL },
+    NULL, NULL },
   { "vr5500",	1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4,
-    NULL },
+    NULL, NULL },
   { "r6000",	1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2,
-    NULL },
+    NULL, NULL },
   { "r8000",	1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4,
-    NULL },
+    NULL, NULL },
   { "r10000",	1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4,
-    NULL },
+    NULL, NULL },
   { "r12000",	1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4,
-    NULL },
+    NULL, NULL },
   { "mips5",	1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5,
-    NULL },
+    NULL, NULL },
   /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
      Note that MIPS-3D and MDMX are not applicable to MIPS32.  (See
      _MIPS32 Architecture For Programmers Volume I: Introduction to the
@@ -216,19 +243,22 @@ struct mips_arch_choice mips_arch_choice
      page 1.  */
   { "mips32",	1, bfd_mach_mipsisa32, CPU_MIPS32,
     ISA_MIPS32 | INSN_MIPS16,
-    mips_cp0_names_mips3264 },
+    mips_cp0_names_mips3264, NULL },
+  { "mips32r2",	1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
+    ISA_MIPS32R2 | INSN_MIPS16,
+    mips_cp0_names_mips3264r2, mips_hwr_names_mips3264r2 },
   /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs.  */
   { "mips64",	1, bfd_mach_mipsisa64, CPU_MIPS64,
     ISA_MIPS64 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX,
-    mips_cp0_names_mips3264 },
+    mips_cp0_names_mips3264, NULL },
   { "sb1",	1, bfd_mach_mips_sb1, CPU_SB1,
     ISA_MIPS64 | INSN_MIPS3D | INSN_SB1,
-    mips_cp0_names_sb1 },
+    mips_cp0_names_sb1, NULL },
 
   /* This entry, mips16, is here only for ISA/processor selection; do
      not print its name.  */
   { "",		1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3 | INSN_MIPS16,
-    NULL },
+    NULL, NULL },
 };
 
 /* ISA and processor type to disassemble for, and register names to use.
@@ -239,6 +269,7 @@ static int mips_isa;
 static const char * const *mips_gpr_names;
 static const char * const *mips_fpr_names;
 static const char * const *mips_cp0_names;
+static const char * const *mips_hwr_names;
 
 static const struct mips_abi_choice *choose_abi_by_name
   PARAMS ((const char *, unsigned int));
@@ -317,12 +348,13 @@ set_default_mips_dis_options (info)
   const struct mips_arch_choice *chosen_arch;
 
   /* Defaults: mipsIII/r3000 (?!), (o)32-style ("oldabi") GPR names,
-     and numeric FPR and CP0 register names.  */
+     and numeric FPR, CP0 register, and HWR names.  */
   mips_isa = ISA_MIPS3;
   mips_processor =  CPU_R3000;
   mips_gpr_names = mips_gpr_names_oldabi;
   mips_fpr_names = mips_fpr_names_numeric;
   mips_cp0_names = mips_cp0_names_numeric;
+  mips_hwr_names = mips_hwr_names_numeric;
 
   /* If an ELF "newabi" binary, use the n32/(n)64 GPR names.  */
   if (info->flavour == bfd_target_elf_flavour && info->symbols != NULL)
@@ -348,6 +380,8 @@ set_default_mips_dis_options (info)
       mips_isa = chosen_arch->isa;
       if (chosen_arch->cp0_names != NULL)
 	mips_cp0_names = chosen_arch->cp0_names;
+      if (chosen_arch->hwr_names != NULL)
+	mips_hwr_names = chosen_arch->hwr_names;
     }
 #endif
 }
@@ -406,6 +440,15 @@ parse_mips_dis_option (option, len)
       return;
     }
 
+  if (strncmp("hwr-names", option, optionlen) == 0
+      && strlen("hwr-names") == optionlen)
+    {
+      chosen_arch = choose_arch_by_name (val, vallen);
+      if (chosen_arch != NULL && chosen_arch->hwr_names != NULL)
+	mips_hwr_names = chosen_arch->hwr_names;
+      return;
+    }
+
   if (strncmp("reg-names", option, optionlen) == 0
       && strlen("reg-names") == optionlen)
     {
@@ -426,6 +469,8 @@ parse_mips_dis_option (option, len)
 	{
 	  if (chosen_arch->cp0_names != NULL)
 	    mips_cp0_names = chosen_arch->cp0_names;
+	  if (chosen_arch->hwr_names != NULL)
+	    mips_hwr_names = chosen_arch->hwr_names;
 	}
       return;
     }
@@ -467,15 +512,16 @@ parse_mips_dis_options (options)
 
 /* Print insn arguments for 32/64-bit code.  */
 
-static void
+static int
 print_insn_arg (d, l, pc, info)
      const char *d;
      register unsigned long int l;
      bfd_vma pc;
      struct disassemble_info *info;
 {
-  int op, delta;
+  int op, delta, consumed;
 
+  consumed = 1;
   switch (*d)
     {
     case ',':
@@ -486,6 +532,42 @@ print_insn_arg (d, l, pc, info)
       (*info->fprintf_func) (info->stream, "%c", *d);
       break;
 
+    case '+':
+      /* Extension character; switch for second char.  */
+      d++;
+      consumed++;
+      switch (*d)
+	{
+	case 'A':
+	  (*info->fprintf_func) (info->stream, "0x%x",
+				 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
+	  break;
+	
+	case 'B':
+	  (*info->fprintf_func) (info->stream, "0x%x",
+				 (((l >> OP_SH_INSMSB) & OP_MASK_INSMSB)
+				   - ((l >> OP_SH_SHAMT) & OP_MASK_SHAMT)
+				  + 1));
+	  break;
+
+	case 'C':
+	  (*info->fprintf_func) (info->stream, "0x%x",
+				 (((l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD)
+				  + 1));
+	  break;
+
+	default:
+	  /* xgettext:c-format */
+	  (*info->fprintf_func) (info->stream,
+				 _("# internal error, undefined extension sequence (+%c)"),
+				 *d);
+	  /* Do not eat the trailing newline.  */
+	  if (*d == '\0')
+	    consumed--;
+	  break;
+	}
+      break;
+
     case 's':
     case 'b':
     case 'r':
@@ -653,6 +735,11 @@ print_insn_arg (d, l, pc, info)
 			       (l >> OP_SH_RD) & OP_MASK_RD);
       break;
 
+    case 'K':
+      (*info->fprintf_func) (info->stream, "%s",
+			     mips_hwr_names[(l >> OP_SH_RD) & OP_MASK_RD]);
+      break;
+
     case 'N':
       (*info->fprintf_func) (info->stream, "$fcc%d",
 			     (l >> OP_SH_BCC) & OP_MASK_BCC);
@@ -737,6 +824,8 @@ print_insn_arg (d, l, pc, info)
 			     *d);
       break;
     }
+
+  return consumed;
 }
 
 /* Check if the object uses NewABI conventions.  */
@@ -843,9 +932,16 @@ print_insn_mips (memaddr, word, info)
 	      d = op->args;
 	      if (d != NULL && *d != '\0')
 		{
+		  int consumed;
+
 		  (*info->fprintf_func) (info->stream, "\t");
-		  for (; *d != '\0'; d++)
-		    print_insn_arg (d, word, memaddr, info);
+		  while (*d != '\0')
+		    {
+		      /* print_insn_arg will not eat the trailing NUL
+			 of (erroneous) multi-character strings.  */
+		      consumed = print_insn_arg (d, word, memaddr, info);
+		      d += consumed;
+		    }
 		}
 
 	      return INSNLEN;
@@ -1514,11 +1610,16 @@ with the -M switch (multiple options sho
                            Default: based on binary being disassembled.\n"));
 
   fprintf (stream, _("\n\
+  hwr-names=ARCH           Print HWR names according to specified \n\
+			   architecture.\n\
+                           Default: based on binary being disassembled.\n"));
+
+  fprintf (stream, _("\n\
   reg-names=ABI            Print GPR and FPR names according to\n\
                            specified ABI.\n"));
 
   fprintf (stream, _("\n\
-  reg-names=ARCH           Print CP0 register names according to\n\
+  reg-names=ARCH           Print CP0 register and HWR names according to\n\
                            specified architecture.\n"));
 
   fprintf (stream, _("\n\
Index: opcodes/mips-opc.c
===================================================================
RCS file: /cvs/src/src/opcodes/mips-opc.c,v
retrieving revision 1.40
diff -u -p -r1.40 mips-opc.c
--- opcodes/mips-opc.c	18 Dec 2002 22:52:43 -0000	1.40
+++ opcodes/mips-opc.c	29 Dec 2002 08:38:53 -0000
@@ -4,7 +4,8 @@
    Contributed by Ralph Campbell and OSF
    Commented and modified by Ian Lance Taylor, Cygnus Support
    Extended for MIPS32 support by Anders Norlander, and by SiByte, Inc.
-   MIPS-3D and MDMX support added by Broadcom Corporation (SiByte).
+   MIPS-3D, MDMX, and MIPS32 Release 2 support added by Broadcom
+   Corporation (SiByte).
 
 This file is part of GDB, GAS, and the GNU binutils.
 
@@ -85,6 +86,7 @@ Software Foundation, 59 Temple Place - S
 #define I5	INSN_ISA5
 #define I32	INSN_ISA32
 #define I64     INSN_ISA64
+#define I33	INSN_ISA32R2
 
 /* MIPS64 MIPS-3D ASE support.  */
 #define I16     INSN_MIPS16
@@ -137,8 +139,9 @@ const struct mips_opcode mips_builtin_op
 /* name,    args,	match,	    mask,	pinfo,          	membership */
 {"pref",    "k,o(b)",   0xcc000000, 0xfc000000, RD_b,           	I4|I32|G3	},
 {"prefx",   "h,t(b)",	0x4c00000f, 0xfc0007ff, RD_b|RD_t,		I4	},
-{"nop",     "",         0x00000000, 0xffffffff, 0,              	I1      },
-{"ssnop",   "",         0x00000040, 0xffffffff, 0,              	I32|N55	},
+{"nop",     "",         0x00000000, 0xffffffff, 0,              	I1      }, /* sll */
+{"ssnop",   "",         0x00000040, 0xffffffff, 0,              	I32|N55	}, /* sll */
+{"ehb",     "",         0x000000c0, 0xffffffff, 0,              	I33	}, /* sll */
 {"li",      "t,j",      0x24000000, 0xffe00000, WR_t,			I1	}, /* addiu */
 {"li",	    "t,i",	0x34000000, 0xffe00000, WR_t,			I1	}, /* ori */
 {"li",      "t,I",	0,    (int) M_LI,	INSN_MACRO,		I1	},
@@ -478,6 +481,8 @@ const struct mips_opcode mips_builtin_op
 {"dctr",    "o(b)",	0xbc050000, 0xfc1f0000, RD_b,			I3	},
 {"dctw",    "o(b)",	0xbc090000, 0xfc1f0000, RD_b,			I3	},
 {"deret",   "",         0x4200001f, 0xffffffff, 0, 			I32|G2	},
+{"di",      "",		0x41606000, 0xffffffff,	WR_t|WR_C0,		I33	},
+{"di",      "t",	0x41606000, 0xffe0ffff,	WR_t|WR_C0,		I33	},
 /* For ddiv, see the comments about div.  */
 {"ddiv",    "z,s,t",    0x0000001e, 0xfc00ffff, RD_s|RD_t|WR_HILO,      I3      },
 {"ddiv",    "d,v,t",	0,    (int) M_DDIV_3,	INSN_MACRO,		I3	},
@@ -574,7 +579,10 @@ const struct mips_opcode mips_builtin_op
 {"dsub",    "d,v,I",	0,    (int) M_DSUB_I,	INSN_MACRO,		I3	},
 {"dsubu",   "d,v,t",	0x0000002f, 0xfc0007ff,	WR_d|RD_s|RD_t,		I3	},
 {"dsubu",   "d,v,I",	0,    (int) M_DSUBU_I,	INSN_MACRO,		I3	},
+{"ei",      "",		0x41606020, 0xffffffff,	WR_t|WR_C0,		I33	},
+{"ei",      "t",	0x41606020, 0xffe0ffff,	WR_t|WR_C0,		I33	},
 {"eret",    "",         0x42000018, 0xffffffff, 0,      		I3|I32	},
+{"ext",     "t,r,+A,+C", 0x7c000000, 0xfc00003f, WR_t|RD_s,    		I33	},
 {"floor.l.d", "D,S",	0x4620000b, 0xffff003f, WR_D|RD_S|FP_D,		I3	},
 {"floor.l.s", "D,S",	0x4600000b, 0xffff003f, WR_D|RD_S|FP_S,		I3	},
 {"floor.w.d", "D,S",	0x4620000f, 0xffff003f, WR_D|RD_S|FP_D,		I2	},
@@ -583,7 +591,9 @@ const struct mips_opcode mips_builtin_op
 {"flushd",  "",		0xbc020000, 0xffffffff, 0, 			L1	},
 {"flushid", "",		0xbc030000, 0xffffffff, 0, 			L1	},
 {"hibernate","",        0x42000023, 0xffffffff,	0, 			V1	},
+{"ins",     "t,r,+A,+B", 0x7c000004, 0xfc00003f, WR_t|RD_s,    		I33	},
 {"jr",      "s",	0x00000008, 0xfc1fffff,	UBD|RD_s,		I1	},
+{"jr.hb",   "s",	0x00000408, 0xfc1fffff,	UBD|RD_s,		I33	},
 {"j",       "s",	0x00000008, 0xfc1fffff,	UBD|RD_s,		I1	}, /* jr */
 /* SVR4 PIC code requires special handling for j, so it must be a
    macro.  */
@@ -594,6 +604,8 @@ const struct mips_opcode mips_builtin_op
 {"j",       "a",	0x08000000, 0xfc000000,	UBD,			I1	},
 {"jalr",    "s",	0x0000f809, 0xfc1fffff,	UBD|RD_s|WR_d,		I1	},
 {"jalr",    "d,s",	0x00000009, 0xfc1f07ff,	UBD|RD_s|WR_d,		I1	},
+{"jalr.hb", "s",	0x0000fc09, 0xfc1fffff,	UBD|RD_s|WR_d,		I33	},
+{"jalr.hb", "d,s",	0x00000409, 0xfc1f07ff,	UBD|RD_s|WR_d,		I33	},
 /* SVR4 PIC code requires special handling for jal, so it must be a
    macro.  */
 {"jal",     "d,s",	0,     (int) M_JAL_2,	INSN_MACRO,		I1	},
@@ -705,8 +717,11 @@ const struct mips_opcode mips_builtin_op
 {"mfc0",    "t,G,H",    0x40000000, 0xffe007f8, LCD|WR_t|RD_C0, 	I32     },
 {"mfc1",    "t,S",	0x44000000, 0xffe007ff,	LCD|WR_t|RD_S|FP_S,	I1	},
 {"mfc1",    "t,G",	0x44000000, 0xffe007ff,	LCD|WR_t|RD_S|FP_S,	I1	},
+{"mfhc1",   "t,S",	0x44600000, 0xffe007ff,	LCD|WR_t|RD_S|FP_S,	I33	},
+{"mfhc1",   "t,G",	0x44600000, 0xffe007ff,	LCD|WR_t|RD_S|FP_S,	I33	},
 {"mfc2",    "t,G",	0x48000000, 0xffe007ff,	LCD|WR_t|RD_C2,		I1	},
 {"mfc2",    "t,G,H",    0x48000000, 0xffe007f8, LCD|WR_t|RD_C2, 	I32     },
+{"mfhc2",   "t,i",	0x48600000, 0xffe00000,	LCD|WR_t|RD_C2,		I33	},
 {"mfc3",    "t,G",	0x4c000000, 0xffe007ff,	LCD|WR_t|RD_C3,		I1	},
 {"mfc3",    "t,G,H",    0x4c000000, 0xffe007f8, LCD|WR_t|RD_C3, 	I32     },
 {"mfdr",    "t,G",	0x7000003d, 0xffe007ff,	LCD|WR_t|RD_C0,		N5      },
@@ -765,8 +780,11 @@ const struct mips_opcode mips_builtin_op
 {"mtc0",    "t,G,H",    0x40800000, 0xffe007f8, COD|RD_t|WR_C0|WR_CC,   I32     },
 {"mtc1",    "t,S",	0x44800000, 0xffe007ff,	COD|RD_t|WR_S|FP_S,	I1	},
 {"mtc1",    "t,G",	0x44800000, 0xffe007ff,	COD|RD_t|WR_S|FP_S,	I1	},
+{"mthc1",   "t,S",	0x44e00000, 0xffe007ff,	COD|RD_t|WR_S|FP_S,	I33	},
+{"mthc1",   "t,G",	0x44e00000, 0xffe007ff,	COD|RD_t|WR_S|FP_S,	I33	},
 {"mtc2",    "t,G",	0x48800000, 0xffe007ff,	COD|RD_t|WR_C2|WR_CC,	I1	},
 {"mtc2",    "t,G,H",    0x48800000, 0xffe007f8, COD|RD_t|WR_C2|WR_CC,   I32     },
+{"mthc2",   "t,i",	0x48e00000, 0xffe00000,	COD|RD_t|WR_C2|WR_CC,	I33	},
 {"mtc3",    "t,G",	0x4c800000, 0xffe007ff,	COD|RD_t|WR_C3|WR_CC,	I1	},
 {"mtc3",    "t,G,H",    0x4c800000, 0xffe007f8, COD|RD_t|WR_C3|WR_CC,   I32     },
 {"mtdr",    "t,G",	0x7080003d, 0xffe007ff,	COD|RD_t|WR_C0,		N5	},
@@ -890,6 +908,8 @@ const struct mips_opcode mips_builtin_op
 {"remu",    "z,s,t",    0x0000001b, 0xfc00ffff, RD_s|RD_t|WR_HILO,      I1	},
 {"remu",    "d,v,t",	0,    (int) M_REMU_3,	INSN_MACRO,		I1	},
 {"remu",    "d,v,I",	0,    (int) M_REMU_3I,	INSN_MACRO,		I1	},
+{"rdhwr",   "t,K",	0x7c00003b, 0xffe007ff, WR_t,			I33	},
+{"rdpgpr",  "d,w",	0x41400000, 0xffe007ff, WR_d,			I33	},
 {"rfe",     "",		0x42000010, 0xffffffff,	0,			I1|T3	},
 {"rnas.qh", "X,Q",	0x78200025, 0xfc20f83f,	WR_D|RD_MACC|RD_T|FP_D,	MX	},
 {"rnau.ob", "X,Q",	0x78000021, 0xfc20f83f,	WR_D|RD_MACC|RD_T|FP_D,	MX|SB1	},
@@ -901,8 +921,13 @@ const struct mips_opcode mips_builtin_op
 {"rol",     "d,v,I",	0,    (int) M_ROL_I,	INSN_MACRO,		I1	},
 {"ror",     "d,v,t",	0,    (int) M_ROR,	INSN_MACRO,		I1	},
 {"ror",     "d,v,I",	0,    (int) M_ROR_I,	INSN_MACRO,		I1	},
-{"ror",	    "d,w,<",	0x00200002, 0xffe0003f,	WR_d|RD_t,		N5	},
-{"rorv",    "d,t,s",	0x00000046, 0xfc0007ff,	RD_t|RD_s|WR_d,		N5	},
+{"ror",	    "d,w,<",	0x00200002, 0xffe0003f,	WR_d|RD_t,		N5|I33	},
+{"rorv",    "d,t,s",	0x00000046, 0xfc0007ff,	RD_t|RD_s|WR_d,		N5|I33	},
+{"rotl",    "d,v,t",	0,    (int) M_ROL,	INSN_MACRO,		I33	},
+{"rotl",    "d,v,I",	0,    (int) M_ROL_I,	INSN_MACRO,		I33	},
+{"rotr",    "d,v,t",	0,    (int) M_ROR,	INSN_MACRO,		I33	},
+{"rotr",    "d,v,I",	0,    (int) M_ROR_I,	INSN_MACRO,		I33	},
+{"rotrv",   "d,t,s",	0x00000046, 0xfc0007ff,	RD_t|RD_s|WR_d,		I33	},
 {"round.l.d", "D,S",	0x46200008, 0xffff003f, WR_D|RD_S|FP_D,		I3	},
 {"round.l.s", "D,S",	0x46000008, 0xffff003f, WR_D|RD_S|FP_S,		I3	},
 {"round.w.d", "D,S",	0x4620000c, 0xffff003f, WR_D|RD_S|FP_D,		I2	},
@@ -950,6 +975,8 @@ const struct mips_opcode mips_builtin_op
 {"sdr",     "t,o(b)",	0xb4000000, 0xfc000000,	SM|RD_t|RD_b,		I3	},
 {"sdr",     "t,A(b)",	0,    (int) M_SDR_AB,	INSN_MACRO,		I3	},
 {"sdxc1",   "S,t(b)",   0x4c000009, 0xfc0007ff, SM|RD_S|RD_t|RD_b,	I4	},
+{"seb",     "d,w",	0x7C000420, 0xffe007ff,	WR_d|RD_t,		I33	},
+{"seh",     "d,w",	0x7C000620, 0xffe007ff,	WR_d|RD_t,		I33	},
 {"selsl",   "d,v,t",	0x00000005, 0xfc0007ff,	WR_d|RD_s|RD_t,		L1	},
 {"selsr",   "d,v,t",	0x00000001, 0xfc0007ff,	WR_d|RD_s|RD_t,		L1	},
 {"seq",     "d,v,t",	0,    (int) M_SEQ,	INSN_MACRO,		I1	},
@@ -1057,6 +1084,7 @@ const struct mips_opcode mips_builtin_op
 {"sync",    "",		0x0000000f, 0xffffffff,	INSN_SYNC,		I2|G1	},
 {"sync.p",  "",		0x0000040f, 0xffffffff,	INSN_SYNC,		I2	},
 {"sync.l",  "",		0x0000000f, 0xffffffff,	INSN_SYNC,		I2	},
+{"synci",   "o(b)",	0x041f0000, 0xfc1f0000,	SM|RD_b,		I33	},
 {"syscall", "",		0x0000000c, 0xffffffff,	TRAP,			I1	},
 {"syscall", "B",	0x0000000c, 0xfc00003f,	TRAP,			I1	},
 {"teqi",    "s,j",	0x040c0000, 0xfc1f0000, RD_s|TRAP,		I2	},
@@ -1125,6 +1153,8 @@ const struct mips_opcode mips_builtin_op
 {"wait",    "J",        0x42000020, 0xfe00003f, TRAP,   		I32|N55	},
 {"waiti",   "",		0x42000020, 0xffffffff,	TRAP,			L1	},
 {"wb", 	    "o(b)",	0xbc040000, 0xfc1f0000, SM|RD_b,		L1	},
+{"wrpgpr",  "d,w",	0x41c00000, 0xffe007ff, RD_t,			I33	},
+{"wsbh",    "d,w",	0x7C0000a0, 0xffe007ff,	WR_d|RD_t,		I33	},
 {"xor",     "d,v,t",	0x00000026, 0xfc0007ff,	WR_d|RD_s|RD_t,		I1	},
 {"xor",     "t,r,I",	0,    (int) M_XOR_I,	INSN_MACRO,		I1	},
 {"xor.ob",  "X,Y,Q",	0x7800000d, 0xfc20003f,	WR_D|RD_S|RD_T|FP_D,	MX|SB1	},


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