Skip to content

Commit e3f9548

Browse files
committed
[RISCV] Add Qualcomm uC Xqcilb (Long Branch) extension
This extension adds two long branch instructions. The current spec can be found at: https://github.com/quic/riscv-unified-db/releases/tag/Xqci-0.7.0 This patch adds assembler only support. Change-Id: I262d59edc8c7266800badc82d6496619ce2aeabf
1 parent 846cf86 commit e3f9548

File tree

12 files changed

+130
-7
lines changed

12 files changed

+130
-7
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@
202202
// CHECK-NEXT: xqcics 0.2 'Xqcics' (Qualcomm uC Conditional Select Extension)
203203
// CHECK-NEXT: xqcicsr 0.2 'Xqcicsr' (Qualcomm uC CSR Extension)
204204
// CHECK-NEXT: xqciint 0.4 'Xqciint' (Qualcomm uC Interrupts Extension)
205+
// CHECK-NEXT: xqcilb 0.2 'Xqcilb' (Qualcomm uC Long Branch Extension)
205206
// CHECK-NEXT: xqcili 0.2 'Xqcili' (Qualcomm uC Load Large Immediate Extension)
206207
// CHECK-NEXT: xqcilia 0.2 'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
207208
// CHECK-NEXT: xqcilo 0.2 'Xqcilo' (Qualcomm uC Large Offset Load Store Extension)

llvm/docs/RISCVUsage.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,9 @@ The current vendor extensions supported are:
456456
``experimental-Xqciint``
457457
LLVM implements `version 0.4 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.
458458

459+
``experimental-Xqcilb``
460+
LLVM implements `version 0.2 of the Qualcomm uC Long Branch 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.
461+
459462
``experimental-Xqcili``
460463
LLVM implements `version 0.2 of the Qualcomm uC Load Large Immediate 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.
461464

llvm/docs/ReleaseNotes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ Changes to the PowerPC Backend
110110
Changes to the RISC-V Backend
111111
-----------------------------
112112

113+
* Adds experimental assembler support for the Qualcomm uC 'Xqcilb` (Long Branch)
114+
extension.
113115
* Adds experimental assembler support for the Qualcomm uC 'Xqcili` (Load Large Immediate)
114116
extension.
115117
* Adds experimental assembler support for the Qualcomm uC 'Xqcilia` (Large Immediate Arithmetic)

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,17 @@ struct RISCVOperand final : public MCParsedAsmOperand {
11061106
VK == RISCVMCExpr::VK_RISCV_None;
11071107
}
11081108

1109+
bool isSImm32Lsb0() const {
1110+
if (!isImm())
1111+
return false;
1112+
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
1113+
int64_t Imm;
1114+
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
1115+
return IsConstantImm &&
1116+
isShiftedInt<31, 1>(fixImmediateForRV32(Imm, isRV64Imm())) &&
1117+
VK == RISCVMCExpr::VK_RISCV_None;
1118+
}
1119+
11091120
/// getStartLoc - Gets location of the first token of this operand
11101121
SMLoc getStartLoc() const override { return StartLoc; }
11111122
/// getEndLoc - Gets location of the last token of this operand
@@ -1729,6 +1740,11 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
17291740
return generateImmOutOfRangeError(Operands, ErrorInfo,
17301741
std::numeric_limits<int32_t>::min(),
17311742
std::numeric_limits<uint32_t>::max());
1743+
case Match_InvalidSImm32Lsb0:
1744+
return generateImmOutOfRangeError(
1745+
Operands, ErrorInfo, std::numeric_limits<int32_t>::min(),
1746+
std::numeric_limits<int32_t>::max() - 1,
1747+
"operand must be a multiple of 2 bytes in the range ");
17321748
case Match_InvalidRnumArg: {
17331749
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
17341750
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -651,9 +651,9 @@ static constexpr FeatureBitset XqciFeatureGroup = {
651651
RISCV::FeatureVendorXqcibm, RISCV::FeatureVendorXqcicli,
652652
RISCV::FeatureVendorXqcicm, RISCV::FeatureVendorXqcics,
653653
RISCV::FeatureVendorXqcicsr, RISCV::FeatureVendorXqciint,
654-
RISCV::FeatureVendorXqcili, RISCV::FeatureVendorXqcilia,
655-
RISCV::FeatureVendorXqcilo, RISCV::FeatureVendorXqcilsm,
656-
RISCV::FeatureVendorXqcisls,
654+
RISCV::FeatureVendorXqcili, RISCV::FeatureVendorXqcilb,
655+
RISCV::FeatureVendorXqcilia, RISCV::FeatureVendorXqcilo,
656+
RISCV::FeatureVendorXqcilsm, RISCV::FeatureVendorXqcisls,
657657
};
658658

659659
static constexpr FeatureBitset XSfVectorGroup = {

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 HasVendorXqciint
13591359
AssemblerPredicate<(all_of FeatureVendorXqciint),
13601360
"'Xqciint' (Qualcomm uC Interrupts Extension)">;
13611361

1362+
def FeatureVendorXqcilb
1363+
: RISCVExperimentalExtension<0, 2, "Qualcomm uC Long Branch Extension",
1364+
[FeatureStdExtZca]>;
1365+
1366+
def HasVendorXqcilb : Predicate<"Subtarget->hasVendorXqcilb()">,
1367+
AssemblerPredicate<(all_of FeatureVendorXqcilb),
1368+
"'Xqcilb' (Qualcomm uC oad Large Immediate Extension)">;
1369+
13621370
def FeatureVendorXqcili
13631371
: RISCVExperimentalExtension<0, 2, "Qualcomm uC Load Large Immediate Extension",
13641372
[FeatureStdExtZca]>;

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,21 @@ def simm32 : RISCVOp<XLenVT> {
7575
}];
7676
}
7777

78+
// A 32-bit signed immediate where the least significant bit is zero.
79+
def simm32_lsb0 : Operand<OtherVT> {
80+
let ParserMatchClass = SImmAsmOperand<32, "Lsb0">;
81+
let PrintMethod = "printBranchOperand";
82+
let EncoderMethod = "getImmOpValueAsr1";
83+
let DecoderMethod = "decodeSImmOperandAndLsl1<32>";
84+
let MCOperandPredicate = [{
85+
int64_t Imm;
86+
if (!MCOp.evaluateAsConstantImm(Imm))
87+
return false;
88+
return isShiftedInt<31, 1>(Imm);
89+
}];
90+
let OperandType = "OPERAND_PCREL";
91+
}
92+
7893
//===----------------------------------------------------------------------===//
7994
// Instruction Formats
8095
//===----------------------------------------------------------------------===//
@@ -345,6 +360,24 @@ class QCIRVInstEI<bits<3> funct3, bits<2> funct2, string opcodestr>
345360
(ins GPRNoX0:$rs1, simm26:$imm), opcodestr,
346361
"$rd, $rs1, $imm">;
347362

363+
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
364+
class QCIRVInst48EJ<bits<2> func2, string opcodestr>
365+
: RVInst48<(outs), (ins simm32_lsb0:$imm31),
366+
opcodestr, "$imm31", [], InstFormatQCEJ> {
367+
bits<31> imm31;
368+
369+
let Inst{47-32} = imm31{30-15};
370+
let Inst{31} = imm31{11};
371+
let Inst{30-25} = imm31{9-4};
372+
let Inst{24-20} = 0b00000;
373+
let Inst{19-17} = imm31{14-12};
374+
let Inst{16-15} = func2;
375+
let Inst{14-12} = 0b100;
376+
let Inst{11-8} = imm31{3-0};
377+
let Inst{7} = imm31{10};
378+
let Inst{6-0} = 0b0011111;
379+
}
380+
348381
//===----------------------------------------------------------------------===//
349382
// Instructions
350383
//===----------------------------------------------------------------------===//
@@ -593,6 +626,13 @@ let Predicates = [HasVendorXqcilo, IsRV32] in {
593626
def QC_E_SW : QCIRVInstESStore<0b110, 0b11, "qc.e.sw">;
594627
} // Predicates = [HasVendorXqcilo, IsRV32]
595628

629+
let Predicates = [HasVendorXqcilb, IsRV32] in {
630+
let isCall = 1, Defs = [X1] in
631+
def QC_E_JAL : QCIRVInst48EJ<0b01, "qc.e.jal">;
632+
let isBranch = 1, isTerminator = 1, isBarrier = 1 in
633+
def QC_E_J : QCIRVInst48EJ<0b00, "qc.e.j">;
634+
} // Predicates = [HasVendorXqcilb, IsRV32]
635+
596636
let Predicates = [HasVendorXqcili, IsRV32] in {
597637
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
598638
def QC_LI : RVInstU<OPC_OP_IMM_32, (outs GPRNoX0:$rd), (ins simm20:$imm20),

llvm/lib/TargetParser/RISCVISAInfo.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -744,9 +744,9 @@ Error RISCVISAInfo::checkDependency() {
744744
bool HasXqccmp = Exts.count("xqccmp") != 0;
745745

746746
static constexpr StringLiteral XqciExts[] = {
747-
{"xqcia"}, {"xqciac"}, {"xqcibm"}, {"xqcicli"}, {"xqcicm"},
748-
{"xqcics"}, {"xqcicsr"}, {"xqciint"}, {"xqcili"}, {"xqcilia"},
749-
{"xqcilo"}, {"xqcilsm"}, {"xqcisls"}};
747+
{"xqcia"}, {"xqciac"}, {"xqcibm"}, {"xqcicli"}, {"xqcicm"},
748+
{"xqcics"}, {"xqcicsr"}, {"xqciint"}, {"xqcilb"}, {"xqcili"},
749+
{"xqcilia"}, {"xqcilo"}, {"xqcilsm"}, {"xqcisls"}};
750750
static constexpr StringLiteral ZcdOverlaps[] = {
751751
{"zcmt"}, {"zcmp"}, {"xqccmp"}, {"xqciac"}, {"xqcicm"}};
752752

llvm/test/CodeGen/RISCV/attributes.ll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcics %s -o - | FileCheck --check-prefix=RV32XQCICS %s
9191
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicsr %s -o - | FileCheck --check-prefix=RV32XQCICSR %s
9292
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqciint %s -o - | FileCheck --check-prefix=RV32XQCIINT %s
93+
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilb %s -o - | FileCheck --check-prefix=RV32XQCILB %s
9394
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcili %s -o - | FileCheck --check-prefix=RV32XQCILI %s
9495
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilia %s -o - | FileCheck --check-prefix=RV32XQCILIA %s
9596
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcilo %s -o - | FileCheck --check-prefix=RV32XQCILO %s
@@ -413,6 +414,7 @@
413414
; RV32XQCICS: .attribute 5, "rv32i2p1_xqcics0p2"
414415
; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
415416
; RV32XQCIINT: .attribute 5, "rv32i2p1_zca1p0_xqciint0p4"
417+
; RV32XQCILB: .attribute 5, "rv32i2p1_zca1p0_xqcilb0p2"
416418
; RV32XQCILI: .attribute 5, "rv32i2p1_zca1p0_xqcili0p2"
417419
; RV32XQCILIA: .attribute 5, "rv32i2p1_zca1p0_xqcilia0p2"
418420
; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Xqcilb - Qualcomm uC Long Branch Extension
2+
# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcilb < %s 2>&1 \
3+
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
4+
# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcilb < %s 2>&1 \
5+
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s
6+
7+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
8+
qc.e.j
9+
10+
# CHECK-PLUS: :[[@LINE+1]]:9: error: operand must be a multiple of 2 bytes in the range [-2147483648, 2147483646]
11+
qc.e.j -2147483649
12+
13+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilb' (Qualcomm uC Long Branch Extension)
14+
qc.e.j -2147483648
15+
16+
17+
# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
18+
qc.e.jal
19+
20+
# CHECK-PLUS: :[[@LINE+1]]:10: error: operand must be a multiple of 2 bytes in the range [-2147483648, 2147483646]
21+
qc.e.jal 2147483649
22+
23+
# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilb' (Qualcomm uC Long Branch Extension)
24+
qc.e.jal 2147483640

0 commit comments

Comments
 (0)