Skip to content

Commit 426cedc

Browse files
authored
[LoongArch] Add support for the ud macro instruction (#171583)
This patch adds support for the `ud ui5` macro instruction. The `ui5` operand must be inthe range `0-31`. The macro expands to: `amswap.w $rd, $r1, $rj` where `ui5` specifies the register number used for `$rd` in the expanded instruction, and `$rd` is the same as `$rj`. Relevant binutils patch: https://sourceware.org/pipermail/binutils/2025-December/146042.html
1 parent 71bfdd1 commit 426cedc

File tree

5 files changed

+60
-9
lines changed

5 files changed

+60
-9
lines changed

llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,29 @@ static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
157157
return MCDisassembler::Success;
158158
}
159159

160+
// Decode AMSWAP.W and UD, which share the same base encoding.
161+
// If rk == 1 and rd == rj, interpret the instruction as UD;
162+
// otherwise decode as AMSWAP.W.
163+
static DecodeStatus DecodeAMOrUDInstruction(MCInst &Inst, unsigned Insn,
164+
uint64_t Address,
165+
const MCDisassembler *Decoder) {
166+
unsigned Rd = fieldFromInstruction(Insn, 0, 5);
167+
unsigned Rj = fieldFromInstruction(Insn, 5, 5);
168+
unsigned Rk = fieldFromInstruction(Insn, 10, 5);
169+
170+
if (Rk == 1 && Rd == Rj) {
171+
Inst.setOpcode(LoongArch::UD);
172+
Inst.addOperand(MCOperand::createImm(Rd));
173+
} else {
174+
Inst.setOpcode(LoongArch::AMSWAP_W);
175+
Inst.addOperand(MCOperand::createReg(LoongArch::R0 + Rd));
176+
Inst.addOperand(MCOperand::createReg(LoongArch::R0 + Rk));
177+
Inst.addOperand(MCOperand::createReg(LoongArch::R0 + Rj));
178+
}
179+
180+
return MCDisassembler::Success;
181+
}
182+
160183
#include "LoongArchGenDisassemblerTables.inc"
161184

162185
DecodeStatus LoongArchDisassembler::getInstruction(MCInst &MI, uint64_t &Size,

llvm/lib/Target/LoongArch/LoongArchInstrFormats.td

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,3 +401,16 @@ class FmtLDPTE<dag outs, dag ins, string opnstr, list<dag> pattern = []>
401401
let Inst{9-5} = rj;
402402
let Inst{4-0} = 0b00000;
403403
}
404+
405+
// FmtUD
406+
// <0b0011100001100000000001 | I5 | I5>
407+
class FmtUD<dag outs, dag ins, string opnstr, list<dag> pattern = []>
408+
: LAInst<outs, ins, deriveInsnMnemonic<NAME>.ret, opnstr, pattern> {
409+
bits<5> imm5;
410+
411+
let Inst{31-10} = 0b0011100001100000000001;
412+
let Inst{9-5} = imm5;
413+
let Inst{4-0} = imm5;
414+
415+
let DecoderMethod = "DecodeAMOrUDInstruction";
416+
}

llvm/lib/Target/LoongArch/LoongArchInstrInfo.td

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,10 @@ class AM_3R<bits<32> op>
800800
let Constraints = "@earlyclobber $rd";
801801
}
802802

803+
class AU_3R<bits<32> op> : AM_3R<op> {
804+
let DecoderMethod = "DecodeAMOrUDInstruction";
805+
}
806+
803807
class AMCAS_3R<bits<32> op>
804808
: Fmt3R<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rk, GPRMemAtomic:$rj),
805809
"$rd, $rk, $rj"> {
@@ -923,6 +927,9 @@ def BREAK : MISC_I15<0x002a0000>;
923927
def RDTIMEL_W : RDTIME_2R<0x00006000>;
924928
def RDTIMEH_W : RDTIME_2R<0x00006400>;
925929

930+
let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
931+
def UD : FmtUD<(outs), (ins uimm5:$imm5), "$imm5">;
932+
926933
// The CPUCFG instruction offers a reliable way to probing CPU features.
927934
// Although support is not guaranteed on LA32R, having compiler support
928935
// nevertheless enables applications to rely on its presence, potentially
@@ -1087,7 +1094,7 @@ def STLE_D : STORE_3R<0x387f8000>;
10871094
// Atomic Memory Access Instructions for 64-bits
10881095
def AMSWAP_B : AM_3R<0x385c0000>;
10891096
def AMSWAP_H : AM_3R<0x385c8000>;
1090-
def AMSWAP_W : AM_3R<0x38600000>;
1097+
def AMSWAP_W : AU_3R<0x38600000>;
10911098
def AMSWAP_D : AM_3R<0x38608000>;
10921099
def AMADD_B : AM_3R<0x385d0000>;
10931100
def AMADD_H : AM_3R<0x385d8000>;
@@ -1410,12 +1417,8 @@ def : Pat<(and GPR:$rj, BstrinsImm:$imm),
14101417

14111418
/// Traps
14121419

1413-
// We lower `trap` to `amswap.w rd:$r0, rk:$r1, rj:$r0`, as this is guaranteed
1414-
// to trap with an INE (non-existent on LA32, explicitly documented to INE on
1415-
// LA64). And the resulting signal is different from `debugtrap` like on some
1416-
// other existing ports so programs/porters might have an easier time.
1417-
def PseudoUNIMP : Pseudo<(outs), (ins), [(trap)]>,
1418-
PseudoInstExpansion<(AMSWAP_W R0, R1, R0)>;
1420+
// We lower `trap` to `ud 0`, which is an alias for `amswap.w $r0, $r1, $r0`.
1421+
def PseudoUNIMP : Pseudo<(outs), (ins), [(trap)]>, PseudoInstExpansion<(UD 0)>;
14191422

14201423
// We lower `debugtrap` to `break 0`, as this is guaranteed to exist and work,
14211424
// even for LA32 Primary. Also, because so far the ISA does not provide a

llvm/test/CodeGen/LoongArch/trap.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ declare void @llvm.debugtrap()
1010
define void @test_trap() nounwind {
1111
; CHECK-LABEL: test_trap:
1212
; CHECK: # %bb.0:
13-
; CHECK-NEXT: amswap.w $zero, $ra, $zero
13+
; CHECK-NEXT: ud 0
1414
; CHECK-NEXT: ret
1515
tail call void @llvm.trap()
1616
ret void

llvm/test/MC/LoongArch/Basic/Integer/misc.s

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# RUN: llvm-mc %s --triple=loongarch32 --filetype=obj | llvm-objdump -d - \
88
# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
99
# RUN: llvm-mc %s --triple=loongarch64 --filetype=obj --defsym=LA64=1 | llvm-objdump -d - \
10-
# RUN: | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ,CHECK64-ASM-AND-OBJ %s
10+
# RUN: | FileCheck --check-prefixes=CHECK-ASM-AND-OBJ,CHECK64-OBJ,CHECK64-ASM-AND-OBJ %s
1111

1212
#############################################################
1313
## Instructions for both loongarch32 and loongarch64
@@ -33,13 +33,25 @@ rdtimeh.w $a7, $a1
3333
# CHECK-ASM: encoding: [0x03,0x6d,0x00,0x00]
3434
cpucfg $sp, $a4
3535

36+
# CHECK-ASM-AND-OBJ: ud 0
37+
# CHECK-ASM: encoding: [0x00,0x04,0x60,0x38]
38+
ud 0
39+
40+
# CHECK-ASM-AND-OBJ: ud 31
41+
# CHECK-ASM: encoding: [0xff,0x07,0x60,0x38]
42+
ud 31
3643

3744
#############################################################
3845
## Instructions only for loongarch64
3946
#############################################################
4047

4148
.ifdef LA64
4249

50+
# CHECK64-OBJ: ud 0
51+
# CHECK64-ASM: amswap.w $zero, $ra, $zero
52+
# CHECK64-ASM: encoding: [0x00,0x04,0x60,0x38]
53+
amswap.w $zero, $ra, $zero
54+
4355
# CHECK64-ASM-AND-OBJ: asrtle.d $t0, $t5
4456
# CHECK64-ASM: encoding: [0x80,0x45,0x01,0x00]
4557
asrtle.d $t0, $t5

0 commit comments

Comments
 (0)