[AArch64][SVE 17/32] Add a prefix parameter to print_register_list
[deliverable/binutils-gdb.git] / opcodes / aarch64-dis.c
index 631f076f0f86bf852720dd2a0b210781eb5e98a6..4c3b521d0de9f73f5944c7469fe71c2d8997ae19 100644 (file)
@@ -1,5 +1,5 @@
 /* aarch64-dis.c -- AArch64 disassembler.
-   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Copyright (C) 2009-2016 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of the GNU opcodes library.
@@ -145,6 +145,26 @@ extract_fields (aarch64_insn code, aarch64_insn mask, ...)
   return value;
 }
 
+/* Extract the value of all fields in SELF->fields from instruction CODE.
+   The least significant bit comes from the final field.  */
+
+static aarch64_insn
+extract_all_fields (const aarch64_operand *self, aarch64_insn code)
+{
+  aarch64_insn value;
+  unsigned int i;
+  enum aarch64_field_kind kind;
+
+  value = 0;
+  for (i = 0; i < ARRAY_SIZE (self->fields) && self->fields[i] != FLD_NIL; ++i)
+    {
+      kind = self->fields[i];
+      value <<= fields[kind].width;
+      value |= extract_field (kind, code, 0);
+    }
+  return value;
+}
+
 /* Sign-extend bit I of VALUE.  */
 static inline int32_t
 sign_extend (aarch64_insn value, unsigned i)
@@ -173,12 +193,19 @@ get_greg_qualifier_from_value (aarch64_insn value)
   return qualifier;
 }
 
-/* Given VALUE, return qualifier for a vector register.  */
+/* Given VALUE, return qualifier for a vector register.  This does not support
+   decoding instructions that accept the 2H vector type.  */
+
 static inline enum aarch64_opnd_qualifier
 get_vreg_qualifier_from_value (aarch64_insn value)
 {
   enum aarch64_opnd_qualifier qualifier = AARCH64_OPND_QLF_V_8B + value;
 
+  /* Instructions using vector type 2H should not call this function.  Skip over
+     the 2H qualifier.  */
+  if (qualifier >= AARCH64_OPND_QLF_V_2H)
+    qualifier += 1;
+
   assert (value <= 0x8
          && aarch64_get_qualifier_standard_value (qualifier) == value);
   return qualifier;
@@ -568,17 +595,8 @@ aarch64_ext_imm (const aarch64_operand *self, aarch64_opnd_info *info,
                 const aarch64_inst *inst ATTRIBUTE_UNUSED)
 {
   int64_t imm;
-  /* Maximum of two fields to extract.  */
-  assert (self->fields[2] == FLD_NIL);
-
-  if (self->fields[1] == FLD_NIL)
-    imm = extract_field (self->fields[0], code, 0);
-  else
-    /* e.g. TBZ b5:b40.  */
-    imm = extract_fields (code, 0, 2, self->fields[0], self->fields[1]);
 
-  if (info->type == AARCH64_OPND_FPIMM)
-    info->imm.is_fp = 1;
+  imm = extract_all_fields (self, code);
 
   if (operand_need_sign_extension (self))
     imm = sign_extend (imm, get_operand_fields_width (self) - 1);
@@ -674,6 +692,17 @@ aarch64_ext_advsimd_imm_modified (const aarch64_operand *self ATTRIBUTE_UNUSED,
   return 1;
 }
 
+/* Decode an 8-bit floating-point immediate.  */
+int
+aarch64_ext_fpimm (const aarch64_operand *self, aarch64_opnd_info *info,
+                  const aarch64_insn code,
+                  const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  info->imm.value = extract_all_fields (self, code);
+  info->imm.is_fp = 1;
+  return 1;
+}
+
 /* Decode scale for e.g. SCVTF <Dd>, <Wn>, #<fbits>.  */
 int
 aarch64_ext_fbits (const aarch64_operand *self ATTRIBUTE_UNUSED,
@@ -1067,6 +1096,33 @@ aarch64_ext_prfop (const aarch64_operand *self ATTRIBUTE_UNUSED,
   return 1;
 }
 
+/* Decode the hint number for an alias taking an operand.  Set info->hint_option
+   to the matching name/value pair in aarch64_hint_options.  */
+
+int
+aarch64_ext_hint (const aarch64_operand *self ATTRIBUTE_UNUSED,
+                 aarch64_opnd_info *info,
+                 aarch64_insn code,
+                 const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+  /* CRm:op2.  */
+  unsigned hint_number;
+  int i;
+
+  hint_number = extract_fields (code, 0, 2, FLD_CRm, FLD_op2);
+
+  for (i = 0; aarch64_hint_options[i].name != NULL; i++)
+    {
+      if (hint_number == aarch64_hint_options[i].value)
+       {
+         info->hint_option = &(aarch64_hint_options[i]);
+         return 1;
+       }
+    }
+
+  return 0;
+}
+
 /* Decode the extended register operand for e.g.
      STR <Qt>, [<Xn|SP>, <R><m>{, <extend> {<amount>}}].  */
 int
@@ -2013,6 +2069,7 @@ aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
     {
       const aarch64_operand *opnd;
       enum aarch64_opnd type;
+
       type = opcode->operands[i];
       if (type == AARCH64_OPND_NIL)
        break;
@@ -2025,6 +2082,13 @@ aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
        }
     }
 
+  /* If the opcode has a verifier, then check it now.  */
+  if (opcode->verifier && ! opcode->verifier (opcode, code))
+    {
+      DEBUG_TRACE ("operand verifier FAIL");
+      goto decode_fail;
+    }
+
   /* Match the qualifiers.  */
   if (aarch64_match_operands_constraint (inst, NULL) == 1)
     {
@@ -2120,8 +2184,7 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
   int i, pcrel_p, num_printed;
   for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
-      const size_t size = 128;
-      char str[size];
+      char str[128];
       /* We regard the opcode operand info more, however we also look into
         the inst->operands to support the disassembling of the optional
         operand.
@@ -2132,7 +2195,7 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
        break;
 
       /* Generate the operand string in STR.  */
-      aarch64_print_operand (str, size, pc, opcode, opnds, i, &pcrel_p,
+      aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
                             &info->target);
 
       /* Print the delimiter (taking account of omitted operand(s)).  */
This page took 0.025461 seconds and 4 git commands to generate.