10b57cec5SDimitry Andric//===-- BPFInstrInfo.td - Target Description for BPF Target ---------------===// 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 BPF instructions in TableGen format. 100b57cec5SDimitry Andric// 110b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andricinclude "BPFInstrFormats.td" 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric// Instruction Operands and Patterns 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric// These are target-independent nodes, but have target-specific formats. 180b57cec5SDimitry Andricdef SDT_BPFCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>, 190b57cec5SDimitry Andric SDTCisVT<1, iPTR>]>; 200b57cec5SDimitry Andricdef SDT_BPFCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>; 210b57cec5SDimitry Andricdef SDT_BPFCall : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>; 220b57cec5SDimitry Andricdef SDT_BPFSetFlag : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>]>; 230b57cec5SDimitry Andricdef SDT_BPFSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, 240b57cec5SDimitry Andric SDTCisSameAs<0, 4>, 250b57cec5SDimitry Andric SDTCisSameAs<4, 5>]>; 260b57cec5SDimitry Andricdef SDT_BPFBrCC : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>, 270b57cec5SDimitry Andric SDTCisVT<3, OtherVT>]>; 280b57cec5SDimitry Andricdef SDT_BPFWrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, 290b57cec5SDimitry Andric SDTCisPtrTy<0>]>; 300b57cec5SDimitry Andricdef SDT_BPFMEMCPY : SDTypeProfile<0, 4, [SDTCisVT<0, i64>, 310b57cec5SDimitry Andric SDTCisVT<1, i64>, 320b57cec5SDimitry Andric SDTCisVT<2, i64>, 330b57cec5SDimitry Andric SDTCisVT<3, i64>]>; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andricdef BPFcall : SDNode<"BPFISD::CALL", SDT_BPFCall, 360b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 370b57cec5SDimitry Andric SDNPVariadic]>; 3806c3fb27SDimitry Andricdef BPFretglue : SDNode<"BPFISD::RET_GLUE", SDTNone, 390b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 400b57cec5SDimitry Andricdef BPFcallseq_start: SDNode<"ISD::CALLSEQ_START", SDT_BPFCallSeqStart, 410b57cec5SDimitry Andric [SDNPHasChain, SDNPOutGlue]>; 420b57cec5SDimitry Andricdef BPFcallseq_end : SDNode<"ISD::CALLSEQ_END", SDT_BPFCallSeqEnd, 430b57cec5SDimitry Andric [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 440b57cec5SDimitry Andricdef BPFbrcc : SDNode<"BPFISD::BR_CC", SDT_BPFBrCC, 450b57cec5SDimitry Andric [SDNPHasChain, SDNPOutGlue, SDNPInGlue]>; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andricdef BPFselectcc : SDNode<"BPFISD::SELECT_CC", SDT_BPFSelectCC, [SDNPInGlue]>; 480b57cec5SDimitry Andricdef BPFWrapper : SDNode<"BPFISD::Wrapper", SDT_BPFWrapper>; 490b57cec5SDimitry Andricdef BPFmemcpy : SDNode<"BPFISD::MEMCPY", SDT_BPFMEMCPY, 500b57cec5SDimitry Andric [SDNPHasChain, SDNPInGlue, SDNPOutGlue, 510b57cec5SDimitry Andric SDNPMayStore, SDNPMayLoad]>; 525f757f3fSDimitry Andricdef BPFIsLittleEndian : Predicate<"Subtarget->isLittleEndian()">; 535f757f3fSDimitry Andricdef BPFIsBigEndian : Predicate<"!Subtarget->isLittleEndian()">; 540b57cec5SDimitry Andricdef BPFHasALU32 : Predicate<"Subtarget->getHasAlu32()">; 550b57cec5SDimitry Andricdef BPFNoALU32 : Predicate<"!Subtarget->getHasAlu32()">; 565f757f3fSDimitry Andricdef BPFHasLdsx : Predicate<"Subtarget->hasLdsx()">; 575f757f3fSDimitry Andricdef BPFHasMovsx : Predicate<"Subtarget->hasMovsx()">; 585f757f3fSDimitry Andricdef BPFHasBswap : Predicate<"Subtarget->hasBswap()">; 595f757f3fSDimitry Andricdef BPFHasSdivSmod : Predicate<"Subtarget->hasSdivSmod()">; 605f757f3fSDimitry Andricdef BPFNoMovsx : Predicate<"!Subtarget->hasMovsx()">; 615f757f3fSDimitry Andricdef BPFNoBswap : Predicate<"!Subtarget->hasBswap()">; 625f757f3fSDimitry Andricdef BPFHasStoreImm : Predicate<"Subtarget->hasStoreImm()">; 635f757f3fSDimitry Andric 645f757f3fSDimitry Andricclass ImmediateAsmOperand<string name> : AsmOperandClass { 655f757f3fSDimitry Andric let Name = name; 665f757f3fSDimitry Andric let RenderMethod = "addImmOperands"; 675f757f3fSDimitry Andric let DiagnosticType = !strconcat("Invalid", name); 685f757f3fSDimitry Andric} 695f757f3fSDimitry Andric 705f757f3fSDimitry Andricdef SImm16AsmOperand : ImmediateAsmOperand<"SImm16">; 710b57cec5SDimitry Andric 720b57cec5SDimitry Andricdef brtarget : Operand<OtherVT> { 730b57cec5SDimitry Andric let PrintMethod = "printBrTargetOperand"; 745f757f3fSDimitry Andric let ParserMatchClass = ImmediateAsmOperand<"BrTarget">; 750b57cec5SDimitry Andric} 760b57cec5SDimitry Andricdef calltarget : Operand<i64>; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andricdef u64imm : Operand<i64> { 790b57cec5SDimitry Andric let PrintMethod = "printImm64Operand"; 800b57cec5SDimitry Andric} 810b57cec5SDimitry Andric 825f757f3fSDimitry Andricdef s16imm : Operand<i16> { 835f757f3fSDimitry Andric let ParserMatchClass = SImm16AsmOperand; 845f757f3fSDimitry Andric} 855f757f3fSDimitry Andric 865f757f3fSDimitry Andricdef gpr_or_imm : Operand<i64>; 875f757f3fSDimitry Andric 880b57cec5SDimitry Andricdef i64immSExt32 : PatLeaf<(i64 imm), 890b57cec5SDimitry Andric [{return isInt<32>(N->getSExtValue()); }]>; 900b57cec5SDimitry Andricdef i32immSExt32 : PatLeaf<(i32 imm), 910b57cec5SDimitry Andric [{return isInt<32>(N->getSExtValue()); }]>; 925f757f3fSDimitry Andricdef i64immZExt32 : PatLeaf<(i64 imm), 935f757f3fSDimitry Andric [{return isUInt<32>(N->getZExtValue()); }]>; 945f757f3fSDimitry Andric 955f757f3fSDimitry Andricdef imm_to_i64 : SDNodeXForm<timm, [{ 965f757f3fSDimitry Andric return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64); 975f757f3fSDimitry Andric}]>; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric// Addressing modes. 1000b57cec5SDimitry Andricdef ADDRri : ComplexPattern<i64, 2, "SelectAddr", [], []>; 1010b57cec5SDimitry Andricdef FIri : ComplexPattern<i64, 2, "SelectFIAddr", [add, or], []>; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric// Address operands 1040b57cec5SDimitry Andricdef MEMri : Operand<i64> { 1050b57cec5SDimitry Andric let PrintMethod = "printMemOperand"; 1060b57cec5SDimitry Andric let EncoderMethod = "getMemoryOpValue"; 1070b57cec5SDimitry Andric let DecoderMethod = "decodeMemoryOpValue"; 1085f757f3fSDimitry Andric let MIOperandInfo = (ops GPR, s16imm); 1090b57cec5SDimitry Andric} 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric// Conditional code predicates - used for pattern matching for jump instructions 1120b57cec5SDimitry Andricdef BPF_CC_EQ : PatLeaf<(i64 imm), 1130b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETEQ);}]>; 1140b57cec5SDimitry Andricdef BPF_CC_NE : PatLeaf<(i64 imm), 1150b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETNE);}]>; 1160b57cec5SDimitry Andricdef BPF_CC_GE : PatLeaf<(i64 imm), 1170b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETGE);}]>; 1180b57cec5SDimitry Andricdef BPF_CC_GT : PatLeaf<(i64 imm), 1190b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETGT);}]>; 1200b57cec5SDimitry Andricdef BPF_CC_GTU : PatLeaf<(i64 imm), 1210b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETUGT);}]>; 1220b57cec5SDimitry Andricdef BPF_CC_GEU : PatLeaf<(i64 imm), 1230b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETUGE);}]>; 1240b57cec5SDimitry Andricdef BPF_CC_LE : PatLeaf<(i64 imm), 1250b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETLE);}]>; 1260b57cec5SDimitry Andricdef BPF_CC_LT : PatLeaf<(i64 imm), 1270b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETLT);}]>; 1280b57cec5SDimitry Andricdef BPF_CC_LTU : PatLeaf<(i64 imm), 1290b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETULT);}]>; 1300b57cec5SDimitry Andricdef BPF_CC_LEU : PatLeaf<(i64 imm), 1310b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETULE);}]>; 1320b57cec5SDimitry Andricdef BPF_CC_EQ_32 : PatLeaf<(i32 imm), 1330b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETEQ);}]>; 1340b57cec5SDimitry Andricdef BPF_CC_NE_32 : PatLeaf<(i32 imm), 1350b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETNE);}]>; 1360b57cec5SDimitry Andricdef BPF_CC_GE_32 : PatLeaf<(i32 imm), 1370b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETGE);}]>; 1380b57cec5SDimitry Andricdef BPF_CC_GT_32 : PatLeaf<(i32 imm), 1390b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETGT);}]>; 1400b57cec5SDimitry Andricdef BPF_CC_GTU_32 : PatLeaf<(i32 imm), 1410b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETUGT);}]>; 1420b57cec5SDimitry Andricdef BPF_CC_GEU_32 : PatLeaf<(i32 imm), 1430b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETUGE);}]>; 1440b57cec5SDimitry Andricdef BPF_CC_LE_32 : PatLeaf<(i32 imm), 1450b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETLE);}]>; 1460b57cec5SDimitry Andricdef BPF_CC_LT_32 : PatLeaf<(i32 imm), 1470b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETLT);}]>; 1480b57cec5SDimitry Andricdef BPF_CC_LTU_32 : PatLeaf<(i32 imm), 1490b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETULT);}]>; 1500b57cec5SDimitry Andricdef BPF_CC_LEU_32 : PatLeaf<(i32 imm), 1510b57cec5SDimitry Andric [{return (N->getZExtValue() == ISD::SETULE);}]>; 1525f757f3fSDimitry Andricdef NoCond : PatLeaf<(vt)> {} 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric// For arithmetic and jump instructions the 8-bit 'code' 1550b57cec5SDimitry Andric// field is divided into three parts: 1560b57cec5SDimitry Andric// 1570b57cec5SDimitry Andric// +----------------+--------+--------------------+ 1580b57cec5SDimitry Andric// | 4 bits | 1 bit | 3 bits | 1590b57cec5SDimitry Andric// | operation code | source | instruction class | 1600b57cec5SDimitry Andric// +----------------+--------+--------------------+ 1610b57cec5SDimitry Andric// (MSB) (LSB) 1620b57cec5SDimitry Andricclass TYPE_ALU_JMP<bits<4> op, bits<1> srctype, 1630b57cec5SDimitry Andric dag outs, dag ins, string asmstr, list<dag> pattern> 1640b57cec5SDimitry Andric : InstBPF<outs, ins, asmstr, pattern> { 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric let Inst{63-60} = op; 1670b57cec5SDimitry Andric let Inst{59} = srctype; 1680b57cec5SDimitry Andric} 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric//For load and store instructions the 8-bit 'code' field is divided as: 1710b57cec5SDimitry Andric// 1720b57cec5SDimitry Andric// +--------+--------+-------------------+ 1730b57cec5SDimitry Andric// | 3 bits | 2 bits | 3 bits | 1740b57cec5SDimitry Andric// | mode | size | instruction class | 1750b57cec5SDimitry Andric// +--------+--------+-------------------+ 1760b57cec5SDimitry Andric// (MSB) (LSB) 1770b57cec5SDimitry Andricclass TYPE_LD_ST<bits<3> mode, bits<2> size, 1780b57cec5SDimitry Andric dag outs, dag ins, string asmstr, list<dag> pattern> 1790b57cec5SDimitry Andric : InstBPF<outs, ins, asmstr, pattern> { 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric let Inst{63-61} = mode; 1820b57cec5SDimitry Andric let Inst{60-59} = size; 1830b57cec5SDimitry Andric} 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric// jump instructions 1860b57cec5SDimitry Andricclass JMP_RR<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond> 1870b57cec5SDimitry Andric : TYPE_ALU_JMP<Opc.Value, BPF_X.Value, 1880b57cec5SDimitry Andric (outs), 1890b57cec5SDimitry Andric (ins GPR:$dst, GPR:$src, brtarget:$BrDst), 1900b57cec5SDimitry Andric "if $dst "#OpcodeStr#" $src goto $BrDst", 1910b57cec5SDimitry Andric [(BPFbrcc i64:$dst, i64:$src, Cond, bb:$BrDst)]> { 1920b57cec5SDimitry Andric bits<4> dst; 1930b57cec5SDimitry Andric bits<4> src; 1940b57cec5SDimitry Andric bits<16> BrDst; 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric let Inst{55-52} = src; 1970b57cec5SDimitry Andric let Inst{51-48} = dst; 1980b57cec5SDimitry Andric let Inst{47-32} = BrDst; 1990b57cec5SDimitry Andric let BPFClass = BPF_JMP; 2000b57cec5SDimitry Andric} 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andricclass JMP_RI<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond> 2030b57cec5SDimitry Andric : TYPE_ALU_JMP<Opc.Value, BPF_K.Value, 2040b57cec5SDimitry Andric (outs), 2050b57cec5SDimitry Andric (ins GPR:$dst, i64imm:$imm, brtarget:$BrDst), 2060b57cec5SDimitry Andric "if $dst "#OpcodeStr#" $imm goto $BrDst", 2070b57cec5SDimitry Andric [(BPFbrcc i64:$dst, i64immSExt32:$imm, Cond, bb:$BrDst)]> { 2080b57cec5SDimitry Andric bits<4> dst; 2090b57cec5SDimitry Andric bits<16> BrDst; 2100b57cec5SDimitry Andric bits<32> imm; 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric let Inst{51-48} = dst; 2130b57cec5SDimitry Andric let Inst{47-32} = BrDst; 2140b57cec5SDimitry Andric let Inst{31-0} = imm; 2150b57cec5SDimitry Andric let BPFClass = BPF_JMP; 2160b57cec5SDimitry Andric} 2170b57cec5SDimitry Andric 218*0fca6ea1SDimitry Andricclass JMP_JCOND<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern> 219*0fca6ea1SDimitry Andric : TYPE_ALU_JMP<Opc.Value, BPF_K.Value, 220*0fca6ea1SDimitry Andric (outs), 221*0fca6ea1SDimitry Andric (ins brtarget:$BrDst), 222*0fca6ea1SDimitry Andric !strconcat(OpcodeStr, " $BrDst"), 223*0fca6ea1SDimitry Andric Pattern> { 224*0fca6ea1SDimitry Andric bits<16> BrDst; 225*0fca6ea1SDimitry Andric 226*0fca6ea1SDimitry Andric let Inst{47-32} = BrDst; 227*0fca6ea1SDimitry Andric let BPFClass = BPF_JMP; 228*0fca6ea1SDimitry Andric} 229*0fca6ea1SDimitry Andric 2300b57cec5SDimitry Andricclass JMP_RR_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond> 2310b57cec5SDimitry Andric : TYPE_ALU_JMP<Opc.Value, BPF_X.Value, 2320b57cec5SDimitry Andric (outs), 2330b57cec5SDimitry Andric (ins GPR32:$dst, GPR32:$src, brtarget:$BrDst), 2340b57cec5SDimitry Andric "if $dst "#OpcodeStr#" $src goto $BrDst", 2350b57cec5SDimitry Andric [(BPFbrcc i32:$dst, i32:$src, Cond, bb:$BrDst)]> { 2360b57cec5SDimitry Andric bits<4> dst; 2370b57cec5SDimitry Andric bits<4> src; 2380b57cec5SDimitry Andric bits<16> BrDst; 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric let Inst{55-52} = src; 2410b57cec5SDimitry Andric let Inst{51-48} = dst; 2420b57cec5SDimitry Andric let Inst{47-32} = BrDst; 2430b57cec5SDimitry Andric let BPFClass = BPF_JMP32; 2440b57cec5SDimitry Andric} 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andricclass JMP_RI_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond> 2470b57cec5SDimitry Andric : TYPE_ALU_JMP<Opc.Value, BPF_K.Value, 2480b57cec5SDimitry Andric (outs), 2490b57cec5SDimitry Andric (ins GPR32:$dst, i32imm:$imm, brtarget:$BrDst), 2500b57cec5SDimitry Andric "if $dst "#OpcodeStr#" $imm goto $BrDst", 2510b57cec5SDimitry Andric [(BPFbrcc i32:$dst, i32immSExt32:$imm, Cond, bb:$BrDst)]> { 2520b57cec5SDimitry Andric bits<4> dst; 2530b57cec5SDimitry Andric bits<16> BrDst; 2540b57cec5SDimitry Andric bits<32> imm; 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric let Inst{51-48} = dst; 2570b57cec5SDimitry Andric let Inst{47-32} = BrDst; 2580b57cec5SDimitry Andric let Inst{31-0} = imm; 2590b57cec5SDimitry Andric let BPFClass = BPF_JMP32; 2600b57cec5SDimitry Andric} 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andricmulticlass J<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond, PatLeaf Cond32> { 2630b57cec5SDimitry Andric def _rr : JMP_RR<Opc, OpcodeStr, Cond>; 2640b57cec5SDimitry Andric def _ri : JMP_RI<Opc, OpcodeStr, Cond>; 2650b57cec5SDimitry Andric def _rr_32 : JMP_RR_32<Opc, OpcodeStr, Cond32>; 2660b57cec5SDimitry Andric def _ri_32 : JMP_RI_32<Opc, OpcodeStr, Cond32>; 2670b57cec5SDimitry Andric} 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andriclet isBranch = 1, isTerminator = 1, hasDelaySlot=0 in { 2700b57cec5SDimitry Andric// cmp+goto instructions 2710b57cec5SDimitry Andricdefm JEQ : J<BPF_JEQ, "==", BPF_CC_EQ, BPF_CC_EQ_32>; 2720b57cec5SDimitry Andricdefm JUGT : J<BPF_JGT, ">", BPF_CC_GTU, BPF_CC_GTU_32>; 2730b57cec5SDimitry Andricdefm JUGE : J<BPF_JGE, ">=", BPF_CC_GEU, BPF_CC_GEU_32>; 2740b57cec5SDimitry Andricdefm JNE : J<BPF_JNE, "!=", BPF_CC_NE, BPF_CC_NE_32>; 2750b57cec5SDimitry Andricdefm JSGT : J<BPF_JSGT, "s>", BPF_CC_GT, BPF_CC_GT_32>; 2760b57cec5SDimitry Andricdefm JSGE : J<BPF_JSGE, "s>=", BPF_CC_GE, BPF_CC_GE_32>; 2770b57cec5SDimitry Andricdefm JULT : J<BPF_JLT, "<", BPF_CC_LTU, BPF_CC_LTU_32>; 2780b57cec5SDimitry Andricdefm JULE : J<BPF_JLE, "<=", BPF_CC_LEU, BPF_CC_LEU_32>; 2790b57cec5SDimitry Andricdefm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT, BPF_CC_LT_32>; 2800b57cec5SDimitry Andricdefm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE, BPF_CC_LE_32>; 2815f757f3fSDimitry Andricdefm JSET : J<BPF_JSET, "&", NoCond, NoCond>; 282*0fca6ea1SDimitry Andricdef JCOND : JMP_JCOND<BPF_JCOND, "may_goto", []>; 2830b57cec5SDimitry Andric} 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric// ALU instructions 2865f757f3fSDimitry Andricclass ALU_RI<BPFOpClass Class, BPFArithOp Opc, int off, 2870b57cec5SDimitry Andric dag outs, dag ins, string asmstr, list<dag> pattern> 2880b57cec5SDimitry Andric : TYPE_ALU_JMP<Opc.Value, BPF_K.Value, outs, ins, asmstr, pattern> { 2890b57cec5SDimitry Andric bits<4> dst; 2900b57cec5SDimitry Andric bits<32> imm; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric let Inst{51-48} = dst; 2935f757f3fSDimitry Andric let Inst{47-32} = off; 2940b57cec5SDimitry Andric let Inst{31-0} = imm; 2950b57cec5SDimitry Andric let BPFClass = Class; 2960b57cec5SDimitry Andric} 2970b57cec5SDimitry Andric 2985f757f3fSDimitry Andricclass ALU_RR<BPFOpClass Class, BPFArithOp Opc, int off, 2990b57cec5SDimitry Andric dag outs, dag ins, string asmstr, list<dag> pattern> 3000b57cec5SDimitry Andric : TYPE_ALU_JMP<Opc.Value, BPF_X.Value, outs, ins, asmstr, pattern> { 3010b57cec5SDimitry Andric bits<4> dst; 3020b57cec5SDimitry Andric bits<4> src; 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric let Inst{55-52} = src; 3050b57cec5SDimitry Andric let Inst{51-48} = dst; 3065f757f3fSDimitry Andric let Inst{47-32} = off; 3070b57cec5SDimitry Andric let BPFClass = Class; 3080b57cec5SDimitry Andric} 3090b57cec5SDimitry Andric 3105f757f3fSDimitry Andricmulticlass ALU<BPFArithOp Opc, int off, string OpcodeStr, SDNode OpNode> { 3115f757f3fSDimitry Andric def _rr : ALU_RR<BPF_ALU64, Opc, off, 3120b57cec5SDimitry Andric (outs GPR:$dst), 3130b57cec5SDimitry Andric (ins GPR:$src2, GPR:$src), 3140b57cec5SDimitry Andric "$dst "#OpcodeStr#" $src", 3150b57cec5SDimitry Andric [(set GPR:$dst, (OpNode i64:$src2, i64:$src))]>; 3165f757f3fSDimitry Andric def _ri : ALU_RI<BPF_ALU64, Opc, off, 3170b57cec5SDimitry Andric (outs GPR:$dst), 3180b57cec5SDimitry Andric (ins GPR:$src2, i64imm:$imm), 3190b57cec5SDimitry Andric "$dst "#OpcodeStr#" $imm", 3200b57cec5SDimitry Andric [(set GPR:$dst, (OpNode GPR:$src2, i64immSExt32:$imm))]>; 3215f757f3fSDimitry Andric def _rr_32 : ALU_RR<BPF_ALU, Opc, off, 3220b57cec5SDimitry Andric (outs GPR32:$dst), 3230b57cec5SDimitry Andric (ins GPR32:$src2, GPR32:$src), 3240b57cec5SDimitry Andric "$dst "#OpcodeStr#" $src", 3250b57cec5SDimitry Andric [(set GPR32:$dst, (OpNode i32:$src2, i32:$src))]>; 3265f757f3fSDimitry Andric def _ri_32 : ALU_RI<BPF_ALU, Opc, off, 3270b57cec5SDimitry Andric (outs GPR32:$dst), 3280b57cec5SDimitry Andric (ins GPR32:$src2, i32imm:$imm), 3290b57cec5SDimitry Andric "$dst "#OpcodeStr#" $imm", 3300b57cec5SDimitry Andric [(set GPR32:$dst, (OpNode GPR32:$src2, i32immSExt32:$imm))]>; 3310b57cec5SDimitry Andric} 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andriclet Constraints = "$dst = $src2" in { 3340b57cec5SDimitry Andriclet isAsCheapAsAMove = 1 in { 3355f757f3fSDimitry Andric defm ADD : ALU<BPF_ADD, 0, "+=", add>; 3365f757f3fSDimitry Andric defm SUB : ALU<BPF_SUB, 0, "-=", sub>; 3375f757f3fSDimitry Andric defm OR : ALU<BPF_OR, 0, "|=", or>; 3385f757f3fSDimitry Andric defm AND : ALU<BPF_AND, 0, "&=", and>; 3395f757f3fSDimitry Andric defm SLL : ALU<BPF_LSH, 0, "<<=", shl>; 3405f757f3fSDimitry Andric defm SRL : ALU<BPF_RSH, 0, ">>=", srl>; 3415f757f3fSDimitry Andric defm XOR : ALU<BPF_XOR, 0, "^=", xor>; 3425f757f3fSDimitry Andric defm SRA : ALU<BPF_ARSH, 0, "s>>=", sra>; 3430b57cec5SDimitry Andric} 3445f757f3fSDimitry Andric defm MUL : ALU<BPF_MUL, 0, "*=", mul>; 3455f757f3fSDimitry Andric defm DIV : ALU<BPF_DIV, 0, "/=", udiv>; 3465f757f3fSDimitry Andric defm MOD : ALU<BPF_MOD, 0, "%=", urem>; 3475f757f3fSDimitry Andric 3485f757f3fSDimitry Andric let Predicates = [BPFHasSdivSmod] in { 3495f757f3fSDimitry Andric defm SDIV : ALU<BPF_DIV, 1, "s/=", sdiv>; 3505f757f3fSDimitry Andric defm SMOD : ALU<BPF_MOD, 1, "s%=", srem>; 3515f757f3fSDimitry Andric } 3520b57cec5SDimitry Andric} 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andricclass NEG_RR<BPFOpClass Class, BPFArithOp Opc, 3550b57cec5SDimitry Andric dag outs, dag ins, string asmstr, list<dag> pattern> 3560b57cec5SDimitry Andric : TYPE_ALU_JMP<Opc.Value, 0, outs, ins, asmstr, pattern> { 3570b57cec5SDimitry Andric bits<4> dst; 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric let Inst{51-48} = dst; 3600b57cec5SDimitry Andric let BPFClass = Class; 3610b57cec5SDimitry Andric} 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andriclet Constraints = "$dst = $src", isAsCheapAsAMove = 1 in { 3640b57cec5SDimitry Andric def NEG_64: NEG_RR<BPF_ALU64, BPF_NEG, (outs GPR:$dst), (ins GPR:$src), 3650b57cec5SDimitry Andric "$dst = -$src", 3660b57cec5SDimitry Andric [(set GPR:$dst, (ineg i64:$src))]>; 3670b57cec5SDimitry Andric def NEG_32: NEG_RR<BPF_ALU, BPF_NEG, (outs GPR32:$dst), (ins GPR32:$src), 3680b57cec5SDimitry Andric "$dst = -$src", 3690b57cec5SDimitry Andric [(set GPR32:$dst, (ineg i32:$src))]>; 3700b57cec5SDimitry Andric} 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andricclass LD_IMM64<bits<4> Pseudo, string OpcodeStr> 3730b57cec5SDimitry Andric : TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value, 3740b57cec5SDimitry Andric (outs GPR:$dst), 3750b57cec5SDimitry Andric (ins u64imm:$imm), 3760b57cec5SDimitry Andric "$dst "#OpcodeStr#" ${imm} ll", 3770b57cec5SDimitry Andric [(set GPR:$dst, (i64 imm:$imm))]> { 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric bits<4> dst; 3800b57cec5SDimitry Andric bits<64> imm; 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric let Inst{51-48} = dst; 3830b57cec5SDimitry Andric let Inst{55-52} = Pseudo; 3840b57cec5SDimitry Andric let Inst{47-32} = 0; 3850b57cec5SDimitry Andric let Inst{31-0} = imm{31-0}; 3860b57cec5SDimitry Andric let BPFClass = BPF_LD; 3870b57cec5SDimitry Andric} 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1 in { 3900b57cec5SDimitry Andricdef LD_imm64 : LD_IMM64<0, "=">; 3915f757f3fSDimitry Andricdef MOV_rr : ALU_RR<BPF_ALU64, BPF_MOV, 0, 3920b57cec5SDimitry Andric (outs GPR:$dst), 3930b57cec5SDimitry Andric (ins GPR:$src), 3940b57cec5SDimitry Andric "$dst = $src", 3950b57cec5SDimitry Andric []>; 3965f757f3fSDimitry Andricdef MOV_ri : ALU_RI<BPF_ALU64, BPF_MOV, 0, 3970b57cec5SDimitry Andric (outs GPR:$dst), 3980b57cec5SDimitry Andric (ins i64imm:$imm), 3990b57cec5SDimitry Andric "$dst = $imm", 4000b57cec5SDimitry Andric [(set GPR:$dst, (i64 i64immSExt32:$imm))]>; 4015f757f3fSDimitry Andricdef MOV_rr_32 : ALU_RR<BPF_ALU, BPF_MOV, 0, 4020b57cec5SDimitry Andric (outs GPR32:$dst), 4030b57cec5SDimitry Andric (ins GPR32:$src), 4040b57cec5SDimitry Andric "$dst = $src", 4050b57cec5SDimitry Andric []>; 4065f757f3fSDimitry Andricdef MOV_ri_32 : ALU_RI<BPF_ALU, BPF_MOV, 0, 4070b57cec5SDimitry Andric (outs GPR32:$dst), 4080b57cec5SDimitry Andric (ins i32imm:$imm), 4090b57cec5SDimitry Andric "$dst = $imm", 4100b57cec5SDimitry Andric [(set GPR32:$dst, (i32 i32immSExt32:$imm))]>; 4115f757f3fSDimitry Andric 4125f757f3fSDimitry Andriclet Predicates = [BPFHasMovsx] in { 4135f757f3fSDimitry Andric def MOVSX_rr_8 : ALU_RR<BPF_ALU64, BPF_MOV, 8, 4145f757f3fSDimitry Andric (outs GPR:$dst), (ins GPR:$src), 4155f757f3fSDimitry Andric "$dst = (s8)$src", 4165f757f3fSDimitry Andric [(set GPR:$dst, (sext_inreg GPR:$src, i8))]>; 4175f757f3fSDimitry Andric def MOVSX_rr_16 : ALU_RR<BPF_ALU64, BPF_MOV, 16, 4185f757f3fSDimitry Andric (outs GPR:$dst), (ins GPR:$src), 4195f757f3fSDimitry Andric "$dst = (s16)$src", 4205f757f3fSDimitry Andric [(set GPR:$dst, (sext_inreg GPR:$src, i16))]>; 4215f757f3fSDimitry Andric def MOVSX_rr_32 : ALU_RR<BPF_ALU64, BPF_MOV, 32, 4225f757f3fSDimitry Andric (outs GPR:$dst), (ins GPR:$src), 4235f757f3fSDimitry Andric "$dst = (s32)$src", 4245f757f3fSDimitry Andric [(set GPR:$dst, (sext_inreg GPR:$src, i32))]>; 4255f757f3fSDimitry Andric def MOVSX_rr_32_8 : ALU_RR<BPF_ALU, BPF_MOV, 8, 4265f757f3fSDimitry Andric (outs GPR32:$dst), (ins GPR32:$src), 4275f757f3fSDimitry Andric "$dst = (s8)$src", 4285f757f3fSDimitry Andric [(set GPR32:$dst, (sext_inreg GPR32:$src, i8))]>; 4295f757f3fSDimitry Andric def MOVSX_rr_32_16 : ALU_RR<BPF_ALU, BPF_MOV, 16, 4305f757f3fSDimitry Andric (outs GPR32:$dst), (ins GPR32:$src), 4315f757f3fSDimitry Andric "$dst = (s16)$src", 4325f757f3fSDimitry Andric [(set GPR32:$dst, (sext_inreg GPR32:$src, i16))]>; 4335f757f3fSDimitry Andric} 4340b57cec5SDimitry Andric} 4350b57cec5SDimitry Andric 436*0fca6ea1SDimitry Andricdef ADDR_SPACE_CAST 437*0fca6ea1SDimitry Andric : ALU_RR<BPF_ALU64, BPF_MOV, 64, 438*0fca6ea1SDimitry Andric (outs GPR:$dst), 439*0fca6ea1SDimitry Andric (ins GPR:$src, i64imm:$dst_as, i64imm:$src_as), 440*0fca6ea1SDimitry Andric "$dst = addr_space_cast($src, $dst_as, $src_as)", 441*0fca6ea1SDimitry Andric []> { 442*0fca6ea1SDimitry Andric bits<64> dst_as; 443*0fca6ea1SDimitry Andric bits<64> src_as; 444*0fca6ea1SDimitry Andric 445*0fca6ea1SDimitry Andric let Inst{47-32} = 1; 446*0fca6ea1SDimitry Andric let Inst{31-16} = dst_as{15-0}; 447*0fca6ea1SDimitry Andric let Inst{15-0} = src_as{15-0}; 448*0fca6ea1SDimitry Andric} 449*0fca6ea1SDimitry Andric 450*0fca6ea1SDimitry Andricdef SrcAddrSpace : SDNodeXForm<addrspacecast, [{ 451*0fca6ea1SDimitry Andric return CurDAG->getTargetConstant( 452*0fca6ea1SDimitry Andric cast<AddrSpaceCastSDNode>(N)->getSrcAddressSpace(), 453*0fca6ea1SDimitry Andric SDLoc(N), MVT::i64); 454*0fca6ea1SDimitry Andric}]>; 455*0fca6ea1SDimitry Andric 456*0fca6ea1SDimitry Andricdef DstAddrSpace : SDNodeXForm<addrspacecast, [{ 457*0fca6ea1SDimitry Andric return CurDAG->getTargetConstant( 458*0fca6ea1SDimitry Andric cast<AddrSpaceCastSDNode>(N)->getDestAddressSpace(), 459*0fca6ea1SDimitry Andric SDLoc(N), MVT::i64); 460*0fca6ea1SDimitry Andric}]>; 461*0fca6ea1SDimitry Andric 462*0fca6ea1SDimitry Andricdef : Pat<(addrspacecast:$this GPR:$src), 463*0fca6ea1SDimitry Andric (ADDR_SPACE_CAST $src, (DstAddrSpace $this), (SrcAddrSpace $this))>; 464*0fca6ea1SDimitry Andric 4650b57cec5SDimitry Andricdef FI_ri 4660b57cec5SDimitry Andric : TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value, 4670b57cec5SDimitry Andric (outs GPR:$dst), 4680b57cec5SDimitry Andric (ins MEMri:$addr), 4690b57cec5SDimitry Andric "lea\t$dst, $addr", 4700b57cec5SDimitry Andric [(set i64:$dst, FIri:$addr)]> { 4710b57cec5SDimitry Andric // This is a tentative instruction, and will be replaced 4720b57cec5SDimitry Andric // with MOV_rr and ADD_ri in PEI phase 4730b57cec5SDimitry Andric let Inst{51-48} = 0; 4740b57cec5SDimitry Andric let Inst{55-52} = 2; 4750b57cec5SDimitry Andric let Inst{47-32} = 0; 4760b57cec5SDimitry Andric let Inst{31-0} = 0; 4770b57cec5SDimitry Andric let BPFClass = BPF_LD; 47881ad6265SDimitry Andric bit isPseudo = true; 4790b57cec5SDimitry Andric} 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andricdef LD_pseudo 4820b57cec5SDimitry Andric : TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value, 4830b57cec5SDimitry Andric (outs GPR:$dst), 4840b57cec5SDimitry Andric (ins i64imm:$pseudo, u64imm:$imm), 4850b57cec5SDimitry Andric "ld_pseudo\t$dst, $pseudo, $imm", 4860b57cec5SDimitry Andric [(set GPR:$dst, (int_bpf_pseudo imm:$pseudo, imm:$imm))]> { 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric bits<4> dst; 4890b57cec5SDimitry Andric bits<64> imm; 4900b57cec5SDimitry Andric bits<4> pseudo; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric let Inst{51-48} = dst; 4930b57cec5SDimitry Andric let Inst{55-52} = pseudo; 4940b57cec5SDimitry Andric let Inst{47-32} = 0; 4950b57cec5SDimitry Andric let Inst{31-0} = imm{31-0}; 4960b57cec5SDimitry Andric let BPFClass = BPF_LD; 4970b57cec5SDimitry Andric} 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric// STORE instructions 5000b57cec5SDimitry Andricclass STORE<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern> 5010b57cec5SDimitry Andric : TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value, 5020b57cec5SDimitry Andric (outs), 5030b57cec5SDimitry Andric (ins GPR:$src, MEMri:$addr), 5040b57cec5SDimitry Andric "*("#OpcodeStr#" *)($addr) = $src", 5050b57cec5SDimitry Andric Pattern> { 5060b57cec5SDimitry Andric bits<4> src; 5070b57cec5SDimitry Andric bits<20> addr; 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 5100b57cec5SDimitry Andric let Inst{55-52} = src; 5110b57cec5SDimitry Andric let Inst{47-32} = addr{15-0}; // offset 5120b57cec5SDimitry Andric let BPFClass = BPF_STX; 5130b57cec5SDimitry Andric} 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andricclass STOREi64<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode> 5165f757f3fSDimitry Andric : STORE<Opc, OpcodeStr, [(OpNode GPR:$src, ADDRri:$addr)]>; 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andriclet Predicates = [BPFNoALU32] in { 5190b57cec5SDimitry Andric def STW : STOREi64<BPF_W, "u32", truncstorei32>; 5200b57cec5SDimitry Andric def STH : STOREi64<BPF_H, "u16", truncstorei16>; 5210b57cec5SDimitry Andric def STB : STOREi64<BPF_B, "u8", truncstorei8>; 5220b57cec5SDimitry Andric} 5230b57cec5SDimitry Andricdef STD : STOREi64<BPF_DW, "u64", store>; 5240b57cec5SDimitry Andric 5255f757f3fSDimitry Andricclass STORE_imm<BPFWidthModifer SizeOp, 5265f757f3fSDimitry Andric string OpcodeStr, dag Pattern> 5270b57cec5SDimitry Andric : TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value, 5285f757f3fSDimitry Andric (outs), 5295f757f3fSDimitry Andric (ins i64imm:$imm, MEMri:$addr), 5305f757f3fSDimitry Andric "*("#OpcodeStr#" *)($addr) = $imm", 5315f757f3fSDimitry Andric [Pattern]> { 5325f757f3fSDimitry Andric bits<20> addr; 5335f757f3fSDimitry Andric bits<32> imm; 5345f757f3fSDimitry Andric 5355f757f3fSDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 5365f757f3fSDimitry Andric let Inst{47-32} = addr{15-0}; // offset 5375f757f3fSDimitry Andric let Inst{31-0} = imm; 5385f757f3fSDimitry Andric let BPFClass = BPF_ST; 5395f757f3fSDimitry Andric} 5405f757f3fSDimitry Andric 5415f757f3fSDimitry Andriclet Predicates = [BPFHasStoreImm] in { 5425f757f3fSDimitry Andric // Opcode (BPF_ST | BPF_MEM | BPF_DW) implies sign extension for 5435f757f3fSDimitry Andric // value stored to memory: 5445f757f3fSDimitry Andric // - it is fine to generate such write when immediate is -1 5455f757f3fSDimitry Andric // - it is incorrect to generate such write when immediate is 5465f757f3fSDimitry Andric // +0xffff_ffff. 5475f757f3fSDimitry Andric // 5485f757f3fSDimitry Andric // In the latter case two instructions would be generated instead of 5495f757f3fSDimitry Andric // one BPF_ST: 5505f757f3fSDimitry Andric // rA = 0xffffffff ll ; LD_imm64 5515f757f3fSDimitry Andric // *(u64 *)(rB + 0) = rA ; STX 5525f757f3fSDimitry Andric // 5535f757f3fSDimitry Andric // For BPF_{B,H,W} the size of value stored matches size of the immediate. 5545f757f3fSDimitry Andric def STD_imm : STORE_imm<BPF_DW, "u64", (store (i64 i64immSExt32:$imm), ADDRri:$addr)>; 5555f757f3fSDimitry Andric def STW_imm : STORE_imm<BPF_W, "u32", (truncstorei32 (i64 i64immZExt32:$imm), ADDRri:$addr)>; 5565f757f3fSDimitry Andric def STH_imm : STORE_imm<BPF_H, "u16", (truncstorei16 (i64 i64immZExt32:$imm), ADDRri:$addr)>; 5575f757f3fSDimitry Andric def STB_imm : STORE_imm<BPF_B, "u8", (truncstorei8 (i64 i64immZExt32:$imm), ADDRri:$addr)>; 5585f757f3fSDimitry Andric} 5595f757f3fSDimitry Andric 5605f757f3fSDimitry Andriclet Predicates = [BPFHasALU32, BPFHasStoreImm] in { 5615f757f3fSDimitry Andric def : Pat<(store (i32 imm:$src), ADDRri:$dst), 5625f757f3fSDimitry Andric (STW_imm (imm_to_i64 $src), ADDRri:$dst)>; 5635f757f3fSDimitry Andric def : Pat<(truncstorei16 (i32 imm:$src), ADDRri:$dst), 5645f757f3fSDimitry Andric (STH_imm (imm_to_i64 imm:$src), ADDRri:$dst)>; 5655f757f3fSDimitry Andric def : Pat<(truncstorei8 (i32 imm:$src), ADDRri:$dst), 5665f757f3fSDimitry Andric (STB_imm (imm_to_i64 imm:$src), ADDRri:$dst)>; 5675f757f3fSDimitry Andric} 5685f757f3fSDimitry Andric 5695f757f3fSDimitry Andric// LOAD instructions 5705f757f3fSDimitry Andricclass LOAD<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, list<dag> Pattern> 5715f757f3fSDimitry Andric : TYPE_LD_ST<ModOp.Value, SizeOp.Value, 5720b57cec5SDimitry Andric (outs GPR:$dst), 5730b57cec5SDimitry Andric (ins MEMri:$addr), 5740b57cec5SDimitry Andric "$dst = *("#OpcodeStr#" *)($addr)", 5750b57cec5SDimitry Andric Pattern> { 5760b57cec5SDimitry Andric bits<4> dst; 5770b57cec5SDimitry Andric bits<20> addr; 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric let Inst{51-48} = dst; 5800b57cec5SDimitry Andric let Inst{55-52} = addr{19-16}; 5810b57cec5SDimitry Andric let Inst{47-32} = addr{15-0}; 5820b57cec5SDimitry Andric let BPFClass = BPF_LDX; 5830b57cec5SDimitry Andric} 5840b57cec5SDimitry Andric 5855f757f3fSDimitry Andricclass LOADi64<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, PatFrag OpNode> 5865f757f3fSDimitry Andric : LOAD<SizeOp, ModOp, OpcodeStr, [(set i64:$dst, (OpNode ADDRri:$addr))]>; 5870b57cec5SDimitry Andric 588480093f4SDimitry Andriclet isCodeGenOnly = 1 in { 5895f757f3fSDimitry Andric class CORE_LD<RegisterClass RegClass, string Sz> 5905f757f3fSDimitry Andric : TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value, 5915f757f3fSDimitry Andric (outs RegClass:$dst), 592480093f4SDimitry Andric (ins u64imm:$opcode, GPR:$src, u64imm:$offset), 5935f757f3fSDimitry Andric "$dst = core_ld"#Sz#"($opcode, $src, $offset)", 594480093f4SDimitry Andric []>; 5955f757f3fSDimitry Andric def CORE_LD64 : CORE_LD<GPR, "64">; 5965f757f3fSDimitry Andric def CORE_LD32 : CORE_LD<GPR32, "32">; 5975f757f3fSDimitry Andric def CORE_ST : TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value, 5985f757f3fSDimitry Andric (outs), 5995f757f3fSDimitry Andric (ins gpr_or_imm:$src, u64imm:$opcode, GPR:$ptr, u64imm:$offset), 6005f757f3fSDimitry Andric "core_st($src, $opcode, $ptr, $offset)", 601480093f4SDimitry Andric []>; 602480093f4SDimitry Andric let Constraints = "$dst = $src" in { 6035f757f3fSDimitry Andric def CORE_SHIFT : ALU_RR<BPF_ALU64, BPF_LSH, 0, 604480093f4SDimitry Andric (outs GPR:$dst), 605480093f4SDimitry Andric (ins u64imm:$opcode, GPR:$src, u64imm:$offset), 606480093f4SDimitry Andric "$dst = core_shift($opcode, $src, $offset)", 607480093f4SDimitry Andric []>; 608480093f4SDimitry Andric } 609480093f4SDimitry Andric} 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andriclet Predicates = [BPFNoALU32] in { 6125f757f3fSDimitry Andric def LDW : LOADi64<BPF_W, BPF_MEM, "u32", zextloadi32>; 6135f757f3fSDimitry Andric def LDH : LOADi64<BPF_H, BPF_MEM, "u16", zextloadi16>; 6145f757f3fSDimitry Andric def LDB : LOADi64<BPF_B, BPF_MEM, "u8", zextloadi8>; 6150b57cec5SDimitry Andric} 6160b57cec5SDimitry Andric 6175f757f3fSDimitry Andriclet Predicates = [BPFHasLdsx] in { 6185f757f3fSDimitry Andric def LDWSX : LOADi64<BPF_W, BPF_MEMSX, "s32", sextloadi32>; 6195f757f3fSDimitry Andric def LDHSX : LOADi64<BPF_H, BPF_MEMSX, "s16", sextloadi16>; 6205f757f3fSDimitry Andric def LDBSX : LOADi64<BPF_B, BPF_MEMSX, "s8", sextloadi8>; 6215f757f3fSDimitry Andric} 6225f757f3fSDimitry Andric 6235f757f3fSDimitry Andricdef LDD : LOADi64<BPF_DW, BPF_MEM, "u64", load>; 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andricclass BRANCH<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern> 6260b57cec5SDimitry Andric : TYPE_ALU_JMP<Opc.Value, BPF_K.Value, 6270b57cec5SDimitry Andric (outs), 6280b57cec5SDimitry Andric (ins brtarget:$BrDst), 6290b57cec5SDimitry Andric !strconcat(OpcodeStr, " $BrDst"), 6300b57cec5SDimitry Andric Pattern> { 6310b57cec5SDimitry Andric bits<16> BrDst; 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric let Inst{47-32} = BrDst; 6340b57cec5SDimitry Andric let BPFClass = BPF_JMP; 6350b57cec5SDimitry Andric} 6360b57cec5SDimitry Andric 6375f757f3fSDimitry Andricclass BRANCH_LONG<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern> 6385f757f3fSDimitry Andric : TYPE_ALU_JMP<Opc.Value, BPF_K.Value, 6395f757f3fSDimitry Andric (outs), 6405f757f3fSDimitry Andric (ins brtarget:$BrDst), 6415f757f3fSDimitry Andric !strconcat(OpcodeStr, " $BrDst"), 6425f757f3fSDimitry Andric Pattern> { 6435f757f3fSDimitry Andric bits<32> BrDst; 6445f757f3fSDimitry Andric 6455f757f3fSDimitry Andric let Inst{31-0} = BrDst; 6465f757f3fSDimitry Andric let BPFClass = BPF_JMP32; 6475f757f3fSDimitry Andric} 6485f757f3fSDimitry Andric 6490b57cec5SDimitry Andricclass CALL<string OpcodeStr> 6500b57cec5SDimitry Andric : TYPE_ALU_JMP<BPF_CALL.Value, BPF_K.Value, 6510b57cec5SDimitry Andric (outs), 6520b57cec5SDimitry Andric (ins calltarget:$BrDst), 6530b57cec5SDimitry Andric !strconcat(OpcodeStr, " $BrDst"), 6540b57cec5SDimitry Andric []> { 6550b57cec5SDimitry Andric bits<32> BrDst; 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric let Inst{31-0} = BrDst; 6580b57cec5SDimitry Andric let BPFClass = BPF_JMP; 6590b57cec5SDimitry Andric} 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andricclass CALLX<string OpcodeStr> 6620b57cec5SDimitry Andric : TYPE_ALU_JMP<BPF_CALL.Value, BPF_X.Value, 6630b57cec5SDimitry Andric (outs), 6648bcb0991SDimitry Andric (ins GPR:$BrDst), 6650b57cec5SDimitry Andric !strconcat(OpcodeStr, " $BrDst"), 6660b57cec5SDimitry Andric []> { 667*0fca6ea1SDimitry Andric bits<4> BrDst; 6680b57cec5SDimitry Andric 669*0fca6ea1SDimitry Andric let Inst{51-48} = BrDst; 6700b57cec5SDimitry Andric let BPFClass = BPF_JMP; 6710b57cec5SDimitry Andric} 6720b57cec5SDimitry Andric 6730b57cec5SDimitry Andric// Jump always 6740b57cec5SDimitry Andriclet isBranch = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1 in { 6750b57cec5SDimitry Andric def JMP : BRANCH<BPF_JA, "goto", [(br bb:$BrDst)]>; 6765f757f3fSDimitry Andric def JMPL : BRANCH_LONG<BPF_JA, "gotol", []>; 6770b57cec5SDimitry Andric} 6780b57cec5SDimitry Andric 6790b57cec5SDimitry Andric// Jump and link 6800b57cec5SDimitry Andriclet isCall=1, hasDelaySlot=0, Uses = [R11], 6810b57cec5SDimitry Andric // Potentially clobbered registers 6820b57cec5SDimitry Andric Defs = [R0, R1, R2, R3, R4, R5] in { 6830b57cec5SDimitry Andric def JAL : CALL<"call">; 6840b57cec5SDimitry Andric def JALX : CALLX<"callx">; 6850b57cec5SDimitry Andric} 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andricclass NOP_I<string OpcodeStr> 6880b57cec5SDimitry Andric : TYPE_ALU_JMP<BPF_MOV.Value, BPF_X.Value, 6890b57cec5SDimitry Andric (outs), 6900b57cec5SDimitry Andric (ins i32imm:$imm), 6910b57cec5SDimitry Andric !strconcat(OpcodeStr, "\t$imm"), 6920b57cec5SDimitry Andric []> { 6930b57cec5SDimitry Andric // mov r0, r0 == nop 6940b57cec5SDimitry Andric let Inst{55-52} = 0; 6950b57cec5SDimitry Andric let Inst{51-48} = 0; 6960b57cec5SDimitry Andric let BPFClass = BPF_ALU64; 6970b57cec5SDimitry Andric} 6980b57cec5SDimitry Andric 6995ffd83dbSDimitry Andriclet hasSideEffects = 0, isCodeGenOnly = 1 in 7000b57cec5SDimitry Andric def NOP : NOP_I<"nop">; 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andricclass RET<string OpcodeStr> 7030b57cec5SDimitry Andric : TYPE_ALU_JMP<BPF_EXIT.Value, BPF_K.Value, 7040b57cec5SDimitry Andric (outs), 7050b57cec5SDimitry Andric (ins), 7060b57cec5SDimitry Andric !strconcat(OpcodeStr, ""), 70706c3fb27SDimitry Andric [(BPFretglue)]> { 7080b57cec5SDimitry Andric let Inst{31-0} = 0; 7090b57cec5SDimitry Andric let BPFClass = BPF_JMP; 7100b57cec5SDimitry Andric} 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andriclet isReturn = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1, 7130b57cec5SDimitry Andric isNotDuplicable = 1 in { 7140b57cec5SDimitry Andric def RET : RET<"exit">; 7150b57cec5SDimitry Andric} 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric// ADJCALLSTACKDOWN/UP pseudo insns 7180b57cec5SDimitry Andriclet Defs = [R11], Uses = [R11], isCodeGenOnly = 1 in { 7190b57cec5SDimitry Andricdef ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), 7200b57cec5SDimitry Andric "#ADJCALLSTACKDOWN $amt1 $amt2", 7210b57cec5SDimitry Andric [(BPFcallseq_start timm:$amt1, timm:$amt2)]>; 7220b57cec5SDimitry Andricdef ADJCALLSTACKUP : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), 7230b57cec5SDimitry Andric "#ADJCALLSTACKUP $amt1 $amt2", 7240b57cec5SDimitry Andric [(BPFcallseq_end timm:$amt1, timm:$amt2)]>; 7250b57cec5SDimitry Andric} 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andriclet usesCustomInserter = 1, isCodeGenOnly = 1 in { 7280b57cec5SDimitry Andric def Select : Pseudo<(outs GPR:$dst), 7290b57cec5SDimitry Andric (ins GPR:$lhs, GPR:$rhs, i64imm:$imm, GPR:$src, GPR:$src2), 7300b57cec5SDimitry Andric "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2", 7310b57cec5SDimitry Andric [(set i64:$dst, 7320b57cec5SDimitry Andric (BPFselectcc i64:$lhs, i64:$rhs, (i64 imm:$imm), i64:$src, i64:$src2))]>; 7330b57cec5SDimitry Andric def Select_Ri : Pseudo<(outs GPR:$dst), 7340b57cec5SDimitry Andric (ins GPR:$lhs, i64imm:$rhs, i64imm:$imm, GPR:$src, GPR:$src2), 7350b57cec5SDimitry Andric "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2", 7360b57cec5SDimitry Andric [(set i64:$dst, 7370b57cec5SDimitry Andric (BPFselectcc i64:$lhs, (i64immSExt32:$rhs), (i64 imm:$imm), i64:$src, i64:$src2))]>; 7380b57cec5SDimitry Andric def Select_64_32 : Pseudo<(outs GPR32:$dst), 7390b57cec5SDimitry Andric (ins GPR:$lhs, GPR:$rhs, i64imm:$imm, GPR32:$src, GPR32:$src2), 7400b57cec5SDimitry Andric "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2", 7410b57cec5SDimitry Andric [(set i32:$dst, 7420b57cec5SDimitry Andric (BPFselectcc i64:$lhs, i64:$rhs, (i64 imm:$imm), i32:$src, i32:$src2))]>; 7430b57cec5SDimitry Andric def Select_Ri_64_32 : Pseudo<(outs GPR32:$dst), 7440b57cec5SDimitry Andric (ins GPR:$lhs, i64imm:$rhs, i64imm:$imm, GPR32:$src, GPR32:$src2), 7450b57cec5SDimitry Andric "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2", 7460b57cec5SDimitry Andric [(set i32:$dst, 7470b57cec5SDimitry Andric (BPFselectcc i64:$lhs, (i64immSExt32:$rhs), (i64 imm:$imm), i32:$src, i32:$src2))]>; 7480b57cec5SDimitry Andric def Select_32 : Pseudo<(outs GPR32:$dst), 7490b57cec5SDimitry Andric (ins GPR32:$lhs, GPR32:$rhs, i32imm:$imm, GPR32:$src, GPR32:$src2), 7500b57cec5SDimitry Andric "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2", 7510b57cec5SDimitry Andric [(set i32:$dst, 7520b57cec5SDimitry Andric (BPFselectcc i32:$lhs, i32:$rhs, (i32 imm:$imm), i32:$src, i32:$src2))]>; 7530b57cec5SDimitry Andric def Select_Ri_32 : Pseudo<(outs GPR32:$dst), 7540b57cec5SDimitry Andric (ins GPR32:$lhs, i32imm:$rhs, i32imm:$imm, GPR32:$src, GPR32:$src2), 7550b57cec5SDimitry Andric "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2", 7560b57cec5SDimitry Andric [(set i32:$dst, 7570b57cec5SDimitry Andric (BPFselectcc i32:$lhs, (i32immSExt32:$rhs), (i32 imm:$imm), i32:$src, i32:$src2))]>; 7580b57cec5SDimitry Andric def Select_32_64 : Pseudo<(outs GPR:$dst), 7590b57cec5SDimitry Andric (ins GPR32:$lhs, GPR32:$rhs, i32imm:$imm, GPR:$src, GPR:$src2), 7600b57cec5SDimitry Andric "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2", 7610b57cec5SDimitry Andric [(set i64:$dst, 7620b57cec5SDimitry Andric (BPFselectcc i32:$lhs, i32:$rhs, (i32 imm:$imm), i64:$src, i64:$src2))]>; 7630b57cec5SDimitry Andric def Select_Ri_32_64 : Pseudo<(outs GPR:$dst), 7640b57cec5SDimitry Andric (ins GPR32:$lhs, i32imm:$rhs, i32imm:$imm, GPR:$src, GPR:$src2), 7650b57cec5SDimitry Andric "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2", 7660b57cec5SDimitry Andric [(set i64:$dst, 7670b57cec5SDimitry Andric (BPFselectcc i32:$lhs, (i32immSExt32:$rhs), (i32 imm:$imm), i64:$src, i64:$src2))]>; 7680b57cec5SDimitry Andric} 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric// load 64-bit global addr into register 7710b57cec5SDimitry Andricdef : Pat<(BPFWrapper tglobaladdr:$in), (LD_imm64 tglobaladdr:$in)>; 772*0fca6ea1SDimitry Andricdef : Pat<(BPFWrapper tconstpool:$in), (LD_imm64 tconstpool:$in)>; 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric// 0xffffFFFF doesn't fit into simm32, optimize common case 7750b57cec5SDimitry Andricdef : Pat<(i64 (and (i64 GPR:$src), 0xffffFFFF)), 7760b57cec5SDimitry Andric (SRL_ri (SLL_ri (i64 GPR:$src), 32), 32)>; 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric// Calls 7790b57cec5SDimitry Andricdef : Pat<(BPFcall tglobaladdr:$dst), (JAL tglobaladdr:$dst)>; 7800b57cec5SDimitry Andricdef : Pat<(BPFcall texternalsym:$dst), (JAL texternalsym:$dst)>; 7810b57cec5SDimitry Andricdef : Pat<(BPFcall imm:$dst), (JAL imm:$dst)>; 7820b57cec5SDimitry Andricdef : Pat<(BPFcall GPR:$dst), (JALX GPR:$dst)>; 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric// Loads 7850b57cec5SDimitry Andriclet Predicates = [BPFNoALU32] in { 7860b57cec5SDimitry Andric def : Pat<(i64 (extloadi8 ADDRri:$src)), (i64 (LDB ADDRri:$src))>; 7870b57cec5SDimitry Andric def : Pat<(i64 (extloadi16 ADDRri:$src)), (i64 (LDH ADDRri:$src))>; 7880b57cec5SDimitry Andric def : Pat<(i64 (extloadi32 ADDRri:$src)), (i64 (LDW ADDRri:$src))>; 7890b57cec5SDimitry Andric} 7900b57cec5SDimitry Andric 791e8d8bef9SDimitry Andric// Atomic XADD for BPFNoALU32 7920b57cec5SDimitry Andricclass XADD<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode> 793e8d8bef9SDimitry Andric : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value, 7940b57cec5SDimitry Andric (outs GPR:$dst), 7950b57cec5SDimitry Andric (ins MEMri:$addr, GPR:$val), 7960b57cec5SDimitry Andric "lock *("#OpcodeStr#" *)($addr) += $val", 7970b57cec5SDimitry Andric [(set GPR:$dst, (OpNode ADDRri:$addr, GPR:$val))]> { 7980b57cec5SDimitry Andric bits<4> dst; 7990b57cec5SDimitry Andric bits<20> addr; 8000b57cec5SDimitry Andric 8010b57cec5SDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 8020b57cec5SDimitry Andric let Inst{55-52} = dst; 8030b57cec5SDimitry Andric let Inst{47-32} = addr{15-0}; // offset 804e8d8bef9SDimitry Andric let Inst{7-4} = BPF_ADD.Value; 8050b57cec5SDimitry Andric let BPFClass = BPF_STX; 8060b57cec5SDimitry Andric} 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andriclet Constraints = "$dst = $val" in { 8090b57cec5SDimitry Andric let Predicates = [BPFNoALU32] in { 810*0fca6ea1SDimitry Andric def XADDW : XADD<BPF_W, "u32", atomic_load_add_i32>; 8110b57cec5SDimitry Andric } 8120b57cec5SDimitry Andric} 8130b57cec5SDimitry Andric 814e8d8bef9SDimitry Andric// Atomic add, and, or, xor 815e8d8bef9SDimitry Andricclass ATOMIC_NOFETCH<BPFArithOp Opc, string Opstr> 816e8d8bef9SDimitry Andric : TYPE_LD_ST<BPF_ATOMIC.Value, BPF_DW.Value, 817e8d8bef9SDimitry Andric (outs GPR:$dst), 818e8d8bef9SDimitry Andric (ins MEMri:$addr, GPR:$val), 819e8d8bef9SDimitry Andric "lock *(u64 *)($addr) " #Opstr# "= $val", 820e8d8bef9SDimitry Andric []> { 821e8d8bef9SDimitry Andric bits<4> dst; 822e8d8bef9SDimitry Andric bits<20> addr; 823e8d8bef9SDimitry Andric 824e8d8bef9SDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 825e8d8bef9SDimitry Andric let Inst{55-52} = dst; 826e8d8bef9SDimitry Andric let Inst{47-32} = addr{15-0}; // offset 827e8d8bef9SDimitry Andric let Inst{7-4} = Opc.Value; 828e8d8bef9SDimitry Andric let BPFClass = BPF_STX; 829e8d8bef9SDimitry Andric} 830e8d8bef9SDimitry Andric 831e8d8bef9SDimitry Andricclass ATOMIC32_NOFETCH<BPFArithOp Opc, string Opstr> 832e8d8bef9SDimitry Andric : TYPE_LD_ST<BPF_ATOMIC.Value, BPF_W.Value, 833e8d8bef9SDimitry Andric (outs GPR32:$dst), 834e8d8bef9SDimitry Andric (ins MEMri:$addr, GPR32:$val), 835e8d8bef9SDimitry Andric "lock *(u32 *)($addr) " #Opstr# "= $val", 836e8d8bef9SDimitry Andric []> { 837e8d8bef9SDimitry Andric bits<4> dst; 838e8d8bef9SDimitry Andric bits<20> addr; 839e8d8bef9SDimitry Andric 840e8d8bef9SDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 841e8d8bef9SDimitry Andric let Inst{55-52} = dst; 842e8d8bef9SDimitry Andric let Inst{47-32} = addr{15-0}; // offset 843e8d8bef9SDimitry Andric let Inst{7-4} = Opc.Value; 844e8d8bef9SDimitry Andric let BPFClass = BPF_STX; 845e8d8bef9SDimitry Andric} 846e8d8bef9SDimitry Andric 847e8d8bef9SDimitry Andriclet Constraints = "$dst = $val" in { 848e8d8bef9SDimitry Andric let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in { 849e8d8bef9SDimitry Andric def XADDW32 : ATOMIC32_NOFETCH<BPF_ADD, "+">; 850e8d8bef9SDimitry Andric def XANDW32 : ATOMIC32_NOFETCH<BPF_AND, "&">; 851e8d8bef9SDimitry Andric def XORW32 : ATOMIC32_NOFETCH<BPF_OR, "|">; 852e8d8bef9SDimitry Andric def XXORW32 : ATOMIC32_NOFETCH<BPF_XOR, "^">; 853e8d8bef9SDimitry Andric } 854e8d8bef9SDimitry Andric 855e8d8bef9SDimitry Andric def XADDD : ATOMIC_NOFETCH<BPF_ADD, "+">; 856e8d8bef9SDimitry Andric def XANDD : ATOMIC_NOFETCH<BPF_AND, "&">; 857e8d8bef9SDimitry Andric def XORD : ATOMIC_NOFETCH<BPF_OR, "|">; 858e8d8bef9SDimitry Andric def XXORD : ATOMIC_NOFETCH<BPF_XOR, "^">; 859e8d8bef9SDimitry Andric} 860e8d8bef9SDimitry Andric 861e8d8bef9SDimitry Andric// Atomic Fetch-and-<add, and, or, xor> operations 862e8d8bef9SDimitry Andricclass XFALU64<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr, 863e8d8bef9SDimitry Andric string OpcStr, PatFrag OpNode> 864e8d8bef9SDimitry Andric : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value, 865e8d8bef9SDimitry Andric (outs GPR:$dst), 866e8d8bef9SDimitry Andric (ins MEMri:$addr, GPR:$val), 867e8d8bef9SDimitry Andric "$dst = atomic_fetch_"#OpcStr#"(("#OpcodeStr#" *)($addr), $val)", 868e8d8bef9SDimitry Andric [(set GPR:$dst, (OpNode ADDRri:$addr, GPR:$val))]> { 869e8d8bef9SDimitry Andric bits<4> dst; 870e8d8bef9SDimitry Andric bits<20> addr; 871e8d8bef9SDimitry Andric 872e8d8bef9SDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 873e8d8bef9SDimitry Andric let Inst{55-52} = dst; 874e8d8bef9SDimitry Andric let Inst{47-32} = addr{15-0}; // offset 875e8d8bef9SDimitry Andric let Inst{7-4} = Opc.Value; 876e8d8bef9SDimitry Andric let Inst{3-0} = BPF_FETCH.Value; 877e8d8bef9SDimitry Andric let BPFClass = BPF_STX; 878e8d8bef9SDimitry Andric} 879e8d8bef9SDimitry Andric 880e8d8bef9SDimitry Andricclass XFALU32<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr, 881e8d8bef9SDimitry Andric string OpcStr, PatFrag OpNode> 882e8d8bef9SDimitry Andric : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value, 883e8d8bef9SDimitry Andric (outs GPR32:$dst), 884e8d8bef9SDimitry Andric (ins MEMri:$addr, GPR32:$val), 885e8d8bef9SDimitry Andric "$dst = atomic_fetch_"#OpcStr#"(("#OpcodeStr#" *)($addr), $val)", 886e8d8bef9SDimitry Andric [(set GPR32:$dst, (OpNode ADDRri:$addr, GPR32:$val))]> { 887e8d8bef9SDimitry Andric bits<4> dst; 888e8d8bef9SDimitry Andric bits<20> addr; 889e8d8bef9SDimitry Andric 890e8d8bef9SDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 891e8d8bef9SDimitry Andric let Inst{55-52} = dst; 892e8d8bef9SDimitry Andric let Inst{47-32} = addr{15-0}; // offset 893e8d8bef9SDimitry Andric let Inst{7-4} = Opc.Value; 894e8d8bef9SDimitry Andric let Inst{3-0} = BPF_FETCH.Value; 895e8d8bef9SDimitry Andric let BPFClass = BPF_STX; 896e8d8bef9SDimitry Andric} 897e8d8bef9SDimitry Andric 898e8d8bef9SDimitry Andriclet Constraints = "$dst = $val" in { 899e8d8bef9SDimitry Andric let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in { 900*0fca6ea1SDimitry Andric def XFADDW32 : XFALU32<BPF_W, BPF_ADD, "u32", "add", atomic_load_add_i32>; 901*0fca6ea1SDimitry Andric def XFANDW32 : XFALU32<BPF_W, BPF_AND, "u32", "and", atomic_load_and_i32>; 902*0fca6ea1SDimitry Andric def XFORW32 : XFALU32<BPF_W, BPF_OR, "u32", "or", atomic_load_or_i32>; 903*0fca6ea1SDimitry Andric def XFXORW32 : XFALU32<BPF_W, BPF_XOR, "u32", "xor", atomic_load_xor_i32>; 904e8d8bef9SDimitry Andric } 905e8d8bef9SDimitry Andric 906*0fca6ea1SDimitry Andric def XFADDD : XFALU64<BPF_DW, BPF_ADD, "u64", "add", atomic_load_add_i64>; 907*0fca6ea1SDimitry Andric def XFANDD : XFALU64<BPF_DW, BPF_AND, "u64", "and", atomic_load_and_i64>; 908*0fca6ea1SDimitry Andric def XFORD : XFALU64<BPF_DW, BPF_OR, "u64", "or", atomic_load_or_i64>; 909*0fca6ea1SDimitry Andric def XFXORD : XFALU64<BPF_DW, BPF_XOR, "u64", "xor", atomic_load_xor_i64>; 910e8d8bef9SDimitry Andric} 911e8d8bef9SDimitry Andric 912e8d8bef9SDimitry Andric// atomic_load_sub can be represented as a neg followed 913e8d8bef9SDimitry Andric// by an atomic_load_add. 914*0fca6ea1SDimitry Andricdef : Pat<(atomic_load_sub_i32 ADDRri:$addr, GPR32:$val), 915e8d8bef9SDimitry Andric (XFADDW32 ADDRri:$addr, (NEG_32 GPR32:$val))>; 916*0fca6ea1SDimitry Andricdef : Pat<(atomic_load_sub_i64 ADDRri:$addr, GPR:$val), 917e8d8bef9SDimitry Andric (XFADDD ADDRri:$addr, (NEG_64 GPR:$val))>; 918e8d8bef9SDimitry Andric 919e8d8bef9SDimitry Andric// Atomic Exchange 920e8d8bef9SDimitry Andricclass XCHG<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode> 921e8d8bef9SDimitry Andric : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value, 922e8d8bef9SDimitry Andric (outs GPR:$dst), 923e8d8bef9SDimitry Andric (ins MEMri:$addr, GPR:$val), 924e8d8bef9SDimitry Andric "$dst = xchg_"#OpcodeStr#"($addr, $val)", 925e8d8bef9SDimitry Andric [(set GPR:$dst, (OpNode ADDRri:$addr,GPR:$val))]> { 926e8d8bef9SDimitry Andric bits<4> dst; 927e8d8bef9SDimitry Andric bits<20> addr; 928e8d8bef9SDimitry Andric 929e8d8bef9SDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 930e8d8bef9SDimitry Andric let Inst{55-52} = dst; 931e8d8bef9SDimitry Andric let Inst{47-32} = addr{15-0}; // offset 932e8d8bef9SDimitry Andric let Inst{7-4} = BPF_XCHG.Value; 933e8d8bef9SDimitry Andric let Inst{3-0} = BPF_FETCH.Value; 934e8d8bef9SDimitry Andric let BPFClass = BPF_STX; 935e8d8bef9SDimitry Andric} 936e8d8bef9SDimitry Andric 937e8d8bef9SDimitry Andricclass XCHG32<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode> 938e8d8bef9SDimitry Andric : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value, 939e8d8bef9SDimitry Andric (outs GPR32:$dst), 940e8d8bef9SDimitry Andric (ins MEMri:$addr, GPR32:$val), 941e8d8bef9SDimitry Andric "$dst = xchg32_"#OpcodeStr#"($addr, $val)", 942e8d8bef9SDimitry Andric [(set GPR32:$dst, (OpNode ADDRri:$addr,GPR32:$val))]> { 943e8d8bef9SDimitry Andric bits<4> dst; 944e8d8bef9SDimitry Andric bits<20> addr; 945e8d8bef9SDimitry Andric 946e8d8bef9SDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 947e8d8bef9SDimitry Andric let Inst{55-52} = dst; 948e8d8bef9SDimitry Andric let Inst{47-32} = addr{15-0}; // offset 949e8d8bef9SDimitry Andric let Inst{7-4} = BPF_XCHG.Value; 950e8d8bef9SDimitry Andric let Inst{3-0} = BPF_FETCH.Value; 951e8d8bef9SDimitry Andric let BPFClass = BPF_STX; 952e8d8bef9SDimitry Andric} 953e8d8bef9SDimitry Andric 954e8d8bef9SDimitry Andriclet Constraints = "$dst = $val" in { 955e8d8bef9SDimitry Andric let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in { 956*0fca6ea1SDimitry Andric def XCHGW32 : XCHG32<BPF_W, "32", atomic_swap_i32>; 957e8d8bef9SDimitry Andric } 958e8d8bef9SDimitry Andric 959*0fca6ea1SDimitry Andric def XCHGD : XCHG<BPF_DW, "64", atomic_swap_i64>; 960e8d8bef9SDimitry Andric} 961e8d8bef9SDimitry Andric 962e8d8bef9SDimitry Andric// Compare-And-Exchange 963e8d8bef9SDimitry Andricclass CMPXCHG<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode> 964e8d8bef9SDimitry Andric : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value, 965e8d8bef9SDimitry Andric (outs), 966e8d8bef9SDimitry Andric (ins MEMri:$addr, GPR:$new), 967e8d8bef9SDimitry Andric "r0 = cmpxchg_"#OpcodeStr#"($addr, r0, $new)", 968e8d8bef9SDimitry Andric [(set R0, (OpNode ADDRri:$addr, R0, GPR:$new))]> { 969e8d8bef9SDimitry Andric bits<4> new; 970e8d8bef9SDimitry Andric bits<20> addr; 971e8d8bef9SDimitry Andric 972e8d8bef9SDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 973e8d8bef9SDimitry Andric let Inst{55-52} = new; 974e8d8bef9SDimitry Andric let Inst{47-32} = addr{15-0}; // offset 975e8d8bef9SDimitry Andric let Inst{7-4} = BPF_CMPXCHG.Value; 976e8d8bef9SDimitry Andric let Inst{3-0} = BPF_FETCH.Value; 977e8d8bef9SDimitry Andric let BPFClass = BPF_STX; 978e8d8bef9SDimitry Andric} 979e8d8bef9SDimitry Andric 980e8d8bef9SDimitry Andricclass CMPXCHG32<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode> 981e8d8bef9SDimitry Andric : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value, 982e8d8bef9SDimitry Andric (outs), 983e8d8bef9SDimitry Andric (ins MEMri:$addr, GPR32:$new), 984e8d8bef9SDimitry Andric "w0 = cmpxchg32_"#OpcodeStr#"($addr, w0, $new)", 985e8d8bef9SDimitry Andric [(set W0, (OpNode ADDRri:$addr, W0, GPR32:$new))]> { 986e8d8bef9SDimitry Andric bits<4> new; 987e8d8bef9SDimitry Andric bits<20> addr; 988e8d8bef9SDimitry Andric 989e8d8bef9SDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 990e8d8bef9SDimitry Andric let Inst{55-52} = new; 991e8d8bef9SDimitry Andric let Inst{47-32} = addr{15-0}; // offset 992e8d8bef9SDimitry Andric let Inst{7-4} = BPF_CMPXCHG.Value; 993e8d8bef9SDimitry Andric let Inst{3-0} = BPF_FETCH.Value; 994e8d8bef9SDimitry Andric let BPFClass = BPF_STX; 995e8d8bef9SDimitry Andric} 996e8d8bef9SDimitry Andric 997e8d8bef9SDimitry Andriclet Predicates = [BPFHasALU32], Defs = [W0], Uses = [W0], 998e8d8bef9SDimitry Andric DecoderNamespace = "BPFALU32" in { 999*0fca6ea1SDimitry Andric def CMPXCHGW32 : CMPXCHG32<BPF_W, "32", atomic_cmp_swap_i32>; 1000e8d8bef9SDimitry Andric} 1001e8d8bef9SDimitry Andric 1002e8d8bef9SDimitry Andriclet Defs = [R0], Uses = [R0] in { 1003*0fca6ea1SDimitry Andric def CMPXCHGD : CMPXCHG<BPF_DW, "64", atomic_cmp_swap_i64>; 10040b57cec5SDimitry Andric} 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric// bswap16, bswap32, bswap64 10075f757f3fSDimitry Andricclass BSWAP<BPFOpClass Class, bits<32> SizeOp, string OpcodeStr, BPFSrcType SrcType, list<dag> Pattern> 10080b57cec5SDimitry Andric : TYPE_ALU_JMP<BPF_END.Value, SrcType.Value, 10090b57cec5SDimitry Andric (outs GPR:$dst), 10100b57cec5SDimitry Andric (ins GPR:$src), 10110b57cec5SDimitry Andric "$dst = "#OpcodeStr#" $src", 10120b57cec5SDimitry Andric Pattern> { 10130b57cec5SDimitry Andric bits<4> dst; 10140b57cec5SDimitry Andric 10150b57cec5SDimitry Andric let Inst{51-48} = dst; 10160b57cec5SDimitry Andric let Inst{31-0} = SizeOp; 10175f757f3fSDimitry Andric let BPFClass = Class; 10180b57cec5SDimitry Andric} 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andriclet Constraints = "$dst = $src" in { 10225f757f3fSDimitry Andric let Predicates = [BPFHasBswap] in { 10235f757f3fSDimitry Andric def BSWAP16 : BSWAP<BPF_ALU64, 16, "bswap16", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>; 10245f757f3fSDimitry Andric def BSWAP32 : BSWAP<BPF_ALU64, 32, "bswap32", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>; 10255f757f3fSDimitry Andric def BSWAP64 : BSWAP<BPF_ALU64, 64, "bswap64", BPF_TO_LE, [(set GPR:$dst, (bswap GPR:$src))]>; 10265f757f3fSDimitry Andric } 10275f757f3fSDimitry Andric 10285f757f3fSDimitry Andric let Predicates = [BPFNoBswap] in { 10290b57cec5SDimitry Andric let Predicates = [BPFIsLittleEndian] in { 10305f757f3fSDimitry Andric def BE16 : BSWAP<BPF_ALU, 16, "be16", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>; 10315f757f3fSDimitry Andric def BE32 : BSWAP<BPF_ALU, 32, "be32", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>; 10325f757f3fSDimitry Andric def BE64 : BSWAP<BPF_ALU, 64, "be64", BPF_TO_BE, [(set GPR:$dst, (bswap GPR:$src))]>; 10330b57cec5SDimitry Andric } 10340b57cec5SDimitry Andric let Predicates = [BPFIsBigEndian] in { 10355f757f3fSDimitry Andric def LE16 : BSWAP<BPF_ALU, 16, "le16", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>; 10365f757f3fSDimitry Andric def LE32 : BSWAP<BPF_ALU, 32, "le32", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>; 10375f757f3fSDimitry Andric def LE64 : BSWAP<BPF_ALU, 64, "le64", BPF_TO_LE, [(set GPR:$dst, (bswap GPR:$src))]>; 10385f757f3fSDimitry Andric } 10390b57cec5SDimitry Andric } 10400b57cec5SDimitry Andric} 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andriclet Defs = [R0, R1, R2, R3, R4, R5], Uses = [R6], hasSideEffects = 1, 10430b57cec5SDimitry Andric hasExtraDefRegAllocReq = 1, hasExtraSrcRegAllocReq = 1, mayLoad = 1 in { 10440b57cec5SDimitry Andricclass LOAD_ABS<BPFWidthModifer SizeOp, string OpcodeStr, Intrinsic OpNode> 10450b57cec5SDimitry Andric : TYPE_LD_ST<BPF_ABS.Value, SizeOp.Value, 10460b57cec5SDimitry Andric (outs), 10470b57cec5SDimitry Andric (ins GPR:$skb, i64imm:$imm), 10480b57cec5SDimitry Andric "r0 = *("#OpcodeStr#" *)skb[$imm]", 10490b57cec5SDimitry Andric [(set R0, (OpNode GPR:$skb, i64immSExt32:$imm))]> { 10500b57cec5SDimitry Andric bits<32> imm; 10510b57cec5SDimitry Andric 10520b57cec5SDimitry Andric let Inst{31-0} = imm; 10530b57cec5SDimitry Andric let BPFClass = BPF_LD; 10540b57cec5SDimitry Andric} 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andricclass LOAD_IND<BPFWidthModifer SizeOp, string OpcodeStr, Intrinsic OpNode> 10570b57cec5SDimitry Andric : TYPE_LD_ST<BPF_IND.Value, SizeOp.Value, 10580b57cec5SDimitry Andric (outs), 10590b57cec5SDimitry Andric (ins GPR:$skb, GPR:$val), 10600b57cec5SDimitry Andric "r0 = *("#OpcodeStr#" *)skb[$val]", 10610b57cec5SDimitry Andric [(set R0, (OpNode GPR:$skb, GPR:$val))]> { 10620b57cec5SDimitry Andric bits<4> val; 10630b57cec5SDimitry Andric 10640b57cec5SDimitry Andric let Inst{55-52} = val; 10650b57cec5SDimitry Andric let BPFClass = BPF_LD; 10660b57cec5SDimitry Andric} 10670b57cec5SDimitry Andric} 10680b57cec5SDimitry Andric 10690b57cec5SDimitry Andricdef LD_ABS_B : LOAD_ABS<BPF_B, "u8", int_bpf_load_byte>; 10700b57cec5SDimitry Andricdef LD_ABS_H : LOAD_ABS<BPF_H, "u16", int_bpf_load_half>; 10710b57cec5SDimitry Andricdef LD_ABS_W : LOAD_ABS<BPF_W, "u32", int_bpf_load_word>; 10720b57cec5SDimitry Andric 10730b57cec5SDimitry Andricdef LD_IND_B : LOAD_IND<BPF_B, "u8", int_bpf_load_byte>; 10740b57cec5SDimitry Andricdef LD_IND_H : LOAD_IND<BPF_H, "u16", int_bpf_load_half>; 10750b57cec5SDimitry Andricdef LD_IND_W : LOAD_IND<BPF_W, "u32", int_bpf_load_word>; 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andriclet isCodeGenOnly = 1 in { 10785f757f3fSDimitry Andric def MOV_32_64 : ALU_RR<BPF_ALU, BPF_MOV, 0, 10790b57cec5SDimitry Andric (outs GPR:$dst), (ins GPR32:$src), 10800b57cec5SDimitry Andric "$dst = $src", []>; 10810b57cec5SDimitry Andric} 10820b57cec5SDimitry Andric 10835f757f3fSDimitry Andriclet Predicates = [BPFNoMovsx] in { 10840b57cec5SDimitry Andric def : Pat<(i64 (sext GPR32:$src)), 10850b57cec5SDimitry Andric (SRA_ri (SLL_ri (MOV_32_64 GPR32:$src), 32), 32)>; 10865f757f3fSDimitry Andric} 10875f757f3fSDimitry Andric 10885f757f3fSDimitry Andriclet Predicates = [BPFHasMovsx] in { 10895f757f3fSDimitry Andric def : Pat<(i64 (sext GPR32:$src)), 10905f757f3fSDimitry Andric (MOVSX_rr_32 (MOV_32_64 GPR32:$src))>; 10915f757f3fSDimitry Andric} 10920b57cec5SDimitry Andric 10935ffd83dbSDimitry Andricdef : Pat<(i64 (zext GPR32:$src)), (MOV_32_64 GPR32:$src)>; 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andric// For i64 -> i32 truncation, use the 32-bit subregister directly. 10960b57cec5SDimitry Andricdef : Pat<(i32 (trunc GPR:$src)), 10970b57cec5SDimitry Andric (i32 (EXTRACT_SUBREG GPR:$src, sub_32))>; 10980b57cec5SDimitry Andric 10990b57cec5SDimitry Andric// For i32 -> i64 anyext, we don't care about the high bits. 11000b57cec5SDimitry Andricdef : Pat<(i64 (anyext GPR32:$src)), 11010b57cec5SDimitry Andric (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>; 11020b57cec5SDimitry Andric 11030b57cec5SDimitry Andricclass STORE32<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern> 11040b57cec5SDimitry Andric : TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value, 11050b57cec5SDimitry Andric (outs), 11060b57cec5SDimitry Andric (ins GPR32:$src, MEMri:$addr), 11070b57cec5SDimitry Andric "*("#OpcodeStr#" *)($addr) = $src", 11080b57cec5SDimitry Andric Pattern> { 11090b57cec5SDimitry Andric bits<4> src; 11100b57cec5SDimitry Andric bits<20> addr; 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric let Inst{51-48} = addr{19-16}; // base reg 11130b57cec5SDimitry Andric let Inst{55-52} = src; 11140b57cec5SDimitry Andric let Inst{47-32} = addr{15-0}; // offset 11150b57cec5SDimitry Andric let BPFClass = BPF_STX; 11160b57cec5SDimitry Andric} 11170b57cec5SDimitry Andric 11180b57cec5SDimitry Andricclass STOREi32<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode> 11195f757f3fSDimitry Andric : STORE32<Opc, OpcodeStr, [(OpNode GPR32:$src, ADDRri:$addr)]>; 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andriclet Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in { 11220b57cec5SDimitry Andric def STW32 : STOREi32<BPF_W, "u32", store>; 11230b57cec5SDimitry Andric def STH32 : STOREi32<BPF_H, "u16", truncstorei16>; 11240b57cec5SDimitry Andric def STB32 : STOREi32<BPF_B, "u8", truncstorei8>; 11250b57cec5SDimitry Andric} 11260b57cec5SDimitry Andric 11275f757f3fSDimitry Andricclass LOAD32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, list<dag> Pattern> 11285f757f3fSDimitry Andric : TYPE_LD_ST<ModOp.Value, SizeOp.Value, 11290b57cec5SDimitry Andric (outs GPR32:$dst), 11300b57cec5SDimitry Andric (ins MEMri:$addr), 11310b57cec5SDimitry Andric "$dst = *("#OpcodeStr#" *)($addr)", 11320b57cec5SDimitry Andric Pattern> { 11330b57cec5SDimitry Andric bits<4> dst; 11340b57cec5SDimitry Andric bits<20> addr; 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric let Inst{51-48} = dst; 11370b57cec5SDimitry Andric let Inst{55-52} = addr{19-16}; 11380b57cec5SDimitry Andric let Inst{47-32} = addr{15-0}; 11390b57cec5SDimitry Andric let BPFClass = BPF_LDX; 11400b57cec5SDimitry Andric} 11410b57cec5SDimitry Andric 11425f757f3fSDimitry Andricclass LOADi32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, PatFrag OpNode> 11435f757f3fSDimitry Andric : LOAD32<SizeOp, ModOp, OpcodeStr, [(set i32:$dst, (OpNode ADDRri:$addr))]>; 11440b57cec5SDimitry Andric 11450b57cec5SDimitry Andriclet Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in { 11465f757f3fSDimitry Andric def LDW32 : LOADi32<BPF_W, BPF_MEM, "u32", load>; 11475f757f3fSDimitry Andric def LDH32 : LOADi32<BPF_H, BPF_MEM, "u16", zextloadi16>; 11485f757f3fSDimitry Andric def LDB32 : LOADi32<BPF_B, BPF_MEM, "u8", zextloadi8>; 11490b57cec5SDimitry Andric} 11500b57cec5SDimitry Andric 11510b57cec5SDimitry Andriclet Predicates = [BPFHasALU32] in { 11520b57cec5SDimitry Andric def : Pat<(truncstorei8 GPR:$src, ADDRri:$dst), 11530b57cec5SDimitry Andric (STB32 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; 11540b57cec5SDimitry Andric def : Pat<(truncstorei16 GPR:$src, ADDRri:$dst), 11550b57cec5SDimitry Andric (STH32 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; 11560b57cec5SDimitry Andric def : Pat<(truncstorei32 GPR:$src, ADDRri:$dst), 11570b57cec5SDimitry Andric (STW32 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>; 11580b57cec5SDimitry Andric def : Pat<(i32 (extloadi8 ADDRri:$src)), (i32 (LDB32 ADDRri:$src))>; 11590b57cec5SDimitry Andric def : Pat<(i32 (extloadi16 ADDRri:$src)), (i32 (LDH32 ADDRri:$src))>; 11605f757f3fSDimitry Andric 11615f757f3fSDimitry Andric let Predicates = [BPFHasLdsx] in { 11625f757f3fSDimitry Andric def : Pat<(i32 (sextloadi8 ADDRri:$src)), (EXTRACT_SUBREG (LDBSX ADDRri:$src), sub_32)>; 11635f757f3fSDimitry Andric def : Pat<(i32 (sextloadi16 ADDRri:$src)), (EXTRACT_SUBREG (LDHSX ADDRri:$src), sub_32)>; 11645f757f3fSDimitry Andric } 11655f757f3fSDimitry Andric 11660b57cec5SDimitry Andric def : Pat<(i64 (zextloadi8 ADDRri:$src)), 11670b57cec5SDimitry Andric (SUBREG_TO_REG (i64 0), (LDB32 ADDRri:$src), sub_32)>; 11680b57cec5SDimitry Andric def : Pat<(i64 (zextloadi16 ADDRri:$src)), 11690b57cec5SDimitry Andric (SUBREG_TO_REG (i64 0), (LDH32 ADDRri:$src), sub_32)>; 11700b57cec5SDimitry Andric def : Pat<(i64 (zextloadi32 ADDRri:$src)), 11710b57cec5SDimitry Andric (SUBREG_TO_REG (i64 0), (LDW32 ADDRri:$src), sub_32)>; 11720b57cec5SDimitry Andric def : Pat<(i64 (extloadi8 ADDRri:$src)), 11730b57cec5SDimitry Andric (SUBREG_TO_REG (i64 0), (LDB32 ADDRri:$src), sub_32)>; 11740b57cec5SDimitry Andric def : Pat<(i64 (extloadi16 ADDRri:$src)), 11750b57cec5SDimitry Andric (SUBREG_TO_REG (i64 0), (LDH32 ADDRri:$src), sub_32)>; 11760b57cec5SDimitry Andric def : Pat<(i64 (extloadi32 ADDRri:$src)), 11770b57cec5SDimitry Andric (SUBREG_TO_REG (i64 0), (LDW32 ADDRri:$src), sub_32)>; 11780b57cec5SDimitry Andric} 11790b57cec5SDimitry Andric 11800b57cec5SDimitry Andriclet usesCustomInserter = 1, isCodeGenOnly = 1 in { 11810b57cec5SDimitry Andric def MEMCPY : Pseudo< 11820b57cec5SDimitry Andric (outs), 11830b57cec5SDimitry Andric (ins GPR:$dst, GPR:$src, i64imm:$len, i64imm:$align, variable_ops), 11840b57cec5SDimitry Andric "#memcpy dst: $dst, src: $src, len: $len, align: $align", 11850b57cec5SDimitry Andric [(BPFmemcpy GPR:$dst, GPR:$src, imm:$len, imm:$align)]>; 11860b57cec5SDimitry Andric} 1187