Skip to content

[RISCV] Add Qualcomm uC Xqcilo (Large Offset Load Store) extension #123881

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/test/Driver/print-supported-extensions-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@
// CHECK-NEXT: xqcics 0.2 'Xqcics' (Qualcomm uC Conditional Select Extension)
// CHECK-NEXT: xqcicsr 0.2 'Xqcicsr' (Qualcomm uC CSR Extension)
// CHECK-NEXT: xqciint 0.2 'Xqciint' (Qualcomm uC Interrupts Extension)
// CHECK-NEXT: xqcilo 0.2 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)
// CHECK-NEXT: xqcilsm 0.2 'Xqcilsm' (Qualcomm uC Load Store Multiple Extension)
// CHECK-NEXT: xqcisls 0.2 'Xqcisls' (Qualcomm uC Scaled Load Store Extension)
// CHECK-EMPTY:
Expand Down
3 changes: 3 additions & 0 deletions llvm/docs/RISCVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,9 @@ The current vendor extensions supported are:
``experimental-Xqciint``
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.

``experimental-Xqcilo``
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.

``experimental-Xqcilsm``
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.

Expand Down
2 changes: 2 additions & 0 deletions llvm/docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ Changes to the RISC-V Backend
extension.
* Adds experimental assembler support for the Qualcomm uC 'Xqciint` (Interrupts)
extension.
* Adds experimental assembler support for the Qualcomm uC 'Xqcilo` (Large Offset Load Store)
extension.
* Added ``Sdext`` and ``Sdtrig`` extensions.

Changes to the WebAssembly Backend
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,16 @@ struct RISCVOperand final : public MCParsedAsmOperand {
VK == RISCVMCExpr::VK_RISCV_None;
}

bool isSImm26() const {
if (!isImm())
return false;
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
int64_t Imm;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
return IsConstantImm && (VK == RISCVMCExpr::VK_RISCV_None) &&
isInt<26>(fixImmediateForRV32(Imm, isRV64Imm()));
}

/// getStartLoc - Gets location of the first token of this operand
SMLoc getStartLoc() const override { return StartLoc; }
/// getEndLoc - Gets location of the last token of this operand
Expand Down Expand Up @@ -1676,6 +1686,9 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
(1 << 4),
"immediate must be in the range");
}
case Match_InvalidSImm26:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 25),
(1 << 25) - 1);
case Match_InvalidRlist: {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(
Expand Down
28 changes: 26 additions & 2 deletions llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class RISCVDisassembler : public MCDisassembler {
private:
void addSPOperands(MCInst &MI) const;

DecodeStatus getInstruction48(MCInst &Instr, uint64_t &Size,
ArrayRef<uint8_t> Bytes, uint64_t Address,
raw_ostream &CStream) const;

DecodeStatus getInstruction32(MCInst &Instr, uint64_t &Size,
ArrayRef<uint8_t> Bytes, uint64_t Address,
raw_ostream &CStream) const;
Expand Down Expand Up @@ -745,6 +749,27 @@ DecodeStatus RISCVDisassembler::getInstruction16(MCInst &MI, uint64_t &Size,
return MCDisassembler::Fail;
}

DecodeStatus RISCVDisassembler::getInstruction48(MCInst &MI, uint64_t &Size,
ArrayRef<uint8_t> Bytes,
uint64_t Address,
raw_ostream &CS) const {
if (Bytes.size() < 6) {
Size = 0;
return MCDisassembler::Fail;
}
Size = 6;

uint64_t Insn = 0;
for (size_t i = Size; i-- != 0;) {
Insn += (static_cast<uint64_t>(Bytes[i]) << 8 * i);
}
TRY_TO_DECODE_FEATURE(
RISCV::FeatureVendorXqcilo, DecoderTableXqcilo48,
"Qualcomm uC Large Offset Load Store custom 48bit opcode table");

return MCDisassembler::Fail;
}

DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
ArrayRef<uint8_t> Bytes,
uint64_t Address,
Expand All @@ -760,8 +785,7 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,

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

// 64-bit instructions are encoded as 0x0111111.
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ enum OperandType : unsigned {
OPERAND_SIMM10_LSB0000_NONZERO,
OPERAND_SIMM12,
OPERAND_SIMM12_LSB00000,
OPERAND_SIMM26,
OPERAND_CLUI_IMM,
OPERAND_VTYPEI10,
OPERAND_VTYPEI11,
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,14 @@ def HasVendorXqciint
AssemblerPredicate<(all_of FeatureVendorXqciint),
"'Xqciint' (Qualcomm uC Interrupts Extension)">;

def FeatureVendorXqcilo
: RISCVExperimentalExtension<0, 2, "Qualcomm uC Large Offset Load Store Extension",
[FeatureStdExtZca]>;
def HasVendorXqcilo
: Predicate<"Subtarget->hasVendorXqcilo()">,
AssemblerPredicate<(all_of FeatureVendorXqcilo),
"'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)">;

//===----------------------------------------------------------------------===//
// LLVM specific features and extensions
//===----------------------------------------------------------------------===//
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2514,6 +2514,7 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
CASE_OPERAND_SIMM(5)
CASE_OPERAND_SIMM(6)
CASE_OPERAND_SIMM(12)
CASE_OPERAND_SIMM(26)
// clang-format on
case RISCVOp::OPERAND_SIMM5_PLUS1:
Ok = (isInt<5>(Imm) && Imm != -16) || Imm == 16;
Expand Down
80 changes: 80 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ def uimm10 : RISCVUImmLeafOp<10>;

def uimm11 : RISCVUImmLeafOp<11>;

def simm26 : RISCVSImmLeafOp<26>;

//===----------------------------------------------------------------------===//
// Instruction Formats
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -198,6 +200,51 @@ class QCIInt_IMM<bits<1> funct1, string opcodestr>
let Inst{24-20} = imm10{9-5};
}

class QCIRVInstEIBase<bits<3> funct3, bits<2> funct2, dag outs,
dag ins, string opcodestr, string argstr>
: RVInst48<outs, ins, opcodestr, argstr, [], InstFormatOther> {
bits<5> rd;
bits<5> rs1;
bits<26> imm;

let Inst{47-32} = imm{25-10};
let Inst{31-30} = funct2;
let Inst{29-20} = imm{9-0};
let Inst{19-15} = rs1;
let Inst{14-12} = funct3;
let Inst{11-7} = rd;
let Inst{6-0} = 0b0011111;
}

let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
class QCIRVInstEILoad<bits<3> funct3, bits<2> funct2, string opcodestr>
: QCIRVInstEIBase<funct3, funct2, (outs GPR:$rd),
(ins GPRMem:$rs1, simm26:$imm), opcodestr,
"$rd, ${imm}(${rs1})">;

class QCIRVInstESBase<bits<3> funct3, bits<2> funct2, dag outs,
dag ins, string opcodestr, string argstr>
: RVInst48<outs, ins, opcodestr, argstr, [], InstFormatOther> {
bits<5> rs1;
bits<5> rs2;
bits<26> imm;

let Inst{47-32} = imm{25-10};
let Inst{31-30} = funct2;
let Inst{29-25} = imm{9-5};
let Inst{24-20} = rs2;
let Inst{19-15} = rs1;
let Inst{14-12} = funct3;
let Inst{11-7} = imm{4-0};
let Inst{6-0} = 0b0011111;
}

let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
class QCIRVInstESStore<bits<3> funct3, bits<2> funct2, string opcodestr>
: QCIRVInstESBase<funct3, funct2, (outs),
(ins GPRMem:$rs2, GPR:$rs1, simm26:$imm),
opcodestr, "$rs2, ${imm}(${rs1})">;

//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -376,6 +423,18 @@ let Predicates = [HasVendorXqciint, IsRV32], DecoderNamespace = "Xqciint" in {
def QC_C_MILEAVERET : QCIRVInst16CI_NONE<0b10100, "qc.c.mileaveret">;
} // Predicates = [HasVendorXqciint, IsRV32], DecoderNamespace = "Xqciint"

let Predicates = [HasVendorXqcilo, IsRV32], DecoderNamespace = "Xqcilo" in {
def QC_E_LB : QCIRVInstEILoad<0b101, 0b00, "qc.e.lb">;
def QC_E_LBU : QCIRVInstEILoad<0b101, 0b01, "qc.e.lbu">;
def QC_E_LH : QCIRVInstEILoad<0b101, 0b10, "qc.e.lh">;
def QC_E_LHU : QCIRVInstEILoad<0b101, 0b11, "qc.e.lhu">;
def QC_E_LW : QCIRVInstEILoad<0b110, 0b00, "qc.e.lw">;

def QC_E_SB : QCIRVInstESStore<0b110, 0b01, "qc.e.sb">;
def QC_E_SH : QCIRVInstESStore<0b110, 0b10, "qc.e.sh">;
def QC_E_SW : QCIRVInstESStore<0b110, 0b11, "qc.e.sw">;
} // Predicates = [HasVendorXqcilo, IsRV32], DecoderNamespace = "Xqcilo"

//===----------------------------------------------------------------------===//
// Aliases
//===----------------------------------------------------------------------===//
Expand All @@ -396,3 +455,24 @@ let EmitPriority = 0 in {
(QC_LWMI GPRNoX0:$rd, GPR:$rs1, uimm5nonzero:$length, 0)>;
} // EmitPriority = 0
} // Predicates = [HasVendorXqcilsm, IsRV32]

let Predicates = [HasVendorXqcilo, IsRV32] in {
let EmitPriority = 0 in {
def : InstAlias<"qc.e.lb $rd, (${rs1})",
(QC_E_LB GPR:$rd, GPR:$rs1, 0)>;
def : InstAlias<"qc.e.lbu $rd, (${rs1})",
(QC_E_LBU GPR:$rd, GPR:$rs1, 0)>;
def : InstAlias<"qc.e.lh $rd, (${rs1})",
(QC_E_LH GPR:$rd, GPR:$rs1, 0)>;
def : InstAlias<"qc.e.lhu $rd, (${rs1})",
(QC_E_LHU GPR:$rd, GPR:$rs1, 0)>;
def : InstAlias<"qc.e.lw $rd, (${rs1})",
(QC_E_LW GPR:$rd, GPR:$rs1, 0)>;
def : InstAlias<"qc.e.sb $rs2, (${rs1})",
(QC_E_SB GPR:$rs2, GPR:$rs1, 0)>;
def : InstAlias<"qc.e.sh $rs2, (${rs1})",
(QC_E_SH GPR:$rs2, GPR:$rs1, 0)>;
def : InstAlias<"qc.e.sw $rs2, (${rs1})",
(QC_E_SW GPR:$rs2, GPR:$rs1, 0)>;
} // EmitPriority = 0
} // Predicates = [HasVendorXqcilo, IsRV32]
4 changes: 2 additions & 2 deletions llvm/lib/TargetParser/RISCVISAInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -742,8 +742,8 @@ Error RISCVISAInfo::checkDependency() {
bool HasZvl = MinVLen != 0;
bool HasZcmt = Exts.count("zcmt") != 0;
static constexpr StringLiteral XqciExts[] = {
{"xqcia"}, {"xqciac"}, {"xqcicli"}, {"xqcicm"}, {"xqcics"},
{"xqcicsr"}, {"xqciint"}, {"xqcilsm"}, {"xqcisls"}};
{"xqcia"}, {"xqciac"}, {"xqcicli"}, {"xqcicm"}, {"xqcics"},
{"xqcicsr"}, {"xqciint"}, {"xqcilo"}, {"xqcilsm"}, {"xqcisls"}};

if (HasI && HasE)
return getIncompatibleError("i", "e");
Expand Down
2 changes: 2 additions & 0 deletions llvm/test/CodeGen/RISCV/attributes.ll
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcics %s -o - | FileCheck --check-prefix=RV32XQCICS %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicsr %s -o - | FileCheck --check-prefix=RV32XQCICSR %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqciint %s -o - | FileCheck --check-prefix=RV32XQCIINT %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilo %s -o - | FileCheck --check-prefix=RV32XQCILO %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilsm %s -o - | FileCheck --check-prefix=RV32XQCILSM %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcisls %s -o - | FileCheck --check-prefix=RV32XQCISLS %s
; RUN: llc -mtriple=riscv32 -mattr=+zaamo %s -o - | FileCheck --check-prefix=RV32ZAAMO %s
Expand Down Expand Up @@ -403,6 +404,7 @@
; RV32XQCICS: .attribute 5, "rv32i2p1_xqcics0p2"
; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
; RV32XQCIINT: .attribute 5, "rv32i2p1_zca1p0_xqciint0p2"
; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p2"
; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"
Expand Down
50 changes: 50 additions & 0 deletions llvm/test/MC/RISCV/xqcilo-aliases-valid.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Xqcilo - Qualcomm uC Large Offset Load Store extension
# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcilo -riscv-no-aliases -show-encoding \
# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcilo < %s \
# RUN: | llvm-objdump --mattr=+experimental-xqcilo -M no-aliases --no-print-imm-hex -d - \
# RUN: | FileCheck -check-prefix=CHECK-INST %s
# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcilo -show-encoding \
# RUN: | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcilo < %s \
# RUN: | llvm-objdump --mattr=+experimental-xqcilo --no-print-imm-hex -d - \
# RUN: | FileCheck -check-prefix=CHECK-INST %s

# CHECK-INST: qc.e.lb a1, 0(a0)
# CHECK-ENC: encoding: [0x9f,0x55,0x05,0x00,0x00,0x00]
qc.e.lb x11, (x10)


# CHECK-INST: qc.e.lbu a1, 0(a0)
# CHECK-ENC: encoding: [0x9f,0x55,0x05,0x40,0x00,0x00]
qc.e.lbu x11, (x10)


# CHECK-INST: qc.e.lh a1, 0(a0)
# CHECK-ENC: encoding: [0x9f,0x55,0x05,0x80,0x00,0x00]
qc.e.lh x11, (x10)


# CHECK-INST: qc.e.lhu a1, 0(a0)
# CHECK-ENC: encoding: [0x9f,0x55,0x05,0xc0,0x00,0x00]
qc.e.lhu x11, (x10)


# CHECK-INST: qc.e.lw a1, 0(a0)
# CHECK-ENC: encoding: [0x9f,0x65,0x05,0x00,0x00,0x00]
qc.e.lw x11, (x10)


# CHECK-INST: qc.e.sb a1, 0(a0)
# CHECK-ENC: encoding: [0x1f,0x60,0xb5,0x40,0x00,0x00]
qc.e.sb x11, (x10)


# CHECK-INST: qc.e.sh a1, 0(a0)
# CHECK-ENC: encoding: [0x1f,0x60,0xb5,0x80,0x00,0x00]
qc.e.sh x11, (x10)


# CHECK-INST: qc.e.sw a1, 0(a0)
# CHECK-ENC: encoding: [0x1f,0x60,0xb5,0xc0,0x00,0x00]
qc.e.sw x11, (x10)
Loading
Loading