Skip to content

[RISCV] Add Qualcomm uC Xqcilia (Large Immediate Arithmetic) extension #124706

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 8 commits into from
Feb 24, 2025

Conversation

hchandel
Copy link
Contributor

This extension adds eight 48 bit large arithmetic instructions.

The current spec can be found at:
https://github.com/quic/riscv-unified-db/releases/latest

This patch adds assembler only support.

Harsh Chandel and others added 2 commits January 24, 2025 16:43
This extension adds eight 48 bit large arithmetic instructions.

The current spec can be found at:
https://github.com/quic/riscv-unified-db/releases/latest

This patch adds assembler only support.

Change-Id: Id7712ee41128ba11a3752cb4c2450a9c7be8e7d7
Change-Id: I49b82a0333ab216d7b150027d973f11d4cbdf35c
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' mc Machine (object) code labels Jan 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 28, 2025

@llvm/pr-subscribers-clang-driver
@llvm/pr-subscribers-mc

@llvm/pr-subscribers-clang

Author: quic_hchandel (hchandel)

Changes

This extension adds eight 48 bit large arithmetic instructions.

The current spec can be found at:
https://github.com/quic/riscv-unified-db/releases/latest

This patch adds assembler only support.


Patch is 20.12 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/124706.diff

13 Files Affected:

  • (modified) clang/test/Driver/print-supported-extensions-riscv.c (+1)
  • (modified) llvm/docs/RISCVUsage.rst (+3)
  • (modified) llvm/docs/ReleaseNotes.md (+2)
  • (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+18)
  • (modified) llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp (+3-1)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+1)
  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+8)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+48)
  • (modified) llvm/lib/TargetParser/RISCVISAInfo.cpp (+2-1)
  • (modified) llvm/test/CodeGen/RISCV/attributes.ll (+2)
  • (added) llvm/test/MC/RISCV/xqcilia-invalid.s (+109)
  • (added) llvm/test/MC/RISCV/xqcilia-valid.s (+82)
  • (modified) llvm/unittests/TargetParser/RISCVISAInfoTest.cpp (+2-1)
diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c
index ae3a1c29df3976..7dbece2a148c77 100644
--- a/clang/test/Driver/print-supported-extensions-riscv.c
+++ b/clang/test/Driver/print-supported-extensions-riscv.c
@@ -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:     xqcilia              0.2       'Xqcilia' (Qualcomm uC Large Immediate Arithmetic 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)
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index c83fd1db0ba9b5..dc367131f13e71 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -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-Xqcilia``
+  LLVM implements `version 0.2 of the Qualcomm uC Large Immediate 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-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.
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 05d902641d0933..d8a222920ee29d 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -296,6 +296,8 @@ Changes to the RISC-V Backend
   extension.
 * Adds experimental assembler support for the Qualcomm uC 'Xqcilo` (Large Offset Load Store)
   extension.
+* Adds experimental assembler support for the Qualcomm uC 'Xqcilia` (Large Immediate Arithmetic)
+  extension.
 * Added ``Sdext`` and ``Sdtrig`` extensions.
 
 Changes to the WebAssembly Backend
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 227a6361730da6..19afda3219e77e 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -1046,6 +1046,20 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            isInt<26>(fixImmediateForRV32(Imm, isRV64Imm()));
   }
 
+  bool isImm32() const {
+    int64_t Imm;
+    RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+    if (!isImm())
+      return false;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    bool IsValid;
+    if (!IsConstantImm)
+      IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
+    else
+      IsValid = isInt<32>(Imm) || isUInt<32>(Imm);
+    return IsValid && VK == RISCVMCExpr::VK_RISCV_None;
+  }
+
   /// 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
@@ -1689,6 +1703,10 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidSImm26:
     return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 25),
                                       (1 << 25) - 1);
+  case Match_InvalidImm32:
+    return generateImmOutOfRangeError(Operands, ErrorInfo,
+                                      std::numeric_limits<int32_t>::min(),
+                                      std::numeric_limits<uint32_t>::max());
   case Match_InvalidRlist: {
     SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
     return Error(
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index a0b87f7c7ff257..a7db6a13a3d63c 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -766,7 +766,9 @@ DecodeStatus RISCVDisassembler::getInstruction48(MCInst &MI, uint64_t &Size,
   TRY_TO_DECODE_FEATURE(
       RISCV::FeatureVendorXqcilo, DecoderTableXqcilo48,
       "Qualcomm uC Large Offset Load Store custom 48bit opcode table");
-
+  TRY_TO_DECODE_FEATURE(
+      RISCV::FeatureVendorXqcilia, DecoderTableXqcilia48,
+      "Qualcomm uC Large Immediate Arithmetic custom 48bit opcode table");
   return MCDisassembler::Fail;
 }
 
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index e9abc90d69a131..6ea038ce4110e0 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -333,6 +333,7 @@ enum OperandType : unsigned {
   OPERAND_SIMM12,
   OPERAND_SIMM12_LSB00000,
   OPERAND_SIMM26,
+  OPERAND_IMM32,
   OPERAND_CLUI_IMM,
   OPERAND_VTYPEI10,
   OPERAND_VTYPEI11,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 4119dd77804f1a..542d4935a90a42 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1310,6 +1310,14 @@ def HasVendorXqciint
       AssemblerPredicate<(all_of FeatureVendorXqciint),
                          "'Xqciint' (Qualcomm uC Interrupts Extension)">;
 
+def FeatureVendorXqcilia
+    : RISCVExperimentalExtension<0, 2, "Qualcomm uC Large Immediate Arithmetic Extension",
+                                 [FeatureStdExtZca]>;
+def HasVendorXqcilia
+    : Predicate<"Subtarget->hasVendorXqcilia()">,
+      AssemblerPredicate<(all_of FeatureVendorXqcilia),
+                         "'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)">;
+
 def FeatureVendorXqcilo
     : RISCVExperimentalExtension<0, 2, "Qualcomm uC Large Offset Load Store Extension",
                                  [FeatureStdExtZca]>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index f746cce8c9a0f1..f014695a18bdd0 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -34,6 +34,21 @@ def uimm11 : RISCVUImmLeafOp<11>;
 
 def simm26 : RISCVSImmLeafOp<26>;
 
+// 32-bit Immediate, used by RV32 Instructions in 32-bit operations, so no
+// sign-/zero-extension. This is represented internally as a signed 32-bit value.
+def imm32 : RISCVOp<XLenVT> {
+  let ParserMatchClass = ImmAsmOperand<"", 32, "">;
+  let EncoderMethod = "getImmOpValue";
+  let DecoderMethod = "decodeSImmOperand<32>";
+  let OperandType = "OPERAND_IMM32";
+  let MCOperandPredicate = [{
+    int64_t Imm;
+    if (MCOp.evaluateAsConstantImm(Imm))
+      return (isInt<32>(Imm) || isUint<32>(Imm));
+    return MCOp.isBareSymbolRef();
+  }];
+}
+
 //===----------------------------------------------------------------------===//
 // Instruction Formats
 //===----------------------------------------------------------------------===//
@@ -245,6 +260,25 @@ class QCIRVInstESStore<bits<3> funct3, bits<2> funct2, string opcodestr>
                       (ins GPRMem:$rs2, GPR:$rs1, simm26:$imm),
                       opcodestr, "$rs2, ${imm}(${rs1})">;
 
+class QCIRVInstEAI<bits<3> funct3, bits<1> funct1, string opcodestr>
+    : RVInst48<(outs GPRNoX0:$rd_wb), (ins GPRNoX0:$rd, imm32:$imm),
+                opcodestr, "$rd, $imm", [], InstFormatOther> {
+  bits<5> rd;
+  bits<32> imm;
+
+  let Constraints = "$rd = $rd_wb";
+  let Inst{47-16} = imm{31-0};
+  let Inst{15} = funct1;
+  let Inst{14-12} = funct3;
+  let Inst{11-7} = rd;
+  let Inst{6-0} = 0b0011111;
+}
+
+class QCIRVInstEI<bits<3> funct3, bits<2> funct2, string opcodestr>
+    : QCIRVInstEIBase<funct3, funct2, (outs GPRNoX0:$rd),
+                      (ins GPRNoX0:$rs1, simm26:$imm), opcodestr,
+                      "$rd, $rs1, $imm">;
+
 //===----------------------------------------------------------------------===//
 // Instructions
 //===----------------------------------------------------------------------===//
@@ -435,6 +469,20 @@ let Predicates = [HasVendorXqcilo, IsRV32], DecoderNamespace = "Xqcilo" in {
   def QC_E_SW    : QCIRVInstESStore<0b110, 0b11, "qc.e.sw">;
 } // Predicates = [HasVendorXqcilo, IsRV32], DecoderNamespace = "Xqcilo"
 
+let Predicates = [HasVendorXqcilia, IsRV32], DecoderNamespace = "Xqcilia" in {
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
+  def QC_E_XORAI : QCIRVInstEAI<0b001, 0b0, "qc.e.xorai">;
+  def QC_E_ORAI  : QCIRVInstEAI<0b001, 0b1, "qc.e.orai" >;
+  def QC_E_ADDAI : QCIRVInstEAI<0b010, 0b0, "qc.e.addai">;
+  def QC_E_ANDAI : QCIRVInstEAI<0b010, 0b1, "qc.e.andai">;
+
+  def QC_E_XORI  : QCIRVInstEI<0b011, 0b00, "qc.e.xori">;
+  def QC_E_ORI   : QCIRVInstEI<0b011, 0b01, "qc.e.ori" >;
+  def QC_E_ADDI  : QCIRVInstEI<0b011, 0b10, "qc.e.addi">;
+  def QC_E_ANDI  : QCIRVInstEI<0b011, 0b11, "qc.e.andi">;
+} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
+} // Predicates = [HasVendorXqcilia, IsRV32], DecoderNamespace = "Xqcilia"
+
 //===----------------------------------------------------------------------===//
 // Aliases
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index c78d60fd86b3fc..3ded9ce64ad598 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -743,7 +743,8 @@ Error RISCVISAInfo::checkDependency() {
   bool HasZcmt = Exts.count("zcmt") != 0;
   static constexpr StringLiteral XqciExts[] = {
       {"xqcia"},   {"xqciac"},  {"xqcicli"}, {"xqcicm"},  {"xqcics"},
-      {"xqcicsr"}, {"xqciint"}, {"xqcilo"},  {"xqcilsm"}, {"xqcisls"}};
+      {"xqcicsr"}, {"xqciint"}, {"xqcilia"}, {"xqcilo"},  {"xqcilsm"},
+      {"xqcisls"}};
 
   if (HasI && HasE)
     return getIncompatibleError("i", "e");
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index caed0bdfb04984..b4b08939a7468f 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -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-xqcilia %s -o - | FileCheck --check-prefix=RV32XQCILIA %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
@@ -404,6 +405,7 @@
 ; RV32XQCICS: .attribute 5, "rv32i2p1_xqcics0p2"
 ; RV32XQCICSR: .attribute 5, "rv32i2p1_xqcicsr0p2"
 ; RV32XQCIINT: .attribute 5, "rv32i2p1_zca1p0_xqciint0p2"
+; RV32XQCILIA: .attribute 5, "rv32i2p1_zca1p0_xqcilia0p2"
 ; RV32XQCILO: .attribute 5, "rv32i2p1_zca1p0_xqcilo0p2"
 ; RV32XQCILSM: .attribute 5, "rv32i2p1_xqcilsm0p2"
 ; RV32XQCISLS: .attribute 5, "rv32i2p1_xqcisls0p2"
diff --git a/llvm/test/MC/RISCV/xqcilia-invalid.s b/llvm/test/MC/RISCV/xqcilia-invalid.s
new file mode 100644
index 00000000000000..e39efd9de73353
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcilia-invalid.s
@@ -0,0 +1,109 @@
+# Xqcilia - Qualcomm uC Large Immediate Arithmetic extension
+# RUN: not llvm-mc -triple riscv32 -mattr=+experimental-xqcilia < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-IMM %s
+# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcilia < %s 2>&1 \
+# RUN:     | FileCheck -check-prefixes=CHECK,CHECK-EXT %s
+
+# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.e.addai 9, 33554432
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.addai x9
+
+# CHECK-IMM: :[[@LINE+1]]:16: error: immediate must be an integer in the range [-2147483648, 4294967295]
+qc.e.addai x9, 20485546494
+
+# CHECK-EXT: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
+qc.e.addai x9, 33554432
+
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.e.addi x10, 9, 554432
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.addi x10, x9
+
+# CHECK-IMM: :[[@LINE+1]]:20: error: immediate must be an integer in the range [-33554432, 33554431]
+qc.e.addi x10, x9, 335544312
+
+# CHECK-EXT: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
+qc.e.addi x10, x9, 554432
+
+
+# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.e.andai 9, 33554432
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.andai x9
+
+# CHECK-IMM: :[[@LINE+1]]:16: error: immediate must be an integer in the range [-2147483648, 4294967295]
+qc.e.andai x9, 20494437494
+
+# CHECK-EXT: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
+qc.e.andai x9, 33554432
+
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.e.andi x10, 9, 554432
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.andi x10, x9
+
+# CHECK-IMM: :[[@LINE+1]]:20: error: immediate must be an integer in the range [-33554432, 33554431]
+qc.e.andi x10, x9, 335544312
+
+# CHECK-EXT: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
+qc.e.andi x10, x9, 554432
+
+
+# CHECK: :[[@LINE+1]]:11: error: invalid operand for instruction
+qc.e.orai 9, 33554432
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.orai x9
+
+# CHECK-IMM: :[[@LINE+1]]:15: error: immediate must be an integer in the range [-2147483648, 4294967295]
+qc.e.orai x9, 20494437494
+
+# CHECK-EXT: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
+qc.e.orai x9, 33554432
+
+
+# CHECK: :[[@LINE+1]]:15: error: invalid operand for instruction
+qc.e.ori x10, 9, 554432
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.ori x10, x9
+
+# CHECK-IMM: :[[@LINE+1]]:19: error: immediate must be an integer in the range [-33554432, 33554431]
+qc.e.ori x10, x9, 335544312
+
+# CHECK-EXT: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
+qc.e.ori x10, x9, 554432
+
+
+
+# CHECK: :[[@LINE+1]]:12: error: invalid operand for instruction
+qc.e.xorai 9, 33554432
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.xorai x9
+
+# CHECK-IMM: :[[@LINE+1]]:16: error: immediate must be an integer in the range [-2147483648, 4294967295]
+qc.e.xorai x9, 20494437494
+
+# CHECK-EXT: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
+qc.e.xorai x9, 33554432
+
+
+# CHECK: :[[@LINE+1]]:16: error: invalid operand for instruction
+qc.e.xori x10, 9, 554432
+
+# CHECK: :[[@LINE+1]]:1: error: too few operands for instruction
+qc.e.xori x10, x9
+
+# CHECK-IMM: :[[@LINE+1]]:20: error: immediate must be an integer in the range [-33554432, 33554431]
+qc.e.xori x10, x9, 335544312
+
+# CHECK-EXT: :[[@LINE+1]]:1: error: instruction requires the following: 'Xqcilia' (Qualcomm uC Large Immediate Arithmetic Extension)
+qc.e.xori x10, x9, 554432
diff --git a/llvm/test/MC/RISCV/xqcilia-valid.s b/llvm/test/MC/RISCV/xqcilia-valid.s
new file mode 100644
index 00000000000000..49727d5d362397
--- /dev/null
+++ b/llvm/test/MC/RISCV/xqcilia-valid.s
@@ -0,0 +1,82 @@
+# Xqcilia - Qualcomm uC Large Immediate Arithmetic extension
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcilia -riscv-no-aliases -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcilia < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcilia -M no-aliases --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+experimental-xqcilia -show-encoding \
+# RUN:     | FileCheck -check-prefixes=CHECK-ENC,CHECK-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+experimental-xqcilia < %s \
+# RUN:     | llvm-objdump --mattr=+experimental-xqcilia --no-print-imm-hex -d - \
+# RUN:     | FileCheck -check-prefix=CHECK-INST %s
+
+# CHECK-INST: qc.e.addai      s1, -1
+# CHECK-ENC: encoding: [0x9f,0x24,0xff,0xff,0xff,0xff]
+qc.e.addai x9, 4294967295
+
+# CHECK-INST: qc.e.addai      s1, -2147483648
+# CHECK-ENC: encoding: [0x9f,0x24,0x00,0x00,0x00,0x80]
+qc.e.addai x9, -2147483648
+
+
+# CHECK-INST: qc.e.addi       a0, s1, -33554432
+# CHECK-ENC: encoding: [0x1f,0xb5,0x04,0x80,0x00,0x80]
+qc.e.addi x10, x9, -33554432
+
+# CHECK-INST: qc.e.addi       a0, s1, 33554431
+# CHECK-ENC: encoding: [0x1f,0xb5,0xf4,0xbf,0xff,0x7f]
+qc.e.addi x10, x9, 33554431
+
+
+# CHECK-INST: qc.e.andai      s1, -1
+# CHECK-ENC: encoding: [0x9f,0xa4,0xff,0xff,0xff,0xff]
+qc.e.andai x9, 4294967295
+
+# CHECK-INST: qc.e.andai      s1, -2147483648
+# CHECK-ENC: encoding: [0x9f,0xa4,0x00,0x00,0x00,0x80]
+qc.e.andai x9, -2147483648
+
+
+# CHECK-INST: qc.e.andi       a0, s1, -33554432
+# CHECK-ENC: encoding: [0x1f,0xb5,0x04,0xc0,0x00,0x80]
+qc.e.andi x10, x9, -33554432
+
+# CHECK-INST: qc.e.andi       a0, s1, 33554431
+# CHECK-ENC: encoding: [0x1f,0xb5,0xf4,0xff,0xff,0x7f]
+qc.e.andi x10, x9, 33554431
+
+
+# CHECK-INST: qc.e.orai       s1, -1
+# CHECK-ENC: encoding: [0x9f,0x94,0xff,0xff,0xff,0xff]
+qc.e.orai x9, 4294967295
+
+# CHECK-INST: qc.e.orai       s1, -2147483648
+# CHECK-ENC: encoding: [0x9f,0x94,0x00,0x00,0x00,0x80]
+qc.e.orai x9, -2147483648
+
+
+# CHECK-INST: qc.e.ori        a0, s1, -33554432
+# CHECK-ENC: encoding: [0x1f,0xb5,0x04,0x40,0x00,0x80]
+qc.e.ori x10, x9, -33554432
+
+# CHECK-INST: qc.e.ori        a0, s1, 33554431
+# CHECK-ENC: encoding: [0x1f,0xb5,0xf4,0x7f,0xff,0x7f]
+qc.e.ori x10, x9, 33554431
+
+
+# CHECK-INST: qc.e.xorai      s1, -1
+# CHECK-ENC: encoding: [0x9f,0x14,0xff,0xff,0xff,0xff]
+qc.e.xorai x9, 4294967295
+
+# CHECK-INST: qc.e.xorai      s1, -2147483648
+# CHECK-ENC: encoding: [0x9f,0x14,0x00,0x00,0x00,0x80]
+qc.e.xorai x9, -2147483648
+
+
+# CHECK-INST: qc.e.xori       a0, s1, -33554432
+# CHECK-ENC: encoding: [0x1f,0xb5,0x04,0x00,0x00,0x80]
+qc.e.xori x10, x9, -33554432
+
+# CHECK-INST: qc.e.xori       a0, s1, 33554431
+# CHECK-ENC: encoding: [0x1f,0xb5,0xf4,0x3f,0xff,0x7f]
+qc.e.xori x10, x9, 33554431
diff --git a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
index 14a60c1857f24f..81d76f5aac37e7 100644
--- a/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVISAInfoTest.cpp
@@ -657,7 +657,7 @@ TEST(ParseArchString, RejectsConflictingExtensions) {
        {"rv64i_xqcisls0p2", "rv64i_xqcia0p2", "rv64i_xqciac0p2",
         "rv64i_xqcicsr0p2", "rv64i_xqcilsm0p2", "rv64i_xqcicm0p2",
         "rv64i_xqcics0p2", "rv64i_xqcicli0p2", "rv64i_xqciint0p2",
-        "rv64i_xqcilo0p2"}) {
+        "rv64i_xqcilo0p2", "rv64i_xqcilia0p2"}) {
     EXPECT_THAT(
         toString(RISCVISAInfo::parseArchString(Input, true).takeError()),
         ::testing::EndsWith(" is only supported for 'rv32'"));
@@ -1123,6 +1123,7 @@ Experimental extensions
     xqcics               0.2
     xqcicsr              0.2
     xqciint              0.2
+...
[truncated]

Copy link

github-actions bot commented Jan 28, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Change-Id: Ifc27c895f1542261efd76b0a3f4f95563ad16b77
if (!IsConstantImm)
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
else
IsValid = isInt<32>(Imm) || isUInt<32>(Imm);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this equivalent to isInt<32>(fixImmediateForRV32(Imm, isRV64Imm())) like we do for other immediates?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this is equivalent, and a neater way to express this. I wrote it this way because i wasn't sure.

Copy link
Member

@lenary lenary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comments Craig!

if (!IsConstantImm)
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK);
else
IsValid = isInt<32>(Imm) || isUInt<32>(Imm);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this is equivalent, and a neater way to express this. I wrote it this way because i wasn't sure.

Change-Id: I82065f41a8236f398543d99e490a8f9b8c492aa5
@hchandel
Copy link
Contributor Author

Thanks @topperc and @lenary. Addressed the comments.

# RUN: not llvm-mc -triple riscv32 -mattr=-experimental-xqcilia < %s 2>&1 \
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-MINUS,CHECK-EXT %s

# CHECK-PLUS: :[[@LINE+2]]:12: error: register must be a GPR excluding zero (x0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lenary I just noticed this error isn't worded well when the user didn't provide a register. Maybe we "operand must a GPR register excluding zero (x0)" would be better?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one of the reasons I intend to work on the DiagnosticPredicate use in RISC-V, but I haven't yet got back to it.

AArch64, where they use diagnosticpredicates, they will give you guidance if you're a register, or say "invalid operand for instruction" if you give an immediate where only a register is allowed.

My work on this has slowed as we're doing our own release work, but I hope to get back to it.

Change-Id: I1138c145571be288f566598214ebe183e1dfb99c
Change-Id: Id8c71e493c60e85bf5c7013f15984ffeadf1951b
Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Change-Id: Icdbaccd7e3e3665f6498341e764531d94a6a1c0d
Change-Id: Iede8b12c1a8a59058969d8431bb7f66ca91c770e
Copy link
Contributor

@svs-quic svs-quic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@lenary lenary merged commit 538b898 into llvm:main Feb 24, 2025
12 checks passed
@hchandel hchandel deleted the xqcilia branch February 25, 2025 05:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants