1//===-- RISCVInstrInfoZfa.td - RISC-V 'Zfa' instructions ---*- 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 RISC-V instructions from the standard 'Zfa'
10// additional floating-point extension, version 0.1.
11// This version is still experimental as the 'Zfa' extension hasn't been
12// ratified yet.
13//
14//===----------------------------------------------------------------------===//
15
16//===----------------------------------------------------------------------===//
17// Operand and SDNode transformation definitions.
18//===----------------------------------------------------------------------===//
19
20// 5-bit floating-point immediate encodings.
21def LoadFPImmOperand : AsmOperandClass {
22  let Name = "LoadFPImm";
23  let ParserMethod = "parseFPImm";
24  let RenderMethod = "addFPImmOperands";
25  let DiagnosticType = "InvalidLoadFPImm";
26}
27
28def loadfpimm : Operand<XLenVT> {
29  let ParserMatchClass = LoadFPImmOperand;
30  let PrintMethod = "printFPImmOperand";
31}
32
33def RTZArg : AsmOperandClass {
34  let Name = "RTZArg";
35  let RenderMethod = "addFRMArgOperands";
36  let DiagnosticType = "InvalidRTZArg";
37  let ParserMethod = "parseFRMArg";
38}
39
40def rtzarg : Operand<XLenVT> {
41  let ParserMatchClass = RTZArg;
42  let PrintMethod = "printFRMArg";
43  let DecoderMethod = "decodeFRMArg";
44}
45
46//===----------------------------------------------------------------------===//
47// Instruction class templates
48//===----------------------------------------------------------------------===//
49
50let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in
51class FPBinaryOp_rr<bits<7> funct7, bits<3> funct3, DAGOperand rdty,
52                    DAGOperand rsty, string opcodestr>
53    : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd),
54              (ins rsty:$rs1, rsty:$rs2), opcodestr, "$rd, $rs1, $rs2">;
55
56let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
57class FPUnaryOp_imm<bits<7> funct7, bits<5> rs2val, bits<3> funct3,
58                    dag outs, dag ins, string opcodestr, string argstr>
59    : RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
60  bits<5> imm;
61  bits<5> rd;
62
63  let Inst{31-25} = funct7;
64  let Inst{24-20} = rs2val;
65  let Inst{19-15} = imm;
66  let Inst{14-12} = funct3;
67  let Inst{11-7} = rd;
68  let Inst{6-0} = OPC_OP_FP.Value;
69}
70
71let hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1,
72    UseNamedOperandTable = 1, hasPostISelHook = 1 in
73class FPUnaryOp_r_rtz<bits<7> funct7, bits<5> rs2val, DAGOperand rdty,
74                      DAGOperand rs1ty, string opcodestr>
75    : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),
76                 (ins rs1ty:$rs1, rtzarg:$frm), opcodestr,
77                  "$rd, $rs1$frm"> {
78  let rs2 = rs2val;
79}
80
81//===----------------------------------------------------------------------===//
82// Instructions
83//===----------------------------------------------------------------------===//
84
85let Predicates = [HasStdExtZfa] in {
86let isReMaterializable = 1, isAsCheapAsAMove = 1 in
87def FLI_S : FPUnaryOp_imm<0b1111000, 0b00001, 0b000, (outs FPR32:$rd),
88            (ins loadfpimm:$imm), "fli.s", "$rd, $imm">,
89            Sched<[WriteFLI32]>;
90
91let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in {
92def FMINM_S: FPALU_rr<0b0010100, 0b010, "fminm.s", FPR32, Commutable=1>;
93def FMAXM_S: FPALU_rr<0b0010100, 0b011, "fmaxm.s", FPR32, Commutable=1>;
94}
95
96def FROUND_S : FPUnaryOp_r_frm<0b0100000, 0b00100, FPR32, FPR32, "fround.s">,
97               Sched<[WriteFRoundF32, ReadFRoundF32]>;
98def FROUNDNX_S : FPUnaryOp_r_frm<0b0100000, 0b00101, FPR32, FPR32, "froundnx.s">,
99                 Sched<[WriteFRoundF32, ReadFRoundF32]>;
100
101let SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in {
102def FLTQ_S : FPCmp_rr<0b1010000, 0b101, "fltq.s", FPR32>;
103def FLEQ_S : FPCmp_rr<0b1010000, 0b100, "fleq.s", FPR32>;
104}
105} // Predicates = [HasStdExtZfa]
106
107let Predicates = [HasStdExtZfa, HasStdExtD] in {
108let isReMaterializable = 1, isAsCheapAsAMove = 1 in
109def FLI_D : FPUnaryOp_imm<0b1111001, 0b00001, 0b000, (outs FPR64:$rd),
110            (ins loadfpimm:$imm), "fli.d", "$rd, $imm">,
111            Sched<[WriteFLI64]>;
112
113let SchedRW = [WriteFMinMax64, ReadFMinMax64, ReadFMinMax64] in {
114def FMINM_D: FPALU_rr<0b0010101, 0b010, "fminm.d", FPR64, Commutable=1>;
115def FMAXM_D: FPALU_rr<0b0010101, 0b011, "fmaxm.d", FPR64, Commutable=1>;
116}
117
118def FROUND_D : FPUnaryOp_r_frm<0b0100001, 0b00100, FPR64, FPR64, "fround.d">,
119               Sched<[WriteFRoundF64, ReadFRoundF64]>;
120def FROUNDNX_D : FPUnaryOp_r_frm<0b0100001, 0b00101, FPR64, FPR64, "froundnx.d">,
121                 Sched<[WriteFRoundF64, ReadFRoundF64]>;
122
123def FCVTMOD_W_D
124    : FPUnaryOp_r_rtz<0b1100001, 0b01000, GPR, FPR64, "fcvtmod.w.d">,
125      Sched<[WriteFCvtF64ToI32, ReadFCvtF64ToI32]>;
126
127let SchedRW = [WriteFCmp64, ReadFCmp64, ReadFCmp64] in {
128def FLTQ_D : FPCmp_rr<0b1010001, 0b101, "fltq.d", FPR64>;
129def FLEQ_D : FPCmp_rr<0b1010001, 0b100, "fleq.d", FPR64>;
130}
131} // Predicates = [HasStdExtZfa, HasStdExtD]
132
133let Predicates = [HasStdExtZfa, HasStdExtD, IsRV32] in {
134let mayRaiseFPException = 0 in {
135def FMVH_X_D : FPUnaryOp_r<0b1110001, 0b00001, 0b000, GPR, FPR64, "fmvh.x.d">,
136               Sched<[WriteFMovF64ToI64, ReadFMovF64ToI64]>;
137def FMVP_D_X : FPBinaryOp_rr<0b1011001, 0b000, FPR64, GPR, "fmvp.d.x">,
138               Sched<[WriteFMovI64ToF64, ReadFMovI64ToF64]>;
139}
140
141let isCodeGenOnly = 1, mayRaiseFPException = 0 in
142def FMV_X_W_FPR64 : FPUnaryOp_r<0b1110000, 0b00000, 0b000, GPR, FPR64,
143                                "fmv.x.w">,
144                    Sched<[WriteFMovF64ToI64, ReadFMovF64ToI64]>;
145} // Predicates = [HasStdExtZfa, HasStdExtD, IsRV32]
146
147let Predicates = [HasStdExtZfa, HasStdExtZfhOrZvfh] in
148let isReMaterializable = 1, isAsCheapAsAMove = 1 in
149def FLI_H : FPUnaryOp_imm<0b1111010, 0b00001, 0b000, (outs FPR16:$rd),
150            (ins loadfpimm:$imm), "fli.h", "$rd, $imm">,
151            Sched<[WriteFLI16]>;
152
153let Predicates = [HasStdExtZfa, HasStdExtZfh] in {
154let SchedRW = [WriteFMinMax16, ReadFMinMax16, ReadFMinMax16] in {
155def FMINM_H: FPALU_rr<0b0010110, 0b010, "fminm.h", FPR16, Commutable=1>;
156def FMAXM_H: FPALU_rr<0b0010110, 0b011, "fmaxm.h", FPR16, Commutable=1>;
157}
158
159def FROUND_H : FPUnaryOp_r_frm<0b0100010, 0b00100, FPR16, FPR16, "fround.h">,
160               Sched<[WriteFRoundF16, ReadFRoundF16]>;
161def FROUNDNX_H : FPUnaryOp_r_frm<0b0100010, 0b00101, FPR16, FPR16, "froundnx.h">,
162                 Sched<[WriteFRoundF16, ReadFRoundF16]>;
163
164let SchedRW = [WriteFCmp16, ReadFCmp16, ReadFCmp16] in {
165def FLTQ_H : FPCmp_rr<0b1010010, 0b101, "fltq.h", FPR16>;
166def FLEQ_H : FPCmp_rr<0b1010010, 0b100, "fleq.h", FPR16>;
167}
168} // Predicates = [HasStdExtZfa, HasStdExtZfh]
169
170//===----------------------------------------------------------------------===//
171// Pseudo-instructions and codegen patterns
172//===----------------------------------------------------------------------===//
173
174let Predicates = [HasStdExtZfa] in {
175def : InstAlias<"fgtq.s $rd, $rs, $rt",
176                (FLTQ_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
177def : InstAlias<"fgeq.s $rd, $rs, $rt",
178                (FLEQ_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
179}
180
181let Predicates = [HasStdExtZfa, HasStdExtD] in {
182def : InstAlias<"fgtq.d $rd, $rs, $rt",
183                (FLTQ_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>;
184def : InstAlias<"fgeq.d $rd, $rs, $rt",
185                (FLEQ_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>;
186}
187
188let Predicates = [HasStdExtZfa, HasStdExtZfh] in {
189def : InstAlias<"fgtq.h $rd, $rs, $rt",
190                (FLTQ_H GPR:$rd, FPR16:$rt, FPR16:$rs), 0>;
191def : InstAlias<"fgeq.h $rd, $rs, $rt",
192                (FLEQ_H GPR:$rd, FPR16:$rt, FPR16:$rs), 0>;
193}
194
195//===----------------------------------------------------------------------===//
196// Codegen patterns
197//===----------------------------------------------------------------------===//
198
199let Predicates = [HasStdExtZfa] in {
200def: PatFprFpr<fminimum, FMINM_S, FPR32, f32>;
201def: PatFprFpr<fmaximum, FMAXM_S, FPR32, f32>;
202
203// frint rounds according to the current rounding mode and detects
204// inexact conditions.
205def: Pat<(any_frint FPR32:$rs1), (FROUNDNX_S FPR32:$rs1, FRM_DYN)>;
206
207// fnearbyint is like frint but does not detect inexact conditions.
208def: Pat<(any_fnearbyint FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_DYN)>;
209
210def: Pat<(any_fround FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RMM)>;
211def: Pat<(any_ffloor FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RDN)>;
212def: Pat<(any_fceil FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RUP)>;
213def: Pat<(any_ftrunc FPR32:$rs1), (FROUND_S FPR32:$rs1, FRM_RTZ)>;
214
215def: PatSetCC<FPR32, strict_fsetcc, SETLT, FLTQ_S, f32>;
216def: PatSetCC<FPR32, strict_fsetcc, SETOLT, FLTQ_S, f32>;
217def: PatSetCC<FPR32, strict_fsetcc, SETLE, FLEQ_S, f32>;
218def: PatSetCC<FPR32, strict_fsetcc, SETOLE, FLEQ_S, f32>;
219} // Predicates = [HasStdExtZfa]
220
221let Predicates = [HasStdExtZfa, HasStdExtD] in {
222def: PatFprFpr<fminimum, FMINM_D, FPR64, f64>;
223def: PatFprFpr<fmaximum, FMAXM_D, FPR64, f64>;
224
225// frint rounds according to the current rounding mode and detects
226// inexact conditions.
227def: Pat<(any_frint FPR64:$rs1), (FROUNDNX_D FPR64:$rs1, FRM_DYN)>;
228
229// fnearbyint is like frint but does not detect inexact conditions.
230def: Pat<(any_fnearbyint FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_DYN)>;
231
232def: Pat<(any_fround FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RMM)>;
233def: Pat<(any_froundeven FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RNE)>;
234def: Pat<(any_ffloor FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RDN)>;
235def: Pat<(any_fceil FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RUP)>;
236def: Pat<(any_ftrunc FPR64:$rs1), (FROUND_D FPR64:$rs1, FRM_RTZ)>;
237
238def: PatSetCC<FPR64, strict_fsetcc, SETLT, FLTQ_D, f64>;
239def: PatSetCC<FPR64, strict_fsetcc, SETOLT, FLTQ_D, f64>;
240def: PatSetCC<FPR64, strict_fsetcc, SETLE, FLEQ_D, f64>;
241def: PatSetCC<FPR64, strict_fsetcc, SETOLE, FLEQ_D, f64>;
242} // Predicates = [HasStdExtZfa, HasStdExtD]
243
244let Predicates = [HasStdExtZfa, HasStdExtD, IsRV32] in {
245def : Pat<(RISCVBuildPairF64 GPR:$rs1, GPR:$rs2),
246          (FMVP_D_X GPR:$rs1, GPR:$rs2)>;
247}
248
249let Predicates = [HasStdExtZfa, HasStdExtZfh] in {
250def: PatFprFpr<fminimum, FMINM_H, FPR16, f16>;
251def: PatFprFpr<fmaximum, FMAXM_H, FPR16, f16>;
252
253// frint rounds according to the current rounding mode and detects
254// inexact conditions.
255def: Pat<(f16 (any_frint FPR16:$rs1)), (FROUNDNX_H FPR16:$rs1, FRM_DYN)>;
256
257// fnearbyint is like frint but does not detect inexact conditions.
258def: Pat<(f16 (any_fnearbyint FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_DYN)>;
259
260def: Pat<(f16 (any_fround FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RMM)>;
261def: Pat<(f16 (any_froundeven FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RNE)>;
262def: Pat<(f16 (any_ffloor FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RDN)>;
263def: Pat<(f16 (any_fceil FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RUP)>;
264def: Pat<(f16 (any_ftrunc FPR16:$rs1)), (FROUND_H FPR16:$rs1, FRM_RTZ)>;
265
266def: PatSetCC<FPR16, strict_fsetcc, SETLT, FLTQ_H, f16>;
267def: PatSetCC<FPR16, strict_fsetcc, SETOLT, FLTQ_H, f16>;
268def: PatSetCC<FPR16, strict_fsetcc, SETLE, FLEQ_H, f16>;
269def: PatSetCC<FPR16, strict_fsetcc, SETOLE, FLEQ_H, f16>;
270} // Predicates = [HasStdExtZfa, HasStdExtZfh]
271