ppc/svp64: disassemble SVP64 operands
authorDmitry Selyutin <ghostmansd@gmail.com>
Sun, 28 May 2023 22:04:57 +0000 (01:04 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Tue, 14 Nov 2023 19:53:36 +0000 (22:53 +0300)
opcodes/ppc-dis.c
opcodes/ppc-svp64-dis.c

index a19b2a840614088375437ba86bbb3bb46ea66a5b..adfd19d44ee79bd4288146a5be8182d63bed14ba 100644 (file)
@@ -989,6 +989,7 @@ print_insn_powerpc_opcode (struct disassemble_info *info,
   d34 = 0;
   for (opindex = opcode->operands; *opindex != 0; opindex++)
     {
+      bool vector;
       int64_t value;
 
       operand = powerpc_operands + *opindex;
@@ -1006,7 +1007,13 @@ print_insn_powerpc_opcode (struct disassemble_info *info,
            continue;
        }
 
+      vector = false;
       value = operand_value_powerpc (operand, insn, dialect);
+      if (svp64)
+       {
+         value = svp64_operand_value (svp64,
+           value, *opindex, operand->flags, &vector);
+       }
 
       if (op_separator == need_comma)
        (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
@@ -1016,65 +1023,80 @@ print_insn_powerpc_opcode (struct disassemble_info *info,
        (*info->fprintf_styled_func) (info->stream, dis_style_text, "%*s",
                                      op_separator, " ");
 
-         /* Print the operand as directed by the flags.  */
-         if ((operand->flags & PPC_OPERAND_GPR) != 0
-             || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
-           (*info->fprintf_styled_func) (info->stream, dis_style_register,
-                                         "r%" PRId64, value);
-         else if ((operand->flags & PPC_OPERAND_FPR) != 0)
-           (*info->fprintf_styled_func) (info->stream, dis_style_register,
-                                         "f%" PRId64, value);
-         else if ((operand->flags & PPC_OPERAND_VR) != 0)
-           (*info->fprintf_styled_func) (info->stream, dis_style_register,
-                                         "v%" PRId64, value);
-         else if ((operand->flags & PPC_OPERAND_VSR) != 0)
-           (*info->fprintf_styled_func) (info->stream, dis_style_register,
-                                         "vs%" PRId64, value);
-         else if ((operand->flags & PPC_OPERAND_DMR) != 0)
-           (*info->fprintf_styled_func) (info->stream, dis_style_register,
-                                         "dm%" PRId64, value);
-         else if ((operand->flags & PPC_OPERAND_ACC) != 0)
-           (*info->fprintf_styled_func) (info->stream, dis_style_register,
-                                         "a%" PRId64, value);
-         else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
-           (*info->print_address_func) (memaddr + value, info);
-         else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
-           (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
-         else if ((operand->flags & PPC_OPERAND_FSL) != 0)
-           (*info->fprintf_styled_func) (info->stream, dis_style_register,
-                                         "fsl%" PRId64, value);
-         else if ((operand->flags & PPC_OPERAND_FCR) != 0)
-           (*info->fprintf_styled_func) (info->stream, dis_style_register,
-                                         "fcr%" PRId64, value);
-         else if ((operand->flags & PPC_OPERAND_UDI) != 0)
-           (*info->fprintf_styled_func) (info->stream, dis_style_register,
-                                         "%" PRId64, value);
-         else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
-                  && (operand->flags & PPC_OPERAND_CR_BIT) == 0
-                  && (((dialect & PPC_OPCODE_PPC) != 0)
-                      || ((dialect & PPC_OPCODE_VLE) != 0)))
-           (*info->fprintf_styled_func) (info->stream, dis_style_register,
-                                         "cr%" PRId64, value);
-         else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
-                  && (operand->flags & PPC_OPERAND_CR_REG) == 0
-                  && (((dialect & PPC_OPCODE_PPC) != 0)
-                      || ((dialect & PPC_OPCODE_VLE) != 0)))
-           {
-             static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
-             int cr;
-             int cc;
+      /* Print the operand as directed by the flags.  */
+      if ((operand->flags & PPC_OPERAND_GPR) != 0
+         || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
+       (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                     "%sr%" PRId64,
+                                     (vector ? "*" : ""), value);
+      else if ((operand->flags & PPC_OPERAND_FPR) != 0)
+       (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                     "%sf%" PRId64,
+                                     (vector ? "*" : ""), value);
+      else if ((operand->flags & PPC_OPERAND_VR) != 0)
+       (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                     "v%" PRId64, value);
+      else if ((operand->flags & PPC_OPERAND_VSR) != 0)
+       (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                     "vs%" PRId64, value);
+      else if ((operand->flags & PPC_OPERAND_DMR) != 0)
+       (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                     "dm%" PRId64, value);
+      else if ((operand->flags & PPC_OPERAND_ACC) != 0)
+       (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                     "a%" PRId64, value);
+      else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
+       (*info->print_address_func) (memaddr + value, info);
+      else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
+       (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
+      else if ((operand->flags & PPC_OPERAND_FSL) != 0)
+       (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                     "fsl%" PRId64, value);
+      else if ((operand->flags & PPC_OPERAND_FCR) != 0)
+       (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                     "fcr%" PRId64, value);
+      else if ((operand->flags & PPC_OPERAND_UDI) != 0)
+       (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                     "%" PRId64, value);
+      else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
+               && (operand->flags & PPC_OPERAND_CR_BIT) == 0
+               && (((dialect & PPC_OPCODE_PPC) != 0)
+                   || ((dialect & PPC_OPCODE_VLE) != 0)))
+       (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                     "cr%" PRId64, value);
+      else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
+               && (operand->flags & PPC_OPERAND_CR_REG) == 0
+               && (((dialect & PPC_OPCODE_PPC) != 0)
+                   || ((dialect & PPC_OPCODE_VLE) != 0)))
+       {
+         static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
+         int cr;
+         int cc;
 
          cr = value >> 2;
          cc = value & 3;
          if (cr != 0)
            {
-             (*info->fprintf_styled_func) (info->stream, dis_style_text,
-                                           "4*");
-             (*info->fprintf_styled_func) (info->stream,
-                                           dis_style_register,
-                                           "cr%d", cr);
-             (*info->fprintf_styled_func) (info->stream, dis_style_text,
-                                           "+");
+             if (svp64)
+               {
+                 (*info->fprintf_styled_func) (info->stream,
+                                               dis_style_register,
+                                               "%scr%d",
+                                               (vector ? "*" : ""),
+                                               cr);
+                 (*info->fprintf_styled_func) (info->stream, dis_style_text,
+                                               ".");
+               }
+             else
+               {
+                 (*info->fprintf_styled_func) (info->stream, dis_style_text,
+                                               "4*");
+                 (*info->fprintf_styled_func) (info->stream,
+                                               dis_style_register,
+                                               "cr%d", cr);
+                 (*info->fprintf_styled_func) (info->stream, dis_style_text,
+                                               "+");
+               }
            }
 
          (*info->fprintf_styled_func) (info->stream,
index 2ffecff825a22016069f81ab4c75081bf77ea2ca..9e6f96b8fa80207152548f4ee380afef27bd7ed8 100644 (file)
@@ -119,3 +119,81 @@ svp64_lookup (uint64_t insn, ppc_cpu_t dialect,
 
   return opcode;
 }
+
+static int64_t
+svp64_operand_value_common (const struct svp64_ctx *svp64,
+  int64_t value, ppc_opindex_t opindex, bool *vector,
+  int vector_shift, int scalar_shift, int spec_shift)
+{
+  uint64_t spec;
+  const struct svp64_extra_desc *desc;
+
+  desc = svp64_extra_desc (svp64->desc, opindex);
+  spec = (*desc->get) (&svp64->insn);
+
+  if (spec == 0)
+    return value;
+
+  *vector = (((spec >> 2) & 1) != 0);
+  if (svp64->desc->etype == SVP64_ETYPE_EXTRA2)
+    spec <<= 1;
+
+  spec = (spec & 0x3);
+
+  if (*vector)
+    value = ((value << vector_shift) | (spec << spec_shift));
+  else
+    value = ((spec << scalar_shift) | value);
+
+  return value;
+}
+
+static int64_t
+svp64_operand_value_gpr (const struct svp64_ctx *svp64,
+  int64_t value, ppc_opindex_t opindex, bool *vector)
+{
+  return svp64_operand_value_common (svp64, value, opindex, vector, 2, 5, 0);
+}
+
+static int64_t
+svp64_operand_value_fpr (const struct svp64_ctx *svp64,
+  int64_t value, ppc_opindex_t opindex, bool *vector)
+{
+  return svp64_operand_value_common (svp64, value, opindex, vector, 2, 5, 0);
+}
+
+static int64_t
+svp64_operand_value_cr_reg (const struct svp64_ctx *svp64,
+  int64_t value, ppc_opindex_t opindex, bool *vector)
+{
+  return svp64_operand_value_common (svp64, value, opindex, vector, 4, 3, 2);
+}
+
+static int64_t
+svp64_operand_value_cr_bit (const struct svp64_ctx *svp64,
+  int64_t value, ppc_opindex_t opindex, bool *vector)
+{
+  uint64_t bits = (value & 0x3);
+
+  value >>= 2;
+  value = svp64_operand_value_common (svp64, value, opindex, vector, 4, 3, 2);
+  value = ((value << 2) | bits);
+
+  return value;
+}
+
+static int64_t
+svp64_operand_value (const struct svp64_ctx *svp64,
+  int64_t value, ppc_opindex_t opindex, uint64_t flags, bool *vector)
+{
+  if (flags & (PPC_OPERAND_GPR | PPC_OPERAND_GPR_0))
+    return svp64_operand_value_gpr (svp64, value, opindex, vector);
+  else if (flags & PPC_OPERAND_FPR)
+    return svp64_operand_value_fpr (svp64, value, opindex, vector);
+  else if (flags & PPC_OPERAND_CR_REG)
+    return svp64_operand_value_cr_reg (svp64, value, opindex, vector);
+  else if (flags & PPC_OPERAND_CR_BIT)
+    return svp64_operand_value_cr_bit (svp64, value, opindex, vector);
+  else
+    return value;
+}