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>]>; 220eae32dcSDimitry Andricdef SDT_RISCVFCVT_W_RV64 2304eeddc0SDimitry Andric : SDTypeProfile<1, 2, [SDTCisVT<0, i64>, SDTCisFP<1>, 2404eeddc0SDimitry Andric SDTCisVT<2, i64>]>; 250eae32dcSDimitry Andricdef SDT_RISCVFCVT_X 2604eeddc0SDimitry Andric : SDTypeProfile<1, 2, [SDTCisVT<0, XLenVT>, SDTCisFP<1>, 2704eeddc0SDimitry Andric SDTCisVT<2, XLenVT>]>; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andricdef riscv_fmv_w_x_rv64 300b57cec5SDimitry Andric : SDNode<"RISCVISD::FMV_W_X_RV64", SDT_RISCVFMV_W_X_RV64>; 310b57cec5SDimitry Andricdef riscv_fmv_x_anyextw_rv64 320b57cec5SDimitry Andric : SDNode<"RISCVISD::FMV_X_ANYEXTW_RV64", SDT_RISCVFMV_X_ANYEXTW_RV64>; 3304eeddc0SDimitry Andricdef riscv_fcvt_w_rv64 3404eeddc0SDimitry Andric : SDNode<"RISCVISD::FCVT_W_RV64", SDT_RISCVFCVT_W_RV64>; 3504eeddc0SDimitry Andricdef riscv_fcvt_wu_rv64 3604eeddc0SDimitry Andric : SDNode<"RISCVISD::FCVT_WU_RV64", SDT_RISCVFCVT_W_RV64>; 3704eeddc0SDimitry Andricdef riscv_fcvt_x 3804eeddc0SDimitry Andric : SDNode<"RISCVISD::FCVT_X", SDT_RISCVFCVT_X>; 3904eeddc0SDimitry Andricdef riscv_fcvt_xu 4004eeddc0SDimitry Andric : SDNode<"RISCVISD::FCVT_XU", SDT_RISCVFCVT_X>; 410eae32dcSDimitry Andric 4204eeddc0SDimitry Andricdef riscv_strict_fcvt_w_rv64 4304eeddc0SDimitry Andric : SDNode<"RISCVISD::STRICT_FCVT_W_RV64", SDT_RISCVFCVT_W_RV64, 440eae32dcSDimitry Andric [SDNPHasChain]>; 4504eeddc0SDimitry Andricdef riscv_strict_fcvt_wu_rv64 4604eeddc0SDimitry Andric : SDNode<"RISCVISD::STRICT_FCVT_WU_RV64", SDT_RISCVFCVT_W_RV64, 470eae32dcSDimitry Andric [SDNPHasChain]>; 480eae32dcSDimitry Andric 4904eeddc0SDimitry Andricdef riscv_any_fcvt_w_rv64 : PatFrags<(ops node:$src, node:$frm), 5004eeddc0SDimitry Andric [(riscv_strict_fcvt_w_rv64 node:$src, node:$frm), 5104eeddc0SDimitry Andric (riscv_fcvt_w_rv64 node:$src, node:$frm)]>; 5204eeddc0SDimitry Andricdef riscv_any_fcvt_wu_rv64 : PatFrags<(ops node:$src, node:$frm), 5304eeddc0SDimitry Andric [(riscv_strict_fcvt_wu_rv64 node:$src, node:$frm), 5404eeddc0SDimitry Andric (riscv_fcvt_wu_rv64 node:$src, node:$frm)]>; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 570b57cec5SDimitry Andric// Operand and SDNode transformation definitions. 580b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric// Floating-point rounding mode 610b57cec5SDimitry Andric 620b57cec5SDimitry Andricdef FRMArg : AsmOperandClass { 630b57cec5SDimitry Andric let Name = "FRMArg"; 640b57cec5SDimitry Andric let RenderMethod = "addFRMArgOperands"; 650b57cec5SDimitry Andric let DiagnosticType = "InvalidFRMArg"; 660b57cec5SDimitry Andric} 670b57cec5SDimitry Andric 680b57cec5SDimitry Andricdef frmarg : Operand<XLenVT> { 690b57cec5SDimitry Andric let ParserMatchClass = FRMArg; 700b57cec5SDimitry Andric let PrintMethod = "printFRMArg"; 710b57cec5SDimitry Andric let DecoderMethod = "decodeFRMArg"; 720b57cec5SDimitry Andric} 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 750b57cec5SDimitry Andric// Instruction class templates 760b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 770b57cec5SDimitry Andric 7804eeddc0SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0 in 7904eeddc0SDimitry Andricclass FPLoad_r<bits<3> funct3, string opcodestr, RegisterClass rty, 8004eeddc0SDimitry Andric SchedWrite sw> 8104eeddc0SDimitry Andric : RVInstI<funct3, OPC_LOAD_FP, (outs rty:$rd), 8204eeddc0SDimitry Andric (ins GPR:$rs1, simm12:$imm12), 8304eeddc0SDimitry Andric opcodestr, "$rd, ${imm12}(${rs1})">, 8404eeddc0SDimitry Andric Sched<[sw, ReadFMemBase]>; 8504eeddc0SDimitry Andric 8604eeddc0SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 1 in 8704eeddc0SDimitry Andricclass FPStore_r<bits<3> funct3, string opcodestr, RegisterClass rty, 8804eeddc0SDimitry Andric SchedWrite sw> 8904eeddc0SDimitry Andric : RVInstS<funct3, OPC_STORE_FP, (outs), 9004eeddc0SDimitry Andric (ins rty:$rs2, GPR:$rs1, simm12:$imm12), 9104eeddc0SDimitry Andric opcodestr, "$rs2, ${imm12}(${rs1})">, 9204eeddc0SDimitry Andric Sched<[sw, ReadStoreData, ReadFMemBase]>; 9304eeddc0SDimitry Andric 940eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1, 950eae32dcSDimitry Andric UseNamedOperandTable = 1, hasPostISelHook = 1 in 960eae32dcSDimitry Andricclass FPFMA_rrr_frm<RISCVOpcode opcode, bits<2> funct2, string opcodestr, 970eae32dcSDimitry Andric RegisterClass rty> 980eae32dcSDimitry Andric : RVInstR4Frm<funct2, opcode, (outs rty:$rd), 990eae32dcSDimitry Andric (ins rty:$rs1, rty:$rs2, rty:$rs3, frmarg:$frm), 1000eae32dcSDimitry Andric opcodestr, "$rd, $rs1, $rs2, $rs3, $frm">; 1010b57cec5SDimitry Andric 1020eae32dcSDimitry Andricclass FPFMADynFrmAlias<FPFMA_rrr_frm Inst, string OpcodeStr, 1030eae32dcSDimitry Andric RegisterClass rty> 1040b57cec5SDimitry Andric : InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3", 1050eae32dcSDimitry Andric (Inst rty:$rd, rty:$rs1, rty:$rs2, rty:$rs3, 0b111)>; 1060b57cec5SDimitry Andric 1070eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in 1080eae32dcSDimitry Andricclass FPALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 1090eae32dcSDimitry Andric RegisterClass rty> 1100eae32dcSDimitry Andric : RVInstR<funct7, funct3, OPC_OP_FP, (outs rty:$rd), 1110eae32dcSDimitry Andric (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2">; 1120b57cec5SDimitry Andric 1130eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1, 1140eae32dcSDimitry Andric UseNamedOperandTable = 1, hasPostISelHook = 1 in 1150eae32dcSDimitry Andricclass FPALU_rr_frm<bits<7> funct7, string opcodestr, RegisterClass rty> 1160eae32dcSDimitry Andric : RVInstRFrm<funct7, OPC_OP_FP, (outs rty:$rd), 1170eae32dcSDimitry Andric (ins rty:$rs1, rty:$rs2, frmarg:$frm), opcodestr, 1180eae32dcSDimitry Andric "$rd, $rs1, $rs2, $frm">; 1190b57cec5SDimitry Andric 1200eae32dcSDimitry Andricclass FPALUDynFrmAlias<FPALU_rr_frm Inst, string OpcodeStr, 1210eae32dcSDimitry Andric RegisterClass rty> 1220b57cec5SDimitry Andric : InstAlias<OpcodeStr#" $rd, $rs1, $rs2", 1230eae32dcSDimitry Andric (Inst rty:$rd, rty:$rs1, rty:$rs2, 0b111)>; 1240b57cec5SDimitry Andric 1250eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in 1260eae32dcSDimitry Andricclass FPUnaryOp_r<bits<7> funct7, bits<5> rs2val, bits<3> funct3, 1270eae32dcSDimitry Andric RegisterClass rdty, RegisterClass rs1ty, string opcodestr> 1280b57cec5SDimitry Andric : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), (ins rs1ty:$rs1), 1290eae32dcSDimitry Andric opcodestr, "$rd, $rs1"> { 1300eae32dcSDimitry Andric let rs2 = rs2val; 1310eae32dcSDimitry Andric} 1320b57cec5SDimitry Andric 1330eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1, 1340eae32dcSDimitry Andric UseNamedOperandTable = 1, hasPostISelHook = 1 in 1350eae32dcSDimitry Andricclass FPUnaryOp_r_frm<bits<7> funct7, bits<5> rs2val, RegisterClass rdty, 1360eae32dcSDimitry Andric RegisterClass rs1ty, string opcodestr> 1370b57cec5SDimitry Andric : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd), 1380eae32dcSDimitry Andric (ins rs1ty:$rs1, frmarg:$frm), opcodestr, 1390eae32dcSDimitry Andric "$rd, $rs1, $frm"> { 1400eae32dcSDimitry Andric let rs2 = rs2val; 1410eae32dcSDimitry Andric} 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andricclass FPUnaryOpDynFrmAlias<FPUnaryOp_r_frm Inst, string OpcodeStr, 1440b57cec5SDimitry Andric RegisterClass rdty, RegisterClass rs1ty> 1450b57cec5SDimitry Andric : InstAlias<OpcodeStr#" $rd, $rs1", 1460b57cec5SDimitry Andric (Inst rdty:$rd, rs1ty:$rs1, 0b111)>; 1470b57cec5SDimitry Andric 1480eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in 1490eae32dcSDimitry Andricclass FPCmp_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 1500eae32dcSDimitry Andric RegisterClass rty> 1510eae32dcSDimitry Andric : RVInstR<funct7, funct3, OPC_OP_FP, (outs GPR:$rd), 1520eae32dcSDimitry Andric (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2">; 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 1550b57cec5SDimitry Andric// Instructions 1560b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in { 15904eeddc0SDimitry Andricdef FLW : FPLoad_r<0b010, "flw", FPR32, WriteFLD32>; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric// Operands for stores are in the order srcreg, base, offset rather than 1620b57cec5SDimitry Andric// reflecting the order these fields are specified in the instruction 1630b57cec5SDimitry Andric// encoding. 16404eeddc0SDimitry Andricdef FSW : FPStore_r<0b010, "fsw", FPR32, WriteFST32>; 1650b57cec5SDimitry Andric 1660eae32dcSDimitry Andriclet SchedRW = [WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32] in { 1670eae32dcSDimitry Andricdef FMADD_S : FPFMA_rrr_frm<OPC_MADD, 0b00, "fmadd.s", FPR32>; 1680eae32dcSDimitry Andricdef FMSUB_S : FPFMA_rrr_frm<OPC_MSUB, 0b00, "fmsub.s", FPR32>; 1690eae32dcSDimitry Andricdef FNMSUB_S : FPFMA_rrr_frm<OPC_NMSUB, 0b00, "fnmsub.s", FPR32>; 1700eae32dcSDimitry Andricdef FNMADD_S : FPFMA_rrr_frm<OPC_NMADD, 0b00, "fnmadd.s", FPR32>; 1710b57cec5SDimitry Andric} 1720eae32dcSDimitry Andric 1730eae32dcSDimitry Andricdef : FPFMADynFrmAlias<FMADD_S, "fmadd.s", FPR32>; 1740eae32dcSDimitry Andricdef : FPFMADynFrmAlias<FMSUB_S, "fmsub.s", FPR32>; 1750eae32dcSDimitry Andricdef : FPFMADynFrmAlias<FNMSUB_S, "fnmsub.s", FPR32>; 1760eae32dcSDimitry Andricdef : FPFMADynFrmAlias<FNMADD_S, "fnmadd.s", FPR32>; 1770eae32dcSDimitry Andric 1780eae32dcSDimitry Andricdef FADD_S : FPALU_rr_frm<0b0000000, "fadd.s", FPR32>, 1790eae32dcSDimitry Andric Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>; 1800eae32dcSDimitry Andricdef FSUB_S : FPALU_rr_frm<0b0000100, "fsub.s", FPR32>, 1810eae32dcSDimitry Andric Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>; 1820eae32dcSDimitry Andricdef FMUL_S : FPALU_rr_frm<0b0001000, "fmul.s", FPR32>, 1830eae32dcSDimitry Andric Sched<[WriteFMul32, ReadFMul32, ReadFMul32]>; 1840eae32dcSDimitry Andricdef FDIV_S : FPALU_rr_frm<0b0001100, "fdiv.s", FPR32>, 1850eae32dcSDimitry Andric Sched<[WriteFDiv32, ReadFDiv32, ReadFDiv32]>; 1860eae32dcSDimitry Andric 1870eae32dcSDimitry Andricdef : FPALUDynFrmAlias<FADD_S, "fadd.s", FPR32>; 1880eae32dcSDimitry Andricdef : FPALUDynFrmAlias<FSUB_S, "fsub.s", FPR32>; 1890eae32dcSDimitry Andricdef : FPALUDynFrmAlias<FMUL_S, "fmul.s", FPR32>; 1900eae32dcSDimitry Andricdef : FPALUDynFrmAlias<FDIV_S, "fdiv.s", FPR32>; 1910eae32dcSDimitry Andric 1920eae32dcSDimitry Andricdef FSQRT_S : FPUnaryOp_r_frm<0b0101100, 0b00000, FPR32, FPR32, "fsqrt.s">, 1930eae32dcSDimitry Andric Sched<[WriteFSqrt32, ReadFSqrt32]>; 1940b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FSQRT_S, "fsqrt.s", FPR32, FPR32>; 1950b57cec5SDimitry Andric 1960eae32dcSDimitry Andriclet SchedRW = [WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32], 1970eae32dcSDimitry Andric mayRaiseFPException = 0 in { 1980eae32dcSDimitry Andricdef FSGNJ_S : FPALU_rr<0b0010000, 0b000, "fsgnj.s", FPR32>; 1990eae32dcSDimitry Andricdef FSGNJN_S : FPALU_rr<0b0010000, 0b001, "fsgnjn.s", FPR32>; 2000eae32dcSDimitry Andricdef FSGNJX_S : FPALU_rr<0b0010000, 0b010, "fsgnjx.s", FPR32>; 2010b57cec5SDimitry Andric} 2020eae32dcSDimitry Andric 2030eae32dcSDimitry Andriclet SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in { 2040eae32dcSDimitry Andricdef FMIN_S : FPALU_rr<0b0010100, 0b000, "fmin.s", FPR32>; 2050eae32dcSDimitry Andricdef FMAX_S : FPALU_rr<0b0010100, 0b001, "fmax.s", FPR32>; 2060eae32dcSDimitry Andric} 2070eae32dcSDimitry Andric 2080eae32dcSDimitry Andricdef FCVT_W_S : FPUnaryOp_r_frm<0b1100000, 0b00000, GPR, FPR32, "fcvt.w.s">, 2090eae32dcSDimitry Andric Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>; 2100b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_W_S, "fcvt.w.s", GPR, FPR32>; 2110b57cec5SDimitry Andric 2120eae32dcSDimitry Andricdef FCVT_WU_S : FPUnaryOp_r_frm<0b1100000, 0b00001, GPR, FPR32, "fcvt.wu.s">, 2130eae32dcSDimitry Andric Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>; 2140b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_WU_S, "fcvt.wu.s", GPR, FPR32>; 2150b57cec5SDimitry Andric 2160eae32dcSDimitry Andriclet mayRaiseFPException = 0 in 2170eae32dcSDimitry Andricdef FMV_X_W : FPUnaryOp_r<0b1110000, 0b00000, 0b000, GPR, FPR32, "fmv.x.w">, 2180eae32dcSDimitry Andric Sched<[WriteFMovF32ToI32, ReadFMovF32ToI32]>; 2190eae32dcSDimitry Andric 2200eae32dcSDimitry Andriclet SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in { 2210eae32dcSDimitry Andricdef FEQ_S : FPCmp_rr<0b1010000, 0b010, "feq.s", FPR32>; 2220eae32dcSDimitry Andricdef FLT_S : FPCmp_rr<0b1010000, 0b001, "flt.s", FPR32>; 2230eae32dcSDimitry Andricdef FLE_S : FPCmp_rr<0b1010000, 0b000, "fle.s", FPR32>; 2240b57cec5SDimitry Andric} 2250b57cec5SDimitry Andric 2260eae32dcSDimitry Andriclet mayRaiseFPException = 0 in 2270eae32dcSDimitry Andricdef FCLASS_S : FPUnaryOp_r<0b1110000, 0b00000, 0b001, GPR, FPR32, "fclass.s">, 2280eae32dcSDimitry Andric Sched<[WriteFClass32, ReadFClass32]>; 2290b57cec5SDimitry Andric 2300eae32dcSDimitry Andricdef FCVT_S_W : FPUnaryOp_r_frm<0b1101000, 0b00000, FPR32, GPR, "fcvt.s.w">, 2310eae32dcSDimitry Andric Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>; 2320b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_S_W, "fcvt.s.w", FPR32, GPR>; 2330b57cec5SDimitry Andric 2340eae32dcSDimitry Andricdef FCVT_S_WU : FPUnaryOp_r_frm<0b1101000, 0b00001, FPR32, GPR, "fcvt.s.wu">, 2350eae32dcSDimitry Andric Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>; 2360b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_S_WU, "fcvt.s.wu", FPR32, GPR>; 2370b57cec5SDimitry Andric 2380eae32dcSDimitry Andriclet mayRaiseFPException = 0 in 2390eae32dcSDimitry Andricdef FMV_W_X : FPUnaryOp_r<0b1111000, 0b00000, 0b000, FPR32, GPR, "fmv.w.x">, 2400eae32dcSDimitry Andric Sched<[WriteFMovI32ToF32, ReadFMovI32ToF32]>; 2410b57cec5SDimitry Andric} // Predicates = [HasStdExtF] 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV64] in { 2440eae32dcSDimitry Andricdef FCVT_L_S : FPUnaryOp_r_frm<0b1100000, 0b00010, GPR, FPR32, "fcvt.l.s">, 2450eae32dcSDimitry Andric Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>; 2460b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_L_S, "fcvt.l.s", GPR, FPR32>; 2470b57cec5SDimitry Andric 2480eae32dcSDimitry Andricdef FCVT_LU_S : FPUnaryOp_r_frm<0b1100000, 0b00011, GPR, FPR32, "fcvt.lu.s">, 2490eae32dcSDimitry Andric Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>; 2500b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_LU_S, "fcvt.lu.s", GPR, FPR32>; 2510b57cec5SDimitry Andric 2520eae32dcSDimitry Andricdef FCVT_S_L : FPUnaryOp_r_frm<0b1101000, 0b00010, FPR32, GPR, "fcvt.s.l">, 2530eae32dcSDimitry Andric Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>; 2540b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_S_L, "fcvt.s.l", FPR32, GPR>; 2550b57cec5SDimitry Andric 2560eae32dcSDimitry Andricdef FCVT_S_LU : FPUnaryOp_r_frm<0b1101000, 0b00011, FPR32, GPR, "fcvt.s.lu">, 2570eae32dcSDimitry Andric Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>; 2580b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_S_LU, "fcvt.s.lu", FPR32, GPR>; 2590b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV64] 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 2620b57cec5SDimitry Andric// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 2630b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in { 2660b57cec5SDimitry Andricdef : InstAlias<"flw $rd, (${rs1})", (FLW FPR32:$rd, GPR:$rs1, 0), 0>; 2670b57cec5SDimitry Andricdef : InstAlias<"fsw $rs2, (${rs1})", (FSW FPR32:$rs2, GPR:$rs1, 0), 0>; 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andricdef : InstAlias<"fmv.s $rd, $rs", (FSGNJ_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; 2700b57cec5SDimitry Andricdef : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; 2710b57cec5SDimitry Andricdef : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric// fgt.s/fge.s are recognised by the GNU assembler but the canonical 2740b57cec5SDimitry Andric// flt.s/fle.s forms will always be printed. Therefore, set a zero weight. 2750b57cec5SDimitry Andricdef : InstAlias<"fgt.s $rd, $rs, $rt", 2760b57cec5SDimitry Andric (FLT_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>; 2770b57cec5SDimitry Andricdef : InstAlias<"fge.s $rd, $rs, $rt", 2780b57cec5SDimitry Andric (FLE_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>; 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric// The following csr instructions actually alias instructions from the base ISA. 2810b57cec5SDimitry Andric// However, it only makes sense to support them when the F extension is enabled. 2820b57cec5SDimitry Andric// NOTE: "frcsr", "frrm", and "frflags" are more specialized version of "csrr". 283fe6060f1SDimitry Andricdef : InstAlias<"frcsr $rd", (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 2>; 284fe6060f1SDimitry Andricdef : InstAlias<"fscsr $rd, $rs", (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs)>; 285fe6060f1SDimitry Andricdef : InstAlias<"fscsr $rs", (CSRRW X0, SysRegFCSR.Encoding, GPR:$rs), 2>; 2860b57cec5SDimitry Andric 2878bcb0991SDimitry Andric// frsr, fssr are obsolete aliases replaced by frcsr, fscsr, so give them 2888bcb0991SDimitry Andric// zero weight. 289fe6060f1SDimitry Andricdef : InstAlias<"frsr $rd", (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 0>; 290fe6060f1SDimitry Andricdef : InstAlias<"fssr $rd, $rs", (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs), 0>; 291fe6060f1SDimitry Andricdef : InstAlias<"fssr $rs", (CSRRW X0, SysRegFCSR.Encoding, GPR:$rs), 0>; 2928bcb0991SDimitry Andric 293fe6060f1SDimitry Andricdef : InstAlias<"frrm $rd", (CSRRS GPR:$rd, SysRegFRM.Encoding, X0), 2>; 294fe6060f1SDimitry Andricdef : InstAlias<"fsrm $rd, $rs", (CSRRW GPR:$rd, SysRegFRM.Encoding, GPR:$rs)>; 295fe6060f1SDimitry Andricdef : InstAlias<"fsrm $rs", (CSRRW X0, SysRegFRM.Encoding, GPR:$rs), 2>; 296fe6060f1SDimitry Andricdef : InstAlias<"fsrmi $rd, $imm", (CSRRWI GPR:$rd, SysRegFRM.Encoding, uimm5:$imm)>; 297fe6060f1SDimitry Andricdef : InstAlias<"fsrmi $imm", (CSRRWI X0, SysRegFRM.Encoding, uimm5:$imm), 2>; 2980b57cec5SDimitry Andric 299fe6060f1SDimitry Andricdef : InstAlias<"frflags $rd", (CSRRS GPR:$rd, SysRegFFLAGS.Encoding, X0), 2>; 300fe6060f1SDimitry Andricdef : InstAlias<"fsflags $rd, $rs", (CSRRW GPR:$rd, SysRegFFLAGS.Encoding, GPR:$rs)>; 301fe6060f1SDimitry Andricdef : InstAlias<"fsflags $rs", (CSRRW X0, SysRegFFLAGS.Encoding, GPR:$rs), 2>; 302fe6060f1SDimitry Andricdef : InstAlias<"fsflagsi $rd, $imm", (CSRRWI GPR:$rd, SysRegFFLAGS.Encoding, uimm5:$imm)>; 303fe6060f1SDimitry Andricdef : InstAlias<"fsflagsi $imm", (CSRRWI X0, SysRegFFLAGS.Encoding, uimm5:$imm), 2>; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric// fmv.w.x and fmv.x.w were previously known as fmv.s.x and fmv.x.s. Both 3060b57cec5SDimitry Andric// spellings should be supported by standard tools. 3070b57cec5SDimitry Andricdef : MnemonicAlias<"fmv.s.x", "fmv.w.x">; 3080b57cec5SDimitry Andricdef : MnemonicAlias<"fmv.x.s", "fmv.x.w">; 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andricdef PseudoFLW : PseudoFloatLoad<"flw", FPR32>; 3110b57cec5SDimitry Andricdef PseudoFSW : PseudoStore<"fsw", FPR32>; 31204eeddc0SDimitry Andriclet usesCustomInserter = 1 in { 31304eeddc0SDimitry Andricdef PseudoQuietFLE_S : PseudoQuietFCMP<FPR32>; 31404eeddc0SDimitry Andricdef PseudoQuietFLT_S : PseudoQuietFCMP<FPR32>; 31504eeddc0SDimitry Andric} 3160b57cec5SDimitry Andric} // Predicates = [HasStdExtF] 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 3190b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns 3200b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 3210b57cec5SDimitry Andric 3225ffd83dbSDimitry Andric/// Floating point constants 3235ffd83dbSDimitry Andricdef fpimm0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>; 32404eeddc0SDimitry Andricdef fpimmneg0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(-0.0); }]>; 3255ffd83dbSDimitry Andric 3260b57cec5SDimitry Andric/// Generic pattern classes 32704eeddc0SDimitry Andricclass PatSetCC<RegisterClass Ty, SDPatternOperator OpNode, CondCode Cond, RVInst Inst> 32804eeddc0SDimitry Andric : Pat<(OpNode Ty:$rs1, Ty:$rs2, Cond), (Inst $rs1, $rs2)>; 32904eeddc0SDimitry Andric 3300b57cec5SDimitry Andricclass PatFpr32Fpr32<SDPatternOperator OpNode, RVInstR Inst> 3310b57cec5SDimitry Andric : Pat<(OpNode FPR32:$rs1, FPR32:$rs2), (Inst $rs1, $rs2)>; 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andricclass PatFpr32Fpr32DynFrm<SDPatternOperator OpNode, RVInstRFrm Inst> 3340b57cec5SDimitry Andric : Pat<(OpNode FPR32:$rs1, FPR32:$rs2), (Inst $rs1, $rs2, 0b111)>; 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in { 3370b57cec5SDimitry Andric 3385ffd83dbSDimitry Andric/// Float constants 3395ffd83dbSDimitry Andricdef : Pat<(f32 (fpimm0)), (FMV_W_X X0)>; 34004eeddc0SDimitry Andricdef : Pat<(f32 (fpimmneg0)), (FSGNJN_S (FMV_W_X X0), (FMV_W_X X0))>; 3415ffd83dbSDimitry Andric 3420b57cec5SDimitry Andric/// Float conversion operations 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric// [u]int32<->float conversion patterns must be gated on IsRV32 or IsRV64, so 3450b57cec5SDimitry Andric// are defined later. 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric/// Float arithmetic operations 3480b57cec5SDimitry Andric 3490eae32dcSDimitry Andricdef : PatFpr32Fpr32DynFrm<any_fadd, FADD_S>; 3500eae32dcSDimitry Andricdef : PatFpr32Fpr32DynFrm<any_fsub, FSUB_S>; 3510eae32dcSDimitry Andricdef : PatFpr32Fpr32DynFrm<any_fmul, FMUL_S>; 3520eae32dcSDimitry Andricdef : PatFpr32Fpr32DynFrm<any_fdiv, FDIV_S>; 3530b57cec5SDimitry Andric 3540eae32dcSDimitry Andricdef : Pat<(any_fsqrt FPR32:$rs1), (FSQRT_S FPR32:$rs1, 0b111)>; 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andricdef : Pat<(fneg FPR32:$rs1), (FSGNJN_S $rs1, $rs1)>; 3570b57cec5SDimitry Andricdef : Pat<(fabs FPR32:$rs1), (FSGNJX_S $rs1, $rs1)>; 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andricdef : PatFpr32Fpr32<fcopysign, FSGNJ_S>; 3600b57cec5SDimitry Andricdef : Pat<(fcopysign FPR32:$rs1, (fneg FPR32:$rs2)), (FSGNJN_S $rs1, $rs2)>; 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric// fmadd: rs1 * rs2 + rs3 3630eae32dcSDimitry Andricdef : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, FPR32:$rs3), 3640b57cec5SDimitry Andric (FMADD_S $rs1, $rs2, $rs3, 0b111)>; 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric// fmsub: rs1 * rs2 - rs3 3670eae32dcSDimitry Andricdef : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, (fneg FPR32:$rs3)), 3680b57cec5SDimitry Andric (FMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>; 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric// fnmsub: -rs1 * rs2 + rs3 3710eae32dcSDimitry Andricdef : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, FPR32:$rs3), 3720b57cec5SDimitry Andric (FNMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>; 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric// fnmadd: -rs1 * rs2 - rs3 3750eae32dcSDimitry Andricdef : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, (fneg FPR32:$rs3)), 3760b57cec5SDimitry Andric (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>; 3770b57cec5SDimitry Andric 378fe6060f1SDimitry Andric// The ratified 20191213 ISA spec defines fmin and fmax in a way that matches 379fe6060f1SDimitry Andric// LLVM's fminnum and fmaxnum 3800b57cec5SDimitry Andric// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>. 3810b57cec5SDimitry Andricdef : PatFpr32Fpr32<fminnum, FMIN_S>; 3820b57cec5SDimitry Andricdef : PatFpr32Fpr32<fmaxnum, FMAX_S>; 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric/// Setcc 38504eeddc0SDimitry Andric// FIXME: SETEQ/SETLT/SETLE imply nonans, can we pick better instructions for 38604eeddc0SDimitry Andric// strict versions of those. 3870b57cec5SDimitry Andric 38804eeddc0SDimitry Andric// Match non-signaling FEQ_S 38904eeddc0SDimitry Andricdef : PatSetCC<FPR32, any_fsetcc, SETEQ, FEQ_S>; 39004eeddc0SDimitry Andricdef : PatSetCC<FPR32, any_fsetcc, SETOEQ, FEQ_S>; 39104eeddc0SDimitry Andricdef : PatSetCC<FPR32, strict_fsetcc, SETLT, PseudoQuietFLT_S>; 39204eeddc0SDimitry Andricdef : PatSetCC<FPR32, strict_fsetcc, SETOLT, PseudoQuietFLT_S>; 39304eeddc0SDimitry Andricdef : PatSetCC<FPR32, strict_fsetcc, SETLE, PseudoQuietFLE_S>; 39404eeddc0SDimitry Andricdef : PatSetCC<FPR32, strict_fsetcc, SETOLE, PseudoQuietFLE_S>; 39504eeddc0SDimitry Andric 39604eeddc0SDimitry Andric// Match signaling FEQ_S 39704eeddc0SDimitry Andricdef : Pat<(strict_fsetccs FPR32:$rs1, FPR32:$rs2, SETEQ), 39804eeddc0SDimitry Andric (AND (FLE_S $rs1, $rs2), 39904eeddc0SDimitry Andric (FLE_S $rs2, $rs1))>; 40004eeddc0SDimitry Andricdef : Pat<(strict_fsetccs FPR32:$rs1, FPR32:$rs2, SETOEQ), 40104eeddc0SDimitry Andric (AND (FLE_S $rs1, $rs2), 40204eeddc0SDimitry Andric (FLE_S $rs2, $rs1))>; 40304eeddc0SDimitry Andric// If both operands are the same, use a single FLE. 40404eeddc0SDimitry Andricdef : Pat<(strict_fsetccs FPR32:$rs1, FPR32:$rs1, SETEQ), 40504eeddc0SDimitry Andric (FLE_S $rs1, $rs1)>; 40604eeddc0SDimitry Andricdef : Pat<(strict_fsetccs FPR32:$rs1, FPR32:$rs1, SETOEQ), 40704eeddc0SDimitry Andric (FLE_S $rs1, $rs1)>; 40804eeddc0SDimitry Andric 40904eeddc0SDimitry Andricdef : PatSetCC<FPR32, any_fsetccs, SETLT, FLT_S>; 41004eeddc0SDimitry Andricdef : PatSetCC<FPR32, any_fsetccs, SETOLT, FLT_S>; 41104eeddc0SDimitry Andricdef : PatSetCC<FPR32, any_fsetccs, SETLE, FLE_S>; 41204eeddc0SDimitry Andricdef : PatSetCC<FPR32, any_fsetccs, SETOLE, FLE_S>; 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andricdef Select_FPR32_Using_CC_GPR : SelectCC_rrirr<FPR32, GPR>; 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric/// Loads 4170b57cec5SDimitry Andric 418fe6060f1SDimitry Andricdefm : LdPat<load, FLW, f32>; 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric/// Stores 4210b57cec5SDimitry Andric 422fe6060f1SDimitry Andricdefm : StPat<store, FSW, FPR32, f32>; 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric} // Predicates = [HasStdExtF] 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV32] in { 427e8d8bef9SDimitry Andric// Moves (no conversion) 428fe6060f1SDimitry Andricdef : Pat<(bitconvert (i32 GPR:$rs1)), (FMV_W_X GPR:$rs1)>; 429fe6060f1SDimitry Andricdef : Pat<(i32 (bitconvert FPR32:$rs1)), (FMV_X_W FPR32:$rs1)>; 430e8d8bef9SDimitry Andric 4310b57cec5SDimitry Andric// float->[u]int. Round-to-zero must be used. 4320eae32dcSDimitry Andricdef : Pat<(i32 (any_fp_to_sint FPR32:$rs1)), (FCVT_W_S $rs1, 0b001)>; 4330eae32dcSDimitry Andricdef : Pat<(i32 (any_fp_to_uint FPR32:$rs1)), (FCVT_WU_S $rs1, 0b001)>; 434fe6060f1SDimitry Andric 435349cc55cSDimitry Andric// Saturating float->[u]int32. 43604eeddc0SDimitry Andricdef : Pat<(i32 (riscv_fcvt_x FPR32:$rs1, timm:$frm)), (FCVT_W_S $rs1, timm:$frm)>; 43704eeddc0SDimitry Andricdef : Pat<(i32 (riscv_fcvt_xu FPR32:$rs1, timm:$frm)), (FCVT_WU_S $rs1, timm:$frm)>; 438349cc55cSDimitry Andric 439fe6060f1SDimitry Andric// float->int32 with current rounding mode. 44004eeddc0SDimitry Andricdef : Pat<(i32 (any_lrint FPR32:$rs1)), (FCVT_W_S $rs1, 0b111)>; 441fe6060f1SDimitry Andric 442fe6060f1SDimitry Andric// float->int32 rounded to nearest with ties rounded away from zero. 44304eeddc0SDimitry Andricdef : Pat<(i32 (any_lround FPR32:$rs1)), (FCVT_W_S $rs1, 0b100)>; 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric// [u]int->float. Match GCC and default to using dynamic rounding mode. 4460eae32dcSDimitry Andricdef : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W $rs1, 0b111)>; 4470eae32dcSDimitry Andricdef : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU $rs1, 0b111)>; 4480b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV32] 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV64] in { 451e8d8bef9SDimitry Andric// Moves (no conversion) 4520b57cec5SDimitry Andricdef : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (FMV_W_X GPR:$src)>; 4530b57cec5SDimitry Andricdef : Pat<(riscv_fmv_x_anyextw_rv64 FPR32:$src), (FMV_X_W FPR32:$src)>; 454e8d8bef9SDimitry Andricdef : Pat<(sext_inreg (riscv_fmv_x_anyextw_rv64 FPR32:$src), i32), 4550b57cec5SDimitry Andric (FMV_X_W FPR32:$src)>; 4560b57cec5SDimitry Andric 457fe6060f1SDimitry Andric// Use target specific isd nodes to help us remember the result is sign 458fe6060f1SDimitry Andric// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be 459fe6060f1SDimitry Andric// duplicated if it has another user that didn't need the sign_extend. 46004eeddc0SDimitry Andricdef : Pat<(riscv_any_fcvt_w_rv64 FPR32:$rs1, timm:$frm), (FCVT_W_S $rs1, timm:$frm)>; 46104eeddc0SDimitry Andricdef : Pat<(riscv_any_fcvt_wu_rv64 FPR32:$rs1, timm:$frm), (FCVT_WU_S $rs1, timm:$frm)>; 4620b57cec5SDimitry Andric 463fe6060f1SDimitry Andric// float->[u]int64. Round-to-zero must be used. 4640eae32dcSDimitry Andricdef : Pat<(i64 (any_fp_to_sint FPR32:$rs1)), (FCVT_L_S $rs1, 0b001)>; 4650eae32dcSDimitry Andricdef : Pat<(i64 (any_fp_to_uint FPR32:$rs1)), (FCVT_LU_S $rs1, 0b001)>; 466fe6060f1SDimitry Andric 467349cc55cSDimitry Andric// Saturating float->[u]int64. 46804eeddc0SDimitry Andricdef : Pat<(i64 (riscv_fcvt_x FPR32:$rs1, timm:$frm)), (FCVT_L_S $rs1, timm:$frm)>; 46904eeddc0SDimitry Andricdef : Pat<(i64 (riscv_fcvt_xu FPR32:$rs1, timm:$frm)), (FCVT_LU_S $rs1, timm:$frm)>; 470349cc55cSDimitry Andric 471fe6060f1SDimitry Andric// float->int64 with current rounding mode. 47204eeddc0SDimitry Andricdef : Pat<(i64 (any_lrint FPR32:$rs1)), (FCVT_L_S $rs1, 0b111)>; 47304eeddc0SDimitry Andricdef : Pat<(i64 (any_llrint FPR32:$rs1)), (FCVT_L_S $rs1, 0b111)>; 474fe6060f1SDimitry Andric 475fe6060f1SDimitry Andric// float->int64 rounded to neartest with ties rounded away from zero. 47604eeddc0SDimitry Andricdef : Pat<(i64 (any_lround FPR32:$rs1)), (FCVT_L_S $rs1, 0b100)>; 47704eeddc0SDimitry Andricdef : Pat<(i64 (any_llround FPR32:$rs1)), (FCVT_L_S $rs1, 0b100)>; 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric// [u]int->fp. Match GCC and default to using dynamic rounding mode. 4800eae32dcSDimitry Andricdef : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W $rs1, 0b111)>; 4810eae32dcSDimitry Andricdef : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU $rs1, 0b111)>; 4820eae32dcSDimitry Andricdef : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_S_L $rs1, 0b111)>; 4830eae32dcSDimitry Andricdef : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_S_LU $rs1, 0b111)>; 4840b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV64] 485