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