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] 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

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