| //===-- RISCVInstrInfoXsf.td - SiFive custom instructions --*- tablegen -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file describes the vendor extensions defined by SiFive. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| //===----------------------------------------------------------------------===// |
| // XSFVCP extension instructions. |
| //===----------------------------------------------------------------------===// |
| |
| def VCIXVS2 : RISCVVConstraint<VS2Constraint.Value>; |
| def VCIXVS2VS1 : RISCVVConstraint<!or(VS2Constraint.Value, |
| VS1Constraint.Value)>; |
| |
| class VCIXType<bits<4> val> { |
| bits<4> Val = val; |
| } |
| |
| def VCIX_X : VCIXType<0b0000>; |
| def VCIX_XV : VCIXType<0b0010>; |
| def VCIX_XVV : VCIXType<0b1010>; |
| def VCIX_XVW : VCIXType<0b1111>; |
| |
| // The payload and timm5 operands are all marked as ImmArg in the IR |
| // intrinsic and will be target constant, so use TImmLeaf rather than ImmLeaf. |
| def payload1 : Operand<XLenVT>, TImmLeaf<XLenVT, [{return isUInt<1>(Imm);}]> { |
| let ParserMatchClass = UImmAsmOperand<1>; |
| let DecoderMethod = "decodeUImmOperand<1>"; |
| let OperandType = "OPERAND_UIMM1"; |
| let OperandNamespace = "RISCVOp"; |
| } |
| |
| def payload2 : Operand<XLenVT>, TImmLeaf<XLenVT, [{return isUInt<2>(Imm);}]> { |
| let ParserMatchClass = UImmAsmOperand<2>; |
| let DecoderMethod = "decodeUImmOperand<2>"; |
| let OperandType = "OPERAND_UIMM2"; |
| let OperandNamespace = "RISCVOp"; |
| } |
| |
| def payload5 : Operand<XLenVT>, TImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> { |
| let ParserMatchClass = UImmAsmOperand<5>; |
| let DecoderMethod = "decodeUImmOperand<5>"; |
| let OperandType = "OPERAND_UIMM5"; |
| let OperandNamespace = "RISCVOp"; |
| } |
| |
| def timm5 : Operand<XLenVT>, TImmLeaf<XLenVT, [{return isInt<5>(Imm);}]> { |
| let ParserMatchClass = SImmAsmOperand<5>; |
| let EncoderMethod = "getImmOpValue"; |
| let DecoderMethod = "decodeSImmOperand<5>"; |
| let MCOperandPredicate = [{ |
| int64_t Imm; |
| if (MCOp.evaluateAsConstantImm(Imm)) |
| return isInt<5>(Imm); |
| return MCOp.isBareSymbolRef(); |
| }]; |
| } |
| |
| class SwapVCIXIns<dag funct6, dag rd, dag rs2, dag rs1, bit swap> { |
| dag Ins = !con(funct6, !if(swap, rs2, rd), !if(swap, rd, rs2), rs1); |
| } |
| |
| class RVInstVCCustom2<bits<4> funct6_hi4, bits<3> funct3, dag outs, dag ins, |
| string opcodestr, string argstr> |
| : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> { |
| bits<5> rs2; |
| bits<5> rs1; |
| bits<5> rd; |
| bits<2> funct6_lo2; |
| bit vm; |
| |
| let Inst{31-28} = funct6_hi4; |
| let Inst{27-26} = funct6_lo2; |
| let Inst{25} = vm; |
| let Inst{24-20} = rs2; |
| let Inst{19-15} = rs1; |
| let Inst{14-12} = funct3; |
| let Inst{11-7} = rd; |
| let Inst{6-0} = OPC_CUSTOM_2.Value; |
| |
| let Uses = [VTYPE, VL]; |
| let RVVConstraint = NoConstraint; |
| } |
| |
| class RVInstVCFCustom2<bits<4> funct6_hi4, bits<3> funct3, dag outs, dag ins, |
| string opcodestr, string argstr> |
| : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> { |
| bits<5> rs2; |
| bits<5> rs1; |
| bits<5> rd; |
| bit funct6_lo1; |
| bit vm; |
| |
| let Inst{31-28} = funct6_hi4; |
| let Inst{27} = 1; |
| let Inst{26} = funct6_lo1; |
| let Inst{25} = vm; |
| let Inst{24-20} = rs2; |
| let Inst{19-15} = rs1; |
| let Inst{14-12} = funct3; |
| let Inst{11-7} = rd; |
| let Inst{6-0} = OPC_CUSTOM_2.Value; |
| |
| let Uses = [VTYPE, VL]; |
| let RVVConstraint = NoConstraint; |
| } |
| |
| class GetFTypeInfo<int sew> { |
| ValueType Scalar = !cond(!eq(sew, 16): f16, |
| !eq(sew, 32): f32, |
| !eq(sew, 64): f64); |
| RegisterClass ScalarRegClass = !cond(!eq(sew, 16): FPR16, |
| !eq(sew, 32): FPR32, |
| !eq(sew, 64): FPR64); |
| } |
| |
| class VCIXInfo<string suffix, VCIXType type, DAGOperand TyRd, |
| DAGOperand TyRs2, DAGOperand TyRs1, bit HaveOutputDst> { |
| string OpcodeStr = !if(HaveOutputDst, "sf.vc.v." # suffix, |
| "sf.vc." # suffix); |
| bits<4> Funct6_hi4 = type.Val; |
| bits<3> Funct3 = !cond(!eq(TyRs1, VR): 0b000, |
| !eq(TyRs1, GPR): 0b100, |
| !eq(TyRs1, FPR32): 0b101, |
| !eq(TyRs1, simm5): 0b011); |
| dag Outs = !if(!not(HaveOutputDst), (outs), |
| !if(!or(!eq(type, VCIX_XVV), !eq(type, VCIX_XVW)), |
| (outs TyRd:$rd_wb), (outs TyRd:$rd))); |
| dag Ins = SwapVCIXIns<!if(!ne(TyRs1, FPR32), (ins uimm2:$funct6_lo2), |
| (ins uimm1:$funct6_lo1)), |
| !if(!and(HaveOutputDst, !or(!eq(type, VCIX_X), |
| !eq(type, VCIX_XV))), |
| (ins), (ins TyRd:$rd)), |
| (ins TyRs2:$rs2), |
| (ins TyRs1:$rs1), |
| !if(!eq(type, VCIX_X), 1, 0)>.Ins; |
| string Prototype = !if(!eq(type, VCIX_X), "$funct6_lo2, $rs2, $rd, $rs1", |
| !if(!ne(TyRs1, FPR32), "$funct6_lo2, $rd, $rs2, $rs1", |
| "$funct6_lo1, $rd, $rs2, $rs1")); |
| string Constraints = !if(!not(HaveOutputDst), "", |
| !if(!or(!eq(type, VCIX_XVV), |
| !eq(type, VCIX_XVW)), "$rd = $rd_wb", "")); |
| RISCVVConstraint RVVConstraint = !if(!or(!not(HaveOutputDst), |
| !ne(type, VCIX_XVW)), NoConstraint, |
| !if(!eq(TyRs1, VR), VCIXVS2VS1, VCIXVS2)); |
| } |
| |
| class CustomSiFiveVCIX<VCIXInfo info> |
| : RVInstVCCustom2<info.Funct6_hi4, info.Funct3, info.Outs, |
| info.Ins, info.OpcodeStr, info.Prototype> { |
| let Constraints = info.Constraints; |
| let RVVConstraint = info.RVVConstraint; |
| } |
| |
| class CustomSiFiveVCIF<VCIXInfo info> |
| : RVInstVCFCustom2<info.Funct6_hi4, info.Funct3, info.Outs, |
| info.Ins, info.OpcodeStr, info.Prototype> { |
| let Constraints = info.Constraints; |
| let RVVConstraint = info.RVVConstraint; |
| } |
| |
| multiclass CustomSiFiveVCIXorVCIF<string suffix, VCIXType type, |
| DAGOperand TyRd, DAGOperand TyRs2, |
| DAGOperand TyRs1, bit HaveOutputDst> { |
| defvar info = VCIXInfo<suffix, type, TyRd, TyRs2, TyRs1, HaveOutputDst>; |
| if !eq(TyRs1, FPR32) then { |
| def NAME : CustomSiFiveVCIF<info>; |
| } else { |
| def NAME : CustomSiFiveVCIX<info>; |
| } |
| } |
| |
| multiclass CustomSiFiveVCIX<string suffix, VCIXType type, |
| DAGOperand InTyRd, DAGOperand InTyRs2, |
| DAGOperand InTyRs1> { |
| let vm = 1 in |
| defm VC_ # NAME : CustomSiFiveVCIXorVCIF<suffix, type, InTyRd, InTyRs2, |
| InTyRs1, 0>; |
| let vm = 0 in |
| defm VC_V_ # NAME : CustomSiFiveVCIXorVCIF<suffix, type, VR, InTyRs2, |
| InTyRs1, 1>; |
| } |
| |
| let Predicates = [HasVendorXSfvcp], mayLoad = 0, mayStore = 0, |
| hasSideEffects = 1, hasNoSchedulingInfo = 1, DecoderNamespace = "XSfvcp" in { |
| defm X : CustomSiFiveVCIX<"x", VCIX_X, uimm5, uimm5, GPR>, Sched<[]>; |
| defm I : CustomSiFiveVCIX<"i", VCIX_X, uimm5, uimm5, simm5>, Sched<[]>; |
| defm XV : CustomSiFiveVCIX<"xv", VCIX_XV, uimm5, VR, GPR>, Sched<[]>; |
| defm IV : CustomSiFiveVCIX<"iv", VCIX_XV, uimm5, VR, simm5>, Sched<[]>; |
| defm VV : CustomSiFiveVCIX<"vv", VCIX_XV, uimm5, VR, VR>, Sched<[]>; |
| defm FV : CustomSiFiveVCIX<"fv", VCIX_XV, uimm5, VR, FPR32>, Sched<[]>; |
| defm XVV : CustomSiFiveVCIX<"xvv", VCIX_XVV, VR, VR, GPR>, Sched<[]>; |
| defm IVV : CustomSiFiveVCIX<"ivv", VCIX_XVV, VR, VR, simm5>, Sched<[]>; |
| defm VVV : CustomSiFiveVCIX<"vvv", VCIX_XVV, VR, VR, VR>, Sched<[]>; |
| defm FVV : CustomSiFiveVCIX<"fvv", VCIX_XVV, VR, VR, FPR32>, Sched<[]>; |
| defm XVW : CustomSiFiveVCIX<"xvw", VCIX_XVW, VR, VR, GPR>, Sched<[]>; |
| defm IVW : CustomSiFiveVCIX<"ivw", VCIX_XVW, VR, VR, simm5>, Sched<[]>; |
| defm VVW : CustomSiFiveVCIX<"vvw", VCIX_XVW, VR, VR, VR>, Sched<[]>; |
| defm FVW : CustomSiFiveVCIX<"fvw", VCIX_XVW, VR, VR, FPR32>, Sched<[]>; |
| } |
| |
| class VPseudoVC_X<Operand OpClass, DAGOperand RS1Class, |
| bit HasSideEffect = 1> : |
| Pseudo<(outs), |
| (ins OpClass:$op1, payload5:$rs2, payload5:$rd, RS1Class:$r1, |
| AVL:$vl, ixlenimm:$sew), []>, |
| RISCVVPseudo { |
| let mayLoad = 0; |
| let mayStore = 0; |
| let HasVLOp = 1; |
| let HasSEWOp = 1; |
| let hasSideEffects = HasSideEffect; |
| let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); |
| } |
| |
| class VPseudoVC_XV<Operand OpClass, VReg RS2Class, DAGOperand RS1Class, |
| bit HasSideEffect = 1> : |
| Pseudo<(outs), |
| (ins OpClass:$op1, payload5:$rd, RS2Class:$rs2, RS1Class:$r1, |
| AVL:$vl, ixlenimm:$sew), []>, |
| RISCVVPseudo { |
| let mayLoad = 0; |
| let mayStore = 0; |
| let HasVLOp = 1; |
| let HasSEWOp = 1; |
| let hasSideEffects = HasSideEffect; |
| let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); |
| } |
| |
| class VPseudoVC_XVV<Operand OpClass, VReg RDClass, VReg RS2Class, |
| DAGOperand RS1Class, bit HasSideEffect = 1> : |
| Pseudo<(outs), |
| (ins OpClass:$op1, RDClass:$rd, RS2Class:$rs2, RS1Class:$r1, |
| AVL:$vl, ixlenimm:$sew), []>, |
| RISCVVPseudo { |
| let mayLoad = 0; |
| let mayStore = 0; |
| let HasVLOp = 1; |
| let HasSEWOp = 1; |
| let hasSideEffects = HasSideEffect; |
| let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); |
| } |
| |
| class VPseudoVC_V_X<Operand OpClass, VReg RDClass, DAGOperand RS1Class, |
| bit HasSideEffect = 1> : |
| Pseudo<(outs RDClass:$rd), |
| (ins OpClass:$op1, payload5:$rs2, RS1Class:$r1, |
| AVL:$vl, ixlenimm:$sew), []>, |
| RISCVVPseudo { |
| let mayLoad = 0; |
| let mayStore = 0; |
| let HasVLOp = 1; |
| let HasSEWOp = 1; |
| let hasSideEffects = HasSideEffect; |
| let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); |
| } |
| |
| class VPseudoVC_V_XV<Operand OpClass, VReg RDClass, VReg RS2Class, |
| DAGOperand RS1Class, bit HasSideEffect = 1> : |
| Pseudo<(outs RDClass:$rd), |
| (ins OpClass:$op1, RS2Class:$rs2, RS1Class:$r1, |
| AVL:$vl, ixlenimm:$sew), []>, |
| RISCVVPseudo { |
| let mayLoad = 0; |
| let mayStore = 0; |
| let HasVLOp = 1; |
| let HasSEWOp = 1; |
| let hasSideEffects = HasSideEffect; |
| let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); |
| } |
| |
| class VPseudoVC_V_XVV<Operand OpClass, VReg RDClass, VReg RS2Class, |
| DAGOperand RS1Class, bit HasSideEffect = 1> : |
| Pseudo<(outs RDClass:$rd), |
| (ins OpClass:$op1, RDClass:$rs3, RS2Class:$rs2, RS1Class:$r1, |
| AVL:$vl, ixlenimm:$sew), []>, |
| RISCVVPseudo { |
| let mayLoad = 0; |
| let mayStore = 0; |
| let HasVLOp = 1; |
| let HasSEWOp = 1; |
| let hasSideEffects = HasSideEffect; |
| let BaseInstr = !cast<Instruction>(PseudoToVInst<NAME>.VInst); |
| } |
| |
| multiclass VPseudoVC_X<LMULInfo m, DAGOperand RS1Class, |
| Operand OpClass = payload2> { |
| let VLMul = m.value in { |
| def "PseudoVC_" # NAME # "_SE_" # m.MX : VPseudoVC_X<OpClass, RS1Class>; |
| def "PseudoVC_V_" # NAME # "_SE_" # m.MX : VPseudoVC_V_X<OpClass, m.vrclass, RS1Class>; |
| def "PseudoVC_V_" # NAME # "_" # m.MX : VPseudoVC_V_X<OpClass, m.vrclass, RS1Class, 0>; |
| } |
| } |
| |
| multiclass VPseudoVC_XV<LMULInfo m, DAGOperand RS1Class, |
| Operand OpClass = payload2> { |
| let VLMul = m.value in { |
| def "PseudoVC_" # NAME # "_SE_" # m.MX : VPseudoVC_XV<OpClass, m.vrclass, RS1Class>; |
| def "PseudoVC_V_" # NAME # "_SE_" # m.MX : VPseudoVC_V_XV<OpClass, m.vrclass, m.vrclass, RS1Class>; |
| def "PseudoVC_V_" # NAME # "_" # m.MX : VPseudoVC_V_XV<OpClass, m.vrclass, m.vrclass, RS1Class, 0>; |
| } |
| } |
| |
| multiclass VPseudoVC_XVV<LMULInfo m, DAGOperand RS1Class, |
| Operand OpClass = payload2> { |
| let VLMul = m.value in { |
| def "PseudoVC_" # NAME # "_SE_" # m.MX : VPseudoVC_XVV<OpClass, m.vrclass, m.vrclass, RS1Class>; |
| def "PseudoVC_V_" # NAME # "_SE_" # m.MX : VPseudoVC_V_XVV<OpClass, m.vrclass, m.vrclass, RS1Class>; |
| def "PseudoVC_V_" # NAME # "_" # m.MX : VPseudoVC_V_XVV<OpClass, m.vrclass, m.vrclass, RS1Class, 0>; |
| } |
| } |
| |
| multiclass VPseudoVC_XVW<LMULInfo m, DAGOperand RS1Class, |
| Operand OpClass = payload2> { |
| let VLMul = m.value in { |
| def "PseudoVC_" # NAME # "_SE_" # m.MX : VPseudoVC_XVV<OpClass, m.wvrclass, m.vrclass, RS1Class>; |
| let Constraints = "@earlyclobber $rd, $rd = $rs3" in { |
| def "PseudoVC_V_" # NAME # "_SE_" # m.MX : VPseudoVC_V_XVV<OpClass, m.wvrclass, m.vrclass, RS1Class>; |
| def "PseudoVC_V_" # NAME # "_" # m.MX : VPseudoVC_V_XVV<OpClass, m.wvrclass, m.vrclass, RS1Class, 0>; |
| } |
| } |
| } |
| |
| let Predicates = [HasVendorXSfvcp] in { |
| foreach m = MxList in { |
| defm X : VPseudoVC_X<m, GPR>; |
| defm I : VPseudoVC_X<m, timm5>; |
| defm XV : VPseudoVC_XV<m, GPR>; |
| defm IV : VPseudoVC_XV<m, timm5>; |
| defm VV : VPseudoVC_XV<m, m.vrclass>; |
| defm XVV : VPseudoVC_XVV<m, GPR>; |
| defm IVV : VPseudoVC_XVV<m, timm5>; |
| defm VVV : VPseudoVC_XVV<m, m.vrclass>; |
| } |
| foreach f = FPList in { |
| foreach m = f.MxList in { |
| defm f.FX # "V" : VPseudoVC_XV<m, f.fprclass, payload1>; |
| defm f.FX # "VV" : VPseudoVC_XVV<m, f.fprclass, payload1>; |
| } |
| } |
| foreach m = MxListW in { |
| defm XVW : VPseudoVC_XVW<m, GPR>; |
| defm IVW : VPseudoVC_XVW<m, timm5>; |
| defm VVW : VPseudoVC_XVW<m, m.vrclass>; |
| } |
| foreach f = FPListW in { |
| foreach m = f.MxList in |
| defm f.FX # "VW" : VPseudoVC_XVW<m, f.fprclass, payload1>; |
| } |
| } |
| |
| class VPatVC_OP4<string intrinsic_name, |
| string inst, |
| ValueType op2_type, |
| ValueType op3_type, |
| ValueType op4_type, |
| int sew, |
| DAGOperand op2_kind, |
| DAGOperand op3_kind, |
| DAGOperand op4_kind, |
| Operand op1_kind = payload2> : |
| Pat<(!cast<Intrinsic>(intrinsic_name) |
| (XLenVT op1_kind:$op1), |
| (op2_type op2_kind:$op2), |
| (op3_type op3_kind:$op3), |
| (op4_type op4_kind:$op4), |
| VLOpFrag), |
| (!cast<Instruction>(inst) |
| (XLenVT op1_kind:$op1), |
| (op2_type op2_kind:$op2), |
| (op3_type op3_kind:$op3), |
| (op4_type op4_kind:$op4), |
| GPR:$vl, sew)>; |
| |
| class VPatVC_V_OP4<string intrinsic_name, |
| string inst, |
| ValueType result_type, |
| ValueType op2_type, |
| ValueType op3_type, |
| ValueType op4_type, |
| int sew, |
| DAGOperand op2_kind, |
| DAGOperand op3_kind, |
| DAGOperand op4_kind, |
| Operand op1_kind = payload2> : |
| Pat<(result_type (!cast<Intrinsic>(intrinsic_name) |
| (XLenVT op1_kind:$op1), |
| (op2_type op2_kind:$op2), |
| (op3_type op3_kind:$op3), |
| (op4_type op4_kind:$op4), |
| VLOpFrag)), |
| (!cast<Instruction>(inst) |
| (XLenVT op1_kind:$op1), |
| (op2_type op2_kind:$op2), |
| (op3_type op3_kind:$op3), |
| (op4_type op4_kind:$op4), |
| GPR:$vl, sew)>; |
| |
| class VPatVC_V_OP3<string intrinsic_name, |
| string inst, |
| ValueType result_type, |
| ValueType op2_type, |
| ValueType op3_type, |
| int sew, |
| DAGOperand op2_kind, |
| DAGOperand op3_kind, |
| Operand op1_kind = payload2> : |
| Pat<(result_type (!cast<Intrinsic>(intrinsic_name) |
| (XLenVT op1_kind:$op1), |
| (op2_type op2_kind:$op2), |
| (op3_type op3_kind:$op3), |
| VLOpFrag)), |
| (!cast<Instruction>(inst) |
| (XLenVT op1_kind:$op1), |
| (op2_type op2_kind:$op2), |
| (op3_type op3_kind:$op3), |
| GPR:$vl, sew)>; |
| |
| multiclass VPatVC_X<string intrinsic_suffix, string instruction_suffix, |
| VTypeInfo vti, ValueType type, DAGOperand kind> { |
| def : VPatVC_OP4<"int_riscv_sf_vc_" # intrinsic_suffix # "_se_e" # vti.SEW # !tolower(vti.LMul.MX), |
| "PseudoVC_" # instruction_suffix # "_SE_" # vti.LMul.MX, |
| XLenVT, XLenVT, type, vti.Log2SEW, |
| payload5, payload5, kind>; |
| def : VPatVC_V_OP3<"int_riscv_sf_vc_v_" # intrinsic_suffix # "_se", |
| "PseudoVC_V_" # instruction_suffix # "_SE_" # vti.LMul.MX, |
| vti.Vector, XLenVT, type, vti.Log2SEW, |
| payload5, kind>; |
| def : VPatVC_V_OP3<"int_riscv_sf_vc_v_" # intrinsic_suffix, |
| "PseudoVC_V_" # instruction_suffix # "_" # vti.LMul.MX, |
| vti.Vector, XLenVT, type, vti.Log2SEW, |
| payload5, kind>; |
| } |
| |
| multiclass VPatVC_XV<string intrinsic_suffix, string instruction_suffix, |
| VTypeInfo vti, ValueType type, DAGOperand kind, |
| Operand op1_kind = payload2> { |
| def : VPatVC_OP4<"int_riscv_sf_vc_" # intrinsic_suffix # "_se", |
| "PseudoVC_" # instruction_suffix # "_SE_" # vti.LMul.MX, |
| XLenVT, vti.Vector, type, vti.Log2SEW, |
| payload5, vti.RegClass, kind, op1_kind>; |
| def : VPatVC_V_OP3<"int_riscv_sf_vc_v_" # intrinsic_suffix # "_se", |
| "PseudoVC_V_" # instruction_suffix # "_SE_" # vti.LMul.MX, |
| vti.Vector, vti.Vector, type, vti.Log2SEW, |
| vti.RegClass, kind, op1_kind>; |
| def : VPatVC_V_OP3<"int_riscv_sf_vc_v_" # intrinsic_suffix, |
| "PseudoVC_V_" # instruction_suffix # "_" # vti.LMul.MX, |
| vti.Vector, vti.Vector, type, vti.Log2SEW, |
| vti.RegClass, kind, op1_kind>; |
| } |
| |
| multiclass VPatVC_XVV<string intrinsic_suffix, string instruction_suffix, |
| VTypeInfo wti, VTypeInfo vti, ValueType type, DAGOperand kind, |
| Operand op1_kind = payload2> { |
| def : VPatVC_OP4<"int_riscv_sf_vc_" # intrinsic_suffix # "_se", |
| "PseudoVC_" # instruction_suffix # "_SE_" # vti.LMul.MX, |
| wti.Vector, vti.Vector, type, vti.Log2SEW, |
| wti.RegClass, vti.RegClass, kind, op1_kind>; |
| def : VPatVC_V_OP4<"int_riscv_sf_vc_v_" # intrinsic_suffix # "_se", |
| "PseudoVC_V_" # instruction_suffix # "_SE_" # vti.LMul.MX, |
| wti.Vector, wti.Vector, vti.Vector, type, vti.Log2SEW, |
| wti.RegClass, vti.RegClass, kind, op1_kind>; |
| def : VPatVC_V_OP4<"int_riscv_sf_vc_v_" # intrinsic_suffix, |
| "PseudoVC_V_" # instruction_suffix # "_" # vti.LMul.MX, |
| wti.Vector, wti.Vector, vti.Vector, type, vti.Log2SEW, |
| wti.RegClass, vti.RegClass, kind, op1_kind>; |
| } |
| |
| let Predicates = [HasVendorXSfvcp] in { |
| foreach vti = AllIntegerVectors in { |
| defm : VPatVC_X<"x", "X", vti, vti.Scalar, vti.ScalarRegClass>; |
| defm : VPatVC_X<"i", "I", vti, XLenVT, timm5>; |
| defm : VPatVC_XV<"xv", "XV", vti, vti.Scalar, vti.ScalarRegClass>; |
| defm : VPatVC_XV<"iv", "IV", vti, XLenVT, timm5>; |
| defm : VPatVC_XV<"vv", "VV", vti, vti.Vector, vti.RegClass>; |
| defm : VPatVC_XVV<"xvv", "XVV", vti, vti, vti.Scalar, vti.ScalarRegClass>; |
| defm : VPatVC_XVV<"ivv", "IVV", vti, vti, XLenVT, timm5>; |
| defm : VPatVC_XVV<"vvv", "VVV", vti, vti, vti.Vector, vti.RegClass>; |
| if !ge(vti.SEW, 16) then { |
| defm : VPatVC_XV<"fv", "F" # vti.SEW # "V", vti, |
| GetFTypeInfo<vti.SEW>.Scalar, |
| GetFTypeInfo<vti.SEW>.ScalarRegClass, payload1>; |
| defm : VPatVC_XVV<"fvv", "F" # vti.SEW # "VV", vti, vti, |
| GetFTypeInfo<vti.SEW>.Scalar, |
| GetFTypeInfo<vti.SEW>.ScalarRegClass, payload1>; |
| } |
| } |
| foreach VtiToWti = AllWidenableIntVectors in { |
| defvar vti = VtiToWti.Vti; |
| defvar wti = VtiToWti.Wti; |
| defm : VPatVC_XVV<"xvw", "XVW", wti, vti, vti.Scalar, vti.ScalarRegClass>; |
| defm : VPatVC_XVV<"ivw", "IVW", wti, vti, XLenVT, timm5>; |
| defm : VPatVC_XVV<"vvw", "VVW", wti, vti, vti.Vector, vti.RegClass>; |
| if !ge(vti.SEW, 16) then { |
| defm : VPatVC_XVV<"fvw", "F" # vti.SEW # "VW", wti, vti, |
| GetFTypeInfo<vti.SEW>.Scalar, |
| GetFTypeInfo<vti.SEW>.ScalarRegClass, payload1>; |
| } |
| } |
| } |
| |
| let Predicates = [HasVendorXSfcie] in { |
| let hasSideEffects = 1, mayLoad = 0, mayStore = 0, DecoderNamespace = "XSfcie" in { |
| def SF_CFLUSH_D_L1 : RVInstI<0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1), "cflush.d.l1","$rs1">, |
| Sched<[]> { |
| let rd = 0; |
| let imm12 = {0b1111,0b1100,0b0000}; |
| } |
| |
| def SF_CDISCARD_D_L1 : RVInstI<0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1), "cdiscard.d.l1","$rs1">, |
| Sched<[]> { |
| let rd = 0; |
| let imm12 = {0b1111,0b1100,0b0010}; |
| } |
| |
| def SF_CEASE : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "cease","">, Sched<[]> { |
| let rs1 = 0; |
| let rd = 0; |
| let imm12 = {0b0011,0b0000,0b0101}; |
| } |
| } |
| def : InstAlias<"cflush.d.l1", (SF_CFLUSH_D_L1 X0)>; |
| def : InstAlias<"cdiscard.d.l1", (SF_CDISCARD_D_L1 X0)>; |
| } // Predicates = [HasVendorXScie] |