This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[Patch][AArch64] - Error on load pair to same register
- From: Ryan Mansfield <rmansfield at qnx dot com>
- To: <binutils at sourceware dot org>
- Date: Wed, 12 Nov 2014 15:07:30 -0500
- Subject: [Patch][AArch64] - Error on load pair to same register
- Authentication-results: sourceware.org; auth=none
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)