LoongArch: Add support for the ud macro instruction

Message ID 20251201074726.163085-1-cailulu@loongson.cn
State New
Headers
Series LoongArch: Add support for the ud macro instruction |

Commit Message

Lulu Cai Dec. 1, 2025, 7:47 a.m. UTC
  In the "ud ui5" macro, the value of ui5 must be in the range 0–31. It
expands to "amswap.w $rd, $r1, $rj", where ui5 specifies the register
number for $rd in the amswap.w instruction, and $rd == $rj.

The test case have been adjusted to no longer report errors for illegal
operands of the amswap.w instruction.

gas/

	* config/tc-loongarch.c (check_this_insn_before_appending): No
	  longer check amswap.w.
	* testsuite/gas/loongarch/illegal-operand.l: Update.
	* testsuite/gas/loongarch/illegal-operand.s: Update.
	* testsuite/gas/loongarch/macro_ud.d: New test.
	* testsuite/gas/loongarch/macro_ud.s: New test.

include/

	* opcode/loongarch.h: Add new macro for amswap.w.

opcodes/

	* loongarch-opc.c: Add macro for ud.

---
 gas/config/tc-loongarch.c                     |  6 ++-
 gas/testsuite/gas/loongarch/illegal-operand.l | 10 ++---
 gas/testsuite/gas/loongarch/illegal-operand.s |  2 -
 gas/testsuite/gas/loongarch/macro_ud.d        | 41 +++++++++++++++++++
 gas/testsuite/gas/loongarch/macro_ud.s        | 32 +++++++++++++++
 include/opcode/loongarch.h                    |  3 ++
 opcodes/loongarch-opc.c                       |  1 +
 7 files changed, 85 insertions(+), 10 deletions(-)
 create mode 100644 gas/testsuite/gas/loongarch/macro_ud.d
 create mode 100644 gas/testsuite/gas/loongarch/macro_ud.s
  

Comments

WANG Xuerui Dec. 1, 2025, 4:31 p.m. UTC | #1
Hi,

On 12/1/25 15:47, Lulu Cai wrote:
> In the "ud ui5" macro, the value of ui5 must be in the range 0–31. It
> expands to "amswap.w $rd, $r1, $rj", where ui5 specifies the register
> number for $rd in the amswap.w instruction, and $rd == $rj.
> 
> The test case have been adjusted to no longer report errors for illegal
> operands of the amswap.w instruction.
> 
> [snip]
> diff --git a/gas/testsuite/gas/loongarch/macro_ud.d b/gas/testsuite/gas/loongarch/macro_ud.d
> new file mode 100644
> index 00000000000..dbc1cdcaf00
> --- /dev/null
> +++ b/gas/testsuite/gas/loongarch/macro_ud.d
> @@ -0,0 +1,41 @@
> +#as:
> +#objdump: -d
> +
> +.*:     file format .*
> +
> +
> +Disassembly of section \.text:
> +
> +0+ <\.text>:
> + *[0-9a-f]+:	38600400 	amswap.w    	\$zero, \$ra, \$zero
> [snip]
> diff --git a/gas/testsuite/gas/loongarch/macro_ud.s b/gas/testsuite/gas/loongarch/macro_ud.s
> new file mode 100644
> index 00000000000..75ebcb8b1b4
> --- /dev/null
> +++ b/gas/testsuite/gas/loongarch/macro_ud.s
> @@ -0,0 +1,32 @@
> +ud  0
> [snip]
> diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c
> index fa53021cfae..b443aebb477 100644
> --- a/opcodes/loongarch-opc.c
> +++ b/opcodes/loongarch-opc.c
> @@ -448,6 +448,7 @@ static struct loongarch_opcode loongarch_macro_opcodes[] =
>     { 0, 0, "la.tls.desc", "r,l",	  INSN_LA_TLS_DESC64_LARGE_ABS,	0 },
>     { 0, 0, "la.tls.desc", "r,l",	  INSN_LA_TLS_DESC64,		0 },
>     { 0, 0, "la.tls.desc", "r,r,l", INSN_LA_TLS_DESC64_LARGE_PCREL,0 },
> +  { 0, 0, "ud",		 "u",	  "amswap.w $r%1,$r1,$r%1",	0, 0, 0 },
>     { 0, 0, 0, 0, 0, 0, 0, 0 } /* Terminate the list.  */
>   };
>   

What about also recognizing the pattern and rendering as such during 
disassembly? It may be hard because an additional constraint is 
involved, may not be possible with the current trivial matching logic... 
But maybe adding a special instruction format specifier just for 
disassembly would be appropriate. Something like "r0:5,r5:5=%1" maybe.
  
Lulu Cai Dec. 3, 2025, 6:22 a.m. UTC | #2
Hi,

On 12/2/25 12:31 AM, WANG Xuerui wrote:
> Hi,
>
> On 12/1/25 15:47, Lulu Cai wrote:
>> In the "ud ui5" macro, the value of ui5 must be in the range 0–31. It
>> expands to "amswap.w $rd, $r1, $rj", where ui5 specifies the register
>> number for $rd in the amswap.w instruction, and $rd == $rj.
>>
>> The test case have been adjusted to no longer report errors for illegal
>> operands of the amswap.w instruction.
>>
>> [snip]
>> diff --git a/gas/testsuite/gas/loongarch/macro_ud.d 
>> b/gas/testsuite/gas/loongarch/macro_ud.d
>> new file mode 100644
>> index 00000000000..dbc1cdcaf00
>> --- /dev/null
>> +++ b/gas/testsuite/gas/loongarch/macro_ud.d
>> @@ -0,0 +1,41 @@
>> +#as:
>> +#objdump: -d
>> +
>> +.*:     file format .*
>> +
>> +
>> +Disassembly of section \.text:
>> +
>> +0+ <\.text>:
>> + *[0-9a-f]+:    38600400     amswap.w        \$zero, \$ra, \$zero
>> [snip]
>> diff --git a/gas/testsuite/gas/loongarch/macro_ud.s 
>> b/gas/testsuite/gas/loongarch/macro_ud.s
>> new file mode 100644
>> index 00000000000..75ebcb8b1b4
>> --- /dev/null
>> +++ b/gas/testsuite/gas/loongarch/macro_ud.s
>> @@ -0,0 +1,32 @@
>> +ud  0
>> [snip]
>> diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c
>> index fa53021cfae..b443aebb477 100644
>> --- a/opcodes/loongarch-opc.c
>> +++ b/opcodes/loongarch-opc.c
>> @@ -448,6 +448,7 @@ static struct loongarch_opcode 
>> loongarch_macro_opcodes[] =
>>     { 0, 0, "la.tls.desc", "r,l", INSN_LA_TLS_DESC64_LARGE_ABS,    0 },
>>     { 0, 0, "la.tls.desc", "r,l", INSN_LA_TLS_DESC64,        0 },
>>     { 0, 0, "la.tls.desc", "r,r,l", INSN_LA_TLS_DESC64_LARGE_PCREL,0 },
>> +  { 0, 0, "ud",         "u",      "amswap.w $r%1,$r1,$r%1", 0, 0, 0 },
>>     { 0, 0, 0, 0, 0, 0, 0, 0 } /* Terminate the list.  */
>>   };
>
> What about also recognizing the pattern and rendering as such during 
> disassembly? It may be hard because an additional constraint is 
> involved, may not be possible with the current trivial matching 
> logic... But maybe adding a special instruction format specifier just 
> for disassembly would be appropriate. Something like "r0:5,r5:5=%1" 
> maybe.

Adding special instruction format specifiers is indeed a more 
appropriate solution. I can try to do this after I finish handling other 
tasks.
  

Patch

diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index b006c6e6451..df5cf9d903c 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -1096,9 +1096,11 @@  check_this_insn_before_appending (struct loongarch_cl_insn *ip)
       ip->reloc_info[ip->reloc_num].value = const_0;
       ip->reloc_num++;
     }
-  /* check all atomic memory insns */
+  /* check all atomic memory insns except amswap.w.
+     amswap.w $rd,$r1,$rj ($rd==$rj) is used for ud ui5.  */
   else if (ip->insn->mask == LARCH_MK_ATOMIC_MEM
-	   && LARCH_INSN_ATOMIC_MEM (ip->insn_bin))
+	   && LARCH_INSN_ATOMIC_MEM (ip->insn_bin)
+	   && !LARCH_INSN_AMSWAP_W (ip->insn_bin))
     {
       /* For AMO insn amswap.[wd], amadd.[wd], etc.  */
       if (ip->args[0] != 0
diff --git a/gas/testsuite/gas/loongarch/illegal-operand.l b/gas/testsuite/gas/loongarch/illegal-operand.l
index 33e859c742e..09b5ea3aa3e 100644
--- a/gas/testsuite/gas/loongarch/illegal-operand.l
+++ b/gas/testsuite/gas/loongarch/illegal-operand.l
@@ -101,13 +101,11 @@ 
 .*:101: Error: atomic memory operations insns require rd != rj && rd != rk when rd isn't r0
 .*:102: Error: atomic memory operations insns require rd != rj && rd != rk when rd isn't r0
 .*:103: Error: atomic memory operations insns require rd != rj && rd != rk when rd isn't r0
-.*:104: Error: atomic memory operations insns require rd != rj && rd != rk when rd isn't r0
-.*:105: Error: atomic memory operations insns require rd != rj && rd != rk when rd isn't r0
+.*:106: Error: bstr\(ins\|pick\)\.\[wd\] require msbd >= lsbd
+.*:107: Error: bstr\(ins\|pick\)\.\[wd\] require msbd >= lsbd
 .*:108: Error: bstr\(ins\|pick\)\.\[wd\] require msbd >= lsbd
 .*:109: Error: bstr\(ins\|pick\)\.\[wd\] require msbd >= lsbd
-.*:110: Error: bstr\(ins\|pick\)\.\[wd\] require msbd >= lsbd
-.*:111: Error: bstr\(ins\|pick\)\.\[wd\] require msbd >= lsbd
+.*:112: Error: g\?csrxchg require rj != r0 && rj != r1
+.*:113: Error: g\?csrxchg require rj != r0 && rj != r1
 .*:114: Error: g\?csrxchg require rj != r0 && rj != r1
 .*:115: Error: g\?csrxchg require rj != r0 && rj != r1
-.*:116: Error: g\?csrxchg require rj != r0 && rj != r1
-.*:117: Error: g\?csrxchg require rj != r0 && rj != r1
diff --git a/gas/testsuite/gas/loongarch/illegal-operand.s b/gas/testsuite/gas/loongarch/illegal-operand.s
index 3860539d242..60de2fdc58c 100644
--- a/gas/testsuite/gas/loongarch/illegal-operand.s
+++ b/gas/testsuite/gas/loongarch/illegal-operand.s
@@ -31,8 +31,6 @@  amadd_db.b $r1,$r1,$r2
 amadd_db.b $r1,$r2,$r1
 amadd_db.h $r1,$r1,$r2
 amadd_db.h $r1,$r2,$r1
-amswap.w $r1,$r1,$r2
-amswap.w $r1,$r2,$r1
 amswap.d $r1,$r1,$r2
 amswap.d $r1,$r2,$r1
 amadd.w $r1,$r1,$r2
diff --git a/gas/testsuite/gas/loongarch/macro_ud.d b/gas/testsuite/gas/loongarch/macro_ud.d
new file mode 100644
index 00000000000..dbc1cdcaf00
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/macro_ud.d
@@ -0,0 +1,41 @@ 
+#as:
+#objdump: -d
+
+.*:     file format .*
+
+
+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
diff --git a/gas/testsuite/gas/loongarch/macro_ud.s b/gas/testsuite/gas/loongarch/macro_ud.s
new file mode 100644
index 00000000000..75ebcb8b1b4
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/macro_ud.s
@@ -0,0 +1,32 @@ 
+ud  0
+ud  1
+ud  2
+ud  3
+ud  4
+ud  5
+ud  6
+ud  7
+ud  8
+ud  9
+ud  10
+ud  11
+ud  12
+ud  13
+ud  14
+ud  15
+ud  16
+ud  17
+ud  18
+ud  19
+ud  20
+ud  21
+ud  22
+ud  23
+ud  24
+ud  25
+ud  26
+ud  27
+ud  28
+ud  29
+ud  30
+ud  31
diff --git a/include/opcode/loongarch.h b/include/opcode/loongarch.h
index b20c78ddf9f..1696f7d4291 100644
--- a/include/opcode/loongarch.h
+++ b/include/opcode/loongarch.h
@@ -73,6 +73,8 @@  extern "C"
   #define LARCH_OP_CSRXCHG 0x04000000
   #define LARCH_MK_GCSRXCHG 0xff000000
   #define LARCH_OP_GCSRXCHG 0x05000000
+  #define LARCH_MK_AMSWAP_W 0xffff8000
+  #define LARCH_OP_AMSWAP_W 0x38600000
 
   #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)
@@ -92,6 +94,7 @@  extern "C"
   #define LARCH_INSN_BSTRPICK_D(insn) LARCH_INSN_OPS((insn), BSTRPICK_D)
   #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_ATOMIC_MEM(insn)			\
 	((insn & 0xfff80000) == 0x38580000	\
diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c
index fa53021cfae..b443aebb477 100644
--- a/opcodes/loongarch-opc.c
+++ b/opcodes/loongarch-opc.c
@@ -448,6 +448,7 @@  static struct loongarch_opcode loongarch_macro_opcodes[] =
   { 0, 0, "la.tls.desc", "r,l",	  INSN_LA_TLS_DESC64_LARGE_ABS,	0 },
   { 0, 0, "la.tls.desc", "r,l",	  INSN_LA_TLS_DESC64,		0 },
   { 0, 0, "la.tls.desc", "r,r,l", INSN_LA_TLS_DESC64_LARGE_PCREL,0 },
+  { 0, 0, "ud",		 "u",	  "amswap.w $r%1,$r1,$r%1",	0, 0, 0 },
   { 0, 0, 0, 0, 0, 0, 0, 0 } /* Terminate the list.  */
 };