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