10b57cec5SDimitry Andric//===-- RISCVInstrInfoF.td - RISC-V 'F' instructions -------*- tablegen -*-===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file describes the RISC-V instructions from the standard 'F',
100b57cec5SDimitry Andric// Single-Precision Floating-Point instruction set extension.
110b57cec5SDimitry Andric//
120b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric// RISC-V specific DAG Nodes.
160b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric
180b57cec5SDimitry Andricdef SDT_RISCVFMV_W_X_RV64
190b57cec5SDimitry Andric    : SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i64>]>;
200b57cec5SDimitry Andricdef SDT_RISCVFMV_X_ANYEXTW_RV64
210b57cec5SDimitry Andric    : SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisVT<1, f32>]>;
220b57cec5SDimitry Andric
230b57cec5SDimitry Andricdef riscv_fmv_w_x_rv64
240b57cec5SDimitry Andric    : SDNode<"RISCVISD::FMV_W_X_RV64", SDT_RISCVFMV_W_X_RV64>;
250b57cec5SDimitry Andricdef riscv_fmv_x_anyextw_rv64
260b57cec5SDimitry Andric    : SDNode<"RISCVISD::FMV_X_ANYEXTW_RV64", SDT_RISCVFMV_X_ANYEXTW_RV64>;
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
290b57cec5SDimitry Andric// Operand and SDNode transformation definitions.
300b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric// Floating-point rounding mode
330b57cec5SDimitry Andric
340b57cec5SDimitry Andricdef FRMArg : AsmOperandClass {
350b57cec5SDimitry Andric  let Name = "FRMArg";
360b57cec5SDimitry Andric  let RenderMethod = "addFRMArgOperands";
370b57cec5SDimitry Andric  let DiagnosticType = "InvalidFRMArg";
380b57cec5SDimitry Andric}
390b57cec5SDimitry Andric
400b57cec5SDimitry Andricdef frmarg : Operand<XLenVT> {
410b57cec5SDimitry Andric  let ParserMatchClass = FRMArg;
420b57cec5SDimitry Andric  let PrintMethod = "printFRMArg";
430b57cec5SDimitry Andric  let DecoderMethod = "decodeFRMArg";
440b57cec5SDimitry Andric}
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
470b57cec5SDimitry Andric// Instruction class templates
480b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
490b57cec5SDimitry Andric
500b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
510b57cec5SDimitry Andricclass FPFMAS_rrr_frm<RISCVOpcode opcode, string opcodestr>
520b57cec5SDimitry Andric    : RVInstR4<0b00, opcode, (outs FPR32:$rd),
530b57cec5SDimitry Andric               (ins FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, frmarg:$funct3),
540b57cec5SDimitry Andric                opcodestr, "$rd, $rs1, $rs2, $rs3, $funct3">;
550b57cec5SDimitry Andric
560b57cec5SDimitry Andricclass FPFMASDynFrmAlias<FPFMAS_rrr_frm Inst, string OpcodeStr>
570b57cec5SDimitry Andric    : InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3",
580b57cec5SDimitry Andric                (Inst FPR32:$rd, FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>;
590b57cec5SDimitry Andric
600b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
610b57cec5SDimitry Andricclass FPALUS_rr<bits<7> funct7, bits<3> funct3, string opcodestr>
620b57cec5SDimitry Andric    : RVInstR<funct7, funct3, OPC_OP_FP, (outs FPR32:$rd),
635ffd83dbSDimitry Andric              (ins FPR32:$rs1, FPR32:$rs2), opcodestr, "$rd, $rs1, $rs2">;
640b57cec5SDimitry Andric
650b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
660b57cec5SDimitry Andricclass FPALUS_rr_frm<bits<7> funct7, string opcodestr>
670b57cec5SDimitry Andric    : RVInstRFrm<funct7, OPC_OP_FP, (outs FPR32:$rd),
680b57cec5SDimitry Andric                 (ins FPR32:$rs1, FPR32:$rs2, frmarg:$funct3), opcodestr,
690b57cec5SDimitry Andric                  "$rd, $rs1, $rs2, $funct3">;
700b57cec5SDimitry Andric
710b57cec5SDimitry Andricclass FPALUSDynFrmAlias<FPALUS_rr_frm Inst, string OpcodeStr>
720b57cec5SDimitry Andric    : InstAlias<OpcodeStr#" $rd, $rs1, $rs2",
730b57cec5SDimitry Andric                (Inst FPR32:$rd, FPR32:$rs1, FPR32:$rs2, 0b111)>;
740b57cec5SDimitry Andric
750b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
760b57cec5SDimitry Andricclass FPUnaryOp_r<bits<7> funct7, bits<3> funct3, RegisterClass rdty,
770b57cec5SDimitry Andric                RegisterClass rs1ty, string opcodestr>
780b57cec5SDimitry Andric    : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), (ins rs1ty:$rs1),
790b57cec5SDimitry Andric              opcodestr, "$rd, $rs1">;
800b57cec5SDimitry Andric
810b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
820b57cec5SDimitry Andricclass FPUnaryOp_r_frm<bits<7> funct7, RegisterClass rdty, RegisterClass rs1ty,
830b57cec5SDimitry Andric                      string opcodestr>
840b57cec5SDimitry Andric    : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd),
850b57cec5SDimitry Andric                 (ins rs1ty:$rs1, frmarg:$funct3), opcodestr,
860b57cec5SDimitry Andric                  "$rd, $rs1, $funct3">;
870b57cec5SDimitry Andric
880b57cec5SDimitry Andricclass FPUnaryOpDynFrmAlias<FPUnaryOp_r_frm Inst, string OpcodeStr,
890b57cec5SDimitry Andric                           RegisterClass rdty, RegisterClass rs1ty>
900b57cec5SDimitry Andric    : InstAlias<OpcodeStr#" $rd, $rs1",
910b57cec5SDimitry Andric                (Inst rdty:$rd, rs1ty:$rs1, 0b111)>;
920b57cec5SDimitry Andric
930b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
940b57cec5SDimitry Andricclass FPCmpS_rr<bits<3> funct3, string opcodestr>
950b57cec5SDimitry Andric    : RVInstR<0b1010000, funct3, OPC_OP_FP, (outs GPR:$rd),
9613138422SDimitry Andric              (ins FPR32:$rs1, FPR32:$rs2), opcodestr, "$rd, $rs1, $rs2">,
9713138422SDimitry Andric      Sched<[WriteFCmp32, ReadFCmp32, ReadFCmp32]>;
980b57cec5SDimitry Andric
990b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1000b57cec5SDimitry Andric// Instructions
1010b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in {
1040b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
1050b57cec5SDimitry Andricdef FLW : RVInstI<0b010, OPC_LOAD_FP, (outs FPR32:$rd),
1060b57cec5SDimitry Andric                  (ins GPR:$rs1, simm12:$imm12),
10713138422SDimitry Andric                   "flw", "$rd, ${imm12}(${rs1})">,
1085ffd83dbSDimitry Andric          Sched<[WriteFLD32, ReadFMemBase]>;
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric// Operands for stores are in the order srcreg, base, offset rather than
1110b57cec5SDimitry Andric// reflecting the order these fields are specified in the instruction
1120b57cec5SDimitry Andric// encoding.
1130b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
1140b57cec5SDimitry Andricdef FSW : RVInstS<0b010, OPC_STORE_FP, (outs),
1150b57cec5SDimitry Andric                  (ins FPR32:$rs2, GPR:$rs1, simm12:$imm12),
11613138422SDimitry Andric                   "fsw", "$rs2, ${imm12}(${rs1})">,
1175ffd83dbSDimitry Andric          Sched<[WriteFST32, ReadStoreData, ReadFMemBase]>;
1180b57cec5SDimitry Andric
11913138422SDimitry Andricdef FMADD_S  : FPFMAS_rrr_frm<OPC_MADD, "fmadd.s">,
12013138422SDimitry Andric               Sched<[WriteFMulAdd32, ReadFMulAdd32, ReadFMulAdd32, ReadFMulAdd32]>;
1210b57cec5SDimitry Andricdef          : FPFMASDynFrmAlias<FMADD_S, "fmadd.s">;
12213138422SDimitry Andricdef FMSUB_S  : FPFMAS_rrr_frm<OPC_MSUB, "fmsub.s">,
12313138422SDimitry Andric               Sched<[WriteFMulSub32, ReadFMulSub32, ReadFMulSub32, ReadFMulSub32]>;
1240b57cec5SDimitry Andricdef          : FPFMASDynFrmAlias<FMSUB_S, "fmsub.s">;
12513138422SDimitry Andricdef FNMSUB_S : FPFMAS_rrr_frm<OPC_NMSUB, "fnmsub.s">,
12613138422SDimitry Andric               Sched<[WriteFMulSub32, ReadFMulSub32, ReadFMulSub32, ReadFMulSub32]>;
1270b57cec5SDimitry Andricdef          : FPFMASDynFrmAlias<FNMSUB_S, "fnmsub.s">;
12813138422SDimitry Andricdef FNMADD_S : FPFMAS_rrr_frm<OPC_NMADD, "fnmadd.s">,
12913138422SDimitry Andric               Sched<[WriteFMulAdd32, ReadFMulAdd32, ReadFMulAdd32, ReadFMulAdd32]>;
1300b57cec5SDimitry Andricdef          : FPFMASDynFrmAlias<FNMADD_S, "fnmadd.s">;
1310b57cec5SDimitry Andric
13213138422SDimitry Andricdef FADD_S : FPALUS_rr_frm<0b0000000, "fadd.s">,
13313138422SDimitry Andric             Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>;
1340b57cec5SDimitry Andricdef        : FPALUSDynFrmAlias<FADD_S, "fadd.s">;
13513138422SDimitry Andricdef FSUB_S : FPALUS_rr_frm<0b0000100, "fsub.s">,
13613138422SDimitry Andric             Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>;
1370b57cec5SDimitry Andricdef        : FPALUSDynFrmAlias<FSUB_S, "fsub.s">;
13813138422SDimitry Andricdef FMUL_S : FPALUS_rr_frm<0b0001000, "fmul.s">,
13913138422SDimitry Andric             Sched<[WriteFMul32, ReadFMul32, ReadFMul32]>;
1400b57cec5SDimitry Andricdef        : FPALUSDynFrmAlias<FMUL_S, "fmul.s">;
14113138422SDimitry Andricdef FDIV_S : FPALUS_rr_frm<0b0001100, "fdiv.s">,
14213138422SDimitry Andric             Sched<[WriteFDiv32, ReadFDiv32, ReadFDiv32]>;
1430b57cec5SDimitry Andricdef        : FPALUSDynFrmAlias<FDIV_S, "fdiv.s">;
1440b57cec5SDimitry Andric
14513138422SDimitry Andricdef FSQRT_S : FPUnaryOp_r_frm<0b0101100, FPR32, FPR32, "fsqrt.s">,
14613138422SDimitry Andric              Sched<[WriteFSqrt32, ReadFSqrt32]> {
1470b57cec5SDimitry Andric  let rs2 = 0b00000;
1480b57cec5SDimitry Andric}
1490b57cec5SDimitry Andricdef         : FPUnaryOpDynFrmAlias<FSQRT_S, "fsqrt.s", FPR32, FPR32>;
1500b57cec5SDimitry Andric
1515ffd83dbSDimitry Andricdef FSGNJ_S  : FPALUS_rr<0b0010000, 0b000, "fsgnj.s">,
1525ffd83dbSDimitry Andric               Sched<[WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32]>;
1535ffd83dbSDimitry Andricdef FSGNJN_S : FPALUS_rr<0b0010000, 0b001, "fsgnjn.s">,
1545ffd83dbSDimitry Andric               Sched<[WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32]>;
1555ffd83dbSDimitry Andricdef FSGNJX_S : FPALUS_rr<0b0010000, 0b010, "fsgnjx.s">,
1565ffd83dbSDimitry Andric               Sched<[WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32]>;
1575ffd83dbSDimitry Andricdef FMIN_S   : FPALUS_rr<0b0010100, 0b000, "fmin.s">,
1585ffd83dbSDimitry Andric               Sched<[WriteFMinMax32, ReadFMinMax32, ReadFMinMax32]>;
1595ffd83dbSDimitry Andricdef FMAX_S   : FPALUS_rr<0b0010100, 0b001, "fmax.s">,
1605ffd83dbSDimitry Andric               Sched<[WriteFMinMax32, ReadFMinMax32, ReadFMinMax32]>;
1610b57cec5SDimitry Andric
16213138422SDimitry Andricdef FCVT_W_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.w.s">,
16313138422SDimitry Andric               Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]> {
1640b57cec5SDimitry Andric  let rs2 = 0b00000;
1650b57cec5SDimitry Andric}
1660b57cec5SDimitry Andricdef          : FPUnaryOpDynFrmAlias<FCVT_W_S, "fcvt.w.s", GPR, FPR32>;
1670b57cec5SDimitry Andric
16813138422SDimitry Andricdef FCVT_WU_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.wu.s">,
16913138422SDimitry Andric                Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]> {
1700b57cec5SDimitry Andric  let rs2 = 0b00001;
1710b57cec5SDimitry Andric}
1720b57cec5SDimitry Andricdef           : FPUnaryOpDynFrmAlias<FCVT_WU_S, "fcvt.wu.s", GPR, FPR32>;
1730b57cec5SDimitry Andric
17413138422SDimitry Andricdef FMV_X_W : FPUnaryOp_r<0b1110000, 0b000, GPR, FPR32, "fmv.x.w">,
17513138422SDimitry Andric              Sched<[WriteFMovF32ToI32, ReadFMovF32ToI32]> {
1760b57cec5SDimitry Andric  let rs2 = 0b00000;
1770b57cec5SDimitry Andric}
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andricdef FEQ_S : FPCmpS_rr<0b010, "feq.s">;
1800b57cec5SDimitry Andricdef FLT_S : FPCmpS_rr<0b001, "flt.s">;
1810b57cec5SDimitry Andricdef FLE_S : FPCmpS_rr<0b000, "fle.s">;
1820b57cec5SDimitry Andric
18313138422SDimitry Andricdef FCLASS_S : FPUnaryOp_r<0b1110000, 0b001, GPR, FPR32, "fclass.s">,
18413138422SDimitry Andric               Sched<[WriteFClass32, ReadFClass32]> {
1850b57cec5SDimitry Andric  let rs2 = 0b00000;
1860b57cec5SDimitry Andric}
1870b57cec5SDimitry Andric
18813138422SDimitry Andricdef FCVT_S_W : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.w">,
18913138422SDimitry Andric               Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]> {
1900b57cec5SDimitry Andric  let rs2 = 0b00000;
1910b57cec5SDimitry Andric}
1920b57cec5SDimitry Andricdef          : FPUnaryOpDynFrmAlias<FCVT_S_W, "fcvt.s.w", FPR32, GPR>;
1930b57cec5SDimitry Andric
19413138422SDimitry Andricdef FCVT_S_WU : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.wu">,
19513138422SDimitry Andric                Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]> {
1960b57cec5SDimitry Andric  let rs2 = 0b00001;
1970b57cec5SDimitry Andric}
1980b57cec5SDimitry Andricdef           : FPUnaryOpDynFrmAlias<FCVT_S_WU, "fcvt.s.wu", FPR32, GPR>;
1990b57cec5SDimitry Andric
20013138422SDimitry Andricdef FMV_W_X : FPUnaryOp_r<0b1111000, 0b000, FPR32, GPR, "fmv.w.x">,
20113138422SDimitry Andric              Sched<[WriteFMovI32ToF32, ReadFMovI32ToF32]> {
2020b57cec5SDimitry Andric  let rs2 = 0b00000;
2030b57cec5SDimitry Andric}
2040b57cec5SDimitry Andric} // Predicates = [HasStdExtF]
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV64] in {
20713138422SDimitry Andricdef FCVT_L_S  : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.l.s">,
20813138422SDimitry Andric                Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]> {
2090b57cec5SDimitry Andric  let rs2 = 0b00010;
2100b57cec5SDimitry Andric}
2110b57cec5SDimitry Andricdef           : FPUnaryOpDynFrmAlias<FCVT_L_S, "fcvt.l.s", GPR, FPR32>;
2120b57cec5SDimitry Andric
21313138422SDimitry Andricdef FCVT_LU_S  : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.lu.s">,
21413138422SDimitry Andric                 Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]> {
2150b57cec5SDimitry Andric  let rs2 = 0b00011;
2160b57cec5SDimitry Andric}
2170b57cec5SDimitry Andricdef            : FPUnaryOpDynFrmAlias<FCVT_LU_S, "fcvt.lu.s", GPR, FPR32>;
2180b57cec5SDimitry Andric
21913138422SDimitry Andricdef FCVT_S_L : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.l">,
22013138422SDimitry Andric               Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]> {
2210b57cec5SDimitry Andric  let rs2 = 0b00010;
2220b57cec5SDimitry Andric}
2230b57cec5SDimitry Andricdef          : FPUnaryOpDynFrmAlias<FCVT_S_L, "fcvt.s.l", FPR32, GPR>;
2240b57cec5SDimitry Andric
22513138422SDimitry Andricdef FCVT_S_LU : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.lu">,
22613138422SDimitry Andric                Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]> {
2270b57cec5SDimitry Andric  let rs2 = 0b00011;
2280b57cec5SDimitry Andric}
2290b57cec5SDimitry Andricdef           : FPUnaryOpDynFrmAlias<FCVT_S_LU, "fcvt.s.lu", FPR32, GPR>;
2300b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV64]
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2330b57cec5SDimitry Andric// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
2340b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in {
2370b57cec5SDimitry Andricdef : InstAlias<"flw $rd, (${rs1})",  (FLW FPR32:$rd,  GPR:$rs1, 0), 0>;
2380b57cec5SDimitry Andricdef : InstAlias<"fsw $rs2, (${rs1})", (FSW FPR32:$rs2, GPR:$rs1, 0), 0>;
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andricdef : InstAlias<"fmv.s $rd, $rs",  (FSGNJ_S  FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
2410b57cec5SDimitry Andricdef : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
2420b57cec5SDimitry Andricdef : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
2430b57cec5SDimitry Andric
2440b57cec5SDimitry Andric// fgt.s/fge.s are recognised by the GNU assembler but the canonical
2450b57cec5SDimitry Andric// flt.s/fle.s forms will always be printed. Therefore, set a zero weight.
2460b57cec5SDimitry Andricdef : InstAlias<"fgt.s $rd, $rs, $rt",
2470b57cec5SDimitry Andric                (FLT_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
2480b57cec5SDimitry Andricdef : InstAlias<"fge.s $rd, $rs, $rt",
2490b57cec5SDimitry Andric                (FLE_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>;
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric// The following csr instructions actually alias instructions from the base ISA.
2520b57cec5SDimitry Andric// However, it only makes sense to support them when the F extension is enabled.
2530b57cec5SDimitry Andric// NOTE: "frcsr", "frrm", and "frflags" are more specialized version of "csrr".
2540b57cec5SDimitry Andricdef : InstAlias<"frcsr $rd",      (CSRRS GPR:$rd, FCSR.Encoding, X0), 2>;
2550b57cec5SDimitry Andricdef : InstAlias<"fscsr $rd, $rs", (CSRRW GPR:$rd, FCSR.Encoding, GPR:$rs)>;
2560b57cec5SDimitry Andricdef : InstAlias<"fscsr $rs",      (CSRRW      X0, FCSR.Encoding, GPR:$rs), 2>;
2570b57cec5SDimitry Andric
2588bcb0991SDimitry Andric// frsr, fssr are obsolete aliases replaced by frcsr, fscsr, so give them
2598bcb0991SDimitry Andric// zero weight.
2608bcb0991SDimitry Andricdef : InstAlias<"frsr $rd",       (CSRRS GPR:$rd, FCSR.Encoding, X0), 0>;
2618bcb0991SDimitry Andricdef : InstAlias<"fssr $rd, $rs",  (CSRRW GPR:$rd, FCSR.Encoding, GPR:$rs), 0>;
2628bcb0991SDimitry Andricdef : InstAlias<"fssr $rs",       (CSRRW      X0, FCSR.Encoding, GPR:$rs), 0>;
2638bcb0991SDimitry Andric
2640b57cec5SDimitry Andricdef : InstAlias<"frrm $rd",        (CSRRS  GPR:$rd, FRM.Encoding, X0), 2>;
2650b57cec5SDimitry Andricdef : InstAlias<"fsrm $rd, $rs",   (CSRRW  GPR:$rd, FRM.Encoding, GPR:$rs)>;
2660b57cec5SDimitry Andricdef : InstAlias<"fsrm $rs",        (CSRRW       X0, FRM.Encoding, GPR:$rs), 2>;
2670b57cec5SDimitry Andricdef : InstAlias<"fsrmi $rd, $imm", (CSRRWI GPR:$rd, FRM.Encoding, uimm5:$imm)>;
2680b57cec5SDimitry Andricdef : InstAlias<"fsrmi $imm",      (CSRRWI      X0, FRM.Encoding, uimm5:$imm), 2>;
2690b57cec5SDimitry Andric
2700b57cec5SDimitry Andricdef : InstAlias<"frflags $rd",        (CSRRS  GPR:$rd, FFLAGS.Encoding, X0), 2>;
2710b57cec5SDimitry Andricdef : InstAlias<"fsflags $rd, $rs",   (CSRRW  GPR:$rd, FFLAGS.Encoding, GPR:$rs)>;
2720b57cec5SDimitry Andricdef : InstAlias<"fsflags $rs",        (CSRRW       X0, FFLAGS.Encoding, GPR:$rs), 2>;
2730b57cec5SDimitry Andricdef : InstAlias<"fsflagsi $rd, $imm", (CSRRWI GPR:$rd, FFLAGS.Encoding, uimm5:$imm)>;
2740b57cec5SDimitry Andricdef : InstAlias<"fsflagsi $imm",      (CSRRWI      X0, FFLAGS.Encoding, uimm5:$imm), 2>;
2750b57cec5SDimitry Andric
2760b57cec5SDimitry Andric// fmv.w.x and fmv.x.w were previously known as fmv.s.x and fmv.x.s. Both
2770b57cec5SDimitry Andric// spellings should be supported by standard tools.
2780b57cec5SDimitry Andricdef : MnemonicAlias<"fmv.s.x", "fmv.w.x">;
2790b57cec5SDimitry Andricdef : MnemonicAlias<"fmv.x.s", "fmv.x.w">;
2800b57cec5SDimitry Andric
2810b57cec5SDimitry Andricdef PseudoFLW  : PseudoFloatLoad<"flw", FPR32>;
2820b57cec5SDimitry Andricdef PseudoFSW  : PseudoStore<"fsw", FPR32>;
2830b57cec5SDimitry Andric} // Predicates = [HasStdExtF]
2840b57cec5SDimitry Andric
2850b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2860b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns
2870b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
2880b57cec5SDimitry Andric
2895ffd83dbSDimitry Andric/// Floating point constants
2905ffd83dbSDimitry Andricdef fpimm0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>;
2915ffd83dbSDimitry Andric
2920b57cec5SDimitry Andric/// Generic pattern classes
2930b57cec5SDimitry Andricclass PatFpr32Fpr32<SDPatternOperator OpNode, RVInstR Inst>
2940b57cec5SDimitry Andric    : Pat<(OpNode FPR32:$rs1, FPR32:$rs2), (Inst $rs1, $rs2)>;
2950b57cec5SDimitry Andric
2960b57cec5SDimitry Andricclass PatFpr32Fpr32DynFrm<SDPatternOperator OpNode, RVInstRFrm Inst>
2970b57cec5SDimitry Andric    : Pat<(OpNode FPR32:$rs1, FPR32:$rs2), (Inst $rs1, $rs2, 0b111)>;
2980b57cec5SDimitry Andric
2990b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in {
3000b57cec5SDimitry Andric
3015ffd83dbSDimitry Andric/// Float constants
3025ffd83dbSDimitry Andricdef : Pat<(f32 (fpimm0)), (FMV_W_X X0)>;
3035ffd83dbSDimitry Andric
3040b57cec5SDimitry Andric/// Float conversion operations
3050b57cec5SDimitry Andric
3060b57cec5SDimitry Andric// [u]int32<->float conversion patterns must be gated on IsRV32 or IsRV64, so
3070b57cec5SDimitry Andric// are defined later.
3080b57cec5SDimitry Andric
3090b57cec5SDimitry Andric/// Float arithmetic operations
3100b57cec5SDimitry Andric
3110b57cec5SDimitry Andricdef : PatFpr32Fpr32DynFrm<fadd, FADD_S>;
3120b57cec5SDimitry Andricdef : PatFpr32Fpr32DynFrm<fsub, FSUB_S>;
3130b57cec5SDimitry Andricdef : PatFpr32Fpr32DynFrm<fmul, FMUL_S>;
3140b57cec5SDimitry Andricdef : PatFpr32Fpr32DynFrm<fdiv, FDIV_S>;
3150b57cec5SDimitry Andric
3160b57cec5SDimitry Andricdef : Pat<(fsqrt FPR32:$rs1), (FSQRT_S FPR32:$rs1, 0b111)>;
3170b57cec5SDimitry Andric
3180b57cec5SDimitry Andricdef : Pat<(fneg FPR32:$rs1), (FSGNJN_S $rs1, $rs1)>;
3190b57cec5SDimitry Andricdef : Pat<(fabs FPR32:$rs1), (FSGNJX_S $rs1, $rs1)>;
3200b57cec5SDimitry Andric
3210b57cec5SDimitry Andricdef : PatFpr32Fpr32<fcopysign, FSGNJ_S>;
3220b57cec5SDimitry Andricdef : Pat<(fcopysign FPR32:$rs1, (fneg FPR32:$rs2)), (FSGNJN_S $rs1, $rs2)>;
3230b57cec5SDimitry Andric
3240b57cec5SDimitry Andric// fmadd: rs1 * rs2 + rs3
3250b57cec5SDimitry Andricdef : Pat<(fma FPR32:$rs1, FPR32:$rs2, FPR32:$rs3),
3260b57cec5SDimitry Andric          (FMADD_S $rs1, $rs2, $rs3, 0b111)>;
3270b57cec5SDimitry Andric
3280b57cec5SDimitry Andric// fmsub: rs1 * rs2 - rs3
3290b57cec5SDimitry Andricdef : Pat<(fma FPR32:$rs1, FPR32:$rs2, (fneg FPR32:$rs3)),
3300b57cec5SDimitry Andric          (FMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>;
3310b57cec5SDimitry Andric
3320b57cec5SDimitry Andric// fnmsub: -rs1 * rs2 + rs3
3330b57cec5SDimitry Andricdef : Pat<(fma (fneg FPR32:$rs1), FPR32:$rs2, FPR32:$rs3),
3340b57cec5SDimitry Andric          (FNMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>;
3350b57cec5SDimitry Andric
3360b57cec5SDimitry Andric// fnmadd: -rs1 * rs2 - rs3
3370b57cec5SDimitry Andricdef : Pat<(fma (fneg FPR32:$rs1), FPR32:$rs2, (fneg FPR32:$rs3)),
3380b57cec5SDimitry Andric          (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>;
3390b57cec5SDimitry Andric
3400b57cec5SDimitry Andric// The RISC-V 2.2 user-level ISA spec defines fmin and fmax as returning the
3410b57cec5SDimitry Andric// canonical NaN when given a signaling NaN. This doesn't match the LLVM
3420b57cec5SDimitry Andric// behaviour (see https://bugs.llvm.org/show_bug.cgi?id=27363). However, the
3430b57cec5SDimitry Andric// draft 2.3 ISA spec changes the definition of fmin and fmax in a way that
3440b57cec5SDimitry Andric// matches LLVM's fminnum and fmaxnum
3450b57cec5SDimitry Andric// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>.
3460b57cec5SDimitry Andricdef : PatFpr32Fpr32<fminnum, FMIN_S>;
3470b57cec5SDimitry Andricdef : PatFpr32Fpr32<fmaxnum, FMAX_S>;
3480b57cec5SDimitry Andric
3490b57cec5SDimitry Andric/// Setcc
3500b57cec5SDimitry Andric
3510b57cec5SDimitry Andricdef : PatFpr32Fpr32<seteq, FEQ_S>;
3520b57cec5SDimitry Andricdef : PatFpr32Fpr32<setoeq, FEQ_S>;
3530b57cec5SDimitry Andricdef : PatFpr32Fpr32<setlt, FLT_S>;
3540b57cec5SDimitry Andricdef : PatFpr32Fpr32<setolt, FLT_S>;
3550b57cec5SDimitry Andricdef : PatFpr32Fpr32<setle, FLE_S>;
3560b57cec5SDimitry Andricdef : PatFpr32Fpr32<setole, FLE_S>;
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andricdef Select_FPR32_Using_CC_GPR : SelectCC_rrirr<FPR32, GPR>;
3590b57cec5SDimitry Andric
3600b57cec5SDimitry Andric/// Loads
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andricdefm : LdPat<load, FLW>;
3630b57cec5SDimitry Andric
3640b57cec5SDimitry Andric/// Stores
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andricdefm : StPat<store, FSW, FPR32>;
3670b57cec5SDimitry Andric
3680b57cec5SDimitry Andric} // Predicates = [HasStdExtF]
3690b57cec5SDimitry Andric
3700b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV32] in {
371e8d8bef9SDimitry Andric// Moves (no conversion)
372e8d8bef9SDimitry Andricdef : Pat<(bitconvert GPR:$rs1), (FMV_W_X GPR:$rs1)>;
373e8d8bef9SDimitry Andricdef : Pat<(bitconvert FPR32:$rs1), (FMV_X_W FPR32:$rs1)>;
374e8d8bef9SDimitry Andric
3750b57cec5SDimitry Andric// float->[u]int. Round-to-zero must be used.
3760b57cec5SDimitry Andricdef : Pat<(fp_to_sint FPR32:$rs1), (FCVT_W_S $rs1, 0b001)>;
3770b57cec5SDimitry Andricdef : Pat<(fp_to_uint FPR32:$rs1), (FCVT_WU_S $rs1, 0b001)>;
3780b57cec5SDimitry Andric
3790b57cec5SDimitry Andric// [u]int->float. Match GCC and default to using dynamic rounding mode.
3800b57cec5SDimitry Andricdef : Pat<(sint_to_fp GPR:$rs1), (FCVT_S_W $rs1, 0b111)>;
3810b57cec5SDimitry Andricdef : Pat<(uint_to_fp GPR:$rs1), (FCVT_S_WU $rs1, 0b111)>;
3820b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV32]
3830b57cec5SDimitry Andric
3840b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV64] in {
385e8d8bef9SDimitry Andric// Moves (no conversion)
3860b57cec5SDimitry Andricdef : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (FMV_W_X GPR:$src)>;
3870b57cec5SDimitry Andricdef : Pat<(riscv_fmv_x_anyextw_rv64 FPR32:$src), (FMV_X_W FPR32:$src)>;
388e8d8bef9SDimitry Andricdef : Pat<(sext_inreg (riscv_fmv_x_anyextw_rv64 FPR32:$src), i32),
3890b57cec5SDimitry Andric          (FMV_X_W FPR32:$src)>;
3900b57cec5SDimitry Andric
3910b57cec5SDimitry Andric// FP->[u]int32 is mostly handled by the FP->[u]int64 patterns. This is safe
3920b57cec5SDimitry Andric// because fpto[u|s]i produces poison if the value can't fit into the target.
3930b57cec5SDimitry Andric// We match the single case below because fcvt.wu.s sign-extends its result so
3940b57cec5SDimitry Andric// is cheaper than fcvt.lu.s+sext.w.
3950b57cec5SDimitry Andricdef : Pat<(sext_inreg (assertzexti32 (fp_to_uint FPR32:$rs1)), i32),
3960b57cec5SDimitry Andric          (FCVT_WU_S $rs1, 0b001)>;
3970b57cec5SDimitry Andric
3980b57cec5SDimitry Andric// FP->[u]int64
3990b57cec5SDimitry Andricdef : Pat<(fp_to_sint FPR32:$rs1), (FCVT_L_S $rs1, 0b001)>;
4000b57cec5SDimitry Andricdef : Pat<(fp_to_uint FPR32:$rs1), (FCVT_LU_S $rs1, 0b001)>;
4010b57cec5SDimitry Andric
4020b57cec5SDimitry Andric// [u]int->fp. Match GCC and default to using dynamic rounding mode.
403e8d8bef9SDimitry Andricdef : Pat<(sint_to_fp (sexti32 GPR:$rs1)), (FCVT_S_W $rs1, 0b111)>;
4040b57cec5SDimitry Andricdef : Pat<(uint_to_fp (zexti32 GPR:$rs1)), (FCVT_S_WU $rs1, 0b111)>;
4050b57cec5SDimitry Andricdef : Pat<(sint_to_fp GPR:$rs1), (FCVT_S_L $rs1, 0b111)>;
4060b57cec5SDimitry Andricdef : Pat<(uint_to_fp GPR:$rs1), (FCVT_S_LU $rs1, 0b111)>;
4070b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV64]
408