[PATCH v2] LoongArch: Add new option annotate for objdump

zhaozhou <[email protected]> Thu, 30 Jul 2026 10:14:53 +0800
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
Add LoongArch architecture new option, objdump -dM annotate: prints
disassembly along with annotations for dbar instructions.
---
 .../binutils-all/loongarch64/annotate-dbar.d  | 43 ++++++++++++
 .../binutils-all/loongarch64/annotate-dbar.s  | 34 +++++++++
 include/opcode/loongarch.h                    |  3 +
 opcodes/loongarch-dis.c                       | 69 +++++++++++++++++++
 4 files changed, 149 insertions(+)
 create mode 100644 binutils/testsuite/binutils-all/loongarch64/annotate-dbar.d
 create mode 100644 binutils/testsuite/binutils-all/loongarch64/annotate-dbar.s

diff --git a/binutils/testsuite/binutils-all/loongarch64/annotate-dbar.d b/binutils/testsuite/binutils-all/loongarch64/annotate-dbar.d
new file mode 100644
index 00000000000..9db6facca7c
--- /dev/null
+++ b/binutils/testsuite/binutils-all/loongarch64/annotate-dbar.d
@@ -0,0 +1,43 @@
+# Skip annotate which reserved hint values such as 0xf, 0x1f and 0x7000.
+#name: Check annotate of dbar
+#source: annotate-dbar.s
+#objdump: -d -M annotate
+
+#...
+Disassembly of section \.text:
+
+0+ <.text>:
+   0:	38720000 	dbar        	0x0	#  RW|RW
+   4:	38720001 	dbar        	0x1	#  RW|R 
+   8:	38720002 	dbar        	0x2	#  RW| W
+   c:	38720003 	dbar        	0x3	#  RW|  
+  10:	38720004 	dbar        	0x4	#  R |RW
+  14:	38720005 	dbar        	0x5	#  R |R 
+  18:	38720006 	dbar        	0x6	#  R | W
+  1c:	38720007 	dbar        	0x7	#  R |  
+  20:	38720008 	dbar        	0x8	#   W|RW
+  24:	38720009 	dbar        	0x9	#   W|R 
+  28:	3872000a 	dbar        	0xa	#   W| W
+  2c:	3872000b 	dbar        	0xb	#   W|  
+  30:	3872000c 	dbar        	0xc	#    |RW
+  34:	3872000d 	dbar        	0xd	#    |R 
+  38:	3872000e 	dbar        	0xe	#    | W
+  3c:	3872000f 	dbar        	0xf
+  40:	38720010 	dbar        	0x10	# CRW|RW
+  44:	38720011 	dbar        	0x11	# CRW|R 
+  48:	38720012 	dbar        	0x12	# CRW| W
+  4c:	38720013 	dbar        	0x13	# CRW|  
+  50:	38720014 	dbar        	0x14	# CR |RW
+  54:	38720015 	dbar        	0x15	# CR |R 
+  58:	38720016 	dbar        	0x16	# CR | W
+  5c:	38720017 	dbar        	0x17	# CR |  
+  60:	38720018 	dbar        	0x18	# C W|RW
+  64:	38720019 	dbar        	0x19	# C W|R 
+  68:	3872001a 	dbar        	0x1a	# C W| W
+  6c:	3872001b 	dbar        	0x1b	# C W|  
+  70:	3872001c 	dbar        	0x1c	# C  |RW
+  74:	3872001d 	dbar        	0x1d	# C  |R 
+  78:	3872001e 	dbar        	0x1e	# C  | W
+  7c:	3872001f 	dbar        	0x1f
+  80:	38720700 	dbar        	0x700	# SA-RAR
+  84:	38727000 	dbar        	0x7000
diff --git a/binutils/testsuite/binutils-all/loongarch64/annotate-dbar.s b/binutils/testsuite/binutils-all/loongarch64/annotate-dbar.s
new file mode 100644
index 00000000000..af5b4f880fa
--- /dev/null
+++ b/binutils/testsuite/binutils-all/loongarch64/annotate-dbar.s
@@ -0,0 +1,34 @@
+dbar  0x0
+dbar  0x1
+dbar  0x2
+dbar  0x3
+dbar  0x4
+dbar  0x5
+dbar  0x6
+dbar  0x7
+dbar  0x8
+dbar  0x9
+dbar  0xa
+dbar  0xb
+dbar  0xc
+dbar  0xd
+dbar  0xe
+dbar  0xf
+dbar  0x10
+dbar  0x11
+dbar  0x12
+dbar  0x13
+dbar  0x14
+dbar  0x15
+dbar  0x16
+dbar  0x17
+dbar  0x18
+dbar  0x19
+dbar  0x1a
+dbar  0x1b
+dbar  0x1c
+dbar  0x1d
+dbar  0x1e
+dbar  0x1f
+dbar  0x700
+dbar  0x7000
diff --git a/include/opcode/loongarch.h b/include/opcode/loongarch.h
index 294b9424ee5..515b06855fd 100644
--- a/include/opcode/loongarch.h
+++ b/include/opcode/loongarch.h
@@ -78,6 +78,8 @@ extern "C"
   #define LARCH_OP_GCSRXCHG 0x05000000
   #define LARCH_MK_AMSWAP_W 0xffff8000
   #define LARCH_OP_AMSWAP_W 0x38600000
+  #define LARCH_MK_DBAR 0xffff8000
+  #define LARCH_OP_DBAR 0x38720000
 
   #define LARCH_INSN_OPS(insn, op) ((insn & LARCH_MK_##op) == LARCH_OP_##op)
   #define LARCH_INSN_ADDI_D(insn) LARCH_INSN_OPS((insn), ADDI_D)
@@ -99,6 +101,7 @@ extern "C"
   #define LARCH_INSN_CSRXCHG(insn) LARCH_INSN_OPS((insn), CSRXCHG)
   #define LARCH_INSN_GCSRXCHG(insn) LARCH_INSN_OPS((insn), GCSRXCHG)
   #define LARCH_INSN_AMSWAP_W(insn) LARCH_INSN_OPS((insn), AMSWAP_W)
+  #define LARCH_INSN_DBAR(insn) LARCH_INSN_OPS((insn), DBAR)
 
   #define LARCH_INSN_ATOMIC_MEM(insn)			\
 	((insn & 0xfff80000) == 0x38580000	\
diff --git a/opcodes/loongarch-dis.c b/opcodes/loongarch-dis.c
index e243963ed49..6cefd24691c 100644
--- a/opcodes/loongarch-dis.c
+++ b/opcodes/loongarch-dis.c
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 
 static bool loongarch_dis_show_aliases = true;
+static bool loongarch_dis_show_annotate = false;
 static const char *const *loongarch_r_disname = NULL;
 static const char *const *loongarch_f_disname = NULL;
 static const char *const *loongarch_fc_disname = NULL;
@@ -117,6 +118,12 @@ parse_loongarch_dis_option (const char *option)
       return 0;
     }
 
+  if (strcmp (option, "annotate") == 0)
+    {
+      loongarch_dis_show_annotate = true;
+      return 0;
+    }
+
   return -1;
 }
 
@@ -242,6 +249,63 @@ dis_one_arg (char esc1, char esc2, const char *bit_field,
   return 0;
 }
 
+static void
+disassemble_annotate_one (insn_t insn, struct disassemble_info *info)
+{
+  if (LARCH_INSN_DBAR (insn))
+    {
+      if ((insn & 0x700) == 0x700)
+	{
+	  info->fprintf_styled_func (info->stream, dis_style_comment_start, "\t# SA-RAR");
+	  return;
+	}
+
+      /* Currently, for reserved hint values such as 0xf, 0x1f and 0x7000, even
+	 though execution behavior matches hint=0 on most hardware, their exact
+	 semantics are undefined.
+	 We adopt a conservative approach and skip annotation for these values.  */
+      if (!(insn & 0x7fe0))
+	{
+	  unsigned int hint = LARCH_GET_RD (insn);
+
+	  /* If hint value is 0xf or 0x1f, its no specific semantics.  */
+	  if ((hint & 0xf) == 0xf)
+	    return;
+
+	  /* dbar imm[4:0] annotate layout:
+	     Bit 0: false denotes W, true denotes null, W declare store after this
+	     dbar are constrained by the barrier.
+	     Bit 1: false denotes R, true denotes null, R declare load after this
+	     dbar are constrained by the barrier.
+	     Bit 3: false denotes W, true denotes null, W declare store before this
+	     dbar are constrained by the barrier.
+	     Bit 4: false denotes R, true denotes null, R declare load before this
+	     dbar are constrained by the barrier.
+	     Bit 4: false denotes null, true denotes C.
+	     Immediate value 0x10 is annotated as CRW|RW that only cached load
+	     and store operations before and after this dbar are constrained
+	     by the barrier.  */
+	  char annotate[7] = {' ', ' ', ' ', '|', ' ', ' ', '\0'};
+	  if ((hint & (1u << 0)) == 0)
+	    annotate[5] = 'W';
+	  if ((hint & (1u << 1)) == 0)
+	    annotate[4] = 'R';
+	  if ((hint & (1u << 2)) == 0)
+	    annotate[2] = 'W';
+	  if ((hint & (1u << 3)) == 0)
+	    annotate[1] = 'R';
+	  if ((hint & (1u << 4)) != 0)
+	    annotate[0] = 'C';
+
+	  info->fprintf_styled_func (info->stream, dis_style_comment_start, "\t# ");
+	  info->fprintf_styled_func (info->stream, dis_style_sub_mnemonic, "%s", annotate);
+	  return;
+	}
+    }
+
+  return;
+}
+
 static void
 disassemble_one (insn_t insn, struct disassemble_info *info)
 {
@@ -319,6 +383,9 @@ disassemble_one (insn_t insn, struct disassemble_info *info)
     free (fake_args);
   }
 
+  if (loongarch_dis_show_annotate)
+    disassemble_annotate_one (insn, info);
+
   if (info->insn_type == dis_branch || info->insn_type == dis_condbranch)
     {
       info->fprintf_styled_func (info->stream, dis_style_comment_start, "\t# ");
@@ -368,5 +435,7 @@ with the -M switch (multiple options should be separated by commas):\n"));
     no-aliases    Use canonical instruction forms.\n"));
   fprintf (stream, _("\n\
     numeric       Print numeric register names, rather than ABI names.\n"));
+  fprintf (stream, _("\n\
+    annotate      Print LoongArch instruction annotations.\n"));
   fprintf (stream, _("\n"));
 }
-- 
2.20.1