[AArch64][SVE 14/32] Make aarch64_logical_immediate_p take an element size
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Sep 2016 15:51:09 +0000 (16:51 +0100)
committerRichard Sandiford <richard.sandiford@arm.com>
Wed, 21 Sep 2016 15:51:09 +0000 (16:51 +0100)
SVE supports logical immediate operations on 8-bit, 16-bit and 32-bit
elements, treating them as aliases of operations on 64-bit elements in
which the immediate is replicated.  This patch therefore replaces the
"32-bit/64-bit" input to aarch64_logical_immediate_p with a more
general "number of bytes" input.

opcodes/
* aarch64-opc.c (aarch64_logical_immediate_p): Replace is32
with an esize parameter.
(operand_general_constraint_met_p): Update accordingly.
Fix misindented code.
* aarch64-asm.c (aarch64_ins_limm): Update call to
aarch64_logical_immediate_p.

opcodes/ChangeLog
opcodes/aarch64-asm.c
opcodes/aarch64-opc.c

index c12ea3a..9f44e97 100644 (file)
@@ -1,5 +1,14 @@
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
 
+       * aarch64-opc.c (aarch64_logical_immediate_p): Replace is32
+       with an esize parameter.
+       (operand_general_constraint_met_p): Update accordingly.
+       Fix misindented code.
+       * aarch64-asm.c (aarch64_ins_limm): Update call to
+       aarch64_logical_immediate_p.
+
+2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
+
        * aarch64-opc.c (match_operands_qualifier): Handle F_STRICT.
 
 2016-09-21  Richard Sandiford  <richard.sandiford@arm.com>
index 2430be5..8fbd66f 100644 (file)
@@ -436,11 +436,11 @@ aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info,
 {
   aarch64_insn value;
   uint64_t imm = info->imm.value;
-  int is32 = aarch64_get_qualifier_esize (inst->operands[0].qualifier) == 4;
+  int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier);
 
   if (inst->opcode->op == OP_BIC)
     imm = ~imm;
-  if (aarch64_logical_immediate_p (imm, is32, &value) == FALSE)
+  if (aarch64_logical_immediate_p (imm, esize, &value) == FALSE)
     /* The constraint check should have guaranteed this wouldn't happen.  */
     assert (0);
 
index d870fd6..84da821 100644 (file)
@@ -1062,16 +1062,18 @@ build_immediate_table (void)
    be accepted by logical (immediate) instructions
    e.g. ORR <Xd|SP>, <Xn>, #<imm>.
 
-   IS32 indicates whether or not VALUE is a 32-bit immediate.
+   ESIZE is the number of bytes in the decoded immediate value.
    If ENCODING is not NULL, on the return of TRUE, the standard encoding for
    VALUE will be returned in *ENCODING.  */
 
 bfd_boolean
-aarch64_logical_immediate_p (uint64_t value, int is32, aarch64_insn *encoding)
+aarch64_logical_immediate_p (uint64_t value, int esize, aarch64_insn *encoding)
 {
   simd_imm_encoding imm_enc;
   const simd_imm_encoding *imm_encoding;
   static bfd_boolean initialized = FALSE;
+  uint64_t upper;
+  int i;
 
   DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 "), is32: %d", value,
               value, is32);
@@ -1082,17 +1084,16 @@ aarch64_logical_immediate_p (uint64_t value, int is32, aarch64_insn *encoding)
       initialized = TRUE;
     }
 
-  if (is32)
-    {
-      /* Allow all zeros or all ones in top 32-bits, so that
-        constant expressions like ~1 are permitted.  */
-      if (value >> 32 != 0 && value >> 32 != 0xffffffff)
-       return FALSE;
+  /* Allow all zeros or all ones in top bits, so that
+     constant expressions like ~1 are permitted.  */
+  upper = (uint64_t) -1 << (esize * 4) << (esize * 4);
+  if ((value & ~upper) != value && (value | upper) != value)
+    return FALSE;
 
-      /* Replicate the 32 lower bits to the 32 upper bits.  */
-      value &= 0xffffffff;
-      value |= value << 32;
-    }
+  /* Replicate to a full 64-bit value.  */
+  value &= ~upper;
+  for (i = esize * 8; i < 64; i *= 2)
+    value |= (value << i);
 
   imm_enc.imm = value;
   imm_encoding = (const simd_imm_encoding *)
@@ -1645,7 +1646,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
 
        case AARCH64_OPND_IMM_MOV:
            {
-             int is32 = aarch64_get_qualifier_esize (opnds[0].qualifier) == 4;
+             int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
              imm = opnd->imm.value;
              assert (idx == 1);
              switch (opcode->op)
@@ -1654,7 +1655,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
                  imm = ~imm;
                  /* Fall through...  */
                case OP_MOV_IMM_WIDE:
-                 if (!aarch64_wide_constant_p (imm, is32, NULL))
+                 if (!aarch64_wide_constant_p (imm, esize == 4, NULL))
                    {
                      set_other_error (mismatch_detail, idx,
                                       _("immediate out of range"));
@@ -1662,7 +1663,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
                    }
                  break;
                case OP_MOV_IMM_LOG:
-                 if (!aarch64_logical_immediate_p (imm, is32, NULL))
+                 if (!aarch64_logical_immediate_p (imm, esize, NULL))
                    {
                      set_other_error (mismatch_detail, idx,
                                       _("immediate out of range"));
@@ -1707,18 +1708,18 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
          break;
 
        case AARCH64_OPND_LIMM:
-           {
-             int is32 = opnds[0].qualifier == AARCH64_OPND_QLF_W;
-             uint64_t uimm = opnd->imm.value;
-             if (opcode->op == OP_BIC)
-               uimm = ~uimm;
-             if (aarch64_logical_immediate_p (uimm, is32, NULL) == FALSE)
-               {
-                 set_other_error (mismatch_detail, idx,
-                                  _("immediate out of range"));
-                 return 0;
-               }
-           }
+         {
+           int esize = aarch64_get_qualifier_esize (opnds[0].qualifier);
+           uint64_t uimm = opnd->imm.value;
+           if (opcode->op == OP_BIC)
+             uimm = ~uimm;
+           if (aarch64_logical_immediate_p (uimm, esize, NULL) == FALSE)
+             {
+               set_other_error (mismatch_detail, idx,
+                                _("immediate out of range"));
+               return 0;
+             }
+         }
          break;
 
        case AARCH64_OPND_IMM0: