LoongArch: Add support for the ud macro instruction
Commit Message
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
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.
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.
@@ -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
@@ -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
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
@@ -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 \
@@ -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. */
};