[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