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 23fe6060f1SDimitry Andric : SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisFP<1>]>; 240eae32dcSDimitry Andricdef SDT_RISCVFCVT_X 25349cc55cSDimitry Andric : SDTypeProfile<1, 1, [SDTCisVT<0, XLenVT>, SDTCisFP<1>]>; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andricdef riscv_fmv_w_x_rv64 280b57cec5SDimitry Andric : SDNode<"RISCVISD::FMV_W_X_RV64", SDT_RISCVFMV_W_X_RV64>; 290b57cec5SDimitry Andricdef riscv_fmv_x_anyextw_rv64 300b57cec5SDimitry Andric : SDNode<"RISCVISD::FMV_X_ANYEXTW_RV64", SDT_RISCVFMV_X_ANYEXTW_RV64>; 31349cc55cSDimitry Andricdef riscv_fcvt_w_rtz_rv64 320eae32dcSDimitry Andric : SDNode<"RISCVISD::FCVT_W_RTZ_RV64", SDT_RISCVFCVT_W_RV64>; 33349cc55cSDimitry Andricdef riscv_fcvt_wu_rtz_rv64 340eae32dcSDimitry Andric : SDNode<"RISCVISD::FCVT_WU_RTZ_RV64", SDT_RISCVFCVT_W_RV64>; 35349cc55cSDimitry Andricdef riscv_fcvt_x_rtz 360eae32dcSDimitry Andric : SDNode<"RISCVISD::FCVT_X_RTZ", SDT_RISCVFCVT_X>; 37349cc55cSDimitry Andricdef riscv_fcvt_xu_rtz 380eae32dcSDimitry Andric : SDNode<"RISCVISD::FCVT_XU_RTZ", SDT_RISCVFCVT_X>; 390eae32dcSDimitry Andric 400eae32dcSDimitry Andricdef riscv_strict_fcvt_w_rtz_rv64 410eae32dcSDimitry Andric : SDNode<"RISCVISD::STRICT_FCVT_W_RTZ_RV64", SDT_RISCVFCVT_W_RV64, 420eae32dcSDimitry Andric [SDNPHasChain]>; 430eae32dcSDimitry Andricdef riscv_strict_fcvt_wu_rtz_rv64 440eae32dcSDimitry Andric : SDNode<"RISCVISD::STRICT_FCVT_WU_RTZ_RV64", SDT_RISCVFCVT_W_RV64, 450eae32dcSDimitry Andric [SDNPHasChain]>; 460eae32dcSDimitry Andric 470eae32dcSDimitry Andricdef riscv_any_fcvt_w_rtz_rv64 : PatFrags<(ops node:$src), 480eae32dcSDimitry Andric [(riscv_strict_fcvt_w_rtz_rv64 node:$src), 490eae32dcSDimitry Andric (riscv_fcvt_w_rtz_rv64 node:$src)]>; 500eae32dcSDimitry Andricdef riscv_any_fcvt_wu_rtz_rv64 : PatFrags<(ops node:$src), 510eae32dcSDimitry Andric [(riscv_strict_fcvt_wu_rtz_rv64 node:$src), 520eae32dcSDimitry Andric (riscv_fcvt_wu_rtz_rv64 node:$src)]>; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 550b57cec5SDimitry Andric// Operand and SDNode transformation definitions. 560b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric// Floating-point rounding mode 590b57cec5SDimitry Andric 600b57cec5SDimitry Andricdef FRMArg : AsmOperandClass { 610b57cec5SDimitry Andric let Name = "FRMArg"; 620b57cec5SDimitry Andric let RenderMethod = "addFRMArgOperands"; 630b57cec5SDimitry Andric let DiagnosticType = "InvalidFRMArg"; 640b57cec5SDimitry Andric} 650b57cec5SDimitry Andric 660b57cec5SDimitry Andricdef frmarg : Operand<XLenVT> { 670b57cec5SDimitry Andric let ParserMatchClass = FRMArg; 680b57cec5SDimitry Andric let PrintMethod = "printFRMArg"; 690b57cec5SDimitry Andric let DecoderMethod = "decodeFRMArg"; 700b57cec5SDimitry Andric} 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 730b57cec5SDimitry Andric// Instruction class templates 740b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 750b57cec5SDimitry Andric 760eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1, 770eae32dcSDimitry Andric UseNamedOperandTable = 1, hasPostISelHook = 1 in 780eae32dcSDimitry Andricclass FPFMA_rrr_frm<RISCVOpcode opcode, bits<2> funct2, string opcodestr, 790eae32dcSDimitry Andric RegisterClass rty> 800eae32dcSDimitry Andric : RVInstR4Frm<funct2, opcode, (outs rty:$rd), 810eae32dcSDimitry Andric (ins rty:$rs1, rty:$rs2, rty:$rs3, frmarg:$frm), 820eae32dcSDimitry Andric opcodestr, "$rd, $rs1, $rs2, $rs3, $frm">; 830b57cec5SDimitry Andric 840eae32dcSDimitry Andricclass FPFMADynFrmAlias<FPFMA_rrr_frm Inst, string OpcodeStr, 850eae32dcSDimitry Andric RegisterClass rty> 860b57cec5SDimitry Andric : InstAlias<OpcodeStr#" $rd, $rs1, $rs2, $rs3", 870eae32dcSDimitry Andric (Inst rty:$rd, rty:$rs1, rty:$rs2, rty:$rs3, 0b111)>; 880b57cec5SDimitry Andric 890eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in 900eae32dcSDimitry Andricclass FPALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 910eae32dcSDimitry Andric RegisterClass rty> 920eae32dcSDimitry Andric : RVInstR<funct7, funct3, OPC_OP_FP, (outs rty:$rd), 930eae32dcSDimitry Andric (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2">; 940b57cec5SDimitry Andric 950eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1, 960eae32dcSDimitry Andric UseNamedOperandTable = 1, hasPostISelHook = 1 in 970eae32dcSDimitry Andricclass FPALU_rr_frm<bits<7> funct7, string opcodestr, RegisterClass rty> 980eae32dcSDimitry Andric : RVInstRFrm<funct7, OPC_OP_FP, (outs rty:$rd), 990eae32dcSDimitry Andric (ins rty:$rs1, rty:$rs2, frmarg:$frm), opcodestr, 1000eae32dcSDimitry Andric "$rd, $rs1, $rs2, $frm">; 1010b57cec5SDimitry Andric 1020eae32dcSDimitry Andricclass FPALUDynFrmAlias<FPALU_rr_frm Inst, string OpcodeStr, 1030eae32dcSDimitry Andric RegisterClass rty> 1040b57cec5SDimitry Andric : InstAlias<OpcodeStr#" $rd, $rs1, $rs2", 1050eae32dcSDimitry Andric (Inst rty:$rd, rty:$rs1, rty:$rs2, 0b111)>; 1060b57cec5SDimitry Andric 1070eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in 1080eae32dcSDimitry Andricclass FPUnaryOp_r<bits<7> funct7, bits<5> rs2val, bits<3> funct3, 1090eae32dcSDimitry Andric RegisterClass rdty, RegisterClass rs1ty, string opcodestr> 1100b57cec5SDimitry Andric : RVInstR<funct7, funct3, OPC_OP_FP, (outs rdty:$rd), (ins rs1ty:$rs1), 1110eae32dcSDimitry Andric opcodestr, "$rd, $rs1"> { 1120eae32dcSDimitry Andric let rs2 = rs2val; 1130eae32dcSDimitry Andric} 1140b57cec5SDimitry Andric 1150eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1, 1160eae32dcSDimitry Andric UseNamedOperandTable = 1, hasPostISelHook = 1 in 1170eae32dcSDimitry Andricclass FPUnaryOp_r_frm<bits<7> funct7, bits<5> rs2val, RegisterClass rdty, 1180eae32dcSDimitry Andric RegisterClass rs1ty, string opcodestr> 1190b57cec5SDimitry Andric : RVInstRFrm<funct7, OPC_OP_FP, (outs rdty:$rd), 1200eae32dcSDimitry Andric (ins rs1ty:$rs1, frmarg:$frm), opcodestr, 1210eae32dcSDimitry Andric "$rd, $rs1, $frm"> { 1220eae32dcSDimitry Andric let rs2 = rs2val; 1230eae32dcSDimitry Andric} 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andricclass FPUnaryOpDynFrmAlias<FPUnaryOp_r_frm Inst, string OpcodeStr, 1260b57cec5SDimitry Andric RegisterClass rdty, RegisterClass rs1ty> 1270b57cec5SDimitry Andric : InstAlias<OpcodeStr#" $rd, $rs1", 1280b57cec5SDimitry Andric (Inst rdty:$rd, rs1ty:$rs1, 0b111)>; 1290b57cec5SDimitry Andric 1300eae32dcSDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, mayRaiseFPException = 1 in 1310eae32dcSDimitry Andricclass FPCmp_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 1320eae32dcSDimitry Andric RegisterClass rty> 1330eae32dcSDimitry Andric : RVInstR<funct7, funct3, OPC_OP_FP, (outs GPR:$rd), 1340eae32dcSDimitry Andric (ins rty:$rs1, rty:$rs2), opcodestr, "$rd, $rs1, $rs2">; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 1370b57cec5SDimitry Andric// Instructions 1380b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in { 1410b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0 in 1420b57cec5SDimitry Andricdef FLW : RVInstI<0b010, OPC_LOAD_FP, (outs FPR32:$rd), 1430b57cec5SDimitry Andric (ins GPR:$rs1, simm12:$imm12), 14413138422SDimitry Andric "flw", "$rd, ${imm12}(${rs1})">, 1455ffd83dbSDimitry Andric Sched<[WriteFLD32, ReadFMemBase]>; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric// Operands for stores are in the order srcreg, base, offset rather than 1480b57cec5SDimitry Andric// reflecting the order these fields are specified in the instruction 1490b57cec5SDimitry Andric// encoding. 1500b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 1 in 1510b57cec5SDimitry Andricdef FSW : RVInstS<0b010, OPC_STORE_FP, (outs), 1520b57cec5SDimitry Andric (ins FPR32:$rs2, GPR:$rs1, simm12:$imm12), 15313138422SDimitry Andric "fsw", "$rs2, ${imm12}(${rs1})">, 1545ffd83dbSDimitry Andric Sched<[WriteFST32, ReadStoreData, ReadFMemBase]>; 1550b57cec5SDimitry Andric 1560eae32dcSDimitry Andriclet SchedRW = [WriteFMA32, ReadFMA32, ReadFMA32, ReadFMA32] in { 1570eae32dcSDimitry Andricdef FMADD_S : FPFMA_rrr_frm<OPC_MADD, 0b00, "fmadd.s", FPR32>; 1580eae32dcSDimitry Andricdef FMSUB_S : FPFMA_rrr_frm<OPC_MSUB, 0b00, "fmsub.s", FPR32>; 1590eae32dcSDimitry Andricdef FNMSUB_S : FPFMA_rrr_frm<OPC_NMSUB, 0b00, "fnmsub.s", FPR32>; 1600eae32dcSDimitry Andricdef FNMADD_S : FPFMA_rrr_frm<OPC_NMADD, 0b00, "fnmadd.s", FPR32>; 1610b57cec5SDimitry Andric} 1620eae32dcSDimitry Andric 1630eae32dcSDimitry Andricdef : FPFMADynFrmAlias<FMADD_S, "fmadd.s", FPR32>; 1640eae32dcSDimitry Andricdef : FPFMADynFrmAlias<FMSUB_S, "fmsub.s", FPR32>; 1650eae32dcSDimitry Andricdef : FPFMADynFrmAlias<FNMSUB_S, "fnmsub.s", FPR32>; 1660eae32dcSDimitry Andricdef : FPFMADynFrmAlias<FNMADD_S, "fnmadd.s", FPR32>; 1670eae32dcSDimitry Andric 1680eae32dcSDimitry Andricdef FADD_S : FPALU_rr_frm<0b0000000, "fadd.s", FPR32>, 1690eae32dcSDimitry Andric Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>; 1700eae32dcSDimitry Andricdef FSUB_S : FPALU_rr_frm<0b0000100, "fsub.s", FPR32>, 1710eae32dcSDimitry Andric Sched<[WriteFALU32, ReadFALU32, ReadFALU32]>; 1720eae32dcSDimitry Andricdef FMUL_S : FPALU_rr_frm<0b0001000, "fmul.s", FPR32>, 1730eae32dcSDimitry Andric Sched<[WriteFMul32, ReadFMul32, ReadFMul32]>; 1740eae32dcSDimitry Andricdef FDIV_S : FPALU_rr_frm<0b0001100, "fdiv.s", FPR32>, 1750eae32dcSDimitry Andric Sched<[WriteFDiv32, ReadFDiv32, ReadFDiv32]>; 1760eae32dcSDimitry Andric 1770eae32dcSDimitry Andricdef : FPALUDynFrmAlias<FADD_S, "fadd.s", FPR32>; 1780eae32dcSDimitry Andricdef : FPALUDynFrmAlias<FSUB_S, "fsub.s", FPR32>; 1790eae32dcSDimitry Andricdef : FPALUDynFrmAlias<FMUL_S, "fmul.s", FPR32>; 1800eae32dcSDimitry Andricdef : FPALUDynFrmAlias<FDIV_S, "fdiv.s", FPR32>; 1810eae32dcSDimitry Andric 1820eae32dcSDimitry Andricdef FSQRT_S : FPUnaryOp_r_frm<0b0101100, 0b00000, FPR32, FPR32, "fsqrt.s">, 1830eae32dcSDimitry Andric Sched<[WriteFSqrt32, ReadFSqrt32]>; 1840b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FSQRT_S, "fsqrt.s", FPR32, FPR32>; 1850b57cec5SDimitry Andric 1860eae32dcSDimitry Andriclet SchedRW = [WriteFSGNJ32, ReadFSGNJ32, ReadFSGNJ32], 1870eae32dcSDimitry Andric mayRaiseFPException = 0 in { 1880eae32dcSDimitry Andricdef FSGNJ_S : FPALU_rr<0b0010000, 0b000, "fsgnj.s", FPR32>; 1890eae32dcSDimitry Andricdef FSGNJN_S : FPALU_rr<0b0010000, 0b001, "fsgnjn.s", FPR32>; 1900eae32dcSDimitry Andricdef FSGNJX_S : FPALU_rr<0b0010000, 0b010, "fsgnjx.s", FPR32>; 1910b57cec5SDimitry Andric} 1920eae32dcSDimitry Andric 1930eae32dcSDimitry Andriclet SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in { 1940eae32dcSDimitry Andricdef FMIN_S : FPALU_rr<0b0010100, 0b000, "fmin.s", FPR32>; 1950eae32dcSDimitry Andricdef FMAX_S : FPALU_rr<0b0010100, 0b001, "fmax.s", FPR32>; 1960eae32dcSDimitry Andric} 1970eae32dcSDimitry Andric 1980eae32dcSDimitry Andricdef FCVT_W_S : FPUnaryOp_r_frm<0b1100000, 0b00000, GPR, FPR32, "fcvt.w.s">, 1990eae32dcSDimitry Andric Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>; 2000b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_W_S, "fcvt.w.s", GPR, FPR32>; 2010b57cec5SDimitry Andric 2020eae32dcSDimitry Andricdef FCVT_WU_S : FPUnaryOp_r_frm<0b1100000, 0b00001, GPR, FPR32, "fcvt.wu.s">, 2030eae32dcSDimitry Andric Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>; 2040b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_WU_S, "fcvt.wu.s", GPR, FPR32>; 2050b57cec5SDimitry Andric 2060eae32dcSDimitry Andriclet mayRaiseFPException = 0 in 2070eae32dcSDimitry Andricdef FMV_X_W : FPUnaryOp_r<0b1110000, 0b00000, 0b000, GPR, FPR32, "fmv.x.w">, 2080eae32dcSDimitry Andric Sched<[WriteFMovF32ToI32, ReadFMovF32ToI32]>; 2090eae32dcSDimitry Andric 2100eae32dcSDimitry Andriclet SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in { 2110eae32dcSDimitry Andricdef FEQ_S : FPCmp_rr<0b1010000, 0b010, "feq.s", FPR32>; 2120eae32dcSDimitry Andricdef FLT_S : FPCmp_rr<0b1010000, 0b001, "flt.s", FPR32>; 2130eae32dcSDimitry Andricdef FLE_S : FPCmp_rr<0b1010000, 0b000, "fle.s", FPR32>; 2140b57cec5SDimitry Andric} 2150b57cec5SDimitry Andric 2160eae32dcSDimitry Andriclet mayRaiseFPException = 0 in 2170eae32dcSDimitry Andricdef FCLASS_S : FPUnaryOp_r<0b1110000, 0b00000, 0b001, GPR, FPR32, "fclass.s">, 2180eae32dcSDimitry Andric Sched<[WriteFClass32, ReadFClass32]>; 2190b57cec5SDimitry Andric 2200eae32dcSDimitry Andricdef FCVT_S_W : FPUnaryOp_r_frm<0b1101000, 0b00000, FPR32, GPR, "fcvt.s.w">, 2210eae32dcSDimitry Andric Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>; 2220b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_S_W, "fcvt.s.w", FPR32, GPR>; 2230b57cec5SDimitry Andric 2240eae32dcSDimitry Andricdef FCVT_S_WU : FPUnaryOp_r_frm<0b1101000, 0b00001, FPR32, GPR, "fcvt.s.wu">, 2250eae32dcSDimitry Andric Sched<[WriteFCvtI32ToF32, ReadFCvtI32ToF32]>; 2260b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_S_WU, "fcvt.s.wu", FPR32, GPR>; 2270b57cec5SDimitry Andric 2280eae32dcSDimitry Andriclet mayRaiseFPException = 0 in 2290eae32dcSDimitry Andricdef FMV_W_X : FPUnaryOp_r<0b1111000, 0b00000, 0b000, FPR32, GPR, "fmv.w.x">, 2300eae32dcSDimitry Andric Sched<[WriteFMovI32ToF32, ReadFMovI32ToF32]>; 2310b57cec5SDimitry Andric} // Predicates = [HasStdExtF] 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV64] in { 2340eae32dcSDimitry Andricdef FCVT_L_S : FPUnaryOp_r_frm<0b1100000, 0b00010, GPR, FPR32, "fcvt.l.s">, 2350eae32dcSDimitry Andric Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>; 2360b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_L_S, "fcvt.l.s", GPR, FPR32>; 2370b57cec5SDimitry Andric 2380eae32dcSDimitry Andricdef FCVT_LU_S : FPUnaryOp_r_frm<0b1100000, 0b00011, GPR, FPR32, "fcvt.lu.s">, 2390eae32dcSDimitry Andric Sched<[WriteFCvtF32ToI64, ReadFCvtF32ToI64]>; 2400b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_LU_S, "fcvt.lu.s", GPR, FPR32>; 2410b57cec5SDimitry Andric 2420eae32dcSDimitry Andricdef FCVT_S_L : FPUnaryOp_r_frm<0b1101000, 0b00010, FPR32, GPR, "fcvt.s.l">, 2430eae32dcSDimitry Andric Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>; 2440b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_S_L, "fcvt.s.l", FPR32, GPR>; 2450b57cec5SDimitry Andric 2460eae32dcSDimitry Andricdef FCVT_S_LU : FPUnaryOp_r_frm<0b1101000, 0b00011, FPR32, GPR, "fcvt.s.lu">, 2470eae32dcSDimitry Andric Sched<[WriteFCvtI64ToF32, ReadFCvtI64ToF32]>; 2480b57cec5SDimitry Andricdef : FPUnaryOpDynFrmAlias<FCVT_S_LU, "fcvt.s.lu", FPR32, GPR>; 2490b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV64] 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 2520b57cec5SDimitry Andric// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 2530b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in { 2560b57cec5SDimitry Andricdef : InstAlias<"flw $rd, (${rs1})", (FLW FPR32:$rd, GPR:$rs1, 0), 0>; 2570b57cec5SDimitry Andricdef : InstAlias<"fsw $rs2, (${rs1})", (FSW FPR32:$rs2, GPR:$rs1, 0), 0>; 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andricdef : InstAlias<"fmv.s $rd, $rs", (FSGNJ_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; 2600b57cec5SDimitry Andricdef : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; 2610b57cec5SDimitry Andricdef : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>; 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric// fgt.s/fge.s are recognised by the GNU assembler but the canonical 2640b57cec5SDimitry Andric// flt.s/fle.s forms will always be printed. Therefore, set a zero weight. 2650b57cec5SDimitry Andricdef : InstAlias<"fgt.s $rd, $rs, $rt", 2660b57cec5SDimitry Andric (FLT_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>; 2670b57cec5SDimitry Andricdef : InstAlias<"fge.s $rd, $rs, $rt", 2680b57cec5SDimitry Andric (FLE_S GPR:$rd, FPR32:$rt, FPR32:$rs), 0>; 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric// The following csr instructions actually alias instructions from the base ISA. 2710b57cec5SDimitry Andric// However, it only makes sense to support them when the F extension is enabled. 2720b57cec5SDimitry Andric// NOTE: "frcsr", "frrm", and "frflags" are more specialized version of "csrr". 273fe6060f1SDimitry Andricdef : InstAlias<"frcsr $rd", (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 2>; 274fe6060f1SDimitry Andricdef : InstAlias<"fscsr $rd, $rs", (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs)>; 275fe6060f1SDimitry Andricdef : InstAlias<"fscsr $rs", (CSRRW X0, SysRegFCSR.Encoding, GPR:$rs), 2>; 2760b57cec5SDimitry Andric 2778bcb0991SDimitry Andric// frsr, fssr are obsolete aliases replaced by frcsr, fscsr, so give them 2788bcb0991SDimitry Andric// zero weight. 279fe6060f1SDimitry Andricdef : InstAlias<"frsr $rd", (CSRRS GPR:$rd, SysRegFCSR.Encoding, X0), 0>; 280fe6060f1SDimitry Andricdef : InstAlias<"fssr $rd, $rs", (CSRRW GPR:$rd, SysRegFCSR.Encoding, GPR:$rs), 0>; 281fe6060f1SDimitry Andricdef : InstAlias<"fssr $rs", (CSRRW X0, SysRegFCSR.Encoding, GPR:$rs), 0>; 2828bcb0991SDimitry Andric 283fe6060f1SDimitry Andricdef : InstAlias<"frrm $rd", (CSRRS GPR:$rd, SysRegFRM.Encoding, X0), 2>; 284fe6060f1SDimitry Andricdef : InstAlias<"fsrm $rd, $rs", (CSRRW GPR:$rd, SysRegFRM.Encoding, GPR:$rs)>; 285fe6060f1SDimitry Andricdef : InstAlias<"fsrm $rs", (CSRRW X0, SysRegFRM.Encoding, GPR:$rs), 2>; 286fe6060f1SDimitry Andricdef : InstAlias<"fsrmi $rd, $imm", (CSRRWI GPR:$rd, SysRegFRM.Encoding, uimm5:$imm)>; 287fe6060f1SDimitry Andricdef : InstAlias<"fsrmi $imm", (CSRRWI X0, SysRegFRM.Encoding, uimm5:$imm), 2>; 2880b57cec5SDimitry Andric 289fe6060f1SDimitry Andricdef : InstAlias<"frflags $rd", (CSRRS GPR:$rd, SysRegFFLAGS.Encoding, X0), 2>; 290fe6060f1SDimitry Andricdef : InstAlias<"fsflags $rd, $rs", (CSRRW GPR:$rd, SysRegFFLAGS.Encoding, GPR:$rs)>; 291fe6060f1SDimitry Andricdef : InstAlias<"fsflags $rs", (CSRRW X0, SysRegFFLAGS.Encoding, GPR:$rs), 2>; 292fe6060f1SDimitry Andricdef : InstAlias<"fsflagsi $rd, $imm", (CSRRWI GPR:$rd, SysRegFFLAGS.Encoding, uimm5:$imm)>; 293fe6060f1SDimitry Andricdef : InstAlias<"fsflagsi $imm", (CSRRWI X0, SysRegFFLAGS.Encoding, uimm5:$imm), 2>; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric// fmv.w.x and fmv.x.w were previously known as fmv.s.x and fmv.x.s. Both 2960b57cec5SDimitry Andric// spellings should be supported by standard tools. 2970b57cec5SDimitry Andricdef : MnemonicAlias<"fmv.s.x", "fmv.w.x">; 2980b57cec5SDimitry Andricdef : MnemonicAlias<"fmv.x.s", "fmv.x.w">; 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andricdef PseudoFLW : PseudoFloatLoad<"flw", FPR32>; 3010b57cec5SDimitry Andricdef PseudoFSW : PseudoStore<"fsw", FPR32>; 3020b57cec5SDimitry Andric} // Predicates = [HasStdExtF] 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 3050b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns 3060b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 3070b57cec5SDimitry Andric 3085ffd83dbSDimitry Andric/// Floating point constants 3095ffd83dbSDimitry Andricdef fpimm0 : PatLeaf<(fpimm), [{ return N->isExactlyValue(+0.0); }]>; 3105ffd83dbSDimitry Andric 3110b57cec5SDimitry Andric/// Generic pattern classes 3120b57cec5SDimitry Andricclass PatFpr32Fpr32<SDPatternOperator OpNode, RVInstR Inst> 3130b57cec5SDimitry Andric : Pat<(OpNode FPR32:$rs1, FPR32:$rs2), (Inst $rs1, $rs2)>; 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andricclass PatFpr32Fpr32DynFrm<SDPatternOperator OpNode, RVInstRFrm Inst> 3160b57cec5SDimitry Andric : Pat<(OpNode FPR32:$rs1, FPR32:$rs2), (Inst $rs1, $rs2, 0b111)>; 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andriclet Predicates = [HasStdExtF] in { 3190b57cec5SDimitry Andric 3205ffd83dbSDimitry Andric/// Float constants 3215ffd83dbSDimitry Andricdef : Pat<(f32 (fpimm0)), (FMV_W_X X0)>; 3225ffd83dbSDimitry Andric 3230b57cec5SDimitry Andric/// Float conversion operations 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric// [u]int32<->float conversion patterns must be gated on IsRV32 or IsRV64, so 3260b57cec5SDimitry Andric// are defined later. 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric/// Float arithmetic operations 3290b57cec5SDimitry Andric 3300eae32dcSDimitry Andricdef : PatFpr32Fpr32DynFrm<any_fadd, FADD_S>; 3310eae32dcSDimitry Andricdef : PatFpr32Fpr32DynFrm<any_fsub, FSUB_S>; 3320eae32dcSDimitry Andricdef : PatFpr32Fpr32DynFrm<any_fmul, FMUL_S>; 3330eae32dcSDimitry Andricdef : PatFpr32Fpr32DynFrm<any_fdiv, FDIV_S>; 3340b57cec5SDimitry Andric 3350eae32dcSDimitry Andricdef : Pat<(any_fsqrt FPR32:$rs1), (FSQRT_S FPR32:$rs1, 0b111)>; 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andricdef : Pat<(fneg FPR32:$rs1), (FSGNJN_S $rs1, $rs1)>; 3380b57cec5SDimitry Andricdef : Pat<(fabs FPR32:$rs1), (FSGNJX_S $rs1, $rs1)>; 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andricdef : PatFpr32Fpr32<fcopysign, FSGNJ_S>; 3410b57cec5SDimitry Andricdef : Pat<(fcopysign FPR32:$rs1, (fneg FPR32:$rs2)), (FSGNJN_S $rs1, $rs2)>; 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric// fmadd: rs1 * rs2 + rs3 3440eae32dcSDimitry Andricdef : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, FPR32:$rs3), 3450b57cec5SDimitry Andric (FMADD_S $rs1, $rs2, $rs3, 0b111)>; 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric// fmsub: rs1 * rs2 - rs3 3480eae32dcSDimitry Andricdef : Pat<(any_fma FPR32:$rs1, FPR32:$rs2, (fneg FPR32:$rs3)), 3490b57cec5SDimitry Andric (FMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>; 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric// fnmsub: -rs1 * rs2 + rs3 3520eae32dcSDimitry Andricdef : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, FPR32:$rs3), 3530b57cec5SDimitry Andric (FNMSUB_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>; 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric// fnmadd: -rs1 * rs2 - rs3 3560eae32dcSDimitry Andricdef : Pat<(any_fma (fneg FPR32:$rs1), FPR32:$rs2, (fneg FPR32:$rs3)), 3570b57cec5SDimitry Andric (FNMADD_S FPR32:$rs1, FPR32:$rs2, FPR32:$rs3, 0b111)>; 3580b57cec5SDimitry Andric 359fe6060f1SDimitry Andric// The ratified 20191213 ISA spec defines fmin and fmax in a way that matches 360fe6060f1SDimitry Andric// LLVM's fminnum and fmaxnum 3610b57cec5SDimitry Andric// <https://github.com/riscv/riscv-isa-manual/commit/cd20cee7efd9bac7c5aa127ec3b451749d2b3cce>. 3620b57cec5SDimitry Andricdef : PatFpr32Fpr32<fminnum, FMIN_S>; 3630b57cec5SDimitry Andricdef : PatFpr32Fpr32<fmaxnum, FMAX_S>; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric/// Setcc 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andricdef : PatFpr32Fpr32<seteq, FEQ_S>; 3680b57cec5SDimitry Andricdef : PatFpr32Fpr32<setoeq, FEQ_S>; 3690b57cec5SDimitry Andricdef : PatFpr32Fpr32<setlt, FLT_S>; 3700b57cec5SDimitry Andricdef : PatFpr32Fpr32<setolt, FLT_S>; 3710b57cec5SDimitry Andricdef : PatFpr32Fpr32<setle, FLE_S>; 3720b57cec5SDimitry Andricdef : PatFpr32Fpr32<setole, FLE_S>; 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andricdef Select_FPR32_Using_CC_GPR : SelectCC_rrirr<FPR32, GPR>; 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric/// Loads 3770b57cec5SDimitry Andric 378fe6060f1SDimitry Andricdefm : LdPat<load, FLW, f32>; 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric/// Stores 3810b57cec5SDimitry Andric 382fe6060f1SDimitry Andricdefm : StPat<store, FSW, FPR32, f32>; 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric} // Predicates = [HasStdExtF] 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV32] in { 387e8d8bef9SDimitry Andric// Moves (no conversion) 388fe6060f1SDimitry Andricdef : Pat<(bitconvert (i32 GPR:$rs1)), (FMV_W_X GPR:$rs1)>; 389fe6060f1SDimitry Andricdef : Pat<(i32 (bitconvert FPR32:$rs1)), (FMV_X_W FPR32:$rs1)>; 390e8d8bef9SDimitry Andric 3910b57cec5SDimitry Andric// float->[u]int. Round-to-zero must be used. 3920eae32dcSDimitry Andricdef : Pat<(i32 (any_fp_to_sint FPR32:$rs1)), (FCVT_W_S $rs1, 0b001)>; 3930eae32dcSDimitry Andricdef : Pat<(i32 (any_fp_to_uint FPR32:$rs1)), (FCVT_WU_S $rs1, 0b001)>; 394fe6060f1SDimitry Andric 395349cc55cSDimitry Andric// Saturating float->[u]int32. 396349cc55cSDimitry Andricdef : Pat<(i32 (riscv_fcvt_x_rtz FPR32:$rs1)), (FCVT_W_S $rs1, 0b001)>; 397349cc55cSDimitry Andricdef : Pat<(i32 (riscv_fcvt_xu_rtz FPR32:$rs1)), (FCVT_WU_S $rs1, 0b001)>; 398349cc55cSDimitry Andric 399fe6060f1SDimitry Andric// float->int32 with current rounding mode. 400fe6060f1SDimitry Andricdef : Pat<(i32 (lrint FPR32:$rs1)), (FCVT_W_S $rs1, 0b111)>; 401fe6060f1SDimitry Andric 402fe6060f1SDimitry Andric// float->int32 rounded to nearest with ties rounded away from zero. 403fe6060f1SDimitry Andricdef : Pat<(i32 (lround FPR32:$rs1)), (FCVT_W_S $rs1, 0b100)>; 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric// [u]int->float. Match GCC and default to using dynamic rounding mode. 4060eae32dcSDimitry Andricdef : Pat<(any_sint_to_fp (i32 GPR:$rs1)), (FCVT_S_W $rs1, 0b111)>; 4070eae32dcSDimitry Andricdef : Pat<(any_uint_to_fp (i32 GPR:$rs1)), (FCVT_S_WU $rs1, 0b111)>; 4080b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV32] 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andriclet Predicates = [HasStdExtF, IsRV64] in { 411e8d8bef9SDimitry Andric// Moves (no conversion) 4120b57cec5SDimitry Andricdef : Pat<(riscv_fmv_w_x_rv64 GPR:$src), (FMV_W_X GPR:$src)>; 4130b57cec5SDimitry Andricdef : Pat<(riscv_fmv_x_anyextw_rv64 FPR32:$src), (FMV_X_W FPR32:$src)>; 414e8d8bef9SDimitry Andricdef : Pat<(sext_inreg (riscv_fmv_x_anyextw_rv64 FPR32:$src), i32), 4150b57cec5SDimitry Andric (FMV_X_W FPR32:$src)>; 4160b57cec5SDimitry Andric 417fe6060f1SDimitry Andric// Use target specific isd nodes to help us remember the result is sign 418fe6060f1SDimitry Andric// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be 419fe6060f1SDimitry Andric// duplicated if it has another user that didn't need the sign_extend. 4200eae32dcSDimitry Andricdef : Pat<(riscv_any_fcvt_w_rtz_rv64 FPR32:$rs1), (FCVT_W_S $rs1, 0b001)>; 4210eae32dcSDimitry Andricdef : Pat<(riscv_any_fcvt_wu_rtz_rv64 FPR32:$rs1), (FCVT_WU_S $rs1, 0b001)>; 4220b57cec5SDimitry Andric 423fe6060f1SDimitry Andric// float->[u]int64. Round-to-zero must be used. 4240eae32dcSDimitry Andricdef : Pat<(i64 (any_fp_to_sint FPR32:$rs1)), (FCVT_L_S $rs1, 0b001)>; 4250eae32dcSDimitry Andricdef : Pat<(i64 (any_fp_to_uint FPR32:$rs1)), (FCVT_LU_S $rs1, 0b001)>; 426fe6060f1SDimitry Andric 427349cc55cSDimitry Andric// Saturating float->[u]int64. 428349cc55cSDimitry Andricdef : Pat<(i64 (riscv_fcvt_x_rtz FPR32:$rs1)), (FCVT_L_S $rs1, 0b001)>; 429349cc55cSDimitry Andricdef : Pat<(i64 (riscv_fcvt_xu_rtz FPR32:$rs1)), (FCVT_LU_S $rs1, 0b001)>; 430349cc55cSDimitry Andric 431fe6060f1SDimitry Andric// float->int64 with current rounding mode. 432fe6060f1SDimitry Andricdef : Pat<(i64 (lrint FPR32:$rs1)), (FCVT_L_S $rs1, 0b111)>; 433fe6060f1SDimitry Andricdef : Pat<(i64 (llrint FPR32:$rs1)), (FCVT_L_S $rs1, 0b111)>; 434fe6060f1SDimitry Andric 435fe6060f1SDimitry Andric// float->int64 rounded to neartest with ties rounded away from zero. 436fe6060f1SDimitry Andricdef : Pat<(i64 (lround FPR32:$rs1)), (FCVT_L_S $rs1, 0b100)>; 437fe6060f1SDimitry Andricdef : Pat<(i64 (llround FPR32:$rs1)), (FCVT_L_S $rs1, 0b100)>; 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric// [u]int->fp. Match GCC and default to using dynamic rounding mode. 4400eae32dcSDimitry Andricdef : Pat<(any_sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_S_W $rs1, 0b111)>; 4410eae32dcSDimitry Andricdef : Pat<(any_uint_to_fp (i64 (zexti32 (i64 GPR:$rs1)))), (FCVT_S_WU $rs1, 0b111)>; 4420eae32dcSDimitry Andricdef : Pat<(any_sint_to_fp (i64 GPR:$rs1)), (FCVT_S_L $rs1, 0b111)>; 4430eae32dcSDimitry Andricdef : Pat<(any_uint_to_fp (i64 GPR:$rs1)), (FCVT_S_LU $rs1, 0b111)>; 4440b57cec5SDimitry Andric} // Predicates = [HasStdExtF, IsRV64] 445