Skip to content

Commit 3a49ad7

Browse files
committed
[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
1 parent 88bb252 commit 3a49ad7

25 files changed

+1397
-39
lines changed

llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/MC/MCParser/MCAsmLexer.h"
1515
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
1616
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
17+
#include "llvm/MC/MCRegisterInfo.h"
1718
#include "llvm/MC/MCStreamer.h"
1819
#include "llvm/MC/MCSubtargetInfo.h"
1920
#include "llvm/MC/TargetRegistry.h"
@@ -42,6 +43,9 @@ class LoongArchAsmParser : public MCTargetAsmParser {
4243
uint64_t &ErrorInfo,
4344
bool MatchingInlineAsm) override;
4445

46+
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
47+
unsigned Kind) override;
48+
4549
bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
4650
int64_t Lower, int64_t Upper, Twine Msg);
4751

@@ -110,6 +114,7 @@ class LoongArchOperand : public MCParsedAsmOperand {
110114
bool isReg() const override { return Kind == KindTy::Register; }
111115
bool isImm() const override { return Kind == KindTy::Immediate; }
112116
bool isMem() const override { return false; }
117+
void setReg(MCRegister PhysReg) { Reg.RegNum = PhysReg; }
113118

114119
static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
115120
if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
@@ -245,9 +250,22 @@ class LoongArchOperand : public MCParsedAsmOperand {
245250
#define GET_MNEMONIC_SPELL_CHECKER
246251
#include "LoongArchGenAsmMatcher.inc"
247252

253+
static MCRegister convertFPR32ToFPR64(MCRegister Reg) {
254+
assert(Reg >= LoongArch::F0 && Reg <= LoongArch::F31 && "Invalid register");
255+
return Reg - LoongArch::F0 + LoongArch::F0_64;
256+
}
257+
258+
// Attempts to match Name as a register (either using the default name or
259+
// alternative ABI names), setting RegNo to the matching register. Upon
260+
// failure, returns true and sets RegNo to 0.
248261
static bool matchRegisterNameHelper(MCRegister &RegNo, StringRef Name) {
249262
RegNo = MatchRegisterName(Name);
250-
263+
// The 32-bit and 64-bit FPRs have the same asm name. Check that the initial
264+
// match always matches the 32-bit variant, and not the 64-bit one.
265+
assert(!(RegNo >= LoongArch::F0_64 && RegNo <= LoongArch::F31_64));
266+
// The default FPR register class is based on the tablegen enum ordering.
267+
static_assert(LoongArch::F0 < LoongArch::F0_64,
268+
"FPR matching must be updated");
251269
if (RegNo == LoongArch::NoRegister)
252270
RegNo = MatchRegisterAltName(Name);
253271

@@ -351,6 +369,25 @@ bool LoongArchAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
351369
return false;
352370
}
353371

372+
unsigned
373+
LoongArchAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
374+
unsigned Kind) {
375+
LoongArchOperand &Op = static_cast<LoongArchOperand &>(AsmOp);
376+
if (!Op.isReg())
377+
return Match_InvalidOperand;
378+
379+
MCRegister Reg = Op.getReg();
380+
// As the parser couldn't differentiate an FPR32 from an FPR64, coerce the
381+
// register from FPR32 to FPR64 if necessary.
382+
if (LoongArchMCRegisterClasses[LoongArch::FPR32RegClassID].contains(Reg) &&
383+
Kind == MCK_FPR64) {
384+
Op.setReg(convertFPR32ToFPR64(Reg));
385+
return Match_Success;
386+
}
387+
388+
return Match_InvalidOperand;
389+
}
390+
354391
bool LoongArchAsmParser::generateImmOutOfRangeError(
355392
OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
356393
Twine Msg = "immediate must be an integer in the range") {

llvm/lib/Target/LoongArch/Disassembler/LoongArchDisassembler.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,42 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
6464
return MCDisassembler::Success;
6565
}
6666

67+
static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,
68+
uint64_t Address,
69+
const MCDisassembler *Decoder) {
70+
if (RegNo >= 32)
71+
return MCDisassembler::Fail;
72+
Inst.addOperand(MCOperand::createReg(LoongArch::F0 + RegNo));
73+
return MCDisassembler::Success;
74+
}
75+
76+
static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo,
77+
uint64_t Address,
78+
const MCDisassembler *Decoder) {
79+
if (RegNo >= 32)
80+
return MCDisassembler::Fail;
81+
Inst.addOperand(MCOperand::createReg(LoongArch::F0_64 + RegNo));
82+
return MCDisassembler::Success;
83+
}
84+
85+
static DecodeStatus DecodeCFRRegisterClass(MCInst &Inst, uint64_t RegNo,
86+
uint64_t Address,
87+
const MCDisassembler *Decoder) {
88+
if (RegNo >= 8)
89+
return MCDisassembler::Fail;
90+
Inst.addOperand(MCOperand::createReg(LoongArch::FCC0 + RegNo));
91+
return MCDisassembler::Success;
92+
}
93+
94+
static DecodeStatus DecodeFCSRRegisterClass(MCInst &Inst, uint64_t RegNo,
95+
uint64_t Address,
96+
const MCDisassembler *Decoder) {
97+
if (RegNo >= 4)
98+
return MCDisassembler::Fail;
99+
Inst.addOperand(MCOperand::createReg(LoongArch::FCSR0 + RegNo));
100+
return MCDisassembler::Success;
101+
}
102+
67103
template <unsigned N, int P = 0>
68104
static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
69105
int64_t Address,
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//=-- LoongArchInstrInfoF.td - Single-Precision Float instr --*- tablegen -*-=//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file describes the baisc single-precision floating-point instructions.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
//===----------------------------------------------------------------------===//
14+
// Instructions
15+
//===----------------------------------------------------------------------===//
16+
17+
let Predicates = [HasBasicF] in {
18+
19+
// Arithmetic Operation Instructions
20+
def FADD_S : FP_ALU_3R<0b00000001000000001, "fadd.s", FPR32>;
21+
def FSUB_S : FP_ALU_3R<0b00000001000000101, "fsub.s", FPR32>;
22+
def FMUL_S : FP_ALU_3R<0b00000001000001001, "fmul.s", FPR32>;
23+
def FDIV_S : FP_ALU_3R<0b00000001000001101, "fdiv.s", FPR32>;
24+
def FMADD_S : FP_ALU_4R<0b000010000001, "fmadd.s", FPR32>;
25+
def FMSUB_S : FP_ALU_4R<0b000010000101, "fmsub.s", FPR32>;
26+
def FNMADD_S : FP_ALU_4R<0b000010001001, "fnmadd.s", FPR32>;
27+
def FNMSUB_S : FP_ALU_4R<0b000010001101, "fnmsub.s", FPR32>;
28+
def FMAX_S : FP_ALU_3R<0b00000001000010001, "fmax.s", FPR32>;
29+
def FMIN_S : FP_ALU_3R<0b00000001000010101, "fmin.s", FPR32>;
30+
def FMAXA_S : FP_ALU_3R<0b00000001000011001, "fmaxa.s", FPR32>;
31+
def FMINA_S : FP_ALU_3R<0b00000001000011101, "fmina.s", FPR32>;
32+
def FABS_S : FP_ALU_2R<0b0000000100010100000001, "fabs.s", FPR32>;
33+
def FNEG_S : FP_ALU_2R<0b0000000100010100000101, "fneg.s", FPR32>;
34+
def FSQRT_S : FP_ALU_2R<0b0000000100010100010001, "fsqrt.s", FPR32>;
35+
def FRECIP_S : FP_ALU_2R<0b0000000100010100010101, "frecip.s", FPR32>;
36+
def FRSQRT_S : FP_ALU_2R<0b0000000100010100011001, "frsqrt.s", FPR32>;
37+
def FSCALEB_S : FP_ALU_3R<0b00000001000100001, "fscaleb.s", FPR32>;
38+
def FLOGB_S : FP_ALU_2R<0b0000000100010100001001, "flogb.s", FPR32>;
39+
def FCOPYSIGN_S : FP_ALU_3R<0b00000001000100101, "fcopysign.s", FPR32>;
40+
def FCLASS_S : FP_ALU_2R<0b0000000100010100001101, "fclass.s", FPR32>;
41+
42+
43+
// Comparison Instructions
44+
def FCMP_CAF_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CAF, "fcmp.caf.s", FPR32>;
45+
def FCMP_CUN_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CUN, "fcmp.cun.s", FPR32>;
46+
def FCMP_CEQ_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CEQ, "fcmp.ceq.s", FPR32>;
47+
def FCMP_CUEQ_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CUEQ, "fcmp.cueq.s", FPR32>;
48+
def FCMP_CLT_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CLT, "fcmp.clt.s", FPR32>;
49+
def FCMP_CULT_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CULT, "fcmp.cult.s", FPR32>;
50+
def FCMP_CLE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CLE, "fcmp.cle.s", FPR32>;
51+
def FCMP_CULE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CULE, "fcmp.cule.s", FPR32>;
52+
def FCMP_CNE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CNE, "fcmp.cne.s", FPR32>;
53+
def FCMP_COR_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_COR, "fcmp.cor.s", FPR32>;
54+
def FCMP_CUNE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_CUNE, "fcmp.cune.s", FPR32>;
55+
def FCMP_SAF_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SAF, "fcmp.saf.s", FPR32>;
56+
def FCMP_SUN_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SUN, "fcmp.sun.s", FPR32>;
57+
def FCMP_SEQ_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SEQ, "fcmp.seq.s", FPR32>;
58+
def FCMP_SUEQ_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SUEQ, "fcmp.sueq.s", FPR32>;
59+
def FCMP_SLT_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SLT, "fcmp.slt.s", FPR32>;
60+
def FCMP_SULT_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SULT, "fcmp.sult.s", FPR32>;
61+
def FCMP_SLE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SLE, "fcmp.sle.s", FPR32>;
62+
def FCMP_SULE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SULE, "fcmp.sule.s", FPR32>;
63+
def FCMP_SNE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SNE, "fcmp.sne.s", FPR32>;
64+
def FCMP_SOR_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SOR, "fcmp.sor.s", FPR32>;
65+
def FCMP_SUNE_S : FP_CMP<FPCMP_OPC_S, FPCMP_COND_SUNE, "fcmp.sune.s", FPR32>;
66+
67+
// Conversion Instructions
68+
def FFINT_S_W : FP_CONV<0b0000000100011101000100, "ffint.s.w", FPR32, FPR32>;
69+
def FTINT_W_S : FP_CONV<0b0000000100011011000001, "ftint.w.s", FPR32, FPR32>;
70+
def FTINTRM_W_S : FP_CONV<0b0000000100011010000001, "ftintrm.w.s", FPR32,
71+
FPR32>;
72+
def FTINTRP_W_S : FP_CONV<0b0000000100011010010001, "ftintrp.w.s", FPR32,
73+
FPR32>;
74+
def FTINTRZ_W_S : FP_CONV<0b0000000100011010100001, "ftintrz.w.s", FPR32,
75+
FPR32>;
76+
def FTINTRNE_W_S : FP_CONV<0b0000000100011010110001, "ftintrne.w.s", FPR32,
77+
FPR32>;
78+
def FRINT_S : FP_CONV<0b0000000100011110010001, "frint.s", FPR32, FPR32>;
79+
80+
// Move Instructions
81+
def FSEL_S : FP_SEL<0b00001101000000, "fsel", FPR32>;
82+
def FMOV_S : FP_MOV<0b0000000100010100100101, "fmov.s", FPR32, FPR32>;
83+
def MOVGR2FR_W : FP_MOV<0b0000000100010100101001, "movgr2fr.w", FPR32, GPR>;
84+
def MOVFR2GR_S : FP_MOV<0b0000000100010100101101, "movfr2gr.s", GPR, FPR32>;
85+
def MOVGR2FCSR : FP_MOV<0b0000000100010100110000, "movgr2fcsr", FCSR, GPR>;
86+
def MOVFCSR2GR : FP_MOV<0b0000000100010100110010, "movfcsr2gr", GPR, FCSR>;
87+
def MOVFR2CF_S : FP_MOV<0b0000000100010100110100, "movfr2cf", CFR, FPR32>;
88+
def MOVCF2FR_S : FP_MOV<0b0000000100010100110101, "movcf2fr", FPR32, CFR>;
89+
def MOVGR2CF : FP_MOV<0b0000000100010100110110, "movgr2cf", CFR, GPR>;
90+
def MOVCF2GR : FP_MOV<0b0000000100010100110111, "movcf2gr", GPR, CFR>;
91+
92+
// Branch Instructions
93+
def BCEQZ : FP_BRANCH<0b01001000, "bceqz">;
94+
def BCNEZ : FP_BRANCH<0b01001001, "bcnez">;
95+
96+
// Common Memory Access Instructions
97+
def FLD_S : FP_LOAD_2RI12<0b0010101100, "fld.s", FPR32>;
98+
def FST_S : FP_STORE_2RI12<0b0010101101, "fst.s", FPR32>;
99+
def FLDX_S : FP_LOAD_3R<0b00111000001100000, "fldx.s", FPR32>;
100+
def FSTX_S : FP_STORE_3R<0b00111000001110000, "fstx.s", FPR32>;
101+
102+
// Bound Check Memory Access Instructions
103+
def FLDGT_S : FP_LOAD_3R<0b00111000011101000, "fldgt.s", FPR32>;
104+
def FLDLE_S : FP_LOAD_3R<0b00111000011101010, "fldle.s", FPR32>;
105+
def FSTGT_S : FP_STORE_3R<0b00111000011101100, "fstgt.s", FPR32>;
106+
def FSTLE_S : FP_STORE_3R<0b00111000011101110, "fstle.s", FPR32>;
107+
108+
} // Predicates = [HasBasicF]
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//=-- LoongArchInstrInfoD.td - Double-Precision Float instr -*- tablegen -*-==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file describes the basic double-precision floating-point instructions.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
//===----------------------------------------------------------------------===//
14+
// Instructions
15+
//===----------------------------------------------------------------------===//
16+
17+
let Predicates = [HasBasicD] in {
18+
19+
// Arithmetic Operation Instructions
20+
def FADD_D : FP_ALU_3R<0b00000001000000010, "fadd.d", FPR64>;
21+
def FSUB_D : FP_ALU_3R<0b00000001000000110, "fsub.d", FPR64>;
22+
def FMUL_D : FP_ALU_3R<0b00000001000001010, "fmul.d", FPR64>;
23+
def FDIV_D : FP_ALU_3R<0b00000001000001110, "fdiv.d", FPR64>;
24+
def FMADD_D : FP_ALU_4R<0b000010000010, "fmadd.d", FPR64>;
25+
def FMSUB_D : FP_ALU_4R<0b000010000110, "fmsub.d", FPR64>;
26+
def FNMADD_D : FP_ALU_4R<0b000010001010, "fnmadd.d", FPR64>;
27+
def FNMSUB_D : FP_ALU_4R<0b000010001110, "fnmsub.d", FPR64>;
28+
def FMAX_D : FP_ALU_3R<0b00000001000010010, "fmax.d", FPR64>;
29+
def FMIN_D : FP_ALU_3R<0b00000001000010110, "fmin.d", FPR64>;
30+
def FMAXA_D : FP_ALU_3R<0b00000001000011010, "fmaxa.d", FPR64>;
31+
def FMINA_D : FP_ALU_3R<0b00000001000011110, "fmina.d", FPR64>;
32+
def FABS_D : FP_ALU_2R<0b0000000100010100000010, "fabs.d", FPR64>;
33+
def FNEG_D : FP_ALU_2R<0b0000000100010100000110, "fneg.d", FPR64>;
34+
def FSQRT_D : FP_ALU_2R<0b0000000100010100010010, "fsqrt.d", FPR64>;
35+
def FRECIP_D : FP_ALU_2R<0b0000000100010100010110, "frecip.d", FPR64>;
36+
def FRSQRT_D : FP_ALU_2R<0b0000000100010100011010, "frsqrt.d", FPR64>;
37+
def FSCALEB_D : FP_ALU_3R<0b00000001000100010, "fscaleb.d", FPR64>;
38+
def FLOGB_D : FP_ALU_2R<0b0000000100010100001010, "flogb.d", FPR64>;
39+
def FCOPYSIGN_D : FP_ALU_3R<0b00000001000100110, "fcopysign.d", FPR64>;
40+
def FCLASS_D : FP_ALU_2R<0b0000000100010100001110, "fclass.d", FPR64>;
41+
42+
// Comparison Instructions
43+
def FCMP_CAF_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CAF, "fcmp.caf.d", FPR32>;
44+
def FCMP_CUN_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CUN, "fcmp.cun.d", FPR32>;
45+
def FCMP_CEQ_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CEQ, "fcmp.ceq.d", FPR32>;
46+
def FCMP_CUEQ_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CUEQ, "fcmp.cueq.d", FPR32>;
47+
def FCMP_CLT_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CLT, "fcmp.clt.d", FPR32>;
48+
def FCMP_CULT_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CULT, "fcmp.cult.d", FPR32>;
49+
def FCMP_CLE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CLE, "fcmp.cle.d", FPR32>;
50+
def FCMP_CULE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CULE, "fcmp.cule.d", FPR32>;
51+
def FCMP_CNE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CNE, "fcmp.cne.d", FPR32>;
52+
def FCMP_COR_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_COR, "fcmp.cor.d", FPR32>;
53+
def FCMP_CUNE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_CUNE, "fcmp.cune.d", FPR32>;
54+
def FCMP_SAF_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SAF, "fcmp.saf.d", FPR32>;
55+
def FCMP_SUN_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SUN, "fcmp.sun.d", FPR32>;
56+
def FCMP_SEQ_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SEQ, "fcmp.seq.d", FPR32>;
57+
def FCMP_SUEQ_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SUEQ, "fcmp.sueq.d", FPR32>;
58+
def FCMP_SLT_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SLT, "fcmp.slt.d", FPR32>;
59+
def FCMP_SULT_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SULT, "fcmp.sult.d", FPR32>;
60+
def FCMP_SLE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SLE, "fcmp.sle.d", FPR32>;
61+
def FCMP_SULE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SULE, "fcmp.sule.d", FPR32>;
62+
def FCMP_SNE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SNE, "fcmp.sne.d", FPR32>;
63+
def FCMP_SOR_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SOR, "fcmp.sor.d", FPR32>;
64+
def FCMP_SUNE_D : FP_CMP<FPCMP_OPC_D, FPCMP_COND_SUNE, "fcmp.sune.d", FPR32>;
65+
66+
// Conversion Instructions
67+
def FFINT_S_L : FP_CONV<0b0000000100011101000110, "ffint.s.l", FPR32, FPR64>;
68+
def FTINT_L_S : FP_CONV<0b0000000100011011001001, "ftint.l.s", FPR64, FPR32>;
69+
def FTINTRM_L_S : FP_CONV<0b0000000100011010001001, "ftintrm.l.s", FPR64,
70+
FPR32>;
71+
def FTINTRP_L_S : FP_CONV<0b0000000100011010011001, "ftintrp.l.s", FPR64,
72+
FPR32>;
73+
def FTINTRZ_L_S : FP_CONV<0b0000000100011010101001, "ftintrz.l.s", FPR64,
74+
FPR32>;
75+
def FTINTRNE_L_S : FP_CONV<0b0000000100011010111001, "ftintrne.l.s", FPR64,
76+
FPR32>;
77+
def FCVT_S_D : FP_CONV<0b0000000100011001000110, "fcvt.s.d", FPR32, FPR64>;
78+
def FCVT_D_S : FP_CONV<0b0000000100011001001001, "fcvt.d.s", FPR64, FPR32>;
79+
def FFINT_D_W : FP_CONV<0b0000000100011101001000, "ffint.d.w", FPR64, FPR32>;
80+
def FFINT_D_L : FP_CONV<0b0000000100011101001010, "ffint.d.l", FPR64, FPR64>;
81+
def FTINT_W_D : FP_CONV<0b0000000100011011000010, "ftint.w.d", FPR32, FPR64>;
82+
def FTINT_L_D : FP_CONV<0b0000000100011011001010, "ftint.l.d", FPR64, FPR64>;
83+
def FTINTRM_W_D : FP_CONV<0b0000000100011010000010, "ftintrm.w.d", FPR32,
84+
FPR64>;
85+
def FTINTRM_L_D : FP_CONV<0b0000000100011010001010, "ftintrm.l.d", FPR64,
86+
FPR64>;
87+
def FTINTRP_W_D : FP_CONV<0b0000000100011010010010, "ftintrp.w.d", FPR32,
88+
FPR64>;
89+
def FTINTRP_L_D : FP_CONV<0b0000000100011010011010, "ftintrp.l.d", FPR64,
90+
FPR64>;
91+
def FTINTRZ_W_D : FP_CONV<0b0000000100011010100010, "ftintrz.w.d", FPR32,
92+
FPR64>;
93+
def FTINTRZ_L_D : FP_CONV<0b0000000100011010101010, "ftintrz.l.d", FPR64,
94+
FPR64>;
95+
def FTINTRNE_W_D : FP_CONV<0b0000000100011010110010, "ftintrne.w.d", FPR32,
96+
FPR64>;
97+
def FTINTRNE_L_D : FP_CONV<0b0000000100011010111010, "ftintrne.l.d", FPR64,
98+
FPR64>;
99+
def FRINT_D : FP_CONV<0b0000000100011110010010, "frint.d", FPR64, FPR64>;
100+
101+
// Move Instructions
102+
def FMOV_D : FP_MOV<0b0000000100010100100110, "fmov.d", FPR64, FPR64>;
103+
def MOVFRH2GR_S : FP_MOV<0b0000000100010100101111, "movfrh2gr.s", GPR, FPR64>;
104+
let isCodeGenOnly = 1 in {
105+
def MOVFR2GR_S_64 : FP_MOV<0b0000000100010100101101, "movfr2gr.s", GPR, FPR64>;
106+
def FSEL_D : FP_SEL<0b00001101000000, "fsel", FPR64>;
107+
} // isCodeGenOnly = 1
108+
let Constraints = "$dst = $out" in {
109+
def MOVGR2FRH_W : FPFmtMOV<0b0000000100010100101011, (outs FPR64:$out),
110+
(ins FPR64:$dst, GPR:$src), "movgr2frh.w",
111+
"$dst, $src">;
112+
} // Constraints = "$dst = $out"
113+
114+
// Common Memory Access Instructions
115+
def FLD_D : FP_LOAD_2RI12<0b0010101110, "fld.d", FPR64>;
116+
def FST_D : FP_STORE_2RI12<0b0010101111, "fst.d", FPR64>;
117+
def FLDX_D : FP_LOAD_3R<0b00111000001101000, "fldx.d", FPR64>;
118+
def FSTX_D : FP_STORE_3R<0b00111000001111000, "fstx.d", FPR64>;
119+
120+
// Bound Check Memory Access Instructions
121+
def FLDGT_D : FP_LOAD_3R<0b00111000011101001, "fldgt.d", FPR64>;
122+
def FLDLE_D : FP_LOAD_3R<0b00111000011101011, "fldle.d", FPR64>;
123+
def FSTGT_D : FP_STORE_3R<0b00111000011101101, "fstgt.d", FPR64>;
124+
def FSTLE_D : FP_STORE_3R<0b00111000011101111, "fstle.d", FPR64>;
125+
126+
} // Predicates = [HasBasicD]
127+
128+
// Instructions only available on LA64
129+
let Predicates = [HasBasicD, IsLA64] in {
130+
def MOVGR2FR_D : FP_MOV<0b0000000100010100101010, "movgr2fr.d", FPR64, GPR>;
131+
def MOVFR2GR_D : FP_MOV<0b0000000100010100101110, "movfr2gr.d", GPR, FPR64>;
132+
} // Predicates = [HasBasicD, IsLA64]
133+

0 commit comments

Comments
 (0)