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