]> granicus.if.org Git - llvm/commitdiff
[RISCV] Add basic RV32E definitions and MC layer support
authorAlex Bradbury <asb@lowrisc.org>
Fri, 22 Mar 2019 11:21:40 +0000 (11:21 +0000)
committerAlex Bradbury <asb@lowrisc.org>
Fri, 22 Mar 2019 11:21:40 +0000 (11:21 +0000)
The RISC-V ISA defines RV32E as an alternative "base" instruction set
encoding, that differs from RV32I by having only 16 rather than 32 registers.
This patch adds basic definitions for RV32E as well as MC layer support
(assembling, disassembling) and tests. The only supported ABI on RV32E is
ILP32E.

Add a new RISCVFeatures::validate() helper to RISCVUtils which can be called
from codegen or MC layer libraries to validate the combination of TargetTriple
and FeatureBitSet. Other targets have similar checks (e.g. erroring if SPE is
enabled on PPC64 or oddspreg + o32 ABI on Mips), but they either duplicate the
checks (Mips), or fail to check for both codegen and MC codepaths (PPC).

Codegen for the ILP32E ABI support and RV32E codegen are left for a future
patch/patches.

Differential Revision: https://reviews.llvm.org/D59470

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@356744 91177308-0d34-0410-b5e6-96231b3b80d8

16 files changed:
lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
lib/Target/RISCV/RISCV.td
lib/Target/RISCV/RISCVISelLowering.cpp
lib/Target/RISCV/RISCVSubtarget.cpp
lib/Target/RISCV/RISCVSubtarget.h
lib/Target/RISCV/Utils/RISCVBaseInfo.cpp
lib/Target/RISCV/Utils/RISCVBaseInfo.h
test/CodeGen/RISCV/mattr-invalid-combination.ll [new file with mode: 0644]
test/CodeGen/RISCV/rv32e.ll [new file with mode: 0644]
test/MC/RISCV/elf-flags.s
test/MC/RISCV/mattr-invalid-combination.s [new file with mode: 0644]
test/MC/RISCV/rv32e-invalid.s [new file with mode: 0644]
test/MC/RISCV/rv32e-valid.s [new file with mode: 0644]
test/MC/RISCV/target-abi-invalid.s

index 4202d5bfe19c521cf0896c60ea8212c273953200..ae7b648460bfecef300d0b6362191efb8d6c79d1 100644 (file)
@@ -47,6 +47,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
 
   SMLoc getLoc() const { return getParser().getTok().getLoc(); }
   bool isRV64() const { return getSTI().hasFeature(RISCV::Feature64Bit); }
+  bool isRV32E() const { return getSTI().hasFeature(RISCV::FeatureRV32E); }
 
   RISCVTargetStreamer &getTargetStreamer() {
     MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
@@ -910,11 +911,15 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
 
 // Attempts to match Name as a register (either using the default name or
 // alternative ABI names), setting RegNo to the matching register. Upon
-// failure, returns true and sets RegNo to 0.
-static bool matchRegisterNameHelper(unsigned &RegNo, StringRef Name) {
+// failure, returns true and sets RegNo to 0. If IsRV32E then registers
+// x16-x31 will be rejected.
+static bool matchRegisterNameHelper(bool IsRV32E, unsigned &RegNo,
+                                    StringRef Name) {
   RegNo = MatchRegisterName(Name);
   if (RegNo == 0)
     RegNo = MatchRegisterAltName(Name);
+  if (IsRV32E && RegNo >= RISCV::X16 && RegNo <= RISCV::X31)
+    RegNo = 0;
   return RegNo == 0;
 }
 
@@ -926,7 +931,7 @@ bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
   RegNo = 0;
   StringRef Name = getLexer().getTok().getIdentifier();
 
-  if (matchRegisterNameHelper(RegNo, Name))
+  if (matchRegisterNameHelper(isRV32E(), RegNo, Name))
     return Error(StartLoc, "invalid register name");
 
   getParser().Lex(); // Eat identifier token.
@@ -954,7 +959,7 @@ OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
   case AsmToken::Identifier:
     StringRef Name = getLexer().getTok().getIdentifier();
     unsigned RegNo;
-    matchRegisterNameHelper(RegNo, Name);
+    matchRegisterNameHelper(isRV32E(), RegNo, Name);
 
     if (RegNo == 0) {
       if (HadParens)
index 26d5bca8de250f9d1a1129065a2d26c3b4ddb50f..0ec22fa80e17f8f7beaa5b63156b6f89d4895eb9 100644 (file)
@@ -69,7 +69,13 @@ static const unsigned GPRDecoderTable[] = {
 static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
                                            uint64_t Address,
                                            const void *Decoder) {
-  if (RegNo > array_lengthof(GPRDecoderTable))
+  const FeatureBitset &FeatureBits =
+      static_cast<const MCDisassembler *>(Decoder)
+          ->getSubtargetInfo()
+          .getFeatureBits();
+  bool IsRV32E = FeatureBits[RISCV::FeatureRV32E];
+
+  if (RegNo > array_lengthof(GPRDecoderTable) || (IsRV32E && RegNo > 15))
     return MCDisassembler::Fail;
 
   // We must define our own mapping from RegNo to register identifier.
index 54d58480e109d81c05d1c97eee3f6ee1f27abfd6..248ef20f927e992cb4a9f9311b93b74fa584671a 100644 (file)
@@ -36,6 +36,7 @@ public:
         TargetOptions(Options) {
     TargetABI = RISCVABI::computeTargetABI(
         STI.getTargetTriple(), STI.getFeatureBits(), Options.getABIName());
+    RISCVFeatures::validate(STI.getTargetTriple(), STI.getFeatureBits());
   }
   ~RISCVAsmBackend() override {}
 
index 3936da677a5f18532fbf77cd1abf1ce35eaebd02..b166418a622f5c37bcf6a744516aa3735c6bc3a9 100644 (file)
@@ -54,6 +54,12 @@ def IsRV32 : Predicate<"!Subtarget->is64Bit()">,
 def RV64           : HwMode<"+64bit">;
 def RV32           : HwMode<"-64bit">;
 
+def FeatureRV32E
+    : SubtargetFeature<"e", "IsRV32E", "true",
+                       "Implements RV32E (provides 16 rather than 32 GPRs)">;
+def IsRV32E : Predicate<"Subtarget->isRV32E()">,
+                        AssemblerPredicate<"FeatureRV32E">;
+
 def FeatureRelax
     : SubtargetFeature<"relax", "EnableLinkerRelax", "true",
                        "Enable Linker relaxation.">;
index 94bd948c694ce00b7e33eb8991fea1c0e8e7e598..12e07143b7beac5d90c7963fccccbdef51678fd5 100644 (file)
@@ -43,6 +43,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
                                          const RISCVSubtarget &STI)
     : TargetLowering(TM), Subtarget(STI) {
 
+  if (Subtarget.isRV32E())
+    report_fatal_error("Codegen not yet implemented for RV32E");
+
   RISCVABI::ABI ABI = Subtarget.getTargetABI();
   assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI");
 
index 0c7355cab38e9bccbe5c2f82e9923021bd0cbc29..6902ed75d8521ac420f3b79ec5671fa7f4e7dbdc 100644 (file)
@@ -39,6 +39,7 @@ RISCVSubtarget &RISCVSubtarget::initializeSubtargetDependencies(
   }
 
   TargetABI = RISCVABI::computeTargetABI(TT, getFeatureBits(), ABIName);
+  RISCVFeatures::validate(TT, getFeatureBits());
   return *this;
 }
 
index 6c10ee44fd6d6480a12016418e12d1f0631e115f..106ff49f021a650f7ebff0c1471e143d04459099 100644 (file)
@@ -36,6 +36,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
   bool HasStdExtD = false;
   bool HasStdExtC = false;
   bool HasRV64 = false;
+  bool IsRV32E = false;
   bool EnableLinkerRelax = false;
   unsigned XLen = 32;
   MVT XLenVT = MVT::i32;
@@ -80,6 +81,7 @@ public:
   bool hasStdExtD() const { return HasStdExtD; }
   bool hasStdExtC() const { return HasStdExtC; }
   bool is64Bit() const { return HasRV64; }
+  bool isRV32E() const { return IsRV32E; }
   bool enableLinkerRelax() const { return EnableLinkerRelax; }
   MVT getXLenVT() const { return XLenVT; }
   unsigned getXLen() const { return XLen; }
index bb967cb0248de06d81f7b8b11466b72b5cce5f52..bc5395768ca1545cf419bf08c9e1f0ed427237d0 100644 (file)
@@ -22,15 +22,18 @@ ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
                        .Case("lp64d", ABI_LP64D)
                        .Default(ABI_Unknown);
 
+  bool IsRV64 = TT.isArch64Bit();
+  bool IsRV32E = FeatureBits[RISCV::FeatureRV32E];
+
   if (!ABIName.empty() && TargetABI == ABI_Unknown) {
     errs()
         << "'" << ABIName
         << "' is not a recognized ABI for this target (ignoring target-abi)\n";
-  } else if (ABIName.startswith("ilp32") && TT.isArch64Bit()) {
+  } else if (ABIName.startswith("ilp32") && IsRV64) {
     errs() << "32-bit ABIs are not supported for 64-bit targets (ignoring "
               "target-abi)\n";
     TargetABI = ABI_Unknown;
-  } else if (ABIName.startswith("lp64") && !TT.isArch64Bit()) {
+  } else if (ABIName.startswith("lp64") && !IsRV64) {
     errs() << "64-bit ABIs are not supported for 32-bit targets (ignoring "
               "target-abi)\n";
     TargetABI = ABI_Unknown;
@@ -44,17 +47,34 @@ ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
               "doesn't support the D instruction set extension (ignoring "
               "target-abi)\n";
     TargetABI = ABI_Unknown;
+  } else if (IsRV32E && TargetABI != ABI_ILP32E && TargetABI != ABI_Unknown) {
+    errs()
+        << "Only the ilp32e ABI is supported for RV32E (ignoring target-abi)\n";
+    TargetABI = ABI_Unknown;
   }
 
-  // For now, default to the ilp32/lp64 if no explicit ABI is given or an
-  // invalid/unrecognised string is given. In the future, it might be worth
-  // changing this to default to ilp32f/lp64f and ilp32d/lp64d when hardware
-  // support for floating point is present.
-  if (TargetABI == ABI_Unknown) {
-    TargetABI = TT.isArch64Bit() ? ABI_LP64 : ABI_ILP32;
-  }
+  if (TargetABI != ABI_Unknown)
+    return TargetABI;
 
-  return TargetABI;
+  // For now, default to the ilp32/ilp32e/lp64 ABI if no explicit ABI is given
+  // or an invalid/unrecognised string is given. In the future, it might be
+  // worth changing this to default to ilp32f/lp64f and ilp32d/lp64d when
+  // hardware support for floating point is present.
+  if (IsRV32E)
+    return ABI_ILP32E;
+  if (IsRV64)
+    return ABI_LP64;
+  return ABI_ILP32;
 }
 } // namespace RISCVABI
+
+namespace RISCVFeatures {
+
+void validate(const Triple &TT, const FeatureBitset &FeatureBits) {
+  if (TT.isArch64Bit() && FeatureBits[RISCV::FeatureRV32E])
+    report_fatal_error("RV32E can't be enabled for an RV64 target");
+}
+
+} // namespace RISCVFeatures
+
 } // namespace llvm
index 4ace9ddbfcdcf84ae126e9717063eceac63457a3..1ccd2254f508688ff8cb8b2b5fdd8ee2ce911625 100644 (file)
@@ -172,6 +172,14 @@ ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
 
 } // namespace RISCVABI
 
+namespace RISCVFeatures {
+
+// Validates if the given combination of features are valid for the target
+// triple. Exits with report_fatal_error if not.
+void validate(const Triple &TT, const FeatureBitset &FeatureBits);
+
+} // namespace RISCVFeatures
+
 } // namespace llvm
 
 #endif
diff --git a/test/CodeGen/RISCV/mattr-invalid-combination.ll b/test/CodeGen/RISCV/mattr-invalid-combination.ll
new file mode 100644 (file)
index 0000000..cb24405
--- /dev/null
@@ -0,0 +1,4 @@
+; RUN: not llc -mtriple=riscv64 -mattr=+e < %s 2>&1 \
+; RUN:   | FileCheck -check-prefix=RV64E %s
+
+; RV64E: LLVM ERROR: RV32E can't be enabled for an RV64 target
diff --git a/test/CodeGen/RISCV/rv32e.ll b/test/CodeGen/RISCV/rv32e.ll
new file mode 100644 (file)
index 0000000..2416639
--- /dev/null
@@ -0,0 +1,7 @@
+; RUN: not llc -mtriple=riscv32 -mattr=+e < %s 2>&1 | FileCheck %s
+
+; CHECK: LLVM ERROR: Codegen not yet implemented for RV32E
+
+define void @nothing() nounwind {
+  ret void
+}
index 1d183aab33974632b594aed314970ae79c36eb90..347f11adf4acb4e5a883fc5afd6bc838af0717b2 100644 (file)
@@ -2,6 +2,9 @@
 # RUN: llvm-mc -triple=riscv64 -filetype=obj < %s | llvm-readobj -file-headers - | FileCheck -check-prefixes=CHECK-RVI %s
 # RUN: llvm-mc -triple=riscv32 -mattr=+c -filetype=obj < %s | llvm-readobj -file-headers - | FileCheck -check-prefixes=CHECK-RVIC %s
 # RUN: llvm-mc -triple=riscv64 -mattr=+c -filetype=obj < %s | llvm-readobj -file-headers - | FileCheck -check-prefixes=CHECK-RVIC %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+e -filetype=obj < %s \
+# RUN:   | llvm-readobj -file-headers - \
+# RUN:   | FileCheck -check-prefix=CHECK-RVE %s
 
 # CHECK-RVI:       Flags [ (0x0)
 # CHECK-RVI-NEXT:  ]
@@ -10,4 +13,8 @@
 # CHECK-RVIC-NEXT:    EF_RISCV_RVC (0x1)
 # CHECK-RVIC-NEXT:  ]
 
+# CHECK-RVE:        Flags [ (0x8)
+# CHECK-RVE-NEXT:     EF_RISCV_RVE (0x8)
+# CHECK-RVE-NEXT:   ]
+
 nop
diff --git a/test/MC/RISCV/mattr-invalid-combination.s b/test/MC/RISCV/mattr-invalid-combination.s
new file mode 100644 (file)
index 0000000..340a2f2
--- /dev/null
@@ -0,0 +1,4 @@
+# RUN: not llvm-mc -triple riscv64 -mattr=+e < %s 2>&1 \
+# RUN:   | FileCheck %s -check-prefix=RV64E
+
+# RV64E: LLVM ERROR: RV32E can't be enabled for an RV64 target
diff --git a/test/MC/RISCV/rv32e-invalid.s b/test/MC/RISCV/rv32e-invalid.s
new file mode 100644 (file)
index 0000000..7403499
--- /dev/null
@@ -0,0 +1,106 @@
+# RUN: not llvm-mc -triple riscv32 -mattr=+e < %s 2>&1 | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 < %s \
+# RUN:     | llvm-objdump -mattr=+e -riscv-no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefix=CHECK-DIS %s
+
+# Perform a simple sanity check that registers x16-x31 (and the equivalent
+# ABI names) are rejected for RV32E, when both assembling and disassembling.
+
+
+# CHECK-DIS: 37 18 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x16, 1
+# CHECK-DIS: b7 28 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x17, 2
+# CHECK-DIS: 37 39 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x18, 3
+# CHECK-DIS: b7 49 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x19, 4
+# CHECK-DIS: 37 5a 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x20, 5
+# CHECK-DIS: b7 6a 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x21, 6
+# CHECK-DIS: 37 7b 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x22, 7
+# CHECK-DIS: b7 8b 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x23, 8
+# CHECK-DIS: 37 9c 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x24, 9
+# CHECK-DIS: b7 ac 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x25, 10
+# CHECK-DIS: 37 bd 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x26, 11
+# CHECK-DIS: b7 cd 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x27, 12
+# CHECK-DIS: 37 de 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x28, 13
+# CHECK-DIS: b7 ee 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x29, 14
+# CHECK-DIS: 37 ff 00 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x30, 15
+# CHECK-DIS: b7 0f 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:5: error: invalid operand for instruction
+lui x31, 16
+
+# CHECK-DIS: 17 18 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc a6, 17
+# CHECK-DIS: 97 28 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc a7, 18
+# CHECK-DIS: 17 39 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc s2, 19
+# CHECK-DIS: 97 49 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc s3, 20
+# CHECK-DIS: 17 5a 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc s4, 21
+# CHECK-DIS: 97 6a 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc s5, 22
+# CHECK-DIS: 17 7b 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc s6, 23
+# CHECK-DIS: 97 8b 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc s7, 24
+# CHECK-DIS: 17 9c 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc s8, 25
+# CHECK-DIS: 97 ac 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc s9, 26
+# CHECK-DIS: 17 bd 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc s10, 27
+# CHECK-DIS: 97 cd 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc s11, 28
+# CHECK-DIS: 17 de 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc t3, 29
+# CHECK-DIS: 97 ee 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc t4, 30
+# CHECK-DIS: 17 ff 01 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc t5, 31
+# CHECK-DIS: 97 0f 02 00 <unknown>
+# CHECK: :[[@LINE+1]]:7: error: invalid operand for instruction
+auipc t6, 32
diff --git a/test/MC/RISCV/rv32e-valid.s b/test/MC/RISCV/rv32e-valid.s
new file mode 100644 (file)
index 0000000..2541976
--- /dev/null
@@ -0,0 +1,115 @@
+# RUN: llvm-mc %s -triple=riscv32 -riscv-no-aliases -mattr=+e -show-encoding \
+# RUN:     | FileCheck -check-prefix=CHECK-ASM-AND-OBJ %s
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+e < %s \
+# RUN:     | llvm-objdump -riscv-no-aliases -d -r - \
+# RUN:     | FileCheck -check-prefix=CHECK-ASM-AND-OBJ %s
+
+# This file provides a basic sanity check for RV32E, checking that the expected
+# set of registers and instructions are accepted.
+
+# CHECK-ASM-AND-OBJ: lui zero, 1
+lui x0, 1
+# CHECK-ASM-AND-OBJ: auipc ra, 2
+auipc x1, 2
+
+# CHECK-ASM-AND-OBJ: jal sp, 4
+jal x2, 4
+# CHECK-ASM-AND-OBJ: jalr gp, gp, 4
+jalr x3, x3, 4
+
+# CHECK-ASM-AND-OBJ: beq tp, t0, 8
+beq x4, x5, 8
+# CHECK-ASM-AND-OBJ: bne t1, t2, 12
+bne x6, x7, 12
+# CHECK-ASM-AND-OBJ: blt s0, s1, 16
+blt x8, x9, 16
+# CHECK-ASM-AND-OBJ: bge a0, a1, 20
+bge x10, x11, 20
+# CHECK-ASM-AND-OBJ: bgeu a2, a3, 24
+bgeu x12, x13, 24
+
+# CHECK-ASM-AND-OBJ: lb a4, 25(a5)
+lb x14, 25(x15)
+# CHECK-ASM-AND-OBJ: lh zero, 26(ra)
+lh zero, 26(ra)
+# CHECK-ASM-AND-OBJ: lw sp, 28(gp)
+lw sp, 28(gp)
+# CHECK-ASM-AND-OBJ: lbu tp, 29(t0)
+lbu tp, 29(t0)
+# CHECK-ASM-AND-OBJ: lhu t1, 30(t2)
+lhu t1, 30(t2)
+# CHECK-ASM-AND-OBJ: sb s0, 31(s1)
+sb s0, 31(s1)
+# CHECK-ASM-AND-OBJ: sh a0, 32(a1)
+sh a0, 32(a1)
+# CHECK-ASM-AND-OBJ: sw a2, 36(a3)
+sw a2, 36(a3)
+
+# CHECK-ASM-AND-OBJ: addi a4, a5, 37
+addi a4, a5, 37
+# CHECK-ASM-AND-OBJ: slti a0, a2, -20
+slti a0, a2, -20
+# CHECK-ASM-AND-OBJ: xori tp, t1, -99
+xori tp, t1, -99
+# CHECK-ASM-AND-OBJ: ori a0, a1, -2048
+ori a0, a1, -2048
+# CHECK-ASM-AND-OBJ: andi ra, sp, 2047
+andi ra, sp, 2047
+# CHECK-ASM-AND-OBJ: slli t1, t1, 31
+slli t1, t1, 31
+# CHECK-ASM-AND-OBJ: srli a0, a4, 0
+srli a0, a4, 0
+# CHECK-ASM-AND-OBJ: srai a1, sp, 15
+srai a1, sp, 15
+# CHECK-ASM-AND-OBJ: slli t0, t1, 13
+slli t0, t1, 13
+
+# CHECK-ASM-AND-OBJ: add ra, zero, zero
+add ra, zero, zero
+# CHECK-ASM-AND-OBJ: sub t0, t2, t1
+sub t0, t2, t1
+# CHECK-ASM-AND-OBJ: sll a5, a4, a3
+sll a5, a4, a3
+# CHECK-ASM-AND-OBJ: slt s0, s0, s0
+slt s0, s0, s0
+# CHECK-ASM-AND-OBJ: sltu gp, a0, a1
+sltu gp, a0, a1
+# CHECK-ASM-AND-OBJ: xor s1, s0, s1
+xor s1, s0, s1
+# CHECK-ASM-AND-OBJ: srl a0, s0, t0
+srl a0, s0, t0
+# CHECK-ASM-AND-OBJ: sra t0, a3, zero
+sra t0, a3, zero
+# CHECK-ASM-AND-OBJ: or a5, t1, ra
+or a5, t1, ra
+# CHECK-ASM-AND-OBJ: and a0, s1, a3
+and a0, s1, a3
+
+# CHECK-ASM-AND-OBJ: fence iorw, iorw
+fence iorw, iorw
+# CHECK-ASM-AND-OBJ: fence.tso
+fence.tso
+# CHECK-ASM-AND-OBJ: fence.i
+fence.i
+
+# CHECK-ASM-AND-OBJ: ecall
+ecall
+# CHECK-ASM-AND-OBJ: ebreak
+ebreak
+# CHECK-ASM-AND-OBJ: unimp
+unimp
+
+# CHECK-ASM-AND-OBJ: csrrw t0, 4095, t1
+csrrw t0, 0xfff, t1
+# CHECK-ASM-AND-OBJ: csrrs s0, cycle, zero
+csrrs s0, 0xc00, x0
+# CHECK-ASM-AND-OBJ: csrrs s0, fflags, a5
+csrrs s0, 0x001, a5
+# CHECK-ASM-AND-OBJ: csrrc sp, ustatus, ra
+csrrc sp, 0x000, ra
+# CHECK-ASM-AND-OBJ: csrrwi a5, ustatus, 0
+csrrwi a5, 0x000, 0
+# CHECK-ASM-AND-OBJ: csrrsi t2, 4095, 31
+csrrsi t2, 0xfff, 31
+# CHECK-ASM-AND-OBJ: csrrci t1, sscratch, 5
+csrrci t1, 0x140, 5
index 16ed94142586c6c580f34652da2d149bd4993e17..20e9f89153e05e3faf1b66ec1ce5b180a30ec8b7 100644 (file)
 # RUN:   | FileCheck -check-prefix=RV32IF-LP64F %s
 # RUN: llvm-mc -triple=riscv32 -mattr=+d -target-abi lp64d < %s 2>&1 \
 # RUN:   | FileCheck -check-prefix=RV32IFD-LP64D %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+e -target-abi lp64 < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32E-LP64 %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+e,+f -target-abi lp64f < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32EF-LP64F %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+e,+d -target-abi lp64f < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32EFD-LP64D %s
 
 # RV32I-LP64: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
 # RV32IF-LP64F: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
 # RV32IFD-LP64D: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
+# RV32E-LP64: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
+# RV32EF-LP64F: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
+# RV32EFD-LP64D: 64-bit ABIs are not supported for 32-bit targets (ignoring target-abi)
 
 # RUN: llvm-mc -triple=riscv32 -target-abi ilp32f < %s 2>&1 \
 # RUN:   | FileCheck -check-prefix=RV32I-ILP32F %s
 # RV64I-LP64D: Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
 # RV64IF-LP64D: Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
 
+# RUN: llvm-mc -triple=riscv32 -mattr=+e -target-abi ilp32 < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32EF-ILP32F %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+e,+f -target-abi ilp32f < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32EF-ILP32F %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+e,+d -target-abi ilp32f < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32EFD-ILP32F %s
+# RUN: llvm-mc -triple=riscv32 -mattr=+e,+d -target-abi ilp32d < %s 2>&1 \
+# RUN:   | FileCheck -check-prefix=RV32EFD-ILP32D %s
+
+# RV32E-ILP32: Only the ilp32e ABI is supported for RV32E (ignoring target-abi)
+# RV32EF-ILP32F: Only the ilp32e ABI is supported for RV32E (ignoring target-abi)
+# RV32EFD-ILP32F: Only the ilp32e ABI is supported for RV32E (ignoring target-abi)
+# RV32EFD-ILP32D: Only the ilp32e ABI is supported for RV32E (ignoring target-abi)
+
 nop