ppc: decouple print_insn_powerpc_opcode routine
[binutils-gdb.git] / opcodes / ppc-dis.c
index 3ba06274b21671d0a1fd710e317334b74ccc60d3..3c74f9666d01a7ae3805af6ef2542260567eb988 100644 (file)
@@ -862,6 +862,185 @@ print_got_plt (struct sec_buf *sb, uint64_t vma, struct disassemble_info *info)
   return false;
 }
 
+static void
+print_insn_powerpc_opcode (struct disassemble_info *info,
+                          bfd_vma memaddr, uint64_t insn, ppc_cpu_t dialect,
+                          const struct powerpc_opcode *opcode)
+{
+  const ppc_opindex_t *opindex;
+  const struct powerpc_operand *operand;
+  enum {
+    need_comma = 0,
+    need_1space = 1,
+    need_2spaces = 2,
+    need_3spaces = 3,
+    need_4spaces = 4,
+    need_5spaces = 5,
+    need_6spaces = 6,
+    need_7spaces = 7,
+    need_paren
+  } op_separator;
+  bool skip_optional;
+  bool is_pcrel;
+  uint64_t d34;
+  int blanks;
+
+  (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+                               "%s", opcode->name);
+  /* gdb fprintf_styled_func doesn't return count printed.  */
+  blanks = 8 - strlen (opcode->name);
+  if (blanks <= 0)
+    blanks = 1;
+
+  /* Now extract and print the operands.  */
+  op_separator = blanks;
+  skip_optional = false;
+  is_pcrel = false;
+  d34 = 0;
+  for (opindex = opcode->operands; *opindex != 0; opindex++)
+    {
+      int64_t value;
+
+      operand = powerpc_operands + *opindex;
+
+      /* If all of the optional operands past this one have their
+        default value, then don't print any of them.  Except in
+        raw mode, print them all.  */
+      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
+         && (dialect & PPC_OPCODE_RAW) == 0)
+       {
+         if (!skip_optional)
+           skip_optional = skip_optional_operands (opindex, insn,
+                                                   dialect, &is_pcrel);
+         if (skip_optional)
+           continue;
+       }
+
+      value = operand_value_powerpc (operand, insn, dialect);
+
+      if (op_separator == need_comma)
+       (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
+      else if (op_separator == need_paren)
+       (*info->fprintf_styled_func) (info->stream, dis_style_text, "(");
+      else
+       (*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_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,
+                                           "+");
+           }
+
+         (*info->fprintf_styled_func) (info->stream,
+                                       dis_style_sub_mnemonic,
+                                       "%s", cbnames[cc]);
+       }
+      else
+       {
+         /* An immediate, but what style?  */
+         enum disassembler_style style;
+
+         if ((operand->flags & PPC_OPERAND_PARENS) != 0)
+           style = dis_style_address_offset;
+         else
+           style = dis_style_immediate;
+
+         (*info->fprintf_styled_func) (info->stream, style,
+                                       "%" PRId64, value);
+       }
+
+      if (operand->shift == 52)
+       is_pcrel = value != 0;
+      else if (operand->bitm == UINT64_C (0x3ffffffff))
+       d34 = value;
+
+      if (op_separator == need_paren)
+       (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
+
+      op_separator = need_comma;
+      if ((operand->flags & PPC_OPERAND_PARENS) != 0)
+       op_separator = need_paren;
+    }
+
+  if (is_pcrel)
+    {
+      d34 += memaddr;
+      (*info->fprintf_styled_func) (info->stream,
+                                   dis_style_comment_start,
+                                   "\t# %" PRIx64, d34);
+      asymbol *sym = (*info->symbol_at_address_func) (d34, info);
+      if (sym)
+       (*info->fprintf_styled_func) (info->stream, dis_style_text,
+                                     " <%s>", bfd_asymbol_name (sym));
+
+      if (info->private_data != NULL
+         && info->section != NULL
+         && info->section->owner != NULL
+         && (bfd_get_file_flags (info->section->owner)
+             & (EXEC_P | DYNAMIC)) != 0
+         && ((insn & ((-1ULL << 50) | (0x3fULL << 26)))
+             == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26)) /* pld */))
+       {
+         for (int i = 0; i < 2; i++)
+           if (print_got_plt (private_data (info)->special + i, d34, info))
+             break;
+       }
+    }
+}
+
 /* Print a PowerPC or POWER instruction.  */
 
 static int
@@ -944,199 +1123,23 @@ print_insn_powerpc (bfd_vma memaddr,
        opcode = lookup_powerpc (insn, dialect);
     }
 
-  if (opcode != NULL)
+  if (opcode == NULL)
     {
-      const ppc_opindex_t *opindex;
-      const struct powerpc_operand *operand;
-      enum {
-       need_comma = 0,
-       need_1space = 1,
-       need_2spaces = 2,
-       need_3spaces = 3,
-       need_4spaces = 4,
-       need_5spaces = 5,
-       need_6spaces = 6,
-       need_7spaces = 7,
-       need_paren
-      } op_separator;
-      bool skip_optional;
-      bool is_pcrel;
-      uint64_t d34;
-      int blanks;
-
-      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
-                                   "%s", opcode->name);
-      /* gdb fprintf_styled_func doesn't return count printed.  */
-      blanks = 8 - strlen (opcode->name);
-      if (blanks <= 0)
-       blanks = 1;
-
-      /* Now extract and print the operands.  */
-      op_separator = blanks;
-      skip_optional = false;
-      is_pcrel = false;
-      d34 = 0;
-      for (opindex = opcode->operands; *opindex != 0; opindex++)
-       {
-         int64_t value;
-
-         operand = powerpc_operands + *opindex;
-
-         /* If all of the optional operands past this one have their
-            default value, then don't print any of them.  Except in
-            raw mode, print them all.  */
-         if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
-             && (dialect & PPC_OPCODE_RAW) == 0)
-           {
-             if (!skip_optional)
-               skip_optional = skip_optional_operands (opindex, insn,
-                                                       dialect, &is_pcrel);
-             if (skip_optional)
-               continue;
-           }
-
-         value = operand_value_powerpc (operand, insn, dialect);
-
-         if (op_separator == need_comma)
-           (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
-         else if (op_separator == need_paren)
-           (*info->fprintf_styled_func) (info->stream, dis_style_text, "(");
-         else
-           (*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_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,
-                                               "+");
-               }
-
-             (*info->fprintf_styled_func) (info->stream,
-                                           dis_style_sub_mnemonic,
-                                           "%s", cbnames[cc]);
-           }
-         else
-           {
-             /* An immediate, but what style?  */
-             enum disassembler_style style;
-
-             if ((operand->flags & PPC_OPERAND_PARENS) != 0)
-               style = dis_style_address_offset;
-             else
-               style = dis_style_immediate;
-
-             (*info->fprintf_styled_func) (info->stream, style,
-                                           "%" PRId64, value);
-           }
-
-         if (operand->shift == 52)
-           is_pcrel = value != 0;
-         else if (operand->bitm == UINT64_C (0x3ffffffff))
-           d34 = value;
-
-         if (op_separator == need_paren)
-           (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
-
-         op_separator = need_comma;
-         if ((operand->flags & PPC_OPERAND_PARENS) != 0)
-           op_separator = need_paren;
-       }
-
-      if (is_pcrel)
+      if (insn_length == 4)
+       (*info->fprintf_styled_func) (info->stream,
+                                     dis_style_assembler_directive, ".long");
+      else
        {
-         d34 += memaddr;
          (*info->fprintf_styled_func) (info->stream,
-                                       dis_style_comment_start,
-                                       "\t# %" PRIx64, d34);
-         asymbol *sym = (*info->symbol_at_address_func) (d34, info);
-         if (sym)
-           (*info->fprintf_styled_func) (info->stream, dis_style_text,
-                                         " <%s>", bfd_asymbol_name (sym));
-
-         if (info->private_data != NULL
-             && info->section != NULL
-             && info->section->owner != NULL
-             && (bfd_get_file_flags (info->section->owner)
-                 & (EXEC_P | DYNAMIC)) != 0
-             && ((insn & ((-1ULL << 50) | (0x3fULL << 26)))
-                 == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26)) /* pld */))
-           {
-             for (int i = 0; i < 2; i++)
-               if (print_got_plt (private_data (info)->special + i, d34, info))
-                 break;
-           }
+                                       dis_style_assembler_directive, ".word");
+         insn >>= 16;
        }
-
-      /* We have found and printed an instruction.  */
-      return insn_length;
+      (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
+      (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x%x",
+                                   (unsigned int) insn);
     }
-
-  /* We could not find a match.  */
-  if (insn_length == 4)
-    (*info->fprintf_styled_func) (info->stream,
-                                 dis_style_assembler_directive, ".long");
   else
-    {
-      (*info->fprintf_styled_func) (info->stream,
-                                   dis_style_assembler_directive, ".word");
-      insn >>= 16;
-    }
-  (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
-  (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x%x",
-                               (unsigned int) insn);
-
+    print_insn_powerpc_opcode (info, memaddr, insn, dialect, opcode);
 
   return insn_length;
 }