Skip to content

Commit

Permalink
[RISCV] Add Qualcomm uC Xqcia (Arithmetic) extension (llvm#118113)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
svs-quic authored Dec 1, 2024
1 parent 017c75b commit 6881c6d
Show file tree
Hide file tree
Showing 13 changed files with 322 additions and 1 deletion.
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 @@ -188,6 +188,7 @@
// CHECK-NEXT: smctr 1.0 'Smctr' (Control Transfer Records Machine Level)
// CHECK-NEXT: ssctr 1.0 'Ssctr' (Control Transfer Records Supervisor Level)
// CHECK-NEXT: svukte 0.3 'Svukte' (Address-Independent Latency of User-Mode Faults to Supervisor Addresses)
// CHECK-NEXT: xqcia 0.2 'Xqcia' (Qualcomm uC Arithmetic Extension)
// CHECK-NEXT: xqcicsr 0.2 'Xqcicsr' (Qualcomm uC CSR 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 @@ -426,6 +426,9 @@ The current vendor extensions supported are:
``Xwchc``
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".

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

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

Expand Down
2 changes: 2 additions & 0 deletions llvm/docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ Changes to the RISC-V Backend
extension.
* Adds experimental assembler support for the Qualcomm uC 'Xqcisls` (Scaled Load Store)
extension.
* Adds experimental assembler support for the Qualcomm uC 'Xqcia` (Arithmetic)
extension.

Changes to the WebAssembly Backend
----------------------------------
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
bool isUImm6() const { return IsUImm<6>(); }
bool isUImm7() const { return IsUImm<7>(); }
bool isUImm8() const { return IsUImm<8>(); }
bool isUImm11() const { return IsUImm<11>(); }
bool isUImm16() const { return IsUImm<16>(); }
bool isUImm20() const { return IsUImm<20>(); }
bool isUImm32() const { return IsUImm<32>(); }
Expand Down Expand Up @@ -1563,6 +1564,8 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 9), (1 << 9) - 16,
"immediate must be a multiple of 16 bytes and non-zero in the range");
case Match_InvalidUImm11:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 11) - 1);
case Match_InvalidSImm12:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 11), (1 << 11) - 1,
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,8 @@ DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,
"Qualcomm uC CSR custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXqcisls, DecoderTableXqcisls32,
"Qualcomm uC Scaled Load Store custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXqcia, DecoderTableXqcia32,
"Qualcomm uC Arithmetic custom opcode table");
TRY_TO_DECODE(true, DecoderTable32, "RISCV32 table");

return MCDisassembler::Fail;
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 @@ -312,6 +312,7 @@ enum OperandType : unsigned {
OPERAND_UIMM8_GE32,
OPERAND_UIMM9_LSB000,
OPERAND_UIMM10_LSB00_NONZERO,
OPERAND_UIMM11,
OPERAND_UIMM12,
OPERAND_UIMM16,
OPERAND_UIMM32,
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 @@ -1359,6 +1359,14 @@ def HasVendorXqcisls
AssemblerPredicate<(all_of FeatureVendorXqcisls),
"'Xqcisls' (Qualcomm uC Scaled Load Store Extension)">;

def FeatureVendorXqcia
: RISCVExperimentalExtension<"xqcia", 0, 2,
"'Xqcia' (Qualcomm uC Arithmetic Extension)">;
def HasVendorXqcia
: Predicate<"Subtarget->hasVendorXqcia()">,
AssemblerPredicate<(all_of FeatureVendorXqcia),
"'Xqcia' (Qualcomm uC Arithmetic Extension)">;

//===----------------------------------------------------------------------===//
// LLVM specific features and extensions
//===----------------------------------------------------------------------===//
Expand Down
36 changes: 36 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
// Operand and SDNode transformation definitions.
//===----------------------------------------------------------------------===//

def uimm11 : RISCVUImmLeafOp<11>;

//===----------------------------------------------------------------------===//
// Instruction Formats
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -45,6 +47,16 @@ class QCIStore_ScaleIdx<bits<4> func4, string opcodestr>
}
}

class QCIRVInstR<bits<4> func4, string opcodestr>
: RVInstR<{0b000, func4}, 0b011, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
(ins GPRNoX0:$rs1), opcodestr, "$rd, $rs1"> {
let rs2 = 0;
}

class QCIRVInstRR<bits<5> func5, DAGOperand InTyRs1, string opcodestr>
: RVInstR<{0b00, func5}, 0b011, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
(ins InTyRs1:$rs1, GPRNoX0:$rs2), opcodestr, "$rd, $rs1, $rs2">;

//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -72,3 +84,27 @@ let Predicates = [HasVendorXqcisls, IsRV32], DecoderNamespace = "Xqcisls" in {
def QC_SRH : QCIStore_ScaleIdx<0b1110, "qc.srh">;
def QC_SRW : QCIStore_ScaleIdx<0b1111, "qc.srw">;
} // Predicates = [HasVendorXqcisls, IsRV32], DecoderNamespace = "Xqcisls"

let Predicates = [HasVendorXqcia, IsRV32], DecoderNamespace = "Xqcia" in {
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
def QC_SLASAT : QCIRVInstRR<0b01010, GPRNoX0, "qc.slasat">;
def QC_SLLSAT : QCIRVInstRR<0b01100, GPRNoX0, "qc.sllsat">;
def QC_ADDSAT : QCIRVInstRR<0b01110, GPRNoX0, "qc.addsat">;
def QC_ADDUSAT : QCIRVInstRR<0b01111, GPRNoX0, "qc.addusat">;
def QC_SUBSAT : QCIRVInstRR<0b10000, GPRNoX0, "qc.subsat">;
def QC_SUBUSAT : QCIRVInstRR<0b10001, GPRNoX0, "qc.subusat">;

def QC_WRAP : QCIRVInstRR<0b10010, GPR, "qc.wrap">;
def QC_WRAPI : RVInstI<0b000, OPC_CUSTOM_0, (outs GPRNoX0:$rd),
(ins GPRNoX0:$rs1, uimm11:$imm11), "qc.wrapi",
"$rd, $rs1, $imm11"> {
bits<11> imm11;

let imm12 = {0b0, imm11};
}

def QC_NORM : QCIRVInstR<0b0111, "qc.norm">;
def QC_NORMU : QCIRVInstR<0b1000, "qc.normu">;
def QC_NORMEU : QCIRVInstR<0b1001, "qc.normeu">;
} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
} // Predicates = [HasVendorXqcia, IsRV32], DecoderNamespace = "Xqcia"
3 changes: 2 additions & 1 deletion llvm/lib/TargetParser/RISCVISAInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,8 @@ Error RISCVISAInfo::checkDependency() {
bool HasVector = Exts.count("zve32x") != 0;
bool HasZvl = MinVLen != 0;
bool HasZcmt = Exts.count("zcmt") != 0;
static constexpr StringLiteral XqciExts[] = {{"xqcicsr"}, {"xqcisls"}};
static constexpr StringLiteral XqciExts[] = {
{"xqcia"}, {"xqcicsr"}, {"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 @@ -81,6 +81,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+xtheadmempair %s -o - | FileCheck --check-prefix=RV32XTHEADMEMPAIR %s
; RUN: llc -mtriple=riscv32 -mattr=+xtheadsync %s -o - | FileCheck --check-prefix=RV32XTHEADSYNC %s
; RUN: llc -mtriple=riscv32 -mattr=+xwchc %s -o - | FileCheck --check-prefix=RV32XWCHC %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcia %s -o - | FileCheck --check-prefix=RV32XQCIA %s
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicsr %s -o - | FileCheck --check-prefix=RV32XQCICSR %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 @@ -387,6 +388,7 @@
; RV32XTHEADMEMPAIR: .attribute 5, "rv32i2p1_xtheadmempair1p0"
; RV32XTHEADSYNC: .attribute 5, "rv32i2p1_xtheadsync1p0"
; RV32XWCHC: .attribute 5, "rv32i2p1_xwchc2p2"
; RV32XQCIA: .attribute 5, "rv32i2p1_xqcia0p2"
; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
; RV32ZAAMO: .attribute 5, "rv32i2p1_zaamo1p0"
Expand Down
201 changes: 201 additions & 0 deletions llvm/test/MC/RISCV/xqcia-invalid.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
# Xqcia - Qualcomm uC Arithmetic Extension
# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcia < %s 2>&1 \
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-PLUS %s
# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcia < %s 2>&1 \
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-MINUS %s

# CHECK: :[[@LINE+1]]:20: error: invalid operand for instruction
qc.slasat x10, x3, 17

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.slasat x10, x3

# CHECK: :[[@LINE+1]]:11: error: invalid operand for instruction
qc.slasat x0, x3, x17

# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
qc.slasat x10, x0, x17

# CHECK: :[[@LINE+1]]:20: error: invalid operand for instruction
qc.slasat x10, x3, x0

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
qc.slasat x10, x3, x17


# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
qc.sllsat x23, x25, 27

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.sllsat x23, x25

# CHECK: :[[@LINE+1]]:11: error: invalid operand for instruction
qc.sllsat x0, x25, x27

# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
qc.sllsat x23, x0, x27

# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
qc.sllsat x23, x25, x0

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
qc.sllsat x23, x25, x27


# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
qc.addsat x17, x14, 7

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.addsat x17, x14

# CHECK: :[[@LINE+1]]:11: error: invalid operand for instruction
qc.addsat x0, x14, x7

# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
qc.addsat x17, x0, x7

# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
qc.addsat x17, x14, x0

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
qc.addsat x17, x14, x7


# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
qc.addusat x8, x18, 28

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.addusat x8, x18

# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
qc.addusat x0, x18, x28

# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
qc.addusat x8, x0, x28

# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
qc.addusat x8, x18, x0

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
qc.addusat x8, x18, x28


# CHECK: :[[@LINE+1]]:20: error: invalid operand for instruction
qc.subsat x22, x2, 12

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.subsat x22, x2

# CHECK: :[[@LINE+1]]:11: error: invalid operand for instruction
qc.subsat x0, x2, x12

# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
qc.subsat x22, x0, x12

# CHECK: :[[@LINE+1]]:20: error: invalid operand for instruction
qc.subsat x22, x2, x0

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
qc.subsat x22, x2, x12


# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
qc.subusat x9, x14, 17

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.subusat x9, x14

# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
qc.subusat x0, x14, x17

# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
qc.subusat x9, x0, x17

# CHECK: :[[@LINE+1]]:21: error: invalid operand for instruction
qc.subusat x9, x14, x0

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
qc.subusat x9, x14, x17


# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
qc.wrap x3, x30, 23

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.wrap x3, x30

# CHECK: :[[@LINE+1]]:9: error: invalid operand for instruction
qc.wrap x0, x30, x23

# CHECK: :[[@LINE+1]]:18: error: invalid operand for instruction
qc.wrap x3, x30, x0

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
qc.wrap x3, x30, x23


# CHECK: :[[@LINE+1]]:10: error: invalid operand for instruction
qc.wrapi x0, 12, 2047

# CHECK: :[[@LINE+1]]:10: error: invalid operand for instruction
qc.wrapi x0, x12, 2047

# CHECK: :[[@LINE+1]]:14: error: invalid operand for instruction
qc.wrapi x6, x0, 2047

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.wrapi x6, x12

# CHECK-PLUS: :[[@LINE+1]]:19: error: immediate must be an integer in the range [0, 2047]
qc.wrapi x6, x12, 2048

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
qc.wrapi x6, x12, 2047


# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
qc.norm x3, 7

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.norm x3

# CHECK: :[[@LINE+1]]:9: error: invalid operand for instruction
qc.norm x0, x7

# CHECK: :[[@LINE+1]]:13: error: invalid operand for instruction
qc.norm x3, x0

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
qc.norm x3, x7


# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
qc.normu x11, 17

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.normu x11

# CHECK: :[[@LINE+1]]:10: error: invalid operand for instruction
qc.normu x0, x17

# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
qc.normu x11, x0

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
qc.normu x11, x17


# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
qc.normeu x26, 31

# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
qc.normeu x26

# CHECK: :[[@LINE+1]]:11: error: invalid operand for instruction
qc.normeu x0, x31

# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
qc.normeu x26, x0

# CHECK-MINUS: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcia' (Qualcomm uC Arithmetic Extension)
qc.normeu x26, x31
Loading

0 comments on commit 6881c6d

Please sign in to comment.