Skip to content

Commit 6881c6d

Browse files
authored
[RISCV] Add Qualcomm uC Xqcia (Arithmetic) extension (#118113)
This extension adds 11 instructions that perform integer arithmetic. The current spec can be found at: https://github.com/quic/riscv-unified-db/releases/latest This patch adds assembler only support.
1 parent 017c75b commit 6881c6d

File tree

13 files changed

+322
-1
lines changed

13 files changed

+322
-1
lines changed

clang/test/Driver/print-supported-extensions-riscv.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@
188188
// CHECK-NEXT: smctr 1.0 'Smctr' (Control Transfer Records Machine Level)
189189
// CHECK-NEXT: ssctr 1.0 'Ssctr' (Control Transfer Records Supervisor Level)
190190
// CHECK-NEXT: svukte 0.3 'Svukte' (Address-Independent Latency of User-Mode Faults to Supervisor Addresses)
191+
// CHECK-NEXT: xqcia 0.2 'Xqcia' (Qualcomm uC Arithmetic Extension)
191192
// CHECK-NEXT: xqcicsr 0.2 'Xqcicsr' (Qualcomm uC CSR Extension)
192193
// CHECK-NEXT: xqcisls 0.2 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
193194
// CHECK-EMPTY:

llvm/docs/RISCVUsage.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,9 @@ The current vendor extensions supported are:
426426
``Xwchc``
427427
LLVM implements `the custom compressed opcodes present in some QingKe cores` by WCH / Nanjing Qinheng Microelectronics. The vendor refers to these opcodes by the name "XW".
428428

429+
``experimental-Xqcia``
430+
LLVM implements `version 0.2 of the Qualcomm uC Arithmetic extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm. All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
431+
429432
``experimental-Xqcicsr``
430433
LLVM implements `version 0.2 of the Qualcomm uC CSR extension specification <https://github.com/quic/riscv-unified-db/releases/latest>`__ by Qualcomm. All instructions are prefixed with `qc.` as described in the specification. These instructions are only available for riscv32.
431434

llvm/docs/ReleaseNotes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ Changes to the RISC-V Backend
215215
extension.
216216
* Adds experimental assembler support for the Qualcomm uC 'Xqcisls` (Scaled Load Store)
217217
extension.
218+
* Adds experimental assembler support for the Qualcomm uC 'Xqcia` (Arithmetic)
219+
extension.
218220

219221
Changes to the WebAssembly Backend
220222
----------------------------------

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
717717
bool isUImm6() const { return IsUImm<6>(); }
718718
bool isUImm7() const { return IsUImm<7>(); }
719719
bool isUImm8() const { return IsUImm<8>(); }
720+
bool isUImm11() const { return IsUImm<11>(); }
720721
bool isUImm16() const { return IsUImm<16>(); }
721722
bool isUImm20() const { return IsUImm<20>(); }
722723
bool isUImm32() const { return IsUImm<32>(); }
@@ -1563,6 +1564,8 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
15631564
return generateImmOutOfRangeError(
15641565
Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
15651566
"immediate must be a multiple of 16 bytes and non-zero in the range");
1567+
case Match_InvalidUImm11:
1568+
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 11) - 1);
15661569
case Match_InvalidSImm12:
15671570
return generateImmOutOfRangeError(
15681571
Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,

llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,8 @@ DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,
686686
"Qualcomm uC CSR custom opcode table");
687687
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXqcisls, DecoderTableXqcisls32,
688688
"Qualcomm uC Scaled Load Store custom opcode table");
689+
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXqcia, DecoderTableXqcia32,
690+
"Qualcomm uC Arithmetic custom opcode table");
689691
TRY_TO_DECODE(true, DecoderTable32, "RISCV32 table");
690692

691693
return MCDisassembler::Fail;

llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ enum OperandType : unsigned {
312312
OPERAND_UIMM8_GE32,
313313
OPERAND_UIMM9_LSB000,
314314
OPERAND_UIMM10_LSB00_NONZERO,
315+
OPERAND_UIMM11,
315316
OPERAND_UIMM12,
316317
OPERAND_UIMM16,
317318
OPERAND_UIMM32,

llvm/lib/Target/RISCV/RISCVFeatures.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,14 @@ def HasVendorXqcisls
13591359
AssemblerPredicate<(all_of FeatureVendorXqcisls),
13601360
"'Xqcisls' (Qualcomm uC Scaled Load Store Extension)">;
13611361

1362+
def FeatureVendorXqcia
1363+
: RISCVExperimentalExtension<"xqcia", 0, 2,
1364+
"'Xqcia' (Qualcomm uC Arithmetic Extension)">;
1365+
def HasVendorXqcia
1366+
: Predicate<"Subtarget->hasVendorXqcia()">,
1367+
AssemblerPredicate<(all_of FeatureVendorXqcia),
1368+
"'Xqcia' (Qualcomm uC Arithmetic Extension)">;
1369+
13621370
//===----------------------------------------------------------------------===//
13631371
// LLVM specific features and extensions
13641372
//===----------------------------------------------------------------------===//

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
// Operand and SDNode transformation definitions.
1515
//===----------------------------------------------------------------------===//
1616

17+
def uimm11 : RISCVUImmLeafOp<11>;
18+
1719
//===----------------------------------------------------------------------===//
1820
// Instruction Formats
1921
//===----------------------------------------------------------------------===//
@@ -45,6 +47,16 @@ class QCIStore_ScaleIdx<bits<4> func4, string opcodestr>
4547
}
4648
}
4749

50+
class QCIRVInstR<bits<4> func4, string opcodestr>
51+
: RVInstR<{0b000, func4}, 0b011, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
52+
(ins GPRNoX0:$rs1), opcodestr, "$rd, $rs1"> {
53+
let rs2 = 0;
54+
}
55+
56+
class QCIRVInstRR<bits<5> func5, DAGOperand InTyRs1, string opcodestr>
57+
: RVInstR<{0b00, func5}, 0b011, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
58+
(ins InTyRs1:$rs1, GPRNoX0:$rs2), opcodestr, "$rd, $rs1, $rs2">;
59+
4860
//===----------------------------------------------------------------------===//
4961
// Instructions
5062
//===----------------------------------------------------------------------===//
@@ -72,3 +84,27 @@ let Predicates = [HasVendorXqcisls, IsRV32], DecoderNamespace = "Xqcisls" in {
7284
def QC_SRH : QCIStore_ScaleIdx<0b1110, "qc.srh">;
7385
def QC_SRW : QCIStore_ScaleIdx<0b1111, "qc.srw">;
7486
} // Predicates = [HasVendorXqcisls, IsRV32], DecoderNamespace = "Xqcisls"
87+
88+
let Predicates = [HasVendorXqcia, IsRV32], DecoderNamespace = "Xqcia" in {
89+
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
90+
def QC_SLASAT : QCIRVInstRR<0b01010, GPRNoX0, "qc.slasat">;
91+
def QC_SLLSAT : QCIRVInstRR<0b01100, GPRNoX0, "qc.sllsat">;
92+
def QC_ADDSAT : QCIRVInstRR<0b01110, GPRNoX0, "qc.addsat">;
93+
def QC_ADDUSAT : QCIRVInstRR<0b01111, GPRNoX0, "qc.addusat">;
94+
def QC_SUBSAT : QCIRVInstRR<0b10000, GPRNoX0, "qc.subsat">;
95+
def QC_SUBUSAT : QCIRVInstRR<0b10001, GPRNoX0, "qc.subusat">;
96+
97+
def QC_WRAP : QCIRVInstRR<0b10010, GPR, "qc.wrap">;
98+
def QC_WRAPI : RVInstI<0b000, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
99+
(ins GPRNoX0:$rs1, uimm11:$imm11), "qc.wrapi",
100+
"$rd, $rs1, $imm11"> {
101+
bits<11> imm11;
102+
103+
let imm12 = {0b0, imm11};
104+
}
105+
106+
def QC_NORM : QCIRVInstR<0b0111, "qc.norm">;
107+
def QC_NORMU : QCIRVInstR<0b1000, "qc.normu">;
108+
def QC_NORMEU : QCIRVInstR<0b1001, "qc.normeu">;
109+
} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
110+
} // Predicates = [HasVendorXqcia, IsRV32], DecoderNamespace = "Xqcia"

llvm/lib/TargetParser/RISCVISAInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,8 @@ Error RISCVISAInfo::checkDependency() {
741741
bool HasVector = Exts.count("zve32x") != 0;
742742
bool HasZvl = MinVLen != 0;
743743
bool HasZcmt = Exts.count("zcmt") != 0;
744-
static constexpr StringLiteral XqciExts[] = {{"xqcicsr"}, {"xqcisls"}};
744+
static constexpr StringLiteral XqciExts[] = {
745+
{"xqcia"}, {"xqcicsr"}, {"xqcisls"}};
745746

746747
if (HasI && HasE)
747748
return getIncompatibleError("i", "e");

llvm/test/CodeGen/RISCV/attributes.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
; RUN: llc -mtriple=riscv32 -mattr=+xtheadmempair %s -o - | FileCheck --check-prefix=RV32XTHEADMEMPAIR %s
8282
; RUN: llc -mtriple=riscv32 -mattr=+xtheadsync %s -o - | FileCheck --check-prefix=RV32XTHEADSYNC %s
8383
; RUN: llc -mtriple=riscv32 -mattr=+xwchc %s -o - | FileCheck --check-prefix=RV32XWCHC %s
84+
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcia %s -o - | FileCheck --check-prefix=RV32XQCIA %s
8485
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicsr %s -o - | FileCheck --check-prefix=RV32XQCICSR %s
8586
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisls %s -o - | FileCheck --check-prefix=RV32XQCISLS %s
8687
; RUN: llc -mtriple=riscv32 -mattr=+zaamo %s -o - | FileCheck --check-prefix=RV32ZAAMO %s
@@ -387,6 +388,7 @@
387388
; RV32XTHEADMEMPAIR: .attribute 5, "rv32i2p1_xtheadmempair1p0"
388389
; RV32XTHEADSYNC: .attribute 5, "rv32i2p1_xtheadsync1p0"
389390
; RV32XWCHC: .attribute 5, "rv32i2p1_xwchc2p2"
391+
; RV32XQCIA: .attribute 5, "rv32i2p1_xqcia0p2"
390392
; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
391393
; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
392394
; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"

llvm/test/MC/RISCV/xqcia-invalid.s

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# Xqcia - Qualcomm uC Arithmetic Extension
2+
# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcia < %s 2>&1 \
3+
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
4+
# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcia < %s 2>&1 \
5+
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s
6+
7+
# CHECK: :[[@LINE+1]]:20: error: invalid operand for instruction
8+
qc.slasat x10, x3, 17
9+
10+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
11+
qc.slasat x10, x3
12+
13+
# CHECK: :[[@LINE+1]]:11: error: invalid operand for instruction
14+
qc.slasat x0, x3, x17
15+
16+
# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
17+
qc.slasat x10, x0, x17
18+
19+
# CHECK: :[[@LINE+1]]:20: error: invalid operand for instruction
20+
qc.slasat x10, x3, x0
21+
22+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
23+
qc.slasat x10, x3, x17
24+
25+
26+
# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
27+
qc.sllsat x23, x25, 27
28+
29+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
30+
qc.sllsat x23, x25
31+
32+
# CHECK: :[[@LINE+1]]:11: error: invalid operand for instruction
33+
qc.sllsat x0, x25, x27
34+
35+
# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
36+
qc.sllsat x23, x0, x27
37+
38+
# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
39+
qc.sllsat x23, x25, x0
40+
41+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
42+
qc.sllsat x23, x25, x27
43+
44+
45+
# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
46+
qc.addsat x17, x14, 7
47+
48+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
49+
qc.addsat x17, x14
50+
51+
# CHECK: :[[@LINE+1]]:11: error: invalid operand for instruction
52+
qc.addsat x0, x14, x7
53+
54+
# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
55+
qc.addsat x17, x0, x7
56+
57+
# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
58+
qc.addsat x17, x14, x0
59+
60+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
61+
qc.addsat x17, x14, x7
62+
63+
64+
# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
65+
qc.addusat x8, x18, 28
66+
67+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
68+
qc.addusat x8, x18
69+
70+
# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
71+
qc.addusat x0, x18, x28
72+
73+
# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
74+
qc.addusat x8, x0, x28
75+
76+
# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
77+
qc.addusat x8, x18, x0
78+
79+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
80+
qc.addusat x8, x18, x28
81+
82+
83+
# CHECK: :[[@LINE+1]]:20: error: invalid operand for instruction
84+
qc.subsat x22, x2, 12
85+
86+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
87+
qc.subsat x22, x2
88+
89+
# CHECK: :[[@LINE+1]]:11: error: invalid operand for instruction
90+
qc.subsat x0, x2, x12
91+
92+
# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
93+
qc.subsat x22, x0, x12
94+
95+
# CHECK: :[[@LINE+1]]:20: error: invalid operand for instruction
96+
qc.subsat x22, x2, x0
97+
98+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
99+
qc.subsat x22, x2, x12
100+
101+
102+
# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
103+
qc.subusat x9, x14, 17
104+
105+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
106+
qc.subusat x9, x14
107+
108+
# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
109+
qc.subusat x0, x14, x17
110+
111+
# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
112+
qc.subusat x9, x0, x17
113+
114+
# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
115+
qc.subusat x9, x14, x0
116+
117+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
118+
qc.subusat x9, x14, x17
119+
120+
121+
# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
122+
qc.wrap x3, x30, 23
123+
124+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
125+
qc.wrap x3, x30
126+
127+
# CHECK: :[[@LINE+1]]:9: error: invalid operand for instruction
128+
qc.wrap x0, x30, x23
129+
130+
# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
131+
qc.wrap x3, x30, x0
132+
133+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
134+
qc.wrap x3, x30, x23
135+
136+
137+
# CHECK: :[[@LINE+1]]:10: error: invalid operand for instruction
138+
qc.wrapi x0, 12, 2047
139+
140+
# CHECK: :[[@LINE+1]]:10: error: invalid operand for instruction
141+
qc.wrapi x0, x12, 2047
142+
143+
# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
144+
qc.wrapi x6, x0, 2047
145+
146+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
147+
qc.wrapi x6, x12
148+
149+
# CHECK-PLUS: :[[@LINE+1]]:19: error: immediate must be an integer in the range [0, 2047]
150+
qc.wrapi x6, x12, 2048
151+
152+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
153+
qc.wrapi x6, x12, 2047
154+
155+
156+
# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
157+
qc.norm x3, 7
158+
159+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
160+
qc.norm x3
161+
162+
# CHECK: :[[@LINE+1]]:9: error: invalid operand for instruction
163+
qc.norm x0, x7
164+
165+
# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
166+
qc.norm x3, x0
167+
168+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
169+
qc.norm x3, x7
170+
171+
172+
# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
173+
qc.normu x11, 17
174+
175+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
176+
qc.normu x11
177+
178+
# CHECK: :[[@LINE+1]]:10: error: invalid operand for instruction
179+
qc.normu x0, x17
180+
181+
# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
182+
qc.normu x11, x0
183+
184+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
185+
qc.normu x11, x17
186+
187+
188+
# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
189+
qc.normeu x26, 31
190+
191+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
192+
qc.normeu x26
193+
194+
# CHECK: :[[@LINE+1]]:11: error: invalid operand for instruction
195+
qc.normeu x0, x31
196+
197+
# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
198+
qc.normeu x26, x0
199+
200+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
201+
qc.normeu x26, x31

0 commit comments

Comments
 (0)