[committed] Add {gpr,fpr}_{read,write}_mask functions to MIPS

Richard Sandiford rdsandiford@googlemail.com
Wed Jun 29 20:38:00 GMT 2011


Several parts of the MIPS GAS backend want to know which registers are
read or written by an instruction.  This patch factors these checks
into new functions.

I fixed a couple of problems with the .reginfo masks:
- we were missing MIPS16 translations on the 8-bit register fields
- we didn't count both registers in an FPR pair
which probably just goes to show how important these masks are in
practice.

I also tightened the insn_uses_reg check for whether we had FPR pairs.
It's still conservatively correct rather than absolutely accurate,
but at least it's a bit better than before.

The branch swapping code calculates the same mask twice.  A follow-on
patch avoids this.

Tested on:

    mips64-elf mips64el-unknown-kfreebsd-gnu mips64-linux-gnu
    mips64octeon-linux-gnu mips64-unknown-kfreebsd-gnu
    mipsel-unknown-kfreebsd-gnu mipsisa32el-linux-gnu
    mipsisa64-elf mips-linux-gnu mips-sgi-irix6.5
    mips-unknown-kfreebsd-gnu mips-wrs-vxworks

and applied.

Richard


gas/
	* config/tc-mips.c (insn_uses_reg): Delete.
	(gpr_read_mask, gpr_write_mask): New functions.
	(fpr_read_mask, fpr_write_mask): Likewise.
	(insns_between, nops_for_vr4130, append_insn): Use them.

gas/testsuite/
	* gas/mips/mips16-e.d, gas/mips/mips16-f.d,
	gas/mips/mipsel16-e.d, gas/mips/mipsel16-f.d,
	gas/mips/tmips16-e.d, gas/mips/tmips16-f.d,
	gas/mips/tmipsel16-e.d, gas/mips/tmipsel16-f.d: Fix GPR mask.
	* gas/mips/reginfo-1.s, gas/mips/reginfo-1a.d,
	gas/mips/reginfo-1b.d: New tests.
	* gas/mips/mips.exp: Run them.

Index: gas/config/tc-mips.c
===================================================================
--- gas/config/tc-mips.c	2011-06-28 21:16:46.000000000 +0100
+++ gas/config/tc-mips.c	2011-06-29 19:55:57.000000000 +0100
@@ -2242,88 +2242,6 @@ fixup_has_matching_lo_p (fixS *fixp)
 	  && fixp->fx_offset == fixp->fx_next->fx_offset);
 }
 
-/* See whether instruction IP reads register REG.  CLASS is the type
-   of register.  */
-
-static int
-insn_uses_reg (const struct mips_cl_insn *ip, unsigned int reg,
-	       enum mips_regclass regclass)
-{
-  if (regclass == MIPS16_REG)
-    {
-      gas_assert (mips_opts.mips16);
-      reg = mips16_to_32_reg_map[reg];
-      regclass = MIPS_GR_REG;
-    }
-
-  /* Don't report on general register ZERO, since it never changes.  */
-  if (regclass == MIPS_GR_REG && reg == ZERO)
-    return 0;
-
-  if (regclass == MIPS_FP_REG)
-    {
-      gas_assert (! mips_opts.mips16);
-      /* If we are called with either $f0 or $f1, we must check $f0.
-	 This is not optimal, because it will introduce an unnecessary
-	 NOP between "lwc1 $f0" and "swc1 $f1".  To fix this we would
-	 need to distinguish reading both $f0 and $f1 or just one of
-	 them.  Note that we don't have to check the other way,
-	 because there is no instruction that sets both $f0 and $f1
-	 and requires a delay.  */
-      if ((ip->insn_mo->pinfo & INSN_READ_FPR_S)
-	  && ((EXTRACT_OPERAND (FS, *ip) & ~(unsigned) 1)
-	      == (reg &~ (unsigned) 1)))
-	return 1;
-      if ((ip->insn_mo->pinfo & INSN_READ_FPR_T)
-	  && ((EXTRACT_OPERAND (FT, *ip) & ~(unsigned) 1)
-	      == (reg &~ (unsigned) 1)))
-	return 1;
-      if ((ip->insn_mo->pinfo2 & INSN2_READ_FPR_Z)
-	  && ((EXTRACT_OPERAND (FZ, *ip) & ~(unsigned) 1)
-	      == (reg &~ (unsigned) 1)))
-	return 1;
-    }
-  else if (! mips_opts.mips16)
-    {
-      if ((ip->insn_mo->pinfo & INSN_READ_GPR_S)
-	  && EXTRACT_OPERAND (RS, *ip) == reg)
-	return 1;
-      if ((ip->insn_mo->pinfo & INSN_READ_GPR_T)
-	  && EXTRACT_OPERAND (RT, *ip) == reg)
-	return 1;
-      if ((ip->insn_mo->pinfo2 & INSN2_READ_GPR_D)
-	  && EXTRACT_OPERAND (RD, *ip) == reg)
-	return 1;
-      if ((ip->insn_mo->pinfo2 & INSN2_READ_GPR_Z)
-	  && EXTRACT_OPERAND (RZ, *ip) == reg)
-	return 1;
-    }
-  else
-    {
-      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_X)
-	  && mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RX, *ip)] == reg)
-	return 1;
-      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_Y)
-	  && mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RY, *ip)] == reg)
-	return 1;
-      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_Z)
-	  && (mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (MOVE32Z, *ip)]
-	      == reg))
-	return 1;
-      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_T) && reg == TREG)
-	return 1;
-      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_SP) && reg == SP)
-	return 1;
-      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_31) && reg == RA)
-	return 1;
-      if ((ip->insn_mo->pinfo & MIPS16_INSN_READ_GPR_X)
-	  && MIPS16_EXTRACT_OPERAND (REGR32, *ip) == reg)
-	return 1;
-    }
-
-  return 0;
-}
-
 /* This function returns true if modifying a register requires a
    delay.  */
 
@@ -2476,6 +2394,149 @@ relax_end (void)
   mips_relax.sequence = 0;
 }
 
+/* Return the mask of core registers that IP reads.  */
+
+static unsigned int
+gpr_read_mask (const struct mips_cl_insn *ip)
+{
+  unsigned long pinfo, pinfo2;
+  unsigned int mask;
+
+  mask = 0;
+  pinfo = ip->insn_mo->pinfo;
+  pinfo2 = ip->insn_mo->pinfo2;
+  if (mips_opts.mips16)
+    {
+      if (pinfo & MIPS16_INSN_READ_X)
+	mask |= 1 << mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RX, *ip)];
+      if (pinfo & MIPS16_INSN_READ_Y)
+	mask |= 1 << mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RY, *ip)];
+      if (pinfo & MIPS16_INSN_READ_T)
+	mask |= 1 << TREG;
+      if (pinfo & MIPS16_INSN_READ_SP)
+	mask |= 1 << SP;
+      if (pinfo & MIPS16_INSN_READ_31)
+	mask |= 1 << RA;
+      if (pinfo & MIPS16_INSN_READ_Z)
+	mask |= 1 << (mips16_to_32_reg_map
+		      [MIPS16_EXTRACT_OPERAND (MOVE32Z, *ip)]);
+      if (pinfo & MIPS16_INSN_READ_GPR_X)
+	mask |= 1 << MIPS16_EXTRACT_OPERAND (REGR32, *ip);
+    }
+  else
+    {
+      if (pinfo2 & INSN2_READ_GPR_D)
+	mask |= 1 << EXTRACT_OPERAND (RD, *ip);
+      if (pinfo & INSN_READ_GPR_T)
+	mask |= 1 << EXTRACT_OPERAND (RT, *ip);
+      if (pinfo & INSN_READ_GPR_S)
+	mask |= 1 << EXTRACT_OPERAND (RS, *ip);
+      if (pinfo2 & INSN2_READ_GPR_Z)
+	mask |= 1 << EXTRACT_OPERAND (RZ, *ip);
+    }
+  return mask & ~0;
+}
+
+/* Return the mask of core registers that IP writes.  */
+
+static unsigned int
+gpr_write_mask (const struct mips_cl_insn *ip)
+{
+  unsigned long pinfo, pinfo2;
+  unsigned int mask;
+
+  mask = 0;
+  pinfo = ip->insn_mo->pinfo;
+  pinfo2 = ip->insn_mo->pinfo2;
+  if (mips_opts.mips16)
+    {
+      if (pinfo & MIPS16_INSN_WRITE_X)
+	mask |= 1 << mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RX, *ip)];
+      if (pinfo & MIPS16_INSN_WRITE_Y)
+	mask |= 1 << mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RY, *ip)];
+      if (pinfo & MIPS16_INSN_WRITE_Z)
+	mask |= 1 << mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RZ, *ip)];
+      if (pinfo & MIPS16_INSN_WRITE_T)
+	mask |= 1 << TREG;
+      if (pinfo & MIPS16_INSN_WRITE_SP)
+	mask |= 1 << SP;
+      if (pinfo & MIPS16_INSN_WRITE_31)
+	mask |= 1 << RA;
+      if (pinfo & MIPS16_INSN_WRITE_GPR_Y)
+	mask |= 1 << MIPS16OP_EXTRACT_REG32R (ip->insn_opcode);
+    }
+  else
+    {
+      if (pinfo & INSN_WRITE_GPR_D)
+	mask |= 1 << EXTRACT_OPERAND (RD, *ip);
+      if (pinfo & INSN_WRITE_GPR_T)
+	mask |= 1 << EXTRACT_OPERAND (RT, *ip);
+      if (pinfo & INSN_WRITE_GPR_31)
+	mask |= 1 << RA;
+      if (pinfo2 & INSN2_WRITE_GPR_Z)
+	mask |= 1 << EXTRACT_OPERAND (RZ, *ip);
+    }
+  return mask & ~0;
+}
+
+/* Return the mask of floating-point registers that IP reads.  */
+
+static unsigned int
+fpr_read_mask (const struct mips_cl_insn *ip)
+{
+  unsigned long pinfo, pinfo2;
+  unsigned int mask;
+
+  mask = 0;
+  pinfo = ip->insn_mo->pinfo;
+  pinfo2 = ip->insn_mo->pinfo2;
+  if (!mips_opts.mips16)
+    {
+      if (pinfo & INSN_READ_FPR_S)
+	mask |= 1 << EXTRACT_OPERAND (FS, *ip);
+      if (pinfo & INSN_READ_FPR_T)
+	mask |= 1 << EXTRACT_OPERAND (FT, *ip);
+      if (pinfo & INSN_READ_FPR_R)
+	mask |= 1 << EXTRACT_OPERAND (FR, *ip);
+      if (pinfo2 & INSN2_READ_FPR_Z)
+	mask |= 1 << EXTRACT_OPERAND (FZ, *ip);
+    }
+  /* Conservatively treat all operands to an FP_D instruction are doubles.
+     (This is overly pessimistic for things like cvt.d.s.)  */
+  if (HAVE_32BIT_FPRS && (pinfo & FP_D))
+    mask |= mask << 1;
+  return mask;
+}
+
+/* Return the mask of floating-point registers that IP writes.  */
+
+static unsigned int
+fpr_write_mask (const struct mips_cl_insn *ip)
+{
+  unsigned long pinfo, pinfo2;
+  unsigned int mask;
+
+  mask = 0;
+  pinfo = ip->insn_mo->pinfo;
+  pinfo2 = ip->insn_mo->pinfo2;
+  if (!mips_opts.mips16)
+    {
+      if (pinfo & INSN_WRITE_FPR_D)
+	mask |= 1 << EXTRACT_OPERAND (FD, *ip);
+      if (pinfo & INSN_WRITE_FPR_S)
+	mask |= 1 << EXTRACT_OPERAND (FS, *ip);
+      if (pinfo & INSN_WRITE_FPR_T)
+	mask |= 1 << EXTRACT_OPERAND (FT, *ip);
+      if (pinfo2 & INSN2_WRITE_FPR_Z)
+	mask |= 1 << EXTRACT_OPERAND (FZ, *ip);
+    }
+  /* Conservatively treat all operands to an FP_D instruction are doubles.
+     (This is overly pessimistic for things like cvt.s.d.)  */
+  if (HAVE_32BIT_FPRS && (pinfo & FP_D))
+    mask |= mask << 1;
+  return mask;
+}
+
 /* Classify an instruction according to the FIX_VR4120_* enumeration.
    Return NUM_FIX_VR4120_CLASSES if the instruction isn't affected
    by VR4120 errata.  */
@@ -2510,16 +2571,17 @@ insns_between (const struct mips_cl_insn
 	       const struct mips_cl_insn *insn2)
 {
   unsigned long pinfo1, pinfo2;
+  unsigned int mask;
 
   /* This function needs to know which pinfo flags are set for INSN2
      and which registers INSN2 uses.  The former is stored in PINFO2 and
-     the latter is tested via INSN2_USES_REG.  If INSN2 is null, PINFO2
-     will have every flag set and INSN2_USES_REG will always return true.  */
+     the latter is tested via INSN2_USES_GPR.  If INSN2 is null, PINFO2
+     will have every flag set and INSN2_USES_GPR will always return true.  */
   pinfo1 = insn1->insn_mo->pinfo;
   pinfo2 = insn2 ? insn2->insn_mo->pinfo : ~0U;
 
-#define INSN2_USES_REG(REG, CLASS) \
-   (insn2 == NULL || insn_uses_reg (insn2, REG, CLASS))
+#define INSN2_USES_GPR(REG) \
+  (insn2 == NULL || (gpr_read_mask (insn2) & (1U << (REG))) != 0)
 
   /* For most targets, write-after-read dependencies on the HI and LO
      registers must be separated by at least two instructions.  */
@@ -2535,7 +2597,7 @@ #define INSN2_USES_REG(REG, CLASS) \
      between an mfhi or mflo and any instruction that uses the result.  */
   if (mips_7000_hilo_fix
       && MF_HILO_INSN (pinfo1)
-      && INSN2_USES_REG (EXTRACT_OPERAND (RD, *insn1), MIPS_GR_REG))
+      && INSN2_USES_GPR (EXTRACT_OPERAND (RD, *insn1)))
     return 2;
 
   /* If we're working around 24K errata, one instruction is required
@@ -2582,7 +2644,7 @@ #define INSN2_USES_REG(REG, CLASS) \
 	  || (!cop_interlocks && (pinfo1 & INSN_LOAD_COPROC_DELAY)))
 	{
 	  know (pinfo1 & INSN_WRITE_GPR_T);
-	  if (INSN2_USES_REG (EXTRACT_OPERAND (RT, *insn1), MIPS_GR_REG))
+	  if (INSN2_USES_GPR (EXTRACT_OPERAND (RT, *insn1)))
 	    return 1;
 	}
 
@@ -2600,14 +2662,10 @@ #define INSN2_USES_REG(REG, CLASS) \
 	  /* Handle cases where INSN1 writes to a known general coprocessor
 	     register.  There must be a one instruction delay before INSN2
 	     if INSN2 reads that register, otherwise no delay is needed.  */
-	  if (pinfo1 & INSN_WRITE_FPR_T)
+	  mask = fpr_write_mask (insn1);
+	  if (mask != 0)
 	    {
-	      if (INSN2_USES_REG (EXTRACT_OPERAND (FT, *insn1), MIPS_FP_REG))
-		return 1;
-	    }
-	  else if (pinfo1 & INSN_WRITE_FPR_S)
-	    {
-	      if (INSN2_USES_REG (EXTRACT_OPERAND (FS, *insn1), MIPS_FP_REG))
+	      if (!insn2 || (mask & fpr_read_mask (insn2)) != 0)
 		return 1;
 	    }
 	  else
@@ -2637,7 +2695,7 @@ #define INSN2_USES_REG(REG, CLASS) \
 	return 1;
     }
 
-#undef INSN2_USES_REG
+#undef INSN2_USES_GPR
 
   return 0;
 }
@@ -2651,7 +2709,8 @@ #define INSN2_USES_REG(REG, CLASS) \
 nops_for_vr4130 (int ignore, const struct mips_cl_insn *hist,
 		 const struct mips_cl_insn *insn)
 {
-  int i, j, reg;
+  int i, j;
+  unsigned int mask;
 
   /* Check if the instruction writes to HI or LO.  MTHI and MTLO
      are not affected by the errata.  */
@@ -2666,18 +2725,15 @@ nops_for_vr4130 (int ignore, const struc
     if (MF_HILO_INSN (hist[i].insn_mo->pinfo))
       {
 	/* Extract the destination register.  */
-	if (mips_opts.mips16)
-	  reg = mips16_to_32_reg_map[MIPS16_EXTRACT_OPERAND (RX, hist[i])];
-	else
-	  reg = EXTRACT_OPERAND (RD, hist[i]);
+	mask = gpr_write_mask (&hist[i]);
 
 	/* No nops are needed if INSN reads that register.  */
-	if (insn != NULL && insn_uses_reg (insn, reg, MIPS_GR_REG))
+	if (insn != NULL && (gpr_read_mask (insn) & mask) != 0)
 	  return 0;
 
 	/* ...or if any of the intervening instructions do.  */
 	for (j = 0; j < i; j++)
-	  if (insn_uses_reg (&hist[j], reg, MIPS_GR_REG))
+	  if (gpr_read_mask (&hist[j]) & mask)
 	    return 0;
 
 	if (i >= ignore)
@@ -3395,59 +3451,8 @@ append_insn (struct mips_cl_insn *ip, ex
   install_insn (ip);
 
   /* Update the register mask information.  */
-  if (! mips_opts.mips16)
-    {
-      if ((pinfo & INSN_WRITE_GPR_D) || (pinfo2 & INSN2_READ_GPR_D))
-	mips_gprmask |= 1 << EXTRACT_OPERAND (RD, *ip);
-      if ((pinfo & (INSN_WRITE_GPR_T | INSN_READ_GPR_T)) != 0)
-	mips_gprmask |= 1 << EXTRACT_OPERAND (RT, *ip);
-      if (pinfo & INSN_READ_GPR_S)
-	mips_gprmask |= 1 << EXTRACT_OPERAND (RS, *ip);
-      if (pinfo & INSN_WRITE_GPR_31)
-	mips_gprmask |= 1 << RA;
-      if (pinfo2 & (INSN2_WRITE_GPR_Z | INSN2_READ_GPR_Z))
-	mips_gprmask |= 1 << EXTRACT_OPERAND (RZ, *ip);
-      if (pinfo & INSN_WRITE_FPR_D)
-	mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FD, *ip);
-      if ((pinfo & (INSN_WRITE_FPR_S | INSN_READ_FPR_S)) != 0)
-	mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FS, *ip);
-      if ((pinfo & (INSN_WRITE_FPR_T | INSN_READ_FPR_T)) != 0)
-	mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FT, *ip);
-      if ((pinfo & INSN_READ_FPR_R) != 0)
-	mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FR, *ip);
-      if (pinfo2 & (INSN2_WRITE_FPR_Z | INSN2_READ_FPR_Z))
-	mips_cprmask[1] |= 1 << EXTRACT_OPERAND (FZ, *ip);
-      if (pinfo & INSN_COP)
-	{
-	  /* We don't keep enough information to sort these cases out.
-	     The itbl support does keep this information however, although
-	     we currently don't support itbl fprmats as part of the cop
-	     instruction.  May want to add this support in the future.  */
-	}
-      /* Never set the bit for $0, which is always zero.  */
-      mips_gprmask &= ~1 << 0;
-    }
-  else
-    {
-      if (pinfo & (MIPS16_INSN_WRITE_X | MIPS16_INSN_READ_X))
-	mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (RX, *ip);
-      if (pinfo & (MIPS16_INSN_WRITE_Y | MIPS16_INSN_READ_Y))
-	mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (RY, *ip);
-      if (pinfo & MIPS16_INSN_WRITE_Z)
-	mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (RZ, *ip);
-      if (pinfo & (MIPS16_INSN_WRITE_T | MIPS16_INSN_READ_T))
-	mips_gprmask |= 1 << TREG;
-      if (pinfo & (MIPS16_INSN_WRITE_SP | MIPS16_INSN_READ_SP))
-	mips_gprmask |= 1 << SP;
-      if (pinfo & (MIPS16_INSN_WRITE_31 | MIPS16_INSN_READ_31))
-	mips_gprmask |= 1 << RA;
-      if (pinfo & MIPS16_INSN_WRITE_GPR_Y)
-	mips_gprmask |= 1 << MIPS16OP_EXTRACT_REG32R (ip->insn_opcode);
-      if (pinfo & MIPS16_INSN_READ_Z)
-	mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (MOVE32Z, *ip);
-      if (pinfo & MIPS16_INSN_READ_GPR_X)
-	mips_gprmask |= 1 << MIPS16_EXTRACT_OPERAND (REGR32, *ip);
-    }
+  mips_gprmask |= gpr_read_mask (ip) | gpr_write_mask (ip);
+  mips_cprmask[1] |= fpr_read_mask (ip) | fpr_write_mask (ip);
 
   if (mips_relax.sequence != 2 && !mips_opts.noreorder)
     {
@@ -3503,77 +3508,13 @@ append_insn (struct mips_cl_insn *ip, ex
 	      || (prev_pinfo & INSN_TRAP)
 	      /* If the branch reads a register that the previous
 		 instruction sets, we can not swap.  */
-	      || (! mips_opts.mips16
-		  && (prev_pinfo & INSN_WRITE_GPR_T)
-		  && insn_uses_reg (ip, EXTRACT_OPERAND (RT, history[0]),
-				    MIPS_GR_REG))
-	      || (! mips_opts.mips16
-		  && (prev_pinfo & INSN_WRITE_GPR_D)
-		  && insn_uses_reg (ip, EXTRACT_OPERAND (RD, history[0]),
-				    MIPS_GR_REG))
-	      || (! mips_opts.mips16
-		  && (prev_pinfo2 & INSN2_WRITE_GPR_Z)
-		  && insn_uses_reg (ip, EXTRACT_OPERAND (RZ, history[0]),
-				    MIPS_GR_REG))
-	      || (mips_opts.mips16
-		  && (((prev_pinfo & MIPS16_INSN_WRITE_X)
-		       && (insn_uses_reg
-			   (ip, MIPS16_EXTRACT_OPERAND (RX, history[0]),
-			    MIPS16_REG)))
-		      || ((prev_pinfo & MIPS16_INSN_WRITE_Y)
-			  && (insn_uses_reg
-			      (ip, MIPS16_EXTRACT_OPERAND (RY, history[0]),
-			       MIPS16_REG)))
-		      || ((prev_pinfo & MIPS16_INSN_WRITE_Z)
-			  && (insn_uses_reg
-			      (ip, MIPS16_EXTRACT_OPERAND (RZ, history[0]),
-			       MIPS16_REG)))
-		      || ((prev_pinfo & MIPS16_INSN_WRITE_T)
-			  && insn_uses_reg (ip, TREG, MIPS_GR_REG))
-		      || ((prev_pinfo & MIPS16_INSN_WRITE_31)
-			  && insn_uses_reg (ip, RA, MIPS_GR_REG))
-		      || ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y)
-			  && insn_uses_reg (ip,
-					    MIPS16OP_EXTRACT_REG32R
-					      (history[0].insn_opcode),
-					    MIPS_GR_REG))))
+	      || (gpr_read_mask (ip) & gpr_write_mask (&history[0])) != 0
 	      /* If the branch writes a register that the previous
-		 instruction sets, we can not swap (we know that
-		 branches write only to RD or to $31).  */
-	      || (! mips_opts.mips16
-		  && (prev_pinfo & INSN_WRITE_GPR_T)
-		  && (((pinfo & INSN_WRITE_GPR_D)
-		       && (EXTRACT_OPERAND (RT, history[0])
-			   == EXTRACT_OPERAND (RD, *ip)))
-		      || ((pinfo & INSN_WRITE_GPR_31)
-			  && EXTRACT_OPERAND (RT, history[0]) == RA)))
-	      || (! mips_opts.mips16
-		  && (prev_pinfo & INSN_WRITE_GPR_D)
-		  && (((pinfo & INSN_WRITE_GPR_D)
-		       && (EXTRACT_OPERAND (RD, history[0])
-			   == EXTRACT_OPERAND (RD, *ip)))
-		      || ((pinfo & INSN_WRITE_GPR_31)
-			  && EXTRACT_OPERAND (RD, history[0]) == RA)))
-	      || (mips_opts.mips16
-		  && (pinfo & MIPS16_INSN_WRITE_31)
-		  && ((prev_pinfo & MIPS16_INSN_WRITE_31)
-		      || ((prev_pinfo & MIPS16_INSN_WRITE_GPR_Y)
-			  && (MIPS16OP_EXTRACT_REG32R (history[0].insn_opcode)
-			      == RA))))
+		 instruction sets, we can not swap.  */
+	      || (gpr_write_mask (ip) & gpr_write_mask (&history[0])) != 0
 	      /* If the branch writes a register that the previous
-		 instruction reads, we can not swap (we know that
-		 branches only write to RD or to $31).  */
-	      || (! mips_opts.mips16
-		  && (pinfo & INSN_WRITE_GPR_D)
-		  && insn_uses_reg (&history[0],
-				    EXTRACT_OPERAND (RD, *ip),
-				    MIPS_GR_REG))
-	      || (! mips_opts.mips16
-		  && (pinfo & INSN_WRITE_GPR_31)
-		  && insn_uses_reg (&history[0], RA, MIPS_GR_REG))
-	      || (mips_opts.mips16
-		  && (pinfo & MIPS16_INSN_WRITE_31)
-		  && insn_uses_reg (&history[0], RA, MIPS_GR_REG))
+		 instruction reads, we can not swap.  */
+	      || (gpr_write_mask (ip) & gpr_read_mask (&history[0])) != 0
 	      /* If one instruction sets a condition code and the
                  other one uses a condition code, we can not swap.  */
 	      || ((pinfo & INSN_READ_COND_CODE)
Index: gas/testsuite/gas/mips/mips16-e.d
===================================================================
--- gas/testsuite/gas/mips/mips16-e.d	2011-06-28 21:16:46.000000000 +0100
+++ gas/testsuite/gas/mips/mips16-e.d	2011-06-28 21:16:46.000000000 +0100
@@ -31,7 +31,7 @@ OFFSET [ ]+ TYPE              VALUE
 Contents of section \.text:
  0000 65006500 65006500 65006500 65006500  .*
 Contents of section \.reginfo:
- 0000 00000001 00000000 00000000 00000000  .*
+ 0000 00010000 00000000 00000000 00000000  .*
  0010 00000000 00000000                    .*
 Contents of section foo:
  0000 00000000 00000008 00000000 00000003  .*
Index: gas/testsuite/gas/mips/mips16-f.d
===================================================================
--- gas/testsuite/gas/mips/mips16-f.d	2011-06-28 21:16:46.000000000 +0100
+++ gas/testsuite/gas/mips/mips16-f.d	2011-06-28 21:16:46.000000000 +0100
@@ -24,7 +24,7 @@ OFFSET [ ]+ TYPE              VALUE
 Contents of section \.text:
  0000 65006500 65006500 65006500 65006500  .*
 Contents of section \.reginfo:
- 0000 00000001 00000000 00000000 00000000  .*
+ 0000 00010000 00000000 00000000 00000000  .*
  0010 00000000 00000000                    .*
 Contents of section foo:
  0000 00000003 00000000 00000000 00000000  .*
Index: gas/testsuite/gas/mips/mipsel16-e.d
===================================================================
--- gas/testsuite/gas/mips/mipsel16-e.d	2011-06-28 21:16:46.000000000 +0100
+++ gas/testsuite/gas/mips/mipsel16-e.d	2011-06-28 21:16:46.000000000 +0100
@@ -32,7 +32,7 @@ OFFSET [ ]+ TYPE              VALUE
 Contents of section \.text:
  0000 00650065 00650065 00650065 00650065  .*
 Contents of section \.reginfo:
- 0000 01000000 00000000 00000000 00000000  .*
+ 0000 00000100 00000000 00000000 00000000  .*
  0010 00000000 00000000                    .*
 Contents of section foo:
  0000 00000000 08000000 00000000 03000000  .*
Index: gas/testsuite/gas/mips/mipsel16-f.d
===================================================================
--- gas/testsuite/gas/mips/mipsel16-f.d	2011-06-28 21:16:46.000000000 +0100
+++ gas/testsuite/gas/mips/mipsel16-f.d	2011-06-28 21:16:46.000000000 +0100
@@ -25,7 +25,7 @@ OFFSET [ ]+ TYPE              VALUE
 Contents of section \.text:
  0000 00650065 00650065 00650065 00650065  .*
 Contents of section \.reginfo:
- 0000 01000000 00000000 00000000 00000000  .*
+ 0000 00000100 00000000 00000000 00000000  .*
  0010 00000000 00000000                    .*
 Contents of section foo:
  0000 03000000 00000000 00000000 00000000  .*
Index: gas/testsuite/gas/mips/tmips16-e.d
===================================================================
--- gas/testsuite/gas/mips/tmips16-e.d	2011-06-28 21:16:46.000000000 +0100
+++ gas/testsuite/gas/mips/tmips16-e.d	2011-06-28 21:16:46.000000000 +0100
@@ -32,7 +32,7 @@ OFFSET [ ]+ TYPE              VALUE
 Contents of section \.text:
  0000 65006500 65006500 65006500 65006500  .*
 Contents of section \.reginfo:
- 0000 00000001 00000000 00000000 00000000  .*
+ 0000 00010000 00000000 00000000 00000000  .*
  0010 00000000 00000000                    .*
 Contents of section foo:
  0000 00000000 00000008 00000000 00000003  .*
Index: gas/testsuite/gas/mips/tmips16-f.d
===================================================================
--- gas/testsuite/gas/mips/tmips16-f.d	2011-06-28 21:16:46.000000000 +0100
+++ gas/testsuite/gas/mips/tmips16-f.d	2011-06-28 21:16:46.000000000 +0100
@@ -25,7 +25,7 @@ OFFSET [ ]+ TYPE              VALUE
 Contents of section \.text:
  0000 65006500 65006500 65006500 65006500  .*
 Contents of section \.reginfo:
- 0000 00000001 00000000 00000000 00000000  .*
+ 0000 00010000 00000000 00000000 00000000  .*
  0010 00000000 00000000                    .*
 Contents of section foo:
  0000 00000003 00000000 00000000 00000000  .*
Index: gas/testsuite/gas/mips/tmipsel16-e.d
===================================================================
--- gas/testsuite/gas/mips/tmipsel16-e.d	2011-06-28 21:16:46.000000000 +0100
+++ gas/testsuite/gas/mips/tmipsel16-e.d	2011-06-28 21:16:46.000000000 +0100
@@ -32,7 +32,7 @@ OFFSET [ ]+ TYPE              VALUE
 Contents of section \.text:
  0000 00650065 00650065 00650065 00650065  .*
 Contents of section \.reginfo:
- 0000 01000000 00000000 00000000 00000000  .*
+ 0000 00000100 00000000 00000000 00000000  .*
  0010 00000000 00000000                    .*
 Contents of section foo:
  0000 00000000 08000000 00000000 03000000  .*
Index: gas/testsuite/gas/mips/tmipsel16-f.d
===================================================================
--- gas/testsuite/gas/mips/tmipsel16-f.d	2011-06-28 21:16:46.000000000 +0100
+++ gas/testsuite/gas/mips/tmipsel16-f.d	2011-06-28 21:16:46.000000000 +0100
@@ -25,7 +25,7 @@ OFFSET [ ]+ TYPE              VALUE
 Contents of section \.text:
  0000 00650065 00650065 00650065 00650065  .*
 Contents of section \.reginfo:
- 0000 01000000 00000000 00000000 00000000  .*
+ 0000 00000100 00000000 00000000 00000000  .*
  0010 00000000 00000000                    .*
 Contents of section foo:
  0000 03000000 00000000 00000000 00000000  .*
Index: gas/testsuite/gas/mips/reginfo-1.s
===================================================================
--- /dev/null	2011-06-29 20:49:09.402506167 +0100
+++ gas/testsuite/gas/mips/reginfo-1.s	2011-06-28 22:35:55.000000000 +0100
@@ -0,0 +1,3 @@
+	ldc1	$f4,($4)
+	add.s	$f10,$f10,$f10
+	add.d	$f16,$f16,$f16
Index: gas/testsuite/gas/mips/reginfo-1a.d
===================================================================
--- /dev/null	2011-06-29 20:49:09.402506167 +0100
+++ gas/testsuite/gas/mips/reginfo-1a.d	2011-06-28 22:36:10.000000000 +0100
@@ -0,0 +1,9 @@
+#source: reginfo-1.s
+#as: -32 -EL -mips4
+#objdump: -sj.reginfo
+
+.*
+
+Contents of section \.reginfo:
+ 0000 10000000 00000000 30040300 00000000  .*
+ 0010 00000000 00000000                    .*
Index: gas/testsuite/gas/mips/reginfo-1b.d
===================================================================
--- /dev/null	2011-06-29 20:49:09.402506167 +0100
+++ gas/testsuite/gas/mips/reginfo-1b.d	2011-06-28 22:36:20.000000000 +0100
@@ -0,0 +1,9 @@
+#source: reginfo-1.s
+#as: -mabi=o64 -EB -mips4
+#objdump: -sj.reginfo
+
+.*
+
+Contents of section \.reginfo:
+ 0000 00000010 00000000 00010410 00000000  .*
+ 0010 00000000 00000000                    .*
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
--- gas/testsuite/gas/mips/mips.exp	2011-06-28 21:30:36.000000000 +0100
+++ gas/testsuite/gas/mips/mips.exp	2011-06-28 21:36:46.000000000 +0100
@@ -1002,4 +1002,6 @@ if { [istarget mips*-*-vxworks*] } {
     if $has_newabi { run_dump_test "cfi-n64-1" }
 
     run_dump_test "pr12915"
+    run_dump_test "reginfo-1a"
+    run_dump_test "reginfo-1b"
 }



More information about the Binutils mailing list