[llvm] 3a49ad7 - [LoongArch] Add basic floating-point instructions definition

Weining Lu via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 20 19:06:06 PDT 2022


Author: Weining Lu
Date: 2022-04-21T10:04:20+08:00
New Revision: 3a49ad717c32c6520c911c3323f7411b05b2ade5

URL: https://github.com/llvm/llvm-project/commit/3a49ad717c32c6520c911c3323f7411b05b2ade5
DIFF: https://github.com/llvm/llvm-project/commit/3a49ad717c32c6520c911c3323f7411b05b2ade5.diff

LOG: [LoongArch] Add basic floating-point instructions definition

These instructions are added by following the `LoongArch Reference
Manual Volume 1: Basic Architecture Version 1.00`.

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

Added: 
    llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
    llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
    llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td
    llvm/test/MC/LoongArch/Basic/Float/d-arith.s
    llvm/test/MC/LoongArch/Basic/Float/d-bound-check.s
    llvm/test/MC/LoongArch/Basic/Float/d-branch.s
    llvm/test/MC/LoongArch/Basic/Float/d-comp.s
    llvm/test/MC/LoongArch/Basic/Float/d-conv.s
    llvm/test/MC/LoongArch/Basic/Float/d-invalid.s
    llvm/test/MC/LoongArch/Basic/Float/d-memory.s
    llvm/test/MC/LoongArch/Basic/Float/d-move.s
    llvm/test/MC/LoongArch/Basic/Float/f-arith.s
    llvm/test/MC/LoongArch/Basic/Float/f-bound-check.s
    llvm/test/MC/LoongArch/Basic/Float/f-branch.s
    llvm/test/MC/LoongArch/Basic/Float/f-comp.s
    llvm/test/MC/LoongArch/Basic/Float/f-conv.s
    llvm/test/MC/LoongArch/Basic/Float/f-invalid.s
    llvm/test/MC/LoongArch/Basic/Float/f-memory.s
    llvm/test/MC/LoongArch/Basic/Float/f-move.s

Modified: 
    llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
    llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp
    llvm/lib/Target/LoongArch/LoongArchInstrFormats.td
    llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
    llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td
    llvm/test/MC/LoongArch/Basic/Integer/invalid.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index f753b5317f501..8f6331d7d699f 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -14,6 +14,7 @@
 #include "llvm/MC/MCParser/MCAsmLexer.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/TargetRegistry.h"
@@ -42,6 +43,9 @@ class LoongArchAsmParser : public MCTargetAsmParser {
                                uint64_t &ErrorInfo,
                                bool MatchingInlineAsm) override;
 
+  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
+                                      unsigned Kind) override;
+
   bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
                                   int64_t Lower, int64_t Upper, Twine Msg);
 
@@ -110,6 +114,7 @@ class LoongArchOperand : public MCParsedAsmOperand {
   bool isReg() const override { return Kind == KindTy::Register; }
   bool isImm() const override { return Kind == KindTy::Immediate; }
   bool isMem() const override { return false; }
+  void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; }
 
   static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
     if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
@@ -245,9 +250,22 @@ class LoongArchOperand : public MCParsedAsmOperand {
 #define GET_MNEMONIC_SPELL_CHECKER
 #include "LoongArchGenAsmMatcher.inc"
 
+static MCRegister convertFPR32ToFPR64(MCRegister Reg) {
+  assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");
+  return Reg - LoongArch::F0 + LoongArch::F0_64;
+}
+
+// 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(MCRegister &RegNo, StringRef Name) {
   RegNo = MatchRegisterName(Name);
-
+  // The 32-bit and 64-bit FPRs have the same asm name. Check that the initial
+  // match always matches the 32-bit variant, and not the 64-bit one.
+  assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));
+  // The default FPR register class is based on the tablegen enum ordering.
+  static_assert(LoongArch::F0 < LoongArch::F0_64,
+                "FPR matching must be updated");
   if (RegNo == LoongArch::NoRegister)
     RegNo = MatchRegisterAltName(Name);
 
@@ -351,6 +369,25 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
   return false;
 }
 
+unsigned
+LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
+                                               unsigned Kind) {
+  LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);
+  if (!Op.isReg())
+    return Match_InvalidOperand;
+
+  MCRegister Reg = Op.getReg();
+  // As the parser couldn't 
diff erentiate an FPR32 from an FPR64, coerce the
+  // register from FPR32 to FPR64 if necessary.
+  if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&
+      Kind == MCK_FPR64) {
+    Op.setReg(convertFPR32ToFPR64(Reg));
+    return Match_Success;
+  }
+
+  return Match_InvalidOperand;
+}
+
 bool LoongArchAsmParser::generateImmOutOfRangeError(
     OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
     Twine Msg = "immediate must be an integer in the range") {

diff  --git a/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp b/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp
index 4564405eb7912..06f618d4f67a0 100644
--- a/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp
+++ b/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp
@@ -64,6 +64,42 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
   return MCDisassembler::Success;
 }
 
+static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,
+                                             uint64_t Address,
+                                             const MCDisassembler *Decoder) {
+  if (RegNo >= 32)
+    return MCDisassembler::Fail;
+  Inst.addOperand(MCOperand::createReg(LoongArch::F0 + RegNo));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo,
+                                             uint64_t Address,
+                                             const MCDisassembler *Decoder) {
+  if (RegNo >= 32)
+    return MCDisassembler::Fail;
+  Inst.addOperand(MCOperand::createReg(LoongArch::F0_64 + RegNo));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeCFRRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                           uint64_t Address,
+                                           const MCDisassembler *Decoder) {
+  if (RegNo >= 8)
+    return MCDisassembler::Fail;
+  Inst.addOperand(MCOperand::createReg(LoongArch::FCC0 + RegNo));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, uint64_t RegNo,
+                                            uint64_t Address,
+                                            const MCDisassembler *Decoder) {
+  if (RegNo >= 4)
+    return MCDisassembler::Fail;
+  Inst.addOperand(MCOperand::createReg(LoongArch::FCSR0 + RegNo));
+  return MCDisassembler::Success;
+}
+
 template <unsigned N, int P = 0>
 static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
                                       int64_t Address,

diff  --git a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
new file mode 100644
index 0000000000000..f47d51b857c10
--- /dev/null
+++ b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td
@@ -0,0 +1,108 @@
+//=-- LoongArchInstrInfoF.td - Single-Precision Float instr --*- tablegen -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the baisc single-precision floating-point instructions.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasBasicF] in {
+
+// Arithmetic Operation Instructions
+def FADD_S : FP_ALU_3R<0b00000001000000001, "fadd.s", FPR32>;
+def FSUB_S : FP_ALU_3R<0b00000001000000101, "fsub.s", FPR32>;
+def FMUL_S : FP_ALU_3R<0b00000001000001001, "fmul.s", FPR32>;
+def FDIV_S : FP_ALU_3R<0b00000001000001101, "fdiv.s", FPR32>;
+def FMADD_S  : FP_ALU_4R<0b000010000001, "fmadd.s", FPR32>;
+def FMSUB_S  : FP_ALU_4R<0b000010000101, "fmsub.s", FPR32>;
+def FNMADD_S : FP_ALU_4R<0b000010001001, "fnmadd.s", FPR32>;
+def FNMSUB_S : FP_ALU_4R<0b000010001101, "fnmsub.s", FPR32>;
+def FMAX_S  : FP_ALU_3R<0b00000001000010001, "fmax.s", FPR32>;
+def FMIN_S  : FP_ALU_3R<0b00000001000010101, "fmin.s", FPR32>;
+def FMAXA_S : FP_ALU_3R<0b00000001000011001, "fmaxa.s", FPR32>;
+def FMINA_S : FP_ALU_3R<0b00000001000011101, "fmina.s", FPR32>;
+def FABS_S   : FP_ALU_2R<0b0000000100010100000001, "fabs.s", FPR32>;
+def FNEG_S   : FP_ALU_2R<0b0000000100010100000101, "fneg.s", FPR32>;
+def FSQRT_S  : FP_ALU_2R<0b0000000100010100010001, "fsqrt.s", FPR32>;
+def FRECIP_S : FP_ALU_2R<0b0000000100010100010101, "frecip.s", FPR32>;
+def FRSQRT_S : FP_ALU_2R<0b0000000100010100011001, "frsqrt.s", FPR32>;
+def FSCALEB_S : FP_ALU_3R<0b00000001000100001, "fscaleb.s", FPR32>;
+def FLOGB_S   : FP_ALU_2R<0b0000000100010100001001, "flogb.s", FPR32>;
+def FCOPYSIGN_S : FP_ALU_3R<0b00000001000100101, "fcopysign.s", FPR32>;
+def FCLASS_S  : FP_ALU_2R<0b0000000100010100001101, "fclass.s", FPR32>;
+
+
+// Comparison Instructions
+def FCMP_CAF_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CAF, "fcmp.caf.s", FPR32>;
+def FCMP_CUN_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CUN, "fcmp.cun.s", FPR32>;
+def FCMP_CEQ_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CEQ, "fcmp.ceq.s", FPR32>;
+def FCMP_CUEQ_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CUEQ, "fcmp.cueq.s", FPR32>;
+def FCMP_CLT_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CLT, "fcmp.clt.s", FPR32>;
+def FCMP_CULT_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CULT, "fcmp.cult.s", FPR32>;
+def FCMP_CLE_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CLE, "fcmp.cle.s", FPR32>;
+def FCMP_CULE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CULE, "fcmp.cule.s", FPR32>;
+def FCMP_CNE_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CNE, "fcmp.cne.s", FPR32>;
+def FCMP_COR_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_COR, "fcmp.cor.s", FPR32>;
+def FCMP_CUNE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CUNE, "fcmp.cune.s", FPR32>;
+def FCMP_SAF_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SAF, "fcmp.saf.s", FPR32>;
+def FCMP_SUN_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SUN, "fcmp.sun.s", FPR32>;
+def FCMP_SEQ_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SEQ, "fcmp.seq.s", FPR32>;
+def FCMP_SUEQ_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SUEQ, "fcmp.sueq.s", FPR32>;
+def FCMP_SLT_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SLT, "fcmp.slt.s", FPR32>;
+def FCMP_SULT_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SULT, "fcmp.sult.s", FPR32>;
+def FCMP_SLE_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SLE, "fcmp.sle.s", FPR32>;
+def FCMP_SULE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SULE, "fcmp.sule.s", FPR32>;
+def FCMP_SNE_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SNE, "fcmp.sne.s", FPR32>;
+def FCMP_SOR_S  : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SOR, "fcmp.sor.s", FPR32>;
+def FCMP_SUNE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SUNE, "fcmp.sune.s", FPR32>;
+
+// Conversion Instructions
+def FFINT_S_W    : FP_CONV<0b0000000100011101000100, "ffint.s.w", FPR32, FPR32>;
+def FTINT_W_S    : FP_CONV<0b0000000100011011000001, "ftint.w.s", FPR32, FPR32>;
+def FTINTRM_W_S  : FP_CONV<0b0000000100011010000001, "ftintrm.w.s", FPR32,
+                           FPR32>;
+def FTINTRP_W_S  : FP_CONV<0b0000000100011010010001, "ftintrp.w.s", FPR32,
+                           FPR32>;
+def FTINTRZ_W_S  : FP_CONV<0b0000000100011010100001, "ftintrz.w.s", FPR32,
+                           FPR32>;
+def FTINTRNE_W_S : FP_CONV<0b0000000100011010110001, "ftintrne.w.s", FPR32,
+                           FPR32>;
+def FRINT_S      : FP_CONV<0b0000000100011110010001, "frint.s", FPR32, FPR32>;
+
+// Move Instructions
+def FSEL_S : FP_SEL<0b00001101000000, "fsel", FPR32>;
+def FMOV_S     : FP_MOV<0b0000000100010100100101, "fmov.s", FPR32, FPR32>;
+def MOVGR2FR_W : FP_MOV<0b0000000100010100101001, "movgr2fr.w", FPR32, GPR>;
+def MOVFR2GR_S : FP_MOV<0b0000000100010100101101, "movfr2gr.s", GPR, FPR32>;
+def MOVGR2FCSR : FP_MOV<0b0000000100010100110000, "movgr2fcsr", FCSR, GPR>;
+def MOVFCSR2GR : FP_MOV<0b0000000100010100110010, "movfcsr2gr", GPR, FCSR>;
+def MOVFR2CF_S : FP_MOV<0b0000000100010100110100, "movfr2cf", CFR, FPR32>;
+def MOVCF2FR_S : FP_MOV<0b0000000100010100110101, "movcf2fr", FPR32, CFR>;
+def MOVGR2CF   : FP_MOV<0b0000000100010100110110, "movgr2cf", CFR, GPR>;
+def MOVCF2GR   : FP_MOV<0b0000000100010100110111, "movcf2gr", GPR, CFR>;
+
+// Branch Instructions
+def BCEQZ : FP_BRANCH<0b01001000, "bceqz">;
+def BCNEZ : FP_BRANCH<0b01001001, "bcnez">;
+
+// Common Memory Access Instructions
+def FLD_S : FP_LOAD_2RI12<0b0010101100, "fld.s", FPR32>;
+def FST_S : FP_STORE_2RI12<0b0010101101, "fst.s", FPR32>;
+def FLDX_S : FP_LOAD_3R<0b00111000001100000, "fldx.s", FPR32>;
+def FSTX_S : FP_STORE_3R<0b00111000001110000, "fstx.s", FPR32>;
+
+// Bound Check Memory Access Instructions
+def FLDGT_S : FP_LOAD_3R<0b00111000011101000, "fldgt.s", FPR32>;
+def FLDLE_S : FP_LOAD_3R<0b00111000011101010, "fldle.s", FPR32>;
+def FSTGT_S : FP_STORE_3R<0b00111000011101100, "fstgt.s", FPR32>;
+def FSTLE_S : FP_STORE_3R<0b00111000011101110, "fstle.s", FPR32>;
+
+} // Predicates = [HasBasicF]

diff  --git a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
new file mode 100644
index 0000000000000..44e365d4a4552
--- /dev/null
+++ b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td
@@ -0,0 +1,133 @@
+//=-- LoongArchInstrInfoD.td - Double-Precision Float instr -*- tablegen -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the basic double-precision floating-point instructions.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasBasicD] in {
+
+// Arithmetic Operation Instructions
+def FADD_D : FP_ALU_3R<0b00000001000000010, "fadd.d", FPR64>;
+def FSUB_D : FP_ALU_3R<0b00000001000000110, "fsub.d", FPR64>;
+def FMUL_D : FP_ALU_3R<0b00000001000001010, "fmul.d", FPR64>;
+def FDIV_D : FP_ALU_3R<0b00000001000001110, "fdiv.d", FPR64>;
+def FMADD_D  : FP_ALU_4R<0b000010000010, "fmadd.d", FPR64>;
+def FMSUB_D  : FP_ALU_4R<0b000010000110, "fmsub.d", FPR64>;
+def FNMADD_D : FP_ALU_4R<0b000010001010, "fnmadd.d", FPR64>;
+def FNMSUB_D : FP_ALU_4R<0b000010001110, "fnmsub.d", FPR64>;
+def FMAX_D  : FP_ALU_3R<0b00000001000010010, "fmax.d", FPR64>;
+def FMIN_D  : FP_ALU_3R<0b00000001000010110, "fmin.d", FPR64>;
+def FMAXA_D : FP_ALU_3R<0b00000001000011010, "fmaxa.d", FPR64>;
+def FMINA_D : FP_ALU_3R<0b00000001000011110, "fmina.d", FPR64>;
+def FABS_D   : FP_ALU_2R<0b0000000100010100000010, "fabs.d", FPR64>;
+def FNEG_D   : FP_ALU_2R<0b0000000100010100000110, "fneg.d", FPR64>;
+def FSQRT_D  : FP_ALU_2R<0b0000000100010100010010, "fsqrt.d", FPR64>;
+def FRECIP_D : FP_ALU_2R<0b0000000100010100010110, "frecip.d", FPR64>;
+def FRSQRT_D : FP_ALU_2R<0b0000000100010100011010, "frsqrt.d", FPR64>;
+def FSCALEB_D : FP_ALU_3R<0b00000001000100010, "fscaleb.d", FPR64>;
+def FLOGB_D   : FP_ALU_2R<0b0000000100010100001010, "flogb.d", FPR64>;
+def FCOPYSIGN_D : FP_ALU_3R<0b00000001000100110, "fcopysign.d", FPR64>;
+def FCLASS_D  : FP_ALU_2R<0b0000000100010100001110, "fclass.d", FPR64>;
+
+// Comparison Instructions
+def FCMP_CAF_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CAF, "fcmp.caf.d", FPR32>;
+def FCMP_CUN_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CUN, "fcmp.cun.d", FPR32>;
+def FCMP_CEQ_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CEQ, "fcmp.ceq.d", FPR32>;
+def FCMP_CUEQ_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CUEQ, "fcmp.cueq.d", FPR32>;
+def FCMP_CLT_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CLT, "fcmp.clt.d", FPR32>;
+def FCMP_CULT_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CULT, "fcmp.cult.d", FPR32>;
+def FCMP_CLE_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CLE, "fcmp.cle.d", FPR32>;
+def FCMP_CULE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CULE, "fcmp.cule.d", FPR32>;
+def FCMP_CNE_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CNE, "fcmp.cne.d", FPR32>;
+def FCMP_COR_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_COR, "fcmp.cor.d", FPR32>;
+def FCMP_CUNE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CUNE, "fcmp.cune.d", FPR32>;
+def FCMP_SAF_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SAF, "fcmp.saf.d", FPR32>;
+def FCMP_SUN_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SUN, "fcmp.sun.d", FPR32>;
+def FCMP_SEQ_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SEQ, "fcmp.seq.d", FPR32>;
+def FCMP_SUEQ_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SUEQ, "fcmp.sueq.d", FPR32>;
+def FCMP_SLT_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SLT, "fcmp.slt.d", FPR32>;
+def FCMP_SULT_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SULT, "fcmp.sult.d", FPR32>;
+def FCMP_SLE_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SLE, "fcmp.sle.d", FPR32>;
+def FCMP_SULE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SULE, "fcmp.sule.d", FPR32>;
+def FCMP_SNE_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SNE, "fcmp.sne.d", FPR32>;
+def FCMP_SOR_D  : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SOR, "fcmp.sor.d", FPR32>;
+def FCMP_SUNE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SUNE, "fcmp.sune.d", FPR32>;
+
+// Conversion Instructions
+def FFINT_S_L : FP_CONV<0b0000000100011101000110, "ffint.s.l", FPR32, FPR64>;
+def FTINT_L_S : FP_CONV<0b0000000100011011001001, "ftint.l.s", FPR64, FPR32>;
+def FTINTRM_L_S : FP_CONV<0b0000000100011010001001, "ftintrm.l.s", FPR64,
+                          FPR32>;
+def FTINTRP_L_S : FP_CONV<0b0000000100011010011001, "ftintrp.l.s", FPR64,
+                          FPR32>;
+def FTINTRZ_L_S : FP_CONV<0b0000000100011010101001, "ftintrz.l.s", FPR64,
+                          FPR32>;
+def FTINTRNE_L_S : FP_CONV<0b0000000100011010111001, "ftintrne.l.s", FPR64,
+                           FPR32>;
+def FCVT_S_D : FP_CONV<0b0000000100011001000110, "fcvt.s.d", FPR32, FPR64>;
+def FCVT_D_S : FP_CONV<0b0000000100011001001001, "fcvt.d.s", FPR64, FPR32>;
+def FFINT_D_W : FP_CONV<0b0000000100011101001000, "ffint.d.w", FPR64, FPR32>;
+def FFINT_D_L : FP_CONV<0b0000000100011101001010, "ffint.d.l", FPR64, FPR64>;
+def FTINT_W_D : FP_CONV<0b0000000100011011000010, "ftint.w.d", FPR32, FPR64>;
+def FTINT_L_D : FP_CONV<0b0000000100011011001010, "ftint.l.d", FPR64, FPR64>;
+def FTINTRM_W_D : FP_CONV<0b0000000100011010000010, "ftintrm.w.d", FPR32,
+                          FPR64>;
+def FTINTRM_L_D : FP_CONV<0b0000000100011010001010, "ftintrm.l.d", FPR64,
+                          FPR64>;
+def FTINTRP_W_D : FP_CONV<0b0000000100011010010010, "ftintrp.w.d", FPR32,
+                          FPR64>;
+def FTINTRP_L_D : FP_CONV<0b0000000100011010011010, "ftintrp.l.d", FPR64,
+                          FPR64>;
+def FTINTRZ_W_D : FP_CONV<0b0000000100011010100010, "ftintrz.w.d", FPR32,
+                          FPR64>;
+def FTINTRZ_L_D : FP_CONV<0b0000000100011010101010, "ftintrz.l.d", FPR64,
+                          FPR64>;
+def FTINTRNE_W_D : FP_CONV<0b0000000100011010110010, "ftintrne.w.d", FPR32,
+                           FPR64>;
+def FTINTRNE_L_D : FP_CONV<0b0000000100011010111010, "ftintrne.l.d", FPR64,
+                           FPR64>;
+def FRINT_D : FP_CONV<0b0000000100011110010010, "frint.d", FPR64, FPR64>;
+
+// Move Instructions
+def FMOV_D        : FP_MOV<0b0000000100010100100110, "fmov.d", FPR64, FPR64>;
+def MOVFRH2GR_S   : FP_MOV<0b0000000100010100101111, "movfrh2gr.s", GPR, FPR64>;
+let isCodeGenOnly = 1 in {
+def MOVFR2GR_S_64 : FP_MOV<0b0000000100010100101101, "movfr2gr.s", GPR, FPR64>;
+def FSEL_D : FP_SEL<0b00001101000000, "fsel", FPR64>;
+} // isCodeGenOnly = 1
+let Constraints = "$dst = $out" in {
+def MOVGR2FRH_W : FPFmtMOV<0b0000000100010100101011, (outs FPR64:$out),
+                           (ins FPR64:$dst, GPR:$src), "movgr2frh.w",
+                           "$dst, $src">;
+} // Constraints = "$dst = $out"
+
+// Common Memory Access Instructions
+def FLD_D : FP_LOAD_2RI12<0b0010101110, "fld.d", FPR64>;
+def FST_D : FP_STORE_2RI12<0b0010101111, "fst.d", FPR64>;
+def FLDX_D : FP_LOAD_3R<0b00111000001101000, "fldx.d", FPR64>;
+def FSTX_D : FP_STORE_3R<0b00111000001111000, "fstx.d", FPR64>;
+
+// Bound Check Memory Access Instructions
+def FLDGT_D : FP_LOAD_3R<0b00111000011101001, "fldgt.d", FPR64>;
+def FLDLE_D : FP_LOAD_3R<0b00111000011101011, "fldle.d", FPR64>;
+def FSTGT_D : FP_STORE_3R<0b00111000011101101, "fstgt.d", FPR64>;
+def FSTLE_D : FP_STORE_3R<0b00111000011101111, "fstle.d", FPR64>;
+
+} // Predicates = [HasBasicD]
+
+// Instructions only available on LA64
+let Predicates = [HasBasicD, IsLA64] in {
+def MOVGR2FR_D  : FP_MOV<0b0000000100010100101010, "movgr2fr.d", FPR64, GPR>;
+def MOVFR2GR_D  : FP_MOV<0b0000000100010100101110, "movfr2gr.d", GPR, FPR64>;
+} // Predicates = [HasBasicD, IsLA64]
+

diff  --git a/llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td b/llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td
new file mode 100644
index 0000000000000..d2ba1fdfffe4b
--- /dev/null
+++ b/llvm/lib/Target/LoongArch/LoongArchFloatInstrFormats.td
@@ -0,0 +1,241 @@
+//==- LoongArchInstrFormatsF.td - LoongArch FP Instr Formats -*- tablegen -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//  Describe LoongArch floating-point instructions format
+//
+//  opcode       - operation code.
+//  fd           - destination register operand.
+//  {c/f}{j/k/a} - source register operand.
+//  immN         - immediate data operand.
+//
+//===----------------------------------------------------------------------===//
+
+// 2R-type
+// <opcode | fj | fd>
+class FPFmt2R<bits<22> op, dag outs, dag ins, string opcstr, string opnstr,
+              list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<5> fj;
+  bits<5> fd;
+
+  let Inst{31-10} = op;
+  let Inst{9-5} = fj;
+  let Inst{4-0} = fd;
+}
+
+// 3R-type
+// <opcode | fk | fj | fd>
+class FPFmt3R<bits<17> op, dag outs, dag ins, string opcstr, string opnstr,
+              list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<5> fk;
+  bits<5> fj;
+  bits<5> fd;
+
+  let Inst{31-15} = op;
+  let Inst{14-10} = fk;
+  let Inst{9-5} = fj;
+  let Inst{4-0} = fd;
+}
+
+// 4R-type
+// <opcode | fa | fk | fj | fd>
+class FPFmt4R<bits<12> op, dag outs, dag ins, string opcstr, string opnstr,
+              list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<5> fa;
+  bits<5> fk;
+  bits<5> fj;
+  bits<5> fd;
+
+  let Inst{31-20} = op;
+  let Inst{19-15} = fa;
+  let Inst{14-10} = fk;
+  let Inst{9-5} = fj;
+  let Inst{4-0} = fd;
+}
+
+// 2RI12-type
+// <opcode | I12 | rj | fd>
+class FPFmt2RI12<bits<10> op, dag outs, dag ins, string opcstr, string opnstr,
+                 list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<12> imm12;
+  bits<5> rj;
+  bits<5> fd;
+
+  let Inst{31-22} = op;
+  let Inst{21-10} = imm12;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = fd;
+}
+
+// FmtFCMP
+// <opcode | cond | fk | fj | 0b00 | cd>
+class FPFmtFCMP<bits<12> op, bits<5> cond, dag outs, dag ins, string opcstr,
+                string opnstr, list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<5> fk;
+  bits<5> fj;
+  bits<3> cd;
+
+  let Inst{31-20} = op;
+  let Inst{19-15} = cond;
+  let Inst{14-10} = fk;
+  let Inst{9-5} = fj;
+  let Inst{4-3} = 0b00;
+  let Inst{2-0} = cd;
+}
+
+// FPFmtBR
+// <opcode[7:2] | I21[15:0] | opcode[1:0] | cj | I21[20:16]>
+class FPFmtBR<bits<8> opcode, dag outs, dag ins, string opcstr,
+              string opnstr, list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<21> imm21;
+  bits<3> cj;
+
+  let Inst{31-26} = opcode{7-2};
+  let Inst{25-10} = imm21{15-0};
+  let Inst{9-8} = opcode{1-0};
+  let Inst{7-5} = cj;
+  let Inst{4-0} = imm21{20-16};
+}
+
+// FmtFSEL
+// <opcode | ca | fk | fj | fd>
+class FPFmtFSEL<bits<14> op, dag outs, dag ins, string opcstr, string opnstr,
+                list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<3> ca;
+  bits<5> fk;
+  bits<5> fj;
+  bits<5> fd;
+
+  let Inst{31-18} = op;
+  let Inst{17-15} = ca;
+  let Inst{14-10} = fk;
+  let Inst{9-5} = fj;
+  let Inst{4-0} = fd;
+}
+
+// FPFmtMOV
+// <opcode | src | dst>
+class FPFmtMOV<bits<22> op, dag outs, dag ins, string opcstr, string opnstr,
+               list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<5> src;
+  bits<5> dst;
+
+  let Inst{31-10} = op;
+  let Inst{9-5} = src;
+  let Inst{4-0} = dst;
+}
+
+// FPFmtMEM
+// <opcode | rk | rj | fd>
+class FPFmtMEM<bits<17> op, dag outs, dag ins, string opcstr, string opnstr,
+               list<dag> pattern = []>
+    : LAInst<outs, ins, opcstr, opnstr, pattern> {
+  bits<5> rk;
+  bits<5> rj;
+  bits<5> fd;
+
+  let Inst{31-15} = op;
+  let Inst{14-10} = rk;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = fd;
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction class templates
+//===----------------------------------------------------------------------===//
+
+class FP_ALU_2R<bits<22> op, string opstr, RegisterClass rc>
+    : FPFmt2R<op, (outs rc:$fd), (ins rc:$fj), opstr, "$fd, $fj">;
+
+class FP_ALU_3R<bits<17> op, string opstr, RegisterClass rc>
+    : FPFmt3R<op, (outs rc:$fd), (ins rc:$fj, rc:$fk), opstr, "$fd, $fj, $fk">;
+
+class FP_ALU_4R<bits<12> op, string opstr, RegisterClass rc>
+    : FPFmt4R<op, (outs rc:$fd), (ins rc:$fj, rc:$fk, rc:$fa), opstr,
+              "$fd, $fj, $fk, $fa">;
+
+class FPCMPOpc<bits<12> value> {
+  bits<12> val = value;
+}
+
+class FPCMPCond<bits<5> value> {
+  bits<5> val = value;
+}
+
+class FP_CMP<FPCMPOpc op, FPCMPCond cond, string opstr, RegisterClass rc>
+    : FPFmtFCMP<op.val, cond.val, (outs CFR:$cd), (ins rc:$fj, rc:$fk), opstr,
+                "$cd, $fj, $fk">;
+
+class FP_CONV<bits<22> op, string opstr, RegisterClass rcd, RegisterClass rcs>
+    : FPFmt2R<op, (outs rcd:$fd), (ins rcs:$fj), opstr, "$fd, $fj">;
+
+class FP_MOV<bits<22> op, string opstr, RegisterClass rcd, RegisterClass rcs>
+    : FPFmtMOV<op, (outs rcd:$dst), (ins rcs:$src), opstr, "$dst, $src">;
+
+class FP_SEL<bits<14> op, string opstr, RegisterClass rc>
+    : FPFmtFSEL<op, (outs rc:$fd), (ins rc:$fj, rc:$fk, CFR:$ca), opstr,
+                "$fd, $fj, $fk, $ca">;
+
+class FP_BRANCH<bits<8> opcode, string opstr>
+    : FPFmtBR<opcode, (outs), (ins CFR:$cj, simm21_lsl2:$imm21), opstr,
+              "$cj, $imm21"> {
+  let isBranch = 1;
+  let isTerminator = 1;
+}
+
+let mayLoad = 1 in {
+class FP_LOAD_3R<bits<17> op, string opstr, RegisterClass rc>
+    : FPFmtMEM<op, (outs rc:$fd), (ins GPR:$rj, GPR:$rk), opstr,
+               "$fd, $rj, $rk">;
+class FP_LOAD_2RI12<bits<10> op, string opstr, RegisterClass rc>
+    : FPFmt2RI12<op, (outs rc:$fd), (ins GPR:$rj, simm12:$imm12), opstr,
+                 "$fd, $rj, $imm12">;
+} // mayLoad = 1
+
+let mayStore = 1 in {
+class FP_STORE_3R<bits<17> op, string opstr, RegisterClass rc>
+    : FPFmtMEM<op, (outs), (ins rc:$fd, GPR:$rj, GPR:$rk), opstr,
+               "$fd, $rj, $rk">;
+class FP_STORE_2RI12<bits<10> op, string opstr, RegisterClass rc>
+    : FPFmt2RI12<op, (outs), (ins rc:$fd, GPR:$rj, simm12:$imm12), opstr,
+                 "$fd, $rj, $imm12">;
+} // mayStore = 1
+
+def FPCMP_OPC_S : FPCMPOpc<0b000011000001>;
+def FPCMP_OPC_D : FPCMPOpc<0b000011000010>;
+
+def FPCMP_COND_CAF  : FPCMPCond<0x0>;
+def FPCMP_COND_CUN  : FPCMPCond<0x8>;
+def FPCMP_COND_CEQ  : FPCMPCond<0x4>;
+def FPCMP_COND_CUEQ : FPCMPCond<0xC>;
+def FPCMP_COND_CLT  : FPCMPCond<0x2>;
+def FPCMP_COND_CULT : FPCMPCond<0xA>;
+def FPCMP_COND_CLE  : FPCMPCond<0x6>;
+def FPCMP_COND_CULE : FPCMPCond<0xE>;
+def FPCMP_COND_CNE  : FPCMPCond<0x10>;
+def FPCMP_COND_COR  : FPCMPCond<0x14>;
+def FPCMP_COND_CUNE : FPCMPCond<0x18>;
+def FPCMP_COND_SAF  : FPCMPCond<0x1>;
+def FPCMP_COND_SUN  : FPCMPCond<0x9>;
+def FPCMP_COND_SEQ  : FPCMPCond<0x5>;
+def FPCMP_COND_SUEQ : FPCMPCond<0xD>;
+def FPCMP_COND_SLT  : FPCMPCond<0x3>;
+def FPCMP_COND_SULT : FPCMPCond<0xB>;
+def FPCMP_COND_SLE  : FPCMPCond<0x7>;
+def FPCMP_COND_SULE : FPCMPCond<0xF>;
+def FPCMP_COND_SNE  : FPCMPCond<0x11>;
+def FPCMP_COND_SOR  : FPCMPCond<0x15>;
+def FPCMP_COND_SUNE : FPCMPCond<0x19>;

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td b/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td
index 175a03e1d970d..a41caceec0e3c 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td
@@ -10,9 +10,9 @@
 //  Describe LoongArch instructions format
 //
 //  opcode       - operation code.
-//  {r/f}d       - destination operand.
-//  {r/f}{j/k/a} - source operand.
-//  immN         - immediate data.
+//  rd           - destination register operand.
+//  r{j/k}       - source register operand.
+//  immN         - immediate data operand.
 //
 //===----------------------------------------------------------------------===//
 
@@ -57,7 +57,6 @@ class Fmt2R<bits<22> op, dag outs, dag ins, string opcstr, string opnstr,
 
 // 3R-type
 // <opcode | rk | rj | rd>
-// <opcode | fk | fj | fd>
 class Fmt3R<bits<17> op, dag outs, dag ins, string opcstr, string opnstr,
             list<dag> pattern = []>
     : LAInst<outs, ins, opcstr, opnstr, pattern> {
@@ -71,36 +70,6 @@ class Fmt3R<bits<17> op, dag outs, dag ins, string opcstr, string opnstr,
   let Inst{4-0} = rd;
 }
 
-class Fmt3FR<bits<17> op, dag outs, dag ins, string opcstr, string opnstr,
-             list<dag> pattern = []>
-    : LAInst<outs, ins, opcstr, opnstr, pattern> {
-  bits<5> fk;
-  bits<5> fj;
-  bits<5> fd;
-
-  let Inst{31-15} = op;
-  let Inst{14-10} = fk;
-  let Inst{9-5} = fj;
-  let Inst{4-0} = fd;
-}
-
-// 4R-type
-// <opcode | ra | rk | rj | rd>
-class Fmt4R<bits<12> op, dag outs, dag ins, string opcstr, string opnstr,
-            list<dag> pattern = []>
-    : LAInst<outs, ins, opcstr, opnstr, pattern> {
-  bits<5> ra;
-  bits<5> rk;
-  bits<5> rj;
-  bits<5> rd;
-
-  let Inst{31-20} = op;
-  let Inst{19-15} = ra;
-  let Inst{14-10} = rk;
-  let Inst{9-5} = rj;
-  let Inst{4-0} = rd;
-}
-
 // 3RI2-type
 // <opcode | I2 | rk | rj | rd>
 class Fmt3RI2<bits<15> op, dag outs, dag ins, string opcstr, string opnstr,

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index e718ebe9db3b1..477e12db952fb 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -22,6 +22,7 @@ def loongarch_ret : SDNode<"LoongArchISD::RET", SDTNone,
 //===----------------------------------------------------------------------===//
 // Operand and SDNode transformation definitions.
 //===----------------------------------------------------------------------===//
+
 class ImmAsmOperand<string prefix, int width, string suffix>
     : AsmOperandClass {
   let Name = prefix # "Imm" # width # suffix;
@@ -111,10 +112,12 @@ def simm26_lsl2 : Operand<GRLenVT> {
 //===----------------------------------------------------------------------===//
 
 include "LoongArchInstrFormats.td"
+include "LoongArchFloatInstrFormats.td"
 
 //===----------------------------------------------------------------------===//
 // Instruction Class Templates
 //===----------------------------------------------------------------------===//
+
 class ALU_3R<bits<17> op, string opstr>
     : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), opstr, "$rd, $rj, $rk">;
 class ALU_2R<bits<22> op, string opstr>
@@ -203,7 +206,7 @@ class SCBase<bits<8> op, string opstr>
                opstr, "$rd, $rj, $imm14">;
 
 //===----------------------------------------------------------------------===//
-// Instructions
+// Basic Integer Instructions
 //===----------------------------------------------------------------------===//
 
 // Arithmetic Operation Instructions
@@ -523,5 +526,13 @@ def : PatGprImm_32<add, ADDI_W, simm12>;
 //===----------------------------------------------------------------------===//
 // Assembler Pseudo Instructions
 //===----------------------------------------------------------------------===//
+
 def : InstAlias<"nop", (ANDI R0, R0, 0)>;
 def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>;
+
+//===----------------------------------------------------------------------===//
+// Basic Floating-Point Instructions
+//===----------------------------------------------------------------------===//
+
+include "LoongArchFloat32InstrInfo.td"
+include "LoongArchFloat64InstrInfo.td"

diff  --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td
index d55b94bcb4240..02c9792bff319 100644
--- a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td
@@ -142,3 +142,18 @@ let RegAltNameIndices = [RegAliasName] in {
 // The order of registers represents the preferred allocation sequence.
 def FPR32 : RegisterClass<"LoongArch", [f32], 32, (sequence "F%u", 0, 31)>;
 def FPR64 : RegisterClass<"LoongArch", [f64], 64, (sequence "F%u_64", 0, 31)>;
+
+// Condition flag registers
+
+foreach I = 0-7 in
+def FCC#I : LoongArchReg<I, "fcc"#I>;
+
+def CFR : RegisterClass<"LoongArch", [i32], 32, (sequence "FCC%u", 0, 7)>;
+
+// Control and status registers
+
+foreach I = 0-3 in
+def FCSR#I : LoongArchReg<I, "fcsr"#I>;
+
+let isAllocatable = false in
+def FCSR : RegisterClass<"LoongArch", [i32], 32, (sequence "FCSR%u", 0, 3)>;

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/d-arith.s b/llvm/test/MC/LoongArch/Basic/Float/d-arith.s
new file mode 100644
index 0000000000000..a10845d7422af
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/d-arith.s
@@ -0,0 +1,99 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+## Support for the 'D' extension implies support for 'F'
+# ASM-AND-OBJ: fadd.s $fs5, $ft7, $fs1
+# ASM: encoding: [0xfd,0xe5,0x00,0x01]
+fadd.s $fs5, $ft7, $fs1
+
+# ASM-AND-OBJ: fadd.d $fs1, $fa7, $ft5
+# ASM: encoding: [0xf9,0x34,0x01,0x01]
+fadd.d $fs1, $fa7, $ft5
+
+# ASM-AND-OBJ: fsub.d $fs5, $fa1, $ft10
+# ASM: encoding: [0x3d,0x48,0x03,0x01]
+fsub.d $fs5, $fa1, $ft10
+
+# ASM-AND-OBJ: fmul.d $fa4, $fs6, $fa7
+# ASM: encoding: [0xc4,0x1f,0x05,0x01]
+fmul.d $fa4, $fs6, $fa7
+
+# ASM-AND-OBJ: fdiv.d $fa3, $fs1, $fs4
+# ASM: encoding: [0x23,0x73,0x07,0x01]
+fdiv.d $fa3, $fs1, $fs4
+
+# ASM-AND-OBJ: fmadd.d $ft13, $fs0, $fs4, $fs0
+# ASM: encoding: [0x15,0x73,0x2c,0x08]
+fmadd.d $ft13, $fs0, $fs4, $fs0
+
+# ASM-AND-OBJ: fmsub.d $fa6, $ft10, $ft12, $fs3
+# ASM: encoding: [0x46,0xd2,0x6d,0x08]
+fmsub.d $fa6, $ft10, $ft12, $fs3
+
+# ASM-AND-OBJ: fnmadd.d $fs1, $ft5, $ft11, $fs6
+# ASM: encoding: [0xb9,0x4d,0xaf,0x08]
+fnmadd.d $fs1, $ft5, $ft11, $fs6
+
+# ASM-AND-OBJ: fnmsub.d $fs6, $fs2, $fa7, $fs0
+# ASM: encoding: [0x5e,0x1f,0xec,0x08]
+fnmsub.d $fs6, $fs2, $fa7, $fs0
+
+# ASM-AND-OBJ: fmax.d $ft3, $fs2, $ft5
+# ASM: encoding: [0x4b,0x37,0x09,0x01]
+fmax.d $ft3, $fs2, $ft5
+
+# ASM-AND-OBJ: fmin.d $fa1, $ft5, $fs3
+# ASM: encoding: [0xa1,0x6d,0x0b,0x01]
+fmin.d $fa1, $ft5, $fs3
+
+# ASM-AND-OBJ: fmaxa.d $fs0, $ft5, $fa4
+# ASM: encoding: [0xb8,0x11,0x0d,0x01]
+fmaxa.d $fs0, $ft5, $fa4
+
+# ASM-AND-OBJ: fmina.d $ft10, $ft2, $fa0
+# ASM: encoding: [0x52,0x01,0x0f,0x01]
+fmina.d $ft10, $ft2, $fa0
+
+# ASM-AND-OBJ: fabs.d $ft15, $fa3
+# ASM: encoding: [0x77,0x08,0x14,0x01]
+fabs.d $ft15, $fa3
+
+# ASM-AND-OBJ: fneg.d $ft3, $fs2
+# ASM: encoding: [0x4b,0x1b,0x14,0x01]
+fneg.d $ft3, $fs2
+
+# ASM-AND-OBJ: fsqrt.d $fa2, $ft3
+# ASM: encoding: [0x62,0x49,0x14,0x01]
+fsqrt.d $fa2, $ft3
+
+# ASM-AND-OBJ: frecip.d $fs3, $fs3
+# ASM: encoding: [0x7b,0x5b,0x14,0x01]
+frecip.d $fs3, $fs3
+
+# ASM-AND-OBJ: frsqrt.d $ft14, $fa3
+# ASM: encoding: [0x76,0x68,0x14,0x01]
+frsqrt.d $ft14, $fa3
+
+# ASM-AND-OBJ: fscaleb.d $ft4, $ft6, $fs2
+# ASM: encoding: [0xcc,0x69,0x11,0x01]
+fscaleb.d $ft4, $ft6, $fs2
+
+# ASM-AND-OBJ: flogb.d $ft13, $fs5
+# ASM: encoding: [0xb5,0x2b,0x14,0x01]
+flogb.d $ft13, $fs5
+
+# ASM-AND-OBJ: fcopysign.d $ft8, $fs2, $fa6
+# ASM: encoding: [0x50,0x1b,0x13,0x01]
+fcopysign.d $ft8, $fs2, $fa6
+
+# ASM-AND-OBJ: fclass.d $ft11, $fa2
+# ASM: encoding: [0x53,0x38,0x14,0x01]
+fclass.d $ft11, $fa2

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/d-bound-check.s b/llvm/test/MC/LoongArch/Basic/Float/d-bound-check.s
new file mode 100644
index 0000000000000..1d6b489f33b04
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/d-bound-check.s
@@ -0,0 +1,31 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+## Support for the 'D' extension implies support for 'F'
+# ASM-AND-OBJ: fldgt.s $fa3, $s4, $t1
+# ASM: encoding: [0x63,0x37,0x74,0x38]
+fldgt.s $fa3, $s4, $t1
+
+# ASM-AND-OBJ: fldgt.d $fs2, $a1, $s8
+# ASM: encoding: [0xba,0xfc,0x74,0x38]
+fldgt.d $fs2, $a1, $s8
+
+# ASM-AND-OBJ: fldle.d $fa3, $t3, $fp
+# ASM: encoding: [0xe3,0xd9,0x75,0x38]
+fldle.d $fa3, $t3, $fp
+
+# ASM-AND-OBJ: fstgt.d $ft5, $a7, $s3
+# ASM: encoding: [0x6d,0xe9,0x76,0x38]
+fstgt.d $ft5, $a7, $s3
+
+# ASM-AND-OBJ: fstle.d $ft10, $a5, $t1
+# ASM: encoding: [0x32,0xb5,0x77,0x38]
+fstle.d $ft10, $a5, $t1

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/d-branch.s b/llvm/test/MC/LoongArch/Basic/Float/d-branch.s
new file mode 100644
index 0000000000000..838b7e9330d77
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/d-branch.s
@@ -0,0 +1,15 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+## Support for the 'D' extension implies support for 'F'
+# ASM-AND-OBJ: bceqz $fcc6, 12
+# ASM: encoding: [0xc0,0x0c,0x00,0x48]
+bceqz $fcc6, 12

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/d-comp.s b/llvm/test/MC/LoongArch/Basic/Float/d-comp.s
new file mode 100644
index 0000000000000..3ddae6d0567f8
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/d-comp.s
@@ -0,0 +1,103 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+## Support for the 'D' extension implies support for 'F'
+# ASM-AND-OBJ: fcmp.caf.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x10,0x0c]
+fcmp.caf.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.caf.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x20,0x0c]
+fcmp.caf.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cun.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x24,0x0c]
+fcmp.cun.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.ceq.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x22,0x0c]
+fcmp.ceq.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cueq.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x26,0x0c]
+fcmp.cueq.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.clt.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x21,0x0c]
+fcmp.clt.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cult.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x25,0x0c]
+fcmp.cult.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cle.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x23,0x0c]
+fcmp.cle.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cule.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x27,0x0c]
+fcmp.cule.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cne.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x28,0x0c]
+fcmp.cne.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cor.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x2a,0x0c]
+fcmp.cor.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cune.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x2c,0x0c]
+fcmp.cune.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.saf.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x20,0x0c]
+fcmp.saf.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sun.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x24,0x0c]
+fcmp.sun.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.seq.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x22,0x0c]
+fcmp.seq.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sueq.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x26,0x0c]
+fcmp.sueq.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.slt.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x21,0x0c]
+fcmp.slt.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sult.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x25,0x0c]
+fcmp.sult.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sle.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x23,0x0c]
+fcmp.sle.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sule.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x27,0x0c]
+fcmp.sule.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sne.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x28,0x0c]
+fcmp.sne.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sor.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x2a,0x0c]
+fcmp.sor.d $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sune.d $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x2c,0x0c]
+fcmp.sune.d $fcc0, $fa0, $fa1

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/d-conv.s b/llvm/test/MC/LoongArch/Basic/Float/d-conv.s
new file mode 100644
index 0000000000000..fa5a5088e6a77
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/d-conv.s
@@ -0,0 +1,99 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+## Support for the 'D' extension implies support for 'F'
+# ASM-AND-OBJ: frint.s $fa5, $ft9
+# ASM: encoding: [0x25,0x46,0x1e,0x01]
+frint.s $fa5, $ft9
+
+# ASM-AND-OBJ: fcvt.s.d $ft4, $ft11
+# ASM: encoding: [0x6c,0x1a,0x19,0x01]
+fcvt.s.d $ft4, $ft11
+
+# ASM-AND-OBJ: fcvt.d.s $ft2, $fa6
+# ASM: encoding: [0xca,0x24,0x19,0x01]
+fcvt.d.s $ft2, $fa6
+
+# ASM-AND-OBJ: ffint.s.l $fa6, $fa5
+# ASM: encoding: [0xa6,0x18,0x1d,0x01]
+ffint.s.l $fa6, $fa5
+
+# ASM-AND-OBJ: ffint.d.w $fs0, $ft10
+# ASM: encoding: [0x58,0x22,0x1d,0x01]
+ffint.d.w $fs0, $ft10
+
+# ASM-AND-OBJ: ffint.d.l $ft15, $fs2
+# ASM: encoding: [0x57,0x2b,0x1d,0x01]
+ffint.d.l $ft15, $fs2
+
+# ASM-AND-OBJ: ftint.w.d $fa3, $ft6
+# ASM: encoding: [0xc3,0x09,0x1b,0x01]
+ftint.w.d $fa3, $ft6
+
+# ASM-AND-OBJ: ftint.l.s $fs7, $fs0
+# ASM: encoding: [0x1f,0x27,0x1b,0x01]
+ftint.l.s $fs7, $fs0
+
+# ASM-AND-OBJ: ftint.l.d $ft8, $fs0
+# ASM: encoding: [0x10,0x2b,0x1b,0x01]
+ftint.l.d $ft8, $fs0
+
+# ASM-AND-OBJ: ftintrm.w.d $fa7, $ft0
+# ASM: encoding: [0x07,0x09,0x1a,0x01]
+ftintrm.w.d $fa7, $ft0
+
+# ASM-AND-OBJ: ftintrm.l.s $fs0, $ft2
+# ASM: encoding: [0x58,0x25,0x1a,0x01]
+ftintrm.l.s $fs0, $ft2
+
+# ASM-AND-OBJ: ftintrm.l.d $ft1, $ft1
+# ASM: encoding: [0x29,0x29,0x1a,0x01]
+ftintrm.l.d $ft1, $ft1
+
+# ASM-AND-OBJ: ftintrp.w.d $ft4, $fa3
+# ASM: encoding: [0x6c,0x48,0x1a,0x01]
+ftintrp.w.d $ft4, $fa3
+
+# ASM-AND-OBJ: ftintrp.l.s $fa0, $ft8
+# ASM: encoding: [0x00,0x66,0x1a,0x01]
+ftintrp.l.s $fa0, $ft8
+
+# ASM-AND-OBJ: ftintrp.l.d $fa4, $fs5
+# ASM: encoding: [0xa4,0x6b,0x1a,0x01]
+ftintrp.l.d $fa4, $fs5
+
+# ASM-AND-OBJ: ftintrz.w.d $fs1, $fs0
+# ASM: encoding: [0x19,0x8b,0x1a,0x01]
+ftintrz.w.d $fs1, $fs0
+
+# ASM-AND-OBJ: ftintrz.l.s $ft15, $fa5
+# ASM: encoding: [0xb7,0xa4,0x1a,0x01]
+ftintrz.l.s $ft15, $fa5
+
+# ASM-AND-OBJ: ftintrz.l.d $fa3, $ft2
+# ASM: encoding: [0x43,0xa9,0x1a,0x01]
+ftintrz.l.d $fa3, $ft2
+
+# ASM-AND-OBJ: ftintrne.w.d $fs7, $ft4
+# ASM: encoding: [0x9f,0xc9,0x1a,0x01]
+ftintrne.w.d $fs7, $ft4
+
+# ASM-AND-OBJ: ftintrne.l.s $ft14, $fs3
+# ASM: encoding: [0x76,0xe7,0x1a,0x01]
+ftintrne.l.s $ft14, $fs3
+
+# ASM-AND-OBJ: ftintrne.l.d $fs4, $fa6
+# ASM: encoding: [0xdc,0xe8,0x1a,0x01]
+ftintrne.l.d $fs4, $fa6
+
+# ASM-AND-OBJ: frint.d $fs5, $fa2
+# ASM: encoding: [0x5d,0x48,0x1e,0x01]
+frint.d $fs5, $fa2

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/d-invalid.s b/llvm/test/MC/LoongArch/Basic/Float/d-invalid.s
new file mode 100644
index 0000000000000..b38a4461afcb4
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/d-invalid.s
@@ -0,0 +1,7 @@
+# RUN: not llvm-mc --triple=loongarch32 -mattr=+d %s 2>&1 | FileCheck %s
+
+# CHECK: :[[#@LINE+1]]:1: error: instruction requires the following: LA64 Basic Integer and Privilege Instruction Set
+movgr2fr.d $fa0, $a0
+
+# CHECK: :[[#@LINE+1]]:1: error: instruction requires the following: LA64 Basic Integer and Privilege Instruction Set
+movfr2gr.d $a0, $fa0

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/d-memory.s b/llvm/test/MC/LoongArch/Basic/Float/d-memory.s
new file mode 100644
index 0000000000000..a8f04cefe059b
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/d-memory.s
@@ -0,0 +1,31 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+## Support for the 'D' extension implies support for 'F'
+# ASM-AND-OBJ: fld.s $ft15, $t3, 250
+# ASM: encoding: [0xf7,0xe9,0x03,0x2b]
+fld.s $ft15, $t3, 250
+
+# ASM-AND-OBJ: fld.d $ft14, $t5, 114
+# ASM: encoding: [0x36,0xca,0x81,0x2b]
+fld.d $ft14, $t5, 114
+
+# ASM-AND-OBJ: fst.d $fs4, $a3, 198
+# ASM: encoding: [0xfc,0x18,0xc3,0x2b]
+fst.d $fs4, $a3, 198
+
+# ASM-AND-OBJ: fldx.d $fs3, $t1, $s8
+# ASM: encoding: [0xbb,0x7d,0x34,0x38]
+fldx.d $fs3, $t1, $s8
+
+# ASM-AND-OBJ: fstx.d $fa6, $t3, $t5
+# ASM: encoding: [0xe6,0x45,0x3c,0x38]
+fstx.d $fa6, $t3, $t5

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/d-move.s b/llvm/test/MC/LoongArch/Basic/Float/d-move.s
new file mode 100644
index 0000000000000..c3008add62849
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/d-move.s
@@ -0,0 +1,39 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --show-encoding --defsym=LA64=1 \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM,ASM-AND-OBJ64,ASM64 %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+d --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+d --filetype=obj --defsym=LA64=1 \
+# RUN:     | llvm-objdump -d --mattr=+d - \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM-AND-OBJ64 %s
+
+## Support for the 'D' extension implies support for 'F'
+# ASM-AND-OBJ: fmov.s $ft5, $ft15
+# ASM: encoding: [0xed,0x96,0x14,0x01]
+fmov.s $ft5, $ft15
+
+# ASM-AND-OBJ: fmov.d $fs6, $ft1
+# ASM: encoding: [0x3e,0x99,0x14,0x01]
+fmov.d $fs6, $ft1
+
+# ASM-AND-OBJ: fsel $ft10, $ft12, $ft13, $fcc4
+# ASM: encoding: [0x92,0x56,0x02,0x0d]
+fsel $ft10, $ft12, $ft13, $fcc4
+
+# ASM-AND-OBJ64: movgr2frh.w $ft15, $s3
+# ASM64: encoding: [0x57,0xaf,0x14,0x01]
+movgr2frh.w $ft15, $s3
+
+.ifdef LA64
+
+# ASM-AND-OBJ64: movgr2fr.d $fs6, $a7
+# ASM64: encoding: [0x7e,0xa9,0x14,0x01]
+movgr2fr.d $fs6, $a7
+
+# ASM-AND-OBJ64: movfr2gr.d $s3, $ft9
+# ASM64: encoding: [0x3a,0xba,0x14,0x01]
+movfr2gr.d $s3, $ft9
+
+.endif

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/f-arith.s b/llvm/test/MC/LoongArch/Basic/Float/f-arith.s
new file mode 100644
index 0000000000000..a5873a54511ac
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/f-arith.s
@@ -0,0 +1,94 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+# ASM-AND-OBJ: fadd.s $fs5, $ft7, $fs1
+# ASM: encoding: [0xfd,0xe5,0x00,0x01]
+fadd.s $fs5, $ft7, $fs1
+
+# ASM-AND-OBJ: fsub.s $ft6, $fa6, $fs7
+# ASM: encoding: [0xce,0xfc,0x02,0x01]
+fsub.s $ft6, $fa6, $fs7
+
+# ASM-AND-OBJ: fmul.s $fa0, $fa7, $ft9
+# ASM: encoding: [0xe0,0xc4,0x04,0x01]
+fmul.s $fa0, $fa7, $ft9
+
+# ASM-AND-OBJ: fdiv.s $ft12, $fs0, $ft11
+# ASM: encoding: [0x14,0xcf,0x06,0x01]
+fdiv.s $ft12, $fs0, $ft11
+
+# ASM-AND-OBJ: fmadd.s $fa3, $ft8, $fa3, $ft7
+# ASM: encoding: [0x03,0x8e,0x17,0x08]
+fmadd.s $fa3, $ft8, $fa3, $ft7
+
+# ASM-AND-OBJ: fmsub.s $ft15, $ft3, $ft13, $fa4
+# ASM: encoding: [0x77,0x55,0x52,0x08]
+fmsub.s $ft15, $ft3, $ft13, $fa4
+
+# ASM-AND-OBJ: fnmadd.s $fs5, $fa1, $fs0, $ft12
+# ASM: encoding: [0x3d,0x60,0x9a,0x08]
+fnmadd.s $fs5, $fa1, $fs0, $ft12
+
+# ASM-AND-OBJ: fnmsub.s $ft0, $fa4, $fs0, $fs1
+# ASM: encoding: [0x88,0xe0,0xdc,0x08]
+fnmsub.s $ft0, $fa4, $fs0, $fs1
+
+# ASM-AND-OBJ: fmax.s $ft14, $fa6, $fs3
+# ASM: encoding: [0xd6,0xec,0x08,0x01]
+fmax.s $ft14, $fa6, $fs3
+
+# ASM-AND-OBJ: fmin.s $ft6, $ft2, $ft11
+# ASM: encoding: [0x4e,0xcd,0x0a,0x01]
+fmin.s $ft6, $ft2, $ft11
+
+# ASM-AND-OBJ: fmaxa.s $ft1, $fs3, $fs7
+# ASM: encoding: [0x69,0xff,0x0c,0x01]
+fmaxa.s $ft1, $fs3, $fs7
+
+# ASM-AND-OBJ: fmina.s $ft7, $ft10, $fa1
+# ASM: encoding: [0x4f,0x86,0x0e,0x01]
+fmina.s $ft7, $ft10, $fa1
+
+# ASM-AND-OBJ: fabs.s $fs4, $ft4
+# ASM: encoding: [0x9c,0x05,0x14,0x01]
+fabs.s $fs4, $ft4
+
+# ASM-AND-OBJ: fneg.s $ft13, $fs0
+# ASM: encoding: [0x15,0x17,0x14,0x01]
+fneg.s $ft13, $fs0
+
+# ASM-AND-OBJ: fsqrt.s $fs3, $ft10
+# ASM: encoding: [0x5b,0x46,0x14,0x01]
+fsqrt.s $fs3, $ft10
+
+# ASM-AND-OBJ: frecip.s $ft9, $fs3
+# ASM: encoding: [0x71,0x57,0x14,0x01]
+frecip.s $ft9, $fs3
+
+# ASM-AND-OBJ: frsqrt.s $fs1, $ft4
+# ASM: encoding: [0x99,0x65,0x14,0x01]
+frsqrt.s $fs1, $ft4
+
+# ASM-AND-OBJ: fscaleb.s $ft13, $ft15, $fa6
+# ASM: encoding: [0xf5,0x9a,0x10,0x01]
+fscaleb.s $ft13, $ft15, $fa6
+
+# ASM-AND-OBJ: flogb.s $fs7, $ft15
+# ASM: encoding: [0xff,0x26,0x14,0x01]
+flogb.s $fs7, $ft15
+
+# ASM-AND-OBJ: fcopysign.s $ft5, $fs0, $ft15
+# ASM: encoding: [0x0d,0xdf,0x12,0x01]
+fcopysign.s $ft5, $fs0, $ft15
+
+# ASM-AND-OBJ: fclass.s $ft12, $ft1
+# ASM: encoding: [0x34,0x35,0x14,0x01]
+fclass.s $ft12, $ft1

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/f-bound-check.s b/llvm/test/MC/LoongArch/Basic/Float/f-bound-check.s
new file mode 100644
index 0000000000000..bfff92ff8a061
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/f-bound-check.s
@@ -0,0 +1,26 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+# ASM-AND-OBJ: fldgt.s $fa3, $s4, $t1
+# ASM: encoding: [0x63,0x37,0x74,0x38]
+fldgt.s $fa3, $s4, $t1
+
+# ASM-AND-OBJ: fldle.s $fs0, $s6, $t5
+# ASM: encoding: [0xb8,0x47,0x75,0x38]
+fldle.s $fs0, $s6, $t5
+
+# ASM-AND-OBJ: fstgt.s $fs7, $t1, $s7
+# ASM: encoding: [0xbf,0x79,0x76,0x38]
+fstgt.s $fs7, $t1, $s7
+
+# ASM-AND-OBJ: fstle.s $ft5, $t1, $a3
+# ASM: encoding: [0xad,0x1d,0x77,0x38]
+fstle.s $ft5, $t1, $a3

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/f-branch.s b/llvm/test/MC/LoongArch/Basic/Float/f-branch.s
new file mode 100644
index 0000000000000..583008b5a4f64
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/f-branch.s
@@ -0,0 +1,18 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+# ASM-AND-OBJ: bceqz $fcc6, 12
+# ASM: encoding: [0xc0,0x0c,0x00,0x48]
+bceqz $fcc6, 12
+
+# ASM-AND-OBJ: bcnez $fcc6, 72
+# ASM: encoding: [0xc0,0x49,0x00,0x48]
+bcnez $fcc6, 72

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/f-comp.s b/llvm/test/MC/LoongArch/Basic/Float/f-comp.s
new file mode 100644
index 0000000000000..cc4e1470d5251
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/f-comp.s
@@ -0,0 +1,98 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+# ASM-AND-OBJ: fcmp.caf.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x10,0x0c]
+fcmp.caf.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cun.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x14,0x0c]
+fcmp.cun.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.ceq.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x12,0x0c]
+fcmp.ceq.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cueq.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x16,0x0c]
+fcmp.cueq.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.clt.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x11,0x0c]
+fcmp.clt.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cult.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x15,0x0c]
+fcmp.cult.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cle.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x13,0x0c]
+fcmp.cle.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cule.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x17,0x0c]
+fcmp.cule.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cne.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x18,0x0c]
+fcmp.cne.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cor.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x1a,0x0c]
+fcmp.cor.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.cune.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x04,0x1c,0x0c]
+fcmp.cune.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.saf.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x10,0x0c]
+fcmp.saf.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sun.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x14,0x0c]
+fcmp.sun.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.seq.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x12,0x0c]
+fcmp.seq.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sueq.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x16,0x0c]
+fcmp.sueq.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.slt.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x11,0x0c]
+fcmp.slt.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sult.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x15,0x0c]
+fcmp.sult.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sle.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x13,0x0c]
+fcmp.sle.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sule.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x17,0x0c]
+fcmp.sule.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sne.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x18,0x0c]
+fcmp.sne.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sor.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x1a,0x0c]
+fcmp.sor.s $fcc0, $fa0, $fa1
+
+# ASM-AND-OBJ: fcmp.sune.s $fcc0, $fa0, $fa1
+# ASM: encoding: [0x00,0x84,0x1c,0x0c]
+fcmp.sune.s $fcc0, $fa0, $fa1

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/f-conv.s b/llvm/test/MC/LoongArch/Basic/Float/f-conv.s
new file mode 100644
index 0000000000000..db44077dfc38f
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/f-conv.s
@@ -0,0 +1,38 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+# ASM-AND-OBJ: ffint.s.w $fs6, $fa5
+# ASM: encoding: [0xbe,0x10,0x1d,0x01]
+ffint.s.w $fs6, $fa5
+
+# ASM-AND-OBJ: ftint.w.s $ft13, $ft5
+# ASM: encoding: [0xb5,0x05,0x1b,0x01]
+ftint.w.s $ft13, $ft5
+
+# ASM-AND-OBJ: ftintrm.w.s $ft8, $ft8
+# ASM: encoding: [0x10,0x06,0x1a,0x01]
+ftintrm.w.s $ft8, $ft8
+
+# ASM-AND-OBJ: ftintrp.w.s $ft6, $fs7
+# ASM: encoding: [0xee,0x47,0x1a,0x01]
+ftintrp.w.s $ft6, $fs7
+
+# ASM-AND-OBJ: ftintrz.w.s $fa4, $fs5
+# ASM: encoding: [0xa4,0x87,0x1a,0x01]
+ftintrz.w.s $fa4, $fs5
+
+# ASM-AND-OBJ: ftintrne.w.s $fa4, $ft9
+# ASM: encoding: [0x24,0xc6,0x1a,0x01]
+ftintrne.w.s $fa4, $ft9
+
+# ASM-AND-OBJ: frint.s $fa5, $ft9
+# ASM: encoding: [0x25,0x46,0x1e,0x01]
+frint.s $fa5, $ft9

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/f-invalid.s b/llvm/test/MC/LoongArch/Basic/Float/f-invalid.s
new file mode 100644
index 0000000000000..2ab91b3f1a777
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/f-invalid.s
@@ -0,0 +1,4 @@
+# RUN: not llvm-mc --triple=loongarch32 -mattr=+f %s 2>&1 | FileCheck %s
+
+# CHECK: :[[#@LINE+1]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point)
+fadd.d $fa0, $fa0, $fa0

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/f-memory.s b/llvm/test/MC/LoongArch/Basic/Float/f-memory.s
new file mode 100644
index 0000000000000..b5fbd9abd2baa
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/f-memory.s
@@ -0,0 +1,26 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+# ASM-AND-OBJ: fld.s $ft15, $t3, 250
+# ASM: encoding: [0xf7,0xe9,0x03,0x2b]
+fld.s $ft15, $t3, 250
+
+# ASM-AND-OBJ: fst.s $fs6, $t7, 230
+# ASM: encoding: [0x7e,0x9a,0x43,0x2b]
+fst.s $fs6, $t7, 230
+
+# ASM-AND-OBJ: fldx.s $fa1, $t3, $t7
+# ASM: encoding: [0xe1,0x4d,0x30,0x38]
+fldx.s $fa1, $t3, $t7
+
+# ASM-AND-OBJ: fstx.s $fs2, $sp, $fp
+# ASM: encoding: [0x7a,0x58,0x38,0x38]
+fstx.s $fs2, $sp, $fp

diff  --git a/llvm/test/MC/LoongArch/Basic/Float/f-move.s b/llvm/test/MC/LoongArch/Basic/Float/f-move.s
new file mode 100644
index 0000000000000..da9107686d35f
--- /dev/null
+++ b/llvm/test/MC/LoongArch/Basic/Float/f-move.s
@@ -0,0 +1,74 @@
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --show-encoding \
+# RUN:     | FileCheck --check-prefixes=ASM-AND-OBJ,ASM %s
+# RUN: llvm-mc %s --triple=loongarch32 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+# RUN: llvm-mc %s --triple=loongarch64 --mattr=+f --filetype=obj \
+# RUN:     | llvm-objdump -d --mattr=+f - \
+# RUN:     | FileCheck --check-prefix=ASM-AND-OBJ %s
+
+# ASM-AND-OBJ: fmov.s $ft5, $ft15
+# ASM: encoding: [0xed,0x96,0x14,0x01]
+fmov.s $ft5, $ft15
+
+# ASM-AND-OBJ: fsel $ft10, $ft12, $ft13, $fcc4
+# ASM: encoding: [0x92,0x56,0x02,0x0d]
+fsel $ft10, $ft12, $ft13, $fcc4
+
+# ASM-AND-OBJ: movgr2fr.w $fa6, $tp
+# ASM: encoding: [0x46,0xa4,0x14,0x01]
+movgr2fr.w $fa6, $tp
+
+# ASM-AND-OBJ: movfr2gr.s $a6, $ft14
+# ASM: encoding: [0xca,0xb6,0x14,0x01]
+movfr2gr.s $a6, $ft14
+
+# ASM-AND-OBJ: movgr2fcsr $fcsr0, $a0
+# ASM: encoding: [0x80,0xc0,0x14,0x01]
+movgr2fcsr $fcsr0, $a0
+
+# ASM-AND-OBJ: movfcsr2gr $a0, $fcsr0
+# ASM: encoding: [0x04,0xc8,0x14,0x01]
+movfcsr2gr $a0, $fcsr0
+
+# ASM-AND-OBJ: movgr2fcsr $fcsr1, $a0
+# ASM: encoding: [0x81,0xc0,0x14,0x01]
+movgr2fcsr $fcsr1, $a0
+
+# ASM-AND-OBJ: movfcsr2gr $a0, $fcsr1
+# ASM: encoding: [0x24,0xc8,0x14,0x01]
+movfcsr2gr $a0, $fcsr1
+
+# ASM-AND-OBJ: movgr2fcsr $fcsr2, $a0
+# ASM: encoding: [0x82,0xc0,0x14,0x01]
+movgr2fcsr $fcsr2, $a0
+
+# ASM-AND-OBJ: movfcsr2gr $a0, $fcsr2
+# ASM: encoding: [0x44,0xc8,0x14,0x01]
+movfcsr2gr $a0, $fcsr2
+
+# ASM-AND-OBJ: movgr2fcsr $fcsr3, $a0
+# ASM: encoding: [0x83,0xc0,0x14,0x01]
+movgr2fcsr $fcsr3, $a0
+
+# ASM-AND-OBJ: movfcsr2gr $a0, $fcsr3
+# ASM: encoding: [0x64,0xc8,0x14,0x01]
+movfcsr2gr $a0, $fcsr3
+
+# ASM-AND-OBJ: movfr2cf $fcc4, $ft3
+# ASM: encoding: [0x64,0xd1,0x14,0x01]
+movfr2cf $fcc4, $ft3
+
+# ASM-AND-OBJ: movcf2fr $ft8, $fcc0
+# ASM: encoding: [0x10,0xd4,0x14,0x01]
+movcf2fr $ft8, $fcc0
+
+# ASM-AND-OBJ: movgr2cf $fcc5, $ra
+# ASM: encoding: [0x25,0xd8,0x14,0x01]
+movgr2cf $fcc5, $ra
+
+# ASM-AND-OBJ: movcf2gr $r21, $fcc7
+# ASM: encoding: [0xf5,0xdc,0x14,0x01]
+movcf2gr $r21, $fcc7

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
index cb6b2ba1beddf..bd01eb49d11cd 100644
--- a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
+++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
@@ -1,7 +1,7 @@
 ## Test invalid instructions on both loongarch32 and loongarch64 target.
 
-# RUN: not llvm-mc --triple=loongarch32 %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK64
-# RUN: not llvm-mc --triple=loongarch64 %s 2>&1 --defsym=LA64=1 | FileCheck %s
+# RUN: not llvm-mc --triple=loongarch32 --mattr=-f %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK64
+# RUN: not llvm-mc --triple=loongarch64 --mattr=-f %s 2>&1 --defsym=LA64=1 | FileCheck %s
 
 ## Out of range immediates
 ## uimm2
@@ -168,9 +168,15 @@ and $a0, $a0
 andi $a0, $a0
 # CHECK: :[[#@LINE-1]]:1: error: too few operands for instruction
 
-## Instructions outside the base ISA
+## Instructions outside the base integer ISA
 ## TODO: Test instructions in LSX/LASX/LBT/LVZ after their introduction.
 
+## Floating-Point mnemonics
+fadd.s $fa0, $fa0, $fa0
+# CHECK:   :[[#@LINE-1]]:1: error: instruction requires the following: 'F' (Single-Precision Floating-Point)
+fadd.d $fa0, $fa0, $fa0
+# CHECK:   :[[#@LINE-1]]:1: error: instruction requires the following: 'D' (Double-Precision Floating-Point)
+
 ## Using floating point registers when integer registers are expected
 sll.w $a0, $a0, $fa0
 # CHECK: :[[#@LINE-1]]:18: error: invalid operand for instruction


        


More information about the llvm-commits mailing list