libopcodes/ppc: add support for disassembler styling
authorAndrew Burgess <aburgess@redhat.com>
Fri, 8 Jul 2022 14:03:03 +0000 (15:03 +0100)
committerAndrew Burgess <aburgess@redhat.com>
Mon, 25 Jul 2022 13:13:34 +0000 (14:13 +0100)
This commit adds disassembler styling to the libopcodes ppc
disassembler.  This conversion was pretty straight forward, I just
converted the fprintf_func calls to fprintf_styled_func calls and
added an appropriate style.

For testing the new styling I just assembled then disassembled the
source files in gas/testsuite/gas/ppc and manually checked that the
styling looked reasonable.

I think the only slightly weird case was how things like '4*cr1+eq'
are styled.  As best I can tell, this construct, used for example in
this instruction:

  crand   4*cr1+lt,4*cr1+gt,4*cr1+eq

is used to access a field of a control register.  I initially tried
styling this whole construct as a register[1], but during review it
was suggested that instead different parts of the text should have
different styles.  In this commit I propose styling '4*cr1+lt' like
this:

  4    - immediate,
  *    - text,
  cr1  - register
  +    - text
  lt   - sub-mnemonic

If the user does not request styled output from objdump, then there
should be no change in the disassembler output after this commit.

[1] https://sourceware.org/pipermail/binutils/2022-July/121771.html

opcodes/disassemble.c
opcodes/ppc-dis.c

index e2e5a2608d6f581ddc14c15eb8cd5f3f85739175..4090e94b623f9e9d6c93c4c0b4dc8d12c369c0e4 100644 (file)
@@ -710,6 +710,7 @@ disassemble_init_for_target (struct disassemble_info * info)
 #endif
 #if defined (ARCH_powerpc) || defined (ARCH_rs6000)
       disassemble_init_powerpc (info);
+      info->created_styled_output = true;
       break;
 #endif
 #ifdef ARCH_riscv
index 45e8faeef5e55738546c5233032765072f0ce2b3..7c7dde87f00ed951c985cb4cf0aa43b787659b50 100644 (file)
@@ -829,12 +829,24 @@ print_got_plt (struct sec_buf *sb, uint64_t vma, struct disassemble_info *info)
                    sym = (*info->symbol_at_address_func) (ent, info);
                }
            }
+         (*info->fprintf_styled_func) (info->stream, dis_style_text, " [");
          if (sym != NULL)
-           (*info->fprintf_func) (info->stream, " [%s@%s]",
-                                  bfd_asymbol_name (sym), sb->name + 1);
+           {
+             (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
+                                           "%s", bfd_asymbol_name (sym));
+             (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
+             (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
+                                           "%s", sb->name + 1);
+           }
          else
-           (*info->fprintf_func) (info->stream, " [%" PRIx64 "@%s]",
-                                  ent, sb->name + 1);
+           {
+             (*info->fprintf_styled_func) (info->stream, dis_style_address,
+                                           "%" PRIx64, ent);
+             (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
+             (*info->fprintf_styled_func) (info->stream, dis_style_symbol,
+                                           "%s", sb->name + 1);
+           }
+         (*info->fprintf_styled_func) (info->stream, dis_style_text, "]");
          return true;
        }
     }
@@ -943,8 +955,9 @@ print_insn_powerpc (bfd_vma memaddr,
       uint64_t d34;
       int blanks;
 
-      (*info->fprintf_func) (info->stream, "%s", opcode->name);
-      /* gdb fprintf_func doesn't return count printed.  */
+      (*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;
@@ -976,39 +989,49 @@ print_insn_powerpc (bfd_vma memaddr,
          value = operand_value_powerpc (operand, insn, dialect);
 
          if (op_separator == need_comma)
-           (*info->fprintf_func) (info->stream, ",");
+           (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
          else if (op_separator == need_paren)
-           (*info->fprintf_func) (info->stream, "(");
+           (*info->fprintf_styled_func) (info->stream, dis_style_text, "(");
          else
-           (*info->fprintf_func) (info->stream, "%*s", op_separator, " ");
+           (*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_func) (info->stream, "r%" PRId64, value);
+           (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                         "r%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_FPR) != 0)
-           (*info->fprintf_func) (info->stream, "f%" PRId64, value);
+           (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                         "f%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_VR) != 0)
-           (*info->fprintf_func) (info->stream, "v%" PRId64, value);
+           (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                         "v%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_VSR) != 0)
-           (*info->fprintf_func) (info->stream, "vs%" PRId64, value);
+           (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                         "vs%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_ACC) != 0)
-           (*info->fprintf_func) (info->stream, "a%" PRId64, value);
+           (*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_func) (info->stream, "fsl%" PRId64, value);
+           (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                         "fsl%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_FCR) != 0)
-           (*info->fprintf_func) (info->stream, "fcr%" PRId64, value);
+           (*info->fprintf_styled_func) (info->stream, dis_style_register,
+                                         "fcr%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_UDI) != 0)
-           (*info->fprintf_func) (info->stream, "%" PRId64, value);
+           (*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_func) (info->stream, "cr%" PRId64, value);
+           (*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)
@@ -1019,13 +1042,35 @@ print_insn_powerpc (bfd_vma memaddr,
              int cc;
 
              cr = value >> 2;
-             if (cr != 0)
-               (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
              cc = value & 3;
-             (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
+             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
-           (*info->fprintf_func) (info->stream, "%" PRId64, value);
+           {
+             /* 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;
@@ -1033,7 +1078,7 @@ print_insn_powerpc (bfd_vma memaddr,
            d34 = value;
 
          if (op_separator == need_paren)
-           (*info->fprintf_func) (info->stream, ")");
+           (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
 
          op_separator = need_comma;
          if ((operand->flags & PPC_OPERAND_PARENS) != 0)
@@ -1043,11 +1088,13 @@ print_insn_powerpc (bfd_vma memaddr,
       if (is_pcrel)
        {
          d34 += memaddr;
-         (*info->fprintf_func) (info->stream, "\t# %" PRIx64, d34);
+         (*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_func) (info->stream, " <%s>",
-                                  bfd_asymbol_name (sym));
+           (*info->fprintf_styled_func) (info->stream, dis_style_text,
+                                         " <%s>", bfd_asymbol_name (sym));
 
          if (info->private_data != NULL
              && info->section != NULL
@@ -1069,11 +1116,19 @@ print_insn_powerpc (bfd_vma memaddr,
 
   /* We could not find a match.  */
   if (insn_length == 4)
-    (*info->fprintf_func) (info->stream, ".long 0x%x",
-                          (unsigned int) insn);
+    (*info->fprintf_styled_func) (info->stream,
+                                 dis_style_assembler_directive, ".long");
   else
-    (*info->fprintf_func) (info->stream, ".word 0x%x",
-                          (unsigned int) insn >> 16);
+    {
+      (*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);
+
+
   return insn_length;
 }