[binutils-gdb] LoongArch: Add disassembly support for ud ui5

liu zhensong liuzhensong@sourceware.org
Sat Dec 20 02:49:33 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8bea934667cdf3046dd388e9d07ca055d4ff5277

commit 8bea934667cdf3046dd388e9d07ca055d4ff5277
Author: Lulu Cai <cailulu@loongson.cn>
Date:   Sat Dec 13 15:33:15 2025 +0800

    LoongArch: Add disassembly support for ud ui5
    
    ud ui5, also known as amswap.w rd,$r1,rj(rd==rj), is displayed as
    "ud ui5" by default during disassembly. Alternatively, the original
    instruction can be printed using the objdump -M no-aliases.
    
    To implement this support, a format specifier "ru0:5,ru5:5" for ud is
    applied exclusively during disassembly. This specifier indicates that
    registers should be printed using their corresponding numeric values,
    and when the instruction is identified as ud, only a single parameter
    is displayed.
    
    binutils/
    
            * testsuite/binutils-all/loongarch64/dis-amswap-ud-noaliases.d:
              New test.
            * testsuite/binutils-all/loongarch64/dis-amswap-ud.d: New test.
            * testsuite/binutils-all/loongarch64/dis-amswap-ud.s: New test.
    
    gas/
    
            * testsuite/gas/loongarch/macro_ud.d: Update test.
    
    include/
    
            * opcode/loongarch.h: New macro.
    
    opcodes/
    
            * loongarch-dis.c (get_loongarch_opcode_by_binfmt): Correct match `ud`.
            (dis_one_arg): Disassemble the `ud` parameter.
            * loongarch-opc.c: Add opcode for "ud" alias.

Diff:
---
 .../loongarch64/dis-amswap-ud-noaliases.d          | 18 ++++++
 .../binutils-all/loongarch64/dis-amswap-ud.d       | 18 ++++++
 .../binutils-all/loongarch64/dis-amswap-ud.s       | 14 +++++
 gas/testsuite/gas/loongarch/macro_ud.d             | 64 +++++++++++-----------
 include/opcode/loongarch.h                         |  1 +
 opcodes/loongarch-dis.c                            | 35 +++++++++++-
 opcodes/loongarch-opc.c                            |  1 +
 7 files changed, 116 insertions(+), 35 deletions(-)

diff --git a/binutils/testsuite/binutils-all/loongarch64/dis-amswap-ud-noaliases.d b/binutils/testsuite/binutils-all/loongarch64/dis-amswap-ud-noaliases.d
new file mode 100644
index 00000000000..30e580c36ac
--- /dev/null
+++ b/binutils/testsuite/binutils-all/loongarch64/dis-amswap-ud-noaliases.d
@@ -0,0 +1,18 @@
+#name: Check correct disassembly of ud orig instructions
+#source: dis-amswap-ud.s
+#objdump: -d -M numeric,no-aliases
+
+#...
+Disassembly of section \.text:
+
+0+ <ud>:
+   0:	38600400 	amswap.w    	\$r0, \$r1, \$r0
+   4:	38600421 	amswap.w    	\$r1, \$r1, \$r1
+   8:	38600442 	amswap.w    	\$r2, \$r1, \$r2
+   c:	38600463 	amswap.w    	\$r3, \$r1, \$r3
+
+0+10 <amswap_w>:
+  10:	38600084 	amswap.w    	\$r4, \$r0, \$r4
+  14:	386008a5 	amswap.w    	\$r5, \$r2, \$r5
+  18:	386004e6 	amswap.w    	\$r6, \$r1, \$r7
+  1c:	38600528 	amswap.w    	\$r8, \$r1, \$r9
diff --git a/binutils/testsuite/binutils-all/loongarch64/dis-amswap-ud.d b/binutils/testsuite/binutils-all/loongarch64/dis-amswap-ud.d
new file mode 100644
index 00000000000..2997153c3cb
--- /dev/null
+++ b/binutils/testsuite/binutils-all/loongarch64/dis-amswap-ud.d
@@ -0,0 +1,18 @@
+#name: Check correct disassembly of ud
+#source: dis-amswap-ud.s
+#objdump: -d -M numeric
+
+#...
+Disassembly of section \.text:
+
+0+ <ud>:
+   0:	38600400 	ud          	0x0
+   4:	38600421 	ud          	0x1
+   8:	38600442 	ud          	0x2
+   c:	38600463 	ud          	0x3
+
+0+10 <amswap_w>:
+  10:	38600084 	amswap.w    	\$r4, \$r0, \$r4
+  14:	386008a5 	amswap.w    	\$r5, \$r2, \$r5
+  18:	386004e6 	amswap.w    	\$r6, \$r1, \$r7
+  1c:	38600528 	amswap.w    	\$r8, \$r1, \$r9
diff --git a/binutils/testsuite/binutils-all/loongarch64/dis-amswap-ud.s b/binutils/testsuite/binutils-all/loongarch64/dis-amswap-ud.s
new file mode 100644
index 00000000000..e9937e0c52d
--- /dev/null
+++ b/binutils/testsuite/binutils-all/loongarch64/dis-amswap-ud.s
@@ -0,0 +1,14 @@
+# Disassembly to "ud ui5" or "amswap.w rd, r1, rj" ,rd==rj
+ud:
+ud  0
+ud  1
+amswap.w  $r2,$r1,$r2
+amswap.w  $r3,$r1,$r3
+
+# No disassembly to ud
+amswap_w:
+amswap.w  $r4, $r0, $r4
+amswap.w  $r5, $r2, $r5
+
+amswap.w  $r6, $r1, $r7
+amswap.w  $r8, $r1, $r9
diff --git a/gas/testsuite/gas/loongarch/macro_ud.d b/gas/testsuite/gas/loongarch/macro_ud.d
index dbc1cdcaf00..7ef5b9bfa82 100644
--- a/gas/testsuite/gas/loongarch/macro_ud.d
+++ b/gas/testsuite/gas/loongarch/macro_ud.d
@@ -7,35 +7,35 @@
 Disassembly of section \.text:
 
 0+ <\.text>:
- *[0-9a-f]+:	38600400 	amswap.w    	\$zero, \$ra, \$zero
- *[0-9a-f]+:	38600421 	amswap.w    	\$ra, \$ra, \$ra
- *[0-9a-f]+:	38600442 	amswap.w    	\$tp, \$ra, \$tp
- *[0-9a-f]+:	38600463 	amswap.w    	\$sp, \$ra, \$sp
- *[0-9a-f]+:	38600484 	amswap.w    	\$a0, \$ra, \$a0
- *[0-9a-f]+:	386004a5 	amswap.w    	\$a1, \$ra, \$a1
- *[0-9a-f]+:	386004c6 	amswap.w    	\$a2, \$ra, \$a2
- *[0-9a-f]+:	386004e7 	amswap.w    	\$a3, \$ra, \$a3
- *[0-9a-f]+:	38600508 	amswap.w    	\$a4, \$ra, \$a4
- *[0-9a-f]+:	38600529 	amswap.w    	\$a5, \$ra, \$a5
- *[0-9a-f]+:	3860054a 	amswap.w    	\$a6, \$ra, \$a6
- *[0-9a-f]+:	3860056b 	amswap.w    	\$a7, \$ra, \$a7
- *[0-9a-f]+:	3860058c 	amswap.w    	\$t0, \$ra, \$t0
- *[0-9a-f]+:	386005ad 	amswap.w    	\$t1, \$ra, \$t1
- *[0-9a-f]+:	386005ce 	amswap.w    	\$t2, \$ra, \$t2
- *[0-9a-f]+:	386005ef 	amswap.w    	\$t3, \$ra, \$t3
- *[0-9a-f]+:	38600610 	amswap.w    	\$t4, \$ra, \$t4
- *[0-9a-f]+:	38600631 	amswap.w    	\$t5, \$ra, \$t5
- *[0-9a-f]+:	38600652 	amswap.w    	\$t6, \$ra, \$t6
- *[0-9a-f]+:	38600673 	amswap.w    	\$t7, \$ra, \$t7
- *[0-9a-f]+:	38600694 	amswap.w    	\$t8, \$ra, \$t8
- *[0-9a-f]+:	386006b5 	amswap.w    	\$r21, \$ra, \$r21
- *[0-9a-f]+:	386006d6 	amswap.w    	\$fp, \$ra, \$fp
- *[0-9a-f]+:	386006f7 	amswap.w    	\$s0, \$ra, \$s0
- *[0-9a-f]+:	38600718 	amswap.w    	\$s1, \$ra, \$s1
- *[0-9a-f]+:	38600739 	amswap.w    	\$s2, \$ra, \$s2
- *[0-9a-f]+:	3860075a 	amswap.w    	\$s3, \$ra, \$s3
- *[0-9a-f]+:	3860077b 	amswap.w    	\$s4, \$ra, \$s4
- *[0-9a-f]+:	3860079c 	amswap.w    	\$s5, \$ra, \$s5
- *[0-9a-f]+:	386007bd 	amswap.w    	\$s6, \$ra, \$s6
- *[0-9a-f]+:	386007de 	amswap.w    	\$s7, \$ra, \$s7
- *[0-9a-f]+:	386007ff 	amswap.w    	\$s8, \$ra, \$s8
+   0:	38600400 	ud          	0x0
+   4:	38600421 	ud          	0x1
+   8:	38600442 	ud          	0x2
+   c:	38600463 	ud          	0x3
+  10:	38600484 	ud          	0x4
+  14:	386004a5 	ud          	0x5
+  18:	386004c6 	ud          	0x6
+  1c:	386004e7 	ud          	0x7
+  20:	38600508 	ud          	0x8
+  24:	38600529 	ud          	0x9
+  28:	3860054a 	ud          	0xa
+  2c:	3860056b 	ud          	0xb
+  30:	3860058c 	ud          	0xc
+  34:	386005ad 	ud          	0xd
+  38:	386005ce 	ud          	0xe
+  3c:	386005ef 	ud          	0xf
+  40:	38600610 	ud          	0x10
+  44:	38600631 	ud          	0x11
+  48:	38600652 	ud          	0x12
+  4c:	38600673 	ud          	0x13
+  50:	38600694 	ud          	0x14
+  54:	386006b5 	ud          	0x15
+  58:	386006d6 	ud          	0x16
+  5c:	386006f7 	ud          	0x17
+  60:	38600718 	ud          	0x18
+  64:	38600739 	ud          	0x19
+  68:	3860075a 	ud          	0x1a
+  6c:	3860077b 	ud          	0x1b
+  70:	3860079c 	ud          	0x1c
+  74:	386007bd 	ud          	0x1d
+  78:	386007de 	ud          	0x1e
+  7c:	386007ff 	ud          	0x1f
diff --git a/include/opcode/loongarch.h b/include/opcode/loongarch.h
index fb6f8be68de..3e8a90a2b27 100644
--- a/include/opcode/loongarch.h
+++ b/include/opcode/loongarch.h
@@ -116,6 +116,7 @@ extern "C"
   #define LARCH_RD_RJ_A0 0x084
   #define LARCH_GET_RD(insn) (insn & 0x1f)
   #define LARCH_GET_RJ(insn) ((insn >> 5) & 0x1f)
+  #define LARCH_GET_RK(insn) ((insn >> 10) & 0x1f)
 
   typedef uint32_t insn_t;
 
diff --git a/opcodes/loongarch-dis.c b/opcodes/loongarch-dis.c
index 2e59bf8035f..05907db2caa 100644
--- a/opcodes/loongarch-dis.c
+++ b/opcodes/loongarch-dis.c
@@ -65,7 +65,17 @@ get_loongarch_opcode_by_binfmt (insn_t insn)
 	if ((insn & it->mask) == it->match && it->mask
 	    && !(it->include && !*it->include)
 	    && !(it->exclude && *it->exclude))
-	  return it;
+	  {
+	    /* ud ui5 need rd==rj. We should continue searching
+	       for the next `it` if rd != rj. Furthermore, we need
+	       `it->pinfo` to ensure that only the `it` in loongarch
+	       alias_opcodes[] is skipped.  */
+	    if (LARCH_INSN_AMSWAP_W (insn)
+		&& (LARCH_GET_RD (insn) != LARCH_GET_RJ (insn))
+		&& (it->pinfo & INSN_DIS_ALIAS))
+	      continue;
+	    return it;
+	  }
     }
   return NULL;
 }
@@ -142,10 +152,19 @@ dis_one_arg (char esc1, char esc2, const char *bit_field,
   insn_t insn = *(insn_t *) info->private_data;
   int32_t imm, u_imm;
   enum disassembler_style style;
+  bool is_ud_2nd_arg = false;
+
+  if (LARCH_INSN_AMSWAP_W (insn)
+      && (LARCH_GET_RD (insn) == LARCH_GET_RJ (insn))
+      && (LARCH_GET_RK (insn) == 1)
+      && loongarch_dis_show_aliases
+      && need_comma)
+    is_ud_2nd_arg = true;
 
   if (esc1)
     {
-      if (need_comma)
+      /* The "ud ui5" does not nedd a comma.  */
+      if (need_comma && !is_ud_2nd_arg)
 	info->fprintf_styled_func (info->stream, dis_style_text, ", ");
       need_comma = 1;
       imm = loongarch_decode_imm (bit_field, insn, 1);
@@ -155,7 +174,17 @@ dis_one_arg (char esc1, char esc2, const char *bit_field,
   switch (esc1)
     {
     case 'r':
-      info->fprintf_styled_func (info->stream, dis_style_register, "%s", loongarch_r_disname[u_imm]);
+      switch (esc2)
+	{
+	  case 'u':
+	    /* The "ud ui5" only needs to print one parameter.  */
+	    if (is_ud_2nd_arg)
+	      break;
+	    info->fprintf_styled_func (info->stream, dis_style_immediate, "0x%x", u_imm);
+	    break;
+	  default:
+	    info->fprintf_styled_func (info->stream, dis_style_register, "%s", loongarch_r_disname[u_imm]);
+	}
       break;
     case 'f':
       switch (esc2)
diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c
index 98ce43358c1..6604bd73f00 100644
--- a/opcodes/loongarch-opc.c
+++ b/opcodes/loongarch-opc.c
@@ -507,6 +507,7 @@ static struct loongarch_opcode loongarch_alias_opcodes[] =
   { 0x60000000,	0xfc0003e0,	"bgtz",		"r0:5,sb10:16<<2",		0,	0, 0, INSN_DIS_ALIAS }, /* blt zero, rd, offset */
   { 0x64000000,	0xfc00001f,	"bgez",		"r5:5,sb10:16<<2",		0,	0, 0, INSN_DIS_ALIAS }, /* bge rj, zero, offset */
   { 0x64000000,	0xfc0003e0,	"blez",		"r0:5,sb10:16<<2",		0,	0, 0, INSN_DIS_ALIAS }, /* bge zero, rd, offset */
+  { 0x38600400,	0xfffffc00,	"ud",		"ru0:5,ru5:5",			0,	0, 0, INSN_DIS_ALIAS }, /* amswap.w rd, $r1, rj, rj==rd */
   { 0, 0, 0, 0, 0, 0, 0, 0 } /* Terminate the list.  */
 };


More information about the Binutils-cvs mailing list