summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/RISCV
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/RISCV')
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp36
-rw-r--r--llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp25
-rw-r--r--llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp12
-rw-r--r--llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.h4
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h58
-rw-r--r--llvm/lib/Target/RISCV/RISCV.td6
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrFormats.td47
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfo.td1
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoF.td167
-rw-r--r--llvm/lib/Target/RISCV/RISCVRegisterInfo.td52
-rw-r--r--llvm/lib/Target/RISCV/RISCVSubtarget.h2
11 files changed, 397 insertions, 13 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 3f76ce3b24a..0037d8d8af4 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -185,6 +185,20 @@ public:
return true;
}
+ /// Return true if the operand is a valid floating point rounding mode.
+ bool isFRMArg() const {
+ if (!isImm())
+ return false;
+ const MCExpr *Val = getImm();
+ auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
+ if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
+ return false;
+
+ StringRef Str = SVal->getSymbol().getName();
+
+ return RISCVFPRndMode::stringToRoundingMode(Str) != RISCVFPRndMode::Invalid;
+ }
+
bool isUImm5() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
@@ -344,6 +358,22 @@ public:
}
Inst.addOperand(MCOperand::createImm(Imm));
}
+
+ // Returns the rounding mode represented by this RISCVOperand. Should only
+ // be called after checking isFRMArg.
+ RISCVFPRndMode::RoundingMode getRoundingMode() const {
+ // isFRMArg has validated the operand, meaning this cast is safe.
+ auto SE = cast<MCSymbolRefExpr>(getImm());
+ RISCVFPRndMode::RoundingMode FRM =
+ RISCVFPRndMode::stringToRoundingMode(SE->getSymbol().getName());
+ assert(FRM != RISCVFPRndMode::Invalid && "Invalid rounding mode");
+ return FRM;
+ }
+
+ void addFRMArgOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createImm(getRoundingMode()));
+ }
};
} // end anonymous namespace.
@@ -411,6 +441,12 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
ErrorLoc,
"operand must be formed of letters selected in-order from 'iorw'");
}
+ case Match_InvalidFRMArg: {
+ SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+ return Error(
+ ErrorLoc,
+ "operand must be a valid floating point rounding mode mnemonic");
+ }
}
llvm_unreachable("Unknown match type detected!");
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index 24c6c8db8a4..0f186004a4f 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -80,6 +80,31 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
return MCDisassembler::Success;
}
+static const unsigned FPR32DecoderTable[] = {
+ RISCV::F0_32, RISCV::F1_32, RISCV::F2_32, RISCV::F3_32,
+ RISCV::F4_32, RISCV::F5_32, RISCV::F6_32, RISCV::F7_32,
+ RISCV::F8_32, RISCV::F9_32, RISCV::F10_32, RISCV::F11_32,
+ RISCV::F12_32, RISCV::F13_32, RISCV::F14_32, RISCV::F15_32,
+ RISCV::F16_32, RISCV::F17_32, RISCV::F18_32, RISCV::F19_32,
+ RISCV::F20_32, RISCV::F21_32, RISCV::F22_32, RISCV::F23_32,
+ RISCV::F24_32, RISCV::F25_32, RISCV::F26_32, RISCV::F27_32,
+ RISCV::F28_32, RISCV::F29_32, RISCV::F30_32, RISCV::F31_32
+};
+
+static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > sizeof(FPR32DecoderTable))
+ return MCDisassembler::Fail;
+
+ // We must define our own mapping from RegNo to register identifier.
+ // Accessing index RegNo in the register class will work in the case that
+ // registers were added in ascending order, but not in general.
+ unsigned Reg = FPR32DecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
template <unsigned N>
static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
int64_t Address, const void *Decoder) {
diff --git a/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp
index 6bc4ea2cd0d..a396025ccc4 100644
--- a/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp
@@ -16,6 +16,7 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
@@ -24,11 +25,13 @@ using namespace llvm;
#define DEBUG_TYPE "asm-printer"
// Include the auto-generated portion of the assembly writer.
+#define PRINT_ALIAS_INSTR
#include "RISCVGenAsmWriter.inc"
void RISCVInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
StringRef Annot, const MCSubtargetInfo &STI) {
- printInstruction(MI, O);
+ if (!printAliasInstr(MI, O))
+ printInstruction(MI, O);
printAnnotation(O, Annot);
}
@@ -67,3 +70,10 @@ void RISCVInstPrinter::printFenceArg(const MCInst *MI, unsigned OpNo,
if ((FenceArg & RISCVFenceField::W) != 0)
O << 'w';
}
+
+void RISCVInstPrinter::printFRMArg(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ auto FRMArg =
+ static_cast<RISCVFPRndMode::RoundingMode>(MI->getOperand(OpNo).getImm());
+ O << RISCVFPRndMode::roundingModeToString(FRMArg);
+}
diff --git a/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.h
index 3bb4fa37f15..58f3f841015 100644
--- a/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.h
+++ b/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.h
@@ -33,9 +33,13 @@ public:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
const char *Modifier = nullptr);
void printFenceArg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
+ void printFRMArg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, raw_ostream &O);
+ bool printAliasInstr(const MCInst *MI, raw_ostream &O);
+ void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx,
+ unsigned PrintMethodIdx, raw_ostream &O);
static const char *getRegisterName(unsigned RegNo,
unsigned AltIdx = RISCV::ABIRegAltName);
};
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 9fafbb0a95a..b38f2eaa81b 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -15,6 +15,8 @@
#define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H
#include "RISCVMCTargetDesc.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
namespace llvm {
@@ -24,12 +26,13 @@ namespace RISCVII {
enum {
InstFormatPseudo = 0,
InstFormatR = 1,
- InstFormatI = 2,
- InstFormatS = 3,
- InstFormatB = 4,
- InstFormatU = 5,
- InstFormatJ = 6,
- InstFormatOther = 7,
+ InstFormatR4 = 2,
+ InstFormatI = 3,
+ InstFormatS = 4,
+ InstFormatB = 5,
+ InstFormatU = 6,
+ InstFormatJ = 7,
+ InstFormatOther = 8,
InstFormatMask = 15
};
@@ -51,6 +54,49 @@ enum FenceField {
W = 1
};
}
+
+// Describes the supported floating point rounding mode encodings.
+namespace RISCVFPRndMode {
+enum RoundingMode {
+ RNE = 0,
+ RTZ = 1,
+ RDN = 2,
+ RUP = 3,
+ RMM = 4,
+ DYN = 7,
+ Invalid
+};
+
+inline static StringRef roundingModeToString(RoundingMode RndMode) {
+ switch (RndMode) {
+ default:
+ llvm_unreachable("Unknown floating point rounding mode");
+ case RISCVFPRndMode::RNE:
+ return "rne";
+ case RISCVFPRndMode::RTZ:
+ return "rtz";
+ case RISCVFPRndMode::RDN:
+ return "rdn";
+ case RISCVFPRndMode::RUP:
+ return "rup";
+ case RISCVFPRndMode::RMM:
+ return "rmm";
+ case RISCVFPRndMode::DYN:
+ return "dyn";
+ }
+}
+
+inline static RoundingMode stringToRoundingMode(StringRef Str) {
+ return StringSwitch<RoundingMode>(Str)
+ .Case("rne", RISCVFPRndMode::RNE)
+ .Case("rtz", RISCVFPRndMode::RTZ)
+ .Case("rdn", RISCVFPRndMode::RDN)
+ .Case("rup", RISCVFPRndMode::RUP)
+ .Case("rmm", RISCVFPRndMode::RMM)
+ .Case("dyn", RISCVFPRndMode::DYN)
+ .Default(RISCVFPRndMode::Invalid);
+}
+} // namespace RISCVFPRndMode
} // namespace llvm
#endif
diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td
index 63d2b827014..2a64ed5ace9 100644
--- a/llvm/lib/Target/RISCV/RISCV.td
+++ b/llvm/lib/Target/RISCV/RISCV.td
@@ -25,6 +25,12 @@ def FeatureStdExtA
def HasStdExtA : Predicate<"Subtarget->hasStdExtA()">,
AssemblerPredicate<"FeatureStdExtA">;
+def FeatureStdExtF
+ : SubtargetFeature<"f", "HasStdExtF", "true",
+ "'F' (Single-Precision Floating-Point)">;
+def HasStdExtF : Predicate<"Subtarget->hasStdExtF()">,
+ AssemblerPredicate<"FeatureStdExtF">;
+
def Feature64Bit
: SubtargetFeature<"64bit", "HasRV64", "true", "Implements RV64">;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
index 3dca957e31f..ca368792340 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
@@ -33,12 +33,13 @@ class InstFormat<bits<4> val> {
}
def InstFormatPseudo : InstFormat<0>;
def InstFormatR : InstFormat<1>;
-def InstFormatI : InstFormat<2>;
-def InstFormatS : InstFormat<3>;
-def InstFormatB : InstFormat<4>;
-def InstFormatU : InstFormat<5>;
-def InstFormatJ : InstFormat<6>;
-def InstFormatOther : InstFormat<7>;
+def InstFormatR4 : InstFormat<2>;
+def InstFormatI : InstFormat<3>;
+def InstFormatS : InstFormat<4>;
+def InstFormatB : InstFormat<5>;
+def InstFormatU : InstFormat<6>;
+def InstFormatJ : InstFormat<7>;
+def InstFormatOther : InstFormat<8>;
// The following opcode names and match those given in Table 19.1 in the
// RISC-V User-level ISA specification ("RISC-V base opcode map").
@@ -118,6 +119,24 @@ class RVInstR<bits<7> funct7, bits<3> funct3, RISCVOpcode opcode, dag outs,
let Opcode = opcode.Value;
}
+class RVInstR4<bits<2> funct2, RISCVOpcode opcode, dag outs, dag ins,
+ string opcodestr, string argstr>
+ : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR4> {
+ bits<5> rs3;
+ bits<5> rs2;
+ bits<5> rs1;
+ bits<3> funct3;
+ bits<5> rd;
+
+ let Inst{31-27} = rs3;
+ let Inst{26-25} = funct2;
+ let Inst{24-20} = rs2;
+ let Inst{19-15} = rs1;
+ let Inst{14-12} = funct3;
+ let Inst{11-7} = rd;
+ let Opcode = opcode.Value;
+}
+
class RVInstRAtomic<bits<5> funct5, bit aq, bit rl, bits<3> funct3,
RISCVOpcode opcode, dag outs, dag ins, string opcodestr,
string argstr>
@@ -136,6 +155,22 @@ class RVInstRAtomic<bits<5> funct5, bit aq, bit rl, bits<3> funct3,
let Opcode = opcode.Value;
}
+class RVInstRFrm<bits<7> funct7, RISCVOpcode opcode, dag outs, dag ins,
+ string opcodestr, string argstr>
+ : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+ bits<5> rs2;
+ bits<5> rs1;
+ bits<3> funct3;
+ bits<5> rd;
+
+ let Inst{31-25} = funct7;
+ let Inst{24-20} = rs2;
+ let Inst{19-15} = rs1;
+ let Inst{14-12} = funct3;
+ let Inst{11-7} = rd;
+ let Opcode = opcode.Value;
+}
+
class RVInstI<bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins,
string opcodestr, string argstr>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index f0015021c16..a141bd9ffc7 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -441,3 +441,4 @@ def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
include "RISCVInstrInfoM.td"
include "RISCVInstrInfoA.td"
+include "RISCVInstrInfoF.td"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
new file mode 100644
index 00000000000..ea2d4175e79
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
@@ -0,0 +1,167 @@
+//===-- RISCVInstrInfoF.td - RISC-V 'F' instructions -------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the RISC-V instructions from the standard 'F',
+// Single-Precision Floating-Point instruction set extension.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Operand and SDNode transformation definitions.
+//===----------------------------------------------------------------------===//
+
+// Floating-point rounding mode
+
+def FRMArg : AsmOperandClass {
+ let Name = "FRMArg";
+ let RenderMethod = "addFRMArgOperands";
+ let DiagnosticType = "InvalidFRMArg";
+}
+
+def frmarg : Operand<XLenVT> {
+ let ParserMatchClass = FRMArg;
+ let PrintMethod = "printFRMArg";
+ let DecoderMethod = "decodeUImmOperand<3>";
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction class templates
+//===----------------------------------------------------------------------===//
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPFMAS_rrr_frm<RISCVOpcode opcode, string opcodestr>
+ : RVInstR4<0b00, opcode, (outs FPR32:$rd),
+ (ins FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, frmarg:$funct3),
+ opcodestr, "$rd, $rs1, $rs2, $rs3, $funct3">;
+
+class FPFMASDynFrmAlias<FPFMAS_rrr_frm Inst, string OpcodeStr>
+ : InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3",
+ (Inst FPR32:$rd, FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPALUS_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
+ : RVInstR<funct7, funct3, OPC_OP_FP, (outs FPR32:$rd),
+ (ins FPR32:$rs1, FPR32:$rs2), opcodestr, "$rd, $rs1, $rs2">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPALUS_rr_frm<bits<7> funct7, string opcodestr>
+ : RVInstRFrm<funct7, OPC_OP_FP, (outs FPR32:$rd),
+ (ins FPR32:$rs1, FPR32:$rs2, frmarg:$funct3), opcodestr,
+ "$rd, $rs1, $rs2, $funct3">;
+
+class FPALUSDynFrmAlias<FPALUS_rr_frm Inst, string OpcodeStr>
+ : InstAlias<OpcodeStr#" $rd, $rs1, $rs2",
+ (Inst FPR32:$rd, FPR32:$rs1, FPR32:$rs2, 0b111)>;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPUnaryOp_r<bits<7> funct7, bits<3> funct3, RegisterClass rdty,
+ RegisterClass rs1ty, string opcodestr>
+ : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), (ins rs1ty:$rs1),
+ opcodestr, "$rd, $rs1">;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPUnaryOp_r_frm<bits<7> funct7, RegisterClass rdty, RegisterClass rs1ty,
+ string opcodestr>
+ : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),
+ (ins rs1ty:$rs1, frmarg:$funct3), opcodestr,
+ "$rd, $rs1, $funct3">;
+
+class FPUnaryOpDynFrmAlias<FPUnaryOp_r_frm Inst, string OpcodeStr,
+ RegisterClass rdty, RegisterClass rs1ty>
+ : InstAlias<OpcodeStr#" $rd, $rs1",
+ (Inst rdty:$rd, rs1ty:$rs1, 0b111)>;
+
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+class FPCmpS_rr<bits<3> funct3, string opcodestr>
+ : RVInstR<0b1010000, funct3, OPC_OP_FP, (outs GPR:$rd),
+ (ins FPR32:$rs1, FPR32:$rs2), opcodestr, "$rd, $rs1, $rs2">;
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasStdExtF] in {
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+def FLW : RVInstI<0b010, OPC_LOAD_FP, (outs FPR32:$rd),
+ (ins GPR:$rs1, simm12:$imm12),
+ "flw", "$rd, ${imm12}(${rs1})">;
+
+// Operands for stores are in the order srcreg, base, offset rather than
+// reflecting the order these fields are specified in the instruction
+// encoding.
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
+def FSW : RVInstS<0b010, OPC_STORE_FP, (outs),
+ (ins FPR32:$rs2, GPR:$rs1, simm12:$imm12),
+ "fsw", "$rs2, ${imm12}(${rs1})">;
+
+def FMADD_S : FPFMAS_rrr_frm<OPC_MADD, "fmadd.s">;
+def : FPFMASDynFrmAlias<FMADD_S, "fmadd.s">;
+def FMSUB_S : FPFMAS_rrr_frm<OPC_MSUB, "fmsub.s">;
+def : FPFMASDynFrmAlias<FMSUB_S, "fmsub.s">;
+def FNMSUB_S : FPFMAS_rrr_frm<OPC_NMSUB, "fnmsub.s">;
+def : FPFMASDynFrmAlias<FNMSUB_S, "fnmsub.s">;
+def FNMADD_S : FPFMAS_rrr_frm<OPC_NMADD, "fnmadd.s">;
+def : FPFMASDynFrmAlias<FNMADD_S, "fnmadd.s">;
+
+def FADD_S : FPALUS_rr_frm<0b0000000, "fadd.s">;
+def : FPALUSDynFrmAlias<FADD_S, "fadd.s">;
+def FSUB_S : FPALUS_rr_frm<0b0000100, "fsub.s">;
+def : FPALUSDynFrmAlias<FSUB_S, "fsub.s">;
+def FMUL_S : FPALUS_rr_frm<0b0001000, "fmul.s">;
+def : FPALUSDynFrmAlias<FMUL_S, "fmul.s">;
+def FDIV_S : FPALUS_rr_frm<0b0001100, "fdiv.s">;
+def : FPALUSDynFrmAlias<FDIV_S, "fdiv.s">;
+
+def FSQRT_S : FPUnaryOp_r_frm<0b0101100, FPR32, FPR32, "fsqrt.s"> {
+ let rs2 = 0b00000;
+}
+def : FPUnaryOpDynFrmAlias<FSQRT_S, "fsqrt.s", FPR32, FPR32>;
+
+def FSGNJ_S : FPALUS_rr<0b0010000, 0b000, "fsgnj.s">;
+def FSGNJN_S : FPALUS_rr<0b0010000, 0b001, "fsgnjn.s">;
+def FSGNJX_S : FPALUS_rr<0b0010000, 0b010, "fsgnjx.s">;
+def FMIN_S : FPALUS_rr<0b0010100, 0b000, "fmin.s">;
+def FMAX_S : FPALUS_rr<0b0010100, 0b001, "fmax.s">;
+
+def FCVT_W_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.w.s"> {
+ let rs2 = 0b00000;
+}
+def : FPUnaryOpDynFrmAlias<FCVT_W_S, "fcvt.w.s", GPR, FPR32>;
+
+def FCVT_WU_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.wu.s"> {
+ let rs2 = 0b00001;
+}
+def : FPUnaryOpDynFrmAlias<FCVT_WU_S, "fcvt.wu.s", GPR, FPR32>;
+
+def FMV_X_W : FPUnaryOp_r<0b1110000, 0b000, GPR, FPR32, "fmv.x.w"> {
+ let rs2 = 0b00000;
+}
+
+def FEQ_S : FPCmpS_rr<0b010, "feq.s">;
+def FLT_S : FPCmpS_rr<0b001, "flt.s">;
+def FLE_S : FPCmpS_rr<0b000, "fle.s">;
+
+def FCLASS_S : FPUnaryOp_r<0b1110000, 0b001, GPR, FPR32, "fclass.s"> {
+ let rs2 = 0b00000;
+}
+
+def FCVT_S_W : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.w"> {
+ let rs2 = 0b00000;
+}
+def : FPUnaryOpDynFrmAlias<FCVT_S_W, "fcvt.s.w", FPR32, GPR>;
+
+def FCVT_S_WU : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.wu"> {
+ let rs2 = 0b00001;
+}
+def : FPUnaryOpDynFrmAlias<FCVT_S_WU, "fcvt.s.wu", FPR32, GPR>;
+
+def FMV_W_X : FPUnaryOp_r<0b1111000, 0b000, FPR32, GPR, "fmv.w.x"> {
+ let rs2 = 0b00000;
+}
+} // Predicates = [HasStdExtF]
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
index 78c036a37b9..fd1d477e638 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -16,6 +16,12 @@ class RISCVReg<bits<5> Enc, string n, list<string> alt = []> : Register<n> {
let HWEncoding{4-0} = Enc;
let AltNames = alt;
}
+
+class RISCVReg32<bits<5> Enc, string n, list<string> alt = []> : Register<n> {
+ let HWEncoding{4-0} = Enc;
+ let AltNames = alt;
+}
+
def ABIRegAltName : RegAltNameIndex;
} // Namespace = "RISCV"
@@ -72,3 +78,49 @@ def GPR : RegisterClass<"RISCV", [XLenVT], 32, (add
[RV32, RV64, DefaultMode],
[RegInfo<32,32,32>, RegInfo<64,64,64>, RegInfo<32,32,32>]>;
}
+
+// Floating point registers
+let RegAltNameIndices = [ABIRegAltName] in {
+ def F0_32 : RISCVReg32<0, "f0", ["ft0"]>, DwarfRegNum<[32]>;
+ def F1_32 : RISCVReg32<1, "f1", ["ft1"]>, DwarfRegNum<[33]>;
+ def F2_32 : RISCVReg32<2, "f2", ["ft2"]>, DwarfRegNum<[34]>;
+ def F3_32 : RISCVReg32<3, "f3", ["ft3"]>, DwarfRegNum<[35]>;
+ def F4_32 : RISCVReg32<4, "f4", ["ft4"]>, DwarfRegNum<[36]>;
+ def F5_32 : RISCVReg32<5, "f5", ["ft5"]>, DwarfRegNum<[37]>;
+ def F6_32 : RISCVReg32<6, "f6", ["ft6"]>, DwarfRegNum<[38]>;
+ def F7_32 : RISCVReg32<7, "f7", ["ft7"]>, DwarfRegNum<[39]>;
+ def F8_32 : RISCVReg32<8, "f8", ["fs0"]>, DwarfRegNum<[40]>;
+ def F9_32 : RISCVReg32<9, "f9", ["fs1"]>, DwarfRegNum<[41]>;
+ def F10_32 : RISCVReg32<10,"f10", ["fa0"]>, DwarfRegNum<[42]>;
+ def F11_32 : RISCVReg32<11,"f11", ["fa1"]>, DwarfRegNum<[43]>;
+ def F12_32 : RISCVReg32<12,"f12", ["fa2"]>, DwarfRegNum<[44]>;
+ def F13_32 : RISCVReg32<13,"f13", ["fa3"]>, DwarfRegNum<[45]>;
+ def F14_32 : RISCVReg32<14,"f14", ["fa4"]>, DwarfRegNum<[46]>;
+ def F15_32 : RISCVReg32<15,"f15", ["fa5"]>, DwarfRegNum<[47]>;
+ def F16_32 : RISCVReg32<16,"f16", ["fa6"]>, DwarfRegNum<[48]>;
+ def F17_32 : RISCVReg32<17,"f17", ["fa7"]>, DwarfRegNum<[49]>;
+ def F18_32 : RISCVReg32<18,"f18", ["fs2"]>, DwarfRegNum<[50]>;
+ def F19_32 : RISCVReg32<19,"f19", ["fs3"]>, DwarfRegNum<[51]>;
+ def F20_32 : RISCVReg32<20,"f20", ["fs4"]>, DwarfRegNum<[52]>;
+ def F21_32 : RISCVReg32<21,"f21", ["fs5"]>, DwarfRegNum<[53]>;
+ def F22_32 : RISCVReg32<22,"f22", ["fs6"]>, DwarfRegNum<[54]>;
+ def F23_32 : RISCVReg32<23,"f23", ["fs7"]>, DwarfRegNum<[55]>;
+ def F24_32 : RISCVReg32<24,"f24", ["fs8"]>, DwarfRegNum<[56]>;
+ def F25_32 : RISCVReg32<25,"f25", ["fs9"]>, DwarfRegNum<[57]>;
+ def F26_32 : RISCVReg32<26,"f26", ["fs10"]>, DwarfRegNum<[58]>;
+ def F27_32 : RISCVReg32<27,"f27", ["fs11"]>, DwarfRegNum<[59]>;
+ def F28_32 : RISCVReg32<28,"f28", ["ft8"]>, DwarfRegNum<[60]>;
+ def F29_32 : RISCVReg32<29,"f29", ["ft9"]>, DwarfRegNum<[61]>;
+ def F30_32 : RISCVReg32<30,"f30", ["ft10"]>, DwarfRegNum<[62]>;
+ def F31_32 : RISCVReg32<31,"f31", ["ft11"]>, DwarfRegNum<[63]>;
+}
+
+// The order of registers represents the preferred allocation sequence,
+// meaning caller-save regs are listed before callee-save.
+def FPR32 : RegisterClass<"RISCV", [f32], 32, (add
+ (sequence "F%u_32", 0, 7),
+ (sequence "F%u_32", 10, 17),
+ (sequence "F%u_32", 28, 31),
+ (sequence "F%u_32", 8, 9),
+ (sequence "F%u_32", 18, 27)
+)>;
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h
index 7080ce58efa..82edef65e11 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -32,6 +32,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
virtual void anchor();
bool HasStdExtM = false;
bool HasStdExtA = false;
+ bool HasStdExtF = false;
bool HasRV64 = false;
unsigned XLen = 32;
MVT XLenVT = MVT::i32;
@@ -70,6 +71,7 @@ public:
}
bool hasStdExtM() const { return HasStdExtM; }
bool hasStdExtA() const { return HasStdExtA; }
+ bool hasStdExtF() const { return HasStdExtF; }
bool is64Bit() const { return HasRV64; }
MVT getXLenVT() const { return XLenVT; }
unsigned getXLen() const { return XLen; }
OpenPOWER on IntegriCloud