diff --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp --- 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 @@ 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 @@ 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(Expr)) { @@ -245,9 +250,22 @@ #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 @@ return false; } +unsigned +LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, + unsigned Kind) { + LoongArchOperand &Op = static_cast(AsmOp); + if (!Op.isReg()) + return Match_InvalidOperand; + + MCRegister Reg = Op.getReg(); + // As the parser couldn't differentiate 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 --- a/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp +++ b/llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp @@ -64,6 +64,42 @@ 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 static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm, int64_t Address, diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td b/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td --- 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 @@ // 3R-type // -// class Fmt3R op, dag outs, dag ins, string opcstr, string opnstr, list pattern = []> : LAInst { @@ -71,36 +70,6 @@ let Inst{4-0} = rd; } -class Fmt3FR op, dag outs, dag ins, string opcstr, string opnstr, - list pattern = []> - : LAInst { - 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 -// -class Fmt4R op, dag outs, dag ins, string opcstr, string opnstr, - list pattern = []> - : LAInst { - 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 // class Fmt3RI2 op, dag outs, dag ins, string opcstr, string opnstr, diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrFormatsF.td b/llvm/lib/Target/LoongArch/LoongArchInstrFormatsF.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchInstrFormatsF.td @@ -0,0 +1,154 @@ +//==- 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 +// +class FPFmt2R op, dag outs, dag ins, string opcstr, string opnstr, + list pattern = []> + : LAInst { + bits<5> fj; + bits<5> fd; + + let Inst{31-10} = op; + let Inst{9-5} = fj; + let Inst{4-0} = fd; +} + +// 3R-type +// +class FPFmt3R op, dag outs, dag ins, string opcstr, string opnstr, + list pattern = []> + : LAInst { + 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 +// +class FPFmt4R op, dag outs, dag ins, string opcstr, string opnstr, + list pattern = []> + : LAInst { + 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 +// +class FPFmt2RI12 op, dag outs, dag ins, string opcstr, string opnstr, + list pattern = []> + : LAInst { + 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 +// +class FPFmtFCMP op, bits<5> cond, dag outs, dag ins, string opcstr, + string opnstr, list pattern = []> + : LAInst { + 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 +// +class FPFmtBR opcode, dag outs, dag ins, string opcstr, + string opnstr, list pattern = []> + : LAInst { + 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 +// +class FPFmtFSEL op, dag outs, dag ins, string opcstr, string opnstr, + list pattern = []> + : LAInst { + 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 +// +class FPFmtMOV op, dag outs, dag ins, string opcstr, string opnstr, + list pattern = []> + : LAInst { + bits<5> src; + bits<5> dst; + + let Inst{31-10} = op; + let Inst{9-5} = src; + let Inst{4-0} = dst; +} + +// FPFmtMEM +// +class FPFmtMEM op, dag outs, dag ins, string opcstr, string opnstr, + list pattern = []> + : LAInst { + 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; +} diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -22,6 +22,7 @@ //===----------------------------------------------------------------------===// // Operand and SDNode transformation definitions. //===----------------------------------------------------------------------===// + class ImmAsmOperand : AsmOperandClass { let Name = prefix # "Imm" # width # suffix; @@ -115,6 +116,7 @@ //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// + class ALU_3R op, string opstr> : Fmt3R; class ALU_2R op, string opstr> @@ -203,7 +205,7 @@ opstr, "$rd, $rj, $imm14">; //===----------------------------------------------------------------------===// -// Instructions +// Basic Integer Instructions //===----------------------------------------------------------------------===// // Arithmetic Operation Instructions @@ -523,5 +525,13 @@ //===----------------------------------------------------------------------===// // 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 "LoongArchInstrInfoF.td" +include "LoongArchInstrInfoD.td" diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfoD.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfoD.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfoD.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; +def FCMP_CUN_D : FP_CMP; +def FCMP_CEQ_D : FP_CMP; +def FCMP_CUEQ_D : FP_CMP; +def FCMP_CLT_D : FP_CMP; +def FCMP_CULT_D : FP_CMP; +def FCMP_CLE_D : FP_CMP; +def FCMP_CULE_D : FP_CMP; +def FCMP_CNE_D : FP_CMP; +def FCMP_COR_D : FP_CMP; +def FCMP_CUNE_D : FP_CMP; +def FCMP_SAF_D : FP_CMP; +def FCMP_SUN_D : FP_CMP; +def FCMP_SEQ_D : FP_CMP; +def FCMP_SUEQ_D : FP_CMP; +def FCMP_SLT_D : FP_CMP; +def FCMP_SULT_D : FP_CMP; +def FCMP_SLE_D : FP_CMP; +def FCMP_SULE_D : FP_CMP; +def FCMP_SNE_D : FP_CMP; +def FCMP_SOR_D : FP_CMP; +def FCMP_SUNE_D : FP_CMP; + +// 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/LoongArchInstrInfoF.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfoF.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfoF.td @@ -0,0 +1,197 @@ +//=-- 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. +// +//===----------------------------------------------------------------------===// + +include "LoongArchInstrFormatsF.td" + +//===----------------------------------------------------------------------===// +// Instruction class templates +//===----------------------------------------------------------------------===// + +class FP_ALU_2R op, string opstr, RegisterClass rc> + : FPFmt2R; + +class FP_ALU_3R op, string opstr, RegisterClass rc> + : FPFmt3R; + +class FP_ALU_4R op, string opstr, RegisterClass rc> + : FPFmt4R; + +class FPCMPOpc value> { + bits<12> val = value; +} + +class FPCMPCond value> { + bits<5> val = value; +} + +class FP_CMP + : FPFmtFCMP; + +class FP_CONV op, string opstr, RegisterClass rcd, RegisterClass rcs> + : FPFmt2R; + +class FP_MOV op, string opstr, RegisterClass rcd, RegisterClass rcs> + : FPFmtMOV; + +class FP_SEL op, string opstr, RegisterClass rc> + : FPFmtFSEL; + +class FP_BRANCH opcode, string opstr> + : FPFmtBR { + let isBranch = 1; + let isTerminator = 1; +} + +let mayLoad = 1 in { +class FP_LOAD_3R op, string opstr, RegisterClass rc> + : FPFmtMEM; +class FP_LOAD_2RI12 op, string opstr, RegisterClass rc> + : FPFmt2RI12; +} // mayLoad = 1 + +let mayStore = 1 in { +class FP_STORE_3R op, string opstr, RegisterClass rc> + : FPFmtMEM; +class FP_STORE_2RI12 op, string opstr, RegisterClass rc> + : FPFmt2RI12; +} // 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>; + +//===----------------------------------------------------------------------===// +// 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; +def FCMP_CUN_S : FP_CMP; +def FCMP_CEQ_S : FP_CMP; +def FCMP_CUEQ_S : FP_CMP; +def FCMP_CLT_S : FP_CMP; +def FCMP_CULT_S : FP_CMP; +def FCMP_CLE_S : FP_CMP; +def FCMP_CULE_S : FP_CMP; +def FCMP_CNE_S : FP_CMP; +def FCMP_COR_S : FP_CMP; +def FCMP_CUNE_S : FP_CMP; +def FCMP_SAF_S : FP_CMP; +def FCMP_SUN_S : FP_CMP; +def FCMP_SEQ_S : FP_CMP; +def FCMP_SUEQ_S : FP_CMP; +def FCMP_SLT_S : FP_CMP; +def FCMP_SULT_S : FP_CMP; +def FCMP_SLE_S : FP_CMP; +def FCMP_SULE_S : FP_CMP; +def FCMP_SNE_S : FP_CMP; +def FCMP_SOR_S : FP_CMP; +def FCMP_SUNE_S : FP_CMP; + +// 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/LoongArchRegisterInfo.td b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td --- a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td @@ -142,3 +142,18 @@ // 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; + +def CFR : RegisterClass<"LoongArch", [i32], 32, (sequence "FCC%u", 0, 7)>; + +// Control and status registers + +foreach I = 0-3 in +def FCSR#I : LoongArchReg; + +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 --- /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 --- /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 --- /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 --- /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 --- /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 --- /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 --- /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 --- /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 --- /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 --- /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 --- /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 --- /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 --- /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 --- /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 --- /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 --- /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 --- 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 @@ 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