public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/2] AArch64 libopcodes styling
@ 2022-06-21 11:22 Andrew Burgess
  2022-06-21 11:22 ` [PATCH 1/2] opcodes/aarch64: split off creation of comment text in disassembler Andrew Burgess
                   ` (2 more replies)
  0 siblings, 3 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-06-21 11:22 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

This series adds libopcodes based styling to the AArch64 disassembler
output, this enables 'objdump -d --disassembler-color=extended-color'
to work for AArch64.

The first commit is a small refactor, while the second commit actually
adds the styling support.

There's a couple of questions that I still have, which I've detailed
in the commit message of the second patch.

All feedback welcome.

Thanks,
Andrew


---

Andrew Burgess (2):
  opcodes/aarch64: split off creation of comment text in disassembler
  libopcodes/aarch64: add support for disassembler styling

 gas/config/tc-aarch64.c                       |  21 +-
 gas/testsuite/gas/aarch64/alias.d             |  26 +-
 gas/testsuite/gas/aarch64/b_c_1.d             |  42 +-
 gas/testsuite/gas/aarch64/float-fp16.d        |  12 +-
 gas/testsuite/gas/aarch64/int-insns.d         |   4 +-
 gas/testsuite/gas/aarch64/no-aliases.d        |  26 +-
 .../gas/aarch64/programmer-friendly.d         |   2 +-
 include/opcode/aarch64.h                      |  10 +-
 opcodes/aarch64-dis.c                         | 185 +++++++--
 opcodes/aarch64-opc.c                         | 367 +++++++++++++-----
 10 files changed, 504 insertions(+), 191 deletions(-)

-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 1/2] opcodes/aarch64: split off creation of comment text in disassembler
  2022-06-21 11:22 [PATCH 0/2] AArch64 libopcodes styling Andrew Burgess
@ 2022-06-21 11:22 ` Andrew Burgess
  2022-06-22 11:02   ` Nick Clifton
  2022-06-21 11:22 ` [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
  2022-07-05 12:45 ` [PATCHv2 0/2] AArch64 libopcodes styling Andrew Burgess
  2 siblings, 1 reply; 31+ messages in thread
From: Andrew Burgess @ 2022-06-21 11:22 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

The function aarch64_print_operand (aarch64-opc.c) is responsible for
converting an instruction operand into the textual representation of
that operand.

In some cases, a comment is included in the operand representation,
though this (currently) only happens for the last operand of the
instruction.

In a future commit I would like to enable the new libopcodes styling
for AArch64, this will allow objdump and GDB[1] to syntax highlight
the disassembler output, however, having operands and comments
combined in a single string like this makes such styling harder.

In this commit, I propose to extend aarch64_print_operand to take a
second buffer.  Any comments for the instruction are written into this
extra buffer.  The two callers of aarch64_print_operand are then
updated to pass an extra buffer, and print any resulting comment.

In this commit no styling is added, that will come later.  However, I
have adjusted the output slightly.  Before this commit some comments
would be separated from the instruction operands with a tab character,
while in other cases the comment was separated with two single spaces.

After this commit I use a single tab character in all cases.  This
means a few test cases needed updated.  If people would prefer me to
move everyone to use the two spaces, then just let me know.  Or maybe
there was a good reason why we used a mix of styles, I could probably
figure out a way to maintain the old output exactly if that is
critical.

Other than that, there should be no user visible changes after this
commit.

[1] GDB patches have not been merged yet, but have been posted to the
GDB mailing list:
https://sourceware.org/pipermail/gdb-patches/2022-June/190142.html
---
 gas/config/tc-aarch64.c                       | 12 +++++-
 gas/testsuite/gas/aarch64/alias.d             | 26 ++++++------
 gas/testsuite/gas/aarch64/b_c_1.d             | 42 +++++++++----------
 gas/testsuite/gas/aarch64/float-fp16.d        | 12 +++---
 gas/testsuite/gas/aarch64/int-insns.d         |  4 +-
 gas/testsuite/gas/aarch64/no-aliases.d        | 26 ++++++------
 .../gas/aarch64/programmer-friendly.d         |  2 +-
 include/opcode/aarch64.h                      |  2 +-
 opcodes/aarch64-dis.c                         | 15 ++++++-
 opcodes/aarch64-opc.c                         | 22 +++++++---
 10 files changed, 97 insertions(+), 66 deletions(-)

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index e9f7ee9fc96..779db31828b 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -5358,6 +5358,7 @@ print_operands (char *buf, const aarch64_opcode *opcode,
   for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
       char str[128];
+      char cmt[128];
 
       /* We regard the opcode operand info more, however we also look into
 	 the inst->operands to support the disassembling of the optional
@@ -5370,7 +5371,7 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL,
-			     NULL, cpu_variant);
+			     NULL, cmt, sizeof (cmt), cpu_variant);
 
       /* Delimiter.  */
       if (str[0] != '\0')
@@ -5378,6 +5379,15 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 
       /* Append the operand string.  */
       strcat (buf, str);
+
+      /* Append a comment.  This works because only the last operand ever
+	 adds a comment.  If that ever changes then we'll need to be
+	 smarter here.  */
+      if (cmt[0] != '\0')
+	{
+	  strcat (buf, "\t// ");
+	  strcat (buf, cmt);
+	}
     }
 }
 
diff --git a/gas/testsuite/gas/aarch64/alias.d b/gas/testsuite/gas/aarch64/alias.d
index 13b943c1b97..b1d1a9a37c2 100644
--- a/gas/testsuite/gas/aarch64/alias.d
+++ b/gas/testsuite/gas/aarch64/alias.d
@@ -29,19 +29,19 @@ Disassembly of section \.text:
   54:	9ba28c20 	umsubl	x0, w1, w2, x3
   58:	9ba2fc20 	umnegl	x0, w1, w2
   5c:	9ba2fc20 	umnegl	x0, w1, w2
-  60:	1a9f0420 	csinc	w0, w1, wzr, eq  // eq = none
-  64:	1a810420 	cinc	w0, w1, ne  // ne = any
-  68:	1a810420 	cinc	w0, w1, ne  // ne = any
-  6c:	1a9f37e0 	cset	w0, cs  // cs = hs, nlast
-  70:	1a9f37e0 	cset	w0, cs  // cs = hs, nlast
-  74:	da9f2020 	csinv	x0, x1, xzr, cs  // cs = hs, nlast
-  78:	da812020 	cinv	x0, x1, cc  // cc = lo, ul, last
-  7c:	da812020 	cinv	x0, x1, cc  // cc = lo, ul, last
-  80:	da9f43e0 	csetm	x0, pl  // pl = nfrst
-  84:	da9f43e0 	csetm	x0, pl  // pl = nfrst
-  88:	da9eb7e0 	csneg	x0, xzr, x30, lt  // lt = tstop
-  8c:	da9eb7c0 	cneg	x0, x30, ge  // ge = tcont
-  90:	da9eb7c0 	cneg	x0, x30, ge  // ge = tcont
+  60:	1a9f0420 	csinc	w0, w1, wzr, eq	// eq = none
+  64:	1a810420 	cinc	w0, w1, ne	// ne = any
+  68:	1a810420 	cinc	w0, w1, ne	// ne = any
+  6c:	1a9f37e0 	cset	w0, cs	// cs = hs, nlast
+  70:	1a9f37e0 	cset	w0, cs	// cs = hs, nlast
+  74:	da9f2020 	csinv	x0, x1, xzr, cs	// cs = hs, nlast
+  78:	da812020 	cinv	x0, x1, cc	// cc = lo, ul, last
+  7c:	da812020 	cinv	x0, x1, cc	// cc = lo, ul, last
+  80:	da9f43e0 	csetm	x0, pl	// pl = nfrst
+  84:	da9f43e0 	csetm	x0, pl	// pl = nfrst
+  88:	da9eb7e0 	csneg	x0, xzr, x30, lt	// lt = tstop
+  8c:	da9eb7c0 	cneg	x0, x30, ge	// ge = tcont
+  90:	da9eb7c0 	cneg	x0, x30, ge	// ge = tcont
   94:	ea020020 	ands	x0, x1, x2
   98:	ea02003f 	tst	x1, x2
   9c:	ea02003f 	tst	x1, x2
diff --git a/gas/testsuite/gas/aarch64/b_c_1.d b/gas/testsuite/gas/aarch64/b_c_1.d
index 6427a3a63a5..f9359a4842c 100644
--- a/gas/testsuite/gas/aarch64/b_c_1.d
+++ b/gas/testsuite/gas/aarch64/b_c_1.d
@@ -31,28 +31,28 @@ Disassembly of section \.text:
 .*:	54.....b 	b\.lt	0 <\.text>  // b\.tstop
 .*:	54.....c 	b\.gt	0 <\.text>
 .*:	54.....d 	b\.le	0 <\.text>
-.*:	9a830041 	csel	x1, x2, x3, eq  // eq = none
-.*:	9a830041 	csel	x1, x2, x3, eq  // eq = none
-.*:	9a832041 	csel	x1, x2, x3, cs  // cs = hs, nlast
-.*:	9a832041 	csel	x1, x2, x3, cs  // cs = hs, nlast
-.*:	9a832041 	csel	x1, x2, x3, cs  // cs = hs, nlast
-.*:	9a833041 	csel	x1, x2, x3, cc  // cc = lo, ul, last
-.*:	9a833041 	csel	x1, x2, x3, cc  // cc = lo, ul, last
-.*:	9a833041 	csel	x1, x2, x3, cc  // cc = lo, ul, last
-.*:	9a833041 	csel	x1, x2, x3, cc  // cc = lo, ul, last
-.*:	9a834041 	csel	x1, x2, x3, mi  // mi = first
-.*:	9a834041 	csel	x1, x2, x3, mi  // mi = first
-.*:	9a835041 	csel	x1, x2, x3, pl  // pl = nfrst
-.*:	9a835041 	csel	x1, x2, x3, pl  // pl = nfrst
+.*:	9a830041 	csel	x1, x2, x3, eq	// eq = none
+.*:	9a830041 	csel	x1, x2, x3, eq	// eq = none
+.*:	9a832041 	csel	x1, x2, x3, cs	// cs = hs, nlast
+.*:	9a832041 	csel	x1, x2, x3, cs	// cs = hs, nlast
+.*:	9a832041 	csel	x1, x2, x3, cs	// cs = hs, nlast
+.*:	9a833041 	csel	x1, x2, x3, cc	// cc = lo, ul, last
+.*:	9a833041 	csel	x1, x2, x3, cc	// cc = lo, ul, last
+.*:	9a833041 	csel	x1, x2, x3, cc	// cc = lo, ul, last
+.*:	9a833041 	csel	x1, x2, x3, cc	// cc = lo, ul, last
+.*:	9a834041 	csel	x1, x2, x3, mi	// mi = first
+.*:	9a834041 	csel	x1, x2, x3, mi	// mi = first
+.*:	9a835041 	csel	x1, x2, x3, pl	// pl = nfrst
+.*:	9a835041 	csel	x1, x2, x3, pl	// pl = nfrst
 .*:	9a836041 	csel	x1, x2, x3, vs
 .*:	9a837041 	csel	x1, x2, x3, vc
-.*:	9a838041 	csel	x1, x2, x3, hi  // hi = pmore
-.*:	9a838041 	csel	x1, x2, x3, hi  // hi = pmore
-.*:	9a839041 	csel	x1, x2, x3, ls  // ls = plast
-.*:	9a839041 	csel	x1, x2, x3, ls  // ls = plast
-.*:	9a83a041 	csel	x1, x2, x3, ge  // ge = tcont
-.*:	9a83a041 	csel	x1, x2, x3, ge  // ge = tcont
-.*:	9a83b041 	csel	x1, x2, x3, lt  // lt = tstop
-.*:	9a83b041 	csel	x1, x2, x3, lt  // lt = tstop
+.*:	9a838041 	csel	x1, x2, x3, hi	// hi = pmore
+.*:	9a838041 	csel	x1, x2, x3, hi	// hi = pmore
+.*:	9a839041 	csel	x1, x2, x3, ls	// ls = plast
+.*:	9a839041 	csel	x1, x2, x3, ls	// ls = plast
+.*:	9a83a041 	csel	x1, x2, x3, ge	// ge = tcont
+.*:	9a83a041 	csel	x1, x2, x3, ge	// ge = tcont
+.*:	9a83b041 	csel	x1, x2, x3, lt	// lt = tstop
+.*:	9a83b041 	csel	x1, x2, x3, lt	// lt = tstop
 .*:	9a83c041 	csel	x1, x2, x3, gt
 .*:	9a83d041 	csel	x1, x2, x3, le
diff --git a/gas/testsuite/gas/aarch64/float-fp16.d b/gas/testsuite/gas/aarch64/float-fp16.d
index d1d69d820f0..3d96a45a80c 100644
--- a/gas/testsuite/gas/aarch64/float-fp16.d
+++ b/gas/testsuite/gas/aarch64/float-fp16.d
@@ -6,12 +6,12 @@
 Disassembly of section \.text:
 
 0+ <.*>:
-   [0-9a-f]+:	1e200400 	fccmp	s0, s0, #0x0, eq  // eq = none
-   [0-9a-f]+:	1ee00400 	fccmp	h0, h0, #0x0, eq  // eq = none
+   [0-9a-f]+:	1e200400 	fccmp	s0, s0, #0x0, eq	// eq = none
+   [0-9a-f]+:	1ee00400 	fccmp	h0, h0, #0x0, eq	// eq = none
    [0-9a-f]+:	1e22d420 	fccmp	s1, s2, #0x0, le
    [0-9a-f]+:	1ee2d420 	fccmp	h1, h2, #0x0, le
-  [0-9a-f]+:	1e200410 	fccmpe	s0, s0, #0x0, eq  // eq = none
-  [0-9a-f]+:	1ee00410 	fccmpe	h0, h0, #0x0, eq  // eq = none
+  [0-9a-f]+:	1e200410 	fccmpe	s0, s0, #0x0, eq	// eq = none
+  [0-9a-f]+:	1ee00410 	fccmpe	h0, h0, #0x0, eq	// eq = none
   [0-9a-f]+:	1e22d430 	fccmpe	s1, s2, #0x0, le
   [0-9a-f]+:	1ee2d430 	fccmpe	h1, h2, #0x0, le
   [0-9a-f]+:	1e202000 	fcmp	s0, s0
@@ -26,8 +26,8 @@ Disassembly of section \.text:
   [0-9a-f]+:	1ee02008 	fcmp	h0, #0\.0
   [0-9a-f]+:	1e202018 	fcmpe	s0, #0\.0
   [0-9a-f]+:	1ee02018 	fcmpe	h0, #0\.0
-  [0-9a-f]+:	1e210c00 	fcsel	s0, s0, s1, eq  // eq = none
-  [0-9a-f]+:	1ee10c00 	fcsel	h0, h0, h1, eq  // eq = none
+  [0-9a-f]+:	1e210c00 	fcsel	s0, s0, s1, eq	// eq = none
+  [0-9a-f]+:	1ee10c00 	fcsel	h0, h0, h1, eq	// eq = none
   [0-9a-f]+:	9ee60000 	fmov	x0, h0
   [0-9a-f]+:	1ee60000 	fmov	w0, h0
   [0-9a-f]+:	9ee70001 	fmov	h1, x0
diff --git a/gas/testsuite/gas/aarch64/int-insns.d b/gas/testsuite/gas/aarch64/int-insns.d
index 419b8a6e841..76f937c4fbf 100644
--- a/gas/testsuite/gas/aarch64/int-insns.d
+++ b/gas/testsuite/gas/aarch64/int-insns.d
@@ -13,8 +13,8 @@ Disassembly of section .text:
   10:	93c3fc41 	extr	x1, x2, x3, #63
   14:	93c30041 	extr	x1, x2, x3, #0
   18:	13837c41 	extr	w1, w2, w3, #31
-  1c:	9a9f17e1 	cset	x1, eq  // eq = none
-  20:	da9f13e1 	csetm	x1, eq  // eq = none
+  1c:	9a9f17e1 	cset	x1, eq	// eq = none
+  20:	da9f13e1 	csetm	x1, eq	// eq = none
   24:	71000021 	subs	w1, w1, #0x0
   28:	7100003f 	cmp	w1, #0x0
   2c:	4b0203e1 	neg	w1, w2
diff --git a/gas/testsuite/gas/aarch64/no-aliases.d b/gas/testsuite/gas/aarch64/no-aliases.d
index dae0b712dab..3cee28df657 100644
--- a/gas/testsuite/gas/aarch64/no-aliases.d
+++ b/gas/testsuite/gas/aarch64/no-aliases.d
@@ -30,19 +30,19 @@ Disassembly of section \.text:
   54:	9ba28c20 	umsubl	x0, w1, w2, x3
   58:	9ba2fc20 	umsubl	x0, w1, w2, xzr
   5c:	9ba2fc20 	umsubl	x0, w1, w2, xzr
-  60:	1a9f0420 	csinc	w0, w1, wzr, eq  // eq = none
-  64:	1a810420 	csinc	w0, w1, w1, eq  // eq = none
-  68:	1a810420 	csinc	w0, w1, w1, eq  // eq = none
-  6c:	1a9f37e0 	csinc	w0, wzr, wzr, cc  // cc = lo, ul, last
-  70:	1a9f37e0 	csinc	w0, wzr, wzr, cc  // cc = lo, ul, last
-  74:	da9f2020 	csinv	x0, x1, xzr, cs  // cs = hs, nlast
-  78:	da812020 	csinv	x0, x1, x1, cs  // cs = hs, nlast
-  7c:	da812020 	csinv	x0, x1, x1, cs  // cs = hs, nlast
-  80:	da9f43e0 	csinv	x0, xzr, xzr, mi  // mi = first
-  84:	da9f43e0 	csinv	x0, xzr, xzr, mi  // mi = first
-  88:	da9eb7e0 	csneg	x0, xzr, x30, lt  // lt = tstop
-  8c:	da9eb7c0 	csneg	x0, x30, x30, lt  // lt = tstop
-  90:	da9eb7c0 	csneg	x0, x30, x30, lt  // lt = tstop
+  60:	1a9f0420 	csinc	w0, w1, wzr, eq	// eq = none
+  64:	1a810420 	csinc	w0, w1, w1, eq	// eq = none
+  68:	1a810420 	csinc	w0, w1, w1, eq	// eq = none
+  6c:	1a9f37e0 	csinc	w0, wzr, wzr, cc	// cc = lo, ul, last
+  70:	1a9f37e0 	csinc	w0, wzr, wzr, cc	// cc = lo, ul, last
+  74:	da9f2020 	csinv	x0, x1, xzr, cs	// cs = hs, nlast
+  78:	da812020 	csinv	x0, x1, x1, cs	// cs = hs, nlast
+  7c:	da812020 	csinv	x0, x1, x1, cs	// cs = hs, nlast
+  80:	da9f43e0 	csinv	x0, xzr, xzr, mi	// mi = first
+  84:	da9f43e0 	csinv	x0, xzr, xzr, mi	// mi = first
+  88:	da9eb7e0 	csneg	x0, xzr, x30, lt	// lt = tstop
+  8c:	da9eb7c0 	csneg	x0, x30, x30, lt	// lt = tstop
+  90:	da9eb7c0 	csneg	x0, x30, x30, lt	// lt = tstop
   94:	ea020020 	ands	x0, x1, x2
   98:	ea02003f 	ands	xzr, x1, x2
   9c:	ea02003f 	ands	xzr, x1, x2
diff --git a/gas/testsuite/gas/aarch64/programmer-friendly.d b/gas/testsuite/gas/aarch64/programmer-friendly.d
index 668a13506fb..8fa6aa70dbf 100644
--- a/gas/testsuite/gas/aarch64/programmer-friendly.d
+++ b/gas/testsuite/gas/aarch64/programmer-friendly.d
@@ -10,7 +10,7 @@ Disassembly of section \.text:
    4:	98000241 	ldrsw	x1, 4c <\.text\+0x4c>
    8:	98000007 	ldrsw	x7, 0 <\.text>
 			8: R_AARCH64_LD_PREL_LO19	\.data\+0x4
-   c:	fa42a02a 	ccmp	x1, x2, #0xa, ge  // ge = tcont
+   c:	fa42a02a 	ccmp	x1, x2, #0xa, ge	// ge = tcont
   10:	53001eaf 	uxtb	w15, w21
   14:	53003f67 	uxth	w7, w27
   18:	2a1f03e8 	mov	w8, wzr
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 8fe27900cba..186ba9a4800 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -1371,7 +1371,7 @@ aarch64_get_opcode (enum aarch64_op);
 extern void
 aarch64_print_operand (char *, size_t, bfd_vma, const aarch64_opcode *,
 		       const aarch64_opnd_info *, int, int *, bfd_vma *,
-		       char **,
+		       char **, char *, size_t,
 		       aarch64_feature_set features);
 
 /* Miscellaneous interface.  */
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index bd2068b0f32..acaad28fdff 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -3287,6 +3287,8 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
   for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
       char str[128];
+      char cmt[128];
+
       /* We regard the opcode operand info more, however we also look into
 	 the inst->operands to support the disassembling of the optional
 	 operand.
@@ -3298,7 +3300,8 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
 
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
-			     &info->target, &notes, arch_variant);
+			     &info->target, &notes, cmt, sizeof (cmt),
+			     arch_variant);
 
       /* Print the delimiter (taking account of omitted operand(s)).  */
       if (str[0] != '\0')
@@ -3309,7 +3312,15 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
       if (pcrel_p)
 	(*info->print_address_func) (info->target, info);
       else
-	(*info->fprintf_func) (info->stream, "%s", str);
+	{
+	  (*info->fprintf_func) (info->stream, "%s", str);
+
+	  /* Print the comment.  This works because only the last operand
+	     ever adds a comment.  If that ever changes then we'll need to
+	     be smarter here.  */
+	  if (cmt[0] != '\0')
+	    (*info->fprintf_func) (info->stream, "\t// %s", cmt);
+	}
     }
 
     if (notes && !no_notes)
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 37f6dae07ad..1c93f836020 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -3229,6 +3229,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 		       const aarch64_opcode *opcode,
 		       const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
 		       bfd_vma *address, char** notes,
+		       char *comment, size_t comment_size,
 		       aarch64_feature_set features)
 {
   unsigned int i, num_conds;
@@ -3237,6 +3238,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
   enum aarch64_modifier_kind kind;
   uint64_t addr, enum_value;
 
+  if (comment != NULL)
+    {
+      assert (comment_size > 0);
+      comment[0] = '\0';
+    }
+  else
+    assert (comment_size == 0);
+
   buf[0] = '\0';
   if (pcrel_p)
     *pcrel_p = 0;
@@ -3572,12 +3581,13 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	case 4:	/* e.g. MOV Wd, #<imm32>.  */
 	    {
 	      int imm32 = opnd->imm.value;
-	      snprintf (buf, size, "#0x%-20x\t// #%d", imm32, imm32);
+	      snprintf (buf, size, "#0x%-20x", imm32);
+	      snprintf (comment, comment_size, "#%d", imm32);
 	    }
 	  break;
 	case 8:	/* e.g. MOV Xd, #<imm64>.  */
-	  snprintf (buf, size, "#0x%-20" PRIx64 "\t// #%" PRIi64,
-		    opnd->imm.value, opnd->imm.value);
+	  snprintf (buf, size, "#0x%-20" PRIx64, opnd->imm.value);
+	  snprintf (comment, comment_size, "#%" PRIi64, opnd->imm.value);
 	  break;
 	default:
 	  snprintf (buf, size, "<invalid>");
@@ -3675,12 +3685,12 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       num_conds = ARRAY_SIZE (opnd->cond->names);
       for (i = 1; i < num_conds && opnd->cond->names[i]; ++i)
 	{
-	  size_t len = strlen (buf);
+	  size_t len = comment != NULL ? strlen (comment) : 0;
 	  if (i == 1)
-	    snprintf (buf + len, size - len, "  // %s = %s",
+	    snprintf (comment + len, comment_size - len, "%s = %s",
 		      opnd->cond->names[0], opnd->cond->names[i]);
 	  else
-	    snprintf (buf + len, size - len, ", %s",
+	    snprintf (comment + len, comment_size - len, ", %s",
 		      opnd->cond->names[i]);
 	}
       break;
-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-06-21 11:22 [PATCH 0/2] AArch64 libopcodes styling Andrew Burgess
  2022-06-21 11:22 ` [PATCH 1/2] opcodes/aarch64: split off creation of comment text in disassembler Andrew Burgess
@ 2022-06-21 11:22 ` Andrew Burgess
  2022-06-22 11:15   ` Nick Clifton
                     ` (2 more replies)
  2022-07-05 12:45 ` [PATCHv2 0/2] AArch64 libopcodes styling Andrew Burgess
  2 siblings, 3 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-06-21 11:22 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

This commit enables disassembler styling for AArch64.  After this
commit it is possible to have objdump style AArch64 disassembler
output (using --disassembler-color option).  Once the required GDB
patches are merged, GDB will also style the disassembler output.

The changes to support styling are mostly split between two files
opcodes/aarch64-dis.c and opcodes/aarch64-opc.c.

The entry point for the AArch64 disassembler can be found in
aarch64-dis.c, this file handles printing the instruction mnemonics,
and assembler directives (e.g. '.byte', '.word', etc).  Some operands,
mostly relating to assembler directives are also printed from this
file.  This commit changes all of this to pass through suitable
styling information.

However, for most "normal" instructions, the instruction operands are
printed using a two step process.  From aarch64-dis.c, in the
print_operands function, the function aarch64_print_operand is called,
this function is in aarch64-opc.c, and converts an instruction operand
into a string.  Then, back in print_operands (aarch64-dis.c), the
operand string is printed.

Unfortunately, the string returned by aarch64_print_operand can be
quite complex, it will include syntax elements, like '[' and ']', in
addition to register names and immediate values.  In some cases, a
single operand will expand into what will appear (to the user) as
multiple operands separated with a ','.

This makes the task of styling more complex, all these different
components need to by styled differently, so we need to get the
styling information out of aarch64_print_operand in some way.

The solution that I propose here is similar to the solution that I
used for the i386 disassembler.

Currently, aarch64_print_operand uses snprintf to write the operand
text into a buffer provided by the caller.

What I propose is that we pass an extra argument to the
aarch64_print_operand function, this argument will be a callback
function that converts a disassembler style into a string.  These
strings can then be written into the buffer using snprintf.  Here's an
example, 'get_style' is the new callback function:

    snprintf (buf, size, "%s%s",
              get_style (dis_style_register),
              get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));

The string returned by 'get_style' is a special sequence of characters
that is not otherwise seen in the disassembler output.  In the
print_operands function we can now scan the buffer returned by
aarch64_print_operand, and split the text based on the style
markers.  Each separately styled block is then printed with the
correct style.

The aarch64_print_operand function is also called from the assembler
to aid in printing diagnostic messages.  Right now I have no plans to
add styling to the assembler output, and so, in this case, the
'get_style' callback is a dummy function that always returns an empty
string.  As a result, when the assembler calls aarch64_print_operand,
the string returns can be immediately printed with no special style
handling required.

I've gone through and updated arch64-opc.c as best I can to add
styling information.  I've mostly used the gas/testsuite/gas/aarch64
tests to check the styling, assembling then disassembling each source
file, then checking that the output looks reasonable.

I do still have a few questions about how some elements should be
styled, consider this instruction:

    add     x1, x2, x3, lsr #1
       ~~~~~  ~~  ~~  ~~   ~      Plain text.
    ~~~                           Mnemonic.
            ~~  ~~  ~~            Register.
	                    ~~    Immediate.
                        ???       What to use here?

The current patch formats the 'lsr' as text, but I wonder if this
would be better formatted as mnemonic?  Or maybe it should be
considered part of the immediate?  I'm open to peoples thoughts on
this.

I have a similar question for how to format 'ge' in:

    ccmp    x1, x2, #0xa, ge

And how to format 'sxtb' in:

    adds    x0, sp, w0, sxtb

With objdump disassembler color turned off, there should be no change
in the output after this commit.
---
 gas/config/tc-aarch64.c  |  11 +-
 include/opcode/aarch64.h |   8 +-
 opcodes/aarch64-dis.c    | 186 +++++++++++++++++----
 opcodes/aarch64-opc.c    | 349 +++++++++++++++++++++++++++------------
 4 files changed, 418 insertions(+), 136 deletions(-)

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 779db31828b..740bde53ea8 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -5347,6 +5347,15 @@ assign_qualifier_sequence (aarch64_inst *instr,
     instr->operands[i].qualifier = *qualifiers;
 }
 
+/* Return a string indicating a switch to STYLE.  As the assembler doesn't
+   use styling in its output, this always returns an empty string.  */
+
+static const char *
+get_style_text (enum disassembler_style style ATTRIBUTE_UNUSED)
+{
+  return "";
+}
+
 /* Print operands for the diagnosis purpose.  */
 
 static void
@@ -5371,7 +5380,7 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL,
-			     NULL, cmt, sizeof (cmt), cpu_variant);
+			     NULL, cmt, sizeof (cmt), cpu_variant, get_style_text);
 
       /* Delimiter.  */
       if (str[0] != '\0')
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 186ba9a4800..373deb6b49c 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -27,6 +27,8 @@
 #include <assert.h>
 #include <stdlib.h>
 
+#include "dis-asm.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -1367,12 +1369,16 @@ aarch64_replace_opcode (struct aarch64_inst *,
 extern const aarch64_opcode *
 aarch64_get_opcode (enum aarch64_op);
 
+/* Return a text string that indicates a change of disassembler style.  */
+typedef const char *(*get_style_func) (enum disassembler_style);
+
 /* Generate the string representation of an operand.  */
 extern void
 aarch64_print_operand (char *, size_t, bfd_vma, const aarch64_opcode *,
 		       const aarch64_opnd_info *, int, int *, bfd_vma *,
 		       char **, char *, size_t,
-		       aarch64_feature_set features);
+		       aarch64_feature_set features,
+		       get_style_func get_style);
 
 /* Miscellaneous interface.  */
 
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index acaad28fdff..fbbd0c5e087 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -25,9 +25,14 @@
 #include "opintl.h"
 #include "aarch64-dis.h"
 #include "elf-bfd.h"
+#include "safe-ctype.h"
 
 #define INSNLEN 4
 
+/* This character is used to encode style information within the output
+   buffers.  See get_style_text and print_operands for more details.  */
+#define STYLE_MARKER_CHAR '\002'
+
 /* Cached mapping symbol state.  */
 enum map_type
 {
@@ -3275,6 +3280,45 @@ aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst,
   return ERR_UND;
 }
 
+/* When the aarch64_print_operand code is building the string to represent
+   an operand, this function is called each time we need to change style,
+   with STYLE being the new style.  The string returned from this function
+   will then be embedded in to the operand buffer.
+
+   When we finally print the operand buffer in print_operands, we find
+   these style markers and split the operand text into chunks, where each
+   chunk is a series of characters with the same style.  */
+
+static const char *
+get_style_text (enum disassembler_style style)
+{
+  static bool init = false;
+  static char formats[16][4];
+  unsigned num;
+
+  /* First time through we build a string for every possible format.  This
+     code relies on there being no more than 16 different styles (there's
+     an assert below for this).  */
+  if (!init)
+    {
+      int i;
+
+      for (i = 0; i <= 0xf; ++i)
+	{
+	  int res = snprintf (&formats[i][0], sizeof (formats[i]), "%c%x%c",
+			      STYLE_MARKER_CHAR, i, STYLE_MARKER_CHAR);
+	  assert (res == 3);
+	}
+
+      init = true;
+    }
+
+  /* Return the string that marks switching to STYLE.  */
+  num = (unsigned) style;
+  assert (style <= 0xf);
+  return formats[num];
+}
+
 /* Print operands.  */
 
 static void
@@ -3301,32 +3345,91 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
 			     &info->target, &notes, cmt, sizeof (cmt),
-			     arch_variant);
+			     arch_variant, get_style_text);
 
       /* Print the delimiter (taking account of omitted operand(s)).  */
       if (str[0] != '\0')
-	(*info->fprintf_func) (info->stream, "%s",
-			       num_printed++ == 0 ? "\t" : ", ");
+	(*info->fprintf_styled_func) (info->stream, dis_style_text, "%s",
+				      num_printed++ == 0 ? "\t" : ", ");
 
       /* Print the operand.  */
       if (pcrel_p)
 	(*info->print_address_func) (info->target, info);
       else
 	{
-	  (*info->fprintf_func) (info->stream, "%s", str);
-
-	  /* Print the comment.  This works because only the last operand
-	     ever adds a comment.  If that ever changes then we'll need to
-	     be smarter here.  */
-	  if (cmt[0] != '\0')
-	    (*info->fprintf_func) (info->stream, "\t// %s", cmt);
+	  /* This operand came from aarch64_print_operand, and will include
+	     embedded strings indicating which style each character should
+	     have.  In the following code we split the text based on
+	     CURR_STYLE, and call the styled print callback to print each
+	     block of text in the appropriate style.  */
+	  char *start, *curr;
+	  enum disassembler_style curr_style = dis_style_text;
+
+	  start = curr = str;
+	  do
+	    {
+	      if (*curr == '\0'
+		  || (*curr == STYLE_MARKER_CHAR
+		      && ISXDIGIT (*(curr + 1))
+		      && *(curr + 2) == STYLE_MARKER_CHAR))
+		{
+		  /* Output content between our START position and CURR.  */
+		  int len = curr - start;
+		  int n = (*info->fprintf_styled_func) (info->stream,
+							curr_style,
+							"%.*s", len, start);
+		  if (n < 0)
+		    break;
+
+		  if (*curr == '\0')
+		    break;
+
+		  /* Skip over the initial STYLE_MARKER_CHAR.  */
+		  ++curr;
+
+		  /* Update the CURR_STYLE.  As there are less than 16
+		     styles, it is possible, that if the input is corrupted
+		     in some way, that we might set CURR_STYLE to an
+		     invalid value.  Don't worry though, we check for this
+		     situation.  */
+		  if (*curr >= '0' && *curr <= '9')
+		    curr_style = (enum disassembler_style) (*curr - '0');
+		  else if (*curr >= 'a' && *curr <= 'f')
+		    curr_style = (enum disassembler_style) (*curr - 'a' + 10);
+		  else
+		    curr_style = dis_style_text;
+
+		  /* Check for an invalid style having been selected.  This
+		     should never happen, but it doesn't hurt to be a
+		     little paranoid.  */
+		  if (curr_style > dis_style_comment_start)
+		    curr_style = dis_style_text;
+
+		  /* Skip the hex character, and the closing STYLE_MARKER_CHAR.  */
+		  curr += 2;
+
+		  /* Reset the START to after the style marker.  */
+		  start = curr;
+		}
+	      else
+		++curr;
+	    }
+	  while (true);
 	}
+
+      /* Print the comment.  This works because only the last operand ever
+	 adds a comment.  If that ever changes then we'll need to be
+	 smarter here.  */
+      if (cmt[0] != '\0')
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "\t// %s", cmt);
     }
 
     if (notes && !no_notes)
       {
 	*has_notes = true;
-	(*info->fprintf_func) (info->stream, "  // note: %s", notes);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "  // note: %s", notes);
       }
 }
 
@@ -3359,10 +3462,12 @@ print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
       char name[8];
 
       remove_dot_suffix (name, inst);
-      (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
+      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				    "%s.%s", name, inst->cond->names[0]);
     }
   else
-    (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
+    (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				  "%s", inst->opcode->name);
 }
 
 /* Decide whether we need to print a comment after the operands of
@@ -3379,9 +3484,10 @@ print_comment (const aarch64_inst *inst, struct disassemble_info *info)
       remove_dot_suffix (name, inst);
       num_conds = ARRAY_SIZE (inst->cond->names);
       for (i = 1; i < num_conds && inst->cond->names[i]; ++i)
-	(*info->fprintf_func) (info->stream, "%s %s.%s",
-			       i == 1 ? "  //" : ",",
-			       name, inst->cond->names[i]);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "%s %s.%s",
+				      i == 1 ? "  //" : ",",
+				      name, inst->cond->names[i]);
     }
 }
 
@@ -3398,28 +3504,30 @@ print_verifier_notes (aarch64_operand_error *detail,
      would not have succeeded.  We can safely ignore these.  */
   assert (detail->non_fatal);
 
-  (*info->fprintf_func) (info->stream, "  // note: ");
+  (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				"  // note: ");
   switch (detail->kind)
     {
     case AARCH64_OPDE_A_SHOULD_FOLLOW_B:
-      (*info->fprintf_func) (info->stream,
-			     _("this `%s' should have an immediately"
-			       " preceding `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("this `%s' should have an immediately"
+				      " preceding `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     case AARCH64_OPDE_EXPECTED_A_AFTER_B:
-      (*info->fprintf_func) (info->stream,
-			     _("expected `%s' after previous `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("expected `%s' after previous `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     default:
       assert (detail->error);
-      (*info->fprintf_func) (info->stream, "%s", detail->error);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    "%s", detail->error);
       if (detail->index >= 0)
-	(*info->fprintf_func) (info->stream, " at operand %d",
-			       detail->index + 1);
+	(*info->fprintf_styled_func) (info->stream, dis_style_text,
+				      " at operand %d", detail->index + 1);
       break;
     }
 }
@@ -3511,8 +3619,13 @@ print_insn_aarch64_word (bfd_vma pc,
     case ERR_NYI:
       /* Handle undefined instructions.  */
       info->insn_type = dis_noninsn;
-      (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
-			     word, err_msg[ret]);
+      (*info->fprintf_styled_func) (info->stream,
+				    dis_style_assembler_directive,
+				    ".inst\t");
+      (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
+				    "0x%08x", word);
+      (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				    " ; %s", err_msg[ret]);
       break;
     case ERR_OK:
       user_friendly_fixup (&inst);
@@ -3554,13 +3667,22 @@ print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
   switch (info->bytes_per_chunk)
     {
     case 1:
-      info->fprintf_func (info->stream, ".byte\t0x%02x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".byte\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%02x", word);
       break;
     case 2:
-      info->fprintf_func (info->stream, ".short\t0x%04x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".short\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%04x", word);
       break;
     case 4:
-      info->fprintf_func (info->stream, ".word\t0x%08x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".word\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%08x", word);
       break;
     default:
       abort ();
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 1c93f836020..f3dc1f81a73 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -3043,13 +3043,13 @@ expand_fp_imm (int size, uint32_t imm8)
    the register name that comes before the register number, such as "v".  */
 static void
 print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
-		     const char *prefix)
+		     const char *prefix, get_style_func get_style)
 {
   const int num_regs = opnd->reglist.num_regs;
   const int first_reg = opnd->reglist.first_regno;
   const int last_reg = (first_reg + num_regs - 1) & 0x1f;
   const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
-  char tb[8];	/* Temporary buffer.  */
+  char tb[16];	/* Temporary buffer.  */
 
   assert (opnd->type != AARCH64_OPND_LEt || opnd->reglist.has_index);
   assert (num_regs >= 1 && num_regs <= 4);
@@ -3057,7 +3057,9 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
   /* Prepare the index if any.  */
   if (opnd->reglist.has_index)
     /* PR 21096: The %100 is to silence a warning about possible truncation.  */
-    snprintf (tb, 8, "[%" PRIi64 "]", (opnd->reglist.index % 100));
+    snprintf (tb, sizeof (tb), "%s[%s%" PRIi64 "%s]",
+	      get_style (dis_style_text), get_style (dis_style_immediate),
+	      (opnd->reglist.index % 100), get_style (dis_style_text));
   else
     tb[0] = '\0';
 
@@ -3065,8 +3067,11 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
      more than two registers in the list, and the register numbers
      are monotonically increasing in increments of one.  */
   if (num_regs > 2 && last_reg > first_reg)
-    snprintf (buf, size, "{%s%d.%s-%s%d.%s}%s", prefix, first_reg, qlf_name,
-	      prefix, last_reg, qlf_name, tb);
+    snprintf (buf, size, "%s{%s%s%d.%s%s-%s%s%d.%s%s}%s",
+	      get_style (dis_style_text), get_style (dis_style_register),
+	      prefix, first_reg, qlf_name, get_style (dis_style_text),
+	      get_style (dis_style_register), prefix, last_reg, qlf_name,
+	      get_style (dis_style_text), tb);
   else
     {
       const int reg0 = first_reg;
@@ -3077,21 +3082,40 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
       switch (num_regs)
 	{
 	case 1:
-	  snprintf (buf, size, "{%s%d.%s}%s", prefix, reg0, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	case 2:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s}%s", prefix, reg0, qlf_name,
-		    prefix, reg1, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg1, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	case 3:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg1, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg2, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	case 4:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, prefix, reg3, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg1, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg2, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg3, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	}
     }
@@ -3103,32 +3127,53 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
 static void
 print_immediate_offset_address (char *buf, size_t size,
 				const aarch64_opnd_info *opnd,
-				const char *base)
+				const char *base, get_style_func get_style)
 {
   if (opnd->addr.writeback)
     {
       if (opnd->addr.preind)
         {
 	  if (opnd->type == AARCH64_OPND_ADDR_SIMM10 && !opnd->addr.offset.imm)
-            snprintf (buf, size, "[%s]!", base);
+	    snprintf (buf, size, "%s[%s%s%s]!",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), base,
+		      get_style (dis_style_text));
           else
-	    snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
+	    snprintf (buf, size, "%s[%s%s%s, %s#%d%s]!",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), base,
+		      get_style (dis_style_text),
+		      get_style (dis_style_immediate), opnd->addr.offset.imm,
+		      get_style (dis_style_text));
         }
       else
-	snprintf (buf, size, "[%s], #%d", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "%s[%s%s%s], %s#%d",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  base, get_style (dis_style_text),
+		  get_style (dis_style_immediate), opnd->addr.offset.imm);
     }
   else
     {
       if (opnd->shifter.operator_present)
 	{
 	  assert (opnd->shifter.kind == AARCH64_MOD_MUL_VL);
-	  snprintf (buf, size, "[%s, #%d, mul vl]",
-		    base, opnd->addr.offset.imm);
+	  snprintf (buf, size, "%s[%s%s%s, %s#%d%s, mul vl]",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), base,
+		    get_style (dis_style_text),
+		    get_style (dis_style_immediate), opnd->addr.offset.imm,
+		    get_style (dis_style_text));
 	}
       else if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "%s[%s%s%s, %s#%d%s]",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  base, get_style (dis_style_text),
+		  get_style (dis_style_immediate), opnd->addr.offset.imm,
+		  get_style (dis_style_text));
       else
-	snprintf (buf, size, "[%s]", base);
+	snprintf (buf, size, "%s[%s%s%s]", get_style (dis_style_text),
+		  get_style (dis_style_register), base,
+		  get_style (dis_style_text));
     }
 }
 
@@ -3138,9 +3183,10 @@ print_immediate_offset_address (char *buf, size_t size,
 static void
 print_register_offset_address (char *buf, size_t size,
 			       const aarch64_opnd_info *opnd,
-			       const char *base, const char *offset)
+			       const char *base, const char *offset,
+			       get_style_func get_style)
 {
-  char tb[16];			/* Temporary buffer.  */
+  char tb[32];			/* Temporary buffer.  */
   bool print_extend_p = true;
   bool print_amount_p = true;
   const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
@@ -3161,7 +3207,9 @@ print_register_offset_address (char *buf, size_t size,
   if (print_extend_p)
     {
       if (print_amount_p)
-	snprintf (tb, sizeof (tb), ", %s #%" PRIi64, shift_name,
+	snprintf (tb, sizeof (tb), ", %s %s#%" PRIi64,
+		  shift_name,
+		  get_style (dis_style_immediate),
   /* PR 21096: The %100 is to silence a warning about possible truncation.  */
 		  (opnd->shifter.amount % 100));
       else
@@ -3170,7 +3218,10 @@ print_register_offset_address (char *buf, size_t size,
   else
     tb[0] = '\0';
 
-  snprintf (buf, size, "[%s, %s%s]", base, offset, tb);
+  snprintf (buf, size, "%s[%s%s%s, %s%s%s%s]",
+	    get_style (dis_style_text), get_style (dis_style_register),
+	    base, get_style (dis_style_text), get_style (dis_style_register),
+	    offset, get_style (dis_style_text), tb);
 }
 
 /* Print ZA tiles from imm8 in ZERO instruction.
@@ -3230,7 +3281,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 		       const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
 		       bfd_vma *address, char** notes,
 		       char *comment, size_t comment_size,
-		       aarch64_feature_set features)
+		       aarch64_feature_set features,
+		       get_style_func get_style)
 {
   unsigned int i, num_conds;
   const char *name = NULL;
@@ -3278,7 +3330,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	break;
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
-      snprintf (buf, size, "%s",
+      snprintf (buf, size, "%s%s",
+		get_style (dis_style_register),
 		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
       break;
 
@@ -3291,7 +3344,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      || opnd->qualifier == AARCH64_OPND_QLF_WSP
 	      || opnd->qualifier == AARCH64_OPND_QLF_X
 	      || opnd->qualifier == AARCH64_OPND_QLF_SP);
-      snprintf (buf, size, "%s",
+      snprintf (buf, size, "%s%s",
+		get_style (dis_style_register),
 		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 1));
       break;
 
@@ -3311,19 +3365,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	  if (opnd->shifter.amount == 0)
 	    {
 	      /* Shifter omitted.  */
-	      snprintf (buf, size, "%s",
+	      snprintf (buf, size, "%s%s",
+			get_style (dis_style_register),
 			get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
 	      break;
 	    }
 	}
       if (opnd->shifter.amount)
-	snprintf (buf, size, "%s, %s #%" PRIi64,
+	snprintf (buf, size, "%s%s%s, %s %s#%" PRIi64,
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+		  get_style (dis_style_text),
 		  aarch64_operand_modifiers[kind].name,
-		  opnd->shifter.amount);
+		  get_style (dis_style_immediate), opnd->shifter.amount);
       else
-	snprintf (buf, size, "%s, %s",
+	snprintf (buf, size, "%s%s%s, %s",
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+		  get_style (dis_style_text),
 		  aarch64_operand_modifiers[kind].name);
       break;
 
@@ -3331,13 +3390,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
       if (opnd->shifter.amount == 0 && opnd->shifter.kind == AARCH64_MOD_LSL)
-	snprintf (buf, size, "%s",
+	snprintf (buf, size, "%s%s",
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
       else
-	snprintf (buf, size, "%s, %s #%" PRIi64,
+	snprintf (buf, size, "%s%s%s, %s %s#%" PRIi64,
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+		  get_style (dis_style_text),
 		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+		  get_style (dis_style_immediate), opnd->shifter.amount);
       break;
 
     case AARCH64_OPND_Fd:
@@ -3353,7 +3415,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Vd:
     case AARCH64_OPND_SVE_Vm:
     case AARCH64_OPND_SVE_Vn:
-      snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
+      snprintf (buf, size, "%s%s%d",
+		get_style (dis_style_register),
+		aarch64_get_qualifier_name (opnd->qualifier),
 		opnd->reg.regno);
       break;
 
@@ -3361,7 +3425,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Vd:
     case AARCH64_OPND_Vn:
     case AARCH64_OPND_Vm:
-      snprintf (buf, size, "v%d.%s", opnd->reg.regno,
+      snprintf (buf, size, "%sv%d.%s",
+		get_style (dis_style_register), opnd->reg.regno,
 		aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
@@ -3370,21 +3435,26 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Em:
     case AARCH64_OPND_Em16:
     case AARCH64_OPND_SM3_IMM2:
-      snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
+      snprintf (buf, size, "%sv%d.%s%s[%s%" PRIi64 "%s]",
+		get_style (dis_style_register), opnd->reglane.regno,
 		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+		get_style (dis_style_text), get_style (dis_style_immediate),
+		opnd->reglane.index, get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_VdD1:
     case AARCH64_OPND_VnD1:
-      snprintf (buf, size, "v%d.d[1]", opnd->reg.regno);
+      snprintf (buf, size, "%sv%d.d%s[%s1%s]",
+		get_style (dis_style_register), opnd->reg.regno,
+		get_style (dis_style_text), get_style (dis_style_immediate),
+		get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_LVn:
     case AARCH64_OPND_LVt:
     case AARCH64_OPND_LVt_AL:
     case AARCH64_OPND_LEt:
-      print_register_list (buf, size, opnd, "v");
+      print_register_list (buf, size, opnd, "v", get_style);
       break;
 
     case AARCH64_OPND_SVE_Pd:
@@ -3397,13 +3467,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Pt:
     case AARCH64_OPND_SME_Pm:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "p%d", opnd->reg.regno);
+	snprintf (buf, size, "%sp%d", get_style (dis_style_register),
+		  opnd->reg.regno);
       else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
 	       || opnd->qualifier == AARCH64_OPND_QLF_P_M)
-	snprintf (buf, size, "p%d/%s", opnd->reg.regno,
+	snprintf (buf, size, "%sp%d/%s", get_style (dis_style_register),
+		  opnd->reg.regno,
 		  aarch64_get_qualifier_name (opnd->qualifier));
       else
-	snprintf (buf, size, "p%d.%s", opnd->reg.regno,
+	snprintf (buf, size, "%sp%d.%s", get_style (dis_style_register),
+		  opnd->reg.regno,
 		  aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
@@ -3415,15 +3488,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zn:
     case AARCH64_OPND_SVE_Zt:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "z%d", opnd->reg.regno);
+	snprintf (buf, size, "%sz%d", get_style (dis_style_register),
+		  opnd->reg.regno);
       else
-	snprintf (buf, size, "z%d.%s", opnd->reg.regno,
+	snprintf (buf, size, "%sz%d.%s", get_style (dis_style_register),
+		  opnd->reg.regno,
 		  aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
     case AARCH64_OPND_SVE_ZnxN:
     case AARCH64_OPND_SVE_ZtxN:
-      print_register_list (buf, size, opnd, "z");
+      print_register_list (buf, size, opnd, "z", get_style);
       break;
 
     case AARCH64_OPND_SVE_Zm3_INDEX:
@@ -3432,14 +3507,18 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zm4_11_INDEX:
     case AARCH64_OPND_SVE_Zm4_INDEX:
     case AARCH64_OPND_SVE_Zn_INDEX:
-      snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
+      snprintf (buf, size, "%sz%d.%s%s[%s%" PRIi64 "%s]",
+		get_style (dis_style_register), opnd->reglane.regno,
 		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+		get_style (dis_style_text),
+		get_style (dis_style_immediate), opnd->reglane.index,
+		get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_SME_ZAda_2b:
     case AARCH64_OPND_SME_ZAda_3b:
-      snprintf (buf, size, "za%d.%s", opnd->reg.regno,
+      snprintf (buf, size, "%sza%d.%s", get_style (dis_style_register),
+		opnd->reg.regno,
                 aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
@@ -3467,7 +3546,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_SME_SM_ZA:
-      snprintf (buf, size, "%s", opnd->reg.regno == 's' ? "sm" : "za");
+      snprintf (buf, size, "%s%s",
+		get_style (dis_style_register),
+		opnd->reg.regno == 's' ? "sm" : "za");
       break;
 
     case AARCH64_OPND_SME_PnT_Wm_imm:
@@ -3480,7 +3561,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 
     case AARCH64_OPND_CRn:
     case AARCH64_OPND_CRm:
-      snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, "%sC%" PRIi64, get_style (dis_style_register),
+		opnd->imm.value);
       break;
 
     case AARCH64_OPND_IDX:
@@ -3521,7 +3603,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_IMM_ROT1:
     case AARCH64_OPND_SVE_IMM_ROT2:
     case AARCH64_OPND_SVE_IMM_ROT3:
-      snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		opnd->imm.value);
       break;
 
     case AARCH64_OPND_SVE_I1_HALF_ONE:
@@ -3530,7 +3613,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       {
 	single_conv_t c;
 	c.i = opnd->imm.value;
-	snprintf (buf, size, "#%.1f", c.f);
+	snprintf (buf, size, "%s#%.1f", get_style (dis_style_immediate), c.f);
 	break;
       }
 
@@ -3541,9 +3624,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[enum_value]);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		  aarch64_sve_pattern_array[enum_value]);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       break;
 
     case AARCH64_OPND_SVE_PATTERN_SCALED:
@@ -3554,9 +3639,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[opnd->imm.value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[opnd->imm.value]);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		  aarch64_sve_pattern_array[opnd->imm.value]);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       if (opnd->shifter.operator_present)
 	{
 	  size_t len = strlen (buf);
@@ -3570,9 +3657,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
       if (aarch64_sve_prfop_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_prfop_array[enum_value]);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		  aarch64_sve_prfop_array[enum_value]);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       break;
 
     case AARCH64_OPND_IMM_MOV:
@@ -3581,12 +3670,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	case 4:	/* e.g. MOV Wd, #<imm32>.  */
 	    {
 	      int imm32 = opnd->imm.value;
-	      snprintf (buf, size, "#0x%-20x", imm32);
+	      snprintf (buf, size, "%s#0x%-20x",
+			get_style (dis_style_immediate), imm32);
 	      snprintf (comment, comment_size, "#%d", imm32);
 	    }
 	  break;
 	case 8:	/* e.g. MOV Xd, #<imm64>.  */
-	  snprintf (buf, size, "#0x%-20" PRIx64, opnd->imm.value);
+	  snprintf (buf, size, "%s#0x%-20" PRIx64,
+		    get_style (dis_style_immediate), opnd->imm.value);
 	  snprintf (comment, comment_size, "#%" PRIi64, opnd->imm.value);
 	  break;
 	default:
@@ -3596,7 +3687,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_FPIMM0:
-      snprintf (buf, size, "#0.0");
+      snprintf (buf, size, "%s#0.0", get_style (dis_style_immediate));
       break;
 
     case AARCH64_OPND_LIMM:
@@ -3606,30 +3697,39 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_LIMM:
     case AARCH64_OPND_SVE_LIMM_MOV:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
+	snprintf (buf, size, "%s#0x%" PRIx64 "%s, lsl %s#%" PRIi64,
+		  get_style (dis_style_immediate), opnd->imm.value,
+		  get_style (dis_style_text), get_style (dis_style_immediate),
 		  opnd->shifter.amount);
       else
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size, "%s#0x%" PRIx64,
+		  get_style (dis_style_immediate), opnd->imm.value);
       break;
 
     case AARCH64_OPND_SIMD_IMM:
     case AARCH64_OPND_SIMD_IMM_SFT:
       if ((! opnd->shifter.amount && opnd->shifter.kind == AARCH64_MOD_LSL)
 	  || opnd->shifter.kind == AARCH64_MOD_NONE)
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size, "%s#0x%" PRIx64,
+		  get_style (dis_style_immediate), opnd->imm.value);
       else
-	snprintf (buf, size, "#0x%" PRIx64 ", %s #%" PRIi64, opnd->imm.value,
+	snprintf (buf, size, "%s#0x%" PRIx64 "%s, %s %s#%" PRIi64,
+		  get_style (dis_style_immediate), opnd->imm.value,
+		  get_style (dis_style_text),
 		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+		  get_style (dis_style_immediate), opnd->shifter.amount);
       break;
 
     case AARCH64_OPND_SVE_AIMM:
     case AARCH64_OPND_SVE_ASIMM:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
+	snprintf (buf, size, "%s#%" PRIi64 "%s, lsl %s#%" PRIi64,
+		  get_style (dis_style_immediate), opnd->imm.value,
+		  get_style (dis_style_text), get_style (dis_style_immediate),
 		  opnd->shifter.amount);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       break;
 
     case AARCH64_OPND_FPIMM:
@@ -3641,21 +3741,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	    {
 	      half_conv_t c;
 	      c.i = expand_fp_imm (2, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size,  "%s#%.18e",
+			get_style (dis_style_immediate), c.f);
 	    }
 	  break;
 	case 4:	/* e.g. FMOV <Vd>.4S, #<imm>.  */
 	    {
 	      single_conv_t c;
 	      c.i = expand_fp_imm (4, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size,  "%s#%.18e",
+			get_style (dis_style_immediate), c.f);
 	    }
 	  break;
 	case 8:	/* e.g. FMOV <Sd>, #<imm>.  */
 	    {
 	      double_conv_t c;
 	      c.i = expand_fp_imm (8, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.d);
+	      snprintf (buf, size,  "%s#%.18e",
+			get_style (dis_style_immediate), c.d);
 	    }
 	  break;
 	default:
@@ -3676,12 +3779,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      (int64_t) get_optional_operand_default_value (opcode)))
 	/* Omit the operand, e.g. DCPS1.  */
 	break;
-      snprintf (buf, size, "#0x%x", (unsigned int)opnd->imm.value);
+      snprintf (buf, size, "%s#0x%x", get_style (dis_style_immediate),
+		(unsigned int)opnd->imm.value);
       break;
 
     case AARCH64_OPND_COND:
     case AARCH64_OPND_COND1:
-      snprintf (buf, size, "%s", opnd->cond->names[0]);
+      snprintf (buf, size, "%s%s", get_style (dis_style_text),
+		opnd->cond->names[0]);
       num_conds = ARRAY_SIZE (opnd->cond->names);
       for (i = 1; i < num_conds && opnd->cond->names[i]; ++i)
 	{
@@ -3706,7 +3811,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, "%s#0x%" PRIx64,
+		get_style (dis_style_address), addr);
       break;
 
     case AARCH64_OPND_ADDR_PCREL14:
@@ -3722,7 +3828,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, "%s#0x%" PRIx64, get_style (dis_style_address),
+		addr);
       break;
 
     case AARCH64_OPND_ADDR_SIMPLE:
@@ -3732,12 +3839,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (opnd->type == AARCH64_OPND_SIMD_ADDR_POST)
 	{
 	  if (opnd->addr.offset.is_reg)
-	    snprintf (buf, size, "[%s], x%d", name, opnd->addr.offset.regno);
+	    snprintf (buf, size, "%s[%s%s%s], %sx%d",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), name,
+		      get_style (dis_style_text),
+		      get_style (dis_style_register),
+		      opnd->addr.offset.regno);
 	  else
-	    snprintf (buf, size, "[%s], #%d", name, opnd->addr.offset.imm);
+	    snprintf (buf, size, "%s[%s%s%s], %s#%d",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), name,
+		      get_style (dis_style_text),
+		      get_style (dis_style_immediate),
+		      opnd->addr.offset.imm);
 	}
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "%s[%s%s%s]",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  name, get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
@@ -3753,14 +3872,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RX_LSL3:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_offset_int_reg_name (opnd));
+	 get_offset_int_reg_name (opnd), get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZX:
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0));
+	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0), get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_RZ:
@@ -3777,7 +3896,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 get_style);
       break;
 
     case AARCH64_OPND_ADDR_SIMM7:
@@ -3801,7 +3921,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RI_U6x4:
     case AARCH64_OPND_SVE_ADDR_RI_U6x8:
       print_immediate_offset_address
-	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1));
+	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
+	 get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZI_U5:
@@ -3810,7 +3931,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
       print_immediate_offset_address
 	(buf, size, opnd,
-	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
+	 get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
@@ -3819,15 +3941,22 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 get_style);
       break;
 
     case AARCH64_OPND_ADDR_UIMM12:
       name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
       if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", name, opnd->addr.offset.imm);
+	snprintf (buf, size, "%s[%s%s%s, %s#%d%s]",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  name, get_style (dis_style_text),
+		  get_style (dis_style_immediate), opnd->addr.offset.imm,
+		  get_style (dis_style_text));
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "%s[%s%s%s]", get_style (dis_style_text),
+		  get_style (dis_style_register), name,
+		  get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_SYSREG:
@@ -3866,14 +3995,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	}
 
       if (name)
-	snprintf (buf, size, "%s", name);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register), name);
       else
 	{
 	  /* Implementation defined system register.  */
 	  unsigned int value = opnd->sysreg.value;
-	  snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
-		    (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
-		    value & 0x7);
+	  snprintf (buf, size, "%ss%u_%u_c%u_c%u_%u",
+		    get_style (dis_style_register), (value >> 14) & 0x3,
+		    (value >> 11) & 0x7, (value >> 7) & 0xf,
+		    (value >> 3) & 0xf, value & 0x7);
 	}
       break;
 
@@ -3899,12 +4029,21 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SYSREG_IC:
     case AARCH64_OPND_SYSREG_TLBI:
     case AARCH64_OPND_SYSREG_SR:
-      snprintf (buf, size, "%s", opnd->sysins_op->name);
+      snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		opnd->sysins_op->name);
       break;
 
     case AARCH64_OPND_BARRIER:
     case AARCH64_OPND_BARRIER_DSB_NXS:
-      snprintf (buf, size, "%s", opnd->barrier->name);
+      {
+	enum disassembler_style style;
+	if (opnd->barrier->name[0] == '#')
+	  style = dis_style_immediate;
+	else
+	  style = dis_style_text;
+	snprintf (buf, size, "%s%s", get_style (style),
+		  opnd->barrier->name);
+      }
       break;
 
     case AARCH64_OPND_BARRIER_ISB:
@@ -3912,14 +4051,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (! optional_operand_p (opcode, idx)
 	  || (opnd->barrier->value
 	      != get_optional_operand_default_value (opcode)))
-	snprintf (buf, size, "#0x%x", opnd->barrier->value);
+	snprintf (buf, size, "%s#0x%x", get_style (dis_style_immediate),
+		  opnd->barrier->value);
       break;
 
     case AARCH64_OPND_PRFOP:
       if (opnd->prfop->name != NULL)
 	snprintf (buf, size, "%s", opnd->prfop->name);
       else
-	snprintf (buf, size, "#0x%02x", opnd->prfop->value);
+	snprintf (buf, size, "%s#0x%02x", get_style (dis_style_immediate),
+		  opnd->prfop->value);
       break;
 
     case AARCH64_OPND_BARRIER_PSB:
@@ -3933,17 +4074,21 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 
     case AARCH64_OPND_MOPS_ADDR_Rd:
     case AARCH64_OPND_MOPS_ADDR_Rs:
-      snprintf (buf, size, "[%s]!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+      snprintf (buf, size, "%s[%s%s%s]!",
+		get_style (dis_style_text), get_style (dis_style_register),
+		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0),
+		get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_MOPS_WB_Rn:
-      snprintf (buf, size, "%s!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+      snprintf (buf, size, "%s%s%s!",
+		get_style (dis_style_register),
+		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0),
+		get_style (dis_style_text));
       break;
 
     default:
-      snprintf (buf, size, "<invalid>");
+      snprintf (buf, size, "%s<invalid>", get_style (dis_style_text));
       break;
     }
 }
-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] opcodes/aarch64: split off creation of comment text in disassembler
  2022-06-21 11:22 ` [PATCH 1/2] opcodes/aarch64: split off creation of comment text in disassembler Andrew Burgess
@ 2022-06-22 11:02   ` Nick Clifton
  2022-06-29 11:19     ` Andrew Burgess
  0 siblings, 1 reply; 31+ messages in thread
From: Nick Clifton @ 2022-06-22 11:02 UTC (permalink / raw)
  To: Andrew Burgess, binutils

Hi Andrew,

> In this commit, I propose to extend aarch64_print_operand to take a
> second buffer.  Any comments for the instruction are written into this
> extra buffer.  The two callers of aarch64_print_operand are then
> updated to pass an extra buffer, and print any resulting comment.

Patch approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-06-21 11:22 ` [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
@ 2022-06-22 11:15   ` Nick Clifton
  2022-06-29 11:01     ` Andrew Burgess
  2022-06-29 12:36   ` Richard Earnshaw
  2022-07-04  9:52   ` Nick Clifton
  2 siblings, 1 reply; 31+ messages in thread
From: Nick Clifton @ 2022-06-22 11:15 UTC (permalink / raw)
  To: Andrew Burgess, binutils

Hi Andrew,

> I do still have a few questions about how some elements should be
> styled, consider this instruction:
> 
>      add     x1, x2, x3, lsr #1
>         ~~~~~  ~~  ~~  ~~   ~      Plain text.
>      ~~~                           Mnemonic.
>              ~~  ~~  ~~            Register.
> 	                    ~~    Immediate.
>                          ???       What to use here?
> 
> The current patch formats the 'lsr' as text, but I wonder if this
> would be better formatted as mnemonic?  Or maybe it should be
> considered part of the immediate? 

My $0.02 worth: It is not an immediate - in fact that instruction does
not have any immediates in it - nor is it just plain text.  I suppose
that you might consider it as being an extension of the mnemonic, but
that also feels wrong to me.  Could you create a new class for this
part of the instruction ?  eg 'shifter' or 'sub-mnemonic'.  If not then
I would go with mnemonic as that is the closest approximation.  IMHO...


> I have a similar question for how to format 'ge' in:
> 
>      ccmp    x1, x2, #0xa, ge

The same reasoning applies here I feel.  This is "ccmp-ge" instruction
with the condition expressed as a separate field in the disassembled
text.  Ideally a "condition-code" class could be used to express its
style, but if that is not possible then mnemonic is the next best thing.


> And how to format 'sxtb' in:
>  >      adds    x0, sp, w0, sxtb

Ditto.  Maybe an "extender" class could be used here ?


The patch itself looks good to me, but I would like to wait to see if
anyone else has any comments on the code before approving it.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-06-22 11:15   ` Nick Clifton
@ 2022-06-29 11:01     ` Andrew Burgess
  2022-06-29 11:12       ` Jan Beulich
  0 siblings, 1 reply; 31+ messages in thread
From: Andrew Burgess @ 2022-06-29 11:01 UTC (permalink / raw)
  To: Nick Clifton, binutils

Nick Clifton via Binutils <binutils@sourceware.org> writes:

> Hi Andrew,
>
>> I do still have a few questions about how some elements should be
>> styled, consider this instruction:
>> 
>>      add     x1, x2, x3, lsr #1
>>         ~~~~~  ~~  ~~  ~~   ~      Plain text.
>>      ~~~                           Mnemonic.
>>              ~~  ~~  ~~            Register.
>> 	                    ~~    Immediate.
>>                          ???       What to use here?
>> 
>> The current patch formats the 'lsr' as text, but I wonder if this
>> would be better formatted as mnemonic?  Or maybe it should be
>> considered part of the immediate? 
>
> My $0.02 worth: It is not an immediate - in fact that instruction does
> not have any immediates in it - nor is it just plain text.  I suppose
> that you might consider it as being an extension of the mnemonic, but
> that also feels wrong to me.  Could you create a new class for this
> part of the instruction ?  eg 'shifter' or 'sub-mnemonic'.  If not then
> I would go with mnemonic as that is the closest approximation.  IMHO...

We can add more styles.  There's a small bit of work needed when we pass
16 styles, but that really is trivial.

My reluctance is to adding new styles for every single architectural
feature, ideally I'd like to map everything to a very small number of
styles, enough to highlight different parts of the instruction, but not
so many that the output looks like a crazy rainbow of colour.

I initially went with mnemonic, but wasn't sure what people would think
of having the mnemonic split into multiple parts like this.

Adding a sub-mnemonic could be a good solution, it keeps the number of
styles low, but allows us to (potentially) style these parts
differently in the future.

>
>
>> I have a similar question for how to format 'ge' in:
>> 
>>      ccmp    x1, x2, #0xa, ge
>
> The same reasoning applies here I feel.  This is "ccmp-ge" instruction
> with the condition expressed as a separate field in the disassembled
> text.  Ideally a "condition-code" class could be used to express its
> style, but if that is not possible then mnemonic is the next best
> thing.
>
>
>> And how to format 'sxtb' in:
>>  >      adds    x0, sp, w0, sxtb
>
> Ditto.  Maybe an "extender" class could be used here ?
>
>
> The patch itself looks good to me, but I would like to wait to see if
> anyone else has any comments on the code before approving it.

Thanks, I'll merge the first patch from this series, but leave this
second one to see what opinions others have.

Thanks,
Andrew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-06-29 11:01     ` Andrew Burgess
@ 2022-06-29 11:12       ` Jan Beulich
  0 siblings, 0 replies; 31+ messages in thread
From: Jan Beulich @ 2022-06-29 11:12 UTC (permalink / raw)
  To: Andrew Burgess, Nick Clifton; +Cc: binutils

On 29.06.2022 13:01, Andrew Burgess via Binutils wrote:
> Nick Clifton via Binutils <binutils@sourceware.org> writes:
> 
>> Hi Andrew,
>>
>>> I do still have a few questions about how some elements should be
>>> styled, consider this instruction:
>>>
>>>      add     x1, x2, x3, lsr #1
>>>         ~~~~~  ~~  ~~  ~~   ~      Plain text.
>>>      ~~~                           Mnemonic.
>>>              ~~  ~~  ~~            Register.
>>> 	                    ~~    Immediate.
>>>                          ???       What to use here?
>>>
>>> The current patch formats the 'lsr' as text, but I wonder if this
>>> would be better formatted as mnemonic?  Or maybe it should be
>>> considered part of the immediate? 
>>
>> My $0.02 worth: It is not an immediate - in fact that instruction does
>> not have any immediates in it - nor is it just plain text.  I suppose
>> that you might consider it as being an extension of the mnemonic, but
>> that also feels wrong to me.  Could you create a new class for this
>> part of the instruction ?  eg 'shifter' or 'sub-mnemonic'.  If not then
>> I would go with mnemonic as that is the closest approximation.  IMHO...
> 
> We can add more styles.  There's a small bit of work needed when we pass
> 16 styles, but that really is trivial.
> 
> My reluctance is to adding new styles for every single architectural
> feature, ideally I'd like to map everything to a very small number of
> styles, enough to highlight different parts of the instruction, but not
> so many that the output looks like a crazy rainbow of colour.
> 
> I initially went with mnemonic, but wasn't sure what people would think
> of having the mnemonic split into multiple parts like this.
> 
> Adding a sub-mnemonic could be a good solution, it keeps the number of
> styles low, but allows us to (potentially) style these parts
> differently in the future.

Alternatively how about having an "operator" style? That wouldn't be
arch-specific. Not sure though in how far ...

>>> I have a similar question for how to format 'ge' in:
>>>
>>>      ccmp    x1, x2, #0xa, ge
>>
>> The same reasoning applies here I feel.  This is "ccmp-ge" instruction
>> with the condition expressed as a separate field in the disassembled
>> text.  Ideally a "condition-code" class could be used to express its
>> style, but if that is not possible then mnemonic is the next best
>> thing.
>>
>>
>>> And how to format 'sxtb' in:
>>>  >      adds    x0, sp, w0, sxtb
>>
>> Ditto.  Maybe an "extender" class could be used here ?

... this could also be considered an operator.

Jan

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] opcodes/aarch64: split off creation of comment text in disassembler
  2022-06-22 11:02   ` Nick Clifton
@ 2022-06-29 11:19     ` Andrew Burgess
  0 siblings, 0 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-06-29 11:19 UTC (permalink / raw)
  To: Nick Clifton, binutils

Nick Clifton via Binutils <binutils@sourceware.org> writes:

> Hi Andrew,
>
>> In this commit, I propose to extend aarch64_print_operand to take a
>> second buffer.  Any comments for the instruction are written into this
>> extra buffer.  The two callers of aarch64_print_operand are then
>> updated to pass an extra buffer, and print any resulting comment.
>
> Patch approved - please apply.

Thanks, I pushed this patch, but will leave part 2 to gather more
feedback.

Andrew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-06-21 11:22 ` [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
  2022-06-22 11:15   ` Nick Clifton
@ 2022-06-29 12:36   ` Richard Earnshaw
  2022-07-04  9:52   ` Nick Clifton
  2 siblings, 0 replies; 31+ messages in thread
From: Richard Earnshaw @ 2022-06-29 12:36 UTC (permalink / raw)
  To: Andrew Burgess, binutils

[-- Attachment #1: Type: text/plain, Size: 51326 bytes --]



On 21/06/2022 12:22, Andrew Burgess via Binutils wrote:
> This commit enables disassembler styling for AArch64.  After this
> commit it is possible to have objdump style AArch64 disassembler
> output (using --disassembler-color option).  Once the required GDB
> patches are merged, GDB will also style the disassembler output.
> 
> The changes to support styling are mostly split between two files
> opcodes/aarch64-dis.c and opcodes/aarch64-opc.c.
> 
> The entry point for the AArch64 disassembler can be found in
> aarch64-dis.c, this file handles printing the instruction mnemonics,
> and assembler directives (e.g. '.byte', '.word', etc).  Some operands,
> mostly relating to assembler directives are also printed from this
> file.  This commit changes all of this to pass through suitable
> styling information.
> 
> However, for most "normal" instructions, the instruction operands are
> printed using a two step process.  From aarch64-dis.c, in the
> print_operands function, the function aarch64_print_operand is called,
> this function is in aarch64-opc.c, and converts an instruction operand
> into a string.  Then, back in print_operands (aarch64-dis.c), the
> operand string is printed.
> 
> Unfortunately, the string returned by aarch64_print_operand can be
> quite complex, it will include syntax elements, like '[' and ']', in
> addition to register names and immediate values.  In some cases, a
> single operand will expand into what will appear (to the user) as
> multiple operands separated with a ','.
> 
> This makes the task of styling more complex, all these different
> components need to by styled differently, so we need to get the
> styling information out of aarch64_print_operand in some way.
> 
> The solution that I propose here is similar to the solution that I
> used for the i386 disassembler.
> 
> Currently, aarch64_print_operand uses snprintf to write the operand
> text into a buffer provided by the caller.
> 
> What I propose is that we pass an extra argument to the
> aarch64_print_operand function, this argument will be a callback
> function that converts a disassembler style into a string.  These
> strings can then be written into the buffer using snprintf.  Here's an
> example, 'get_style' is the new callback function:
> 
>      snprintf (buf, size, "%s%s",
>                get_style (dis_style_register),
>                get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
> 
> The string returned by 'get_style' is a special sequence of characters
> that is not otherwise seen in the disassembler output.  In the
> print_operands function we can now scan the buffer returned by
> aarch64_print_operand, and split the text based on the style
> markers.  Each separately styled block is then printed with the
> correct style.
> 
> The aarch64_print_operand function is also called from the assembler
> to aid in printing diagnostic messages.  Right now I have no plans to
> add styling to the assembler output, and so, in this case, the
> 'get_style' callback is a dummy function that always returns an empty
> string.  As a result, when the assembler calls aarch64_print_operand,
> the string returns can be immediately printed with no special style
> handling required.
> 
> I've gone through and updated arch64-opc.c as best I can to add
> styling information.  I've mostly used the gas/testsuite/gas/aarch64
> tests to check the styling, assembling then disassembling each source
> file, then checking that the output looks reasonable.
> 
> I do still have a few questions about how some elements should be
> styled, consider this instruction:
> 
>      add     x1, x2, x3, lsr #1
>         ~~~~~  ~~  ~~  ~~   ~      Plain text.
>      ~~~                           Mnemonic.
>              ~~  ~~  ~~            Register.
> 	                    ~~    Immediate.
>                          ???       What to use here?
> 
> The current patch formats the 'lsr' as text, but I wonder if this
> would be better formatted as mnemonic?  Or maybe it should be
> considered part of the immediate?  I'm open to peoples thoughts on
> this.
> 
> I have a similar question for how to format 'ge' in:
> 
>      ccmp    x1, x2, #0xa, ge
> 
> And how to format 'sxtb' in:
> 
>      adds    x0, sp, w0, sxtb
> 
> With objdump disassembler color turned off, there should be no change
> in the output after this commit.

The Arm tools have a similar feature.  I'm not sure if I can attach PNG 
files as an example, but lets have a go.  This screen shot shows the 
colour-picker panel that allows customizing the colour set.

I think we treat 'ge' and 'sxtb' in the above cases as plain text, but 
having a separate category for those wouldn't hurt.

Things can get a little more complex when you get to Neon and even more 
so when you get to SVE as registers can have size and other modifiers. 
These are all treated as part of the register name (otherwise you end up 
with a very confusing rainbow :).

R.


> ---
>   gas/config/tc-aarch64.c  |  11 +-
>   include/opcode/aarch64.h |   8 +-
>   opcodes/aarch64-dis.c    | 186 +++++++++++++++++----
>   opcodes/aarch64-opc.c    | 349 +++++++++++++++++++++++++++------------
>   4 files changed, 418 insertions(+), 136 deletions(-)
> 
> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index 779db31828b..740bde53ea8 100644
> --- a/gas/config/tc-aarch64.c
> +++ b/gas/config/tc-aarch64.c
> @@ -5347,6 +5347,15 @@ assign_qualifier_sequence (aarch64_inst *instr,
>       instr->operands[i].qualifier = *qualifiers;
>   }
>   
> +/* Return a string indicating a switch to STYLE.  As the assembler doesn't
> +   use styling in its output, this always returns an empty string.  */
> +
> +static const char *
> +get_style_text (enum disassembler_style style ATTRIBUTE_UNUSED)
> +{
> +  return "";
> +}
> +
>   /* Print operands for the diagnosis purpose.  */
>   
>   static void
> @@ -5371,7 +5380,7 @@ print_operands (char *buf, const aarch64_opcode *opcode,
>   
>         /* Generate the operand string in STR.  */
>         aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL,
> -			     NULL, cmt, sizeof (cmt), cpu_variant);
> +			     NULL, cmt, sizeof (cmt), cpu_variant, get_style_text);
>   
>         /* Delimiter.  */
>         if (str[0] != '\0')
> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
> index 186ba9a4800..373deb6b49c 100644
> --- a/include/opcode/aarch64.h
> +++ b/include/opcode/aarch64.h
> @@ -27,6 +27,8 @@
>   #include <assert.h>
>   #include <stdlib.h>
>   
> +#include "dis-asm.h"
> +
>   #ifdef __cplusplus
>   extern "C" {
>   #endif
> @@ -1367,12 +1369,16 @@ aarch64_replace_opcode (struct aarch64_inst *,
>   extern const aarch64_opcode *
>   aarch64_get_opcode (enum aarch64_op);
>   
> +/* Return a text string that indicates a change of disassembler style.  */
> +typedef const char *(*get_style_func) (enum disassembler_style);
> +
>   /* Generate the string representation of an operand.  */
>   extern void
>   aarch64_print_operand (char *, size_t, bfd_vma, const aarch64_opcode *,
>   		       const aarch64_opnd_info *, int, int *, bfd_vma *,
>   		       char **, char *, size_t,
> -		       aarch64_feature_set features);
> +		       aarch64_feature_set features,
> +		       get_style_func get_style);
>   
>   /* Miscellaneous interface.  */
>   
> diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
> index acaad28fdff..fbbd0c5e087 100644
> --- a/opcodes/aarch64-dis.c
> +++ b/opcodes/aarch64-dis.c
> @@ -25,9 +25,14 @@
>   #include "opintl.h"
>   #include "aarch64-dis.h"
>   #include "elf-bfd.h"
> +#include "safe-ctype.h"
>   
>   #define INSNLEN 4
>   
> +/* This character is used to encode style information within the output
> +   buffers.  See get_style_text and print_operands for more details.  */
> +#define STYLE_MARKER_CHAR '\002'
> +
>   /* Cached mapping symbol state.  */
>   enum map_type
>   {
> @@ -3275,6 +3280,45 @@ aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst,
>     return ERR_UND;
>   }
>   
> +/* When the aarch64_print_operand code is building the string to represent
> +   an operand, this function is called each time we need to change style,
> +   with STYLE being the new style.  The string returned from this function
> +   will then be embedded in to the operand buffer.
> +
> +   When we finally print the operand buffer in print_operands, we find
> +   these style markers and split the operand text into chunks, where each
> +   chunk is a series of characters with the same style.  */
> +
> +static const char *
> +get_style_text (enum disassembler_style style)
> +{
> +  static bool init = false;
> +  static char formats[16][4];
> +  unsigned num;
> +
> +  /* First time through we build a string for every possible format.  This
> +     code relies on there being no more than 16 different styles (there's
> +     an assert below for this).  */
> +  if (!init)
> +    {
> +      int i;
> +
> +      for (i = 0; i <= 0xf; ++i)
> +	{
> +	  int res = snprintf (&formats[i][0], sizeof (formats[i]), "%c%x%c",
> +			      STYLE_MARKER_CHAR, i, STYLE_MARKER_CHAR);
> +	  assert (res == 3);
> +	}
> +
> +      init = true;
> +    }
> +
> +  /* Return the string that marks switching to STYLE.  */
> +  num = (unsigned) style;
> +  assert (style <= 0xf);
> +  return formats[num];
> +}
> +
>   /* Print operands.  */
>   
>   static void
> @@ -3301,32 +3345,91 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
>         /* Generate the operand string in STR.  */
>         aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
>   			     &info->target, &notes, cmt, sizeof (cmt),
> -			     arch_variant);
> +			     arch_variant, get_style_text);
>   
>         /* Print the delimiter (taking account of omitted operand(s)).  */
>         if (str[0] != '\0')
> -	(*info->fprintf_func) (info->stream, "%s",
> -			       num_printed++ == 0 ? "\t" : ", ");
> +	(*info->fprintf_styled_func) (info->stream, dis_style_text, "%s",
> +				      num_printed++ == 0 ? "\t" : ", ");
>   
>         /* Print the operand.  */
>         if (pcrel_p)
>   	(*info->print_address_func) (info->target, info);
>         else
>   	{
> -	  (*info->fprintf_func) (info->stream, "%s", str);
> -
> -	  /* Print the comment.  This works because only the last operand
> -	     ever adds a comment.  If that ever changes then we'll need to
> -	     be smarter here.  */
> -	  if (cmt[0] != '\0')
> -	    (*info->fprintf_func) (info->stream, "\t// %s", cmt);
> +	  /* This operand came from aarch64_print_operand, and will include
> +	     embedded strings indicating which style each character should
> +	     have.  In the following code we split the text based on
> +	     CURR_STYLE, and call the styled print callback to print each
> +	     block of text in the appropriate style.  */
> +	  char *start, *curr;
> +	  enum disassembler_style curr_style = dis_style_text;
> +
> +	  start = curr = str;
> +	  do
> +	    {
> +	      if (*curr == '\0'
> +		  || (*curr == STYLE_MARKER_CHAR
> +		      && ISXDIGIT (*(curr + 1))
> +		      && *(curr + 2) == STYLE_MARKER_CHAR))
> +		{
> +		  /* Output content between our START position and CURR.  */
> +		  int len = curr - start;
> +		  int n = (*info->fprintf_styled_func) (info->stream,
> +							curr_style,
> +							"%.*s", len, start);
> +		  if (n < 0)
> +		    break;
> +
> +		  if (*curr == '\0')
> +		    break;
> +
> +		  /* Skip over the initial STYLE_MARKER_CHAR.  */
> +		  ++curr;
> +
> +		  /* Update the CURR_STYLE.  As there are less than 16
> +		     styles, it is possible, that if the input is corrupted
> +		     in some way, that we might set CURR_STYLE to an
> +		     invalid value.  Don't worry though, we check for this
> +		     situation.  */
> +		  if (*curr >= '0' && *curr <= '9')
> +		    curr_style = (enum disassembler_style) (*curr - '0');
> +		  else if (*curr >= 'a' && *curr <= 'f')
> +		    curr_style = (enum disassembler_style) (*curr - 'a' + 10);
> +		  else
> +		    curr_style = dis_style_text;
> +
> +		  /* Check for an invalid style having been selected.  This
> +		     should never happen, but it doesn't hurt to be a
> +		     little paranoid.  */
> +		  if (curr_style > dis_style_comment_start)
> +		    curr_style = dis_style_text;
> +
> +		  /* Skip the hex character, and the closing STYLE_MARKER_CHAR.  */
> +		  curr += 2;
> +
> +		  /* Reset the START to after the style marker.  */
> +		  start = curr;
> +		}
> +	      else
> +		++curr;
> +	    }
> +	  while (true);
>   	}
> +
> +      /* Print the comment.  This works because only the last operand ever
> +	 adds a comment.  If that ever changes then we'll need to be
> +	 smarter here.  */
> +      if (cmt[0] != '\0')
> +	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
> +				      "\t// %s", cmt);
>       }
>   
>       if (notes && !no_notes)
>         {
>   	*has_notes = true;
> -	(*info->fprintf_func) (info->stream, "  // note: %s", notes);
> +	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
> +				      "  // note: %s", notes);
>         }
>   }
>   
> @@ -3359,10 +3462,12 @@ print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
>         char name[8];
>   
>         remove_dot_suffix (name, inst);
> -      (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
> +      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
> +				    "%s.%s", name, inst->cond->names[0]);
>       }
>     else
> -    (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
> +    (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
> +				  "%s", inst->opcode->name);
>   }
>   
>   /* Decide whether we need to print a comment after the operands of
> @@ -3379,9 +3484,10 @@ print_comment (const aarch64_inst *inst, struct disassemble_info *info)
>         remove_dot_suffix (name, inst);
>         num_conds = ARRAY_SIZE (inst->cond->names);
>         for (i = 1; i < num_conds && inst->cond->names[i]; ++i)
> -	(*info->fprintf_func) (info->stream, "%s %s.%s",
> -			       i == 1 ? "  //" : ",",
> -			       name, inst->cond->names[i]);
> +	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
> +				      "%s %s.%s",
> +				      i == 1 ? "  //" : ",",
> +				      name, inst->cond->names[i]);
>       }
>   }
>   
> @@ -3398,28 +3504,30 @@ print_verifier_notes (aarch64_operand_error *detail,
>        would not have succeeded.  We can safely ignore these.  */
>     assert (detail->non_fatal);
>   
> -  (*info->fprintf_func) (info->stream, "  // note: ");
> +  (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
> +				"  // note: ");
>     switch (detail->kind)
>       {
>       case AARCH64_OPDE_A_SHOULD_FOLLOW_B:
> -      (*info->fprintf_func) (info->stream,
> -			     _("this `%s' should have an immediately"
> -			       " preceding `%s'"),
> -			     detail->data[0].s, detail->data[1].s);
> +      (*info->fprintf_styled_func) (info->stream, dis_style_text,
> +				    _("this `%s' should have an immediately"
> +				      " preceding `%s'"),
> +				    detail->data[0].s, detail->data[1].s);
>         break;
>   
>       case AARCH64_OPDE_EXPECTED_A_AFTER_B:
> -      (*info->fprintf_func) (info->stream,
> -			     _("expected `%s' after previous `%s'"),
> -			     detail->data[0].s, detail->data[1].s);
> +      (*info->fprintf_styled_func) (info->stream, dis_style_text,
> +				    _("expected `%s' after previous `%s'"),
> +				    detail->data[0].s, detail->data[1].s);
>         break;
>   
>       default:
>         assert (detail->error);
> -      (*info->fprintf_func) (info->stream, "%s", detail->error);
> +      (*info->fprintf_styled_func) (info->stream, dis_style_text,
> +				    "%s", detail->error);
>         if (detail->index >= 0)
> -	(*info->fprintf_func) (info->stream, " at operand %d",
> -			       detail->index + 1);
> +	(*info->fprintf_styled_func) (info->stream, dis_style_text,
> +				      " at operand %d", detail->index + 1);
>         break;
>       }
>   }
> @@ -3511,8 +3619,13 @@ print_insn_aarch64_word (bfd_vma pc,
>       case ERR_NYI:
>         /* Handle undefined instructions.  */
>         info->insn_type = dis_noninsn;
> -      (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
> -			     word, err_msg[ret]);
> +      (*info->fprintf_styled_func) (info->stream,
> +				    dis_style_assembler_directive,
> +				    ".inst\t");
> +      (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
> +				    "0x%08x", word);
> +      (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
> +				    " ; %s", err_msg[ret]);
>         break;
>       case ERR_OK:
>         user_friendly_fixup (&inst);
> @@ -3554,13 +3667,22 @@ print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
>     switch (info->bytes_per_chunk)
>       {
>       case 1:
> -      info->fprintf_func (info->stream, ".byte\t0x%02x", word);
> +      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
> +				 ".byte\t");
> +      info->fprintf_styled_func (info->stream, dis_style_immediate,
> +				 "0x%02x", word);
>         break;
>       case 2:
> -      info->fprintf_func (info->stream, ".short\t0x%04x", word);
> +      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
> +				 ".short\t");
> +      info->fprintf_styled_func (info->stream, dis_style_immediate,
> +				 "0x%04x", word);
>         break;
>       case 4:
> -      info->fprintf_func (info->stream, ".word\t0x%08x", word);
> +      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
> +				 ".word\t");
> +      info->fprintf_styled_func (info->stream, dis_style_immediate,
> +				 "0x%08x", word);
>         break;
>       default:
>         abort ();
> diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
> index 1c93f836020..f3dc1f81a73 100644
> --- a/opcodes/aarch64-opc.c
> +++ b/opcodes/aarch64-opc.c
> @@ -3043,13 +3043,13 @@ expand_fp_imm (int size, uint32_t imm8)
>      the register name that comes before the register number, such as "v".  */
>   static void
>   print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
> -		     const char *prefix)
> +		     const char *prefix, get_style_func get_style)
>   {
>     const int num_regs = opnd->reglist.num_regs;
>     const int first_reg = opnd->reglist.first_regno;
>     const int last_reg = (first_reg + num_regs - 1) & 0x1f;
>     const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
> -  char tb[8];	/* Temporary buffer.  */
> +  char tb[16];	/* Temporary buffer.  */
>   
>     assert (opnd->type != AARCH64_OPND_LEt || opnd->reglist.has_index);
>     assert (num_regs >= 1 && num_regs <= 4);
> @@ -3057,7 +3057,9 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
>     /* Prepare the index if any.  */
>     if (opnd->reglist.has_index)
>       /* PR 21096: The %100 is to silence a warning about possible truncation.  */
> -    snprintf (tb, 8, "[%" PRIi64 "]", (opnd->reglist.index % 100));
> +    snprintf (tb, sizeof (tb), "%s[%s%" PRIi64 "%s]",
> +	      get_style (dis_style_text), get_style (dis_style_immediate),
> +	      (opnd->reglist.index % 100), get_style (dis_style_text));
>     else
>       tb[0] = '\0';
>   
> @@ -3065,8 +3067,11 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
>        more than two registers in the list, and the register numbers
>        are monotonically increasing in increments of one.  */
>     if (num_regs > 2 && last_reg > first_reg)
> -    snprintf (buf, size, "{%s%d.%s-%s%d.%s}%s", prefix, first_reg, qlf_name,
> -	      prefix, last_reg, qlf_name, tb);
> +    snprintf (buf, size, "%s{%s%s%d.%s%s-%s%s%d.%s%s}%s",
> +	      get_style (dis_style_text), get_style (dis_style_register),
> +	      prefix, first_reg, qlf_name, get_style (dis_style_text),
> +	      get_style (dis_style_register), prefix, last_reg, qlf_name,
> +	      get_style (dis_style_text), tb);
>     else
>       {
>         const int reg0 = first_reg;
> @@ -3077,21 +3082,40 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
>         switch (num_regs)
>   	{
>   	case 1:
> -	  snprintf (buf, size, "{%s%d.%s}%s", prefix, reg0, qlf_name, tb);
> +	  snprintf (buf, size, "%s{%s%s%d.%s%s}%s",
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg0, qlf_name,
> +		    get_style (dis_style_text), tb);
>   	  break;
>   	case 2:
> -	  snprintf (buf, size, "{%s%d.%s, %s%d.%s}%s", prefix, reg0, qlf_name,
> -		    prefix, reg1, qlf_name, tb);
> +	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s}%s",
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg0, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg1, qlf_name,
> +		    get_style (dis_style_text), tb);
>   	  break;
>   	case 3:
> -	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s}%s",
> -		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
> -		    prefix, reg2, qlf_name, tb);
> +	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s}%s",
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg0, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg1, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg2, qlf_name,
> +		    get_style (dis_style_text), tb);
>   	  break;
>   	case 4:
> -	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s, %s%d.%s}%s",
> -		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
> -		    prefix, reg2, qlf_name, prefix, reg3, qlf_name, tb);
> +	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s}%s",
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg0, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg1, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg2, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg3, qlf_name,
> +		    get_style (dis_style_text), tb);
>   	  break;
>   	}
>       }
> @@ -3103,32 +3127,53 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
>   static void
>   print_immediate_offset_address (char *buf, size_t size,
>   				const aarch64_opnd_info *opnd,
> -				const char *base)
> +				const char *base, get_style_func get_style)
>   {
>     if (opnd->addr.writeback)
>       {
>         if (opnd->addr.preind)
>           {
>   	  if (opnd->type == AARCH64_OPND_ADDR_SIMM10 && !opnd->addr.offset.imm)
> -            snprintf (buf, size, "[%s]!", base);
> +	    snprintf (buf, size, "%s[%s%s%s]!",
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_register), base,
> +		      get_style (dis_style_text));
>             else
> -	    snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
> +	    snprintf (buf, size, "%s[%s%s%s, %s#%d%s]!",
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_register), base,
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_immediate), opnd->addr.offset.imm,
> +		      get_style (dis_style_text));
>           }
>         else
> -	snprintf (buf, size, "[%s], #%d", base, opnd->addr.offset.imm);
> +	snprintf (buf, size, "%s[%s%s%s], %s#%d",
> +		  get_style (dis_style_text), get_style (dis_style_register),
> +		  base, get_style (dis_style_text),
> +		  get_style (dis_style_immediate), opnd->addr.offset.imm);
>       }
>     else
>       {
>         if (opnd->shifter.operator_present)
>   	{
>   	  assert (opnd->shifter.kind == AARCH64_MOD_MUL_VL);
> -	  snprintf (buf, size, "[%s, #%d, mul vl]",
> -		    base, opnd->addr.offset.imm);
> +	  snprintf (buf, size, "%s[%s%s%s, %s#%d%s, mul vl]",
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), base,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_immediate), opnd->addr.offset.imm,
> +		    get_style (dis_style_text));
>   	}
>         else if (opnd->addr.offset.imm)
> -	snprintf (buf, size, "[%s, #%d]", base, opnd->addr.offset.imm);
> +	snprintf (buf, size, "%s[%s%s%s, %s#%d%s]",
> +		  get_style (dis_style_text), get_style (dis_style_register),
> +		  base, get_style (dis_style_text),
> +		  get_style (dis_style_immediate), opnd->addr.offset.imm,
> +		  get_style (dis_style_text));
>         else
> -	snprintf (buf, size, "[%s]", base);
> +	snprintf (buf, size, "%s[%s%s%s]", get_style (dis_style_text),
> +		  get_style (dis_style_register), base,
> +		  get_style (dis_style_text));
>       }
>   }
>   
> @@ -3138,9 +3183,10 @@ print_immediate_offset_address (char *buf, size_t size,
>   static void
>   print_register_offset_address (char *buf, size_t size,
>   			       const aarch64_opnd_info *opnd,
> -			       const char *base, const char *offset)
> +			       const char *base, const char *offset,
> +			       get_style_func get_style)
>   {
> -  char tb[16];			/* Temporary buffer.  */
> +  char tb[32];			/* Temporary buffer.  */
>     bool print_extend_p = true;
>     bool print_amount_p = true;
>     const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
> @@ -3161,7 +3207,9 @@ print_register_offset_address (char *buf, size_t size,
>     if (print_extend_p)
>       {
>         if (print_amount_p)
> -	snprintf (tb, sizeof (tb), ", %s #%" PRIi64, shift_name,
> +	snprintf (tb, sizeof (tb), ", %s %s#%" PRIi64,
> +		  shift_name,
> +		  get_style (dis_style_immediate),
>     /* PR 21096: The %100 is to silence a warning about possible truncation.  */
>   		  (opnd->shifter.amount % 100));
>         else
> @@ -3170,7 +3218,10 @@ print_register_offset_address (char *buf, size_t size,
>     else
>       tb[0] = '\0';
>   
> -  snprintf (buf, size, "[%s, %s%s]", base, offset, tb);
> +  snprintf (buf, size, "%s[%s%s%s, %s%s%s%s]",
> +	    get_style (dis_style_text), get_style (dis_style_register),
> +	    base, get_style (dis_style_text), get_style (dis_style_register),
> +	    offset, get_style (dis_style_text), tb);
>   }
>   
>   /* Print ZA tiles from imm8 in ZERO instruction.
> @@ -3230,7 +3281,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   		       const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
>   		       bfd_vma *address, char** notes,
>   		       char *comment, size_t comment_size,
> -		       aarch64_feature_set features)
> +		       aarch64_feature_set features,
> +		       get_style_func get_style)
>   {
>     unsigned int i, num_conds;
>     const char *name = NULL;
> @@ -3278,7 +3330,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	break;
>         assert (opnd->qualifier == AARCH64_OPND_QLF_W
>   	      || opnd->qualifier == AARCH64_OPND_QLF_X);
> -      snprintf (buf, size, "%s",
> +      snprintf (buf, size, "%s%s",
> +		get_style (dis_style_register),
>   		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
>         break;
>   
> @@ -3291,7 +3344,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	      || opnd->qualifier == AARCH64_OPND_QLF_WSP
>   	      || opnd->qualifier == AARCH64_OPND_QLF_X
>   	      || opnd->qualifier == AARCH64_OPND_QLF_SP);
> -      snprintf (buf, size, "%s",
> +      snprintf (buf, size, "%s%s",
> +		get_style (dis_style_register),
>   		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 1));
>         break;
>   
> @@ -3311,19 +3365,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	  if (opnd->shifter.amount == 0)
>   	    {
>   	      /* Shifter omitted.  */
> -	      snprintf (buf, size, "%s",
> +	      snprintf (buf, size, "%s%s",
> +			get_style (dis_style_register),
>   			get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
>   	      break;
>   	    }
>   	}
>         if (opnd->shifter.amount)
> -	snprintf (buf, size, "%s, %s #%" PRIi64,
> +	snprintf (buf, size, "%s%s%s, %s %s#%" PRIi64,
> +		  get_style (dis_style_register),
>   		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
> +		  get_style (dis_style_text),
>   		  aarch64_operand_modifiers[kind].name,
> -		  opnd->shifter.amount);
> +		  get_style (dis_style_immediate), opnd->shifter.amount);
>         else
> -	snprintf (buf, size, "%s, %s",
> +	snprintf (buf, size, "%s%s%s, %s",
> +		  get_style (dis_style_register),
>   		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
> +		  get_style (dis_style_text),
>   		  aarch64_operand_modifiers[kind].name);
>         break;
>   
> @@ -3331,13 +3390,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         assert (opnd->qualifier == AARCH64_OPND_QLF_W
>   	      || opnd->qualifier == AARCH64_OPND_QLF_X);
>         if (opnd->shifter.amount == 0 && opnd->shifter.kind == AARCH64_MOD_LSL)
> -	snprintf (buf, size, "%s",
> +	snprintf (buf, size, "%s%s",
> +		  get_style (dis_style_register),
>   		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
>         else
> -	snprintf (buf, size, "%s, %s #%" PRIi64,
> +	snprintf (buf, size, "%s%s%s, %s %s#%" PRIi64,
> +		  get_style (dis_style_register),
>   		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
> +		  get_style (dis_style_text),
>   		  aarch64_operand_modifiers[opnd->shifter.kind].name,
> -		  opnd->shifter.amount);
> +		  get_style (dis_style_immediate), opnd->shifter.amount);
>         break;
>   
>       case AARCH64_OPND_Fd:
> @@ -3353,7 +3415,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_Vd:
>       case AARCH64_OPND_SVE_Vm:
>       case AARCH64_OPND_SVE_Vn:
> -      snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
> +      snprintf (buf, size, "%s%s%d",
> +		get_style (dis_style_register),
> +		aarch64_get_qualifier_name (opnd->qualifier),
>   		opnd->reg.regno);
>         break;
>   
> @@ -3361,7 +3425,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_Vd:
>       case AARCH64_OPND_Vn:
>       case AARCH64_OPND_Vm:
> -      snprintf (buf, size, "v%d.%s", opnd->reg.regno,
> +      snprintf (buf, size, "%sv%d.%s",
> +		get_style (dis_style_register), opnd->reg.regno,
>   		aarch64_get_qualifier_name (opnd->qualifier));
>         break;
>   
> @@ -3370,21 +3435,26 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_Em:
>       case AARCH64_OPND_Em16:
>       case AARCH64_OPND_SM3_IMM2:
> -      snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
> +      snprintf (buf, size, "%sv%d.%s%s[%s%" PRIi64 "%s]",
> +		get_style (dis_style_register), opnd->reglane.regno,
>   		aarch64_get_qualifier_name (opnd->qualifier),
> -		opnd->reglane.index);
> +		get_style (dis_style_text), get_style (dis_style_immediate),
> +		opnd->reglane.index, get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_VdD1:
>       case AARCH64_OPND_VnD1:
> -      snprintf (buf, size, "v%d.d[1]", opnd->reg.regno);
> +      snprintf (buf, size, "%sv%d.d%s[%s1%s]",
> +		get_style (dis_style_register), opnd->reg.regno,
> +		get_style (dis_style_text), get_style (dis_style_immediate),
> +		get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_LVn:
>       case AARCH64_OPND_LVt:
>       case AARCH64_OPND_LVt_AL:
>       case AARCH64_OPND_LEt:
> -      print_register_list (buf, size, opnd, "v");
> +      print_register_list (buf, size, opnd, "v", get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_Pd:
> @@ -3397,13 +3467,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_Pt:
>       case AARCH64_OPND_SME_Pm:
>         if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
> -	snprintf (buf, size, "p%d", opnd->reg.regno);
> +	snprintf (buf, size, "%sp%d", get_style (dis_style_register),
> +		  opnd->reg.regno);
>         else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
>   	       || opnd->qualifier == AARCH64_OPND_QLF_P_M)
> -	snprintf (buf, size, "p%d/%s", opnd->reg.regno,
> +	snprintf (buf, size, "%sp%d/%s", get_style (dis_style_register),
> +		  opnd->reg.regno,
>   		  aarch64_get_qualifier_name (opnd->qualifier));
>         else
> -	snprintf (buf, size, "p%d.%s", opnd->reg.regno,
> +	snprintf (buf, size, "%sp%d.%s", get_style (dis_style_register),
> +		  opnd->reg.regno,
>   		  aarch64_get_qualifier_name (opnd->qualifier));
>         break;
>   
> @@ -3415,15 +3488,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_Zn:
>       case AARCH64_OPND_SVE_Zt:
>         if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
> -	snprintf (buf, size, "z%d", opnd->reg.regno);
> +	snprintf (buf, size, "%sz%d", get_style (dis_style_register),
> +		  opnd->reg.regno);
>         else
> -	snprintf (buf, size, "z%d.%s", opnd->reg.regno,
> +	snprintf (buf, size, "%sz%d.%s", get_style (dis_style_register),
> +		  opnd->reg.regno,
>   		  aarch64_get_qualifier_name (opnd->qualifier));
>         break;
>   
>       case AARCH64_OPND_SVE_ZnxN:
>       case AARCH64_OPND_SVE_ZtxN:
> -      print_register_list (buf, size, opnd, "z");
> +      print_register_list (buf, size, opnd, "z", get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_Zm3_INDEX:
> @@ -3432,14 +3507,18 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_Zm4_11_INDEX:
>       case AARCH64_OPND_SVE_Zm4_INDEX:
>       case AARCH64_OPND_SVE_Zn_INDEX:
> -      snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
> +      snprintf (buf, size, "%sz%d.%s%s[%s%" PRIi64 "%s]",
> +		get_style (dis_style_register), opnd->reglane.regno,
>   		aarch64_get_qualifier_name (opnd->qualifier),
> -		opnd->reglane.index);
> +		get_style (dis_style_text),
> +		get_style (dis_style_immediate), opnd->reglane.index,
> +		get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_SME_ZAda_2b:
>       case AARCH64_OPND_SME_ZAda_3b:
> -      snprintf (buf, size, "za%d.%s", opnd->reg.regno,
> +      snprintf (buf, size, "%sza%d.%s", get_style (dis_style_register),
> +		opnd->reg.regno,
>                   aarch64_get_qualifier_name (opnd->qualifier));
>         break;
>   
> @@ -3467,7 +3546,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         break;
>   
>       case AARCH64_OPND_SME_SM_ZA:
> -      snprintf (buf, size, "%s", opnd->reg.regno == 's' ? "sm" : "za");
> +      snprintf (buf, size, "%s%s",
> +		get_style (dis_style_register),
> +		opnd->reg.regno == 's' ? "sm" : "za");
>         break;
>   
>       case AARCH64_OPND_SME_PnT_Wm_imm:
> @@ -3480,7 +3561,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   
>       case AARCH64_OPND_CRn:
>       case AARCH64_OPND_CRm:
> -      snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
> +      snprintf (buf, size, "%sC%" PRIi64, get_style (dis_style_register),
> +		opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_IDX:
> @@ -3521,7 +3603,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_IMM_ROT1:
>       case AARCH64_OPND_SVE_IMM_ROT2:
>       case AARCH64_OPND_SVE_IMM_ROT3:
> -      snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> +      snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
> +		opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_SVE_I1_HALF_ONE:
> @@ -3530,7 +3613,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         {
>   	single_conv_t c;
>   	c.i = opnd->imm.value;
> -	snprintf (buf, size, "#%.1f", c.f);
> +	snprintf (buf, size, "%s#%.1f", get_style (dis_style_immediate), c.f);
>   	break;
>         }
>   
> @@ -3541,9 +3624,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         enum_value = opnd->imm.value;
>         assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
>         if (aarch64_sve_pattern_array[enum_value])
> -	snprintf (buf, size, "%s", aarch64_sve_pattern_array[enum_value]);
> +	snprintf (buf, size, "%s%s", get_style (dis_style_register),
> +		  aarch64_sve_pattern_array[enum_value]);
>         else
> -	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> +	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
> +		  opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_SVE_PATTERN_SCALED:
> @@ -3554,9 +3639,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         enum_value = opnd->imm.value;
>         assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
>         if (aarch64_sve_pattern_array[opnd->imm.value])
> -	snprintf (buf, size, "%s", aarch64_sve_pattern_array[opnd->imm.value]);
> +	snprintf (buf, size, "%s%s", get_style (dis_style_register),
> +		  aarch64_sve_pattern_array[opnd->imm.value]);
>         else
> -	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> +	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
> +		  opnd->imm.value);
>         if (opnd->shifter.operator_present)
>   	{
>   	  size_t len = strlen (buf);
> @@ -3570,9 +3657,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         enum_value = opnd->imm.value;
>         assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
>         if (aarch64_sve_prfop_array[enum_value])
> -	snprintf (buf, size, "%s", aarch64_sve_prfop_array[enum_value]);
> +	snprintf (buf, size, "%s%s", get_style (dis_style_register),
> +		  aarch64_sve_prfop_array[enum_value]);
>         else
> -	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> +	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
> +		  opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_IMM_MOV:
> @@ -3581,12 +3670,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	case 4:	/* e.g. MOV Wd, #<imm32>.  */
>   	    {
>   	      int imm32 = opnd->imm.value;
> -	      snprintf (buf, size, "#0x%-20x", imm32);
> +	      snprintf (buf, size, "%s#0x%-20x",
> +			get_style (dis_style_immediate), imm32);
>   	      snprintf (comment, comment_size, "#%d", imm32);
>   	    }
>   	  break;
>   	case 8:	/* e.g. MOV Xd, #<imm64>.  */
> -	  snprintf (buf, size, "#0x%-20" PRIx64, opnd->imm.value);
> +	  snprintf (buf, size, "%s#0x%-20" PRIx64,
> +		    get_style (dis_style_immediate), opnd->imm.value);
>   	  snprintf (comment, comment_size, "#%" PRIi64, opnd->imm.value);
>   	  break;
>   	default:
> @@ -3596,7 +3687,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         break;
>   
>       case AARCH64_OPND_FPIMM0:
> -      snprintf (buf, size, "#0.0");
> +      snprintf (buf, size, "%s#0.0", get_style (dis_style_immediate));
>         break;
>   
>       case AARCH64_OPND_LIMM:
> @@ -3606,30 +3697,39 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_LIMM:
>       case AARCH64_OPND_SVE_LIMM_MOV:
>         if (opnd->shifter.amount)
> -	snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
> +	snprintf (buf, size, "%s#0x%" PRIx64 "%s, lsl %s#%" PRIi64,
> +		  get_style (dis_style_immediate), opnd->imm.value,
> +		  get_style (dis_style_text), get_style (dis_style_immediate),
>   		  opnd->shifter.amount);
>         else
> -	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
> +	snprintf (buf, size, "%s#0x%" PRIx64,
> +		  get_style (dis_style_immediate), opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_SIMD_IMM:
>       case AARCH64_OPND_SIMD_IMM_SFT:
>         if ((! opnd->shifter.amount && opnd->shifter.kind == AARCH64_MOD_LSL)
>   	  || opnd->shifter.kind == AARCH64_MOD_NONE)
> -	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
> +	snprintf (buf, size, "%s#0x%" PRIx64,
> +		  get_style (dis_style_immediate), opnd->imm.value);
>         else
> -	snprintf (buf, size, "#0x%" PRIx64 ", %s #%" PRIi64, opnd->imm.value,
> +	snprintf (buf, size, "%s#0x%" PRIx64 "%s, %s %s#%" PRIi64,
> +		  get_style (dis_style_immediate), opnd->imm.value,
> +		  get_style (dis_style_text),
>   		  aarch64_operand_modifiers[opnd->shifter.kind].name,
> -		  opnd->shifter.amount);
> +		  get_style (dis_style_immediate), opnd->shifter.amount);
>         break;
>   
>       case AARCH64_OPND_SVE_AIMM:
>       case AARCH64_OPND_SVE_ASIMM:
>         if (opnd->shifter.amount)
> -	snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
> +	snprintf (buf, size, "%s#%" PRIi64 "%s, lsl %s#%" PRIi64,
> +		  get_style (dis_style_immediate), opnd->imm.value,
> +		  get_style (dis_style_text), get_style (dis_style_immediate),
>   		  opnd->shifter.amount);
>         else
> -	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> +	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
> +		  opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_FPIMM:
> @@ -3641,21 +3741,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	    {
>   	      half_conv_t c;
>   	      c.i = expand_fp_imm (2, opnd->imm.value);
> -	      snprintf (buf, size,  "#%.18e", c.f);
> +	      snprintf (buf, size,  "%s#%.18e",
> +			get_style (dis_style_immediate), c.f);
>   	    }
>   	  break;
>   	case 4:	/* e.g. FMOV <Vd>.4S, #<imm>.  */
>   	    {
>   	      single_conv_t c;
>   	      c.i = expand_fp_imm (4, opnd->imm.value);
> -	      snprintf (buf, size,  "#%.18e", c.f);
> +	      snprintf (buf, size,  "%s#%.18e",
> +			get_style (dis_style_immediate), c.f);
>   	    }
>   	  break;
>   	case 8:	/* e.g. FMOV <Sd>, #<imm>.  */
>   	    {
>   	      double_conv_t c;
>   	      c.i = expand_fp_imm (8, opnd->imm.value);
> -	      snprintf (buf, size,  "#%.18e", c.d);
> +	      snprintf (buf, size,  "%s#%.18e",
> +			get_style (dis_style_immediate), c.d);
>   	    }
>   	  break;
>   	default:
> @@ -3676,12 +3779,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	      (int64_t) get_optional_operand_default_value (opcode)))
>   	/* Omit the operand, e.g. DCPS1.  */
>   	break;
> -      snprintf (buf, size, "#0x%x", (unsigned int)opnd->imm.value);
> +      snprintf (buf, size, "%s#0x%x", get_style (dis_style_immediate),
> +		(unsigned int)opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_COND:
>       case AARCH64_OPND_COND1:
> -      snprintf (buf, size, "%s", opnd->cond->names[0]);
> +      snprintf (buf, size, "%s%s", get_style (dis_style_text),
> +		opnd->cond->names[0]);
>         num_conds = ARRAY_SIZE (opnd->cond->names);
>         for (i = 1; i < num_conds && opnd->cond->names[i]; ++i)
>   	{
> @@ -3706,7 +3811,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	 in the disassemble_info will take care of the printing.  But some
>   	 other callers may be still interested in getting the string in *STR,
>   	 so here we do snprintf regardless.  */
> -      snprintf (buf, size, "#0x%" PRIx64, addr);
> +      snprintf (buf, size, "%s#0x%" PRIx64,
> +		get_style (dis_style_address), addr);
>         break;
>   
>       case AARCH64_OPND_ADDR_PCREL14:
> @@ -3722,7 +3828,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	 in the disassemble_info will take care of the printing.  But some
>   	 other callers may be still interested in getting the string in *STR,
>   	 so here we do snprintf regardless.  */
> -      snprintf (buf, size, "#0x%" PRIx64, addr);
> +      snprintf (buf, size, "%s#0x%" PRIx64, get_style (dis_style_address),
> +		addr);
>         break;
>   
>       case AARCH64_OPND_ADDR_SIMPLE:
> @@ -3732,12 +3839,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         if (opnd->type == AARCH64_OPND_SIMD_ADDR_POST)
>   	{
>   	  if (opnd->addr.offset.is_reg)
> -	    snprintf (buf, size, "[%s], x%d", name, opnd->addr.offset.regno);
> +	    snprintf (buf, size, "%s[%s%s%s], %sx%d",
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_register), name,
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_register),
> +		      opnd->addr.offset.regno);
>   	  else
> -	    snprintf (buf, size, "[%s], #%d", name, opnd->addr.offset.imm);
> +	    snprintf (buf, size, "%s[%s%s%s], %s#%d",
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_register), name,
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_immediate),
> +		      opnd->addr.offset.imm);
>   	}
>         else
> -	snprintf (buf, size, "[%s]", name);
> +	snprintf (buf, size, "%s[%s%s%s]",
> +		  get_style (dis_style_text), get_style (dis_style_register),
> +		  name, get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_ADDR_REGOFF:
> @@ -3753,14 +3872,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_ADDR_RX_LSL3:
>         print_register_offset_address
>   	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
> -	 get_offset_int_reg_name (opnd));
> +	 get_offset_int_reg_name (opnd), get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_ADDR_ZX:
>         print_register_offset_address
>   	(buf, size, opnd,
>   	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
> -	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0));
> +	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0), get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_ADDR_RZ:
> @@ -3777,7 +3896,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
>         print_register_offset_address
>   	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
> -	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
> +	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
> +	 get_style);
>         break;
>   
>       case AARCH64_OPND_ADDR_SIMM7:
> @@ -3801,7 +3921,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_ADDR_RI_U6x4:
>       case AARCH64_OPND_SVE_ADDR_RI_U6x8:
>         print_immediate_offset_address
> -	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1));
> +	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
> +	 get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_ADDR_ZI_U5:
> @@ -3810,7 +3931,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
>         print_immediate_offset_address
>   	(buf, size, opnd,
> -	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier));
> +	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
> +	 get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
> @@ -3819,15 +3941,22 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         print_register_offset_address
>   	(buf, size, opnd,
>   	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
> -	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
> +	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
> +	 get_style);
>         break;
>   
>       case AARCH64_OPND_ADDR_UIMM12:
>         name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
>         if (opnd->addr.offset.imm)
> -	snprintf (buf, size, "[%s, #%d]", name, opnd->addr.offset.imm);
> +	snprintf (buf, size, "%s[%s%s%s, %s#%d%s]",
> +		  get_style (dis_style_text), get_style (dis_style_register),
> +		  name, get_style (dis_style_text),
> +		  get_style (dis_style_immediate), opnd->addr.offset.imm,
> +		  get_style (dis_style_text));
>         else
> -	snprintf (buf, size, "[%s]", name);
> +	snprintf (buf, size, "%s[%s%s%s]", get_style (dis_style_text),
> +		  get_style (dis_style_register), name,
> +		  get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_SYSREG:
> @@ -3866,14 +3995,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	}
>   
>         if (name)
> -	snprintf (buf, size, "%s", name);
> +	snprintf (buf, size, "%s%s", get_style (dis_style_register), name);
>         else
>   	{
>   	  /* Implementation defined system register.  */
>   	  unsigned int value = opnd->sysreg.value;
> -	  snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
> -		    (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
> -		    value & 0x7);
> +	  snprintf (buf, size, "%ss%u_%u_c%u_c%u_%u",
> +		    get_style (dis_style_register), (value >> 14) & 0x3,
> +		    (value >> 11) & 0x7, (value >> 7) & 0xf,
> +		    (value >> 3) & 0xf, value & 0x7);
>   	}
>         break;
>   
> @@ -3899,12 +4029,21 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SYSREG_IC:
>       case AARCH64_OPND_SYSREG_TLBI:
>       case AARCH64_OPND_SYSREG_SR:
> -      snprintf (buf, size, "%s", opnd->sysins_op->name);
> +      snprintf (buf, size, "%s%s", get_style (dis_style_register),
> +		opnd->sysins_op->name);
>         break;
>   
>       case AARCH64_OPND_BARRIER:
>       case AARCH64_OPND_BARRIER_DSB_NXS:
> -      snprintf (buf, size, "%s", opnd->barrier->name);
> +      {
> +	enum disassembler_style style;
> +	if (opnd->barrier->name[0] == '#')
> +	  style = dis_style_immediate;
> +	else
> +	  style = dis_style_text;
> +	snprintf (buf, size, "%s%s", get_style (style),
> +		  opnd->barrier->name);
> +      }
>         break;
>   
>       case AARCH64_OPND_BARRIER_ISB:
> @@ -3912,14 +4051,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         if (! optional_operand_p (opcode, idx)
>   	  || (opnd->barrier->value
>   	      != get_optional_operand_default_value (opcode)))
> -	snprintf (buf, size, "#0x%x", opnd->barrier->value);
> +	snprintf (buf, size, "%s#0x%x", get_style (dis_style_immediate),
> +		  opnd->barrier->value);
>         break;
>   
>       case AARCH64_OPND_PRFOP:
>         if (opnd->prfop->name != NULL)
>   	snprintf (buf, size, "%s", opnd->prfop->name);
>         else
> -	snprintf (buf, size, "#0x%02x", opnd->prfop->value);
> +	snprintf (buf, size, "%s#0x%02x", get_style (dis_style_immediate),
> +		  opnd->prfop->value);
>         break;
>   
>       case AARCH64_OPND_BARRIER_PSB:
> @@ -3933,17 +4074,21 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   
>       case AARCH64_OPND_MOPS_ADDR_Rd:
>       case AARCH64_OPND_MOPS_ADDR_Rs:
> -      snprintf (buf, size, "[%s]!",
> -		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
> +      snprintf (buf, size, "%s[%s%s%s]!",
> +		get_style (dis_style_text), get_style (dis_style_register),
> +		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0),
> +		get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_MOPS_WB_Rn:
> -      snprintf (buf, size, "%s!",
> -		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
> +      snprintf (buf, size, "%s%s%s!",
> +		get_style (dis_style_register),
> +		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0),
> +		get_style (dis_style_text));
>         break;
>   
>       default:
> -      snprintf (buf, size, "<invalid>");
> +      snprintf (buf, size, "%s<invalid>", get_style (dis_style_text));
>         break;
>       }
>   }

[-- Attachment #2: image.png --]
[-- Type: image/png, Size: 20223 bytes --]

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-06-21 11:22 ` [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
  2022-06-22 11:15   ` Nick Clifton
  2022-06-29 12:36   ` Richard Earnshaw
@ 2022-07-04  9:52   ` Nick Clifton
  2 siblings, 0 replies; 31+ messages in thread
From: Nick Clifton @ 2022-07-04  9:52 UTC (permalink / raw)
  To: Andrew Burgess, binutils

Hi Andrew,

> This commit enables disassembler styling for AArch64.  After this
> commit it is possible to have objdump style AArch64 disassembler
> output (using --disassembler-color option).  Once the required GDB
> patches are merged, GDB will also style the disassembler output.

It does not look like there are going to be any other comments on
this patch, so please either commit as is, or resubmit with an
extended style selection.

Cheers
   Nick



^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv2 0/2] AArch64 libopcodes styling
  2022-06-21 11:22 [PATCH 0/2] AArch64 libopcodes styling Andrew Burgess
  2022-06-21 11:22 ` [PATCH 1/2] opcodes/aarch64: split off creation of comment text in disassembler Andrew Burgess
  2022-06-21 11:22 ` [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
@ 2022-07-05 12:45 ` Andrew Burgess
  2022-07-05 12:46   ` [PATCHv2 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
  2022-07-05 12:46   ` [PATCHv2 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
  2 siblings, 2 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-07-05 12:45 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

Changes since v1:

  - Original patch #1 has been merged,

  - New patch #1 adds a dis_style_sub_mnemonic style and updates
    objdump to handle this style,

  - Patch #2 has been updated to make use of the new style.

---

Andrew Burgess (2):
  opcodes: add new sub-mnemonic disassembler style
  libopcodes/aarch64: add support for disassembler styling

 binutils/objdump.c       |   2 +
 gas/config/tc-aarch64.c  |  11 +-
 include/dis-asm.h        |   7 +
 include/opcode/aarch64.h |   8 +-
 opcodes/aarch64-dis.c    | 186 ++++++++++++++----
 opcodes/aarch64-opc.c    | 399 ++++++++++++++++++++++++++++-----------
 6 files changed, 472 insertions(+), 141 deletions(-)

-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv2 1/2] opcodes: add new sub-mnemonic disassembler style
  2022-07-05 12:45 ` [PATCHv2 0/2] AArch64 libopcodes styling Andrew Burgess
@ 2022-07-05 12:46   ` Andrew Burgess
  2022-07-05 12:46   ` [PATCHv2 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
  1 sibling, 0 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-07-05 12:46 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

When adding libopcodes disassembler styling support for AArch64, it
feels like the results would be improved by having a new sub-mnemonic
style.  This will be used in cases like:

  add    w16, w7, w1, uxtb #2
                      ^^^^----- Here

And:

  cinc   w0, w1, ne
                 ^^----- Here

This commit just adds the new style, and prepares objdump to handle
the style.  A later commit will add AArch64 styling, and will actually
make use of the style.

As this style is currently unused, there should be no user visible
changes after this commit.
---
 binutils/objdump.c | 2 ++
 include/dis-asm.h  | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/binutils/objdump.c b/binutils/objdump.c
index 67824053527..4076587151c 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -2167,6 +2167,7 @@ objdump_color_for_disassembler_style (enum disassembler_style style)
 	{
 	case dis_style_symbol: color = 32; break;
         case dis_style_assembler_directive:
+	case dis_style_sub_mnemonic:
 	case dis_style_mnemonic: color = 33; break;
 	case dis_style_register: color = 34; break;
 	case dis_style_address:
@@ -2185,6 +2186,7 @@ objdump_color_for_disassembler_style (enum disassembler_style style)
 	{
 	case dis_style_symbol: color = 40; break;
         case dis_style_assembler_directive:
+	case dis_style_sub_mnemonic:
 	case dis_style_mnemonic: color = 142; break;
 	case dis_style_register: color = 27; break;
 	case dis_style_address:
diff --git a/include/dis-asm.h b/include/dis-asm.h
index 4f91df12498..f1a83dc84e5 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -62,6 +62,13 @@ enum disassembler_style
      instructions.  */
   dis_style_mnemonic,
 
+  /* Some architectures include additional mnemonic like fields within the
+     instruction operands, e.g. on aarch64 'add w16, w7, w1, lsl #2' where
+     the 'lsl' is an additional piece of text that describes how the
+     instruction should behave.  This sub-mnemonic style can be used for
+     these pieces of text.  */
+  dis_style_sub_mnemonic,
+
   /* For things that aren't real machine instructions, but rather
      assembler directives, e.g. .byte, etc.  */
   dis_style_assembler_directive,
-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv2 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-07-05 12:45 ` [PATCHv2 0/2] AArch64 libopcodes styling Andrew Burgess
  2022-07-05 12:46   ` [PATCHv2 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
@ 2022-07-05 12:46   ` Andrew Burgess
  2022-07-05 12:51     ` Andrew Burgess
  1 sibling, 1 reply; 31+ messages in thread
From: Andrew Burgess @ 2022-07-05 12:46 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

This commit enables disassembler styling for AArch64.  After this
commit it is possible to have objdump style AArch64 disassembler
output (using --disassembler-color option).  Once the required GDB
patches are merged, GDB will also style the disassembler output.

The changes to support styling are mostly split between two files
opcodes/aarch64-dis.c and opcodes/aarch64-opc.c.

The entry point for the AArch64 disassembler can be found in
aarch64-dis.c, this file handles printing the instruction mnemonics,
and assembler directives (e.g. '.byte', '.word', etc).  Some operands,
mostly relating to assembler directives are also printed from this
file.  This commit changes all of this to pass through suitable
styling information.

However, for most "normal" instructions, the instruction operands are
printed using a two step process.  From aarch64-dis.c, in the
print_operands function, the function aarch64_print_operand is called,
this function is in aarch64-opc.c, and converts an instruction operand
into a string.  Then, back in print_operands (aarch64-dis.c), the
operand string is printed.

Unfortunately, the string returned by aarch64_print_operand can be
quite complex, it will include syntax elements, like '[' and ']', in
addition to register names and immediate values.  In some cases, a
single operand will expand into what will appear (to the user) as
multiple operands separated with a ','.

This makes the task of styling more complex, all these different
components need to by styled differently, so we need to get the
styling information out of aarch64_print_operand in some way.

The solution that I propose here is similar to the solution that I
used for the i386 disassembler.

Currently, aarch64_print_operand uses snprintf to write the operand
text into a buffer provided by the caller.

What I propose is that we pass an extra argument to the
aarch64_print_operand function, this argument will be a callback
function that converts a disassembler style into a string.  These
strings can then be written into the buffer using snprintf.  Here's an
example, 'get_style' is the new callback function:

    snprintf (buf, size, "%s%s",
              get_style (dis_style_register),
              get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));

The string returned by 'get_style' is a special sequence of characters
that is not otherwise seen in the disassembler output.  In the
print_operands function we can now scan the buffer returned by
aarch64_print_operand, and split the text based on the style
markers.  Each separately styled block is then printed with the
correct style.

The aarch64_print_operand function is also called from the assembler
to aid in printing diagnostic messages.  Right now I have no plans to
add styling to the assembler output, and so, in this case, the
'get_style' callback is a dummy function that always returns an empty
string.  As a result, when the assembler calls aarch64_print_operand,
the string returns can be immediately printed with no special style
handling required.

I've gone through and updated arch64-opc.c as best I can to add
styling information.  I've mostly used the gas/testsuite/gas/aarch64
tests to check the styling, assembling then disassembling each source
file, then checking that the output looks reasonable.

With objdump disassembler color turned off, there should be no change
in the output after this commit.
---
 gas/config/tc-aarch64.c  |  11 +-
 include/opcode/aarch64.h |   8 +-
 opcodes/aarch64-dis.c    | 186 ++++++++++++++----
 opcodes/aarch64-opc.c    | 399 ++++++++++++++++++++++++++++-----------
 4 files changed, 463 insertions(+), 141 deletions(-)

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 779db31828b..740bde53ea8 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -5347,6 +5347,15 @@ assign_qualifier_sequence (aarch64_inst *instr,
     instr->operands[i].qualifier = *qualifiers;
 }
 
+/* Return a string indicating a switch to STYLE.  As the assembler doesn't
+   use styling in its output, this always returns an empty string.  */
+
+static const char *
+get_style_text (enum disassembler_style style ATTRIBUTE_UNUSED)
+{
+  return "";
+}
+
 /* Print operands for the diagnosis purpose.  */
 
 static void
@@ -5371,7 +5380,7 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL,
-			     NULL, cmt, sizeof (cmt), cpu_variant);
+			     NULL, cmt, sizeof (cmt), cpu_variant, get_style_text);
 
       /* Delimiter.  */
       if (str[0] != '\0')
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 186ba9a4800..373deb6b49c 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -27,6 +27,8 @@
 #include <assert.h>
 #include <stdlib.h>
 
+#include "dis-asm.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -1367,12 +1369,16 @@ aarch64_replace_opcode (struct aarch64_inst *,
 extern const aarch64_opcode *
 aarch64_get_opcode (enum aarch64_op);
 
+/* Return a text string that indicates a change of disassembler style.  */
+typedef const char *(*get_style_func) (enum disassembler_style);
+
 /* Generate the string representation of an operand.  */
 extern void
 aarch64_print_operand (char *, size_t, bfd_vma, const aarch64_opcode *,
 		       const aarch64_opnd_info *, int, int *, bfd_vma *,
 		       char **, char *, size_t,
-		       aarch64_feature_set features);
+		       aarch64_feature_set features,
+		       get_style_func get_style);
 
 /* Miscellaneous interface.  */
 
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index acaad28fdff..fbbd0c5e087 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -25,9 +25,14 @@
 #include "opintl.h"
 #include "aarch64-dis.h"
 #include "elf-bfd.h"
+#include "safe-ctype.h"
 
 #define INSNLEN 4
 
+/* This character is used to encode style information within the output
+   buffers.  See get_style_text and print_operands for more details.  */
+#define STYLE_MARKER_CHAR '\002'
+
 /* Cached mapping symbol state.  */
 enum map_type
 {
@@ -3275,6 +3280,45 @@ aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst,
   return ERR_UND;
 }
 
+/* When the aarch64_print_operand code is building the string to represent
+   an operand, this function is called each time we need to change style,
+   with STYLE being the new style.  The string returned from this function
+   will then be embedded in to the operand buffer.
+
+   When we finally print the operand buffer in print_operands, we find
+   these style markers and split the operand text into chunks, where each
+   chunk is a series of characters with the same style.  */
+
+static const char *
+get_style_text (enum disassembler_style style)
+{
+  static bool init = false;
+  static char formats[16][4];
+  unsigned num;
+
+  /* First time through we build a string for every possible format.  This
+     code relies on there being no more than 16 different styles (there's
+     an assert below for this).  */
+  if (!init)
+    {
+      int i;
+
+      for (i = 0; i <= 0xf; ++i)
+	{
+	  int res = snprintf (&formats[i][0], sizeof (formats[i]), "%c%x%c",
+			      STYLE_MARKER_CHAR, i, STYLE_MARKER_CHAR);
+	  assert (res == 3);
+	}
+
+      init = true;
+    }
+
+  /* Return the string that marks switching to STYLE.  */
+  num = (unsigned) style;
+  assert (style <= 0xf);
+  return formats[num];
+}
+
 /* Print operands.  */
 
 static void
@@ -3301,32 +3345,91 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
 			     &info->target, &notes, cmt, sizeof (cmt),
-			     arch_variant);
+			     arch_variant, get_style_text);
 
       /* Print the delimiter (taking account of omitted operand(s)).  */
       if (str[0] != '\0')
-	(*info->fprintf_func) (info->stream, "%s",
-			       num_printed++ == 0 ? "\t" : ", ");
+	(*info->fprintf_styled_func) (info->stream, dis_style_text, "%s",
+				      num_printed++ == 0 ? "\t" : ", ");
 
       /* Print the operand.  */
       if (pcrel_p)
 	(*info->print_address_func) (info->target, info);
       else
 	{
-	  (*info->fprintf_func) (info->stream, "%s", str);
-
-	  /* Print the comment.  This works because only the last operand
-	     ever adds a comment.  If that ever changes then we'll need to
-	     be smarter here.  */
-	  if (cmt[0] != '\0')
-	    (*info->fprintf_func) (info->stream, "\t// %s", cmt);
+	  /* This operand came from aarch64_print_operand, and will include
+	     embedded strings indicating which style each character should
+	     have.  In the following code we split the text based on
+	     CURR_STYLE, and call the styled print callback to print each
+	     block of text in the appropriate style.  */
+	  char *start, *curr;
+	  enum disassembler_style curr_style = dis_style_text;
+
+	  start = curr = str;
+	  do
+	    {
+	      if (*curr == '\0'
+		  || (*curr == STYLE_MARKER_CHAR
+		      && ISXDIGIT (*(curr + 1))
+		      && *(curr + 2) == STYLE_MARKER_CHAR))
+		{
+		  /* Output content between our START position and CURR.  */
+		  int len = curr - start;
+		  int n = (*info->fprintf_styled_func) (info->stream,
+							curr_style,
+							"%.*s", len, start);
+		  if (n < 0)
+		    break;
+
+		  if (*curr == '\0')
+		    break;
+
+		  /* Skip over the initial STYLE_MARKER_CHAR.  */
+		  ++curr;
+
+		  /* Update the CURR_STYLE.  As there are less than 16
+		     styles, it is possible, that if the input is corrupted
+		     in some way, that we might set CURR_STYLE to an
+		     invalid value.  Don't worry though, we check for this
+		     situation.  */
+		  if (*curr >= '0' && *curr <= '9')
+		    curr_style = (enum disassembler_style) (*curr - '0');
+		  else if (*curr >= 'a' && *curr <= 'f')
+		    curr_style = (enum disassembler_style) (*curr - 'a' + 10);
+		  else
+		    curr_style = dis_style_text;
+
+		  /* Check for an invalid style having been selected.  This
+		     should never happen, but it doesn't hurt to be a
+		     little paranoid.  */
+		  if (curr_style > dis_style_comment_start)
+		    curr_style = dis_style_text;
+
+		  /* Skip the hex character, and the closing STYLE_MARKER_CHAR.  */
+		  curr += 2;
+
+		  /* Reset the START to after the style marker.  */
+		  start = curr;
+		}
+	      else
+		++curr;
+	    }
+	  while (true);
 	}
+
+      /* Print the comment.  This works because only the last operand ever
+	 adds a comment.  If that ever changes then we'll need to be
+	 smarter here.  */
+      if (cmt[0] != '\0')
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "\t// %s", cmt);
     }
 
     if (notes && !no_notes)
       {
 	*has_notes = true;
-	(*info->fprintf_func) (info->stream, "  // note: %s", notes);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "  // note: %s", notes);
       }
 }
 
@@ -3359,10 +3462,12 @@ print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
       char name[8];
 
       remove_dot_suffix (name, inst);
-      (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
+      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				    "%s.%s", name, inst->cond->names[0]);
     }
   else
-    (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
+    (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				  "%s", inst->opcode->name);
 }
 
 /* Decide whether we need to print a comment after the operands of
@@ -3379,9 +3484,10 @@ print_comment (const aarch64_inst *inst, struct disassemble_info *info)
       remove_dot_suffix (name, inst);
       num_conds = ARRAY_SIZE (inst->cond->names);
       for (i = 1; i < num_conds && inst->cond->names[i]; ++i)
-	(*info->fprintf_func) (info->stream, "%s %s.%s",
-			       i == 1 ? "  //" : ",",
-			       name, inst->cond->names[i]);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "%s %s.%s",
+				      i == 1 ? "  //" : ",",
+				      name, inst->cond->names[i]);
     }
 }
 
@@ -3398,28 +3504,30 @@ print_verifier_notes (aarch64_operand_error *detail,
      would not have succeeded.  We can safely ignore these.  */
   assert (detail->non_fatal);
 
-  (*info->fprintf_func) (info->stream, "  // note: ");
+  (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				"  // note: ");
   switch (detail->kind)
     {
     case AARCH64_OPDE_A_SHOULD_FOLLOW_B:
-      (*info->fprintf_func) (info->stream,
-			     _("this `%s' should have an immediately"
-			       " preceding `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("this `%s' should have an immediately"
+				      " preceding `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     case AARCH64_OPDE_EXPECTED_A_AFTER_B:
-      (*info->fprintf_func) (info->stream,
-			     _("expected `%s' after previous `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("expected `%s' after previous `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     default:
       assert (detail->error);
-      (*info->fprintf_func) (info->stream, "%s", detail->error);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    "%s", detail->error);
       if (detail->index >= 0)
-	(*info->fprintf_func) (info->stream, " at operand %d",
-			       detail->index + 1);
+	(*info->fprintf_styled_func) (info->stream, dis_style_text,
+				      " at operand %d", detail->index + 1);
       break;
     }
 }
@@ -3511,8 +3619,13 @@ print_insn_aarch64_word (bfd_vma pc,
     case ERR_NYI:
       /* Handle undefined instructions.  */
       info->insn_type = dis_noninsn;
-      (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
-			     word, err_msg[ret]);
+      (*info->fprintf_styled_func) (info->stream,
+				    dis_style_assembler_directive,
+				    ".inst\t");
+      (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
+				    "0x%08x", word);
+      (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				    " ; %s", err_msg[ret]);
       break;
     case ERR_OK:
       user_friendly_fixup (&inst);
@@ -3554,13 +3667,22 @@ print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
   switch (info->bytes_per_chunk)
     {
     case 1:
-      info->fprintf_func (info->stream, ".byte\t0x%02x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".byte\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%02x", word);
       break;
     case 2:
-      info->fprintf_func (info->stream, ".short\t0x%04x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".short\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%04x", word);
       break;
     case 4:
-      info->fprintf_func (info->stream, ".word\t0x%08x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".word\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%08x", word);
       break;
     default:
       abort ();
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 1c93f836020..00a4afac565 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -35,6 +35,35 @@
 int debug_dump = false;
 #endif /* DEBUG_AARCH64 */
 
+/* ... */
+static int
+debug_snprintf (char *str, size_t size, int lineno, const char *fmt, ...)
+{
+  char tmp[1024];
+  va_list ap;
+  int res;
+  static bool init;
+  static bool debug_p;
+  if (!init)
+    {
+      debug_p = getenv ("DEBUG_AARCH64") != NULL;
+      init = true;
+    }
+
+  if (debug_p)
+    snprintf (tmp, sizeof (tmp), "<%d:%s>", lineno, fmt);
+  else
+    snprintf (tmp, sizeof (tmp), "%s", fmt);
+
+  va_start (ap, fmt);
+  res = vsnprintf (str, size, tmp, ap);
+  va_end (ap);
+  return res;
+}
+
+#define snprintf(BUF,LEN,FMT,...)                              \
+  debug_snprintf (BUF, LEN, __LINE__, FMT, ##__VA_ARGS__)
+
 /* The enumeration strings associated with each value of a 5-bit SVE
    pattern operand.  A null entry indicates a reserved meaning.  */
 const char *const aarch64_sve_pattern_array[32] = {
@@ -3043,13 +3072,13 @@ expand_fp_imm (int size, uint32_t imm8)
    the register name that comes before the register number, such as "v".  */
 static void
 print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
-		     const char *prefix)
+		     const char *prefix, get_style_func get_style)
 {
   const int num_regs = opnd->reglist.num_regs;
   const int first_reg = opnd->reglist.first_regno;
   const int last_reg = (first_reg + num_regs - 1) & 0x1f;
   const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
-  char tb[8];	/* Temporary buffer.  */
+  char tb[16];	/* Temporary buffer.  */
 
   assert (opnd->type != AARCH64_OPND_LEt || opnd->reglist.has_index);
   assert (num_regs >= 1 && num_regs <= 4);
@@ -3057,7 +3086,9 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
   /* Prepare the index if any.  */
   if (opnd->reglist.has_index)
     /* PR 21096: The %100 is to silence a warning about possible truncation.  */
-    snprintf (tb, 8, "[%" PRIi64 "]", (opnd->reglist.index % 100));
+    snprintf (tb, sizeof (tb), "%s[%s%" PRIi64 "%s]",
+	      get_style (dis_style_text), get_style (dis_style_immediate),
+	      (opnd->reglist.index % 100), get_style (dis_style_text));
   else
     tb[0] = '\0';
 
@@ -3065,8 +3096,11 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
      more than two registers in the list, and the register numbers
      are monotonically increasing in increments of one.  */
   if (num_regs > 2 && last_reg > first_reg)
-    snprintf (buf, size, "{%s%d.%s-%s%d.%s}%s", prefix, first_reg, qlf_name,
-	      prefix, last_reg, qlf_name, tb);
+    snprintf (buf, size, "%s{%s%s%d.%s%s-%s%s%d.%s%s}%s",
+	      get_style (dis_style_text), get_style (dis_style_register),
+	      prefix, first_reg, qlf_name, get_style (dis_style_text),
+	      get_style (dis_style_register), prefix, last_reg, qlf_name,
+	      get_style (dis_style_text), tb);
   else
     {
       const int reg0 = first_reg;
@@ -3077,21 +3111,40 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
       switch (num_regs)
 	{
 	case 1:
-	  snprintf (buf, size, "{%s%d.%s}%s", prefix, reg0, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	case 2:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s}%s", prefix, reg0, qlf_name,
-		    prefix, reg1, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg1, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	case 3:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg1, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg2, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	case 4:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, prefix, reg3, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg1, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg2, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg3, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	}
     }
@@ -3103,32 +3156,53 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
 static void
 print_immediate_offset_address (char *buf, size_t size,
 				const aarch64_opnd_info *opnd,
-				const char *base)
+				const char *base, get_style_func get_style)
 {
   if (opnd->addr.writeback)
     {
       if (opnd->addr.preind)
         {
 	  if (opnd->type == AARCH64_OPND_ADDR_SIMM10 && !opnd->addr.offset.imm)
-            snprintf (buf, size, "[%s]!", base);
+	    snprintf (buf, size, "%s[%s%s%s]!",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), base,
+		      get_style (dis_style_text));
           else
-	    snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
+	    snprintf (buf, size, "%s[%s%s%s, %s#%d%s]!",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), base,
+		      get_style (dis_style_text),
+		      get_style (dis_style_immediate), opnd->addr.offset.imm,
+		      get_style (dis_style_text));
         }
       else
-	snprintf (buf, size, "[%s], #%d", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "%s[%s%s%s], %s#%d",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  base, get_style (dis_style_text),
+		  get_style (dis_style_immediate), opnd->addr.offset.imm);
     }
   else
     {
       if (opnd->shifter.operator_present)
 	{
 	  assert (opnd->shifter.kind == AARCH64_MOD_MUL_VL);
-	  snprintf (buf, size, "[%s, #%d, mul vl]",
-		    base, opnd->addr.offset.imm);
+	  snprintf (buf, size, "%s[%s%s%s, %s#%d%s, mul vl]",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), base,
+		    get_style (dis_style_text),
+		    get_style (dis_style_immediate), opnd->addr.offset.imm,
+		    get_style (dis_style_text));
 	}
       else if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "%s[%s%s%s, %s#%d%s]",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  base, get_style (dis_style_text),
+		  get_style (dis_style_immediate), opnd->addr.offset.imm,
+		  get_style (dis_style_text));
       else
-	snprintf (buf, size, "[%s]", base);
+	snprintf (buf, size, "%s[%s%s%s]", get_style (dis_style_text),
+		  get_style (dis_style_register), base,
+		  get_style (dis_style_text));
     }
 }
 
@@ -3138,9 +3212,10 @@ print_immediate_offset_address (char *buf, size_t size,
 static void
 print_register_offset_address (char *buf, size_t size,
 			       const aarch64_opnd_info *opnd,
-			       const char *base, const char *offset)
+			       const char *base, const char *offset,
+			       get_style_func get_style)
 {
-  char tb[16];			/* Temporary buffer.  */
+  char tb[32];			/* Temporary buffer.  */
   bool print_extend_p = true;
   bool print_amount_p = true;
   const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
@@ -3161,16 +3236,23 @@ print_register_offset_address (char *buf, size_t size,
   if (print_extend_p)
     {
       if (print_amount_p)
-	snprintf (tb, sizeof (tb), ", %s #%" PRIi64, shift_name,
+	snprintf (tb, sizeof (tb), ", %s%s %s#%" PRIi64,
+		  get_style (dis_style_sub_mnemonic),
+		  shift_name,
+		  get_style (dis_style_immediate),
   /* PR 21096: The %100 is to silence a warning about possible truncation.  */
 		  (opnd->shifter.amount % 100));
       else
-	snprintf (tb, sizeof (tb), ", %s", shift_name);
+	snprintf (tb, sizeof (tb), ", %s%s",
+		  get_style (dis_style_sub_mnemonic), shift_name);
     }
   else
     tb[0] = '\0';
 
-  snprintf (buf, size, "[%s, %s%s]", base, offset, tb);
+  snprintf (buf, size, "%s[%s%s%s, %s%s%s%s]",
+	    get_style (dis_style_text), get_style (dis_style_register),
+	    base, get_style (dis_style_text), get_style (dis_style_register),
+	    offset, get_style (dis_style_text), tb);
 }
 
 /* Print ZA tiles from imm8 in ZERO instruction.
@@ -3230,7 +3312,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 		       const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
 		       bfd_vma *address, char** notes,
 		       char *comment, size_t comment_size,
-		       aarch64_feature_set features)
+		       aarch64_feature_set features,
+		       get_style_func get_style)
 {
   unsigned int i, num_conds;
   const char *name = NULL;
@@ -3278,7 +3361,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	break;
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
-      snprintf (buf, size, "%s",
+      snprintf (buf, size, "%s%s",
+		get_style (dis_style_register),
 		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
       break;
 
@@ -3291,7 +3375,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      || opnd->qualifier == AARCH64_OPND_QLF_WSP
 	      || opnd->qualifier == AARCH64_OPND_QLF_X
 	      || opnd->qualifier == AARCH64_OPND_QLF_SP);
-      snprintf (buf, size, "%s",
+      snprintf (buf, size, "%s%s",
+		get_style (dis_style_register),
 		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 1));
       break;
 
@@ -3311,19 +3396,26 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	  if (opnd->shifter.amount == 0)
 	    {
 	      /* Shifter omitted.  */
-	      snprintf (buf, size, "%s",
+	      snprintf (buf, size, "%s%s",
+			get_style (dis_style_register),
 			get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
 	      break;
 	    }
 	}
       if (opnd->shifter.amount)
-	snprintf (buf, size, "%s, %s #%" PRIi64,
+	snprintf (buf, size, "%s%s%s, %s%s %s#%" PRIi64,
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+		  get_style (dis_style_text),
+		  get_style (dis_style_sub_mnemonic),
 		  aarch64_operand_modifiers[kind].name,
-		  opnd->shifter.amount);
+		  get_style (dis_style_immediate), opnd->shifter.amount);
       else
-	snprintf (buf, size, "%s, %s",
+	snprintf (buf, size, "%s%s%s, %s%s",
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+		  get_style (dis_style_text),
+		  get_style (dis_style_sub_mnemonic),
 		  aarch64_operand_modifiers[kind].name);
       break;
 
@@ -3331,13 +3423,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
       if (opnd->shifter.amount == 0 && opnd->shifter.kind == AARCH64_MOD_LSL)
-	snprintf (buf, size, "%s",
+	snprintf (buf, size, "%s%s",
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
       else
-	snprintf (buf, size, "%s, %s #%" PRIi64,
+	snprintf (buf, size, "%s%s%s, %s%s %s#%" PRIi64,
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+		  get_style (dis_style_text),
+		  get_style (dis_style_sub_mnemonic),
 		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+		  get_style (dis_style_immediate), opnd->shifter.amount);
       break;
 
     case AARCH64_OPND_Fd:
@@ -3353,7 +3449,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Vd:
     case AARCH64_OPND_SVE_Vm:
     case AARCH64_OPND_SVE_Vn:
-      snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
+      snprintf (buf, size, "%s%s%d",
+		get_style (dis_style_register),
+		aarch64_get_qualifier_name (opnd->qualifier),
 		opnd->reg.regno);
       break;
 
@@ -3361,7 +3459,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Vd:
     case AARCH64_OPND_Vn:
     case AARCH64_OPND_Vm:
-      snprintf (buf, size, "v%d.%s", opnd->reg.regno,
+      snprintf (buf, size, "%sv%d.%s",
+		get_style (dis_style_register), opnd->reg.regno,
 		aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
@@ -3370,21 +3469,26 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Em:
     case AARCH64_OPND_Em16:
     case AARCH64_OPND_SM3_IMM2:
-      snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
+      snprintf (buf, size, "%sv%d.%s%s[%s%" PRIi64 "%s]",
+		get_style (dis_style_register), opnd->reglane.regno,
 		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+		get_style (dis_style_text), get_style (dis_style_immediate),
+		opnd->reglane.index, get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_VdD1:
     case AARCH64_OPND_VnD1:
-      snprintf (buf, size, "v%d.d[1]", opnd->reg.regno);
+      snprintf (buf, size, "%sv%d.d%s[%s1%s]",
+		get_style (dis_style_register), opnd->reg.regno,
+		get_style (dis_style_text), get_style (dis_style_immediate),
+		get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_LVn:
     case AARCH64_OPND_LVt:
     case AARCH64_OPND_LVt_AL:
     case AARCH64_OPND_LEt:
-      print_register_list (buf, size, opnd, "v");
+      print_register_list (buf, size, opnd, "v", get_style);
       break;
 
     case AARCH64_OPND_SVE_Pd:
@@ -3397,13 +3501,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Pt:
     case AARCH64_OPND_SME_Pm:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "p%d", opnd->reg.regno);
+	snprintf (buf, size, "%sp%d", get_style (dis_style_register),
+		  opnd->reg.regno);
       else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
 	       || opnd->qualifier == AARCH64_OPND_QLF_P_M)
-	snprintf (buf, size, "p%d/%s", opnd->reg.regno,
+	snprintf (buf, size, "%sp%d/%s", get_style (dis_style_register),
+		  opnd->reg.regno,
 		  aarch64_get_qualifier_name (opnd->qualifier));
       else
-	snprintf (buf, size, "p%d.%s", opnd->reg.regno,
+	snprintf (buf, size, "%sp%d.%s", get_style (dis_style_register),
+		  opnd->reg.regno,
 		  aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
@@ -3415,15 +3522,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zn:
     case AARCH64_OPND_SVE_Zt:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "z%d", opnd->reg.regno);
+	snprintf (buf, size, "%sz%d", get_style (dis_style_register),
+		  opnd->reg.regno);
       else
-	snprintf (buf, size, "z%d.%s", opnd->reg.regno,
+	snprintf (buf, size, "%sz%d.%s", get_style (dis_style_register),
+		  opnd->reg.regno,
 		  aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
     case AARCH64_OPND_SVE_ZnxN:
     case AARCH64_OPND_SVE_ZtxN:
-      print_register_list (buf, size, opnd, "z");
+      print_register_list (buf, size, opnd, "z", get_style);
       break;
 
     case AARCH64_OPND_SVE_Zm3_INDEX:
@@ -3432,14 +3541,18 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zm4_11_INDEX:
     case AARCH64_OPND_SVE_Zm4_INDEX:
     case AARCH64_OPND_SVE_Zn_INDEX:
-      snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
+      snprintf (buf, size, "%sz%d.%s%s[%s%" PRIi64 "%s]",
+		get_style (dis_style_register), opnd->reglane.regno,
 		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+		get_style (dis_style_text),
+		get_style (dis_style_immediate), opnd->reglane.index,
+		get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_SME_ZAda_2b:
     case AARCH64_OPND_SME_ZAda_3b:
-      snprintf (buf, size, "za%d.%s", opnd->reg.regno,
+      snprintf (buf, size, "%sza%d.%s", get_style (dis_style_register),
+		opnd->reg.regno,
                 aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
@@ -3467,7 +3580,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_SME_SM_ZA:
-      snprintf (buf, size, "%s", opnd->reg.regno == 's' ? "sm" : "za");
+      snprintf (buf, size, "%s%s",
+		get_style (dis_style_register),
+		opnd->reg.regno == 's' ? "sm" : "za");
       break;
 
     case AARCH64_OPND_SME_PnT_Wm_imm:
@@ -3480,7 +3595,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 
     case AARCH64_OPND_CRn:
     case AARCH64_OPND_CRm:
-      snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, "%sC%" PRIi64, get_style (dis_style_register),
+		opnd->imm.value);
       break;
 
     case AARCH64_OPND_IDX:
@@ -3521,7 +3637,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_IMM_ROT1:
     case AARCH64_OPND_SVE_IMM_ROT2:
     case AARCH64_OPND_SVE_IMM_ROT3:
-      snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		opnd->imm.value);
       break;
 
     case AARCH64_OPND_SVE_I1_HALF_ONE:
@@ -3530,7 +3647,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       {
 	single_conv_t c;
 	c.i = opnd->imm.value;
-	snprintf (buf, size, "#%.1f", c.f);
+	snprintf (buf, size, "%s#%.1f", get_style (dis_style_immediate), c.f);
 	break;
       }
 
@@ -3541,9 +3658,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[enum_value]);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		  aarch64_sve_pattern_array[enum_value]);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       break;
 
     case AARCH64_OPND_SVE_PATTERN_SCALED:
@@ -3554,13 +3673,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[opnd->imm.value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[opnd->imm.value]);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		  aarch64_sve_pattern_array[opnd->imm.value]);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       if (opnd->shifter.operator_present)
 	{
 	  size_t len = strlen (buf);
-	  snprintf (buf + len, size - len, ", %s #%" PRIi64,
+	  snprintf (buf + len, size - len, ", %s%s #%" PRIi64,
+		    get_style (dis_style_sub_mnemonic),
 		    aarch64_operand_modifiers[opnd->shifter.kind].name,
 		    opnd->shifter.amount);
 	}
@@ -3570,9 +3692,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
       if (aarch64_sve_prfop_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_prfop_array[enum_value]);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		  aarch64_sve_prfop_array[enum_value]);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       break;
 
     case AARCH64_OPND_IMM_MOV:
@@ -3581,12 +3705,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	case 4:	/* e.g. MOV Wd, #<imm32>.  */
 	    {
 	      int imm32 = opnd->imm.value;
-	      snprintf (buf, size, "#0x%-20x", imm32);
+	      snprintf (buf, size, "%s#0x%-20x",
+			get_style (dis_style_immediate), imm32);
 	      snprintf (comment, comment_size, "#%d", imm32);
 	    }
 	  break;
 	case 8:	/* e.g. MOV Xd, #<imm64>.  */
-	  snprintf (buf, size, "#0x%-20" PRIx64, opnd->imm.value);
+	  snprintf (buf, size, "%s#0x%-20" PRIx64,
+		    get_style (dis_style_immediate), opnd->imm.value);
 	  snprintf (comment, comment_size, "#%" PRIi64, opnd->imm.value);
 	  break;
 	default:
@@ -3596,7 +3722,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_FPIMM0:
-      snprintf (buf, size, "#0.0");
+      snprintf (buf, size, "%s#0.0", get_style (dis_style_immediate));
       break;
 
     case AARCH64_OPND_LIMM:
@@ -3606,30 +3732,42 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_LIMM:
     case AARCH64_OPND_SVE_LIMM_MOV:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
+	snprintf (buf, size, "%s#0x%" PRIx64 "%s, %slsl %s#%" PRIi64,
+		  get_style (dis_style_immediate), opnd->imm.value,
+		  get_style (dis_style_text),
+		  get_style (dis_style_sub_mnemonic),
+		  get_style (dis_style_immediate),
 		  opnd->shifter.amount);
       else
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size, "%s#0x%" PRIx64,
+		  get_style (dis_style_immediate), opnd->imm.value);
       break;
 
     case AARCH64_OPND_SIMD_IMM:
     case AARCH64_OPND_SIMD_IMM_SFT:
       if ((! opnd->shifter.amount && opnd->shifter.kind == AARCH64_MOD_LSL)
 	  || opnd->shifter.kind == AARCH64_MOD_NONE)
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size, "%s#0x%" PRIx64,
+		  get_style (dis_style_immediate), opnd->imm.value);
       else
-	snprintf (buf, size, "#0x%" PRIx64 ", %s #%" PRIi64, opnd->imm.value,
+	snprintf (buf, size, "%s#0x%" PRIx64 "%s, %s%s %s#%" PRIi64,
+		  get_style (dis_style_immediate), opnd->imm.value,
+		  get_style (dis_style_text),
+		  get_style (dis_style_sub_mnemonic),
 		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+		  get_style (dis_style_immediate), opnd->shifter.amount);
       break;
 
     case AARCH64_OPND_SVE_AIMM:
     case AARCH64_OPND_SVE_ASIMM:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
+	snprintf (buf, size, "%s#%" PRIi64 "%s, lsl %s#%" PRIi64,
+		  get_style (dis_style_immediate), opnd->imm.value,
+		  get_style (dis_style_text), get_style (dis_style_immediate),
 		  opnd->shifter.amount);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       break;
 
     case AARCH64_OPND_FPIMM:
@@ -3641,21 +3779,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	    {
 	      half_conv_t c;
 	      c.i = expand_fp_imm (2, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size,  "%s#%.18e",
+			get_style (dis_style_immediate), c.f);
 	    }
 	  break;
 	case 4:	/* e.g. FMOV <Vd>.4S, #<imm>.  */
 	    {
 	      single_conv_t c;
 	      c.i = expand_fp_imm (4, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size,  "%s#%.18e",
+			get_style (dis_style_immediate), c.f);
 	    }
 	  break;
 	case 8:	/* e.g. FMOV <Sd>, #<imm>.  */
 	    {
 	      double_conv_t c;
 	      c.i = expand_fp_imm (8, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.d);
+	      snprintf (buf, size,  "%s#%.18e",
+			get_style (dis_style_immediate), c.d);
 	    }
 	  break;
 	default:
@@ -3676,12 +3817,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      (int64_t) get_optional_operand_default_value (opcode)))
 	/* Omit the operand, e.g. DCPS1.  */
 	break;
-      snprintf (buf, size, "#0x%x", (unsigned int)opnd->imm.value);
+      snprintf (buf, size, "%s#0x%x", get_style (dis_style_immediate),
+		(unsigned int)opnd->imm.value);
       break;
 
     case AARCH64_OPND_COND:
     case AARCH64_OPND_COND1:
-      snprintf (buf, size, "%s", opnd->cond->names[0]);
+      snprintf (buf, size, "%s%s", get_style (dis_style_sub_mnemonic),
+		opnd->cond->names[0]);
       num_conds = ARRAY_SIZE (opnd->cond->names);
       for (i = 1; i < num_conds && opnd->cond->names[i]; ++i)
 	{
@@ -3706,7 +3849,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, "%s#0x%" PRIx64,
+		get_style (dis_style_address), addr);
       break;
 
     case AARCH64_OPND_ADDR_PCREL14:
@@ -3722,7 +3866,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, "%s#0x%" PRIx64, get_style (dis_style_address),
+		addr);
       break;
 
     case AARCH64_OPND_ADDR_SIMPLE:
@@ -3732,12 +3877,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (opnd->type == AARCH64_OPND_SIMD_ADDR_POST)
 	{
 	  if (opnd->addr.offset.is_reg)
-	    snprintf (buf, size, "[%s], x%d", name, opnd->addr.offset.regno);
+	    snprintf (buf, size, "%s[%s%s%s], %sx%d",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), name,
+		      get_style (dis_style_text),
+		      get_style (dis_style_register),
+		      opnd->addr.offset.regno);
 	  else
-	    snprintf (buf, size, "[%s], #%d", name, opnd->addr.offset.imm);
+	    snprintf (buf, size, "%s[%s%s%s], %s#%d",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), name,
+		      get_style (dis_style_text),
+		      get_style (dis_style_immediate),
+		      opnd->addr.offset.imm);
 	}
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "%s[%s%s%s]",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  name, get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
@@ -3753,14 +3910,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RX_LSL3:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_offset_int_reg_name (opnd));
+	 get_offset_int_reg_name (opnd), get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZX:
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0));
+	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0), get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_RZ:
@@ -3777,7 +3934,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 get_style);
       break;
 
     case AARCH64_OPND_ADDR_SIMM7:
@@ -3801,7 +3959,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RI_U6x4:
     case AARCH64_OPND_SVE_ADDR_RI_U6x8:
       print_immediate_offset_address
-	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1));
+	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
+	 get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZI_U5:
@@ -3810,7 +3969,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
       print_immediate_offset_address
 	(buf, size, opnd,
-	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
+	 get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
@@ -3819,15 +3979,22 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 get_style);
       break;
 
     case AARCH64_OPND_ADDR_UIMM12:
       name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
       if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", name, opnd->addr.offset.imm);
+	snprintf (buf, size, "%s[%s%s%s, %s#%d%s]",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  name, get_style (dis_style_text),
+		  get_style (dis_style_immediate), opnd->addr.offset.imm,
+		  get_style (dis_style_text));
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "%s[%s%s%s]", get_style (dis_style_text),
+		  get_style (dis_style_register), name,
+		  get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_SYSREG:
@@ -3866,14 +4033,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	}
 
       if (name)
-	snprintf (buf, size, "%s", name);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register), name);
       else
 	{
 	  /* Implementation defined system register.  */
 	  unsigned int value = opnd->sysreg.value;
-	  snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
-		    (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
-		    value & 0x7);
+	  snprintf (buf, size, "%ss%u_%u_c%u_c%u_%u",
+		    get_style (dis_style_register), (value >> 14) & 0x3,
+		    (value >> 11) & 0x7, (value >> 7) & 0xf,
+		    (value >> 3) & 0xf, value & 0x7);
 	}
       break;
 
@@ -3899,12 +4067,21 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SYSREG_IC:
     case AARCH64_OPND_SYSREG_TLBI:
     case AARCH64_OPND_SYSREG_SR:
-      snprintf (buf, size, "%s", opnd->sysins_op->name);
+      snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		opnd->sysins_op->name);
       break;
 
     case AARCH64_OPND_BARRIER:
     case AARCH64_OPND_BARRIER_DSB_NXS:
-      snprintf (buf, size, "%s", opnd->barrier->name);
+      {
+	enum disassembler_style style;
+	if (opnd->barrier->name[0] == '#')
+	  style = dis_style_immediate;
+	else
+	  style = dis_style_sub_mnemonic;
+	snprintf (buf, size, "%s%s", get_style (style),
+		  opnd->barrier->name);
+      }
       break;
 
     case AARCH64_OPND_BARRIER_ISB:
@@ -3912,38 +4089,46 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (! optional_operand_p (opcode, idx)
 	  || (opnd->barrier->value
 	      != get_optional_operand_default_value (opcode)))
-	snprintf (buf, size, "#0x%x", opnd->barrier->value);
+	snprintf (buf, size, "%s#0x%x", get_style (dis_style_immediate),
+		  opnd->barrier->value);
       break;
 
     case AARCH64_OPND_PRFOP:
       if (opnd->prfop->name != NULL)
-	snprintf (buf, size, "%s", opnd->prfop->name);
+	snprintf (buf, size, "%s%s", get_style (dis_style_sub_mnemonic),
+		  opnd->prfop->name);
       else
-	snprintf (buf, size, "#0x%02x", opnd->prfop->value);
+	snprintf (buf, size, "%s#0x%02x", get_style (dis_style_immediate),
+		  opnd->prfop->value);
       break;
 
     case AARCH64_OPND_BARRIER_PSB:
-      snprintf (buf, size, "csync");
+      snprintf (buf, size, "%scsync", get_style (dis_style_sub_mnemonic));
       break;
 
     case AARCH64_OPND_BTI_TARGET:
       if ((HINT_FLAG (opnd->hint_option->value) & HINT_OPD_F_NOPRINT) == 0)
-	snprintf (buf, size, "%s", opnd->hint_option->name);
+	snprintf (buf, size, "%s%s", get_style (dis_style_sub_mnemonic),
+		  opnd->hint_option->name);
       break;
 
     case AARCH64_OPND_MOPS_ADDR_Rd:
     case AARCH64_OPND_MOPS_ADDR_Rs:
-      snprintf (buf, size, "[%s]!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+      snprintf (buf, size, "%s[%s%s%s]!",
+		get_style (dis_style_text), get_style (dis_style_register),
+		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0),
+		get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_MOPS_WB_Rn:
-      snprintf (buf, size, "%s!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+      snprintf (buf, size, "%s%s%s!",
+		get_style (dis_style_register),
+		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0),
+		get_style (dis_style_text));
       break;
 
     default:
-      snprintf (buf, size, "<invalid>");
+      snprintf (buf, size, "%s<invalid>", get_style (dis_style_text));
       break;
     }
 }
-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCHv2 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-07-05 12:46   ` [PATCHv2 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
@ 2022-07-05 12:51     ` Andrew Burgess
  2022-07-05 13:10       ` Richard Earnshaw
  0 siblings, 1 reply; 31+ messages in thread
From: Andrew Burgess @ 2022-07-05 12:51 UTC (permalink / raw)
  To: Andrew Burgess via Binutils, binutils


Apologies, I left some debug code in this latest version of the
patch.  Here's an update with the debug code removed.

Thanks,
Andrew

---

commit 69a681f8747a145dcaba969ae8972a20d1176a05
Author: Andrew Burgess <aburgess@redhat.com>
Date:   Thu Apr 28 13:31:07 2022 +0100

    libopcodes/aarch64: add support for disassembler styling
    
    This commit enables disassembler styling for AArch64.  After this
    commit it is possible to have objdump style AArch64 disassembler
    output (using --disassembler-color option).  Once the required GDB
    patches are merged, GDB will also style the disassembler output.
    
    The changes to support styling are mostly split between two files
    opcodes/aarch64-dis.c and opcodes/aarch64-opc.c.
    
    The entry point for the AArch64 disassembler can be found in
    aarch64-dis.c, this file handles printing the instruction mnemonics,
    and assembler directives (e.g. '.byte', '.word', etc).  Some operands,
    mostly relating to assembler directives are also printed from this
    file.  This commit changes all of this to pass through suitable
    styling information.
    
    However, for most "normal" instructions, the instruction operands are
    printed using a two step process.  From aarch64-dis.c, in the
    print_operands function, the function aarch64_print_operand is called,
    this function is in aarch64-opc.c, and converts an instruction operand
    into a string.  Then, back in print_operands (aarch64-dis.c), the
    operand string is printed.
    
    Unfortunately, the string returned by aarch64_print_operand can be
    quite complex, it will include syntax elements, like '[' and ']', in
    addition to register names and immediate values.  In some cases, a
    single operand will expand into what will appear (to the user) as
    multiple operands separated with a ','.
    
    This makes the task of styling more complex, all these different
    components need to by styled differently, so we need to get the
    styling information out of aarch64_print_operand in some way.
    
    The solution that I propose here is similar to the solution that I
    used for the i386 disassembler.
    
    Currently, aarch64_print_operand uses snprintf to write the operand
    text into a buffer provided by the caller.
    
    What I propose is that we pass an extra argument to the
    aarch64_print_operand function, this argument will be a callback
    function that converts a disassembler style into a string.  These
    strings can then be written into the buffer using snprintf.  Here's an
    example, 'get_style' is the new callback function:
    
        snprintf (buf, size, "%s%s",
                  get_style (dis_style_register),
                  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
    
    The string returned by 'get_style' is a special sequence of characters
    that is not otherwise seen in the disassembler output.  In the
    print_operands function we can now scan the buffer returned by
    aarch64_print_operand, and split the text based on the style
    markers.  Each separately styled block is then printed with the
    correct style.
    
    The aarch64_print_operand function is also called from the assembler
    to aid in printing diagnostic messages.  Right now I have no plans to
    add styling to the assembler output, and so, in this case, the
    'get_style' callback is a dummy function that always returns an empty
    string.  As a result, when the assembler calls aarch64_print_operand,
    the string returns can be immediately printed with no special style
    handling required.
    
    I've gone through and updated arch64-opc.c as best I can to add
    styling information.  I've mostly used the gas/testsuite/gas/aarch64
    tests to check the styling, assembling then disassembling each source
    file, then checking that the output looks reasonable.
    
    With objdump disassembler color turned off, there should be no change
    in the output after this commit.

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 779db31828b..740bde53ea8 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -5347,6 +5347,15 @@ assign_qualifier_sequence (aarch64_inst *instr,
     instr->operands[i].qualifier = *qualifiers;
 }
 
+/* Return a string indicating a switch to STYLE.  As the assembler doesn't
+   use styling in its output, this always returns an empty string.  */
+
+static const char *
+get_style_text (enum disassembler_style style ATTRIBUTE_UNUSED)
+{
+  return "";
+}
+
 /* Print operands for the diagnosis purpose.  */
 
 static void
@@ -5371,7 +5380,7 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL,
-			     NULL, cmt, sizeof (cmt), cpu_variant);
+			     NULL, cmt, sizeof (cmt), cpu_variant, get_style_text);
 
       /* Delimiter.  */
       if (str[0] != '\0')
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 186ba9a4800..373deb6b49c 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -27,6 +27,8 @@
 #include <assert.h>
 #include <stdlib.h>
 
+#include "dis-asm.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -1367,12 +1369,16 @@ aarch64_replace_opcode (struct aarch64_inst *,
 extern const aarch64_opcode *
 aarch64_get_opcode (enum aarch64_op);
 
+/* Return a text string that indicates a change of disassembler style.  */
+typedef const char *(*get_style_func) (enum disassembler_style);
+
 /* Generate the string representation of an operand.  */
 extern void
 aarch64_print_operand (char *, size_t, bfd_vma, const aarch64_opcode *,
 		       const aarch64_opnd_info *, int, int *, bfd_vma *,
 		       char **, char *, size_t,
-		       aarch64_feature_set features);
+		       aarch64_feature_set features,
+		       get_style_func get_style);
 
 /* Miscellaneous interface.  */
 
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index acaad28fdff..fbbd0c5e087 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -25,9 +25,14 @@
 #include "opintl.h"
 #include "aarch64-dis.h"
 #include "elf-bfd.h"
+#include "safe-ctype.h"
 
 #define INSNLEN 4
 
+/* This character is used to encode style information within the output
+   buffers.  See get_style_text and print_operands for more details.  */
+#define STYLE_MARKER_CHAR '\002'
+
 /* Cached mapping symbol state.  */
 enum map_type
 {
@@ -3275,6 +3280,45 @@ aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst,
   return ERR_UND;
 }
 
+/* When the aarch64_print_operand code is building the string to represent
+   an operand, this function is called each time we need to change style,
+   with STYLE being the new style.  The string returned from this function
+   will then be embedded in to the operand buffer.
+
+   When we finally print the operand buffer in print_operands, we find
+   these style markers and split the operand text into chunks, where each
+   chunk is a series of characters with the same style.  */
+
+static const char *
+get_style_text (enum disassembler_style style)
+{
+  static bool init = false;
+  static char formats[16][4];
+  unsigned num;
+
+  /* First time through we build a string for every possible format.  This
+     code relies on there being no more than 16 different styles (there's
+     an assert below for this).  */
+  if (!init)
+    {
+      int i;
+
+      for (i = 0; i <= 0xf; ++i)
+	{
+	  int res = snprintf (&formats[i][0], sizeof (formats[i]), "%c%x%c",
+			      STYLE_MARKER_CHAR, i, STYLE_MARKER_CHAR);
+	  assert (res == 3);
+	}
+
+      init = true;
+    }
+
+  /* Return the string that marks switching to STYLE.  */
+  num = (unsigned) style;
+  assert (style <= 0xf);
+  return formats[num];
+}
+
 /* Print operands.  */
 
 static void
@@ -3301,32 +3345,91 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
 			     &info->target, &notes, cmt, sizeof (cmt),
-			     arch_variant);
+			     arch_variant, get_style_text);
 
       /* Print the delimiter (taking account of omitted operand(s)).  */
       if (str[0] != '\0')
-	(*info->fprintf_func) (info->stream, "%s",
-			       num_printed++ == 0 ? "\t" : ", ");
+	(*info->fprintf_styled_func) (info->stream, dis_style_text, "%s",
+				      num_printed++ == 0 ? "\t" : ", ");
 
       /* Print the operand.  */
       if (pcrel_p)
 	(*info->print_address_func) (info->target, info);
       else
 	{
-	  (*info->fprintf_func) (info->stream, "%s", str);
-
-	  /* Print the comment.  This works because only the last operand
-	     ever adds a comment.  If that ever changes then we'll need to
-	     be smarter here.  */
-	  if (cmt[0] != '\0')
-	    (*info->fprintf_func) (info->stream, "\t// %s", cmt);
+	  /* This operand came from aarch64_print_operand, and will include
+	     embedded strings indicating which style each character should
+	     have.  In the following code we split the text based on
+	     CURR_STYLE, and call the styled print callback to print each
+	     block of text in the appropriate style.  */
+	  char *start, *curr;
+	  enum disassembler_style curr_style = dis_style_text;
+
+	  start = curr = str;
+	  do
+	    {
+	      if (*curr == '\0'
+		  || (*curr == STYLE_MARKER_CHAR
+		      && ISXDIGIT (*(curr + 1))
+		      && *(curr + 2) == STYLE_MARKER_CHAR))
+		{
+		  /* Output content between our START position and CURR.  */
+		  int len = curr - start;
+		  int n = (*info->fprintf_styled_func) (info->stream,
+							curr_style,
+							"%.*s", len, start);
+		  if (n < 0)
+		    break;
+
+		  if (*curr == '\0')
+		    break;
+
+		  /* Skip over the initial STYLE_MARKER_CHAR.  */
+		  ++curr;
+
+		  /* Update the CURR_STYLE.  As there are less than 16
+		     styles, it is possible, that if the input is corrupted
+		     in some way, that we might set CURR_STYLE to an
+		     invalid value.  Don't worry though, we check for this
+		     situation.  */
+		  if (*curr >= '0' && *curr <= '9')
+		    curr_style = (enum disassembler_style) (*curr - '0');
+		  else if (*curr >= 'a' && *curr <= 'f')
+		    curr_style = (enum disassembler_style) (*curr - 'a' + 10);
+		  else
+		    curr_style = dis_style_text;
+
+		  /* Check for an invalid style having been selected.  This
+		     should never happen, but it doesn't hurt to be a
+		     little paranoid.  */
+		  if (curr_style > dis_style_comment_start)
+		    curr_style = dis_style_text;
+
+		  /* Skip the hex character, and the closing STYLE_MARKER_CHAR.  */
+		  curr += 2;
+
+		  /* Reset the START to after the style marker.  */
+		  start = curr;
+		}
+	      else
+		++curr;
+	    }
+	  while (true);
 	}
+
+      /* Print the comment.  This works because only the last operand ever
+	 adds a comment.  If that ever changes then we'll need to be
+	 smarter here.  */
+      if (cmt[0] != '\0')
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "\t// %s", cmt);
     }
 
     if (notes && !no_notes)
       {
 	*has_notes = true;
-	(*info->fprintf_func) (info->stream, "  // note: %s", notes);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "  // note: %s", notes);
       }
 }
 
@@ -3359,10 +3462,12 @@ print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
       char name[8];
 
       remove_dot_suffix (name, inst);
-      (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
+      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				    "%s.%s", name, inst->cond->names[0]);
     }
   else
-    (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
+    (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				  "%s", inst->opcode->name);
 }
 
 /* Decide whether we need to print a comment after the operands of
@@ -3379,9 +3484,10 @@ print_comment (const aarch64_inst *inst, struct disassemble_info *info)
       remove_dot_suffix (name, inst);
       num_conds = ARRAY_SIZE (inst->cond->names);
       for (i = 1; i < num_conds && inst->cond->names[i]; ++i)
-	(*info->fprintf_func) (info->stream, "%s %s.%s",
-			       i == 1 ? "  //" : ",",
-			       name, inst->cond->names[i]);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "%s %s.%s",
+				      i == 1 ? "  //" : ",",
+				      name, inst->cond->names[i]);
     }
 }
 
@@ -3398,28 +3504,30 @@ print_verifier_notes (aarch64_operand_error *detail,
      would not have succeeded.  We can safely ignore these.  */
   assert (detail->non_fatal);
 
-  (*info->fprintf_func) (info->stream, "  // note: ");
+  (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				"  // note: ");
   switch (detail->kind)
     {
     case AARCH64_OPDE_A_SHOULD_FOLLOW_B:
-      (*info->fprintf_func) (info->stream,
-			     _("this `%s' should have an immediately"
-			       " preceding `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("this `%s' should have an immediately"
+				      " preceding `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     case AARCH64_OPDE_EXPECTED_A_AFTER_B:
-      (*info->fprintf_func) (info->stream,
-			     _("expected `%s' after previous `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("expected `%s' after previous `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     default:
       assert (detail->error);
-      (*info->fprintf_func) (info->stream, "%s", detail->error);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    "%s", detail->error);
       if (detail->index >= 0)
-	(*info->fprintf_func) (info->stream, " at operand %d",
-			       detail->index + 1);
+	(*info->fprintf_styled_func) (info->stream, dis_style_text,
+				      " at operand %d", detail->index + 1);
       break;
     }
 }
@@ -3511,8 +3619,13 @@ print_insn_aarch64_word (bfd_vma pc,
     case ERR_NYI:
       /* Handle undefined instructions.  */
       info->insn_type = dis_noninsn;
-      (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
-			     word, err_msg[ret]);
+      (*info->fprintf_styled_func) (info->stream,
+				    dis_style_assembler_directive,
+				    ".inst\t");
+      (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
+				    "0x%08x", word);
+      (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				    " ; %s", err_msg[ret]);
       break;
     case ERR_OK:
       user_friendly_fixup (&inst);
@@ -3554,13 +3667,22 @@ print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
   switch (info->bytes_per_chunk)
     {
     case 1:
-      info->fprintf_func (info->stream, ".byte\t0x%02x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".byte\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%02x", word);
       break;
     case 2:
-      info->fprintf_func (info->stream, ".short\t0x%04x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".short\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%04x", word);
       break;
     case 4:
-      info->fprintf_func (info->stream, ".word\t0x%08x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".word\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%08x", word);
       break;
     default:
       abort ();
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 1c93f836020..4f38a3328d4 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -3043,13 +3043,13 @@ expand_fp_imm (int size, uint32_t imm8)
    the register name that comes before the register number, such as "v".  */
 static void
 print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
-		     const char *prefix)
+		     const char *prefix, get_style_func get_style)
 {
   const int num_regs = opnd->reglist.num_regs;
   const int first_reg = opnd->reglist.first_regno;
   const int last_reg = (first_reg + num_regs - 1) & 0x1f;
   const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
-  char tb[8];	/* Temporary buffer.  */
+  char tb[16];	/* Temporary buffer.  */
 
   assert (opnd->type != AARCH64_OPND_LEt || opnd->reglist.has_index);
   assert (num_regs >= 1 && num_regs <= 4);
@@ -3057,7 +3057,9 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
   /* Prepare the index if any.  */
   if (opnd->reglist.has_index)
     /* PR 21096: The %100 is to silence a warning about possible truncation.  */
-    snprintf (tb, 8, "[%" PRIi64 "]", (opnd->reglist.index % 100));
+    snprintf (tb, sizeof (tb), "%s[%s%" PRIi64 "%s]",
+	      get_style (dis_style_text), get_style (dis_style_immediate),
+	      (opnd->reglist.index % 100), get_style (dis_style_text));
   else
     tb[0] = '\0';
 
@@ -3065,8 +3067,11 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
      more than two registers in the list, and the register numbers
      are monotonically increasing in increments of one.  */
   if (num_regs > 2 && last_reg > first_reg)
-    snprintf (buf, size, "{%s%d.%s-%s%d.%s}%s", prefix, first_reg, qlf_name,
-	      prefix, last_reg, qlf_name, tb);
+    snprintf (buf, size, "%s{%s%s%d.%s%s-%s%s%d.%s%s}%s",
+	      get_style (dis_style_text), get_style (dis_style_register),
+	      prefix, first_reg, qlf_name, get_style (dis_style_text),
+	      get_style (dis_style_register), prefix, last_reg, qlf_name,
+	      get_style (dis_style_text), tb);
   else
     {
       const int reg0 = first_reg;
@@ -3077,21 +3082,40 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
       switch (num_regs)
 	{
 	case 1:
-	  snprintf (buf, size, "{%s%d.%s}%s", prefix, reg0, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	case 2:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s}%s", prefix, reg0, qlf_name,
-		    prefix, reg1, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg1, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	case 3:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg1, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg2, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	case 4:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, prefix, reg3, qlf_name, tb);
+	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s}%s",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg0, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg1, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg2, qlf_name,
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), prefix, reg3, qlf_name,
+		    get_style (dis_style_text), tb);
 	  break;
 	}
     }
@@ -3103,32 +3127,53 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
 static void
 print_immediate_offset_address (char *buf, size_t size,
 				const aarch64_opnd_info *opnd,
-				const char *base)
+				const char *base, get_style_func get_style)
 {
   if (opnd->addr.writeback)
     {
       if (opnd->addr.preind)
         {
 	  if (opnd->type == AARCH64_OPND_ADDR_SIMM10 && !opnd->addr.offset.imm)
-            snprintf (buf, size, "[%s]!", base);
+	    snprintf (buf, size, "%s[%s%s%s]!",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), base,
+		      get_style (dis_style_text));
           else
-	    snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
+	    snprintf (buf, size, "%s[%s%s%s, %s#%d%s]!",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), base,
+		      get_style (dis_style_text),
+		      get_style (dis_style_immediate), opnd->addr.offset.imm,
+		      get_style (dis_style_text));
         }
       else
-	snprintf (buf, size, "[%s], #%d", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "%s[%s%s%s], %s#%d",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  base, get_style (dis_style_text),
+		  get_style (dis_style_immediate), opnd->addr.offset.imm);
     }
   else
     {
       if (opnd->shifter.operator_present)
 	{
 	  assert (opnd->shifter.kind == AARCH64_MOD_MUL_VL);
-	  snprintf (buf, size, "[%s, #%d, mul vl]",
-		    base, opnd->addr.offset.imm);
+	  snprintf (buf, size, "%s[%s%s%s, %s#%d%s, mul vl]",
+		    get_style (dis_style_text),
+		    get_style (dis_style_register), base,
+		    get_style (dis_style_text),
+		    get_style (dis_style_immediate), opnd->addr.offset.imm,
+		    get_style (dis_style_text));
 	}
       else if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "%s[%s%s%s, %s#%d%s]",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  base, get_style (dis_style_text),
+		  get_style (dis_style_immediate), opnd->addr.offset.imm,
+		  get_style (dis_style_text));
       else
-	snprintf (buf, size, "[%s]", base);
+	snprintf (buf, size, "%s[%s%s%s]", get_style (dis_style_text),
+		  get_style (dis_style_register), base,
+		  get_style (dis_style_text));
     }
 }
 
@@ -3138,9 +3183,10 @@ print_immediate_offset_address (char *buf, size_t size,
 static void
 print_register_offset_address (char *buf, size_t size,
 			       const aarch64_opnd_info *opnd,
-			       const char *base, const char *offset)
+			       const char *base, const char *offset,
+			       get_style_func get_style)
 {
-  char tb[16];			/* Temporary buffer.  */
+  char tb[32];			/* Temporary buffer.  */
   bool print_extend_p = true;
   bool print_amount_p = true;
   const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
@@ -3161,16 +3207,23 @@ print_register_offset_address (char *buf, size_t size,
   if (print_extend_p)
     {
       if (print_amount_p)
-	snprintf (tb, sizeof (tb), ", %s #%" PRIi64, shift_name,
+	snprintf (tb, sizeof (tb), ", %s%s %s#%" PRIi64,
+		  get_style (dis_style_sub_mnemonic),
+		  shift_name,
+		  get_style (dis_style_immediate),
   /* PR 21096: The %100 is to silence a warning about possible truncation.  */
 		  (opnd->shifter.amount % 100));
       else
-	snprintf (tb, sizeof (tb), ", %s", shift_name);
+	snprintf (tb, sizeof (tb), ", %s%s",
+		  get_style (dis_style_sub_mnemonic), shift_name);
     }
   else
     tb[0] = '\0';
 
-  snprintf (buf, size, "[%s, %s%s]", base, offset, tb);
+  snprintf (buf, size, "%s[%s%s%s, %s%s%s%s]",
+	    get_style (dis_style_text), get_style (dis_style_register),
+	    base, get_style (dis_style_text), get_style (dis_style_register),
+	    offset, get_style (dis_style_text), tb);
 }
 
 /* Print ZA tiles from imm8 in ZERO instruction.
@@ -3230,7 +3283,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 		       const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
 		       bfd_vma *address, char** notes,
 		       char *comment, size_t comment_size,
-		       aarch64_feature_set features)
+		       aarch64_feature_set features,
+		       get_style_func get_style)
 {
   unsigned int i, num_conds;
   const char *name = NULL;
@@ -3278,7 +3332,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	break;
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
-      snprintf (buf, size, "%s",
+      snprintf (buf, size, "%s%s",
+		get_style (dis_style_register),
 		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
       break;
 
@@ -3291,7 +3346,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      || opnd->qualifier == AARCH64_OPND_QLF_WSP
 	      || opnd->qualifier == AARCH64_OPND_QLF_X
 	      || opnd->qualifier == AARCH64_OPND_QLF_SP);
-      snprintf (buf, size, "%s",
+      snprintf (buf, size, "%s%s",
+		get_style (dis_style_register),
 		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 1));
       break;
 
@@ -3311,19 +3367,26 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	  if (opnd->shifter.amount == 0)
 	    {
 	      /* Shifter omitted.  */
-	      snprintf (buf, size, "%s",
+	      snprintf (buf, size, "%s%s",
+			get_style (dis_style_register),
 			get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
 	      break;
 	    }
 	}
       if (opnd->shifter.amount)
-	snprintf (buf, size, "%s, %s #%" PRIi64,
+	snprintf (buf, size, "%s%s%s, %s%s %s#%" PRIi64,
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+		  get_style (dis_style_text),
+		  get_style (dis_style_sub_mnemonic),
 		  aarch64_operand_modifiers[kind].name,
-		  opnd->shifter.amount);
+		  get_style (dis_style_immediate), opnd->shifter.amount);
       else
-	snprintf (buf, size, "%s, %s",
+	snprintf (buf, size, "%s%s%s, %s%s",
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+		  get_style (dis_style_text),
+		  get_style (dis_style_sub_mnemonic),
 		  aarch64_operand_modifiers[kind].name);
       break;
 
@@ -3331,13 +3394,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
       if (opnd->shifter.amount == 0 && opnd->shifter.kind == AARCH64_MOD_LSL)
-	snprintf (buf, size, "%s",
+	snprintf (buf, size, "%s%s",
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
       else
-	snprintf (buf, size, "%s, %s #%" PRIi64,
+	snprintf (buf, size, "%s%s%s, %s%s %s#%" PRIi64,
+		  get_style (dis_style_register),
 		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
+		  get_style (dis_style_text),
+		  get_style (dis_style_sub_mnemonic),
 		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+		  get_style (dis_style_immediate), opnd->shifter.amount);
       break;
 
     case AARCH64_OPND_Fd:
@@ -3353,7 +3420,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Vd:
     case AARCH64_OPND_SVE_Vm:
     case AARCH64_OPND_SVE_Vn:
-      snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
+      snprintf (buf, size, "%s%s%d",
+		get_style (dis_style_register),
+		aarch64_get_qualifier_name (opnd->qualifier),
 		opnd->reg.regno);
       break;
 
@@ -3361,7 +3430,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Vd:
     case AARCH64_OPND_Vn:
     case AARCH64_OPND_Vm:
-      snprintf (buf, size, "v%d.%s", opnd->reg.regno,
+      snprintf (buf, size, "%sv%d.%s",
+		get_style (dis_style_register), opnd->reg.regno,
 		aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
@@ -3370,21 +3440,26 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Em:
     case AARCH64_OPND_Em16:
     case AARCH64_OPND_SM3_IMM2:
-      snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
+      snprintf (buf, size, "%sv%d.%s%s[%s%" PRIi64 "%s]",
+		get_style (dis_style_register), opnd->reglane.regno,
 		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+		get_style (dis_style_text), get_style (dis_style_immediate),
+		opnd->reglane.index, get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_VdD1:
     case AARCH64_OPND_VnD1:
-      snprintf (buf, size, "v%d.d[1]", opnd->reg.regno);
+      snprintf (buf, size, "%sv%d.d%s[%s1%s]",
+		get_style (dis_style_register), opnd->reg.regno,
+		get_style (dis_style_text), get_style (dis_style_immediate),
+		get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_LVn:
     case AARCH64_OPND_LVt:
     case AARCH64_OPND_LVt_AL:
     case AARCH64_OPND_LEt:
-      print_register_list (buf, size, opnd, "v");
+      print_register_list (buf, size, opnd, "v", get_style);
       break;
 
     case AARCH64_OPND_SVE_Pd:
@@ -3397,13 +3472,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Pt:
     case AARCH64_OPND_SME_Pm:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "p%d", opnd->reg.regno);
+	snprintf (buf, size, "%sp%d", get_style (dis_style_register),
+		  opnd->reg.regno);
       else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
 	       || opnd->qualifier == AARCH64_OPND_QLF_P_M)
-	snprintf (buf, size, "p%d/%s", opnd->reg.regno,
+	snprintf (buf, size, "%sp%d/%s", get_style (dis_style_register),
+		  opnd->reg.regno,
 		  aarch64_get_qualifier_name (opnd->qualifier));
       else
-	snprintf (buf, size, "p%d.%s", opnd->reg.regno,
+	snprintf (buf, size, "%sp%d.%s", get_style (dis_style_register),
+		  opnd->reg.regno,
 		  aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
@@ -3415,15 +3493,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zn:
     case AARCH64_OPND_SVE_Zt:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "z%d", opnd->reg.regno);
+	snprintf (buf, size, "%sz%d", get_style (dis_style_register),
+		  opnd->reg.regno);
       else
-	snprintf (buf, size, "z%d.%s", opnd->reg.regno,
+	snprintf (buf, size, "%sz%d.%s", get_style (dis_style_register),
+		  opnd->reg.regno,
 		  aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
     case AARCH64_OPND_SVE_ZnxN:
     case AARCH64_OPND_SVE_ZtxN:
-      print_register_list (buf, size, opnd, "z");
+      print_register_list (buf, size, opnd, "z", get_style);
       break;
 
     case AARCH64_OPND_SVE_Zm3_INDEX:
@@ -3432,14 +3512,18 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zm4_11_INDEX:
     case AARCH64_OPND_SVE_Zm4_INDEX:
     case AARCH64_OPND_SVE_Zn_INDEX:
-      snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
+      snprintf (buf, size, "%sz%d.%s%s[%s%" PRIi64 "%s]",
+		get_style (dis_style_register), opnd->reglane.regno,
 		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+		get_style (dis_style_text),
+		get_style (dis_style_immediate), opnd->reglane.index,
+		get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_SME_ZAda_2b:
     case AARCH64_OPND_SME_ZAda_3b:
-      snprintf (buf, size, "za%d.%s", opnd->reg.regno,
+      snprintf (buf, size, "%sza%d.%s", get_style (dis_style_register),
+		opnd->reg.regno,
                 aarch64_get_qualifier_name (opnd->qualifier));
       break;
 
@@ -3467,7 +3551,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_SME_SM_ZA:
-      snprintf (buf, size, "%s", opnd->reg.regno == 's' ? "sm" : "za");
+      snprintf (buf, size, "%s%s",
+		get_style (dis_style_register),
+		opnd->reg.regno == 's' ? "sm" : "za");
       break;
 
     case AARCH64_OPND_SME_PnT_Wm_imm:
@@ -3480,7 +3566,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 
     case AARCH64_OPND_CRn:
     case AARCH64_OPND_CRm:
-      snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, "%sC%" PRIi64, get_style (dis_style_register),
+		opnd->imm.value);
       break;
 
     case AARCH64_OPND_IDX:
@@ -3521,7 +3608,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_IMM_ROT1:
     case AARCH64_OPND_SVE_IMM_ROT2:
     case AARCH64_OPND_SVE_IMM_ROT3:
-      snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		opnd->imm.value);
       break;
 
     case AARCH64_OPND_SVE_I1_HALF_ONE:
@@ -3530,7 +3618,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       {
 	single_conv_t c;
 	c.i = opnd->imm.value;
-	snprintf (buf, size, "#%.1f", c.f);
+	snprintf (buf, size, "%s#%.1f", get_style (dis_style_immediate), c.f);
 	break;
       }
 
@@ -3541,9 +3629,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[enum_value]);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		  aarch64_sve_pattern_array[enum_value]);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       break;
 
     case AARCH64_OPND_SVE_PATTERN_SCALED:
@@ -3554,13 +3644,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[opnd->imm.value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[opnd->imm.value]);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		  aarch64_sve_pattern_array[opnd->imm.value]);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       if (opnd->shifter.operator_present)
 	{
 	  size_t len = strlen (buf);
-	  snprintf (buf + len, size - len, ", %s #%" PRIi64,
+	  snprintf (buf + len, size - len, ", %s%s #%" PRIi64,
+		    get_style (dis_style_sub_mnemonic),
 		    aarch64_operand_modifiers[opnd->shifter.kind].name,
 		    opnd->shifter.amount);
 	}
@@ -3570,9 +3663,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
       if (aarch64_sve_prfop_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_prfop_array[enum_value]);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		  aarch64_sve_prfop_array[enum_value]);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       break;
 
     case AARCH64_OPND_IMM_MOV:
@@ -3581,12 +3676,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	case 4:	/* e.g. MOV Wd, #<imm32>.  */
 	    {
 	      int imm32 = opnd->imm.value;
-	      snprintf (buf, size, "#0x%-20x", imm32);
+	      snprintf (buf, size, "%s#0x%-20x",
+			get_style (dis_style_immediate), imm32);
 	      snprintf (comment, comment_size, "#%d", imm32);
 	    }
 	  break;
 	case 8:	/* e.g. MOV Xd, #<imm64>.  */
-	  snprintf (buf, size, "#0x%-20" PRIx64, opnd->imm.value);
+	  snprintf (buf, size, "%s#0x%-20" PRIx64,
+		    get_style (dis_style_immediate), opnd->imm.value);
 	  snprintf (comment, comment_size, "#%" PRIi64, opnd->imm.value);
 	  break;
 	default:
@@ -3596,7 +3693,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_FPIMM0:
-      snprintf (buf, size, "#0.0");
+      snprintf (buf, size, "%s#0.0", get_style (dis_style_immediate));
       break;
 
     case AARCH64_OPND_LIMM:
@@ -3606,30 +3703,42 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_LIMM:
     case AARCH64_OPND_SVE_LIMM_MOV:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
+	snprintf (buf, size, "%s#0x%" PRIx64 "%s, %slsl %s#%" PRIi64,
+		  get_style (dis_style_immediate), opnd->imm.value,
+		  get_style (dis_style_text),
+		  get_style (dis_style_sub_mnemonic),
+		  get_style (dis_style_immediate),
 		  opnd->shifter.amount);
       else
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size, "%s#0x%" PRIx64,
+		  get_style (dis_style_immediate), opnd->imm.value);
       break;
 
     case AARCH64_OPND_SIMD_IMM:
     case AARCH64_OPND_SIMD_IMM_SFT:
       if ((! opnd->shifter.amount && opnd->shifter.kind == AARCH64_MOD_LSL)
 	  || opnd->shifter.kind == AARCH64_MOD_NONE)
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size, "%s#0x%" PRIx64,
+		  get_style (dis_style_immediate), opnd->imm.value);
       else
-	snprintf (buf, size, "#0x%" PRIx64 ", %s #%" PRIi64, opnd->imm.value,
+	snprintf (buf, size, "%s#0x%" PRIx64 "%s, %s%s %s#%" PRIi64,
+		  get_style (dis_style_immediate), opnd->imm.value,
+		  get_style (dis_style_text),
+		  get_style (dis_style_sub_mnemonic),
 		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+		  get_style (dis_style_immediate), opnd->shifter.amount);
       break;
 
     case AARCH64_OPND_SVE_AIMM:
     case AARCH64_OPND_SVE_ASIMM:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
+	snprintf (buf, size, "%s#%" PRIi64 "%s, lsl %s#%" PRIi64,
+		  get_style (dis_style_immediate), opnd->imm.value,
+		  get_style (dis_style_text), get_style (dis_style_immediate),
 		  opnd->shifter.amount);
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
+		  opnd->imm.value);
       break;
 
     case AARCH64_OPND_FPIMM:
@@ -3641,21 +3750,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	    {
 	      half_conv_t c;
 	      c.i = expand_fp_imm (2, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size,  "%s#%.18e",
+			get_style (dis_style_immediate), c.f);
 	    }
 	  break;
 	case 4:	/* e.g. FMOV <Vd>.4S, #<imm>.  */
 	    {
 	      single_conv_t c;
 	      c.i = expand_fp_imm (4, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size,  "%s#%.18e",
+			get_style (dis_style_immediate), c.f);
 	    }
 	  break;
 	case 8:	/* e.g. FMOV <Sd>, #<imm>.  */
 	    {
 	      double_conv_t c;
 	      c.i = expand_fp_imm (8, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.d);
+	      snprintf (buf, size,  "%s#%.18e",
+			get_style (dis_style_immediate), c.d);
 	    }
 	  break;
 	default:
@@ -3676,12 +3788,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      (int64_t) get_optional_operand_default_value (opcode)))
 	/* Omit the operand, e.g. DCPS1.  */
 	break;
-      snprintf (buf, size, "#0x%x", (unsigned int)opnd->imm.value);
+      snprintf (buf, size, "%s#0x%x", get_style (dis_style_immediate),
+		(unsigned int)opnd->imm.value);
       break;
 
     case AARCH64_OPND_COND:
     case AARCH64_OPND_COND1:
-      snprintf (buf, size, "%s", opnd->cond->names[0]);
+      snprintf (buf, size, "%s%s", get_style (dis_style_sub_mnemonic),
+		opnd->cond->names[0]);
       num_conds = ARRAY_SIZE (opnd->cond->names);
       for (i = 1; i < num_conds && opnd->cond->names[i]; ++i)
 	{
@@ -3706,7 +3820,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, "%s#0x%" PRIx64,
+		get_style (dis_style_address), addr);
       break;
 
     case AARCH64_OPND_ADDR_PCREL14:
@@ -3722,7 +3837,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, "%s#0x%" PRIx64, get_style (dis_style_address),
+		addr);
       break;
 
     case AARCH64_OPND_ADDR_SIMPLE:
@@ -3732,12 +3848,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (opnd->type == AARCH64_OPND_SIMD_ADDR_POST)
 	{
 	  if (opnd->addr.offset.is_reg)
-	    snprintf (buf, size, "[%s], x%d", name, opnd->addr.offset.regno);
+	    snprintf (buf, size, "%s[%s%s%s], %sx%d",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), name,
+		      get_style (dis_style_text),
+		      get_style (dis_style_register),
+		      opnd->addr.offset.regno);
 	  else
-	    snprintf (buf, size, "[%s], #%d", name, opnd->addr.offset.imm);
+	    snprintf (buf, size, "%s[%s%s%s], %s#%d",
+		      get_style (dis_style_text),
+		      get_style (dis_style_register), name,
+		      get_style (dis_style_text),
+		      get_style (dis_style_immediate),
+		      opnd->addr.offset.imm);
 	}
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "%s[%s%s%s]",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  name, get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
@@ -3753,14 +3881,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RX_LSL3:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_offset_int_reg_name (opnd));
+	 get_offset_int_reg_name (opnd), get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZX:
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0));
+	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0), get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_RZ:
@@ -3777,7 +3905,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 get_style);
       break;
 
     case AARCH64_OPND_ADDR_SIMM7:
@@ -3801,7 +3930,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RI_U6x4:
     case AARCH64_OPND_SVE_ADDR_RI_U6x8:
       print_immediate_offset_address
-	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1));
+	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
+	 get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZI_U5:
@@ -3810,7 +3940,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
       print_immediate_offset_address
 	(buf, size, opnd,
-	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
+	 get_style);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
@@ -3819,15 +3950,22 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 get_style);
       break;
 
     case AARCH64_OPND_ADDR_UIMM12:
       name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
       if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", name, opnd->addr.offset.imm);
+	snprintf (buf, size, "%s[%s%s%s, %s#%d%s]",
+		  get_style (dis_style_text), get_style (dis_style_register),
+		  name, get_style (dis_style_text),
+		  get_style (dis_style_immediate), opnd->addr.offset.imm,
+		  get_style (dis_style_text));
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "%s[%s%s%s]", get_style (dis_style_text),
+		  get_style (dis_style_register), name,
+		  get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_SYSREG:
@@ -3866,14 +4004,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	}
 
       if (name)
-	snprintf (buf, size, "%s", name);
+	snprintf (buf, size, "%s%s", get_style (dis_style_register), name);
       else
 	{
 	  /* Implementation defined system register.  */
 	  unsigned int value = opnd->sysreg.value;
-	  snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
-		    (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
-		    value & 0x7);
+	  snprintf (buf, size, "%ss%u_%u_c%u_c%u_%u",
+		    get_style (dis_style_register), (value >> 14) & 0x3,
+		    (value >> 11) & 0x7, (value >> 7) & 0xf,
+		    (value >> 3) & 0xf, value & 0x7);
 	}
       break;
 
@@ -3899,12 +4038,21 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SYSREG_IC:
     case AARCH64_OPND_SYSREG_TLBI:
     case AARCH64_OPND_SYSREG_SR:
-      snprintf (buf, size, "%s", opnd->sysins_op->name);
+      snprintf (buf, size, "%s%s", get_style (dis_style_register),
+		opnd->sysins_op->name);
       break;
 
     case AARCH64_OPND_BARRIER:
     case AARCH64_OPND_BARRIER_DSB_NXS:
-      snprintf (buf, size, "%s", opnd->barrier->name);
+      {
+	enum disassembler_style style;
+	if (opnd->barrier->name[0] == '#')
+	  style = dis_style_immediate;
+	else
+	  style = dis_style_sub_mnemonic;
+	snprintf (buf, size, "%s%s", get_style (style),
+		  opnd->barrier->name);
+      }
       break;
 
     case AARCH64_OPND_BARRIER_ISB:
@@ -3912,38 +4060,46 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (! optional_operand_p (opcode, idx)
 	  || (opnd->barrier->value
 	      != get_optional_operand_default_value (opcode)))
-	snprintf (buf, size, "#0x%x", opnd->barrier->value);
+	snprintf (buf, size, "%s#0x%x", get_style (dis_style_immediate),
+		  opnd->barrier->value);
       break;
 
     case AARCH64_OPND_PRFOP:
       if (opnd->prfop->name != NULL)
-	snprintf (buf, size, "%s", opnd->prfop->name);
+	snprintf (buf, size, "%s%s", get_style (dis_style_sub_mnemonic),
+		  opnd->prfop->name);
       else
-	snprintf (buf, size, "#0x%02x", opnd->prfop->value);
+	snprintf (buf, size, "%s#0x%02x", get_style (dis_style_immediate),
+		  opnd->prfop->value);
       break;
 
     case AARCH64_OPND_BARRIER_PSB:
-      snprintf (buf, size, "csync");
+      snprintf (buf, size, "%scsync", get_style (dis_style_sub_mnemonic));
       break;
 
     case AARCH64_OPND_BTI_TARGET:
       if ((HINT_FLAG (opnd->hint_option->value) & HINT_OPD_F_NOPRINT) == 0)
-	snprintf (buf, size, "%s", opnd->hint_option->name);
+	snprintf (buf, size, "%s%s", get_style (dis_style_sub_mnemonic),
+		  opnd->hint_option->name);
       break;
 
     case AARCH64_OPND_MOPS_ADDR_Rd:
     case AARCH64_OPND_MOPS_ADDR_Rs:
-      snprintf (buf, size, "[%s]!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+      snprintf (buf, size, "%s[%s%s%s]!",
+		get_style (dis_style_text), get_style (dis_style_register),
+		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0),
+		get_style (dis_style_text));
       break;
 
     case AARCH64_OPND_MOPS_WB_Rn:
-      snprintf (buf, size, "%s!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+      snprintf (buf, size, "%s%s%s!",
+		get_style (dis_style_register),
+		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0),
+		get_style (dis_style_text));
       break;
 
     default:
-      snprintf (buf, size, "<invalid>");
+      snprintf (buf, size, "%s<invalid>", get_style (dis_style_text));
       break;
     }
 }


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCHv2 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-07-05 12:51     ` Andrew Burgess
@ 2022-07-05 13:10       ` Richard Earnshaw
  2022-07-07 10:23         ` [PATCHv3 0/2] AArch64 libopcodes styling Andrew Burgess
  0 siblings, 1 reply; 31+ messages in thread
From: Richard Earnshaw @ 2022-07-05 13:10 UTC (permalink / raw)
  To: Andrew Burgess, Andrew Burgess via Binutils

I think my biggest criticism of this approach is the need to rewrite all 
the template strings, eg:

-    snprintf (buf, size, "{%s%d.%s-%s%d.%s}%s", prefix, first_reg, 
qlf_name,
-	      prefix, last_reg, qlf_name, tb);
+    snprintf (buf, size, "%s{%s%s%d.%s%s-%s%s%d.%s%s}%s", ...

It would all be so much cleaner if we could write something more like


   snprintf (buf, size, "{%s-%s}%s",
             format_reg (prefix, first_reg, qlf_name),
             format_reg (prefix, last_reg, qlf_name), ...

I guess the difficultly here would be creating a lot of garbage strings 
that would then need to be garbage-collected later on, but still...

Who said obstacks?

R.

On 05/07/2022 13:51, Andrew Burgess via Binutils wrote:
> 
> Apologies, I left some debug code in this latest version of the
> patch.  Here's an update with the debug code removed.
> 
> Thanks,
> Andrew
> 
> ---
> 
> commit 69a681f8747a145dcaba969ae8972a20d1176a05
> Author: Andrew Burgess <aburgess@redhat.com>
> Date:   Thu Apr 28 13:31:07 2022 +0100
> 
>      libopcodes/aarch64: add support for disassembler styling
>      
>      This commit enables disassembler styling for AArch64.  After this
>      commit it is possible to have objdump style AArch64 disassembler
>      output (using --disassembler-color option).  Once the required GDB
>      patches are merged, GDB will also style the disassembler output.
>      
>      The changes to support styling are mostly split between two files
>      opcodes/aarch64-dis.c and opcodes/aarch64-opc.c.
>      
>      The entry point for the AArch64 disassembler can be found in
>      aarch64-dis.c, this file handles printing the instruction mnemonics,
>      and assembler directives (e.g. '.byte', '.word', etc).  Some operands,
>      mostly relating to assembler directives are also printed from this
>      file.  This commit changes all of this to pass through suitable
>      styling information.
>      
>      However, for most "normal" instructions, the instruction operands are
>      printed using a two step process.  From aarch64-dis.c, in the
>      print_operands function, the function aarch64_print_operand is called,
>      this function is in aarch64-opc.c, and converts an instruction operand
>      into a string.  Then, back in print_operands (aarch64-dis.c), the
>      operand string is printed.
>      
>      Unfortunately, the string returned by aarch64_print_operand can be
>      quite complex, it will include syntax elements, like '[' and ']', in
>      addition to register names and immediate values.  In some cases, a
>      single operand will expand into what will appear (to the user) as
>      multiple operands separated with a ','.
>      
>      This makes the task of styling more complex, all these different
>      components need to by styled differently, so we need to get the
>      styling information out of aarch64_print_operand in some way.
>      
>      The solution that I propose here is similar to the solution that I
>      used for the i386 disassembler.
>      
>      Currently, aarch64_print_operand uses snprintf to write the operand
>      text into a buffer provided by the caller.
>      
>      What I propose is that we pass an extra argument to the
>      aarch64_print_operand function, this argument will be a callback
>      function that converts a disassembler style into a string.  These
>      strings can then be written into the buffer using snprintf.  Here's an
>      example, 'get_style' is the new callback function:
>      
>          snprintf (buf, size, "%s%s",
>                    get_style (dis_style_register),
>                    get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
>      
>      The string returned by 'get_style' is a special sequence of characters
>      that is not otherwise seen in the disassembler output.  In the
>      print_operands function we can now scan the buffer returned by
>      aarch64_print_operand, and split the text based on the style
>      markers.  Each separately styled block is then printed with the
>      correct style.
>      
>      The aarch64_print_operand function is also called from the assembler
>      to aid in printing diagnostic messages.  Right now I have no plans to
>      add styling to the assembler output, and so, in this case, the
>      'get_style' callback is a dummy function that always returns an empty
>      string.  As a result, when the assembler calls aarch64_print_operand,
>      the string returns can be immediately printed with no special style
>      handling required.
>      
>      I've gone through and updated arch64-opc.c as best I can to add
>      styling information.  I've mostly used the gas/testsuite/gas/aarch64
>      tests to check the styling, assembling then disassembling each source
>      file, then checking that the output looks reasonable.
>      
>      With objdump disassembler color turned off, there should be no change
>      in the output after this commit.
> 
> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index 779db31828b..740bde53ea8 100644
> --- a/gas/config/tc-aarch64.c
> +++ b/gas/config/tc-aarch64.c
> @@ -5347,6 +5347,15 @@ assign_qualifier_sequence (aarch64_inst *instr,
>       instr->operands[i].qualifier = *qualifiers;
>   }
>   
> +/* Return a string indicating a switch to STYLE.  As the assembler doesn't
> +   use styling in its output, this always returns an empty string.  */
> +
> +static const char *
> +get_style_text (enum disassembler_style style ATTRIBUTE_UNUSED)
> +{
> +  return "";
> +}
> +
>   /* Print operands for the diagnosis purpose.  */
>   
>   static void
> @@ -5371,7 +5380,7 @@ print_operands (char *buf, const aarch64_opcode *opcode,
>   
>         /* Generate the operand string in STR.  */
>         aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL,
> -			     NULL, cmt, sizeof (cmt), cpu_variant);
> +			     NULL, cmt, sizeof (cmt), cpu_variant, get_style_text);
>   
>         /* Delimiter.  */
>         if (str[0] != '\0')
> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
> index 186ba9a4800..373deb6b49c 100644
> --- a/include/opcode/aarch64.h
> +++ b/include/opcode/aarch64.h
> @@ -27,6 +27,8 @@
>   #include <assert.h>
>   #include <stdlib.h>
>   
> +#include "dis-asm.h"
> +
>   #ifdef __cplusplus
>   extern "C" {
>   #endif
> @@ -1367,12 +1369,16 @@ aarch64_replace_opcode (struct aarch64_inst *,
>   extern const aarch64_opcode *
>   aarch64_get_opcode (enum aarch64_op);
>   
> +/* Return a text string that indicates a change of disassembler style.  */
> +typedef const char *(*get_style_func) (enum disassembler_style);
> +
>   /* Generate the string representation of an operand.  */
>   extern void
>   aarch64_print_operand (char *, size_t, bfd_vma, const aarch64_opcode *,
>   		       const aarch64_opnd_info *, int, int *, bfd_vma *,
>   		       char **, char *, size_t,
> -		       aarch64_feature_set features);
> +		       aarch64_feature_set features,
> +		       get_style_func get_style);
>   
>   /* Miscellaneous interface.  */
>   
> diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
> index acaad28fdff..fbbd0c5e087 100644
> --- a/opcodes/aarch64-dis.c
> +++ b/opcodes/aarch64-dis.c
> @@ -25,9 +25,14 @@
>   #include "opintl.h"
>   #include "aarch64-dis.h"
>   #include "elf-bfd.h"
> +#include "safe-ctype.h"
>   
>   #define INSNLEN 4
>   
> +/* This character is used to encode style information within the output
> +   buffers.  See get_style_text and print_operands for more details.  */
> +#define STYLE_MARKER_CHAR '\002'
> +
>   /* Cached mapping symbol state.  */
>   enum map_type
>   {
> @@ -3275,6 +3280,45 @@ aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst,
>     return ERR_UND;
>   }
>   
> +/* When the aarch64_print_operand code is building the string to represent
> +   an operand, this function is called each time we need to change style,
> +   with STYLE being the new style.  The string returned from this function
> +   will then be embedded in to the operand buffer.
> +
> +   When we finally print the operand buffer in print_operands, we find
> +   these style markers and split the operand text into chunks, where each
> +   chunk is a series of characters with the same style.  */
> +
> +static const char *
> +get_style_text (enum disassembler_style style)
> +{
> +  static bool init = false;
> +  static char formats[16][4];
> +  unsigned num;
> +
> +  /* First time through we build a string for every possible format.  This
> +     code relies on there being no more than 16 different styles (there's
> +     an assert below for this).  */
> +  if (!init)
> +    {
> +      int i;
> +
> +      for (i = 0; i <= 0xf; ++i)
> +	{
> +	  int res = snprintf (&formats[i][0], sizeof (formats[i]), "%c%x%c",
> +			      STYLE_MARKER_CHAR, i, STYLE_MARKER_CHAR);
> +	  assert (res == 3);
> +	}
> +
> +      init = true;
> +    }
> +
> +  /* Return the string that marks switching to STYLE.  */
> +  num = (unsigned) style;
> +  assert (style <= 0xf);
> +  return formats[num];
> +}
> +
>   /* Print operands.  */
>   
>   static void
> @@ -3301,32 +3345,91 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
>         /* Generate the operand string in STR.  */
>         aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
>   			     &info->target, &notes, cmt, sizeof (cmt),
> -			     arch_variant);
> +			     arch_variant, get_style_text);
>   
>         /* Print the delimiter (taking account of omitted operand(s)).  */
>         if (str[0] != '\0')
> -	(*info->fprintf_func) (info->stream, "%s",
> -			       num_printed++ == 0 ? "\t" : ", ");
> +	(*info->fprintf_styled_func) (info->stream, dis_style_text, "%s",
> +				      num_printed++ == 0 ? "\t" : ", ");
>   
>         /* Print the operand.  */
>         if (pcrel_p)
>   	(*info->print_address_func) (info->target, info);
>         else
>   	{
> -	  (*info->fprintf_func) (info->stream, "%s", str);
> -
> -	  /* Print the comment.  This works because only the last operand
> -	     ever adds a comment.  If that ever changes then we'll need to
> -	     be smarter here.  */
> -	  if (cmt[0] != '\0')
> -	    (*info->fprintf_func) (info->stream, "\t// %s", cmt);
> +	  /* This operand came from aarch64_print_operand, and will include
> +	     embedded strings indicating which style each character should
> +	     have.  In the following code we split the text based on
> +	     CURR_STYLE, and call the styled print callback to print each
> +	     block of text in the appropriate style.  */
> +	  char *start, *curr;
> +	  enum disassembler_style curr_style = dis_style_text;
> +
> +	  start = curr = str;
> +	  do
> +	    {
> +	      if (*curr == '\0'
> +		  || (*curr == STYLE_MARKER_CHAR
> +		      && ISXDIGIT (*(curr + 1))
> +		      && *(curr + 2) == STYLE_MARKER_CHAR))
> +		{
> +		  /* Output content between our START position and CURR.  */
> +		  int len = curr - start;
> +		  int n = (*info->fprintf_styled_func) (info->stream,
> +							curr_style,
> +							"%.*s", len, start);
> +		  if (n < 0)
> +		    break;
> +
> +		  if (*curr == '\0')
> +		    break;
> +
> +		  /* Skip over the initial STYLE_MARKER_CHAR.  */
> +		  ++curr;
> +
> +		  /* Update the CURR_STYLE.  As there are less than 16
> +		     styles, it is possible, that if the input is corrupted
> +		     in some way, that we might set CURR_STYLE to an
> +		     invalid value.  Don't worry though, we check for this
> +		     situation.  */
> +		  if (*curr >= '0' && *curr <= '9')
> +		    curr_style = (enum disassembler_style) (*curr - '0');
> +		  else if (*curr >= 'a' && *curr <= 'f')
> +		    curr_style = (enum disassembler_style) (*curr - 'a' + 10);
> +		  else
> +		    curr_style = dis_style_text;
> +
> +		  /* Check for an invalid style having been selected.  This
> +		     should never happen, but it doesn't hurt to be a
> +		     little paranoid.  */
> +		  if (curr_style > dis_style_comment_start)
> +		    curr_style = dis_style_text;
> +
> +		  /* Skip the hex character, and the closing STYLE_MARKER_CHAR.  */
> +		  curr += 2;
> +
> +		  /* Reset the START to after the style marker.  */
> +		  start = curr;
> +		}
> +	      else
> +		++curr;
> +	    }
> +	  while (true);
>   	}
> +
> +      /* Print the comment.  This works because only the last operand ever
> +	 adds a comment.  If that ever changes then we'll need to be
> +	 smarter here.  */
> +      if (cmt[0] != '\0')
> +	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
> +				      "\t// %s", cmt);
>       }
>   
>       if (notes && !no_notes)
>         {
>   	*has_notes = true;
> -	(*info->fprintf_func) (info->stream, "  // note: %s", notes);
> +	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
> +				      "  // note: %s", notes);
>         }
>   }
>   
> @@ -3359,10 +3462,12 @@ print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
>         char name[8];
>   
>         remove_dot_suffix (name, inst);
> -      (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
> +      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
> +				    "%s.%s", name, inst->cond->names[0]);
>       }
>     else
> -    (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
> +    (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
> +				  "%s", inst->opcode->name);
>   }
>   
>   /* Decide whether we need to print a comment after the operands of
> @@ -3379,9 +3484,10 @@ print_comment (const aarch64_inst *inst, struct disassemble_info *info)
>         remove_dot_suffix (name, inst);
>         num_conds = ARRAY_SIZE (inst->cond->names);
>         for (i = 1; i < num_conds && inst->cond->names[i]; ++i)
> -	(*info->fprintf_func) (info->stream, "%s %s.%s",
> -			       i == 1 ? "  //" : ",",
> -			       name, inst->cond->names[i]);
> +	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
> +				      "%s %s.%s",
> +				      i == 1 ? "  //" : ",",
> +				      name, inst->cond->names[i]);
>       }
>   }
>   
> @@ -3398,28 +3504,30 @@ print_verifier_notes (aarch64_operand_error *detail,
>        would not have succeeded.  We can safely ignore these.  */
>     assert (detail->non_fatal);
>   
> -  (*info->fprintf_func) (info->stream, "  // note: ");
> +  (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
> +				"  // note: ");
>     switch (detail->kind)
>       {
>       case AARCH64_OPDE_A_SHOULD_FOLLOW_B:
> -      (*info->fprintf_func) (info->stream,
> -			     _("this `%s' should have an immediately"
> -			       " preceding `%s'"),
> -			     detail->data[0].s, detail->data[1].s);
> +      (*info->fprintf_styled_func) (info->stream, dis_style_text,
> +				    _("this `%s' should have an immediately"
> +				      " preceding `%s'"),
> +				    detail->data[0].s, detail->data[1].s);
>         break;
>   
>       case AARCH64_OPDE_EXPECTED_A_AFTER_B:
> -      (*info->fprintf_func) (info->stream,
> -			     _("expected `%s' after previous `%s'"),
> -			     detail->data[0].s, detail->data[1].s);
> +      (*info->fprintf_styled_func) (info->stream, dis_style_text,
> +				    _("expected `%s' after previous `%s'"),
> +				    detail->data[0].s, detail->data[1].s);
>         break;
>   
>       default:
>         assert (detail->error);
> -      (*info->fprintf_func) (info->stream, "%s", detail->error);
> +      (*info->fprintf_styled_func) (info->stream, dis_style_text,
> +				    "%s", detail->error);
>         if (detail->index >= 0)
> -	(*info->fprintf_func) (info->stream, " at operand %d",
> -			       detail->index + 1);
> +	(*info->fprintf_styled_func) (info->stream, dis_style_text,
> +				      " at operand %d", detail->index + 1);
>         break;
>       }
>   }
> @@ -3511,8 +3619,13 @@ print_insn_aarch64_word (bfd_vma pc,
>       case ERR_NYI:
>         /* Handle undefined instructions.  */
>         info->insn_type = dis_noninsn;
> -      (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
> -			     word, err_msg[ret]);
> +      (*info->fprintf_styled_func) (info->stream,
> +				    dis_style_assembler_directive,
> +				    ".inst\t");
> +      (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
> +				    "0x%08x", word);
> +      (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
> +				    " ; %s", err_msg[ret]);
>         break;
>       case ERR_OK:
>         user_friendly_fixup (&inst);
> @@ -3554,13 +3667,22 @@ print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
>     switch (info->bytes_per_chunk)
>       {
>       case 1:
> -      info->fprintf_func (info->stream, ".byte\t0x%02x", word);
> +      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
> +				 ".byte\t");
> +      info->fprintf_styled_func (info->stream, dis_style_immediate,
> +				 "0x%02x", word);
>         break;
>       case 2:
> -      info->fprintf_func (info->stream, ".short\t0x%04x", word);
> +      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
> +				 ".short\t");
> +      info->fprintf_styled_func (info->stream, dis_style_immediate,
> +				 "0x%04x", word);
>         break;
>       case 4:
> -      info->fprintf_func (info->stream, ".word\t0x%08x", word);
> +      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
> +				 ".word\t");
> +      info->fprintf_styled_func (info->stream, dis_style_immediate,
> +				 "0x%08x", word);
>         break;
>       default:
>         abort ();
> diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
> index 1c93f836020..4f38a3328d4 100644
> --- a/opcodes/aarch64-opc.c
> +++ b/opcodes/aarch64-opc.c
> @@ -3043,13 +3043,13 @@ expand_fp_imm (int size, uint32_t imm8)
>      the register name that comes before the register number, such as "v".  */
>   static void
>   print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
> -		     const char *prefix)
> +		     const char *prefix, get_style_func get_style)
>   {
>     const int num_regs = opnd->reglist.num_regs;
>     const int first_reg = opnd->reglist.first_regno;
>     const int last_reg = (first_reg + num_regs - 1) & 0x1f;
>     const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
> -  char tb[8];	/* Temporary buffer.  */
> +  char tb[16];	/* Temporary buffer.  */
>   
>     assert (opnd->type != AARCH64_OPND_LEt || opnd->reglist.has_index);
>     assert (num_regs >= 1 && num_regs <= 4);
> @@ -3057,7 +3057,9 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
>     /* Prepare the index if any.  */
>     if (opnd->reglist.has_index)
>       /* PR 21096: The %100 is to silence a warning about possible truncation.  */
> -    snprintf (tb, 8, "[%" PRIi64 "]", (opnd->reglist.index % 100));
> +    snprintf (tb, sizeof (tb), "%s[%s%" PRIi64 "%s]",
> +	      get_style (dis_style_text), get_style (dis_style_immediate),
> +	      (opnd->reglist.index % 100), get_style (dis_style_text));
>     else
>       tb[0] = '\0';
>   
> @@ -3065,8 +3067,11 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
>        more than two registers in the list, and the register numbers
>        are monotonically increasing in increments of one.  */
>     if (num_regs > 2 && last_reg > first_reg)
> -    snprintf (buf, size, "{%s%d.%s-%s%d.%s}%s", prefix, first_reg, qlf_name,
> -	      prefix, last_reg, qlf_name, tb);
> +    snprintf (buf, size, "%s{%s%s%d.%s%s-%s%s%d.%s%s}%s",
> +	      get_style (dis_style_text), get_style (dis_style_register),
> +	      prefix, first_reg, qlf_name, get_style (dis_style_text),
> +	      get_style (dis_style_register), prefix, last_reg, qlf_name,
> +	      get_style (dis_style_text), tb);
>     else
>       {
>         const int reg0 = first_reg;
> @@ -3077,21 +3082,40 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
>         switch (num_regs)
>   	{
>   	case 1:
> -	  snprintf (buf, size, "{%s%d.%s}%s", prefix, reg0, qlf_name, tb);
> +	  snprintf (buf, size, "%s{%s%s%d.%s%s}%s",
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg0, qlf_name,
> +		    get_style (dis_style_text), tb);
>   	  break;
>   	case 2:
> -	  snprintf (buf, size, "{%s%d.%s, %s%d.%s}%s", prefix, reg0, qlf_name,
> -		    prefix, reg1, qlf_name, tb);
> +	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s}%s",
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg0, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg1, qlf_name,
> +		    get_style (dis_style_text), tb);
>   	  break;
>   	case 3:
> -	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s}%s",
> -		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
> -		    prefix, reg2, qlf_name, tb);
> +	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s}%s",
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg0, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg1, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg2, qlf_name,
> +		    get_style (dis_style_text), tb);
>   	  break;
>   	case 4:
> -	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s, %s%d.%s}%s",
> -		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
> -		    prefix, reg2, qlf_name, prefix, reg3, qlf_name, tb);
> +	  snprintf (buf, size, "%s{%s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s, %s%s%d.%s%s}%s",
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg0, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg1, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg2, qlf_name,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), prefix, reg3, qlf_name,
> +		    get_style (dis_style_text), tb);
>   	  break;
>   	}
>       }
> @@ -3103,32 +3127,53 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
>   static void
>   print_immediate_offset_address (char *buf, size_t size,
>   				const aarch64_opnd_info *opnd,
> -				const char *base)
> +				const char *base, get_style_func get_style)
>   {
>     if (opnd->addr.writeback)
>       {
>         if (opnd->addr.preind)
>           {
>   	  if (opnd->type == AARCH64_OPND_ADDR_SIMM10 && !opnd->addr.offset.imm)
> -            snprintf (buf, size, "[%s]!", base);
> +	    snprintf (buf, size, "%s[%s%s%s]!",
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_register), base,
> +		      get_style (dis_style_text));
>             else
> -	    snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
> +	    snprintf (buf, size, "%s[%s%s%s, %s#%d%s]!",
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_register), base,
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_immediate), opnd->addr.offset.imm,
> +		      get_style (dis_style_text));
>           }
>         else
> -	snprintf (buf, size, "[%s], #%d", base, opnd->addr.offset.imm);
> +	snprintf (buf, size, "%s[%s%s%s], %s#%d",
> +		  get_style (dis_style_text), get_style (dis_style_register),
> +		  base, get_style (dis_style_text),
> +		  get_style (dis_style_immediate), opnd->addr.offset.imm);
>       }
>     else
>       {
>         if (opnd->shifter.operator_present)
>   	{
>   	  assert (opnd->shifter.kind == AARCH64_MOD_MUL_VL);
> -	  snprintf (buf, size, "[%s, #%d, mul vl]",
> -		    base, opnd->addr.offset.imm);
> +	  snprintf (buf, size, "%s[%s%s%s, %s#%d%s, mul vl]",
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_register), base,
> +		    get_style (dis_style_text),
> +		    get_style (dis_style_immediate), opnd->addr.offset.imm,
> +		    get_style (dis_style_text));
>   	}
>         else if (opnd->addr.offset.imm)
> -	snprintf (buf, size, "[%s, #%d]", base, opnd->addr.offset.imm);
> +	snprintf (buf, size, "%s[%s%s%s, %s#%d%s]",
> +		  get_style (dis_style_text), get_style (dis_style_register),
> +		  base, get_style (dis_style_text),
> +		  get_style (dis_style_immediate), opnd->addr.offset.imm,
> +		  get_style (dis_style_text));
>         else
> -	snprintf (buf, size, "[%s]", base);
> +	snprintf (buf, size, "%s[%s%s%s]", get_style (dis_style_text),
> +		  get_style (dis_style_register), base,
> +		  get_style (dis_style_text));
>       }
>   }
>   
> @@ -3138,9 +3183,10 @@ print_immediate_offset_address (char *buf, size_t size,
>   static void
>   print_register_offset_address (char *buf, size_t size,
>   			       const aarch64_opnd_info *opnd,
> -			       const char *base, const char *offset)
> +			       const char *base, const char *offset,
> +			       get_style_func get_style)
>   {
> -  char tb[16];			/* Temporary buffer.  */
> +  char tb[32];			/* Temporary buffer.  */
>     bool print_extend_p = true;
>     bool print_amount_p = true;
>     const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
> @@ -3161,16 +3207,23 @@ print_register_offset_address (char *buf, size_t size,
>     if (print_extend_p)
>       {
>         if (print_amount_p)
> -	snprintf (tb, sizeof (tb), ", %s #%" PRIi64, shift_name,
> +	snprintf (tb, sizeof (tb), ", %s%s %s#%" PRIi64,
> +		  get_style (dis_style_sub_mnemonic),
> +		  shift_name,
> +		  get_style (dis_style_immediate),
>     /* PR 21096: The %100 is to silence a warning about possible truncation.  */
>   		  (opnd->shifter.amount % 100));
>         else
> -	snprintf (tb, sizeof (tb), ", %s", shift_name);
> +	snprintf (tb, sizeof (tb), ", %s%s",
> +		  get_style (dis_style_sub_mnemonic), shift_name);
>       }
>     else
>       tb[0] = '\0';
>   
> -  snprintf (buf, size, "[%s, %s%s]", base, offset, tb);
> +  snprintf (buf, size, "%s[%s%s%s, %s%s%s%s]",
> +	    get_style (dis_style_text), get_style (dis_style_register),
> +	    base, get_style (dis_style_text), get_style (dis_style_register),
> +	    offset, get_style (dis_style_text), tb);
>   }
>   
>   /* Print ZA tiles from imm8 in ZERO instruction.
> @@ -3230,7 +3283,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   		       const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
>   		       bfd_vma *address, char** notes,
>   		       char *comment, size_t comment_size,
> -		       aarch64_feature_set features)
> +		       aarch64_feature_set features,
> +		       get_style_func get_style)
>   {
>     unsigned int i, num_conds;
>     const char *name = NULL;
> @@ -3278,7 +3332,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	break;
>         assert (opnd->qualifier == AARCH64_OPND_QLF_W
>   	      || opnd->qualifier == AARCH64_OPND_QLF_X);
> -      snprintf (buf, size, "%s",
> +      snprintf (buf, size, "%s%s",
> +		get_style (dis_style_register),
>   		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
>         break;
>   
> @@ -3291,7 +3346,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	      || opnd->qualifier == AARCH64_OPND_QLF_WSP
>   	      || opnd->qualifier == AARCH64_OPND_QLF_X
>   	      || opnd->qualifier == AARCH64_OPND_QLF_SP);
> -      snprintf (buf, size, "%s",
> +      snprintf (buf, size, "%s%s",
> +		get_style (dis_style_register),
>   		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 1));
>         break;
>   
> @@ -3311,19 +3367,26 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	  if (opnd->shifter.amount == 0)
>   	    {
>   	      /* Shifter omitted.  */
> -	      snprintf (buf, size, "%s",
> +	      snprintf (buf, size, "%s%s",
> +			get_style (dis_style_register),
>   			get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
>   	      break;
>   	    }
>   	}
>         if (opnd->shifter.amount)
> -	snprintf (buf, size, "%s, %s #%" PRIi64,
> +	snprintf (buf, size, "%s%s%s, %s%s %s#%" PRIi64,
> +		  get_style (dis_style_register),
>   		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
> +		  get_style (dis_style_text),
> +		  get_style (dis_style_sub_mnemonic),
>   		  aarch64_operand_modifiers[kind].name,
> -		  opnd->shifter.amount);
> +		  get_style (dis_style_immediate), opnd->shifter.amount);
>         else
> -	snprintf (buf, size, "%s, %s",
> +	snprintf (buf, size, "%s%s%s, %s%s",
> +		  get_style (dis_style_register),
>   		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
> +		  get_style (dis_style_text),
> +		  get_style (dis_style_sub_mnemonic),
>   		  aarch64_operand_modifiers[kind].name);
>         break;
>   
> @@ -3331,13 +3394,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         assert (opnd->qualifier == AARCH64_OPND_QLF_W
>   	      || opnd->qualifier == AARCH64_OPND_QLF_X);
>         if (opnd->shifter.amount == 0 && opnd->shifter.kind == AARCH64_MOD_LSL)
> -	snprintf (buf, size, "%s",
> +	snprintf (buf, size, "%s%s",
> +		  get_style (dis_style_register),
>   		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
>         else
> -	snprintf (buf, size, "%s, %s #%" PRIi64,
> +	snprintf (buf, size, "%s%s%s, %s%s %s#%" PRIi64,
> +		  get_style (dis_style_register),
>   		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
> +		  get_style (dis_style_text),
> +		  get_style (dis_style_sub_mnemonic),
>   		  aarch64_operand_modifiers[opnd->shifter.kind].name,
> -		  opnd->shifter.amount);
> +		  get_style (dis_style_immediate), opnd->shifter.amount);
>         break;
>   
>       case AARCH64_OPND_Fd:
> @@ -3353,7 +3420,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_Vd:
>       case AARCH64_OPND_SVE_Vm:
>       case AARCH64_OPND_SVE_Vn:
> -      snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
> +      snprintf (buf, size, "%s%s%d",
> +		get_style (dis_style_register),
> +		aarch64_get_qualifier_name (opnd->qualifier),
>   		opnd->reg.regno);
>         break;
>   
> @@ -3361,7 +3430,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_Vd:
>       case AARCH64_OPND_Vn:
>       case AARCH64_OPND_Vm:
> -      snprintf (buf, size, "v%d.%s", opnd->reg.regno,
> +      snprintf (buf, size, "%sv%d.%s",
> +		get_style (dis_style_register), opnd->reg.regno,
>   		aarch64_get_qualifier_name (opnd->qualifier));
>         break;
>   
> @@ -3370,21 +3440,26 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_Em:
>       case AARCH64_OPND_Em16:
>       case AARCH64_OPND_SM3_IMM2:
> -      snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
> +      snprintf (buf, size, "%sv%d.%s%s[%s%" PRIi64 "%s]",
> +		get_style (dis_style_register), opnd->reglane.regno,
>   		aarch64_get_qualifier_name (opnd->qualifier),
> -		opnd->reglane.index);
> +		get_style (dis_style_text), get_style (dis_style_immediate),
> +		opnd->reglane.index, get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_VdD1:
>       case AARCH64_OPND_VnD1:
> -      snprintf (buf, size, "v%d.d[1]", opnd->reg.regno);
> +      snprintf (buf, size, "%sv%d.d%s[%s1%s]",
> +		get_style (dis_style_register), opnd->reg.regno,
> +		get_style (dis_style_text), get_style (dis_style_immediate),
> +		get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_LVn:
>       case AARCH64_OPND_LVt:
>       case AARCH64_OPND_LVt_AL:
>       case AARCH64_OPND_LEt:
> -      print_register_list (buf, size, opnd, "v");
> +      print_register_list (buf, size, opnd, "v", get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_Pd:
> @@ -3397,13 +3472,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_Pt:
>       case AARCH64_OPND_SME_Pm:
>         if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
> -	snprintf (buf, size, "p%d", opnd->reg.regno);
> +	snprintf (buf, size, "%sp%d", get_style (dis_style_register),
> +		  opnd->reg.regno);
>         else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
>   	       || opnd->qualifier == AARCH64_OPND_QLF_P_M)
> -	snprintf (buf, size, "p%d/%s", opnd->reg.regno,
> +	snprintf (buf, size, "%sp%d/%s", get_style (dis_style_register),
> +		  opnd->reg.regno,
>   		  aarch64_get_qualifier_name (opnd->qualifier));
>         else
> -	snprintf (buf, size, "p%d.%s", opnd->reg.regno,
> +	snprintf (buf, size, "%sp%d.%s", get_style (dis_style_register),
> +		  opnd->reg.regno,
>   		  aarch64_get_qualifier_name (opnd->qualifier));
>         break;
>   
> @@ -3415,15 +3493,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_Zn:
>       case AARCH64_OPND_SVE_Zt:
>         if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
> -	snprintf (buf, size, "z%d", opnd->reg.regno);
> +	snprintf (buf, size, "%sz%d", get_style (dis_style_register),
> +		  opnd->reg.regno);
>         else
> -	snprintf (buf, size, "z%d.%s", opnd->reg.regno,
> +	snprintf (buf, size, "%sz%d.%s", get_style (dis_style_register),
> +		  opnd->reg.regno,
>   		  aarch64_get_qualifier_name (opnd->qualifier));
>         break;
>   
>       case AARCH64_OPND_SVE_ZnxN:
>       case AARCH64_OPND_SVE_ZtxN:
> -      print_register_list (buf, size, opnd, "z");
> +      print_register_list (buf, size, opnd, "z", get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_Zm3_INDEX:
> @@ -3432,14 +3512,18 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_Zm4_11_INDEX:
>       case AARCH64_OPND_SVE_Zm4_INDEX:
>       case AARCH64_OPND_SVE_Zn_INDEX:
> -      snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
> +      snprintf (buf, size, "%sz%d.%s%s[%s%" PRIi64 "%s]",
> +		get_style (dis_style_register), opnd->reglane.regno,
>   		aarch64_get_qualifier_name (opnd->qualifier),
> -		opnd->reglane.index);
> +		get_style (dis_style_text),
> +		get_style (dis_style_immediate), opnd->reglane.index,
> +		get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_SME_ZAda_2b:
>       case AARCH64_OPND_SME_ZAda_3b:
> -      snprintf (buf, size, "za%d.%s", opnd->reg.regno,
> +      snprintf (buf, size, "%sza%d.%s", get_style (dis_style_register),
> +		opnd->reg.regno,
>                   aarch64_get_qualifier_name (opnd->qualifier));
>         break;
>   
> @@ -3467,7 +3551,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         break;
>   
>       case AARCH64_OPND_SME_SM_ZA:
> -      snprintf (buf, size, "%s", opnd->reg.regno == 's' ? "sm" : "za");
> +      snprintf (buf, size, "%s%s",
> +		get_style (dis_style_register),
> +		opnd->reg.regno == 's' ? "sm" : "za");
>         break;
>   
>       case AARCH64_OPND_SME_PnT_Wm_imm:
> @@ -3480,7 +3566,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   
>       case AARCH64_OPND_CRn:
>       case AARCH64_OPND_CRm:
> -      snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
> +      snprintf (buf, size, "%sC%" PRIi64, get_style (dis_style_register),
> +		opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_IDX:
> @@ -3521,7 +3608,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_IMM_ROT1:
>       case AARCH64_OPND_SVE_IMM_ROT2:
>       case AARCH64_OPND_SVE_IMM_ROT3:
> -      snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> +      snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
> +		opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_SVE_I1_HALF_ONE:
> @@ -3530,7 +3618,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         {
>   	single_conv_t c;
>   	c.i = opnd->imm.value;
> -	snprintf (buf, size, "#%.1f", c.f);
> +	snprintf (buf, size, "%s#%.1f", get_style (dis_style_immediate), c.f);
>   	break;
>         }
>   
> @@ -3541,9 +3629,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         enum_value = opnd->imm.value;
>         assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
>         if (aarch64_sve_pattern_array[enum_value])
> -	snprintf (buf, size, "%s", aarch64_sve_pattern_array[enum_value]);
> +	snprintf (buf, size, "%s%s", get_style (dis_style_register),
> +		  aarch64_sve_pattern_array[enum_value]);
>         else
> -	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> +	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
> +		  opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_SVE_PATTERN_SCALED:
> @@ -3554,13 +3644,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         enum_value = opnd->imm.value;
>         assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
>         if (aarch64_sve_pattern_array[opnd->imm.value])
> -	snprintf (buf, size, "%s", aarch64_sve_pattern_array[opnd->imm.value]);
> +	snprintf (buf, size, "%s%s", get_style (dis_style_register),
> +		  aarch64_sve_pattern_array[opnd->imm.value]);
>         else
> -	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> +	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
> +		  opnd->imm.value);
>         if (opnd->shifter.operator_present)
>   	{
>   	  size_t len = strlen (buf);
> -	  snprintf (buf + len, size - len, ", %s #%" PRIi64,
> +	  snprintf (buf + len, size - len, ", %s%s #%" PRIi64,
> +		    get_style (dis_style_sub_mnemonic),
>   		    aarch64_operand_modifiers[opnd->shifter.kind].name,
>   		    opnd->shifter.amount);
>   	}
> @@ -3570,9 +3663,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         enum_value = opnd->imm.value;
>         assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
>         if (aarch64_sve_prfop_array[enum_value])
> -	snprintf (buf, size, "%s", aarch64_sve_prfop_array[enum_value]);
> +	snprintf (buf, size, "%s%s", get_style (dis_style_register),
> +		  aarch64_sve_prfop_array[enum_value]);
>         else
> -	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> +	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
> +		  opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_IMM_MOV:
> @@ -3581,12 +3676,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	case 4:	/* e.g. MOV Wd, #<imm32>.  */
>   	    {
>   	      int imm32 = opnd->imm.value;
> -	      snprintf (buf, size, "#0x%-20x", imm32);
> +	      snprintf (buf, size, "%s#0x%-20x",
> +			get_style (dis_style_immediate), imm32);
>   	      snprintf (comment, comment_size, "#%d", imm32);
>   	    }
>   	  break;
>   	case 8:	/* e.g. MOV Xd, #<imm64>.  */
> -	  snprintf (buf, size, "#0x%-20" PRIx64, opnd->imm.value);
> +	  snprintf (buf, size, "%s#0x%-20" PRIx64,
> +		    get_style (dis_style_immediate), opnd->imm.value);
>   	  snprintf (comment, comment_size, "#%" PRIi64, opnd->imm.value);
>   	  break;
>   	default:
> @@ -3596,7 +3693,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         break;
>   
>       case AARCH64_OPND_FPIMM0:
> -      snprintf (buf, size, "#0.0");
> +      snprintf (buf, size, "%s#0.0", get_style (dis_style_immediate));
>         break;
>   
>       case AARCH64_OPND_LIMM:
> @@ -3606,30 +3703,42 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_LIMM:
>       case AARCH64_OPND_SVE_LIMM_MOV:
>         if (opnd->shifter.amount)
> -	snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
> +	snprintf (buf, size, "%s#0x%" PRIx64 "%s, %slsl %s#%" PRIi64,
> +		  get_style (dis_style_immediate), opnd->imm.value,
> +		  get_style (dis_style_text),
> +		  get_style (dis_style_sub_mnemonic),
> +		  get_style (dis_style_immediate),
>   		  opnd->shifter.amount);
>         else
> -	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
> +	snprintf (buf, size, "%s#0x%" PRIx64,
> +		  get_style (dis_style_immediate), opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_SIMD_IMM:
>       case AARCH64_OPND_SIMD_IMM_SFT:
>         if ((! opnd->shifter.amount && opnd->shifter.kind == AARCH64_MOD_LSL)
>   	  || opnd->shifter.kind == AARCH64_MOD_NONE)
> -	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
> +	snprintf (buf, size, "%s#0x%" PRIx64,
> +		  get_style (dis_style_immediate), opnd->imm.value);
>         else
> -	snprintf (buf, size, "#0x%" PRIx64 ", %s #%" PRIi64, opnd->imm.value,
> +	snprintf (buf, size, "%s#0x%" PRIx64 "%s, %s%s %s#%" PRIi64,
> +		  get_style (dis_style_immediate), opnd->imm.value,
> +		  get_style (dis_style_text),
> +		  get_style (dis_style_sub_mnemonic),
>   		  aarch64_operand_modifiers[opnd->shifter.kind].name,
> -		  opnd->shifter.amount);
> +		  get_style (dis_style_immediate), opnd->shifter.amount);
>         break;
>   
>       case AARCH64_OPND_SVE_AIMM:
>       case AARCH64_OPND_SVE_ASIMM:
>         if (opnd->shifter.amount)
> -	snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
> +	snprintf (buf, size, "%s#%" PRIi64 "%s, lsl %s#%" PRIi64,
> +		  get_style (dis_style_immediate), opnd->imm.value,
> +		  get_style (dis_style_text), get_style (dis_style_immediate),
>   		  opnd->shifter.amount);
>         else
> -	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
> +	snprintf (buf, size, "%s#%" PRIi64, get_style (dis_style_immediate),
> +		  opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_FPIMM:
> @@ -3641,21 +3750,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	    {
>   	      half_conv_t c;
>   	      c.i = expand_fp_imm (2, opnd->imm.value);
> -	      snprintf (buf, size,  "#%.18e", c.f);
> +	      snprintf (buf, size,  "%s#%.18e",
> +			get_style (dis_style_immediate), c.f);
>   	    }
>   	  break;
>   	case 4:	/* e.g. FMOV <Vd>.4S, #<imm>.  */
>   	    {
>   	      single_conv_t c;
>   	      c.i = expand_fp_imm (4, opnd->imm.value);
> -	      snprintf (buf, size,  "#%.18e", c.f);
> +	      snprintf (buf, size,  "%s#%.18e",
> +			get_style (dis_style_immediate), c.f);
>   	    }
>   	  break;
>   	case 8:	/* e.g. FMOV <Sd>, #<imm>.  */
>   	    {
>   	      double_conv_t c;
>   	      c.i = expand_fp_imm (8, opnd->imm.value);
> -	      snprintf (buf, size,  "#%.18e", c.d);
> +	      snprintf (buf, size,  "%s#%.18e",
> +			get_style (dis_style_immediate), c.d);
>   	    }
>   	  break;
>   	default:
> @@ -3676,12 +3788,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	      (int64_t) get_optional_operand_default_value (opcode)))
>   	/* Omit the operand, e.g. DCPS1.  */
>   	break;
> -      snprintf (buf, size, "#0x%x", (unsigned int)opnd->imm.value);
> +      snprintf (buf, size, "%s#0x%x", get_style (dis_style_immediate),
> +		(unsigned int)opnd->imm.value);
>         break;
>   
>       case AARCH64_OPND_COND:
>       case AARCH64_OPND_COND1:
> -      snprintf (buf, size, "%s", opnd->cond->names[0]);
> +      snprintf (buf, size, "%s%s", get_style (dis_style_sub_mnemonic),
> +		opnd->cond->names[0]);
>         num_conds = ARRAY_SIZE (opnd->cond->names);
>         for (i = 1; i < num_conds && opnd->cond->names[i]; ++i)
>   	{
> @@ -3706,7 +3820,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	 in the disassemble_info will take care of the printing.  But some
>   	 other callers may be still interested in getting the string in *STR,
>   	 so here we do snprintf regardless.  */
> -      snprintf (buf, size, "#0x%" PRIx64, addr);
> +      snprintf (buf, size, "%s#0x%" PRIx64,
> +		get_style (dis_style_address), addr);
>         break;
>   
>       case AARCH64_OPND_ADDR_PCREL14:
> @@ -3722,7 +3837,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	 in the disassemble_info will take care of the printing.  But some
>   	 other callers may be still interested in getting the string in *STR,
>   	 so here we do snprintf regardless.  */
> -      snprintf (buf, size, "#0x%" PRIx64, addr);
> +      snprintf (buf, size, "%s#0x%" PRIx64, get_style (dis_style_address),
> +		addr);
>         break;
>   
>       case AARCH64_OPND_ADDR_SIMPLE:
> @@ -3732,12 +3848,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         if (opnd->type == AARCH64_OPND_SIMD_ADDR_POST)
>   	{
>   	  if (opnd->addr.offset.is_reg)
> -	    snprintf (buf, size, "[%s], x%d", name, opnd->addr.offset.regno);
> +	    snprintf (buf, size, "%s[%s%s%s], %sx%d",
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_register), name,
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_register),
> +		      opnd->addr.offset.regno);
>   	  else
> -	    snprintf (buf, size, "[%s], #%d", name, opnd->addr.offset.imm);
> +	    snprintf (buf, size, "%s[%s%s%s], %s#%d",
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_register), name,
> +		      get_style (dis_style_text),
> +		      get_style (dis_style_immediate),
> +		      opnd->addr.offset.imm);
>   	}
>         else
> -	snprintf (buf, size, "[%s]", name);
> +	snprintf (buf, size, "%s[%s%s%s]",
> +		  get_style (dis_style_text), get_style (dis_style_register),
> +		  name, get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_ADDR_REGOFF:
> @@ -3753,14 +3881,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_ADDR_RX_LSL3:
>         print_register_offset_address
>   	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
> -	 get_offset_int_reg_name (opnd));
> +	 get_offset_int_reg_name (opnd), get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_ADDR_ZX:
>         print_register_offset_address
>   	(buf, size, opnd,
>   	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
> -	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0));
> +	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0), get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_ADDR_RZ:
> @@ -3777,7 +3905,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
>         print_register_offset_address
>   	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
> -	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
> +	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
> +	 get_style);
>         break;
>   
>       case AARCH64_OPND_ADDR_SIMM7:
> @@ -3801,7 +3930,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_ADDR_RI_U6x4:
>       case AARCH64_OPND_SVE_ADDR_RI_U6x8:
>         print_immediate_offset_address
> -	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1));
> +	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
> +	 get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_ADDR_ZI_U5:
> @@ -3810,7 +3940,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
>         print_immediate_offset_address
>   	(buf, size, opnd,
> -	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier));
> +	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
> +	 get_style);
>         break;
>   
>       case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
> @@ -3819,15 +3950,22 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         print_register_offset_address
>   	(buf, size, opnd,
>   	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
> -	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
> +	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
> +	 get_style);
>         break;
>   
>       case AARCH64_OPND_ADDR_UIMM12:
>         name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
>         if (opnd->addr.offset.imm)
> -	snprintf (buf, size, "[%s, #%d]", name, opnd->addr.offset.imm);
> +	snprintf (buf, size, "%s[%s%s%s, %s#%d%s]",
> +		  get_style (dis_style_text), get_style (dis_style_register),
> +		  name, get_style (dis_style_text),
> +		  get_style (dis_style_immediate), opnd->addr.offset.imm,
> +		  get_style (dis_style_text));
>         else
> -	snprintf (buf, size, "[%s]", name);
> +	snprintf (buf, size, "%s[%s%s%s]", get_style (dis_style_text),
> +		  get_style (dis_style_register), name,
> +		  get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_SYSREG:
> @@ -3866,14 +4004,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>   	}
>   
>         if (name)
> -	snprintf (buf, size, "%s", name);
> +	snprintf (buf, size, "%s%s", get_style (dis_style_register), name);
>         else
>   	{
>   	  /* Implementation defined system register.  */
>   	  unsigned int value = opnd->sysreg.value;
> -	  snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
> -		    (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
> -		    value & 0x7);
> +	  snprintf (buf, size, "%ss%u_%u_c%u_c%u_%u",
> +		    get_style (dis_style_register), (value >> 14) & 0x3,
> +		    (value >> 11) & 0x7, (value >> 7) & 0xf,
> +		    (value >> 3) & 0xf, value & 0x7);
>   	}
>         break;
>   
> @@ -3899,12 +4038,21 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>       case AARCH64_OPND_SYSREG_IC:
>       case AARCH64_OPND_SYSREG_TLBI:
>       case AARCH64_OPND_SYSREG_SR:
> -      snprintf (buf, size, "%s", opnd->sysins_op->name);
> +      snprintf (buf, size, "%s%s", get_style (dis_style_register),
> +		opnd->sysins_op->name);
>         break;
>   
>       case AARCH64_OPND_BARRIER:
>       case AARCH64_OPND_BARRIER_DSB_NXS:
> -      snprintf (buf, size, "%s", opnd->barrier->name);
> +      {
> +	enum disassembler_style style;
> +	if (opnd->barrier->name[0] == '#')
> +	  style = dis_style_immediate;
> +	else
> +	  style = dis_style_sub_mnemonic;
> +	snprintf (buf, size, "%s%s", get_style (style),
> +		  opnd->barrier->name);
> +      }
>         break;
>   
>       case AARCH64_OPND_BARRIER_ISB:
> @@ -3912,38 +4060,46 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
>         if (! optional_operand_p (opcode, idx)
>   	  || (opnd->barrier->value
>   	      != get_optional_operand_default_value (opcode)))
> -	snprintf (buf, size, "#0x%x", opnd->barrier->value);
> +	snprintf (buf, size, "%s#0x%x", get_style (dis_style_immediate),
> +		  opnd->barrier->value);
>         break;
>   
>       case AARCH64_OPND_PRFOP:
>         if (opnd->prfop->name != NULL)
> -	snprintf (buf, size, "%s", opnd->prfop->name);
> +	snprintf (buf, size, "%s%s", get_style (dis_style_sub_mnemonic),
> +		  opnd->prfop->name);
>         else
> -	snprintf (buf, size, "#0x%02x", opnd->prfop->value);
> +	snprintf (buf, size, "%s#0x%02x", get_style (dis_style_immediate),
> +		  opnd->prfop->value);
>         break;
>   
>       case AARCH64_OPND_BARRIER_PSB:
> -      snprintf (buf, size, "csync");
> +      snprintf (buf, size, "%scsync", get_style (dis_style_sub_mnemonic));
>         break;
>   
>       case AARCH64_OPND_BTI_TARGET:
>         if ((HINT_FLAG (opnd->hint_option->value) & HINT_OPD_F_NOPRINT) == 0)
> -	snprintf (buf, size, "%s", opnd->hint_option->name);
> +	snprintf (buf, size, "%s%s", get_style (dis_style_sub_mnemonic),
> +		  opnd->hint_option->name);
>         break;
>   
>       case AARCH64_OPND_MOPS_ADDR_Rd:
>       case AARCH64_OPND_MOPS_ADDR_Rs:
> -      snprintf (buf, size, "[%s]!",
> -		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
> +      snprintf (buf, size, "%s[%s%s%s]!",
> +		get_style (dis_style_text), get_style (dis_style_register),
> +		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0),
> +		get_style (dis_style_text));
>         break;
>   
>       case AARCH64_OPND_MOPS_WB_Rn:
> -      snprintf (buf, size, "%s!",
> -		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
> +      snprintf (buf, size, "%s%s%s!",
> +		get_style (dis_style_register),
> +		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0),
> +		get_style (dis_style_text));
>         break;
>   
>       default:
> -      snprintf (buf, size, "<invalid>");
> +      snprintf (buf, size, "%s<invalid>", get_style (dis_style_text));
>         break;
>       }
>   }
> 

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv3 0/2] AArch64 libopcodes styling
  2022-07-05 13:10       ` Richard Earnshaw
@ 2022-07-07 10:23         ` Andrew Burgess
  2022-07-07 10:23           ` [PATCHv3 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
                             ` (2 more replies)
  0 siblings, 3 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-07-07 10:23 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

Changes since v2:

  - Patch #1 is unchanged,

  - Patch #2, now with more OBSTACK!  This patch is pretty much a
    complete rewrite from the gound up based on Richard's feedback.
    The new iteration makes use of obstacks (in aarch64-dis.c and
    tc-aarch64.c) to format each chunk of disassembler output.  These
    chunks are then combined in aarch64-opc.c as required.

Changes since v1:

  - Original patch #1 has been merged,

  - New patch #1 adds a dis_style_sub_mnemonic style and updates
    objdump to handle this style,

  - Patch #2 has been updated to make use of the new style.

---

Andrew Burgess (2):
  opcodes: add new sub-mnemonic disassembler style
  libopcodes/aarch64: add support for disassembler styling

 binutils/objdump.c       |   2 +
 gas/config/tc-aarch64.c  |  45 +++-
 include/dis-asm.h        |   7 +
 include/opcode/aarch64.h |  28 ++-
 opcodes/aarch64-dis.c    | 247 +++++++++++++++++---
 opcodes/aarch64-opc.c    | 470 ++++++++++++++++++++++++++-------------
 6 files changed, 616 insertions(+), 183 deletions(-)

-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv3 1/2] opcodes: add new sub-mnemonic disassembler style
  2022-07-07 10:23         ` [PATCHv3 0/2] AArch64 libopcodes styling Andrew Burgess
@ 2022-07-07 10:23           ` Andrew Burgess
  2022-07-07 10:23           ` [PATCHv3 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
  2022-07-08 10:25           ` [PATCHv4 0/2] AArch64 libopcodes styling Andrew Burgess
  2 siblings, 0 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-07-07 10:23 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

When adding libopcodes disassembler styling support for AArch64, it
feels like the results would be improved by having a new sub-mnemonic
style.  This will be used in cases like:

  add    w16, w7, w1, uxtb #2
                      ^^^^----- Here

And:

  cinc   w0, w1, ne
                 ^^----- Here

This commit just adds the new style, and prepares objdump to handle
the style.  A later commit will add AArch64 styling, and will actually
make use of the style.

As this style is currently unused, there should be no user visible
changes after this commit.
---
 binutils/objdump.c | 2 ++
 include/dis-asm.h  | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/binutils/objdump.c b/binutils/objdump.c
index 67824053527..4076587151c 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -2167,6 +2167,7 @@ objdump_color_for_disassembler_style (enum disassembler_style style)
 	{
 	case dis_style_symbol: color = 32; break;
         case dis_style_assembler_directive:
+	case dis_style_sub_mnemonic:
 	case dis_style_mnemonic: color = 33; break;
 	case dis_style_register: color = 34; break;
 	case dis_style_address:
@@ -2185,6 +2186,7 @@ objdump_color_for_disassembler_style (enum disassembler_style style)
 	{
 	case dis_style_symbol: color = 40; break;
         case dis_style_assembler_directive:
+	case dis_style_sub_mnemonic:
 	case dis_style_mnemonic: color = 142; break;
 	case dis_style_register: color = 27; break;
 	case dis_style_address:
diff --git a/include/dis-asm.h b/include/dis-asm.h
index 4f91df12498..f1a83dc84e5 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -62,6 +62,13 @@ enum disassembler_style
      instructions.  */
   dis_style_mnemonic,
 
+  /* Some architectures include additional mnemonic like fields within the
+     instruction operands, e.g. on aarch64 'add w16, w7, w1, lsl #2' where
+     the 'lsl' is an additional piece of text that describes how the
+     instruction should behave.  This sub-mnemonic style can be used for
+     these pieces of text.  */
+  dis_style_sub_mnemonic,
+
   /* For things that aren't real machine instructions, but rather
      assembler directives, e.g. .byte, etc.  */
   dis_style_assembler_directive,
-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv3 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-07-07 10:23         ` [PATCHv3 0/2] AArch64 libopcodes styling Andrew Burgess
  2022-07-07 10:23           ` [PATCHv3 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
@ 2022-07-07 10:23           ` Andrew Burgess
  2022-07-07 10:44             ` Andrew Burgess
  2022-07-08 10:25           ` [PATCHv4 0/2] AArch64 libopcodes styling Andrew Burgess
  2 siblings, 1 reply; 31+ messages in thread
From: Andrew Burgess @ 2022-07-07 10:23 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

This commit enables disassembler styling for AArch64.  After this
commit it is possible to have objdump style AArch64 disassembler
output (using --disassembler-color option).  Once the required GDB
patches are merged, GDB will also style the disassembler output.

The changes to support styling are mostly split between two files
opcodes/aarch64-dis.c and opcodes/aarch64-opc.c.

The entry point for the AArch64 disassembler can be found in
aarch64-dis.c, this file handles printing the instruction mnemonics,
and assembler directives (e.g. '.byte', '.word', etc).  Some operands,
mostly relating to assembler directives are also printed from this
file.  This commit changes all of this to pass through suitable
styling information.

However, for most "normal" instructions, the instruction operands are
printed using a two step process.  From aarch64-dis.c, in the
print_operands function, the function aarch64_print_operand is called,
this function is in aarch64-opc.c, and converts an instruction operand
into a string.  Then, back in print_operands (aarch64-dis.c), the
operand string is printed.

Unfortunately, the string returned by aarch64_print_operand can be
quite complex, it will include syntax elements, like '[' and ']', in
addition to register names and immediate values.  In some cases, a
single operand will expand into what will appear (to the user) as
multiple operands separated with a ','.

This makes the task of styling more complex, all these different
components need to by styled differently, so we need to get the
styling information out of aarch64_print_operand in some way.

The solution that I propose here is similar to the solution that I
used for the i386 disassembler.

Currently, aarch64_print_operand uses snprintf to write the operand
text into a buffer provided by the caller.

What I propose is that we pass an extra argument to the
aarch64_print_operand function, this argument will be a structure, the
structure contains a callback function and some state.

When aarch64_print_operand needs to format part of its output this can
be done by using the callback function within the new structure, this
callback returns a string with special embedded markers that indicate
which mode should be used for each piece of text.  Back in
aarch64-dis.c we can spot these special style markers and use this to
split the disassembler output up and apply the correct style to each
piece.

To make aarch64-opc.c clearer a series of new static functions have
been added, e.g. 'style_reg', 'style_imm', etc.  Each of these
functions formats a piece of text in a different style, 'register' and
'immediate' in this case.

Here's an example taken from aarch64-opc.c of the new functions in
use:

    snprintf (buf, size, "[%s, %s]!",
              style_reg (styler, base),
              style_imm (styler, "#%d", opnd->addr.offset.imm));

The aarch64_print_operand function is also called from the assembler
to aid in printing diagnostic messages.  Right now I have no plans to
add styling to the assembler output, and so, the callback function
used in the assembler ignores the styling information and just returns
an plain string.

I've used the source files in gas/testsuite/gas/aarch64/ for testing,
and have manually gone through and checked that the styling looks
reasonable, however, I'm not an AArch64 expert, so it is possible that
the odd piece is styled incorrectly.  Please point out any mistakes
I've made.

With objdump disassembler color turned off, there should be no change
in the output after this commit.
---
 gas/config/tc-aarch64.c  |  45 +++-
 include/opcode/aarch64.h |  28 ++-
 opcodes/aarch64-dis.c    | 247 +++++++++++++++++---
 opcodes/aarch64-opc.c    | 470 ++++++++++++++++++++++++++-------------
 4 files changed, 607 insertions(+), 183 deletions(-)

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 779db31828b..dc154b96fce 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -5347,6 +5347,41 @@ assign_qualifier_sequence (aarch64_inst *instr,
     instr->operands[i].qualifier = *qualifiers;
 }
 
+/* Callback used by aarch64_print_operand to apply STYLE to the
+   disassembler output created from FMT and ARGS.  The STYLER object holds
+   any required state.  Must return a pointer to a string (created from FMT
+   and ARGS) that will continue to be valid until the complete disassembled
+   instruction has been printed.
+
+   We don't currently add any styling to the output of the disassembler as
+   used within assembler error messages, and so STYLE is ignored here.  A
+   new string is allocated on the obstack help within STYLER and returned
+   to the caller.  */
+
+static const char *aarch64_apply_style
+	(struct aarch64_styler *styler,
+	 enum disassembler_style style ATTRIBUTE_UNUSED,
+	 const char *fmt, va_list args)
+{
+  int res;
+  char *ptr;
+  struct obstack *stack = (struct obstack *) styler->state;
+  va_list ap;
+
+  /* Calculate the required space.  */
+  va_copy (ap, args);
+  res = vsnprintf (NULL, 0, fmt, ap);
+  va_end (ap);
+  gas_assert (res >= 0);
+
+  /* Allocate space on the obstack and format the result.  */
+  ptr = (char *) obstack_alloc (stack, res + 1);
+  res = vsnprintf (ptr, (res + 1), fmt, args);
+  gas_assert (res >= 0);
+
+  return ptr;
+}
+
 /* Print operands for the diagnosis purpose.  */
 
 static void
@@ -5354,6 +5389,12 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 		const aarch64_opnd_info *opnds)
 {
   int i;
+  struct aarch64_styler styler;
+  struct obstack content;
+  obstack_init (&content);
+
+  styler.apply_style = aarch64_apply_style;
+  styler.state = (void *) &content;
 
   for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
@@ -5371,7 +5412,7 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL,
-			     NULL, cmt, sizeof (cmt), cpu_variant);
+			     NULL, cmt, sizeof (cmt), cpu_variant, &styler);
 
       /* Delimiter.  */
       if (str[0] != '\0')
@@ -5389,6 +5430,8 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 	  strcat (buf, cmt);
 	}
     }
+
+  obstack_free (&content, NULL);
 }
 
 /* Send to stderr a string as information.  */
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 186ba9a4800..9477ac98f3b 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -27,6 +27,8 @@
 #include <assert.h>
 #include <stdlib.h>
 
+#include "dis-asm.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -1367,12 +1369,36 @@ aarch64_replace_opcode (struct aarch64_inst *,
 extern const aarch64_opcode *
 aarch64_get_opcode (enum aarch64_op);
 
+/* An instance of this structure is passed to aarch64_print_operand, and
+   the callback within this structure is used to apply styling to the
+   disassembler output.  This structure encapsulates the callback and a
+   state pointer.  */
+
+struct aarch64_styler
+{
+  /* The callback used to apply styling.  Returns a string created from FMT
+     and ARGS with STYLE applied to the string.  STYLER is a pointer back
+     to this object so that the callback can access the state member.
+
+     The string returned from this callback must remain valid until the
+     call to aarch64_print_operand has completed.  */
+  const char *(*apply_style) (struct aarch64_styler *styler,
+			      enum disassembler_style style,
+			      const char *fmt,
+			      va_list args);
+
+  /* A pointer to a state object which can be used by the apply_style
+     callback function.  */
+  void *state;
+};
+
 /* Generate the string representation of an operand.  */
 extern void
 aarch64_print_operand (char *, size_t, bfd_vma, const aarch64_opcode *,
 		       const aarch64_opnd_info *, int, int *, bfd_vma *,
 		       char **, char *, size_t,
-		       aarch64_feature_set features);
+		       aarch64_feature_set features,
+		       struct aarch64_styler *styler);
 
 /* Miscellaneous interface.  */
 
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index acaad28fdff..fa69b893f22 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -25,9 +25,18 @@
 #include "opintl.h"
 #include "aarch64-dis.h"
 #include "elf-bfd.h"
+#include "safe-ctype.h"
+#include "obstack.h"
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
 
 #define INSNLEN 4
 
+/* This character is used to encode style information within the output
+   buffers.  See get_style_text and print_operands for more details.  */
+#define STYLE_MARKER_CHAR '\002'
+
 /* Cached mapping symbol state.  */
 enum map_type
 {
@@ -3275,6 +3284,90 @@ aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst,
   return ERR_UND;
 }
 
+/* Return a short string to indicate a switch to STYLE.  These strings
+   will be embedded into the disassembled operand text (as produced by
+   aarch64_print_operand), and then spotted in the print_operands function
+   so that the disassembler output can be slit by style.  */
+
+static const char *
+get_style_text (enum disassembler_style style)
+{
+  static bool init = false;
+  static char formats[16][4];
+  unsigned num;
+
+  /* First time through we build a string for every possible format.  This
+     code relies on there being no more than 16 different styles (there's
+     an assert below for this).  */
+  if (!init)
+    {
+      int i;
+
+      for (i = 0; i <= 0xf; ++i)
+	{
+	  int res = snprintf (&formats[i][0], sizeof (formats[i]), "%c%x%c",
+			      STYLE_MARKER_CHAR, i, STYLE_MARKER_CHAR);
+	  assert (res == 3);
+	}
+
+      init = true;
+    }
+
+  /* Return the string that marks switching to STYLE.  */
+  num = (unsigned) style;
+  assert (style <= 0xf);
+  return formats[num];
+}
+
+/* Callback used by aarch64_print_operand to apply STYLE to the
+   disassembler output created from FMT and ARGS.  The STYLER object holds
+   any required state.  Must return a pointer to a string (created from FMT
+   and ARGS) that will continue to be valid until the complete disassembled
+   instruction has been printed.
+
+   We return a string that includes two embedded style markers, the first,
+   places at the start of the string, indicates a switch to STYLE, and the
+   second, placed at the end of the string, indicates a switch back to the
+   default text style.
+
+   Later, when we print the operand text we take care to collapse any
+   adjacent style markers, and to ignore any style markers that appear at
+   the very end of a complete operand string.  */
+
+static const char *aarch64_apply_style (struct aarch64_styler *styler,
+					enum disassembler_style style,
+					const char *fmt,
+					va_list args)
+{
+  int res;
+  char *ptr, *tmp;
+  struct obstack *stack = (struct obstack *) styler->state;
+  va_list ap;
+
+  /* These are the two strings for switching styles.  */
+  const char *style_on = get_style_text (style);
+  const char *style_off = get_style_text (dis_style_text);
+
+  /* Calculate space needed once FMT and ARGS are expanded.  */
+  va_copy (ap, args);
+  res = vsnprintf (NULL, 0, fmt, ap);
+  va_end (ap);
+  assert (res >= 0);
+
+  /* Allocate space on the obstack for the expanded FMT and ARGS, as well
+     as the two strings for switching styles, then write all of these
+     strings onto the obstack.  */
+  ptr = (char *) obstack_alloc (stack, res + strlen (style_on)
+				+ strlen (style_off) + 1);
+  tmp = stpcpy (ptr, style_on);
+  res = vsnprintf (tmp, (res + 1), fmt, args);
+  assert (res >= 0);
+  tmp += res;
+  strcpy (tmp, style_off);
+
+  return ptr;
+}
+
 /* Print operands.  */
 
 static void
@@ -3284,6 +3377,13 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
 {
   char *notes = NULL;
   int i, pcrel_p, num_printed;
+  struct aarch64_styler styler;
+  struct obstack content;
+  obstack_init (&content);
+
+  styler.apply_style = aarch64_apply_style;
+  styler.state = (void *) &content;
+
   for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
       char str[128];
@@ -3301,33 +3401,97 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
 			     &info->target, &notes, cmt, sizeof (cmt),
-			     arch_variant);
+			     arch_variant, &styler);
 
       /* Print the delimiter (taking account of omitted operand(s)).  */
       if (str[0] != '\0')
-	(*info->fprintf_func) (info->stream, "%s",
-			       num_printed++ == 0 ? "\t" : ", ");
+	(*info->fprintf_styled_func) (info->stream, dis_style_text, "%s",
+				      num_printed++ == 0 ? "\t" : ", ");
 
       /* Print the operand.  */
       if (pcrel_p)
 	(*info->print_address_func) (info->target, info);
       else
 	{
-	  (*info->fprintf_func) (info->stream, "%s", str);
-
-	  /* Print the comment.  This works because only the last operand
-	     ever adds a comment.  If that ever changes then we'll need to
-	     be smarter here.  */
-	  if (cmt[0] != '\0')
-	    (*info->fprintf_func) (info->stream, "\t// %s", cmt);
+	  /* This operand came from aarch64_print_operand, and will include
+	     embedded strings indicating which style each character should
+	     have.  In the following code we split the text based on
+	     CURR_STYLE, and call the styled print callback to print each
+	     block of text in the appropriate style.  */
+	  char *start, *curr;
+	  enum disassembler_style curr_style = dis_style_text;
+
+	  start = curr = str;
+	  do
+	    {
+	      if (*curr == '\0'
+		  || (*curr == STYLE_MARKER_CHAR
+		      && ISXDIGIT (*(curr + 1))
+		      && *(curr + 2) == STYLE_MARKER_CHAR))
+		{
+		  /* Output content between our START position and CURR.  */
+		  int len = curr - start;
+		  if (len > 0)
+		    {
+		      if ((*info->fprintf_styled_func) (info->stream,
+							curr_style,
+							"%.*s",
+							len, start) < 0)
+			break;
+		    }
+
+		  if (*curr == '\0')
+		    break;
+
+		  /* Skip over the initial STYLE_MARKER_CHAR.  */
+		  ++curr;
+
+		  /* Update the CURR_STYLE.  As there are less than 16
+		     styles, it is possible, that if the input is corrupted
+		     in some way, that we might set CURR_STYLE to an
+		     invalid value.  Don't worry though, we check for this
+		     situation.  */
+		  if (*curr >= '0' && *curr <= '9')
+		    curr_style = (enum disassembler_style) (*curr - '0');
+		  else if (*curr >= 'a' && *curr <= 'f')
+		    curr_style = (enum disassembler_style) (*curr - 'a' + 10);
+		  else
+		    curr_style = dis_style_text;
+
+		  /* Check for an invalid style having been selected.  This
+		     should never happen, but it doesn't hurt to be a
+		     little paranoid.  */
+		  if (curr_style > dis_style_comment_start)
+		    curr_style = dis_style_text;
+
+		  /* Skip the hex character, and the closing STYLE_MARKER_CHAR.  */
+		  curr += 2;
+
+		  /* Reset the START to after the style marker.  */
+		  start = curr;
+		}
+	      else
+		++curr;
+	    }
+	  while (true);
 	}
+
+      /* Print the comment.  This works because only the last operand ever
+	 adds a comment.  If that ever changes then we'll need to be
+	 smarter here.  */
+      if (cmt[0] != '\0')
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "\t// %s", cmt);
     }
 
     if (notes && !no_notes)
       {
 	*has_notes = true;
-	(*info->fprintf_func) (info->stream, "  // note: %s", notes);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "  // note: %s", notes);
       }
+
+    obstack_free (&content, NULL);
 }
 
 /* Set NAME to a copy of INST's mnemonic with the "." suffix removed.  */
@@ -3359,10 +3523,12 @@ print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
       char name[8];
 
       remove_dot_suffix (name, inst);
-      (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
+      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				    "%s.%s", name, inst->cond->names[0]);
     }
   else
-    (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
+    (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				  "%s", inst->opcode->name);
 }
 
 /* Decide whether we need to print a comment after the operands of
@@ -3379,9 +3545,10 @@ print_comment (const aarch64_inst *inst, struct disassemble_info *info)
       remove_dot_suffix (name, inst);
       num_conds = ARRAY_SIZE (inst->cond->names);
       for (i = 1; i < num_conds && inst->cond->names[i]; ++i)
-	(*info->fprintf_func) (info->stream, "%s %s.%s",
-			       i == 1 ? "  //" : ",",
-			       name, inst->cond->names[i]);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "%s %s.%s",
+				      i == 1 ? "  //" : ",",
+				      name, inst->cond->names[i]);
     }
 }
 
@@ -3398,28 +3565,30 @@ print_verifier_notes (aarch64_operand_error *detail,
      would not have succeeded.  We can safely ignore these.  */
   assert (detail->non_fatal);
 
-  (*info->fprintf_func) (info->stream, "  // note: ");
+  (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				"  // note: ");
   switch (detail->kind)
     {
     case AARCH64_OPDE_A_SHOULD_FOLLOW_B:
-      (*info->fprintf_func) (info->stream,
-			     _("this `%s' should have an immediately"
-			       " preceding `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("this `%s' should have an immediately"
+				      " preceding `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     case AARCH64_OPDE_EXPECTED_A_AFTER_B:
-      (*info->fprintf_func) (info->stream,
-			     _("expected `%s' after previous `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("expected `%s' after previous `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     default:
       assert (detail->error);
-      (*info->fprintf_func) (info->stream, "%s", detail->error);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    "%s", detail->error);
       if (detail->index >= 0)
-	(*info->fprintf_func) (info->stream, " at operand %d",
-			       detail->index + 1);
+	(*info->fprintf_styled_func) (info->stream, dis_style_text,
+				      " at operand %d", detail->index + 1);
       break;
     }
 }
@@ -3511,8 +3680,13 @@ print_insn_aarch64_word (bfd_vma pc,
     case ERR_NYI:
       /* Handle undefined instructions.  */
       info->insn_type = dis_noninsn;
-      (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
-			     word, err_msg[ret]);
+      (*info->fprintf_styled_func) (info->stream,
+				    dis_style_assembler_directive,
+				    ".inst\t");
+      (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
+				    "0x%08x", word);
+      (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				    " ; %s", err_msg[ret]);
       break;
     case ERR_OK:
       user_friendly_fixup (&inst);
@@ -3554,13 +3728,22 @@ print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
   switch (info->bytes_per_chunk)
     {
     case 1:
-      info->fprintf_func (info->stream, ".byte\t0x%02x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".byte\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%02x", word);
       break;
     case 2:
-      info->fprintf_func (info->stream, ".short\t0x%04x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".short\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%04x", word);
       break;
     case 4:
-      info->fprintf_func (info->stream, ".word\t0x%08x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".word\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%08x", word);
       break;
     default:
       abort ();
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 1c93f836020..b6de4c96baf 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -35,6 +35,36 @@
 int debug_dump = false;
 #endif /* DEBUG_AARCH64 */
 
+/* ... */
+static int
+debug_snprintf (char *str, size_t size, int lineno, const char *fmt, ...)
+{
+  char tmp[1024];
+  va_list ap;
+  int res;
+  static bool init;
+  static bool debug_p;
+  if (!init)
+    {
+      debug_p = getenv ("DEBUG_AARCH64") != NULL;
+      init = true;
+    }
+
+  if (debug_p)
+    snprintf (tmp, sizeof (tmp), "<%d:%s>", lineno, fmt);	/* IGNORE.  */
+  else
+    snprintf (tmp, sizeof (tmp), "%s", fmt);			/* IGNORE.  */
+
+  va_start (ap, fmt);
+  res = vsnprintf (str, size, tmp, ap);
+  va_end (ap);
+  return res;
+}
+
+#define snprintf(BUF,LEN,FMT,...)                              \
+  debug_snprintf (BUF, LEN, __LINE__, FMT, ##__VA_ARGS__)
+
+
 /* The enumeration strings associated with each value of a 5-bit SVE
    pattern operand.  A null entry indicates a reserved meaning.  */
 const char *const aarch64_sve_pattern_array[32] = {
@@ -3038,18 +3068,78 @@ expand_fp_imm (int size, uint32_t imm8)
   return imm;
 }
 
+/* Return a string based on FMT with the register style applied.  */
+
+static const char *
+style_reg (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_register, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
+/* Return a string based on FMT with the immediate style applied.  */
+
+static const char *
+style_imm (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_immediate, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
+/* Return a string based on FMT with the sub-mnemonic style applied.  */
+
+static const char *
+style_sub_mnem (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_sub_mnemonic, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
+/* Return a string based on FMT with the address style applied.  */
+
+static const char *
+style_addr (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_address, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
 /* Produce the string representation of the register list operand *OPND
    in the buffer pointed by BUF of size SIZE.  PREFIX is the part of
    the register name that comes before the register number, such as "v".  */
 static void
 print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
-		     const char *prefix)
+		     const char *prefix, struct aarch64_styler *styler)
 {
   const int num_regs = opnd->reglist.num_regs;
   const int first_reg = opnd->reglist.first_regno;
   const int last_reg = (first_reg + num_regs - 1) & 0x1f;
   const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
-  char tb[8];	/* Temporary buffer.  */
+  char tb[16];	/* Temporary buffer.  */
 
   assert (opnd->type != AARCH64_OPND_LEt || opnd->reglist.has_index);
   assert (num_regs >= 1 && num_regs <= 4);
@@ -3057,7 +3147,8 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
   /* Prepare the index if any.  */
   if (opnd->reglist.has_index)
     /* PR 21096: The %100 is to silence a warning about possible truncation.  */
-    snprintf (tb, 8, "[%" PRIi64 "]", (opnd->reglist.index % 100));
+    snprintf (tb, sizeof (tb), "[%s]",
+	      style_imm (styler, "%" PRIi64, (opnd->reglist.index % 100)));
   else
     tb[0] = '\0';
 
@@ -3065,8 +3156,9 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
      more than two registers in the list, and the register numbers
      are monotonically increasing in increments of one.  */
   if (num_regs > 2 && last_reg > first_reg)
-    snprintf (buf, size, "{%s%d.%s-%s%d.%s}%s", prefix, first_reg, qlf_name,
-	      prefix, last_reg, qlf_name, tb);
+    snprintf (buf, size, "{%s-%s}%s",
+	      style_reg (styler, "%s%d.%s", prefix, first_reg, qlf_name),
+	      style_reg (styler, "%s%d.%s", prefix, last_reg, qlf_name), tb);
   else
     {
       const int reg0 = first_reg;
@@ -3077,21 +3169,30 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
       switch (num_regs)
 	{
 	case 1:
-	  snprintf (buf, size, "{%s%d.%s}%s", prefix, reg0, qlf_name, tb);
+	  snprintf (buf, size, "{%s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    tb);
 	  break;
 	case 2:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s}%s", prefix, reg0, qlf_name,
-		    prefix, reg1, qlf_name, tb);
+	  snprintf (buf, size, "{%s, %s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg1, qlf_name),
+		    tb);
 	  break;
 	case 3:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, tb);
+	  snprintf (buf, size, "{%s, %s, %s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg1, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg2, qlf_name),
+		    tb);
 	  break;
 	case 4:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, prefix, reg3, qlf_name, tb);
+	  snprintf (buf, size, "{%s, %s, %s, %s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg1, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg2, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg3, qlf_name),
+		    tb);
 	  break;
 	}
     }
@@ -3103,32 +3204,41 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
 static void
 print_immediate_offset_address (char *buf, size_t size,
 				const aarch64_opnd_info *opnd,
-				const char *base)
+				const char *base,
+				struct aarch64_styler *styler)
 {
   if (opnd->addr.writeback)
     {
       if (opnd->addr.preind)
         {
 	  if (opnd->type == AARCH64_OPND_ADDR_SIMM10 && !opnd->addr.offset.imm)
-            snprintf (buf, size, "[%s]!", base);
+	    snprintf (buf, size, "[%s]!", style_reg (styler, base));
           else
-	    snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
+	    snprintf (buf, size, "[%s, %s]!",
+		      style_reg (styler, base),
+		      style_imm (styler, "#%d", opnd->addr.offset.imm));
         }
       else
-	snprintf (buf, size, "[%s], #%d", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "[%s], %s",
+		  style_reg (styler, base),
+		  style_imm (styler, "#%d", opnd->addr.offset.imm));
     }
   else
     {
       if (opnd->shifter.operator_present)
 	{
 	  assert (opnd->shifter.kind == AARCH64_MOD_MUL_VL);
-	  snprintf (buf, size, "[%s, #%d, mul vl]",
-		    base, opnd->addr.offset.imm);
+	  snprintf (buf, size, "[%s, %s, %s]",
+		    style_reg (styler, base),
+		    style_imm (styler, "#%d", opnd->addr.offset.imm),
+		    style_sub_mnem (styler, "mul vl"));
 	}
       else if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "[%s, %s]",
+		  style_reg (styler, base),
+		  style_imm (styler, "#%d", opnd->addr.offset.imm));
       else
-	snprintf (buf, size, "[%s]", base);
+	snprintf (buf, size, "[%s]", style_reg (styler, base));
     }
 }
 
@@ -3138,9 +3248,10 @@ print_immediate_offset_address (char *buf, size_t size,
 static void
 print_register_offset_address (char *buf, size_t size,
 			       const aarch64_opnd_info *opnd,
-			       const char *base, const char *offset)
+			       const char *base, const char *offset,
+			       struct aarch64_styler *styler)
 {
-  char tb[16];			/* Temporary buffer.  */
+  char tb[32];			/* Temporary buffer.  */
   bool print_extend_p = true;
   bool print_amount_p = true;
   const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
@@ -3161,16 +3272,20 @@ print_register_offset_address (char *buf, size_t size,
   if (print_extend_p)
     {
       if (print_amount_p)
-	snprintf (tb, sizeof (tb), ", %s #%" PRIi64, shift_name,
+	snprintf (tb, sizeof (tb), ", %s %s",
+		  style_sub_mnem (styler, shift_name),
+		  style_imm (styler, "#%" PRIi64,
   /* PR 21096: The %100 is to silence a warning about possible truncation.  */
-		  (opnd->shifter.amount % 100));
+			     (opnd->shifter.amount % 100)));
       else
-	snprintf (tb, sizeof (tb), ", %s", shift_name);
+	snprintf (tb, sizeof (tb), ", %s",
+		  style_sub_mnem (styler, shift_name));
     }
   else
     tb[0] = '\0';
 
-  snprintf (buf, size, "[%s, %s%s]", base, offset, tb);
+  snprintf (buf, size, "[%s, %s%s]", style_reg (styler, base),
+	    style_reg (styler, offset), tb);
 }
 
 /* Print ZA tiles from imm8 in ZERO instruction.
@@ -3183,7 +3298,8 @@ print_register_offset_address (char *buf, size_t size,
     * An all-zeros immediate is disassembled as an empty list { }.
 */
 static void
-print_sme_za_list(char *buf, size_t size, int mask)
+print_sme_za_list (char *buf, size_t size, int mask,
+		   struct aarch64_styler *styler)
 {
   const char* zan[] = { "za",    "za0.h", "za1.h", "za0.s",
                         "za1.s", "za2.s", "za3.s", "za0.d",
@@ -3203,9 +3319,9 @@ print_sme_za_list(char *buf, size_t size, int mask)
         {
           mask &= ~zan_v[i];
           if (k > 1)
-            k += snprintf (buf + k, size - k, ", %s", zan[i]);
-          else
-            k += snprintf (buf + k, size - k, "%s", zan[i]);
+	    k += snprintf (buf + k, size - k, ", ");
+
+	  k += snprintf (buf + k, size - k, style_reg (styler, zan[i]));
         }
       if (mask == 0)
         break;
@@ -3230,7 +3346,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 		       const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
 		       bfd_vma *address, char** notes,
 		       char *comment, size_t comment_size,
-		       aarch64_feature_set features)
+		       aarch64_feature_set features,
+		       struct aarch64_styler *styler)
 {
   unsigned int i, num_conds;
   const char *name = NULL;
@@ -3278,8 +3395,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	break;
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
-      snprintf (buf, size, "%s",
-		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+      snprintf (buf, size,
+		style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						     opnd->qualifier, 0)));
       break;
 
     case AARCH64_OPND_Rd_SP:
@@ -3291,8 +3409,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      || opnd->qualifier == AARCH64_OPND_QLF_WSP
 	      || opnd->qualifier == AARCH64_OPND_QLF_X
 	      || opnd->qualifier == AARCH64_OPND_QLF_SP);
-      snprintf (buf, size, "%s",
-		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 1));
+      snprintf (buf, size,
+		style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						     opnd->qualifier, 1)));
       break;
 
     case AARCH64_OPND_Rm_EXT:
@@ -3311,33 +3430,36 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	  if (opnd->shifter.amount == 0)
 	    {
 	      /* Shifter omitted.  */
-	      snprintf (buf, size, "%s",
-			get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+	      snprintf (buf, size,
+			style_reg (styler,
+				   get_int_reg_name (opnd->reg.regno,
+						     opnd->qualifier, 0)));
 	      break;
 	    }
 	}
       if (opnd->shifter.amount)
-	snprintf (buf, size, "%s, %s #%" PRIi64,
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
-		  aarch64_operand_modifiers[kind].name,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0)),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[kind].name),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       else
 	snprintf (buf, size, "%s, %s",
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
-		  aarch64_operand_modifiers[kind].name);
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0)),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[kind].name));
       break;
 
     case AARCH64_OPND_Rm_SFT:
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
       if (opnd->shifter.amount == 0 && opnd->shifter.kind == AARCH64_MOD_LSL)
-	snprintf (buf, size, "%s",
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+	snprintf (buf, size,
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						       opnd->qualifier, 0)));
       else
-	snprintf (buf, size, "%s, %s #%" PRIi64,
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
-		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0)),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[opnd->shifter.kind].name),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       break;
 
     case AARCH64_OPND_Fd:
@@ -3353,16 +3475,19 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Vd:
     case AARCH64_OPND_SVE_Vm:
     case AARCH64_OPND_SVE_Vn:
-      snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reg.regno);
+      snprintf (buf, size,
+		style_reg (styler, "%s%d",
+			   aarch64_get_qualifier_name (opnd->qualifier),
+			   opnd->reg.regno));
       break;
 
     case AARCH64_OPND_Va:
     case AARCH64_OPND_Vd:
     case AARCH64_OPND_Vn:
     case AARCH64_OPND_Vm:
-      snprintf (buf, size, "v%d.%s", opnd->reg.regno,
-		aarch64_get_qualifier_name (opnd->qualifier));
+      snprintf (buf, size,
+		style_reg (styler, "v%d.%s", opnd->reg.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_Ed:
@@ -3370,21 +3495,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Em:
     case AARCH64_OPND_Em16:
     case AARCH64_OPND_SM3_IMM2:
-      snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
-		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+      snprintf (buf, size, "%s[%s]",
+		style_reg (styler, "v%d.%s", opnd->reglane.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+		style_imm (styler, "%" PRIi64, opnd->reglane.index));
       break;
 
     case AARCH64_OPND_VdD1:
     case AARCH64_OPND_VnD1:
-      snprintf (buf, size, "v%d.d[1]", opnd->reg.regno);
+      snprintf (buf, size, "%s[%s]",
+		style_reg (styler, "v%d.d", opnd->reg.regno),
+		style_imm (styler, "1"));
       break;
 
     case AARCH64_OPND_LVn:
     case AARCH64_OPND_LVt:
     case AARCH64_OPND_LVt_AL:
     case AARCH64_OPND_LEt:
-      print_register_list (buf, size, opnd, "v");
+      print_register_list (buf, size, opnd, "v", styler);
       break;
 
     case AARCH64_OPND_SVE_Pd:
@@ -3397,14 +3525,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Pt:
     case AARCH64_OPND_SME_Pm:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "p%d", opnd->reg.regno);
+	snprintf (buf, size, style_reg (styler, "p%d", opnd->reg.regno));
       else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
 	       || opnd->qualifier == AARCH64_OPND_QLF_P_M)
-	snprintf (buf, size, "p%d/%s", opnd->reg.regno,
-		  aarch64_get_qualifier_name (opnd->qualifier));
+	snprintf (buf, size,
+		  style_reg (styler, "p%d/%s", opnd->reg.regno,
+			     aarch64_get_qualifier_name (opnd->qualifier)));
       else
-	snprintf (buf, size, "p%d.%s", opnd->reg.regno,
-		  aarch64_get_qualifier_name (opnd->qualifier));
+	snprintf (buf, size,
+		  style_reg (styler, "p%d.%s", opnd->reg.regno,
+			     aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_SVE_Za_5:
@@ -3415,15 +3545,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zn:
     case AARCH64_OPND_SVE_Zt:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "z%d", opnd->reg.regno);
+	snprintf (buf, size, style_reg (styler, "z%d", opnd->reg.regno));
       else
-	snprintf (buf, size, "z%d.%s", opnd->reg.regno,
-		  aarch64_get_qualifier_name (opnd->qualifier));
+	snprintf (buf, size,
+		  style_reg (styler, "z%d.%s", opnd->reg.regno,
+			     aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_SVE_ZnxN:
     case AARCH64_OPND_SVE_ZtxN:
-      print_register_list (buf, size, opnd, "z");
+      print_register_list (buf, size, opnd, "z", styler);
       break;
 
     case AARCH64_OPND_SVE_Zm3_INDEX:
@@ -3432,55 +3563,60 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zm4_11_INDEX:
     case AARCH64_OPND_SVE_Zm4_INDEX:
     case AARCH64_OPND_SVE_Zn_INDEX:
-      snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
-		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+      snprintf (buf, size, "%s[%s]",
+		style_reg (styler, "z%d.%s", opnd->reglane.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+		style_imm (styler, "%" PRIi64, opnd->reglane.index));
       break;
 
     case AARCH64_OPND_SME_ZAda_2b:
     case AARCH64_OPND_SME_ZAda_3b:
-      snprintf (buf, size, "za%d.%s", opnd->reg.regno,
-                aarch64_get_qualifier_name (opnd->qualifier));
+      snprintf (buf, size,
+		style_reg (styler, "za%d.%s", opnd->reg.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_SME_ZA_HV_idx_src:
     case AARCH64_OPND_SME_ZA_HV_idx_dest:
     case AARCH64_OPND_SME_ZA_HV_idx_ldstr:
-      snprintf (buf, size, "%sza%d%c.%s[w%d, %d]%s",
-                opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "{" : "",
-                opnd->za_tile_vector.regno,
-                opnd->za_tile_vector.v == 1 ? 'v' : 'h',
-                aarch64_get_qualifier_name (opnd->qualifier),
-                opnd->za_tile_vector.index.regno,
-                opnd->za_tile_vector.index.imm,
-                opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "}" : "");
+      snprintf (buf, size, "%s%s[%s, %s]%s",
+		opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "{" : "",
+		style_reg (styler, "za%d%c.%s",
+			   opnd->za_tile_vector.regno,
+			   opnd->za_tile_vector.v == 1 ? 'v' : 'h',
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+		style_reg (styler, "w%d", opnd->za_tile_vector.index.regno),
+		style_imm (styler, "%d", opnd->za_tile_vector.index.imm),
+		opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "}" : "");
       break;
 
     case AARCH64_OPND_SME_list_of_64bit_tiles:
-      print_sme_za_list (buf, size, opnd->reg.regno);
+      print_sme_za_list (buf, size, opnd->reg.regno, styler);
       break;
 
     case AARCH64_OPND_SME_ZA_array:
-      snprintf (buf, size, "za[w%d, %d]",
-                opnd->za_tile_vector.index.regno,
-                opnd->za_tile_vector.index.imm);
+      snprintf (buf, size, "%s[%s, %s]",
+		style_reg (styler, "za"),
+		style_reg (styler, "w%d", opnd->za_tile_vector.index.regno),
+		style_imm (styler, "%d", opnd->za_tile_vector.index.imm));
       break;
 
     case AARCH64_OPND_SME_SM_ZA:
-      snprintf (buf, size, "%s", opnd->reg.regno == 's' ? "sm" : "za");
+      snprintf (buf, size,
+		style_reg (styler, opnd->reg.regno == 's' ? "sm" : "za"));
       break;
 
     case AARCH64_OPND_SME_PnT_Wm_imm:
-      snprintf (buf, size, "p%d.%s[w%d, %d]",
-                opnd->za_tile_vector.regno,
-                aarch64_get_qualifier_name (opnd->qualifier),
-                opnd->za_tile_vector.index.regno,
-                opnd->za_tile_vector.index.imm);
+      snprintf (buf, size, "%s[%s, %s]",
+		style_reg (styler, "p%d.%s", opnd->za_tile_vector.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+                style_reg (styler, "w%d", opnd->za_tile_vector.index.regno),
+                style_imm (styler, "%d", opnd->za_tile_vector.index.imm));
       break;
 
     case AARCH64_OPND_CRn:
     case AARCH64_OPND_CRm:
-      snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, style_reg (styler, "C%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_IDX:
@@ -3521,7 +3657,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_IMM_ROT1:
     case AARCH64_OPND_SVE_IMM_ROT2:
     case AARCH64_OPND_SVE_IMM_ROT3:
-      snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_SVE_I1_HALF_ONE:
@@ -3530,7 +3666,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       {
 	single_conv_t c;
 	c.i = opnd->imm.value;
-	snprintf (buf, size, "#%.1f", c.f);
+	snprintf (buf, size, style_imm (styler, "#%.1f", c.f));
 	break;
       }
 
@@ -3541,9 +3677,10 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[enum_value]);
+	snprintf (buf, size,
+		  style_reg (styler, aarch64_sve_pattern_array[enum_value]));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_SVE_PATTERN_SCALED:
@@ -3554,15 +3691,19 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[opnd->imm.value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[opnd->imm.value]);
+	snprintf (buf, size,
+		  style_reg (styler,
+			     aarch64_sve_pattern_array[opnd->imm.value]));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, style_imm (styler, "#%" PRIi64, opnd->imm.value));
       if (opnd->shifter.operator_present)
 	{
 	  size_t len = strlen (buf);
-	  snprintf (buf + len, size - len, ", %s #%" PRIi64,
-		    aarch64_operand_modifiers[opnd->shifter.kind].name,
-		    opnd->shifter.amount);
+	  const char *shift_name
+	    = aarch64_operand_modifiers[opnd->shifter.kind].name;
+	  snprintf (buf + len, size - len, ", %s %s",
+		    style_sub_mnem (styler, shift_name),
+		    style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
 	}
       break;
 
@@ -3570,9 +3711,10 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
       if (aarch64_sve_prfop_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_prfop_array[enum_value]);
+	snprintf (buf, size,
+		  style_reg (styler, aarch64_sve_prfop_array[enum_value]));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_IMM_MOV:
@@ -3581,12 +3723,13 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	case 4:	/* e.g. MOV Wd, #<imm32>.  */
 	    {
 	      int imm32 = opnd->imm.value;
-	      snprintf (buf, size, "#0x%-20x", imm32);
+	      snprintf (buf, size, style_imm (styler, "#0x%-20x", imm32));
 	      snprintf (comment, comment_size, "#%d", imm32);
 	    }
 	  break;
 	case 8:	/* e.g. MOV Xd, #<imm64>.  */
-	  snprintf (buf, size, "#0x%-20" PRIx64, opnd->imm.value);
+	  snprintf (buf, size, style_imm (styler, "#0x%-20" PRIx64,
+					  opnd->imm.value));
 	  snprintf (comment, comment_size, "#%" PRIi64, opnd->imm.value);
 	  break;
 	default:
@@ -3596,7 +3739,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_FPIMM0:
-      snprintf (buf, size, "#0.0");
+      snprintf (buf, size, style_imm (styler, "#0.0"));
       break;
 
     case AARCH64_OPND_LIMM:
@@ -3606,30 +3749,37 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_LIMM:
     case AARCH64_OPND_SVE_LIMM_MOV:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value),
+		  style_sub_mnem (styler, "lsl"),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       else
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size,
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_SIMD_IMM:
     case AARCH64_OPND_SIMD_IMM_SFT:
       if ((! opnd->shifter.amount && opnd->shifter.kind == AARCH64_MOD_LSL)
 	  || opnd->shifter.kind == AARCH64_MOD_NONE)
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size,
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value));
       else
-	snprintf (buf, size, "#0x%" PRIx64 ", %s #%" PRIi64, opnd->imm.value,
-		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[opnd->shifter.kind].name),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       break;
 
     case AARCH64_OPND_SVE_AIMM:
     case AARCH64_OPND_SVE_ASIMM:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_imm (styler, "#%" PRIi64, opnd->imm.value),
+		  style_sub_mnem (styler, "lsl"),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_FPIMM:
@@ -3641,21 +3791,21 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	    {
 	      half_conv_t c;
 	      c.i = expand_fp_imm (2, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size, style_imm (styler, "#%.18e", c.f));
 	    }
 	  break;
 	case 4:	/* e.g. FMOV <Vd>.4S, #<imm>.  */
 	    {
 	      single_conv_t c;
 	      c.i = expand_fp_imm (4, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size, style_imm (styler, "#%.18e", c.f));
 	    }
 	  break;
 	case 8:	/* e.g. FMOV <Sd>, #<imm>.  */
 	    {
 	      double_conv_t c;
 	      c.i = expand_fp_imm (8, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.d);
+	      snprintf (buf, size, style_imm (styler, "#%.18e", c.d));
 	    }
 	  break;
 	default:
@@ -3676,12 +3826,13 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      (int64_t) get_optional_operand_default_value (opcode)))
 	/* Omit the operand, e.g. DCPS1.  */
 	break;
-      snprintf (buf, size, "#0x%x", (unsigned int)opnd->imm.value);
+      snprintf (buf, size,
+		style_imm (styler, "#0x%x", (unsigned int) opnd->imm.value));
       break;
 
     case AARCH64_OPND_COND:
     case AARCH64_OPND_COND1:
-      snprintf (buf, size, "%s", opnd->cond->names[0]);
+      snprintf (buf, size, style_sub_mnem (styler, opnd->cond->names[0]));
       num_conds = ARRAY_SIZE (opnd->cond->names);
       for (i = 1; i < num_conds && opnd->cond->names[i]; ++i)
 	{
@@ -3706,7 +3857,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, style_addr (styler, "#0x%" PRIx64 , addr));
       break;
 
     case AARCH64_OPND_ADDR_PCREL14:
@@ -3722,7 +3873,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, style_addr (styler, "#0x%" PRIx64, addr));
       break;
 
     case AARCH64_OPND_ADDR_SIMPLE:
@@ -3732,12 +3883,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (opnd->type == AARCH64_OPND_SIMD_ADDR_POST)
 	{
 	  if (opnd->addr.offset.is_reg)
-	    snprintf (buf, size, "[%s], x%d", name, opnd->addr.offset.regno);
+	    snprintf (buf, size, "[%s], %s",
+		      style_reg (styler, name),
+		      style_reg (styler, "x%d", opnd->addr.offset.regno));
 	  else
-	    snprintf (buf, size, "[%s], #%d", name, opnd->addr.offset.imm);
+	    snprintf (buf, size, "[%s], %s",
+		      style_reg (styler, name),
+		      style_imm (styler, "#%d", opnd->addr.offset.imm));
 	}
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "[%s]", style_reg (styler, name));
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
@@ -3753,14 +3908,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RX_LSL3:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_offset_int_reg_name (opnd));
+	 get_offset_int_reg_name (opnd), styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZX:
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0));
+	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0), styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_RZ:
@@ -3777,7 +3932,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 styler);
       break;
 
     case AARCH64_OPND_ADDR_SIMM7:
@@ -3801,7 +3957,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RI_U6x4:
     case AARCH64_OPND_SVE_ADDR_RI_U6x8:
       print_immediate_offset_address
-	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1));
+	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
+	 styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZI_U5:
@@ -3810,7 +3967,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
       print_immediate_offset_address
 	(buf, size, opnd,
-	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
+	 styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
@@ -3819,15 +3977,18 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 styler);
       break;
 
     case AARCH64_OPND_ADDR_UIMM12:
       name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
       if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", name, opnd->addr.offset.imm);
+	snprintf (buf, size, "[%s, %s]",
+		  style_reg (styler, name),
+		  style_imm (styler, "#%d", opnd->addr.offset.imm));
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "[%s]", style_reg (styler, name));
       break;
 
     case AARCH64_OPND_SYSREG:
@@ -3866,14 +4027,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	}
 
       if (name)
-	snprintf (buf, size, "%s", name);
+	snprintf (buf, size, style_reg (styler, name));
       else
 	{
 	  /* Implementation defined system register.  */
 	  unsigned int value = opnd->sysreg.value;
-	  snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
-		    (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
-		    value & 0x7);
+	  snprintf (buf, size,
+		    style_reg (styler, "s%u_%u_c%u_c%u_%u",
+			       (value >> 14) & 0x3, (value >> 11) & 0x7,
+			       (value >> 7) & 0xf, (value >> 3) & 0xf,
+			       value & 0x7));
 	}
       break;
 
@@ -3891,7 +4054,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
             break;
           }
       assert (aarch64_pstatefields[i].name);
-      snprintf (buf, size, "%s", aarch64_pstatefields[i].name);
+      snprintf (buf, size, style_reg (styler, aarch64_pstatefields[i].name));
       break;
 
     case AARCH64_OPND_SYSREG_AT:
@@ -3899,12 +4062,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SYSREG_IC:
     case AARCH64_OPND_SYSREG_TLBI:
     case AARCH64_OPND_SYSREG_SR:
-      snprintf (buf, size, "%s", opnd->sysins_op->name);
+      snprintf (buf, size, style_reg (styler, opnd->sysins_op->name));
       break;
 
     case AARCH64_OPND_BARRIER:
     case AARCH64_OPND_BARRIER_DSB_NXS:
-      snprintf (buf, size, "%s", opnd->barrier->name);
+      {
+	if (opnd->barrier->name[0] == '#')
+	  snprintf (buf, size, style_imm (styler, opnd->barrier->name));
+	else
+	  snprintf (buf, size, style_sub_mnem (styler, opnd->barrier->name));
+      }
       break;
 
     case AARCH64_OPND_BARRIER_ISB:
@@ -3912,34 +4080,38 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (! optional_operand_p (opcode, idx)
 	  || (opnd->barrier->value
 	      != get_optional_operand_default_value (opcode)))
-	snprintf (buf, size, "#0x%x", opnd->barrier->value);
+	snprintf (buf, size, style_imm (styler, "#0x%x", opnd->barrier->value));
       break;
 
     case AARCH64_OPND_PRFOP:
       if (opnd->prfop->name != NULL)
-	snprintf (buf, size, "%s", opnd->prfop->name);
+	snprintf (buf, size, style_sub_mnem (styler, opnd->prfop->name));
       else
-	snprintf (buf, size, "#0x%02x", opnd->prfop->value);
+	snprintf (buf, size, style_imm (styler, "#0x%02x",
+					opnd->prfop->value));
       break;
 
     case AARCH64_OPND_BARRIER_PSB:
-      snprintf (buf, size, "csync");
+      snprintf (buf, size, style_sub_mnem (styler, "csync"));
       break;
 
     case AARCH64_OPND_BTI_TARGET:
       if ((HINT_FLAG (opnd->hint_option->value) & HINT_OPD_F_NOPRINT) == 0)
-	snprintf (buf, size, "%s", opnd->hint_option->name);
+	snprintf (buf, size, style_sub_mnem (styler, opnd->hint_option->name));
       break;
 
     case AARCH64_OPND_MOPS_ADDR_Rd:
     case AARCH64_OPND_MOPS_ADDR_Rs:
       snprintf (buf, size, "[%s]!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+		style_reg (styler,
+			   get_int_reg_name (opnd->reg.regno,
+					     AARCH64_OPND_QLF_X, 0)));
       break;
 
     case AARCH64_OPND_MOPS_WB_Rn:
       snprintf (buf, size, "%s!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+		style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						     AARCH64_OPND_QLF_X, 0)));
       break;
 
     default:
-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCHv3 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-07-07 10:23           ` [PATCHv3 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
@ 2022-07-07 10:44             ` Andrew Burgess
  0 siblings, 0 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-07-07 10:44 UTC (permalink / raw)
  To: Andrew Burgess via Binutils, binutils

Andrew Burgess via Binutils <binutils@sourceware.org> writes:

<snip>

> diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
> index 1c93f836020..b6de4c96baf 100644
> --- a/opcodes/aarch64-opc.c
> +++ b/opcodes/aarch64-opc.c
> @@ -35,6 +35,36 @@
>  int debug_dump = false;
>  #endif /* DEBUG_AARCH64 */
>  
> +/* ... */
> +static int
> +debug_snprintf (char *str, size_t size, int lineno, const char *fmt, ...)
> +{
> +  char tmp[1024];
> +  va_list ap;
> +  int res;
> +  static bool init;
> +  static bool debug_p;
> +  if (!init)
> +    {
> +      debug_p = getenv ("DEBUG_AARCH64") != NULL;
> +      init = true;
> +    }
> +
> +  if (debug_p)
> +    snprintf (tmp, sizeof (tmp), "<%d:%s>", lineno, fmt);	/* IGNORE.  */
> +  else
> +    snprintf (tmp, sizeof (tmp), "%s", fmt);			/* IGNORE.  */
> +
> +  va_start (ap, fmt);
> +  res = vsnprintf (str, size, tmp, ap);
> +  va_end (ap);
> +  return res;
> +}
> +
> +#define snprintf(BUF,LEN,FMT,...)                              \
> +  debug_snprintf (BUF, LEN, __LINE__, FMT, ##__VA_ARGS__)
> +

Once again, I've manged to leave this debug code in the posted patch.  I
even remembered that I needed to remove this, then did one final review
of the patch .... and forgot to actually remove it :/

I've now deleted this code from my local tree, and if this patch is
approved, this will not be included in the push.

Again ... I'm sorry.

Thanks,
Andrew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv4 0/2] AArch64 libopcodes styling
  2022-07-07 10:23         ` [PATCHv3 0/2] AArch64 libopcodes styling Andrew Burgess
  2022-07-07 10:23           ` [PATCHv3 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
  2022-07-07 10:23           ` [PATCHv3 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
@ 2022-07-08 10:25           ` Andrew Burgess
  2022-07-08 10:25             ` [PATCHv4 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
                               ` (2 more replies)
  2 siblings, 3 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-07-08 10:25 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

Changed since v3:

  - Patch #1 is unchanged,

  - Removed debug code that was accidentally left in patch #2,

  - Patch #2 now sets the disassemble_info::created_styled_output flag
    correctly in disassembler.c.

Changes since v2:

  - Patch #1 is unchanged,

  - Patch #2, now with more OBSTACK!  This patch is pretty much a
    complete rewrite from the gound up based on Richard's feedback.
    The new iteration makes use of obstacks (in aarch64-dis.c and
    tc-aarch64.c) to format each chunk of disassembler output.  These
    chunks are then combined in aarch64-opc.c as required.

Changes since v1:

  - Original patch #1 has been merged,

  - New patch #1 adds a dis_style_sub_mnemonic style and updates
    objdump to handle this style,

  - Patch #2 has been updated to make use of the new style.

---

Andrew Burgess (2):
  opcodes: add new sub-mnemonic disassembler style
  libopcodes/aarch64: add support for disassembler styling

 binutils/objdump.c       |   2 +
 gas/config/tc-aarch64.c  |  45 +++-
 include/dis-asm.h        |   7 +
 include/opcode/aarch64.h |  28 ++-
 opcodes/aarch64-dis.c    | 247 +++++++++++++++++++---
 opcodes/aarch64-opc.c    | 440 ++++++++++++++++++++++++++-------------
 opcodes/disassemble.c    |   1 +
 7 files changed, 587 insertions(+), 183 deletions(-)

-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv4 1/2] opcodes: add new sub-mnemonic disassembler style
  2022-07-08 10:25           ` [PATCHv4 0/2] AArch64 libopcodes styling Andrew Burgess
@ 2022-07-08 10:25             ` Andrew Burgess
  2022-07-26 13:54               ` Nick Clifton
  2022-07-08 10:25             ` [PATCHv4 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
  2022-07-19 12:52             ` [PATCHv4 0/2] AArch64 libopcodes styling Andrew Burgess
  2 siblings, 1 reply; 31+ messages in thread
From: Andrew Burgess @ 2022-07-08 10:25 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

When adding libopcodes disassembler styling support for AArch64, it
feels like the results would be improved by having a new sub-mnemonic
style.  This will be used in cases like:

  add    w16, w7, w1, uxtb #2
                      ^^^^----- Here

And:

  cinc   w0, w1, ne
                 ^^----- Here

This commit just adds the new style, and prepares objdump to handle
the style.  A later commit will add AArch64 styling, and will actually
make use of the style.

As this style is currently unused, there should be no user visible
changes after this commit.
---
 binutils/objdump.c | 2 ++
 include/dis-asm.h  | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/binutils/objdump.c b/binutils/objdump.c
index 67824053527..4076587151c 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -2167,6 +2167,7 @@ objdump_color_for_disassembler_style (enum disassembler_style style)
 	{
 	case dis_style_symbol: color = 32; break;
         case dis_style_assembler_directive:
+	case dis_style_sub_mnemonic:
 	case dis_style_mnemonic: color = 33; break;
 	case dis_style_register: color = 34; break;
 	case dis_style_address:
@@ -2185,6 +2186,7 @@ objdump_color_for_disassembler_style (enum disassembler_style style)
 	{
 	case dis_style_symbol: color = 40; break;
         case dis_style_assembler_directive:
+	case dis_style_sub_mnemonic:
 	case dis_style_mnemonic: color = 142; break;
 	case dis_style_register: color = 27; break;
 	case dis_style_address:
diff --git a/include/dis-asm.h b/include/dis-asm.h
index 4f91df12498..f1a83dc84e5 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -62,6 +62,13 @@ enum disassembler_style
      instructions.  */
   dis_style_mnemonic,
 
+  /* Some architectures include additional mnemonic like fields within the
+     instruction operands, e.g. on aarch64 'add w16, w7, w1, lsl #2' where
+     the 'lsl' is an additional piece of text that describes how the
+     instruction should behave.  This sub-mnemonic style can be used for
+     these pieces of text.  */
+  dis_style_sub_mnemonic,
+
   /* For things that aren't real machine instructions, but rather
      assembler directives, e.g. .byte, etc.  */
   dis_style_assembler_directive,
-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv4 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-07-08 10:25           ` [PATCHv4 0/2] AArch64 libopcodes styling Andrew Burgess
  2022-07-08 10:25             ` [PATCHv4 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
@ 2022-07-08 10:25             ` Andrew Burgess
  2022-07-19 15:33               ` Richard Earnshaw
  2022-07-19 12:52             ` [PATCHv4 0/2] AArch64 libopcodes styling Andrew Burgess
  2 siblings, 1 reply; 31+ messages in thread
From: Andrew Burgess @ 2022-07-08 10:25 UTC (permalink / raw)
  To: binutils; +Cc: Andrew Burgess

This commit enables disassembler styling for AArch64.  After this
commit it is possible to have objdump style AArch64 disassembler
output (using --disassembler-color option).  Once the required GDB
patches are merged, GDB will also style the disassembler output.

The changes to support styling are mostly split between two files
opcodes/aarch64-dis.c and opcodes/aarch64-opc.c.

The entry point for the AArch64 disassembler can be found in
aarch64-dis.c, this file handles printing the instruction mnemonics,
and assembler directives (e.g. '.byte', '.word', etc).  Some operands,
mostly relating to assembler directives are also printed from this
file.  This commit changes all of this to pass through suitable
styling information.

However, for most "normal" instructions, the instruction operands are
printed using a two step process.  From aarch64-dis.c, in the
print_operands function, the function aarch64_print_operand is called,
this function is in aarch64-opc.c, and converts an instruction operand
into a string.  Then, back in print_operands (aarch64-dis.c), the
operand string is printed.

Unfortunately, the string returned by aarch64_print_operand can be
quite complex, it will include syntax elements, like '[' and ']', in
addition to register names and immediate values.  In some cases, a
single operand will expand into what will appear (to the user) as
multiple operands separated with a ','.

This makes the task of styling more complex, all these different
components need to by styled differently, so we need to get the
styling information out of aarch64_print_operand in some way.

The solution that I propose here is similar to the solution that I
used for the i386 disassembler.

Currently, aarch64_print_operand uses snprintf to write the operand
text into a buffer provided by the caller.

What I propose is that we pass an extra argument to the
aarch64_print_operand function, this argument will be a structure, the
structure contains a callback function and some state.

When aarch64_print_operand needs to format part of its output this can
be done by using the callback function within the new structure, this
callback returns a string with special embedded markers that indicate
which mode should be used for each piece of text.  Back in
aarch64-dis.c we can spot these special style markers and use this to
split the disassembler output up and apply the correct style to each
piece.

To make aarch64-opc.c clearer a series of new static functions have
been added, e.g. 'style_reg', 'style_imm', etc.  Each of these
functions formats a piece of text in a different style, 'register' and
'immediate' in this case.

Here's an example taken from aarch64-opc.c of the new functions in
use:

    snprintf (buf, size, "[%s, %s]!",
              style_reg (styler, base),
              style_imm (styler, "#%d", opnd->addr.offset.imm));

The aarch64_print_operand function is also called from the assembler
to aid in printing diagnostic messages.  Right now I have no plans to
add styling to the assembler output, and so, the callback function
used in the assembler ignores the styling information and just returns
an plain string.

I've used the source files in gas/testsuite/gas/aarch64/ for testing,
and have manually gone through and checked that the styling looks
reasonable, however, I'm not an AArch64 expert, so it is possible that
the odd piece is styled incorrectly.  Please point out any mistakes
I've made.

With objdump disassembler color turned off, there should be no change
in the output after this commit.
---
 gas/config/tc-aarch64.c  |  45 +++-
 include/opcode/aarch64.h |  28 ++-
 opcodes/aarch64-dis.c    | 247 +++++++++++++++++++---
 opcodes/aarch64-opc.c    | 440 ++++++++++++++++++++++++++-------------
 opcodes/disassemble.c    |   1 +
 5 files changed, 578 insertions(+), 183 deletions(-)

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 779db31828b..dc154b96fce 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -5347,6 +5347,41 @@ assign_qualifier_sequence (aarch64_inst *instr,
     instr->operands[i].qualifier = *qualifiers;
 }
 
+/* Callback used by aarch64_print_operand to apply STYLE to the
+   disassembler output created from FMT and ARGS.  The STYLER object holds
+   any required state.  Must return a pointer to a string (created from FMT
+   and ARGS) that will continue to be valid until the complete disassembled
+   instruction has been printed.
+
+   We don't currently add any styling to the output of the disassembler as
+   used within assembler error messages, and so STYLE is ignored here.  A
+   new string is allocated on the obstack help within STYLER and returned
+   to the caller.  */
+
+static const char *aarch64_apply_style
+	(struct aarch64_styler *styler,
+	 enum disassembler_style style ATTRIBUTE_UNUSED,
+	 const char *fmt, va_list args)
+{
+  int res;
+  char *ptr;
+  struct obstack *stack = (struct obstack *) styler->state;
+  va_list ap;
+
+  /* Calculate the required space.  */
+  va_copy (ap, args);
+  res = vsnprintf (NULL, 0, fmt, ap);
+  va_end (ap);
+  gas_assert (res >= 0);
+
+  /* Allocate space on the obstack and format the result.  */
+  ptr = (char *) obstack_alloc (stack, res + 1);
+  res = vsnprintf (ptr, (res + 1), fmt, args);
+  gas_assert (res >= 0);
+
+  return ptr;
+}
+
 /* Print operands for the diagnosis purpose.  */
 
 static void
@@ -5354,6 +5389,12 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 		const aarch64_opnd_info *opnds)
 {
   int i;
+  struct aarch64_styler styler;
+  struct obstack content;
+  obstack_init (&content);
+
+  styler.apply_style = aarch64_apply_style;
+  styler.state = (void *) &content;
 
   for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
@@ -5371,7 +5412,7 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL,
-			     NULL, cmt, sizeof (cmt), cpu_variant);
+			     NULL, cmt, sizeof (cmt), cpu_variant, &styler);
 
       /* Delimiter.  */
       if (str[0] != '\0')
@@ -5389,6 +5430,8 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 	  strcat (buf, cmt);
 	}
     }
+
+  obstack_free (&content, NULL);
 }
 
 /* Send to stderr a string as information.  */
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 186ba9a4800..9477ac98f3b 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -27,6 +27,8 @@
 #include <assert.h>
 #include <stdlib.h>
 
+#include "dis-asm.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -1367,12 +1369,36 @@ aarch64_replace_opcode (struct aarch64_inst *,
 extern const aarch64_opcode *
 aarch64_get_opcode (enum aarch64_op);
 
+/* An instance of this structure is passed to aarch64_print_operand, and
+   the callback within this structure is used to apply styling to the
+   disassembler output.  This structure encapsulates the callback and a
+   state pointer.  */
+
+struct aarch64_styler
+{
+  /* The callback used to apply styling.  Returns a string created from FMT
+     and ARGS with STYLE applied to the string.  STYLER is a pointer back
+     to this object so that the callback can access the state member.
+
+     The string returned from this callback must remain valid until the
+     call to aarch64_print_operand has completed.  */
+  const char *(*apply_style) (struct aarch64_styler *styler,
+			      enum disassembler_style style,
+			      const char *fmt,
+			      va_list args);
+
+  /* A pointer to a state object which can be used by the apply_style
+     callback function.  */
+  void *state;
+};
+
 /* Generate the string representation of an operand.  */
 extern void
 aarch64_print_operand (char *, size_t, bfd_vma, const aarch64_opcode *,
 		       const aarch64_opnd_info *, int, int *, bfd_vma *,
 		       char **, char *, size_t,
-		       aarch64_feature_set features);
+		       aarch64_feature_set features,
+		       struct aarch64_styler *styler);
 
 /* Miscellaneous interface.  */
 
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index acaad28fdff..fa69b893f22 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -25,9 +25,18 @@
 #include "opintl.h"
 #include "aarch64-dis.h"
 #include "elf-bfd.h"
+#include "safe-ctype.h"
+#include "obstack.h"
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
 
 #define INSNLEN 4
 
+/* This character is used to encode style information within the output
+   buffers.  See get_style_text and print_operands for more details.  */
+#define STYLE_MARKER_CHAR '\002'
+
 /* Cached mapping symbol state.  */
 enum map_type
 {
@@ -3275,6 +3284,90 @@ aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst,
   return ERR_UND;
 }
 
+/* Return a short string to indicate a switch to STYLE.  These strings
+   will be embedded into the disassembled operand text (as produced by
+   aarch64_print_operand), and then spotted in the print_operands function
+   so that the disassembler output can be slit by style.  */
+
+static const char *
+get_style_text (enum disassembler_style style)
+{
+  static bool init = false;
+  static char formats[16][4];
+  unsigned num;
+
+  /* First time through we build a string for every possible format.  This
+     code relies on there being no more than 16 different styles (there's
+     an assert below for this).  */
+  if (!init)
+    {
+      int i;
+
+      for (i = 0; i <= 0xf; ++i)
+	{
+	  int res = snprintf (&formats[i][0], sizeof (formats[i]), "%c%x%c",
+			      STYLE_MARKER_CHAR, i, STYLE_MARKER_CHAR);
+	  assert (res == 3);
+	}
+
+      init = true;
+    }
+
+  /* Return the string that marks switching to STYLE.  */
+  num = (unsigned) style;
+  assert (style <= 0xf);
+  return formats[num];
+}
+
+/* Callback used by aarch64_print_operand to apply STYLE to the
+   disassembler output created from FMT and ARGS.  The STYLER object holds
+   any required state.  Must return a pointer to a string (created from FMT
+   and ARGS) that will continue to be valid until the complete disassembled
+   instruction has been printed.
+
+   We return a string that includes two embedded style markers, the first,
+   places at the start of the string, indicates a switch to STYLE, and the
+   second, placed at the end of the string, indicates a switch back to the
+   default text style.
+
+   Later, when we print the operand text we take care to collapse any
+   adjacent style markers, and to ignore any style markers that appear at
+   the very end of a complete operand string.  */
+
+static const char *aarch64_apply_style (struct aarch64_styler *styler,
+					enum disassembler_style style,
+					const char *fmt,
+					va_list args)
+{
+  int res;
+  char *ptr, *tmp;
+  struct obstack *stack = (struct obstack *) styler->state;
+  va_list ap;
+
+  /* These are the two strings for switching styles.  */
+  const char *style_on = get_style_text (style);
+  const char *style_off = get_style_text (dis_style_text);
+
+  /* Calculate space needed once FMT and ARGS are expanded.  */
+  va_copy (ap, args);
+  res = vsnprintf (NULL, 0, fmt, ap);
+  va_end (ap);
+  assert (res >= 0);
+
+  /* Allocate space on the obstack for the expanded FMT and ARGS, as well
+     as the two strings for switching styles, then write all of these
+     strings onto the obstack.  */
+  ptr = (char *) obstack_alloc (stack, res + strlen (style_on)
+				+ strlen (style_off) + 1);
+  tmp = stpcpy (ptr, style_on);
+  res = vsnprintf (tmp, (res + 1), fmt, args);
+  assert (res >= 0);
+  tmp += res;
+  strcpy (tmp, style_off);
+
+  return ptr;
+}
+
 /* Print operands.  */
 
 static void
@@ -3284,6 +3377,13 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
 {
   char *notes = NULL;
   int i, pcrel_p, num_printed;
+  struct aarch64_styler styler;
+  struct obstack content;
+  obstack_init (&content);
+
+  styler.apply_style = aarch64_apply_style;
+  styler.state = (void *) &content;
+
   for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
       char str[128];
@@ -3301,33 +3401,97 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
 			     &info->target, &notes, cmt, sizeof (cmt),
-			     arch_variant);
+			     arch_variant, &styler);
 
       /* Print the delimiter (taking account of omitted operand(s)).  */
       if (str[0] != '\0')
-	(*info->fprintf_func) (info->stream, "%s",
-			       num_printed++ == 0 ? "\t" : ", ");
+	(*info->fprintf_styled_func) (info->stream, dis_style_text, "%s",
+				      num_printed++ == 0 ? "\t" : ", ");
 
       /* Print the operand.  */
       if (pcrel_p)
 	(*info->print_address_func) (info->target, info);
       else
 	{
-	  (*info->fprintf_func) (info->stream, "%s", str);
-
-	  /* Print the comment.  This works because only the last operand
-	     ever adds a comment.  If that ever changes then we'll need to
-	     be smarter here.  */
-	  if (cmt[0] != '\0')
-	    (*info->fprintf_func) (info->stream, "\t// %s", cmt);
+	  /* This operand came from aarch64_print_operand, and will include
+	     embedded strings indicating which style each character should
+	     have.  In the following code we split the text based on
+	     CURR_STYLE, and call the styled print callback to print each
+	     block of text in the appropriate style.  */
+	  char *start, *curr;
+	  enum disassembler_style curr_style = dis_style_text;
+
+	  start = curr = str;
+	  do
+	    {
+	      if (*curr == '\0'
+		  || (*curr == STYLE_MARKER_CHAR
+		      && ISXDIGIT (*(curr + 1))
+		      && *(curr + 2) == STYLE_MARKER_CHAR))
+		{
+		  /* Output content between our START position and CURR.  */
+		  int len = curr - start;
+		  if (len > 0)
+		    {
+		      if ((*info->fprintf_styled_func) (info->stream,
+							curr_style,
+							"%.*s",
+							len, start) < 0)
+			break;
+		    }
+
+		  if (*curr == '\0')
+		    break;
+
+		  /* Skip over the initial STYLE_MARKER_CHAR.  */
+		  ++curr;
+
+		  /* Update the CURR_STYLE.  As there are less than 16
+		     styles, it is possible, that if the input is corrupted
+		     in some way, that we might set CURR_STYLE to an
+		     invalid value.  Don't worry though, we check for this
+		     situation.  */
+		  if (*curr >= '0' && *curr <= '9')
+		    curr_style = (enum disassembler_style) (*curr - '0');
+		  else if (*curr >= 'a' && *curr <= 'f')
+		    curr_style = (enum disassembler_style) (*curr - 'a' + 10);
+		  else
+		    curr_style = dis_style_text;
+
+		  /* Check for an invalid style having been selected.  This
+		     should never happen, but it doesn't hurt to be a
+		     little paranoid.  */
+		  if (curr_style > dis_style_comment_start)
+		    curr_style = dis_style_text;
+
+		  /* Skip the hex character, and the closing STYLE_MARKER_CHAR.  */
+		  curr += 2;
+
+		  /* Reset the START to after the style marker.  */
+		  start = curr;
+		}
+	      else
+		++curr;
+	    }
+	  while (true);
 	}
+
+      /* Print the comment.  This works because only the last operand ever
+	 adds a comment.  If that ever changes then we'll need to be
+	 smarter here.  */
+      if (cmt[0] != '\0')
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "\t// %s", cmt);
     }
 
     if (notes && !no_notes)
       {
 	*has_notes = true;
-	(*info->fprintf_func) (info->stream, "  // note: %s", notes);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "  // note: %s", notes);
       }
+
+    obstack_free (&content, NULL);
 }
 
 /* Set NAME to a copy of INST's mnemonic with the "." suffix removed.  */
@@ -3359,10 +3523,12 @@ print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
       char name[8];
 
       remove_dot_suffix (name, inst);
-      (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
+      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				    "%s.%s", name, inst->cond->names[0]);
     }
   else
-    (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
+    (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				  "%s", inst->opcode->name);
 }
 
 /* Decide whether we need to print a comment after the operands of
@@ -3379,9 +3545,10 @@ print_comment (const aarch64_inst *inst, struct disassemble_info *info)
       remove_dot_suffix (name, inst);
       num_conds = ARRAY_SIZE (inst->cond->names);
       for (i = 1; i < num_conds && inst->cond->names[i]; ++i)
-	(*info->fprintf_func) (info->stream, "%s %s.%s",
-			       i == 1 ? "  //" : ",",
-			       name, inst->cond->names[i]);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "%s %s.%s",
+				      i == 1 ? "  //" : ",",
+				      name, inst->cond->names[i]);
     }
 }
 
@@ -3398,28 +3565,30 @@ print_verifier_notes (aarch64_operand_error *detail,
      would not have succeeded.  We can safely ignore these.  */
   assert (detail->non_fatal);
 
-  (*info->fprintf_func) (info->stream, "  // note: ");
+  (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				"  // note: ");
   switch (detail->kind)
     {
     case AARCH64_OPDE_A_SHOULD_FOLLOW_B:
-      (*info->fprintf_func) (info->stream,
-			     _("this `%s' should have an immediately"
-			       " preceding `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("this `%s' should have an immediately"
+				      " preceding `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     case AARCH64_OPDE_EXPECTED_A_AFTER_B:
-      (*info->fprintf_func) (info->stream,
-			     _("expected `%s' after previous `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("expected `%s' after previous `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     default:
       assert (detail->error);
-      (*info->fprintf_func) (info->stream, "%s", detail->error);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    "%s", detail->error);
       if (detail->index >= 0)
-	(*info->fprintf_func) (info->stream, " at operand %d",
-			       detail->index + 1);
+	(*info->fprintf_styled_func) (info->stream, dis_style_text,
+				      " at operand %d", detail->index + 1);
       break;
     }
 }
@@ -3511,8 +3680,13 @@ print_insn_aarch64_word (bfd_vma pc,
     case ERR_NYI:
       /* Handle undefined instructions.  */
       info->insn_type = dis_noninsn;
-      (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
-			     word, err_msg[ret]);
+      (*info->fprintf_styled_func) (info->stream,
+				    dis_style_assembler_directive,
+				    ".inst\t");
+      (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
+				    "0x%08x", word);
+      (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				    " ; %s", err_msg[ret]);
       break;
     case ERR_OK:
       user_friendly_fixup (&inst);
@@ -3554,13 +3728,22 @@ print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
   switch (info->bytes_per_chunk)
     {
     case 1:
-      info->fprintf_func (info->stream, ".byte\t0x%02x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".byte\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%02x", word);
       break;
     case 2:
-      info->fprintf_func (info->stream, ".short\t0x%04x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".short\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%04x", word);
       break;
     case 4:
-      info->fprintf_func (info->stream, ".word\t0x%08x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".word\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%08x", word);
       break;
     default:
       abort ();
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 1c93f836020..2685e790b6f 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -3038,18 +3038,78 @@ expand_fp_imm (int size, uint32_t imm8)
   return imm;
 }
 
+/* Return a string based on FMT with the register style applied.  */
+
+static const char *
+style_reg (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_register, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
+/* Return a string based on FMT with the immediate style applied.  */
+
+static const char *
+style_imm (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_immediate, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
+/* Return a string based on FMT with the sub-mnemonic style applied.  */
+
+static const char *
+style_sub_mnem (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_sub_mnemonic, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
+/* Return a string based on FMT with the address style applied.  */
+
+static const char *
+style_addr (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_address, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
 /* Produce the string representation of the register list operand *OPND
    in the buffer pointed by BUF of size SIZE.  PREFIX is the part of
    the register name that comes before the register number, such as "v".  */
 static void
 print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
-		     const char *prefix)
+		     const char *prefix, struct aarch64_styler *styler)
 {
   const int num_regs = opnd->reglist.num_regs;
   const int first_reg = opnd->reglist.first_regno;
   const int last_reg = (first_reg + num_regs - 1) & 0x1f;
   const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
-  char tb[8];	/* Temporary buffer.  */
+  char tb[16];	/* Temporary buffer.  */
 
   assert (opnd->type != AARCH64_OPND_LEt || opnd->reglist.has_index);
   assert (num_regs >= 1 && num_regs <= 4);
@@ -3057,7 +3117,8 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
   /* Prepare the index if any.  */
   if (opnd->reglist.has_index)
     /* PR 21096: The %100 is to silence a warning about possible truncation.  */
-    snprintf (tb, 8, "[%" PRIi64 "]", (opnd->reglist.index % 100));
+    snprintf (tb, sizeof (tb), "[%s]",
+	      style_imm (styler, "%" PRIi64, (opnd->reglist.index % 100)));
   else
     tb[0] = '\0';
 
@@ -3065,8 +3126,9 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
      more than two registers in the list, and the register numbers
      are monotonically increasing in increments of one.  */
   if (num_regs > 2 && last_reg > first_reg)
-    snprintf (buf, size, "{%s%d.%s-%s%d.%s}%s", prefix, first_reg, qlf_name,
-	      prefix, last_reg, qlf_name, tb);
+    snprintf (buf, size, "{%s-%s}%s",
+	      style_reg (styler, "%s%d.%s", prefix, first_reg, qlf_name),
+	      style_reg (styler, "%s%d.%s", prefix, last_reg, qlf_name), tb);
   else
     {
       const int reg0 = first_reg;
@@ -3077,21 +3139,30 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
       switch (num_regs)
 	{
 	case 1:
-	  snprintf (buf, size, "{%s%d.%s}%s", prefix, reg0, qlf_name, tb);
+	  snprintf (buf, size, "{%s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    tb);
 	  break;
 	case 2:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s}%s", prefix, reg0, qlf_name,
-		    prefix, reg1, qlf_name, tb);
+	  snprintf (buf, size, "{%s, %s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg1, qlf_name),
+		    tb);
 	  break;
 	case 3:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, tb);
+	  snprintf (buf, size, "{%s, %s, %s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg1, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg2, qlf_name),
+		    tb);
 	  break;
 	case 4:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, prefix, reg3, qlf_name, tb);
+	  snprintf (buf, size, "{%s, %s, %s, %s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg1, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg2, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg3, qlf_name),
+		    tb);
 	  break;
 	}
     }
@@ -3103,32 +3174,41 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
 static void
 print_immediate_offset_address (char *buf, size_t size,
 				const aarch64_opnd_info *opnd,
-				const char *base)
+				const char *base,
+				struct aarch64_styler *styler)
 {
   if (opnd->addr.writeback)
     {
       if (opnd->addr.preind)
         {
 	  if (opnd->type == AARCH64_OPND_ADDR_SIMM10 && !opnd->addr.offset.imm)
-            snprintf (buf, size, "[%s]!", base);
+	    snprintf (buf, size, "[%s]!", style_reg (styler, base));
           else
-	    snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
+	    snprintf (buf, size, "[%s, %s]!",
+		      style_reg (styler, base),
+		      style_imm (styler, "#%d", opnd->addr.offset.imm));
         }
       else
-	snprintf (buf, size, "[%s], #%d", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "[%s], %s",
+		  style_reg (styler, base),
+		  style_imm (styler, "#%d", opnd->addr.offset.imm));
     }
   else
     {
       if (opnd->shifter.operator_present)
 	{
 	  assert (opnd->shifter.kind == AARCH64_MOD_MUL_VL);
-	  snprintf (buf, size, "[%s, #%d, mul vl]",
-		    base, opnd->addr.offset.imm);
+	  snprintf (buf, size, "[%s, %s, %s]",
+		    style_reg (styler, base),
+		    style_imm (styler, "#%d", opnd->addr.offset.imm),
+		    style_sub_mnem (styler, "mul vl"));
 	}
       else if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "[%s, %s]",
+		  style_reg (styler, base),
+		  style_imm (styler, "#%d", opnd->addr.offset.imm));
       else
-	snprintf (buf, size, "[%s]", base);
+	snprintf (buf, size, "[%s]", style_reg (styler, base));
     }
 }
 
@@ -3138,9 +3218,10 @@ print_immediate_offset_address (char *buf, size_t size,
 static void
 print_register_offset_address (char *buf, size_t size,
 			       const aarch64_opnd_info *opnd,
-			       const char *base, const char *offset)
+			       const char *base, const char *offset,
+			       struct aarch64_styler *styler)
 {
-  char tb[16];			/* Temporary buffer.  */
+  char tb[32];			/* Temporary buffer.  */
   bool print_extend_p = true;
   bool print_amount_p = true;
   const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
@@ -3161,16 +3242,20 @@ print_register_offset_address (char *buf, size_t size,
   if (print_extend_p)
     {
       if (print_amount_p)
-	snprintf (tb, sizeof (tb), ", %s #%" PRIi64, shift_name,
+	snprintf (tb, sizeof (tb), ", %s %s",
+		  style_sub_mnem (styler, shift_name),
+		  style_imm (styler, "#%" PRIi64,
   /* PR 21096: The %100 is to silence a warning about possible truncation.  */
-		  (opnd->shifter.amount % 100));
+			     (opnd->shifter.amount % 100)));
       else
-	snprintf (tb, sizeof (tb), ", %s", shift_name);
+	snprintf (tb, sizeof (tb), ", %s",
+		  style_sub_mnem (styler, shift_name));
     }
   else
     tb[0] = '\0';
 
-  snprintf (buf, size, "[%s, %s%s]", base, offset, tb);
+  snprintf (buf, size, "[%s, %s%s]", style_reg (styler, base),
+	    style_reg (styler, offset), tb);
 }
 
 /* Print ZA tiles from imm8 in ZERO instruction.
@@ -3183,7 +3268,8 @@ print_register_offset_address (char *buf, size_t size,
     * An all-zeros immediate is disassembled as an empty list { }.
 */
 static void
-print_sme_za_list(char *buf, size_t size, int mask)
+print_sme_za_list (char *buf, size_t size, int mask,
+		   struct aarch64_styler *styler)
 {
   const char* zan[] = { "za",    "za0.h", "za1.h", "za0.s",
                         "za1.s", "za2.s", "za3.s", "za0.d",
@@ -3203,9 +3289,9 @@ print_sme_za_list(char *buf, size_t size, int mask)
         {
           mask &= ~zan_v[i];
           if (k > 1)
-            k += snprintf (buf + k, size - k, ", %s", zan[i]);
-          else
-            k += snprintf (buf + k, size - k, "%s", zan[i]);
+	    k += snprintf (buf + k, size - k, ", ");
+
+	  k += snprintf (buf + k, size - k, style_reg (styler, zan[i]));
         }
       if (mask == 0)
         break;
@@ -3230,7 +3316,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 		       const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
 		       bfd_vma *address, char** notes,
 		       char *comment, size_t comment_size,
-		       aarch64_feature_set features)
+		       aarch64_feature_set features,
+		       struct aarch64_styler *styler)
 {
   unsigned int i, num_conds;
   const char *name = NULL;
@@ -3278,8 +3365,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	break;
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
-      snprintf (buf, size, "%s",
-		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+      snprintf (buf, size,
+		style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						     opnd->qualifier, 0)));
       break;
 
     case AARCH64_OPND_Rd_SP:
@@ -3291,8 +3379,9 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      || opnd->qualifier == AARCH64_OPND_QLF_WSP
 	      || opnd->qualifier == AARCH64_OPND_QLF_X
 	      || opnd->qualifier == AARCH64_OPND_QLF_SP);
-      snprintf (buf, size, "%s",
-		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 1));
+      snprintf (buf, size,
+		style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						     opnd->qualifier, 1)));
       break;
 
     case AARCH64_OPND_Rm_EXT:
@@ -3311,33 +3400,36 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	  if (opnd->shifter.amount == 0)
 	    {
 	      /* Shifter omitted.  */
-	      snprintf (buf, size, "%s",
-			get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+	      snprintf (buf, size,
+			style_reg (styler,
+				   get_int_reg_name (opnd->reg.regno,
+						     opnd->qualifier, 0)));
 	      break;
 	    }
 	}
       if (opnd->shifter.amount)
-	snprintf (buf, size, "%s, %s #%" PRIi64,
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
-		  aarch64_operand_modifiers[kind].name,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0)),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[kind].name),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       else
 	snprintf (buf, size, "%s, %s",
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
-		  aarch64_operand_modifiers[kind].name);
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0)),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[kind].name));
       break;
 
     case AARCH64_OPND_Rm_SFT:
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
       if (opnd->shifter.amount == 0 && opnd->shifter.kind == AARCH64_MOD_LSL)
-	snprintf (buf, size, "%s",
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+	snprintf (buf, size,
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						       opnd->qualifier, 0)));
       else
-	snprintf (buf, size, "%s, %s #%" PRIi64,
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
-		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0)),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[opnd->shifter.kind].name),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       break;
 
     case AARCH64_OPND_Fd:
@@ -3353,16 +3445,19 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Vd:
     case AARCH64_OPND_SVE_Vm:
     case AARCH64_OPND_SVE_Vn:
-      snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reg.regno);
+      snprintf (buf, size,
+		style_reg (styler, "%s%d",
+			   aarch64_get_qualifier_name (opnd->qualifier),
+			   opnd->reg.regno));
       break;
 
     case AARCH64_OPND_Va:
     case AARCH64_OPND_Vd:
     case AARCH64_OPND_Vn:
     case AARCH64_OPND_Vm:
-      snprintf (buf, size, "v%d.%s", opnd->reg.regno,
-		aarch64_get_qualifier_name (opnd->qualifier));
+      snprintf (buf, size,
+		style_reg (styler, "v%d.%s", opnd->reg.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_Ed:
@@ -3370,21 +3465,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Em:
     case AARCH64_OPND_Em16:
     case AARCH64_OPND_SM3_IMM2:
-      snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
-		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+      snprintf (buf, size, "%s[%s]",
+		style_reg (styler, "v%d.%s", opnd->reglane.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+		style_imm (styler, "%" PRIi64, opnd->reglane.index));
       break;
 
     case AARCH64_OPND_VdD1:
     case AARCH64_OPND_VnD1:
-      snprintf (buf, size, "v%d.d[1]", opnd->reg.regno);
+      snprintf (buf, size, "%s[%s]",
+		style_reg (styler, "v%d.d", opnd->reg.regno),
+		style_imm (styler, "1"));
       break;
 
     case AARCH64_OPND_LVn:
     case AARCH64_OPND_LVt:
     case AARCH64_OPND_LVt_AL:
     case AARCH64_OPND_LEt:
-      print_register_list (buf, size, opnd, "v");
+      print_register_list (buf, size, opnd, "v", styler);
       break;
 
     case AARCH64_OPND_SVE_Pd:
@@ -3397,14 +3495,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Pt:
     case AARCH64_OPND_SME_Pm:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "p%d", opnd->reg.regno);
+	snprintf (buf, size, style_reg (styler, "p%d", opnd->reg.regno));
       else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
 	       || opnd->qualifier == AARCH64_OPND_QLF_P_M)
-	snprintf (buf, size, "p%d/%s", opnd->reg.regno,
-		  aarch64_get_qualifier_name (opnd->qualifier));
+	snprintf (buf, size,
+		  style_reg (styler, "p%d/%s", opnd->reg.regno,
+			     aarch64_get_qualifier_name (opnd->qualifier)));
       else
-	snprintf (buf, size, "p%d.%s", opnd->reg.regno,
-		  aarch64_get_qualifier_name (opnd->qualifier));
+	snprintf (buf, size,
+		  style_reg (styler, "p%d.%s", opnd->reg.regno,
+			     aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_SVE_Za_5:
@@ -3415,15 +3515,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zn:
     case AARCH64_OPND_SVE_Zt:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "z%d", opnd->reg.regno);
+	snprintf (buf, size, style_reg (styler, "z%d", opnd->reg.regno));
       else
-	snprintf (buf, size, "z%d.%s", opnd->reg.regno,
-		  aarch64_get_qualifier_name (opnd->qualifier));
+	snprintf (buf, size,
+		  style_reg (styler, "z%d.%s", opnd->reg.regno,
+			     aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_SVE_ZnxN:
     case AARCH64_OPND_SVE_ZtxN:
-      print_register_list (buf, size, opnd, "z");
+      print_register_list (buf, size, opnd, "z", styler);
       break;
 
     case AARCH64_OPND_SVE_Zm3_INDEX:
@@ -3432,55 +3533,60 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zm4_11_INDEX:
     case AARCH64_OPND_SVE_Zm4_INDEX:
     case AARCH64_OPND_SVE_Zn_INDEX:
-      snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
-		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+      snprintf (buf, size, "%s[%s]",
+		style_reg (styler, "z%d.%s", opnd->reglane.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+		style_imm (styler, "%" PRIi64, opnd->reglane.index));
       break;
 
     case AARCH64_OPND_SME_ZAda_2b:
     case AARCH64_OPND_SME_ZAda_3b:
-      snprintf (buf, size, "za%d.%s", opnd->reg.regno,
-                aarch64_get_qualifier_name (opnd->qualifier));
+      snprintf (buf, size,
+		style_reg (styler, "za%d.%s", opnd->reg.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_SME_ZA_HV_idx_src:
     case AARCH64_OPND_SME_ZA_HV_idx_dest:
     case AARCH64_OPND_SME_ZA_HV_idx_ldstr:
-      snprintf (buf, size, "%sza%d%c.%s[w%d, %d]%s",
-                opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "{" : "",
-                opnd->za_tile_vector.regno,
-                opnd->za_tile_vector.v == 1 ? 'v' : 'h',
-                aarch64_get_qualifier_name (opnd->qualifier),
-                opnd->za_tile_vector.index.regno,
-                opnd->za_tile_vector.index.imm,
-                opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "}" : "");
+      snprintf (buf, size, "%s%s[%s, %s]%s",
+		opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "{" : "",
+		style_reg (styler, "za%d%c.%s",
+			   opnd->za_tile_vector.regno,
+			   opnd->za_tile_vector.v == 1 ? 'v' : 'h',
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+		style_reg (styler, "w%d", opnd->za_tile_vector.index.regno),
+		style_imm (styler, "%d", opnd->za_tile_vector.index.imm),
+		opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "}" : "");
       break;
 
     case AARCH64_OPND_SME_list_of_64bit_tiles:
-      print_sme_za_list (buf, size, opnd->reg.regno);
+      print_sme_za_list (buf, size, opnd->reg.regno, styler);
       break;
 
     case AARCH64_OPND_SME_ZA_array:
-      snprintf (buf, size, "za[w%d, %d]",
-                opnd->za_tile_vector.index.regno,
-                opnd->za_tile_vector.index.imm);
+      snprintf (buf, size, "%s[%s, %s]",
+		style_reg (styler, "za"),
+		style_reg (styler, "w%d", opnd->za_tile_vector.index.regno),
+		style_imm (styler, "%d", opnd->za_tile_vector.index.imm));
       break;
 
     case AARCH64_OPND_SME_SM_ZA:
-      snprintf (buf, size, "%s", opnd->reg.regno == 's' ? "sm" : "za");
+      snprintf (buf, size,
+		style_reg (styler, opnd->reg.regno == 's' ? "sm" : "za"));
       break;
 
     case AARCH64_OPND_SME_PnT_Wm_imm:
-      snprintf (buf, size, "p%d.%s[w%d, %d]",
-                opnd->za_tile_vector.regno,
-                aarch64_get_qualifier_name (opnd->qualifier),
-                opnd->za_tile_vector.index.regno,
-                opnd->za_tile_vector.index.imm);
+      snprintf (buf, size, "%s[%s, %s]",
+		style_reg (styler, "p%d.%s", opnd->za_tile_vector.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+                style_reg (styler, "w%d", opnd->za_tile_vector.index.regno),
+                style_imm (styler, "%d", opnd->za_tile_vector.index.imm));
       break;
 
     case AARCH64_OPND_CRn:
     case AARCH64_OPND_CRm:
-      snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, style_reg (styler, "C%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_IDX:
@@ -3521,7 +3627,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_IMM_ROT1:
     case AARCH64_OPND_SVE_IMM_ROT2:
     case AARCH64_OPND_SVE_IMM_ROT3:
-      snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_SVE_I1_HALF_ONE:
@@ -3530,7 +3636,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       {
 	single_conv_t c;
 	c.i = opnd->imm.value;
-	snprintf (buf, size, "#%.1f", c.f);
+	snprintf (buf, size, style_imm (styler, "#%.1f", c.f));
 	break;
       }
 
@@ -3541,9 +3647,10 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[enum_value]);
+	snprintf (buf, size,
+		  style_reg (styler, aarch64_sve_pattern_array[enum_value]));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_SVE_PATTERN_SCALED:
@@ -3554,15 +3661,19 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[opnd->imm.value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[opnd->imm.value]);
+	snprintf (buf, size,
+		  style_reg (styler,
+			     aarch64_sve_pattern_array[opnd->imm.value]));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, style_imm (styler, "#%" PRIi64, opnd->imm.value));
       if (opnd->shifter.operator_present)
 	{
 	  size_t len = strlen (buf);
-	  snprintf (buf + len, size - len, ", %s #%" PRIi64,
-		    aarch64_operand_modifiers[opnd->shifter.kind].name,
-		    opnd->shifter.amount);
+	  const char *shift_name
+	    = aarch64_operand_modifiers[opnd->shifter.kind].name;
+	  snprintf (buf + len, size - len, ", %s %s",
+		    style_sub_mnem (styler, shift_name),
+		    style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
 	}
       break;
 
@@ -3570,9 +3681,10 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
       if (aarch64_sve_prfop_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_prfop_array[enum_value]);
+	snprintf (buf, size,
+		  style_reg (styler, aarch64_sve_prfop_array[enum_value]));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_IMM_MOV:
@@ -3581,12 +3693,13 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	case 4:	/* e.g. MOV Wd, #<imm32>.  */
 	    {
 	      int imm32 = opnd->imm.value;
-	      snprintf (buf, size, "#0x%-20x", imm32);
+	      snprintf (buf, size, style_imm (styler, "#0x%-20x", imm32));
 	      snprintf (comment, comment_size, "#%d", imm32);
 	    }
 	  break;
 	case 8:	/* e.g. MOV Xd, #<imm64>.  */
-	  snprintf (buf, size, "#0x%-20" PRIx64, opnd->imm.value);
+	  snprintf (buf, size, style_imm (styler, "#0x%-20" PRIx64,
+					  opnd->imm.value));
 	  snprintf (comment, comment_size, "#%" PRIi64, opnd->imm.value);
 	  break;
 	default:
@@ -3596,7 +3709,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_FPIMM0:
-      snprintf (buf, size, "#0.0");
+      snprintf (buf, size, style_imm (styler, "#0.0"));
       break;
 
     case AARCH64_OPND_LIMM:
@@ -3606,30 +3719,37 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_LIMM:
     case AARCH64_OPND_SVE_LIMM_MOV:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value),
+		  style_sub_mnem (styler, "lsl"),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       else
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size,
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_SIMD_IMM:
     case AARCH64_OPND_SIMD_IMM_SFT:
       if ((! opnd->shifter.amount && opnd->shifter.kind == AARCH64_MOD_LSL)
 	  || opnd->shifter.kind == AARCH64_MOD_NONE)
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size,
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value));
       else
-	snprintf (buf, size, "#0x%" PRIx64 ", %s #%" PRIi64, opnd->imm.value,
-		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[opnd->shifter.kind].name),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       break;
 
     case AARCH64_OPND_SVE_AIMM:
     case AARCH64_OPND_SVE_ASIMM:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_imm (styler, "#%" PRIi64, opnd->imm.value),
+		  style_sub_mnem (styler, "lsl"),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_FPIMM:
@@ -3641,21 +3761,21 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	    {
 	      half_conv_t c;
 	      c.i = expand_fp_imm (2, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size, style_imm (styler, "#%.18e", c.f));
 	    }
 	  break;
 	case 4:	/* e.g. FMOV <Vd>.4S, #<imm>.  */
 	    {
 	      single_conv_t c;
 	      c.i = expand_fp_imm (4, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size, style_imm (styler, "#%.18e", c.f));
 	    }
 	  break;
 	case 8:	/* e.g. FMOV <Sd>, #<imm>.  */
 	    {
 	      double_conv_t c;
 	      c.i = expand_fp_imm (8, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.d);
+	      snprintf (buf, size, style_imm (styler, "#%.18e", c.d));
 	    }
 	  break;
 	default:
@@ -3676,12 +3796,13 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      (int64_t) get_optional_operand_default_value (opcode)))
 	/* Omit the operand, e.g. DCPS1.  */
 	break;
-      snprintf (buf, size, "#0x%x", (unsigned int)opnd->imm.value);
+      snprintf (buf, size,
+		style_imm (styler, "#0x%x", (unsigned int) opnd->imm.value));
       break;
 
     case AARCH64_OPND_COND:
     case AARCH64_OPND_COND1:
-      snprintf (buf, size, "%s", opnd->cond->names[0]);
+      snprintf (buf, size, style_sub_mnem (styler, opnd->cond->names[0]));
       num_conds = ARRAY_SIZE (opnd->cond->names);
       for (i = 1; i < num_conds && opnd->cond->names[i]; ++i)
 	{
@@ -3706,7 +3827,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, style_addr (styler, "#0x%" PRIx64 , addr));
       break;
 
     case AARCH64_OPND_ADDR_PCREL14:
@@ -3722,7 +3843,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, style_addr (styler, "#0x%" PRIx64, addr));
       break;
 
     case AARCH64_OPND_ADDR_SIMPLE:
@@ -3732,12 +3853,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (opnd->type == AARCH64_OPND_SIMD_ADDR_POST)
 	{
 	  if (opnd->addr.offset.is_reg)
-	    snprintf (buf, size, "[%s], x%d", name, opnd->addr.offset.regno);
+	    snprintf (buf, size, "[%s], %s",
+		      style_reg (styler, name),
+		      style_reg (styler, "x%d", opnd->addr.offset.regno));
 	  else
-	    snprintf (buf, size, "[%s], #%d", name, opnd->addr.offset.imm);
+	    snprintf (buf, size, "[%s], %s",
+		      style_reg (styler, name),
+		      style_imm (styler, "#%d", opnd->addr.offset.imm));
 	}
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "[%s]", style_reg (styler, name));
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
@@ -3753,14 +3878,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RX_LSL3:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_offset_int_reg_name (opnd));
+	 get_offset_int_reg_name (opnd), styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZX:
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0));
+	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0), styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_RZ:
@@ -3777,7 +3902,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 styler);
       break;
 
     case AARCH64_OPND_ADDR_SIMM7:
@@ -3801,7 +3927,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RI_U6x4:
     case AARCH64_OPND_SVE_ADDR_RI_U6x8:
       print_immediate_offset_address
-	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1));
+	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
+	 styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZI_U5:
@@ -3810,7 +3937,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
       print_immediate_offset_address
 	(buf, size, opnd,
-	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
+	 styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
@@ -3819,15 +3947,18 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 styler);
       break;
 
     case AARCH64_OPND_ADDR_UIMM12:
       name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
       if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", name, opnd->addr.offset.imm);
+	snprintf (buf, size, "[%s, %s]",
+		  style_reg (styler, name),
+		  style_imm (styler, "#%d", opnd->addr.offset.imm));
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "[%s]", style_reg (styler, name));
       break;
 
     case AARCH64_OPND_SYSREG:
@@ -3866,14 +3997,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	}
 
       if (name)
-	snprintf (buf, size, "%s", name);
+	snprintf (buf, size, style_reg (styler, name));
       else
 	{
 	  /* Implementation defined system register.  */
 	  unsigned int value = opnd->sysreg.value;
-	  snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
-		    (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
-		    value & 0x7);
+	  snprintf (buf, size,
+		    style_reg (styler, "s%u_%u_c%u_c%u_%u",
+			       (value >> 14) & 0x3, (value >> 11) & 0x7,
+			       (value >> 7) & 0xf, (value >> 3) & 0xf,
+			       value & 0x7));
 	}
       break;
 
@@ -3891,7 +4024,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
             break;
           }
       assert (aarch64_pstatefields[i].name);
-      snprintf (buf, size, "%s", aarch64_pstatefields[i].name);
+      snprintf (buf, size, style_reg (styler, aarch64_pstatefields[i].name));
       break;
 
     case AARCH64_OPND_SYSREG_AT:
@@ -3899,12 +4032,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SYSREG_IC:
     case AARCH64_OPND_SYSREG_TLBI:
     case AARCH64_OPND_SYSREG_SR:
-      snprintf (buf, size, "%s", opnd->sysins_op->name);
+      snprintf (buf, size, style_reg (styler, opnd->sysins_op->name));
       break;
 
     case AARCH64_OPND_BARRIER:
     case AARCH64_OPND_BARRIER_DSB_NXS:
-      snprintf (buf, size, "%s", opnd->barrier->name);
+      {
+	if (opnd->barrier->name[0] == '#')
+	  snprintf (buf, size, style_imm (styler, opnd->barrier->name));
+	else
+	  snprintf (buf, size, style_sub_mnem (styler, opnd->barrier->name));
+      }
       break;
 
     case AARCH64_OPND_BARRIER_ISB:
@@ -3912,34 +4050,38 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (! optional_operand_p (opcode, idx)
 	  || (opnd->barrier->value
 	      != get_optional_operand_default_value (opcode)))
-	snprintf (buf, size, "#0x%x", opnd->barrier->value);
+	snprintf (buf, size, style_imm (styler, "#0x%x", opnd->barrier->value));
       break;
 
     case AARCH64_OPND_PRFOP:
       if (opnd->prfop->name != NULL)
-	snprintf (buf, size, "%s", opnd->prfop->name);
+	snprintf (buf, size, style_sub_mnem (styler, opnd->prfop->name));
       else
-	snprintf (buf, size, "#0x%02x", opnd->prfop->value);
+	snprintf (buf, size, style_imm (styler, "#0x%02x",
+					opnd->prfop->value));
       break;
 
     case AARCH64_OPND_BARRIER_PSB:
-      snprintf (buf, size, "csync");
+      snprintf (buf, size, style_sub_mnem (styler, "csync"));
       break;
 
     case AARCH64_OPND_BTI_TARGET:
       if ((HINT_FLAG (opnd->hint_option->value) & HINT_OPD_F_NOPRINT) == 0)
-	snprintf (buf, size, "%s", opnd->hint_option->name);
+	snprintf (buf, size, style_sub_mnem (styler, opnd->hint_option->name));
       break;
 
     case AARCH64_OPND_MOPS_ADDR_Rd:
     case AARCH64_OPND_MOPS_ADDR_Rs:
       snprintf (buf, size, "[%s]!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+		style_reg (styler,
+			   get_int_reg_name (opnd->reg.regno,
+					     AARCH64_OPND_QLF_X, 0)));
       break;
 
     case AARCH64_OPND_MOPS_WB_Rn:
       snprintf (buf, size, "%s!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+		style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						     AARCH64_OPND_QLF_X, 0)));
       break;
 
     default:
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index 9c0dacaf391..21a24949747 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -610,6 +610,7 @@ disassemble_init_for_target (struct disassemble_info * info)
     case bfd_arch_aarch64:
       info->symbol_is_valid = aarch64_symbol_is_valid;
       info->disassembler_needs_relocs = true;
+      info->created_styled_output = true;
       break;
 #endif
 #ifdef ARCH_arm
-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCHv4 0/2] AArch64 libopcodes styling
  2022-07-08 10:25           ` [PATCHv4 0/2] AArch64 libopcodes styling Andrew Burgess
  2022-07-08 10:25             ` [PATCHv4 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
  2022-07-08 10:25             ` [PATCHv4 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
@ 2022-07-19 12:52             ` Andrew Burgess
  2 siblings, 0 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-07-19 12:52 UTC (permalink / raw)
  To: Andrew Burgess via Binutils, binutils

Andrew Burgess via Binutils <binutils@sourceware.org> writes:

> Changed since v3:
>
>   - Patch #1 is unchanged,
>
>   - Removed debug code that was accidentally left in patch #2,
>
>   - Patch #2 now sets the disassemble_info::created_styled_output flag
>     correctly in disassembler.c.
>
> Changes since v2:
>
>   - Patch #1 is unchanged,
>
>   - Patch #2, now with more OBSTACK!  This patch is pretty much a
>     complete rewrite from the gound up based on Richard's feedback.
>     The new iteration makes use of obstacks (in aarch64-dis.c and
>     tc-aarch64.c) to format each chunk of disassembler output.  These
>     chunks are then combined in aarch64-opc.c as required.
>
> Changes since v1:
>
>   - Original patch #1 has been merged,
>
>   - New patch #1 adds a dis_style_sub_mnemonic style and updates
>     objdump to handle this style,
>
>   - Patch #2 has been updated to make use of the new style.

Ping!

Thanks,
Andrew


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCHv4 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-07-08 10:25             ` [PATCHv4 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
@ 2022-07-19 15:33               ` Richard Earnshaw
  2022-07-21  8:56                 ` [PATCHv5 0/2] AArch64 libopcodes styling Andrew Burgess
  0 siblings, 1 reply; 31+ messages in thread
From: Richard Earnshaw @ 2022-07-19 15:33 UTC (permalink / raw)
  To: Andrew Burgess, binutils



On 08/07/2022 11:25, Andrew Burgess via Binutils wrote:
> This commit enables disassembler styling for AArch64.  After this
> commit it is possible to have objdump style AArch64 disassembler
> output (using --disassembler-color option).  Once the required GDB
> patches are merged, GDB will also style the disassembler output.
> 
> The changes to support styling are mostly split between two files
> opcodes/aarch64-dis.c and opcodes/aarch64-opc.c.
> 
> The entry point for the AArch64 disassembler can be found in
> aarch64-dis.c, this file handles printing the instruction mnemonics,
> and assembler directives (e.g. '.byte', '.word', etc).  Some operands,
> mostly relating to assembler directives are also printed from this
> file.  This commit changes all of this to pass through suitable
> styling information.
> 
> However, for most "normal" instructions, the instruction operands are
> printed using a two step process.  From aarch64-dis.c, in the
> print_operands function, the function aarch64_print_operand is called,
> this function is in aarch64-opc.c, and converts an instruction operand
> into a string.  Then, back in print_operands (aarch64-dis.c), the
> operand string is printed.
> 
> Unfortunately, the string returned by aarch64_print_operand can be
> quite complex, it will include syntax elements, like '[' and ']', in
> addition to register names and immediate values.  In some cases, a
> single operand will expand into what will appear (to the user) as
> multiple operands separated with a ','.
> 
> This makes the task of styling more complex, all these different
> components need to by styled differently, so we need to get the
> styling information out of aarch64_print_operand in some way.
> 
> The solution that I propose here is similar to the solution that I
> used for the i386 disassembler.
> 
> Currently, aarch64_print_operand uses snprintf to write the operand
> text into a buffer provided by the caller.
> 
> What I propose is that we pass an extra argument to the
> aarch64_print_operand function, this argument will be a structure, the
> structure contains a callback function and some state.
> 
> When aarch64_print_operand needs to format part of its output this can
> be done by using the callback function within the new structure, this
> callback returns a string with special embedded markers that indicate
> which mode should be used for each piece of text.  Back in
> aarch64-dis.c we can spot these special style markers and use this to
> split the disassembler output up and apply the correct style to each
> piece.
> 
> To make aarch64-opc.c clearer a series of new static functions have
> been added, e.g. 'style_reg', 'style_imm', etc.  Each of these
> functions formats a piece of text in a different style, 'register' and
> 'immediate' in this case.
> 
> Here's an example taken from aarch64-opc.c of the new functions in
> use:
> 
>      snprintf (buf, size, "[%s, %s]!",
>                style_reg (styler, base),
>                style_imm (styler, "#%d", opnd->addr.offset.imm));
> 
> The aarch64_print_operand function is also called from the assembler
> to aid in printing diagnostic messages.  Right now I have no plans to
> add styling to the assembler output, and so, the callback function
> used in the assembler ignores the styling information and just returns
> an plain string.
> 
> I've used the source files in gas/testsuite/gas/aarch64/ for testing,
> and have manually gone through and checked that the styling looks
> reasonable, however, I'm not an AArch64 expert, so it is possible that
> the odd piece is styled incorrectly.  Please point out any mistakes
> I've made.
> 

There are several places where you've omitted a format string and 
instead passed the output of style_...() directly as the format.  For 
example:
      case AARCH64_OPND_BARRIER_DSB_NXS:
-      snprintf (buf, size, "%s", opnd->barrier->name);
+      {
+	if (opnd->barrier->name[0] == '#')
+	  snprintf (buf, size, style_imm (styler, opnd->barrier->name));
+	else
+	  snprintf (buf, size, style_sub_mnem (styler, opnd->barrier->name));
+      }
        break;

There's a small risk of that containing a % character itself and thus 
causing UB, so I think it would be better to use an explicit "%s" 
argument in those cases.

There's one possible typo that I spotted: s/slit/split/?

Other than that, I think this is OK.  It would be nice if the obstack 
could be allocated once and then reset after each use, that would avoid 
having to malloc a new stack each time aarch64_print_operand is called, 
but it's not a massive overhead.

R.


> +/* Return a short string to indicate a switch to STYLE.  These strings
> +   will be embedded into the disassembled operand text (as produced by
> +   aarch64_print_operand), and then spotted in the print_operands function
> +   so that the disassembler output can be slit by style.  */

s/slit/split/?


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv5 0/2] AArch64 libopcodes styling
  2022-07-19 15:33               ` Richard Earnshaw
@ 2022-07-21  8:56                 ` Andrew Burgess
  2022-07-21  8:56                   ` [PATCHv5 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
  2022-07-21  8:56                   ` [PATCHv5 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
  0 siblings, 2 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-07-21  8:56 UTC (permalink / raw)
  To: binutils; +Cc: Richard Earnshaw, Andrew Burgess

Richard,

Here's an updated series.  I've fixed the typo you spotted, and I now
pass "%s" in where I'm formatting a single string, which avoids
potential formatting issues if there's ever a '%' in the string to
print.

What I've not done in this commit is try to optimise how we handle the
obstack.

In your comment you talk about the obstack being initialised for each
call to aarch64_print_operand - this isn't exactly correct, we
initialise the obstack once in print_operands (there's a version of
this in the assembler and disassembler), and then make multiple calls
to aarch64_print_operand using the same obstack.  This means we
initialise the obstack once per instruction right now.

However, we could do better, we could make use of
disassemble_init_for_target, and then store the obstack in the
disassemble_info::private_data field.  In this way we really could
initialise the obstack once, and then disassemble multiple
instructions (resetting the obstack after each instruction has
completed).  In the assembler we could potentially just make the
obstack global (as the assembler already has lots of global state),
or, as the assembler only prints instructions on an error path, we
maybe don't care about allocating the obstack multiple times...

That said, I haven't done either of these things in this patch.  If
you think this is worth doing then I'm happy to write this patch, but
I'll keep it as a separate patch as it feels like a new piece of work.

Let me know what you think,

Thanks,
Andrew

---

Changes since v4:

  - Fixed a typo in patch #2,

  - Pass "%s" format in more cases.

Changed since v3:

  - Patch #1 is unchanged,

  - Removed debug code that was accidentally left in patch #2,

  - Patch #2 now sets the disassemble_info::created_styled_output flag
    correctly in disassembler.c.

Changes since v2:

  - Patch #1 is unchanged,

  - Patch #2, now with more OBSTACK!  This patch is pretty much a
    complete rewrite from the gound up based on Richard's feedback.
    The new iteration makes use of obstacks (in aarch64-dis.c and
    tc-aarch64.c) to format each chunk of disassembler output.  These
    chunks are then combined in aarch64-opc.c as required.

Changes since v1:

  - Original patch #1 has been merged,

  - New patch #1 adds a dis_style_sub_mnemonic style and updates
    objdump to handle this style,

  - Patch #2 has been updated to make use of the new style.

---

Andrew Burgess (2):
  opcodes: add new sub-mnemonic disassembler style
  libopcodes/aarch64: add support for disassembler styling

 binutils/objdump.c       |   2 +
 gas/config/tc-aarch64.c  |  45 +++-
 include/dis-asm.h        |   7 +
 include/opcode/aarch64.h |  28 ++-
 opcodes/aarch64-dis.c    | 247 +++++++++++++++++++---
 opcodes/aarch64-opc.c    | 445 ++++++++++++++++++++++++++-------------
 opcodes/disassemble.c    |   1 +
 7 files changed, 596 insertions(+), 179 deletions(-)

-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv5 1/2] opcodes: add new sub-mnemonic disassembler style
  2022-07-21  8:56                 ` [PATCHv5 0/2] AArch64 libopcodes styling Andrew Burgess
@ 2022-07-21  8:56                   ` Andrew Burgess
  2022-07-25 13:34                     ` Andrew Burgess
  2022-07-21  8:56                   ` [PATCHv5 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
  1 sibling, 1 reply; 31+ messages in thread
From: Andrew Burgess @ 2022-07-21  8:56 UTC (permalink / raw)
  To: binutils; +Cc: Richard Earnshaw, Andrew Burgess

When adding libopcodes disassembler styling support for AArch64, it
feels like the results would be improved by having a new sub-mnemonic
style.  This will be used in cases like:

  add    w16, w7, w1, uxtb #2
                      ^^^^----- Here

And:

  cinc   w0, w1, ne
                 ^^----- Here

This commit just adds the new style, and prepares objdump to handle
the style.  A later commit will add AArch64 styling, and will actually
make use of the style.

As this style is currently unused, there should be no user visible
changes after this commit.
---
 binutils/objdump.c | 2 ++
 include/dis-asm.h  | 7 +++++++
 2 files changed, 9 insertions(+)

diff --git a/binutils/objdump.c b/binutils/objdump.c
index 67824053527..4076587151c 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -2167,6 +2167,7 @@ objdump_color_for_disassembler_style (enum disassembler_style style)
 	{
 	case dis_style_symbol: color = 32; break;
         case dis_style_assembler_directive:
+	case dis_style_sub_mnemonic:
 	case dis_style_mnemonic: color = 33; break;
 	case dis_style_register: color = 34; break;
 	case dis_style_address:
@@ -2185,6 +2186,7 @@ objdump_color_for_disassembler_style (enum disassembler_style style)
 	{
 	case dis_style_symbol: color = 40; break;
         case dis_style_assembler_directive:
+	case dis_style_sub_mnemonic:
 	case dis_style_mnemonic: color = 142; break;
 	case dis_style_register: color = 27; break;
 	case dis_style_address:
diff --git a/include/dis-asm.h b/include/dis-asm.h
index 4f91df12498..f1a83dc84e5 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -62,6 +62,13 @@ enum disassembler_style
      instructions.  */
   dis_style_mnemonic,
 
+  /* Some architectures include additional mnemonic like fields within the
+     instruction operands, e.g. on aarch64 'add w16, w7, w1, lsl #2' where
+     the 'lsl' is an additional piece of text that describes how the
+     instruction should behave.  This sub-mnemonic style can be used for
+     these pieces of text.  */
+  dis_style_sub_mnemonic,
+
   /* For things that aren't real machine instructions, but rather
      assembler directives, e.g. .byte, etc.  */
   dis_style_assembler_directive,
-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCHv5 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-07-21  8:56                 ` [PATCHv5 0/2] AArch64 libopcodes styling Andrew Burgess
  2022-07-21  8:56                   ` [PATCHv5 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
@ 2022-07-21  8:56                   ` Andrew Burgess
  2022-07-26 13:55                     ` Nick Clifton
  1 sibling, 1 reply; 31+ messages in thread
From: Andrew Burgess @ 2022-07-21  8:56 UTC (permalink / raw)
  To: binutils; +Cc: Richard Earnshaw, Andrew Burgess

This commit enables disassembler styling for AArch64.  After this
commit it is possible to have objdump style AArch64 disassembler
output (using --disassembler-color option).  Once the required GDB
patches are merged, GDB will also style the disassembler output.

The changes to support styling are mostly split between two files
opcodes/aarch64-dis.c and opcodes/aarch64-opc.c.

The entry point for the AArch64 disassembler can be found in
aarch64-dis.c, this file handles printing the instruction mnemonics,
and assembler directives (e.g. '.byte', '.word', etc).  Some operands,
mostly relating to assembler directives are also printed from this
file.  This commit changes all of this to pass through suitable
styling information.

However, for most "normal" instructions, the instruction operands are
printed using a two step process.  From aarch64-dis.c, in the
print_operands function, the function aarch64_print_operand is called,
this function is in aarch64-opc.c, and converts an instruction operand
into a string.  Then, back in print_operands (aarch64-dis.c), the
operand string is printed.

Unfortunately, the string returned by aarch64_print_operand can be
quite complex, it will include syntax elements, like '[' and ']', in
addition to register names and immediate values.  In some cases, a
single operand will expand into what will appear (to the user) as
multiple operands separated with a ','.

This makes the task of styling more complex, all these different
components need to by styled differently, so we need to get the
styling information out of aarch64_print_operand in some way.

The solution that I propose here is similar to the solution that I
used for the i386 disassembler.

Currently, aarch64_print_operand uses snprintf to write the operand
text into a buffer provided by the caller.

What I propose is that we pass an extra argument to the
aarch64_print_operand function, this argument will be a structure, the
structure contains a callback function and some state.

When aarch64_print_operand needs to format part of its output this can
be done by using the callback function within the new structure, this
callback returns a string with special embedded markers that indicate
which mode should be used for each piece of text.  Back in
aarch64-dis.c we can spot these special style markers and use this to
split the disassembler output up and apply the correct style to each
piece.

To make aarch64-opc.c clearer a series of new static functions have
been added, e.g. 'style_reg', 'style_imm', etc.  Each of these
functions formats a piece of text in a different style, 'register' and
'immediate' in this case.

Here's an example taken from aarch64-opc.c of the new functions in
use:

    snprintf (buf, size, "[%s, %s]!",
              style_reg (styler, base),
              style_imm (styler, "#%d", opnd->addr.offset.imm));

The aarch64_print_operand function is also called from the assembler
to aid in printing diagnostic messages.  Right now I have no plans to
add styling to the assembler output, and so, the callback function
used in the assembler ignores the styling information and just returns
an plain string.

I've used the source files in gas/testsuite/gas/aarch64/ for testing,
and have manually gone through and checked that the styling looks
reasonable, however, I'm not an AArch64 expert, so it is possible that
the odd piece is styled incorrectly.  Please point out any mistakes
I've made.

With objdump disassembler color turned off, there should be no change
in the output after this commit.
---
 gas/config/tc-aarch64.c  |  45 +++-
 include/opcode/aarch64.h |  28 ++-
 opcodes/aarch64-dis.c    | 247 +++++++++++++++++++---
 opcodes/aarch64-opc.c    | 445 ++++++++++++++++++++++++++-------------
 opcodes/disassemble.c    |   1 +
 5 files changed, 587 insertions(+), 179 deletions(-)

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 779db31828b..dc154b96fce 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -5347,6 +5347,41 @@ assign_qualifier_sequence (aarch64_inst *instr,
     instr->operands[i].qualifier = *qualifiers;
 }
 
+/* Callback used by aarch64_print_operand to apply STYLE to the
+   disassembler output created from FMT and ARGS.  The STYLER object holds
+   any required state.  Must return a pointer to a string (created from FMT
+   and ARGS) that will continue to be valid until the complete disassembled
+   instruction has been printed.
+
+   We don't currently add any styling to the output of the disassembler as
+   used within assembler error messages, and so STYLE is ignored here.  A
+   new string is allocated on the obstack help within STYLER and returned
+   to the caller.  */
+
+static const char *aarch64_apply_style
+	(struct aarch64_styler *styler,
+	 enum disassembler_style style ATTRIBUTE_UNUSED,
+	 const char *fmt, va_list args)
+{
+  int res;
+  char *ptr;
+  struct obstack *stack = (struct obstack *) styler->state;
+  va_list ap;
+
+  /* Calculate the required space.  */
+  va_copy (ap, args);
+  res = vsnprintf (NULL, 0, fmt, ap);
+  va_end (ap);
+  gas_assert (res >= 0);
+
+  /* Allocate space on the obstack and format the result.  */
+  ptr = (char *) obstack_alloc (stack, res + 1);
+  res = vsnprintf (ptr, (res + 1), fmt, args);
+  gas_assert (res >= 0);
+
+  return ptr;
+}
+
 /* Print operands for the diagnosis purpose.  */
 
 static void
@@ -5354,6 +5389,12 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 		const aarch64_opnd_info *opnds)
 {
   int i;
+  struct aarch64_styler styler;
+  struct obstack content;
+  obstack_init (&content);
+
+  styler.apply_style = aarch64_apply_style;
+  styler.state = (void *) &content;
 
   for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
@@ -5371,7 +5412,7 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), 0, opcode, opnds, i, NULL, NULL,
-			     NULL, cmt, sizeof (cmt), cpu_variant);
+			     NULL, cmt, sizeof (cmt), cpu_variant, &styler);
 
       /* Delimiter.  */
       if (str[0] != '\0')
@@ -5389,6 +5430,8 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 	  strcat (buf, cmt);
 	}
     }
+
+  obstack_free (&content, NULL);
 }
 
 /* Send to stderr a string as information.  */
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 186ba9a4800..9477ac98f3b 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -27,6 +27,8 @@
 #include <assert.h>
 #include <stdlib.h>
 
+#include "dis-asm.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -1367,12 +1369,36 @@ aarch64_replace_opcode (struct aarch64_inst *,
 extern const aarch64_opcode *
 aarch64_get_opcode (enum aarch64_op);
 
+/* An instance of this structure is passed to aarch64_print_operand, and
+   the callback within this structure is used to apply styling to the
+   disassembler output.  This structure encapsulates the callback and a
+   state pointer.  */
+
+struct aarch64_styler
+{
+  /* The callback used to apply styling.  Returns a string created from FMT
+     and ARGS with STYLE applied to the string.  STYLER is a pointer back
+     to this object so that the callback can access the state member.
+
+     The string returned from this callback must remain valid until the
+     call to aarch64_print_operand has completed.  */
+  const char *(*apply_style) (struct aarch64_styler *styler,
+			      enum disassembler_style style,
+			      const char *fmt,
+			      va_list args);
+
+  /* A pointer to a state object which can be used by the apply_style
+     callback function.  */
+  void *state;
+};
+
 /* Generate the string representation of an operand.  */
 extern void
 aarch64_print_operand (char *, size_t, bfd_vma, const aarch64_opcode *,
 		       const aarch64_opnd_info *, int, int *, bfd_vma *,
 		       char **, char *, size_t,
-		       aarch64_feature_set features);
+		       aarch64_feature_set features,
+		       struct aarch64_styler *styler);
 
 /* Miscellaneous interface.  */
 
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index acaad28fdff..9e98f0d2f20 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -25,9 +25,18 @@
 #include "opintl.h"
 #include "aarch64-dis.h"
 #include "elf-bfd.h"
+#include "safe-ctype.h"
+#include "obstack.h"
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
 
 #define INSNLEN 4
 
+/* This character is used to encode style information within the output
+   buffers.  See get_style_text and print_operands for more details.  */
+#define STYLE_MARKER_CHAR '\002'
+
 /* Cached mapping symbol state.  */
 enum map_type
 {
@@ -3275,6 +3284,90 @@ aarch64_decode_insn (aarch64_insn insn, aarch64_inst *inst,
   return ERR_UND;
 }
 
+/* Return a short string to indicate a switch to STYLE.  These strings
+   will be embedded into the disassembled operand text (as produced by
+   aarch64_print_operand), and then spotted in the print_operands function
+   so that the disassembler output can be split by style.  */
+
+static const char *
+get_style_text (enum disassembler_style style)
+{
+  static bool init = false;
+  static char formats[16][4];
+  unsigned num;
+
+  /* First time through we build a string for every possible format.  This
+     code relies on there being no more than 16 different styles (there's
+     an assert below for this).  */
+  if (!init)
+    {
+      int i;
+
+      for (i = 0; i <= 0xf; ++i)
+	{
+	  int res = snprintf (&formats[i][0], sizeof (formats[i]), "%c%x%c",
+			      STYLE_MARKER_CHAR, i, STYLE_MARKER_CHAR);
+	  assert (res == 3);
+	}
+
+      init = true;
+    }
+
+  /* Return the string that marks switching to STYLE.  */
+  num = (unsigned) style;
+  assert (style <= 0xf);
+  return formats[num];
+}
+
+/* Callback used by aarch64_print_operand to apply STYLE to the
+   disassembler output created from FMT and ARGS.  The STYLER object holds
+   any required state.  Must return a pointer to a string (created from FMT
+   and ARGS) that will continue to be valid until the complete disassembled
+   instruction has been printed.
+
+   We return a string that includes two embedded style markers, the first,
+   places at the start of the string, indicates a switch to STYLE, and the
+   second, placed at the end of the string, indicates a switch back to the
+   default text style.
+
+   Later, when we print the operand text we take care to collapse any
+   adjacent style markers, and to ignore any style markers that appear at
+   the very end of a complete operand string.  */
+
+static const char *aarch64_apply_style (struct aarch64_styler *styler,
+					enum disassembler_style style,
+					const char *fmt,
+					va_list args)
+{
+  int res;
+  char *ptr, *tmp;
+  struct obstack *stack = (struct obstack *) styler->state;
+  va_list ap;
+
+  /* These are the two strings for switching styles.  */
+  const char *style_on = get_style_text (style);
+  const char *style_off = get_style_text (dis_style_text);
+
+  /* Calculate space needed once FMT and ARGS are expanded.  */
+  va_copy (ap, args);
+  res = vsnprintf (NULL, 0, fmt, ap);
+  va_end (ap);
+  assert (res >= 0);
+
+  /* Allocate space on the obstack for the expanded FMT and ARGS, as well
+     as the two strings for switching styles, then write all of these
+     strings onto the obstack.  */
+  ptr = (char *) obstack_alloc (stack, res + strlen (style_on)
+				+ strlen (style_off) + 1);
+  tmp = stpcpy (ptr, style_on);
+  res = vsnprintf (tmp, (res + 1), fmt, args);
+  assert (res >= 0);
+  tmp += res;
+  strcpy (tmp, style_off);
+
+  return ptr;
+}
+
 /* Print operands.  */
 
 static void
@@ -3284,6 +3377,13 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
 {
   char *notes = NULL;
   int i, pcrel_p, num_printed;
+  struct aarch64_styler styler;
+  struct obstack content;
+  obstack_init (&content);
+
+  styler.apply_style = aarch64_apply_style;
+  styler.state = (void *) &content;
+
   for (i = 0, num_printed = 0; i < AARCH64_MAX_OPND_NUM; ++i)
     {
       char str[128];
@@ -3301,33 +3401,97 @@ print_operands (bfd_vma pc, const aarch64_opcode *opcode,
       /* Generate the operand string in STR.  */
       aarch64_print_operand (str, sizeof (str), pc, opcode, opnds, i, &pcrel_p,
 			     &info->target, &notes, cmt, sizeof (cmt),
-			     arch_variant);
+			     arch_variant, &styler);
 
       /* Print the delimiter (taking account of omitted operand(s)).  */
       if (str[0] != '\0')
-	(*info->fprintf_func) (info->stream, "%s",
-			       num_printed++ == 0 ? "\t" : ", ");
+	(*info->fprintf_styled_func) (info->stream, dis_style_text, "%s",
+				      num_printed++ == 0 ? "\t" : ", ");
 
       /* Print the operand.  */
       if (pcrel_p)
 	(*info->print_address_func) (info->target, info);
       else
 	{
-	  (*info->fprintf_func) (info->stream, "%s", str);
-
-	  /* Print the comment.  This works because only the last operand
-	     ever adds a comment.  If that ever changes then we'll need to
-	     be smarter here.  */
-	  if (cmt[0] != '\0')
-	    (*info->fprintf_func) (info->stream, "\t// %s", cmt);
+	  /* This operand came from aarch64_print_operand, and will include
+	     embedded strings indicating which style each character should
+	     have.  In the following code we split the text based on
+	     CURR_STYLE, and call the styled print callback to print each
+	     block of text in the appropriate style.  */
+	  char *start, *curr;
+	  enum disassembler_style curr_style = dis_style_text;
+
+	  start = curr = str;
+	  do
+	    {
+	      if (*curr == '\0'
+		  || (*curr == STYLE_MARKER_CHAR
+		      && ISXDIGIT (*(curr + 1))
+		      && *(curr + 2) == STYLE_MARKER_CHAR))
+		{
+		  /* Output content between our START position and CURR.  */
+		  int len = curr - start;
+		  if (len > 0)
+		    {
+		      if ((*info->fprintf_styled_func) (info->stream,
+							curr_style,
+							"%.*s",
+							len, start) < 0)
+			break;
+		    }
+
+		  if (*curr == '\0')
+		    break;
+
+		  /* Skip over the initial STYLE_MARKER_CHAR.  */
+		  ++curr;
+
+		  /* Update the CURR_STYLE.  As there are less than 16
+		     styles, it is possible, that if the input is corrupted
+		     in some way, that we might set CURR_STYLE to an
+		     invalid value.  Don't worry though, we check for this
+		     situation.  */
+		  if (*curr >= '0' && *curr <= '9')
+		    curr_style = (enum disassembler_style) (*curr - '0');
+		  else if (*curr >= 'a' && *curr <= 'f')
+		    curr_style = (enum disassembler_style) (*curr - 'a' + 10);
+		  else
+		    curr_style = dis_style_text;
+
+		  /* Check for an invalid style having been selected.  This
+		     should never happen, but it doesn't hurt to be a
+		     little paranoid.  */
+		  if (curr_style > dis_style_comment_start)
+		    curr_style = dis_style_text;
+
+		  /* Skip the hex character, and the closing STYLE_MARKER_CHAR.  */
+		  curr += 2;
+
+		  /* Reset the START to after the style marker.  */
+		  start = curr;
+		}
+	      else
+		++curr;
+	    }
+	  while (true);
 	}
+
+      /* Print the comment.  This works because only the last operand ever
+	 adds a comment.  If that ever changes then we'll need to be
+	 smarter here.  */
+      if (cmt[0] != '\0')
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "\t// %s", cmt);
     }
 
     if (notes && !no_notes)
       {
 	*has_notes = true;
-	(*info->fprintf_func) (info->stream, "  // note: %s", notes);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "  // note: %s", notes);
       }
+
+    obstack_free (&content, NULL);
 }
 
 /* Set NAME to a copy of INST's mnemonic with the "." suffix removed.  */
@@ -3359,10 +3523,12 @@ print_mnemonic_name (const aarch64_inst *inst, struct disassemble_info *info)
       char name[8];
 
       remove_dot_suffix (name, inst);
-      (*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
+      (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				    "%s.%s", name, inst->cond->names[0]);
     }
   else
-    (*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
+    (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
+				  "%s", inst->opcode->name);
 }
 
 /* Decide whether we need to print a comment after the operands of
@@ -3379,9 +3545,10 @@ print_comment (const aarch64_inst *inst, struct disassemble_info *info)
       remove_dot_suffix (name, inst);
       num_conds = ARRAY_SIZE (inst->cond->names);
       for (i = 1; i < num_conds && inst->cond->names[i]; ++i)
-	(*info->fprintf_func) (info->stream, "%s %s.%s",
-			       i == 1 ? "  //" : ",",
-			       name, inst->cond->names[i]);
+	(*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				      "%s %s.%s",
+				      i == 1 ? "  //" : ",",
+				      name, inst->cond->names[i]);
     }
 }
 
@@ -3398,28 +3565,30 @@ print_verifier_notes (aarch64_operand_error *detail,
      would not have succeeded.  We can safely ignore these.  */
   assert (detail->non_fatal);
 
-  (*info->fprintf_func) (info->stream, "  // note: ");
+  (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				"  // note: ");
   switch (detail->kind)
     {
     case AARCH64_OPDE_A_SHOULD_FOLLOW_B:
-      (*info->fprintf_func) (info->stream,
-			     _("this `%s' should have an immediately"
-			       " preceding `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("this `%s' should have an immediately"
+				      " preceding `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     case AARCH64_OPDE_EXPECTED_A_AFTER_B:
-      (*info->fprintf_func) (info->stream,
-			     _("expected `%s' after previous `%s'"),
-			     detail->data[0].s, detail->data[1].s);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    _("expected `%s' after previous `%s'"),
+				    detail->data[0].s, detail->data[1].s);
       break;
 
     default:
       assert (detail->error);
-      (*info->fprintf_func) (info->stream, "%s", detail->error);
+      (*info->fprintf_styled_func) (info->stream, dis_style_text,
+				    "%s", detail->error);
       if (detail->index >= 0)
-	(*info->fprintf_func) (info->stream, " at operand %d",
-			       detail->index + 1);
+	(*info->fprintf_styled_func) (info->stream, dis_style_text,
+				      " at operand %d", detail->index + 1);
       break;
     }
 }
@@ -3511,8 +3680,13 @@ print_insn_aarch64_word (bfd_vma pc,
     case ERR_NYI:
       /* Handle undefined instructions.  */
       info->insn_type = dis_noninsn;
-      (*info->fprintf_func) (info->stream,".inst\t0x%08x ; %s",
-			     word, err_msg[ret]);
+      (*info->fprintf_styled_func) (info->stream,
+				    dis_style_assembler_directive,
+				    ".inst\t");
+      (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
+				    "0x%08x", word);
+      (*info->fprintf_styled_func) (info->stream, dis_style_comment_start,
+				    " ; %s", err_msg[ret]);
       break;
     case ERR_OK:
       user_friendly_fixup (&inst);
@@ -3554,13 +3728,22 @@ print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
   switch (info->bytes_per_chunk)
     {
     case 1:
-      info->fprintf_func (info->stream, ".byte\t0x%02x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".byte\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%02x", word);
       break;
     case 2:
-      info->fprintf_func (info->stream, ".short\t0x%04x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".short\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%04x", word);
       break;
     case 4:
-      info->fprintf_func (info->stream, ".word\t0x%08x", word);
+      info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
+				 ".word\t");
+      info->fprintf_styled_func (info->stream, dis_style_immediate,
+				 "0x%08x", word);
       break;
     default:
       abort ();
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 1c93f836020..1d4668a3fbd 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -3038,18 +3038,78 @@ expand_fp_imm (int size, uint32_t imm8)
   return imm;
 }
 
+/* Return a string based on FMT with the register style applied.  */
+
+static const char *
+style_reg (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_register, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
+/* Return a string based on FMT with the immediate style applied.  */
+
+static const char *
+style_imm (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_immediate, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
+/* Return a string based on FMT with the sub-mnemonic style applied.  */
+
+static const char *
+style_sub_mnem (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_sub_mnemonic, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
+/* Return a string based on FMT with the address style applied.  */
+
+static const char *
+style_addr (struct aarch64_styler *styler, const char *fmt, ...)
+{
+  const char *txt;
+  va_list ap;
+
+  va_start (ap, fmt);
+  txt = styler->apply_style (styler, dis_style_address, fmt, ap);
+  va_end (ap);
+
+  return txt;
+}
+
 /* Produce the string representation of the register list operand *OPND
    in the buffer pointed by BUF of size SIZE.  PREFIX is the part of
    the register name that comes before the register number, such as "v".  */
 static void
 print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
-		     const char *prefix)
+		     const char *prefix, struct aarch64_styler *styler)
 {
   const int num_regs = opnd->reglist.num_regs;
   const int first_reg = opnd->reglist.first_regno;
   const int last_reg = (first_reg + num_regs - 1) & 0x1f;
   const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
-  char tb[8];	/* Temporary buffer.  */
+  char tb[16];	/* Temporary buffer.  */
 
   assert (opnd->type != AARCH64_OPND_LEt || opnd->reglist.has_index);
   assert (num_regs >= 1 && num_regs <= 4);
@@ -3057,7 +3117,8 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
   /* Prepare the index if any.  */
   if (opnd->reglist.has_index)
     /* PR 21096: The %100 is to silence a warning about possible truncation.  */
-    snprintf (tb, 8, "[%" PRIi64 "]", (opnd->reglist.index % 100));
+    snprintf (tb, sizeof (tb), "[%s]",
+	      style_imm (styler, "%" PRIi64, (opnd->reglist.index % 100)));
   else
     tb[0] = '\0';
 
@@ -3065,8 +3126,9 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
      more than two registers in the list, and the register numbers
      are monotonically increasing in increments of one.  */
   if (num_regs > 2 && last_reg > first_reg)
-    snprintf (buf, size, "{%s%d.%s-%s%d.%s}%s", prefix, first_reg, qlf_name,
-	      prefix, last_reg, qlf_name, tb);
+    snprintf (buf, size, "{%s-%s}%s",
+	      style_reg (styler, "%s%d.%s", prefix, first_reg, qlf_name),
+	      style_reg (styler, "%s%d.%s", prefix, last_reg, qlf_name), tb);
   else
     {
       const int reg0 = first_reg;
@@ -3077,21 +3139,30 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
       switch (num_regs)
 	{
 	case 1:
-	  snprintf (buf, size, "{%s%d.%s}%s", prefix, reg0, qlf_name, tb);
+	  snprintf (buf, size, "{%s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    tb);
 	  break;
 	case 2:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s}%s", prefix, reg0, qlf_name,
-		    prefix, reg1, qlf_name, tb);
+	  snprintf (buf, size, "{%s, %s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg1, qlf_name),
+		    tb);
 	  break;
 	case 3:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, tb);
+	  snprintf (buf, size, "{%s, %s, %s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg1, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg2, qlf_name),
+		    tb);
 	  break;
 	case 4:
-	  snprintf (buf, size, "{%s%d.%s, %s%d.%s, %s%d.%s, %s%d.%s}%s",
-		    prefix, reg0, qlf_name, prefix, reg1, qlf_name,
-		    prefix, reg2, qlf_name, prefix, reg3, qlf_name, tb);
+	  snprintf (buf, size, "{%s, %s, %s, %s}%s",
+		    style_reg (styler, "%s%d.%s", prefix, reg0, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg1, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg2, qlf_name),
+		    style_reg (styler, "%s%d.%s", prefix, reg3, qlf_name),
+		    tb);
 	  break;
 	}
     }
@@ -3103,32 +3174,41 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
 static void
 print_immediate_offset_address (char *buf, size_t size,
 				const aarch64_opnd_info *opnd,
-				const char *base)
+				const char *base,
+				struct aarch64_styler *styler)
 {
   if (opnd->addr.writeback)
     {
       if (opnd->addr.preind)
         {
 	  if (opnd->type == AARCH64_OPND_ADDR_SIMM10 && !opnd->addr.offset.imm)
-            snprintf (buf, size, "[%s]!", base);
+	    snprintf (buf, size, "[%s]!", style_reg (styler, base));
           else
-	    snprintf (buf, size, "[%s, #%d]!", base, opnd->addr.offset.imm);
+	    snprintf (buf, size, "[%s, %s]!",
+		      style_reg (styler, base),
+		      style_imm (styler, "#%d", opnd->addr.offset.imm));
         }
       else
-	snprintf (buf, size, "[%s], #%d", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "[%s], %s",
+		  style_reg (styler, base),
+		  style_imm (styler, "#%d", opnd->addr.offset.imm));
     }
   else
     {
       if (opnd->shifter.operator_present)
 	{
 	  assert (opnd->shifter.kind == AARCH64_MOD_MUL_VL);
-	  snprintf (buf, size, "[%s, #%d, mul vl]",
-		    base, opnd->addr.offset.imm);
+	  snprintf (buf, size, "[%s, %s, %s]",
+		    style_reg (styler, base),
+		    style_imm (styler, "#%d", opnd->addr.offset.imm),
+		    style_sub_mnem (styler, "mul vl"));
 	}
       else if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", base, opnd->addr.offset.imm);
+	snprintf (buf, size, "[%s, %s]",
+		  style_reg (styler, base),
+		  style_imm (styler, "#%d", opnd->addr.offset.imm));
       else
-	snprintf (buf, size, "[%s]", base);
+	snprintf (buf, size, "[%s]", style_reg (styler, base));
     }
 }
 
@@ -3138,9 +3218,10 @@ print_immediate_offset_address (char *buf, size_t size,
 static void
 print_register_offset_address (char *buf, size_t size,
 			       const aarch64_opnd_info *opnd,
-			       const char *base, const char *offset)
+			       const char *base, const char *offset,
+			       struct aarch64_styler *styler)
 {
-  char tb[16];			/* Temporary buffer.  */
+  char tb[32];			/* Temporary buffer.  */
   bool print_extend_p = true;
   bool print_amount_p = true;
   const char *shift_name = aarch64_operand_modifiers[opnd->shifter.kind].name;
@@ -3161,16 +3242,20 @@ print_register_offset_address (char *buf, size_t size,
   if (print_extend_p)
     {
       if (print_amount_p)
-	snprintf (tb, sizeof (tb), ", %s #%" PRIi64, shift_name,
+	snprintf (tb, sizeof (tb), ", %s %s",
+		  style_sub_mnem (styler, shift_name),
+		  style_imm (styler, "#%" PRIi64,
   /* PR 21096: The %100 is to silence a warning about possible truncation.  */
-		  (opnd->shifter.amount % 100));
+			     (opnd->shifter.amount % 100)));
       else
-	snprintf (tb, sizeof (tb), ", %s", shift_name);
+	snprintf (tb, sizeof (tb), ", %s",
+		  style_sub_mnem (styler, shift_name));
     }
   else
     tb[0] = '\0';
 
-  snprintf (buf, size, "[%s, %s%s]", base, offset, tb);
+  snprintf (buf, size, "[%s, %s%s]", style_reg (styler, base),
+	    style_reg (styler, offset), tb);
 }
 
 /* Print ZA tiles from imm8 in ZERO instruction.
@@ -3183,7 +3268,8 @@ print_register_offset_address (char *buf, size_t size,
     * An all-zeros immediate is disassembled as an empty list { }.
 */
 static void
-print_sme_za_list(char *buf, size_t size, int mask)
+print_sme_za_list (char *buf, size_t size, int mask,
+		   struct aarch64_styler *styler)
 {
   const char* zan[] = { "za",    "za0.h", "za1.h", "za0.s",
                         "za1.s", "za2.s", "za3.s", "za0.d",
@@ -3203,9 +3289,9 @@ print_sme_za_list(char *buf, size_t size, int mask)
         {
           mask &= ~zan_v[i];
           if (k > 1)
-            k += snprintf (buf + k, size - k, ", %s", zan[i]);
-          else
-            k += snprintf (buf + k, size - k, "%s", zan[i]);
+	    k += snprintf (buf + k, size - k, ", ");
+
+	  k += snprintf (buf + k, size - k, "%s", style_reg (styler, zan[i]));
         }
       if (mask == 0)
         break;
@@ -3230,7 +3316,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 		       const aarch64_opnd_info *opnds, int idx, int *pcrel_p,
 		       bfd_vma *address, char** notes,
 		       char *comment, size_t comment_size,
-		       aarch64_feature_set features)
+		       aarch64_feature_set features,
+		       struct aarch64_styler *styler)
 {
   unsigned int i, num_conds;
   const char *name = NULL;
@@ -3279,7 +3366,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       assert (opnd->qualifier == AARCH64_OPND_QLF_W
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
       snprintf (buf, size, "%s",
-		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+		style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						     opnd->qualifier, 0)));
       break;
 
     case AARCH64_OPND_Rd_SP:
@@ -3292,7 +3380,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      || opnd->qualifier == AARCH64_OPND_QLF_X
 	      || opnd->qualifier == AARCH64_OPND_QLF_SP);
       snprintf (buf, size, "%s",
-		get_int_reg_name (opnd->reg.regno, opnd->qualifier, 1));
+		style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						     opnd->qualifier, 1)));
       break;
 
     case AARCH64_OPND_Rm_EXT:
@@ -3312,19 +3401,21 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	    {
 	      /* Shifter omitted.  */
 	      snprintf (buf, size, "%s",
-			get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+			style_reg (styler,
+				   get_int_reg_name (opnd->reg.regno,
+						     opnd->qualifier, 0)));
 	      break;
 	    }
 	}
       if (opnd->shifter.amount)
-	snprintf (buf, size, "%s, %s #%" PRIi64,
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
-		  aarch64_operand_modifiers[kind].name,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0)),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[kind].name),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       else
 	snprintf (buf, size, "%s, %s",
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
-		  aarch64_operand_modifiers[kind].name);
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0)),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[kind].name));
       break;
 
     case AARCH64_OPND_Rm_SFT:
@@ -3332,12 +3423,13 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      || opnd->qualifier == AARCH64_OPND_QLF_X);
       if (opnd->shifter.amount == 0 && opnd->shifter.kind == AARCH64_MOD_LSL)
 	snprintf (buf, size, "%s",
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0));
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						       opnd->qualifier, 0)));
       else
-	snprintf (buf, size, "%s, %s #%" PRIi64,
-		  get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0),
-		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_reg (styler, get_int_reg_name (opnd->reg.regno, opnd->qualifier, 0)),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[opnd->shifter.kind].name),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       break;
 
     case AARCH64_OPND_Fd:
@@ -3353,16 +3445,19 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Vd:
     case AARCH64_OPND_SVE_Vm:
     case AARCH64_OPND_SVE_Vn:
-      snprintf (buf, size, "%s%d", aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reg.regno);
+      snprintf (buf, size, "%s",
+		style_reg (styler, "%s%d",
+			   aarch64_get_qualifier_name (opnd->qualifier),
+			   opnd->reg.regno));
       break;
 
     case AARCH64_OPND_Va:
     case AARCH64_OPND_Vd:
     case AARCH64_OPND_Vn:
     case AARCH64_OPND_Vm:
-      snprintf (buf, size, "v%d.%s", opnd->reg.regno,
-		aarch64_get_qualifier_name (opnd->qualifier));
+      snprintf (buf, size, "%s",
+		style_reg (styler, "v%d.%s", opnd->reg.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_Ed:
@@ -3370,21 +3465,24 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_Em:
     case AARCH64_OPND_Em16:
     case AARCH64_OPND_SM3_IMM2:
-      snprintf (buf, size, "v%d.%s[%" PRIi64 "]", opnd->reglane.regno,
-		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+      snprintf (buf, size, "%s[%s]",
+		style_reg (styler, "v%d.%s", opnd->reglane.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+		style_imm (styler, "%" PRIi64, opnd->reglane.index));
       break;
 
     case AARCH64_OPND_VdD1:
     case AARCH64_OPND_VnD1:
-      snprintf (buf, size, "v%d.d[1]", opnd->reg.regno);
+      snprintf (buf, size, "%s[%s]",
+		style_reg (styler, "v%d.d", opnd->reg.regno),
+		style_imm (styler, "1"));
       break;
 
     case AARCH64_OPND_LVn:
     case AARCH64_OPND_LVt:
     case AARCH64_OPND_LVt_AL:
     case AARCH64_OPND_LEt:
-      print_register_list (buf, size, opnd, "v");
+      print_register_list (buf, size, opnd, "v", styler);
       break;
 
     case AARCH64_OPND_SVE_Pd:
@@ -3397,14 +3495,17 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Pt:
     case AARCH64_OPND_SME_Pm:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "p%d", opnd->reg.regno);
+	snprintf (buf, size, "%s",
+		  style_reg (styler, "p%d", opnd->reg.regno));
       else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
 	       || opnd->qualifier == AARCH64_OPND_QLF_P_M)
-	snprintf (buf, size, "p%d/%s", opnd->reg.regno,
-		  aarch64_get_qualifier_name (opnd->qualifier));
+	snprintf (buf, size, "%s",
+		  style_reg (styler, "p%d/%s", opnd->reg.regno,
+			     aarch64_get_qualifier_name (opnd->qualifier)));
       else
-	snprintf (buf, size, "p%d.%s", opnd->reg.regno,
-		  aarch64_get_qualifier_name (opnd->qualifier));
+	snprintf (buf, size, "%s",
+		  style_reg (styler, "p%d.%s", opnd->reg.regno,
+			     aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_SVE_Za_5:
@@ -3415,15 +3516,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zn:
     case AARCH64_OPND_SVE_Zt:
       if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
-	snprintf (buf, size, "z%d", opnd->reg.regno);
+	snprintf (buf, size, "%s", style_reg (styler, "z%d", opnd->reg.regno));
       else
-	snprintf (buf, size, "z%d.%s", opnd->reg.regno,
-		  aarch64_get_qualifier_name (opnd->qualifier));
+	snprintf (buf, size, "%s",
+		  style_reg (styler, "z%d.%s", opnd->reg.regno,
+			     aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_SVE_ZnxN:
     case AARCH64_OPND_SVE_ZtxN:
-      print_register_list (buf, size, opnd, "z");
+      print_register_list (buf, size, opnd, "z", styler);
       break;
 
     case AARCH64_OPND_SVE_Zm3_INDEX:
@@ -3432,55 +3534,61 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_Zm4_11_INDEX:
     case AARCH64_OPND_SVE_Zm4_INDEX:
     case AARCH64_OPND_SVE_Zn_INDEX:
-      snprintf (buf, size, "z%d.%s[%" PRIi64 "]", opnd->reglane.regno,
-		aarch64_get_qualifier_name (opnd->qualifier),
-		opnd->reglane.index);
+      snprintf (buf, size, "%s[%s]",
+		style_reg (styler, "z%d.%s", opnd->reglane.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+		style_imm (styler, "%" PRIi64, opnd->reglane.index));
       break;
 
     case AARCH64_OPND_SME_ZAda_2b:
     case AARCH64_OPND_SME_ZAda_3b:
-      snprintf (buf, size, "za%d.%s", opnd->reg.regno,
-                aarch64_get_qualifier_name (opnd->qualifier));
+      snprintf (buf, size, "%s",
+		style_reg (styler, "za%d.%s", opnd->reg.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)));
       break;
 
     case AARCH64_OPND_SME_ZA_HV_idx_src:
     case AARCH64_OPND_SME_ZA_HV_idx_dest:
     case AARCH64_OPND_SME_ZA_HV_idx_ldstr:
-      snprintf (buf, size, "%sza%d%c.%s[w%d, %d]%s",
-                opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "{" : "",
-                opnd->za_tile_vector.regno,
-                opnd->za_tile_vector.v == 1 ? 'v' : 'h',
-                aarch64_get_qualifier_name (opnd->qualifier),
-                opnd->za_tile_vector.index.regno,
-                opnd->za_tile_vector.index.imm,
-                opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "}" : "");
+      snprintf (buf, size, "%s%s[%s, %s]%s",
+		opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "{" : "",
+		style_reg (styler, "za%d%c.%s",
+			   opnd->za_tile_vector.regno,
+			   opnd->za_tile_vector.v == 1 ? 'v' : 'h',
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+		style_reg (styler, "w%d", opnd->za_tile_vector.index.regno),
+		style_imm (styler, "%d", opnd->za_tile_vector.index.imm),
+		opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "}" : "");
       break;
 
     case AARCH64_OPND_SME_list_of_64bit_tiles:
-      print_sme_za_list (buf, size, opnd->reg.regno);
+      print_sme_za_list (buf, size, opnd->reg.regno, styler);
       break;
 
     case AARCH64_OPND_SME_ZA_array:
-      snprintf (buf, size, "za[w%d, %d]",
-                opnd->za_tile_vector.index.regno,
-                opnd->za_tile_vector.index.imm);
+      snprintf (buf, size, "%s[%s, %s]",
+		style_reg (styler, "za"),
+		style_reg (styler, "w%d", opnd->za_tile_vector.index.regno),
+		style_imm (styler, "%d", opnd->za_tile_vector.index.imm));
       break;
 
     case AARCH64_OPND_SME_SM_ZA:
-      snprintf (buf, size, "%s", opnd->reg.regno == 's' ? "sm" : "za");
+      snprintf (buf, size, "%s",
+		style_reg (styler, opnd->reg.regno == 's' ? "sm" : "za"));
       break;
 
     case AARCH64_OPND_SME_PnT_Wm_imm:
-      snprintf (buf, size, "p%d.%s[w%d, %d]",
-                opnd->za_tile_vector.regno,
-                aarch64_get_qualifier_name (opnd->qualifier),
-                opnd->za_tile_vector.index.regno,
-                opnd->za_tile_vector.index.imm);
+      snprintf (buf, size, "%s[%s, %s]",
+		style_reg (styler, "p%d.%s", opnd->za_tile_vector.regno,
+			   aarch64_get_qualifier_name (opnd->qualifier)),
+                style_reg (styler, "w%d", opnd->za_tile_vector.index.regno),
+                style_imm (styler, "%d", opnd->za_tile_vector.index.imm));
       break;
 
     case AARCH64_OPND_CRn:
     case AARCH64_OPND_CRm:
-      snprintf (buf, size, "C%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, "%s",
+		style_reg (styler, "C%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_IDX:
@@ -3521,7 +3629,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_IMM_ROT1:
     case AARCH64_OPND_SVE_IMM_ROT2:
     case AARCH64_OPND_SVE_IMM_ROT3:
-      snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+      snprintf (buf, size, "%s",
+		style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_SVE_I1_HALF_ONE:
@@ -3530,7 +3639,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       {
 	single_conv_t c;
 	c.i = opnd->imm.value;
-	snprintf (buf, size, "#%.1f", c.f);
+	snprintf (buf, size, "%s", style_imm (styler, "#%.1f", c.f));
 	break;
       }
 
@@ -3541,9 +3650,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[enum_value]);
+	snprintf (buf, size, "%s",
+		  style_reg (styler, aarch64_sve_pattern_array[enum_value]));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s",
+		  style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_SVE_PATTERN_SCALED:
@@ -3554,15 +3665,20 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_pattern_array));
       if (aarch64_sve_pattern_array[opnd->imm.value])
-	snprintf (buf, size, "%s", aarch64_sve_pattern_array[opnd->imm.value]);
+	snprintf (buf, size, "%s",
+		  style_reg (styler,
+			     aarch64_sve_pattern_array[opnd->imm.value]));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s",
+		  style_imm (styler, "#%" PRIi64, opnd->imm.value));
       if (opnd->shifter.operator_present)
 	{
 	  size_t len = strlen (buf);
-	  snprintf (buf + len, size - len, ", %s #%" PRIi64,
-		    aarch64_operand_modifiers[opnd->shifter.kind].name,
-		    opnd->shifter.amount);
+	  const char *shift_name
+	    = aarch64_operand_modifiers[opnd->shifter.kind].name;
+	  snprintf (buf + len, size - len, ", %s %s",
+		    style_sub_mnem (styler, shift_name),
+		    style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
 	}
       break;
 
@@ -3570,9 +3686,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       enum_value = opnd->imm.value;
       assert (enum_value < ARRAY_SIZE (aarch64_sve_prfop_array));
       if (aarch64_sve_prfop_array[enum_value])
-	snprintf (buf, size, "%s", aarch64_sve_prfop_array[enum_value]);
+	snprintf (buf, size, "%s",
+		  style_reg (styler, aarch64_sve_prfop_array[enum_value]));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s",
+		  style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_IMM_MOV:
@@ -3581,12 +3699,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	case 4:	/* e.g. MOV Wd, #<imm32>.  */
 	    {
 	      int imm32 = opnd->imm.value;
-	      snprintf (buf, size, "#0x%-20x", imm32);
+	      snprintf (buf, size, "%s",
+			style_imm (styler, "#0x%-20x", imm32));
 	      snprintf (comment, comment_size, "#%d", imm32);
 	    }
 	  break;
 	case 8:	/* e.g. MOV Xd, #<imm64>.  */
-	  snprintf (buf, size, "#0x%-20" PRIx64, opnd->imm.value);
+	  snprintf (buf, size, "%s", style_imm (styler, "#0x%-20" PRIx64,
+						opnd->imm.value));
 	  snprintf (comment, comment_size, "#%" PRIi64, opnd->imm.value);
 	  break;
 	default:
@@ -3596,7 +3716,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       break;
 
     case AARCH64_OPND_FPIMM0:
-      snprintf (buf, size, "#0.0");
+      snprintf (buf, size, "%s", style_imm (styler, "#0.0"));
       break;
 
     case AARCH64_OPND_LIMM:
@@ -3606,30 +3726,38 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_LIMM:
     case AARCH64_OPND_SVE_LIMM_MOV:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#0x%" PRIx64 ", lsl #%" PRIi64, opnd->imm.value,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value),
+		  style_sub_mnem (styler, "lsl"),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       else
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size, "%s",
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_SIMD_IMM:
     case AARCH64_OPND_SIMD_IMM_SFT:
       if ((! opnd->shifter.amount && opnd->shifter.kind == AARCH64_MOD_LSL)
 	  || opnd->shifter.kind == AARCH64_MOD_NONE)
-	snprintf (buf, size, "#0x%" PRIx64, opnd->imm.value);
+	snprintf (buf, size, "%s",
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value));
       else
-	snprintf (buf, size, "#0x%" PRIx64 ", %s #%" PRIi64, opnd->imm.value,
-		  aarch64_operand_modifiers[opnd->shifter.kind].name,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_imm (styler, "#0x%" PRIx64, opnd->imm.value),
+		  style_sub_mnem (styler, aarch64_operand_modifiers[opnd->shifter.kind].name),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       break;
 
     case AARCH64_OPND_SVE_AIMM:
     case AARCH64_OPND_SVE_ASIMM:
       if (opnd->shifter.amount)
-	snprintf (buf, size, "#%" PRIi64 ", lsl #%" PRIi64, opnd->imm.value,
-		  opnd->shifter.amount);
+	snprintf (buf, size, "%s, %s %s",
+		  style_imm (styler, "#%" PRIi64, opnd->imm.value),
+		  style_sub_mnem (styler, "lsl"),
+		  style_imm (styler, "#%" PRIi64, opnd->shifter.amount));
       else
-	snprintf (buf, size, "#%" PRIi64, opnd->imm.value);
+	snprintf (buf, size, "%s",
+		  style_imm (styler, "#%" PRIi64, opnd->imm.value));
       break;
 
     case AARCH64_OPND_FPIMM:
@@ -3641,21 +3769,21 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	    {
 	      half_conv_t c;
 	      c.i = expand_fp_imm (2, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size, "%s", style_imm (styler, "#%.18e", c.f));
 	    }
 	  break;
 	case 4:	/* e.g. FMOV <Vd>.4S, #<imm>.  */
 	    {
 	      single_conv_t c;
 	      c.i = expand_fp_imm (4, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.f);
+	      snprintf (buf, size, "%s", style_imm (styler, "#%.18e", c.f));
 	    }
 	  break;
 	case 8:	/* e.g. FMOV <Sd>, #<imm>.  */
 	    {
 	      double_conv_t c;
 	      c.i = expand_fp_imm (8, opnd->imm.value);
-	      snprintf (buf, size,  "#%.18e", c.d);
+	      snprintf (buf, size, "%s", style_imm (styler, "#%.18e", c.d));
 	    }
 	  break;
 	default:
@@ -3676,12 +3804,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	      (int64_t) get_optional_operand_default_value (opcode)))
 	/* Omit the operand, e.g. DCPS1.  */
 	break;
-      snprintf (buf, size, "#0x%x", (unsigned int)opnd->imm.value);
+      snprintf (buf, size, "%s",
+		style_imm (styler, "#0x%x", (unsigned int) opnd->imm.value));
       break;
 
     case AARCH64_OPND_COND:
     case AARCH64_OPND_COND1:
-      snprintf (buf, size, "%s", opnd->cond->names[0]);
+      snprintf (buf, size, "%s",
+		style_sub_mnem (styler, opnd->cond->names[0]));
       num_conds = ARRAY_SIZE (opnd->cond->names);
       for (i = 1; i < num_conds && opnd->cond->names[i]; ++i)
 	{
@@ -3706,7 +3836,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, "%s", style_addr (styler, "#0x%" PRIx64 , addr));
       break;
 
     case AARCH64_OPND_ADDR_PCREL14:
@@ -3722,7 +3852,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	 in the disassemble_info will take care of the printing.  But some
 	 other callers may be still interested in getting the string in *STR,
 	 so here we do snprintf regardless.  */
-      snprintf (buf, size, "#0x%" PRIx64, addr);
+      snprintf (buf, size, "%s", style_addr (styler, "#0x%" PRIx64, addr));
       break;
 
     case AARCH64_OPND_ADDR_SIMPLE:
@@ -3732,12 +3862,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (opnd->type == AARCH64_OPND_SIMD_ADDR_POST)
 	{
 	  if (opnd->addr.offset.is_reg)
-	    snprintf (buf, size, "[%s], x%d", name, opnd->addr.offset.regno);
+	    snprintf (buf, size, "[%s], %s",
+		      style_reg (styler, name),
+		      style_reg (styler, "x%d", opnd->addr.offset.regno));
 	  else
-	    snprintf (buf, size, "[%s], #%d", name, opnd->addr.offset.imm);
+	    snprintf (buf, size, "[%s], %s",
+		      style_reg (styler, name),
+		      style_imm (styler, "#%d", opnd->addr.offset.imm));
 	}
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "[%s]", style_reg (styler, name));
       break;
 
     case AARCH64_OPND_ADDR_REGOFF:
@@ -3753,14 +3887,14 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RX_LSL3:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_offset_int_reg_name (opnd));
+	 get_offset_int_reg_name (opnd), styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZX:
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0));
+	 get_64bit_int_reg_name (opnd->addr.offset.regno, 0), styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_RZ:
@@ -3777,7 +3911,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RZ_XTW3_22:
       print_register_offset_address
 	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 styler);
       break;
 
     case AARCH64_OPND_ADDR_SIMM7:
@@ -3801,7 +3936,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_RI_U6x4:
     case AARCH64_OPND_SVE_ADDR_RI_U6x8:
       print_immediate_offset_address
-	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1));
+	(buf, size, opnd, get_64bit_int_reg_name (opnd->addr.base_regno, 1),
+	 styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZI_U5:
@@ -3810,7 +3946,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SVE_ADDR_ZI_U5x8:
       print_immediate_offset_address
 	(buf, size, opnd,
-	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
+	 styler);
       break;
 
     case AARCH64_OPND_SVE_ADDR_ZZ_LSL:
@@ -3819,15 +3956,18 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       print_register_offset_address
 	(buf, size, opnd,
 	 get_addr_sve_reg_name (opnd->addr.base_regno, opnd->qualifier),
-	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier));
+	 get_addr_sve_reg_name (opnd->addr.offset.regno, opnd->qualifier),
+	 styler);
       break;
 
     case AARCH64_OPND_ADDR_UIMM12:
       name = get_64bit_int_reg_name (opnd->addr.base_regno, 1);
       if (opnd->addr.offset.imm)
-	snprintf (buf, size, "[%s, #%d]", name, opnd->addr.offset.imm);
+	snprintf (buf, size, "[%s, %s]",
+		  style_reg (styler, name),
+		  style_imm (styler, "#%d", opnd->addr.offset.imm));
       else
-	snprintf (buf, size, "[%s]", name);
+	snprintf (buf, size, "[%s]", style_reg (styler, name));
       break;
 
     case AARCH64_OPND_SYSREG:
@@ -3866,14 +4006,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
 	}
 
       if (name)
-	snprintf (buf, size, "%s", name);
+	snprintf (buf, size, "%s", style_reg (styler, name));
       else
 	{
 	  /* Implementation defined system register.  */
 	  unsigned int value = opnd->sysreg.value;
-	  snprintf (buf, size, "s%u_%u_c%u_c%u_%u", (value >> 14) & 0x3,
-		    (value >> 11) & 0x7, (value >> 7) & 0xf, (value >> 3) & 0xf,
-		    value & 0x7);
+	  snprintf (buf, size, "%s",
+		    style_reg (styler, "s%u_%u_c%u_c%u_%u",
+			       (value >> 14) & 0x3, (value >> 11) & 0x7,
+			       (value >> 7) & 0xf, (value >> 3) & 0xf,
+			       value & 0x7));
 	}
       break;
 
@@ -3891,7 +4033,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
             break;
           }
       assert (aarch64_pstatefields[i].name);
-      snprintf (buf, size, "%s", aarch64_pstatefields[i].name);
+      snprintf (buf, size, "%s",
+		style_reg (styler, aarch64_pstatefields[i].name));
       break;
 
     case AARCH64_OPND_SYSREG_AT:
@@ -3899,12 +4042,18 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
     case AARCH64_OPND_SYSREG_IC:
     case AARCH64_OPND_SYSREG_TLBI:
     case AARCH64_OPND_SYSREG_SR:
-      snprintf (buf, size, "%s", opnd->sysins_op->name);
+      snprintf (buf, size, "%s", style_reg (styler, opnd->sysins_op->name));
       break;
 
     case AARCH64_OPND_BARRIER:
     case AARCH64_OPND_BARRIER_DSB_NXS:
-      snprintf (buf, size, "%s", opnd->barrier->name);
+      {
+	if (opnd->barrier->name[0] == '#')
+	  snprintf (buf, size, "%s", style_imm (styler, opnd->barrier->name));
+	else
+	  snprintf (buf, size, "%s",
+		    style_sub_mnem (styler, opnd->barrier->name));
+      }
       break;
 
     case AARCH64_OPND_BARRIER_ISB:
@@ -3912,34 +4061,40 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       if (! optional_operand_p (opcode, idx)
 	  || (opnd->barrier->value
 	      != get_optional_operand_default_value (opcode)))
-	snprintf (buf, size, "#0x%x", opnd->barrier->value);
+	snprintf (buf, size, "%s",
+		  style_imm (styler, "#0x%x", opnd->barrier->value));
       break;
 
     case AARCH64_OPND_PRFOP:
       if (opnd->prfop->name != NULL)
-	snprintf (buf, size, "%s", opnd->prfop->name);
+	snprintf (buf, size, "%s", style_sub_mnem (styler, opnd->prfop->name));
       else
-	snprintf (buf, size, "#0x%02x", opnd->prfop->value);
+	snprintf (buf, size, "%s", style_imm (styler, "#0x%02x",
+					      opnd->prfop->value));
       break;
 
     case AARCH64_OPND_BARRIER_PSB:
-      snprintf (buf, size, "csync");
+      snprintf (buf, size, "%s", style_sub_mnem (styler, "csync"));
       break;
 
     case AARCH64_OPND_BTI_TARGET:
       if ((HINT_FLAG (opnd->hint_option->value) & HINT_OPD_F_NOPRINT) == 0)
-	snprintf (buf, size, "%s", opnd->hint_option->name);
+	snprintf (buf, size, "%s",
+		  style_sub_mnem (styler, opnd->hint_option->name));
       break;
 
     case AARCH64_OPND_MOPS_ADDR_Rd:
     case AARCH64_OPND_MOPS_ADDR_Rs:
       snprintf (buf, size, "[%s]!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+		style_reg (styler,
+			   get_int_reg_name (opnd->reg.regno,
+					     AARCH64_OPND_QLF_X, 0)));
       break;
 
     case AARCH64_OPND_MOPS_WB_Rn:
       snprintf (buf, size, "%s!",
-		get_int_reg_name (opnd->reg.regno, AARCH64_OPND_QLF_X, 0));
+		style_reg (styler, get_int_reg_name (opnd->reg.regno,
+						     AARCH64_OPND_QLF_X, 0)));
       break;
 
     default:
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index e2e5a2608d6..29100f310ed 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -610,6 +610,7 @@ disassemble_init_for_target (struct disassemble_info * info)
     case bfd_arch_aarch64:
       info->symbol_is_valid = aarch64_symbol_is_valid;
       info->disassembler_needs_relocs = true;
+      info->created_styled_output = true;
       break;
 #endif
 #ifdef ARCH_arc
-- 
2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCHv5 1/2] opcodes: add new sub-mnemonic disassembler style
  2022-07-21  8:56                   ` [PATCHv5 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
@ 2022-07-25 13:34                     ` Andrew Burgess
  0 siblings, 0 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-07-25 13:34 UTC (permalink / raw)
  To: Andrew Burgess via Binutils, binutils; +Cc: Richard Earnshaw

Andrew Burgess via Binutils <binutils@sourceware.org> writes:

> When adding libopcodes disassembler styling support for AArch64, it
> feels like the results would be improved by having a new sub-mnemonic
> style.  This will be used in cases like:
>
>   add    w16, w7, w1, uxtb #2
>                       ^^^^----- Here
>
> And:
>
>   cinc   w0, w1, ne
>                  ^^----- Here
>
> This commit just adds the new style, and prepares objdump to handle
> the style.  A later commit will add AArch64 styling, and will actually
> make use of the style.
>
> As this style is currently unused, there should be no user visible
> changes after this commit.

The dis_style_sub_mnemonic style has now been merged upstream as part of
the ppc styling patches.  The other patch in this series still needs
approval.

Thanks,
Andrew



> ---
>  binutils/objdump.c | 2 ++
>  include/dis-asm.h  | 7 +++++++
>  2 files changed, 9 insertions(+)
>
> diff --git a/binutils/objdump.c b/binutils/objdump.c
> index 67824053527..4076587151c 100644
> --- a/binutils/objdump.c
> +++ b/binutils/objdump.c
> @@ -2167,6 +2167,7 @@ objdump_color_for_disassembler_style (enum disassembler_style style)
>  	{
>  	case dis_style_symbol: color = 32; break;
>          case dis_style_assembler_directive:
> +	case dis_style_sub_mnemonic:
>  	case dis_style_mnemonic: color = 33; break;
>  	case dis_style_register: color = 34; break;
>  	case dis_style_address:
> @@ -2185,6 +2186,7 @@ objdump_color_for_disassembler_style (enum disassembler_style style)
>  	{
>  	case dis_style_symbol: color = 40; break;
>          case dis_style_assembler_directive:
> +	case dis_style_sub_mnemonic:
>  	case dis_style_mnemonic: color = 142; break;
>  	case dis_style_register: color = 27; break;
>  	case dis_style_address:
> diff --git a/include/dis-asm.h b/include/dis-asm.h
> index 4f91df12498..f1a83dc84e5 100644
> --- a/include/dis-asm.h
> +++ b/include/dis-asm.h
> @@ -62,6 +62,13 @@ enum disassembler_style
>       instructions.  */
>    dis_style_mnemonic,
>  
> +  /* Some architectures include additional mnemonic like fields within the
> +     instruction operands, e.g. on aarch64 'add w16, w7, w1, lsl #2' where
> +     the 'lsl' is an additional piece of text that describes how the
> +     instruction should behave.  This sub-mnemonic style can be used for
> +     these pieces of text.  */
> +  dis_style_sub_mnemonic,
> +
>    /* For things that aren't real machine instructions, but rather
>       assembler directives, e.g. .byte, etc.  */
>    dis_style_assembler_directive,
> -- 
> 2.25.4


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCHv4 1/2] opcodes: add new sub-mnemonic disassembler style
  2022-07-08 10:25             ` [PATCHv4 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
@ 2022-07-26 13:54               ` Nick Clifton
  0 siblings, 0 replies; 31+ messages in thread
From: Nick Clifton @ 2022-07-26 13:54 UTC (permalink / raw)
  To: Andrew Burgess, binutils

Hi Andrew,

> This commit just adds the new style, and prepares objdump to handle
> the style.  A later commit will add AArch64 styling, and will actually
> make use of the style.

Approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCHv5 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-07-21  8:56                   ` [PATCHv5 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
@ 2022-07-26 13:55                     ` Nick Clifton
  2022-07-29 13:12                       ` Andrew Burgess
  0 siblings, 1 reply; 31+ messages in thread
From: Nick Clifton @ 2022-07-26 13:55 UTC (permalink / raw)
  To: Andrew Burgess, binutils; +Cc: Richard Earnshaw

Hi Andrew,

> This commit enables disassembler styling for AArch64.  After this
> commit it is possible to have objdump style AArch64 disassembler
> output (using --disassembler-color option).  Once the required GDB
> patches are merged, GDB will also style the disassembler output.

Patch approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCHv5 2/2] libopcodes/aarch64: add support for disassembler styling
  2022-07-26 13:55                     ` Nick Clifton
@ 2022-07-29 13:12                       ` Andrew Burgess
  0 siblings, 0 replies; 31+ messages in thread
From: Andrew Burgess @ 2022-07-29 13:12 UTC (permalink / raw)
  To: Nick Clifton, binutils; +Cc: Richard Earnshaw

Nick Clifton via Binutils <binutils@sourceware.org> writes:

> Hi Andrew,
>
>> This commit enables disassembler styling for AArch64.  After this
>> commit it is possible to have objdump style AArch64 disassembler
>> output (using --disassembler-color option).  Once the required GDB
>> patches are merged, GDB will also style the disassembler output.
>
> Patch approved - please apply.

Thanks, I've pushed this now.

Andrew


^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2022-07-29 13:12 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-21 11:22 [PATCH 0/2] AArch64 libopcodes styling Andrew Burgess
2022-06-21 11:22 ` [PATCH 1/2] opcodes/aarch64: split off creation of comment text in disassembler Andrew Burgess
2022-06-22 11:02   ` Nick Clifton
2022-06-29 11:19     ` Andrew Burgess
2022-06-21 11:22 ` [PATCH 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
2022-06-22 11:15   ` Nick Clifton
2022-06-29 11:01     ` Andrew Burgess
2022-06-29 11:12       ` Jan Beulich
2022-06-29 12:36   ` Richard Earnshaw
2022-07-04  9:52   ` Nick Clifton
2022-07-05 12:45 ` [PATCHv2 0/2] AArch64 libopcodes styling Andrew Burgess
2022-07-05 12:46   ` [PATCHv2 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
2022-07-05 12:46   ` [PATCHv2 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
2022-07-05 12:51     ` Andrew Burgess
2022-07-05 13:10       ` Richard Earnshaw
2022-07-07 10:23         ` [PATCHv3 0/2] AArch64 libopcodes styling Andrew Burgess
2022-07-07 10:23           ` [PATCHv3 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
2022-07-07 10:23           ` [PATCHv3 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
2022-07-07 10:44             ` Andrew Burgess
2022-07-08 10:25           ` [PATCHv4 0/2] AArch64 libopcodes styling Andrew Burgess
2022-07-08 10:25             ` [PATCHv4 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
2022-07-26 13:54               ` Nick Clifton
2022-07-08 10:25             ` [PATCHv4 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
2022-07-19 15:33               ` Richard Earnshaw
2022-07-21  8:56                 ` [PATCHv5 0/2] AArch64 libopcodes styling Andrew Burgess
2022-07-21  8:56                   ` [PATCHv5 1/2] opcodes: add new sub-mnemonic disassembler style Andrew Burgess
2022-07-25 13:34                     ` Andrew Burgess
2022-07-21  8:56                   ` [PATCHv5 2/2] libopcodes/aarch64: add support for disassembler styling Andrew Burgess
2022-07-26 13:55                     ` Nick Clifton
2022-07-29 13:12                       ` Andrew Burgess
2022-07-19 12:52             ` [PATCHv4 0/2] AArch64 libopcodes styling Andrew Burgess

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).