Skip to content

Commit 163935a

Browse files
hchandelHarsh Chandel
and
Harsh Chandel
authored
[RISCV] Add Qualcomm uC Xqcilo (Large Offset Load Store) extension (#123881)
This extension adds eight 48 bit load store instructions. The current spec can be found at: https://github.com/quic/riscv-unified-db/releases/latest This patch adds assembler only support. --------- Co-authored-by: Harsh Chandel <[email protected]>
1 parent aa273fd commit 163935a

File tree

15 files changed

+414
-5
lines changed

15 files changed

+414
-5
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@
197197
// CHECK-NEXT: xqcics 0.2 'Xqcics' (Qualcomm uC Conditional Select Extension)
198198
// CHECK-NEXT: xqcicsr 0.2 'Xqcicsr' (Qualcomm uC CSR Extension)
199199
// CHECK-NEXT: xqciint 0.2 'Xqciint' (Qualcomm uC Interrupts Extension)
200+
// CHECK-NEXT: xqcilo 0.2 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
200201
// CHECK-NEXT: xqcilsm 0.2 'Xqcilsm' (Qualcomm uC Load Store Multiple Extension)
201202
// CHECK-NEXT: xqcisls 0.2 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
202203
// CHECK-EMPTY:

llvm/docs/RISCVUsage.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,9 @@ The current vendor extensions supported are:
450450
``experimental-Xqciint``
451451
LLVM implements `version 0.2 of the Qualcomm uC Interrupts 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.
452452

453+
``experimental-Xqcilo``
454+
LLVM implements `version 0.2 of the Qualcomm uC Large Offset Load Store 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.
455+
453456
``experimental-Xqcilsm``
454457
LLVM implements `version 0.2 of the Qualcomm uC Load Store Multiple 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.
455458

llvm/docs/ReleaseNotes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ Changes to the RISC-V Backend
294294
extension.
295295
* Adds experimental assembler support for the Qualcomm uC 'Xqciint` (Interrupts)
296296
extension.
297+
* Adds experimental assembler support for the Qualcomm uC 'Xqcilo` (Large Offset Load Store)
298+
extension.
297299
* Added ``Sdext`` and ``Sdtrig`` extensions.
298300

299301
Changes to the WebAssembly Backend

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,16 @@ struct RISCVOperand final : public MCParsedAsmOperand {
10361036
VK == RISCVMCExpr::VK_RISCV_None;
10371037
}
10381038

1039+
bool isSImm26() const {
1040+
if (!isImm())
1041+
return false;
1042+
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1043+
int64_t Imm;
1044+
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1045+
return IsConstantImm && (VK == RISCVMCExpr::VK_RISCV_None) &&
1046+
isInt<26>(fixImmediateForRV32(Imm, isRV64Imm()));
1047+
}
1048+
10391049
/// getStartLoc - Gets location of the first token of this operand
10401050
SMLoc getStartLoc() const override { return StartLoc; }
10411051
/// getEndLoc - Gets location of the last token of this operand
@@ -1676,6 +1686,9 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
16761686
(1 << 4),
16771687
"immediate must be in the range");
16781688
}
1689+
case Match_InvalidSImm26:
1690+
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 25),
1691+
(1 << 25) - 1);
16791692
case Match_InvalidRlist: {
16801693
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
16811694
return Error(

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

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ class RISCVDisassembler : public MCDisassembler {
4545
private:
4646
void addSPOperands(MCInst &MI) const;
4747

48+
DecodeStatus getInstruction48(MCInst &Instr, uint64_t &Size,
49+
ArrayRef<uint8_t> Bytes, uint64_t Address,
50+
raw_ostream &CStream) const;
51+
4852
DecodeStatus getInstruction32(MCInst &Instr, uint64_t &Size,
4953
ArrayRef<uint8_t> Bytes, uint64_t Address,
5054
raw_ostream &CStream) const;
@@ -745,6 +749,27 @@ DecodeStatus RISCVDisassembler::getInstruction16(MCInst &MI, uint64_t &Size,
745749
return MCDisassembler::Fail;
746750
}
747751

752+
DecodeStatus RISCVDisassembler::getInstruction48(MCInst &MI, uint64_t &Size,
753+
ArrayRef<uint8_t> Bytes,
754+
uint64_t Address,
755+
raw_ostream &CS) const {
756+
if (Bytes.size() < 6) {
757+
Size = 0;
758+
return MCDisassembler::Fail;
759+
}
760+
Size = 6;
761+
762+
uint64_t Insn = 0;
763+
for (size_t i = Size; i-- != 0;) {
764+
Insn += (static_cast<uint64_t>(Bytes[i]) << 8 * i);
765+
}
766+
TRY_TO_DECODE_FEATURE(
767+
RISCV::FeatureVendorXqcilo, DecoderTableXqcilo48,
768+
"Qualcomm uC Large Offset Load Store custom 48bit opcode table");
769+
770+
return MCDisassembler::Fail;
771+
}
772+
748773
DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
749774
ArrayRef<uint8_t> Bytes,
750775
uint64_t Address,
@@ -760,8 +785,7 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
760785

761786
// 48-bit instructions are encoded as 0bxx011111.
762787
if ((Bytes[0] & 0b11'1111) == 0b01'1111) {
763-
Size = Bytes.size() >= 6 ? 6 : 0;
764-
return MCDisassembler::Fail;
788+
return getInstruction48(MI, Size, Bytes, Address, CS);
765789
}
766790

767791
// 64-bit instructions are encoded as 0x0111111.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ enum OperandType : unsigned {
332332
OPERAND_SIMM10_LSB0000_NONZERO,
333333
OPERAND_SIMM12,
334334
OPERAND_SIMM12_LSB00000,
335+
OPERAND_SIMM26,
335336
OPERAND_CLUI_IMM,
336337
OPERAND_VTYPEI10,
337338
OPERAND_VTYPEI11,

llvm/lib/Target/RISCV/RISCVFeatures.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,14 @@ def HasVendorXqciint
13101310
AssemblerPredicate<(all_of FeatureVendorXqciint),
13111311
"'Xqciint' (Qualcomm uC Interrupts Extension)">;
13121312

1313+
def FeatureVendorXqcilo
1314+
: RISCVExperimentalExtension<0, 2, "Qualcomm uC Large Offset Load Store Extension",
1315+
[FeatureStdExtZca]>;
1316+
def HasVendorXqcilo
1317+
: Predicate<"Subtarget->hasVendorXqcilo()">,
1318+
AssemblerPredicate<(all_of FeatureVendorXqcilo),
1319+
"'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)">;
1320+
13131321
//===----------------------------------------------------------------------===//
13141322
// LLVM specific features and extensions
13151323
//===----------------------------------------------------------------------===//

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2513,6 +2513,7 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
25132513
CASE_OPERAND_SIMM(5)
25142514
CASE_OPERAND_SIMM(6)
25152515
CASE_OPERAND_SIMM(12)
2516+
CASE_OPERAND_SIMM(26)
25162517
// clang-format on
25172518
case RISCVOp::OPERAND_SIMM5_PLUS1:
25182519
Ok = (isInt<5>(Imm) && Imm != -16) || Imm == 16;

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ def uimm10 : RISCVUImmLeafOp<10>;
3232

3333
def uimm11 : RISCVUImmLeafOp<11>;
3434

35+
def simm26 : RISCVSImmLeafOp<26>;
36+
3537
//===----------------------------------------------------------------------===//
3638
// Instruction Formats
3739
//===----------------------------------------------------------------------===//
@@ -198,6 +200,51 @@ class QCIInt_IMM<bits<1> funct1, string opcodestr>
198200
let Inst{24-20} = imm10{9-5};
199201
}
200202

203+
class QCIRVInstEIBase<bits<3> funct3, bits<2> funct2, dag outs,
204+
dag ins, string opcodestr, string argstr>
205+
: RVInst48<outs, ins, opcodestr, argstr, [], InstFormatOther> {
206+
bits<5> rd;
207+
bits<5> rs1;
208+
bits<26> imm;
209+
210+
let Inst{47-32} = imm{25-10};
211+
let Inst{31-30} = funct2;
212+
let Inst{29-20} = imm{9-0};
213+
let Inst{19-15} = rs1;
214+
let Inst{14-12} = funct3;
215+
let Inst{11-7} = rd;
216+
let Inst{6-0} = 0b0011111;
217+
}
218+
219+
let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
220+
class QCIRVInstEILoad<bits<3> funct3, bits<2> funct2, string opcodestr>
221+
: QCIRVInstEIBase<funct3, funct2, (outs GPR:$rd),
222+
(ins GPRMem:$rs1, simm26:$imm), opcodestr,
223+
"$rd, ${imm}(${rs1})">;
224+
225+
class QCIRVInstESBase<bits<3> funct3, bits<2> funct2, dag outs,
226+
dag ins, string opcodestr, string argstr>
227+
: RVInst48<outs, ins, opcodestr, argstr, [], InstFormatOther> {
228+
bits<5> rs1;
229+
bits<5> rs2;
230+
bits<26> imm;
231+
232+
let Inst{47-32} = imm{25-10};
233+
let Inst{31-30} = funct2;
234+
let Inst{29-25} = imm{9-5};
235+
let Inst{24-20} = rs2;
236+
let Inst{19-15} = rs1;
237+
let Inst{14-12} = funct3;
238+
let Inst{11-7} = imm{4-0};
239+
let Inst{6-0} = 0b0011111;
240+
}
241+
242+
let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
243+
class QCIRVInstESStore<bits<3> funct3, bits<2> funct2, string opcodestr>
244+
: QCIRVInstESBase<funct3, funct2, (outs),
245+
(ins GPRMem:$rs2, GPR:$rs1, simm26:$imm),
246+
opcodestr, "$rs2, ${imm}(${rs1})">;
247+
201248
//===----------------------------------------------------------------------===//
202249
// Instructions
203250
//===----------------------------------------------------------------------===//
@@ -376,6 +423,18 @@ let Predicates = [HasVendorXqciint, IsRV32], DecoderNamespace = "Xqciint" in {
376423
def QC_C_MILEAVERET : QCIRVInst16CI_NONE<0b10100, "qc.c.mileaveret">;
377424
} // Predicates = [HasVendorXqciint, IsRV32], DecoderNamespace = "Xqciint"
378425

426+
let Predicates = [HasVendorXqcilo, IsRV32], DecoderNamespace = "Xqcilo" in {
427+
def QC_E_LB : QCIRVInstEILoad<0b101, 0b00, "qc.e.lb">;
428+
def QC_E_LBU : QCIRVInstEILoad<0b101, 0b01, "qc.e.lbu">;
429+
def QC_E_LH : QCIRVInstEILoad<0b101, 0b10, "qc.e.lh">;
430+
def QC_E_LHU : QCIRVInstEILoad<0b101, 0b11, "qc.e.lhu">;
431+
def QC_E_LW : QCIRVInstEILoad<0b110, 0b00, "qc.e.lw">;
432+
433+
def QC_E_SB : QCIRVInstESStore<0b110, 0b01, "qc.e.sb">;
434+
def QC_E_SH : QCIRVInstESStore<0b110, 0b10, "qc.e.sh">;
435+
def QC_E_SW : QCIRVInstESStore<0b110, 0b11, "qc.e.sw">;
436+
} // Predicates = [HasVendorXqcilo, IsRV32], DecoderNamespace = "Xqcilo"
437+
379438
//===----------------------------------------------------------------------===//
380439
// Aliases
381440
//===----------------------------------------------------------------------===//
@@ -396,3 +455,24 @@ let EmitPriority = 0 in {
396455
(QC_LWMI GPRNoX0:$rd, GPR:$rs1, uimm5nonzero:$length, 0)>;
397456
} // EmitPriority = 0
398457
} // Predicates = [HasVendorXqcilsm, IsRV32]
458+
459+
let Predicates = [HasVendorXqcilo, IsRV32] in {
460+
let EmitPriority = 0 in {
461+
def : InstAlias<"qc.e.lb $rd, (${rs1})",
462+
(QC_E_LB GPR:$rd, GPR:$rs1, 0)>;
463+
def : InstAlias<"qc.e.lbu $rd, (${rs1})",
464+
(QC_E_LBU GPR:$rd, GPR:$rs1, 0)>;
465+
def : InstAlias<"qc.e.lh $rd, (${rs1})",
466+
(QC_E_LH GPR:$rd, GPR:$rs1, 0)>;
467+
def : InstAlias<"qc.e.lhu $rd, (${rs1})",
468+
(QC_E_LHU GPR:$rd, GPR:$rs1, 0)>;
469+
def : InstAlias<"qc.e.lw $rd, (${rs1})",
470+
(QC_E_LW GPR:$rd, GPR:$rs1, 0)>;
471+
def : InstAlias<"qc.e.sb $rs2, (${rs1})",
472+
(QC_E_SB GPR:$rs2, GPR:$rs1, 0)>;
473+
def : InstAlias<"qc.e.sh $rs2, (${rs1})",
474+
(QC_E_SH GPR:$rs2, GPR:$rs1, 0)>;
475+
def : InstAlias<"qc.e.sw $rs2, (${rs1})",
476+
(QC_E_SW GPR:$rs2, GPR:$rs1, 0)>;
477+
} // EmitPriority = 0
478+
} // Predicates = [HasVendorXqcilo, IsRV32]

llvm/lib/TargetParser/RISCVISAInfo.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -742,8 +742,8 @@ Error RISCVISAInfo::checkDependency() {
742742
bool HasZvl = MinVLen != 0;
743743
bool HasZcmt = Exts.count("zcmt") != 0;
744744
static constexpr StringLiteral XqciExts[] = {
745-
{"xqcia"}, {"xqciac"}, {"xqcicli"}, {"xqcicm"}, {"xqcics"},
746-
{"xqcicsr"}, {"xqciint"}, {"xqcilsm"}, {"xqcisls"}};
745+
{"xqcia"}, {"xqciac"}, {"xqcicli"}, {"xqcicm"}, {"xqcics"},
746+
{"xqcicsr"}, {"xqciint"}, {"xqcilo"}, {"xqcilsm"}, {"xqcisls"}};
747747

748748
if (HasI && HasE)
749749
return getIncompatibleError("i", "e");

llvm/test/CodeGen/RISCV/attributes.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcics %s -o - | FileCheck --check-prefix=RV32XQCICS %s
8989
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicsr %s -o - | FileCheck --check-prefix=RV32XQCICSR %s
9090
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqciint %s -o - | FileCheck --check-prefix=RV32XQCIINT %s
91+
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilo %s -o - | FileCheck --check-prefix=RV32XQCILO %s
9192
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilsm %s -o - | FileCheck --check-prefix=RV32XQCILSM %s
9293
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisls %s -o - | FileCheck --check-prefix=RV32XQCISLS %s
9394
; RUN: llc -mtriple=riscv32 -mattr=+zaamo %s -o - | FileCheck --check-prefix=RV32ZAAMO %s
@@ -403,6 +404,7 @@
403404
; RV32XQCICS: .attribute 5, "rv32i2p1_xqcics0p2"
404405
; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
405406
; RV32XQCIINT: .attribute 5, "rv32i2p1_zca1p0_xqciint0p2"
407+
; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
406408
; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p2"
407409
; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
408410
; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Xqcilo - Qualcomm uC Large Offset Load Store extension
2+
# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcilo -riscv-no-aliases -show-encoding \
3+
# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
4+
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcilo < %s \
5+
# RUN: | llvm-objdump --mattr=+experimental-xqcilo -M no-aliases --no-print-imm-hex -d - \
6+
# RUN: | FileCheck -check-prefix=CHECK-INST %s
7+
# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcilo -show-encoding \
8+
# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
9+
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcilo < %s \
10+
# RUN: | llvm-objdump --mattr=+experimental-xqcilo --no-print-imm-hex -d - \
11+
# RUN: | FileCheck -check-prefix=CHECK-INST %s
12+
13+
# CHECK-INST: qc.e.lb a1, 0(a0)
14+
# CHECK-ENC: encoding: [0x9f,0x55,0x05,0x00,0x00,0x00]
15+
qc.e.lb x11, (x10)
16+
17+
18+
# CHECK-INST: qc.e.lbu a1, 0(a0)
19+
# CHECK-ENC: encoding: [0x9f,0x55,0x05,0x40,0x00,0x00]
20+
qc.e.lbu x11, (x10)
21+
22+
23+
# CHECK-INST: qc.e.lh a1, 0(a0)
24+
# CHECK-ENC: encoding: [0x9f,0x55,0x05,0x80,0x00,0x00]
25+
qc.e.lh x11, (x10)
26+
27+
28+
# CHECK-INST: qc.e.lhu a1, 0(a0)
29+
# CHECK-ENC: encoding: [0x9f,0x55,0x05,0xc0,0x00,0x00]
30+
qc.e.lhu x11, (x10)
31+
32+
33+
# CHECK-INST: qc.e.lw a1, 0(a0)
34+
# CHECK-ENC: encoding: [0x9f,0x65,0x05,0x00,0x00,0x00]
35+
qc.e.lw x11, (x10)
36+
37+
38+
# CHECK-INST: qc.e.sb a1, 0(a0)
39+
# CHECK-ENC: encoding: [0x1f,0x60,0xb5,0x40,0x00,0x00]
40+
qc.e.sb x11, (x10)
41+
42+
43+
# CHECK-INST: qc.e.sh a1, 0(a0)
44+
# CHECK-ENC: encoding: [0x1f,0x60,0xb5,0x80,0x00,0x00]
45+
qc.e.sh x11, (x10)
46+
47+
48+
# CHECK-INST: qc.e.sw a1, 0(a0)
49+
# CHECK-ENC: encoding: [0x1f,0x60,0xb5,0xc0,0x00,0x00]
50+
qc.e.sw x11, (x10)

0 commit comments

Comments
 (0)