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]

[Patch][AArch64] - Error on load pair to same register


Hi,

I came across a SIGILL at runtime caused by a typo specifying the same register in a load pair.

The ARM DDI 0487A says on page C6-507

if memop == MemOp_LOAD && t == t2 then
	Constraint c = ConstrainUnpredictable();
	assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
	case c of
		when Constraint_UNKNOWN rt_unknown = TRUE; // result is UNKNOWN
		when Constraint_UNDEF UnallocatedEncoding();
		when Constraint_NOP EndOfInstruction();

I doubt that any one would intentionally do this operation since the behaviour is unpredictable so it just seems safer to reject the code.

2014-11-12  Ryan Mansfield  <rmansfield@qnx.com>

        * aarch64-opc.c (operand_general_constraint_met_p): Add constraint
        that load pair must have different registers.

Regards,

Ryan Mansfield
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 430cf5b..a98aed4 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -1290,6 +1290,29 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
 	      return 0;
 	    }
 	}
+
+      switch (opcode->iclass)
+	{
+	  case ldstpair_indexed:
+	  case ldstpair_off:
+	  case ldstnapair_offs:
+	    if (type == AARCH64_OPND_Rt2)
+	      {
+		assert (idx == 1 && (aarch64_get_operand_class (opnds[0].type)
+				     == AARCH64_OPND_CLASS_INT_REG));
+		if ((opcode->opcode & (1 << 22)) && opnds[idx].reg.regno
+		    == opnds[idx - 1].reg.regno)
+		  {
+		    set_other_error (mismatch_detail, idx,
+				     _("reg pair must differ"));
+		    return 0;
+		  }
+	      }
+	    break;
+	  default:
+	    break;
+	}
+
       switch (qualifier)
 	{
 	case AARCH64_OPND_QLF_WSP:
@@ -1306,6 +1329,30 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
 	}
       break;
 
+    case AARCH64_OPND_CLASS_FP_REG:
+      switch (opcode->iclass)
+	{
+	case ldstpair_indexed:
+	case ldstpair_off:
+	case ldstnapair_offs:
+	  if (type == AARCH64_OPND_Ft2)
+	    {
+	      assert (idx == 1 && (aarch64_get_operand_class (opnds[0].type)
+				   == AARCH64_OPND_CLASS_FP_REG));
+	      if ((opcode->opcode & (1 << 22)) && opnds[idx].reg.regno
+		  == opnds[idx - 1].reg.regno)
+		{
+		  set_other_error (mismatch_detail, idx,
+				   _("reg pair must differ"));
+		  return 0;
+		}
+	    }
+	  break;
+	default:
+	  break;
+	}
+      break;
+
     case AARCH64_OPND_CLASS_COND:
       if (type == AARCH64_OPND_COND1
 	  && (opnds[idx].cond->value & 0xe) == 0xe)

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