Home | History | Annotate | Line # | Download | only in MCTargetDesc
      1 //===-- RISCVBaseInfo.cpp - Top level definitions for RISCV MC ------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file contains small standalone enum definitions for the RISCV target
     10 // useful for the compiler back-end and the MC libraries.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "RISCVBaseInfo.h"
     15 #include "llvm/ADT/ArrayRef.h"
     16 #include "llvm/ADT/Triple.h"
     17 #include "llvm/Support/raw_ostream.h"
     18 
     19 namespace llvm {
     20 namespace RISCVSysReg {
     21 #define GET_SysRegsList_IMPL
     22 #include "RISCVGenSearchableTables.inc"
     23 } // namespace RISCVSysReg
     24 
     25 namespace RISCVABI {
     26 ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits,
     27                      StringRef ABIName) {
     28   auto TargetABI = getTargetABI(ABIName);
     29   bool IsRV64 = TT.isArch64Bit();
     30   bool IsRV32E = FeatureBits[RISCV::FeatureRV32E];
     31 
     32   if (!ABIName.empty() && TargetABI == ABI_Unknown) {
     33     errs()
     34         << "'" << ABIName
     35         << "' is not a recognized ABI for this target (ignoring target-abi)\n";
     36   } else if (ABIName.startswith("ilp32") && IsRV64) {
     37     errs() << "32-bit ABIs are not supported for 64-bit targets (ignoring "
     38               "target-abi)\n";
     39     TargetABI = ABI_Unknown;
     40   } else if (ABIName.startswith("lp64") && !IsRV64) {
     41     errs() << "64-bit ABIs are not supported for 32-bit targets (ignoring "
     42               "target-abi)\n";
     43     TargetABI = ABI_Unknown;
     44   } else if (IsRV32E && TargetABI != ABI_ILP32E && TargetABI != ABI_Unknown) {
     45     // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser
     46     errs()
     47         << "Only the ilp32e ABI is supported for RV32E (ignoring target-abi)\n";
     48     TargetABI = ABI_Unknown;
     49   }
     50 
     51   if (TargetABI != ABI_Unknown)
     52     return TargetABI;
     53 
     54   // For now, default to the ilp32/ilp32e/lp64 ABI if no explicit ABI is given
     55   // or an invalid/unrecognised string is given. In the future, it might be
     56   // worth changing this to default to ilp32f/lp64f and ilp32d/lp64d when
     57   // hardware support for floating point is present.
     58   if (IsRV32E)
     59     return ABI_ILP32E;
     60   if (IsRV64)
     61     return ABI_LP64;
     62   return ABI_ILP32;
     63 }
     64 
     65 ABI getTargetABI(StringRef ABIName) {
     66   auto TargetABI = StringSwitch<ABI>(ABIName)
     67                        .Case("ilp32", ABI_ILP32)
     68                        .Case("ilp32f", ABI_ILP32F)
     69                        .Case("ilp32d", ABI_ILP32D)
     70                        .Case("ilp32e", ABI_ILP32E)
     71                        .Case("lp64", ABI_LP64)
     72                        .Case("lp64f", ABI_LP64F)
     73                        .Case("lp64d", ABI_LP64D)
     74                        .Default(ABI_Unknown);
     75   return TargetABI;
     76 }
     77 
     78 // To avoid the BP value clobbered by a function call, we need to choose a
     79 // callee saved register to save the value. RV32E only has X8 and X9 as callee
     80 // saved registers and X8 will be used as fp. So we choose X9 as bp.
     81 MCRegister getBPReg() { return RISCV::X9; }
     82 
     83 // Returns the register holding shadow call stack pointer.
     84 MCRegister getSCSPReg() { return RISCV::X18; }
     85 
     86 } // namespace RISCVABI
     87 
     88 namespace RISCVFeatures {
     89 
     90 void validate(const Triple &TT, const FeatureBitset &FeatureBits) {
     91   if (TT.isArch64Bit() && !FeatureBits[RISCV::Feature64Bit])
     92     report_fatal_error("RV64 target requires an RV64 CPU");
     93   if (!TT.isArch64Bit() && FeatureBits[RISCV::Feature64Bit])
     94     report_fatal_error("RV32 target requires an RV32 CPU");
     95   if (TT.isArch64Bit() && FeatureBits[RISCV::FeatureRV32E])
     96     report_fatal_error("RV32E can't be enabled for an RV64 target");
     97 }
     98 
     99 } // namespace RISCVFeatures
    100 
    101 // Encode VTYPE into the binary format used by the the VSETVLI instruction which
    102 // is used by our MC layer representation.
    103 //
    104 // Bits | Name       | Description
    105 // -----+------------+------------------------------------------------
    106 // 7    | vma        | Vector mask agnostic
    107 // 6    | vta        | Vector tail agnostic
    108 // 5:3  | vsew[2:0]  | Standard element width (SEW) setting
    109 // 2:0  | vlmul[2:0] | Vector register group multiplier (LMUL) setting
    110 unsigned RISCVVType::encodeVTYPE(RISCVII::VLMUL VLMUL, unsigned SEW,
    111                                  bool TailAgnostic, bool MaskAgnostic) {
    112   assert(isValidSEW(SEW) && "Invalid SEW");
    113   unsigned VLMULBits = static_cast<unsigned>(VLMUL);
    114   unsigned VSEWBits = Log2_32(SEW) - 3;
    115   unsigned VTypeI = (VSEWBits << 3) | (VLMULBits & 0x7);
    116   if (TailAgnostic)
    117     VTypeI |= 0x40;
    118   if (MaskAgnostic)
    119     VTypeI |= 0x80;
    120 
    121   return VTypeI;
    122 }
    123 
    124 void RISCVVType::printVType(unsigned VType, raw_ostream &OS) {
    125   RISCVII::VLMUL VLMUL = getVLMUL(VType);
    126 
    127   unsigned Sew = getSEW(VType);
    128   OS << "e" << Sew;
    129 
    130   switch (VLMUL) {
    131   case RISCVII::VLMUL::LMUL_RESERVED:
    132     llvm_unreachable("Unexpected LMUL value!");
    133   case RISCVII::VLMUL::LMUL_1:
    134   case RISCVII::VLMUL::LMUL_2:
    135   case RISCVII::VLMUL::LMUL_4:
    136   case RISCVII::VLMUL::LMUL_8: {
    137     unsigned LMul = 1 << static_cast<unsigned>(VLMUL);
    138     OS << ",m" << LMul;
    139     break;
    140   }
    141   case RISCVII::VLMUL::LMUL_F2:
    142   case RISCVII::VLMUL::LMUL_F4:
    143   case RISCVII::VLMUL::LMUL_F8: {
    144     unsigned LMul = 1 << (8 - static_cast<unsigned>(VLMUL));
    145     OS << ",mf" << LMul;
    146     break;
    147   }
    148   }
    149 
    150   if (isTailAgnostic(VType))
    151     OS << ",ta";
    152   else
    153     OS << ",tu";
    154 
    155   if (isMaskAgnostic(VType))
    156     OS << ",ma";
    157   else
    158     OS << ",mu";
    159 }
    160 
    161 } // namespace llvm
    162