[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