This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] GAS - Neon three-args rejection fix
- From: Daniel Gutson <dgutson at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Fri, 25 Dec 2009 20:38:00 -0300
- Subject: [PATCH] GAS - Neon three-args rejection fix
Currently, gas accepts
vorr.i32 q0, #0xff
but rejects this:
vorr.i32 q0, q0, #0xff
This patch fixes that by adding the following changes:
The OP_NILO operand tag (which was used only in these insns family) is
replaced by the OP_RNDQ_IMVNb tag (now renamed to OP_RNDQ_Ibig) instead.
This is because OP_NILO had a complicated logic that allowed either an
optional operand, plus a register or immediate operand, but such logic
didn't cover the form required by the three operands args described above.
I replaced the
<2, (RNDQ, NILO)>
shape with this one:
<3, (RNDQ, oRNDQ, RNDQ_Ibig)>.
using the already implemented kind-of LL(k) mechanism.
In the insn enconding side:
I now allow the immediate operand to be either in the 2nd or 3rd
operand.
I tested this patch by running the ld, binutils, and gas test suites,
the latter being enhanced with a test case I added for this.
Please let me know if OK to commit.
Daniel.
ChangeLog:
2009-12-25 Daniel Gutson <dgutson@codesourcery.com>
gas/
* config/tc-arm.c (do_neon_logic): Accept imm value
in the third operand too.
(operand_parse_code): OP_RNDQ_IMVNb renamed to
OP_RNDQ_Ibig.
(parse_operands): OP_NILO case removed, applied renaming.
(insns): Neon shape changed for some logic instructions.
gas/testsuite/
* gas/arm/neon-logic.d: New test case.
* gas/arm/neon-logic.s: New file.
--
Daniel Gutson
CodeSourcery
www.codesourcery.com
? neon_three_args.patch
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.422
diff -u -p -r1.422 tc-arm.c
--- gas/config/tc-arm.c 21 Dec 2009 12:56:41 -0000 1.422
+++ gas/config/tc-arm.c 25 Dec 2009 23:30:13 -0000
@@ -5765,7 +5765,6 @@ enum operand_parse_code
OP_NRDLST, /* Neon double-precision register list (d0-d31, qN aliases) */
OP_NSTRLST, /* Neon element/structure list */
- OP_NILO, /* Neon immediate/logic operands 2 or 2+3. (VBIC, VORR...) */
OP_RNDQ_I0, /* Neon D or Q reg, or immediate zero. */
OP_RVSD_I0, /* VFP S or D reg, or immediate zero. */
OP_RR_RNSC, /* ARM reg or Neon scalar. */
@@ -5773,7 +5772,7 @@ enum operand_parse_code
OP_RNDQ_RNSC, /* Neon D or Q reg, or Neon scalar. */
OP_RND_RNSC, /* Neon D reg, or Neon scalar. */
OP_VMOV, /* Neon VMOV operands. */
- OP_RNDQ_IMVNb,/* Neon D or Q reg, or immediate good for VMVN. */
+ OP_RNDQ_Ibig, /* Neon D or Q reg, or big immediate for logic and VMVN. */
OP_RNDQ_I63b, /* Neon D or Q reg, or immediate for shift. */
OP_RIWR_I32z, /* iWMMXt wR register, or immediate 0 .. 32 for iWMMXt2. */
@@ -6005,36 +6004,6 @@ parse_operands (char *str, const unsigne
scalars are accepted here, so deal with those in later code. */
case OP_RNSC: po_scalar_or_goto (8, failure); break;
- /* WARNING: We can expand to two operands here. This has the potential
- to totally confuse the backtracking mechanism! It will be OK at
- least as long as we don't try to use optional args as well,
- though. */
- case OP_NILO:
- {
- po_reg_or_goto (REG_TYPE_NDQ, try_imm);
- inst.operands[i].present = 1;
- i++;
- skip_past_comma (&str);
- po_reg_or_goto (REG_TYPE_NDQ, one_reg_only);
- break;
- one_reg_only:
- /* Optional register operand was omitted. Unfortunately, it's in
- operands[i-1] and we need it to be in inst.operands[i]. Fix that
- here (this is a bit grotty). */
- inst.operands[i] = inst.operands[i-1];
- inst.operands[i-1].present = 0;
- break;
- try_imm:
- /* There's a possibility of getting a 64-bit immediate here, so
- we need special handling. */
- if (parse_big_immediate (&str, i) == FAIL)
- {
- inst.error = _("immediate value is out of range");
- goto failure;
- }
- }
- break;
-
case OP_RNDQ_I0:
{
po_reg_or_goto (REG_TYPE_NDQ, try_imm0);
@@ -6090,11 +6059,11 @@ parse_operands (char *str, const unsigne
po_misc_or_fail (parse_neon_mov (&str, &i) == FAIL);
break;
- case OP_RNDQ_IMVNb:
+ case OP_RNDQ_Ibig:
{
- po_reg_or_goto (REG_TYPE_NDQ, try_mvnimm);
+ po_reg_or_goto (REG_TYPE_NDQ, try_immbig);
break;
- try_mvnimm:
+ try_immbig:
/* There's a possibility of getting a 64-bit immediate here, so
we need special handling. */
if (parse_big_immediate (&str, i) == FAIL)
@@ -12880,7 +12849,12 @@ do_neon_logic (void)
}
else
{
- enum neon_shape rs = neon_select_shape (NS_DI, NS_QI, NS_NULL);
+ const int three_ops_form = (inst.operands[2].present
+ && !inst.operands[2].isreg);
+ const int immoperand = (three_ops_form ? 2 : 1);
+ enum neon_shape rs = (three_ops_form
+ ? neon_select_shape (NS_DDI, NS_QQI, NS_NULL)
+ : neon_select_shape (NS_DI, NS_QI, NS_NULL));
struct neon_type_el et = neon_check_type (2, rs,
N_I8 | N_I16 | N_I32 | N_I64 | N_F32 | N_KEY, N_EQK);
enum neon_opc opcode = (enum neon_opc) inst.instruction & 0x0fffffff;
@@ -12890,15 +12864,19 @@ do_neon_logic (void)
if (et.type == NT_invtype)
return;
+ if (three_ops_form)
+ constraint (inst.operands[0].reg != inst.operands[1].reg,
+ _("first and second operands shall be the same register"));
+
inst.instruction = NEON_ENC_IMMED (inst.instruction);
- immbits = inst.operands[1].imm;
+ immbits = inst.operands[immoperand].imm;
if (et.size == 64)
{
/* .i64 is a pseudo-op, so the immediate must be a repeating
pattern. */
- if (immbits != (inst.operands[1].regisimm ?
- inst.operands[1].reg : 0))
+ if (immbits != (inst.operands[immoperand].regisimm ?
+ inst.operands[immoperand].reg : 0))
{
/* Set immbits to an invalid constant. */
immbits = 0xdeadbeef;
@@ -17441,16 +17419,16 @@ static const struct asm_opcode insns[] =
nUF(vqshl, _vqshl, 3, (RNDQ, oRNDQ, RNDQ_I63b), neon_qshl_imm),
nUF(vqshlq, _vqshl, 3, (RNQ, oRNQ, RNDQ_I63b), neon_qshl_imm),
/* Logic ops, types optional & ignored. */
- nUF(vand, _vand, 2, (RNDQ, NILO), neon_logic),
- nUF(vandq, _vand, 2, (RNQ, NILO), neon_logic),
- nUF(vbic, _vbic, 2, (RNDQ, NILO), neon_logic),
- nUF(vbicq, _vbic, 2, (RNQ, NILO), neon_logic),
- nUF(vorr, _vorr, 2, (RNDQ, NILO), neon_logic),
- nUF(vorrq, _vorr, 2, (RNQ, NILO), neon_logic),
- nUF(vorn, _vorn, 2, (RNDQ, NILO), neon_logic),
- nUF(vornq, _vorn, 2, (RNQ, NILO), neon_logic),
- nUF(veor, _veor, 3, (RNDQ, oRNDQ, RNDQ), neon_logic),
- nUF(veorq, _veor, 3, (RNQ, oRNQ, RNQ), neon_logic),
+ nUF(vand, _vand, 3, (RNDQ, oRNDQ, RNDQ_Ibig), neon_logic),
+ nUF(vandq, _vand, 3, (RNQ, oRNQ, RNDQ_Ibig), neon_logic),
+ nUF(vbic, _vbic, 3, (RNDQ, oRNDQ, RNDQ_Ibig), neon_logic),
+ nUF(vbicq, _vbic, 3, (RNQ, oRNQ, RNDQ_Ibig), neon_logic),
+ nUF(vorr, _vorr, 3, (RNDQ, oRNDQ, RNDQ_Ibig), neon_logic),
+ nUF(vorrq, _vorr, 3, (RNQ, oRNQ, RNDQ_Ibig), neon_logic),
+ nUF(vorn, _vorn, 3, (RNDQ, oRNDQ, RNDQ_Ibig), neon_logic),
+ nUF(vornq, _vorn, 3, (RNQ, oRNQ, RNDQ_Ibig), neon_logic),
+ nUF(veor, _veor, 3, (RNDQ, oRNDQ, RNDQ), neon_logic),
+ nUF(veorq, _veor, 3, (RNQ, oRNQ, RNQ), neon_logic),
/* Bitfield ops, untyped. */
NUF(vbsl, 1100110, 3, (RNDQ, RNDQ, RNDQ), neon_bitfield),
NUF(vbslq, 1100110, 3, (RNQ, RNQ, RNQ), neon_bitfield),
@@ -17549,8 +17527,8 @@ static const struct asm_opcode insns[] =
/* CVT with optional immediate for fixed-point variant. */
nUF(vcvtq, _vcvt, 3, (RNQ, RNQ, oI32b), neon_cvt),
- nUF(vmvn, _vmvn, 2, (RNDQ, RNDQ_IMVNb), neon_mvn),
- nUF(vmvnq, _vmvn, 2, (RNQ, RNDQ_IMVNb), neon_mvn),
+ nUF(vmvn, _vmvn, 2, (RNDQ, RNDQ_Ibig), neon_mvn),
+ nUF(vmvnq, _vmvn, 2, (RNQ, RNDQ_Ibig), neon_mvn),
/* Data processing, three registers of different lengths. */
/* Dyadic, long insns. Types S8 S16 S32 U8 U16 U32. */
Index: gas/testsuite/gas/arm/neon-logic.d
===================================================================
RCS file: gas/testsuite/gas/arm/neon-logic.d
diff -N gas/testsuite/gas/arm/neon-logic.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/neon-logic.d 25 Dec 2009 23:30:13 -0000
@@ -0,0 +1,16 @@
+# name: Neon logic insns with two and three operands including imm. values
+# as: -mfpu=neon
+# objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+
+Disassembly of section \.text:
+00000000 <.text> f387015f vorr.i32 q0, #255 ; 0x000000ff
+00000004 <.text\+0x4> f387015f vorr.i32 q0, #255 ; 0x000000ff
+00000008 <.text\+0x8> f2220154 vorr q0, q1, q2
+0000000c <.text\+0xc> f2200152 vorr q0, q0, q1
+00000010 <.text\+0x10> f387011f vorr.i32 d0, #255 ; 0x000000ff
+00000014 <.text\+0x14> f387011f vorr.i32 d0, #255 ; 0x000000ff
+00000018 <.text\+0x18> f2210112 vorr d0, d1, d2
+0000001c <.text\+0x1c> f2200111 vorr d0, d0, d1
Index: gas/testsuite/gas/arm/neon-logic.s
===================================================================
RCS file: gas/testsuite/gas/arm/neon-logic.s
diff -N gas/testsuite/gas/arm/neon-logic.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gas/testsuite/gas/arm/neon-logic.s 25 Dec 2009 23:30:13 -0000
@@ -0,0 +1,9 @@
+.syntax unified
+vorr.i32 q0, q0, #0xff
+vorr.i32 q0, #0xff
+vorr.i32 q0, q1, q2
+vorr.i32 q0, q1
+vorr.i32 d0, d0, #0xff
+vorr.i32 d0, #0xff
+vorr.i32 d0, d1, d2
+vorr.i32 d0, d1