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


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

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


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"
 }


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