Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / lib / Target / BPF / BPFInstrInfo.td
blob305cbbd34d2707da0daf6fe5a063380ecd05a369
1 //===-- BPFInstrInfo.td - Target Description for BPF Target ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file describes the BPF instructions in TableGen format.
11 //===----------------------------------------------------------------------===//
13 include "BPFInstrFormats.td"
15 // Instruction Operands and Patterns
17 // These are target-independent nodes, but have target-specific formats.
18 def SDT_BPFCallSeqStart : SDCallSeqStart<[SDTCisVT<0, iPTR>,
19                                           SDTCisVT<1, iPTR>]>;
20 def SDT_BPFCallSeqEnd   : SDCallSeqEnd<[SDTCisVT<0, iPTR>, SDTCisVT<1, iPTR>]>;
21 def SDT_BPFCall         : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
22 def SDT_BPFSetFlag      : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>]>;
23 def SDT_BPFSelectCC     : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>,
24                                                SDTCisSameAs<0, 4>,
25                                                SDTCisSameAs<4, 5>]>;
26 def SDT_BPFBrCC         : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>,
27                                                SDTCisVT<3, OtherVT>]>;
28 def SDT_BPFWrapper      : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>,
29                                                SDTCisPtrTy<0>]>;
30 def SDT_BPFMEMCPY       : SDTypeProfile<0, 4, [SDTCisVT<0, i64>,
31                                                SDTCisVT<1, i64>,
32                                                SDTCisVT<2, i64>,
33                                                SDTCisVT<3, i64>]>;
35 def BPFcall         : SDNode<"BPFISD::CALL", SDT_BPFCall,
36                              [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
37                               SDNPVariadic]>;
38 def BPFretglue      : SDNode<"BPFISD::RET_GLUE", SDTNone,
39                              [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
40 def BPFcallseq_start: SDNode<"ISD::CALLSEQ_START", SDT_BPFCallSeqStart,
41                              [SDNPHasChain, SDNPOutGlue]>;
42 def BPFcallseq_end  : SDNode<"ISD::CALLSEQ_END",   SDT_BPFCallSeqEnd,
43                              [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
44 def BPFbrcc         : SDNode<"BPFISD::BR_CC", SDT_BPFBrCC,
45                              [SDNPHasChain, SDNPOutGlue, SDNPInGlue]>;
47 def BPFselectcc     : SDNode<"BPFISD::SELECT_CC", SDT_BPFSelectCC, [SDNPInGlue]>;
48 def BPFWrapper      : SDNode<"BPFISD::Wrapper", SDT_BPFWrapper>;
49 def BPFmemcpy       : SDNode<"BPFISD::MEMCPY", SDT_BPFMEMCPY,
50                              [SDNPHasChain, SDNPInGlue, SDNPOutGlue,
51                               SDNPMayStore, SDNPMayLoad]>;
52 def BPFIsLittleEndian : Predicate<"CurDAG->getDataLayout().isLittleEndian()">;
53 def BPFIsBigEndian    : Predicate<"!CurDAG->getDataLayout().isLittleEndian()">;
54 def BPFHasALU32 : Predicate<"Subtarget->getHasAlu32()">;
55 def BPFNoALU32 : Predicate<"!Subtarget->getHasAlu32()">;
56 def BPFHasLdsx : Predicate<"Subtarget->hasLdsx()">;
57 def BPFHasMovsx : Predicate<"Subtarget->hasMovsx()">;
58 def BPFHasBswap : Predicate<"Subtarget->hasBswap()">;
59 def BPFHasSdivSmod : Predicate<"Subtarget->hasSdivSmod()">;
60 def BPFNoMovsx : Predicate<"!Subtarget->hasMovsx()">;
61 def BPFNoBswap : Predicate<"!Subtarget->hasBswap()">;
62 def BPFHasStoreImm : Predicate<"Subtarget->hasStoreImm()">;
64 class ImmediateAsmOperand<string name> : AsmOperandClass {
65   let Name = name;
66   let RenderMethod = "addImmOperands";
67   let DiagnosticType = !strconcat("Invalid", name);
70 def SImm16AsmOperand : ImmediateAsmOperand<"SImm16">;
72 def brtarget : Operand<OtherVT> {
73   let PrintMethod = "printBrTargetOperand";
74   let ParserMatchClass = ImmediateAsmOperand<"BrTarget">;
76 def calltarget : Operand<i64>;
78 def u64imm   : Operand<i64> {
79   let PrintMethod = "printImm64Operand";
82 def s16imm : Operand<i16> {
83   let ParserMatchClass = SImm16AsmOperand;
86 def gpr_or_imm : Operand<i64>;
88 def i64immSExt32 : PatLeaf<(i64 imm),
89                 [{return isInt<32>(N->getSExtValue()); }]>;
90 def i32immSExt32 : PatLeaf<(i32 imm),
91                 [{return isInt<32>(N->getSExtValue()); }]>;
92 def i64immZExt32 : PatLeaf<(i64 imm),
93                 [{return isUInt<32>(N->getZExtValue()); }]>;
95 def imm_to_i64 : SDNodeXForm<timm, [{
96   return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
97 }]>;
99 // Addressing modes.
100 def ADDRri : ComplexPattern<i64, 2, "SelectAddr", [], []>;
101 def FIri : ComplexPattern<i64, 2, "SelectFIAddr", [add, or], []>;
103 // Address operands
104 def MEMri : Operand<i64> {
105   let PrintMethod = "printMemOperand";
106   let EncoderMethod = "getMemoryOpValue";
107   let DecoderMethod = "decodeMemoryOpValue";
108   let MIOperandInfo = (ops GPR, s16imm);
111 // Conditional code predicates - used for pattern matching for jump instructions
112 def BPF_CC_EQ  : PatLeaf<(i64 imm),
113                          [{return (N->getZExtValue() == ISD::SETEQ);}]>;
114 def BPF_CC_NE  : PatLeaf<(i64 imm),
115                          [{return (N->getZExtValue() == ISD::SETNE);}]>;
116 def BPF_CC_GE  : PatLeaf<(i64 imm),
117                          [{return (N->getZExtValue() == ISD::SETGE);}]>;
118 def BPF_CC_GT  : PatLeaf<(i64 imm),
119                          [{return (N->getZExtValue() == ISD::SETGT);}]>;
120 def BPF_CC_GTU : PatLeaf<(i64 imm),
121                          [{return (N->getZExtValue() == ISD::SETUGT);}]>;
122 def BPF_CC_GEU : PatLeaf<(i64 imm),
123                          [{return (N->getZExtValue() == ISD::SETUGE);}]>;
124 def BPF_CC_LE  : PatLeaf<(i64 imm),
125                          [{return (N->getZExtValue() == ISD::SETLE);}]>;
126 def BPF_CC_LT  : PatLeaf<(i64 imm),
127                          [{return (N->getZExtValue() == ISD::SETLT);}]>;
128 def BPF_CC_LTU : PatLeaf<(i64 imm),
129                          [{return (N->getZExtValue() == ISD::SETULT);}]>;
130 def BPF_CC_LEU : PatLeaf<(i64 imm),
131                          [{return (N->getZExtValue() == ISD::SETULE);}]>;
132 def BPF_CC_EQ_32  : PatLeaf<(i32 imm),
133                          [{return (N->getZExtValue() == ISD::SETEQ);}]>;
134 def BPF_CC_NE_32  : PatLeaf<(i32 imm),
135                          [{return (N->getZExtValue() == ISD::SETNE);}]>;
136 def BPF_CC_GE_32  : PatLeaf<(i32 imm),
137                          [{return (N->getZExtValue() == ISD::SETGE);}]>;
138 def BPF_CC_GT_32  : PatLeaf<(i32 imm),
139                          [{return (N->getZExtValue() == ISD::SETGT);}]>;
140 def BPF_CC_GTU_32 : PatLeaf<(i32 imm),
141                          [{return (N->getZExtValue() == ISD::SETUGT);}]>;
142 def BPF_CC_GEU_32 : PatLeaf<(i32 imm),
143                          [{return (N->getZExtValue() == ISD::SETUGE);}]>;
144 def BPF_CC_LE_32  : PatLeaf<(i32 imm),
145                          [{return (N->getZExtValue() == ISD::SETLE);}]>;
146 def BPF_CC_LT_32  : PatLeaf<(i32 imm),
147                          [{return (N->getZExtValue() == ISD::SETLT);}]>;
148 def BPF_CC_LTU_32 : PatLeaf<(i32 imm),
149                          [{return (N->getZExtValue() == ISD::SETULT);}]>;
150 def BPF_CC_LEU_32 : PatLeaf<(i32 imm),
151                          [{return (N->getZExtValue() == ISD::SETULE);}]>;
153 // For arithmetic and jump instructions the 8-bit 'code'
154 // field is divided into three parts:
156 //  +----------------+--------+--------------------+
157 //  |   4 bits       |  1 bit |   3 bits           |
158 //  | operation code | source | instruction class  |
159 //  +----------------+--------+--------------------+
160 //  (MSB)                                      (LSB)
161 class TYPE_ALU_JMP<bits<4> op, bits<1> srctype,
162                    dag outs, dag ins, string asmstr, list<dag> pattern>
163   : InstBPF<outs, ins, asmstr, pattern> {
165   let Inst{63-60} = op;
166   let Inst{59} = srctype;
169 //For load and store instructions the 8-bit 'code' field is divided as:
171 //  +--------+--------+-------------------+
172 //  | 3 bits | 2 bits |   3 bits          |
173 //  |  mode  |  size  | instruction class |
174 //  +--------+--------+-------------------+
175 //  (MSB)                             (LSB)
176 class TYPE_LD_ST<bits<3> mode, bits<2> size,
177                  dag outs, dag ins, string asmstr, list<dag> pattern>
178   : InstBPF<outs, ins, asmstr, pattern> {
180   let Inst{63-61} = mode;
181   let Inst{60-59} = size;
184 // jump instructions
185 class JMP_RR<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
186     : TYPE_ALU_JMP<Opc.Value, BPF_X.Value,
187                    (outs),
188                    (ins GPR:$dst, GPR:$src, brtarget:$BrDst),
189                    "if $dst "#OpcodeStr#" $src goto $BrDst",
190                    [(BPFbrcc i64:$dst, i64:$src, Cond, bb:$BrDst)]> {
191   bits<4> dst;
192   bits<4> src;
193   bits<16> BrDst;
195   let Inst{55-52} = src;
196   let Inst{51-48} = dst;
197   let Inst{47-32} = BrDst;
198   let BPFClass = BPF_JMP;
201 class JMP_RI<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
202     : TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
203                    (outs),
204                    (ins GPR:$dst, i64imm:$imm, brtarget:$BrDst),
205                    "if $dst "#OpcodeStr#" $imm goto $BrDst",
206                    [(BPFbrcc i64:$dst, i64immSExt32:$imm, Cond, bb:$BrDst)]> {
207   bits<4> dst;
208   bits<16> BrDst;
209   bits<32> imm;
211   let Inst{51-48} = dst;
212   let Inst{47-32} = BrDst;
213   let Inst{31-0} = imm;
214   let BPFClass = BPF_JMP;
217 class JMP_RR_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
218     : TYPE_ALU_JMP<Opc.Value, BPF_X.Value,
219                    (outs),
220                    (ins GPR32:$dst, GPR32:$src, brtarget:$BrDst),
221                    "if $dst "#OpcodeStr#" $src goto $BrDst",
222                    [(BPFbrcc i32:$dst, i32:$src, Cond, bb:$BrDst)]> {
223   bits<4> dst;
224   bits<4> src;
225   bits<16> BrDst;
227   let Inst{55-52} = src;
228   let Inst{51-48} = dst;
229   let Inst{47-32} = BrDst;
230   let BPFClass = BPF_JMP32;
233 class JMP_RI_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
234     : TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
235                    (outs),
236                    (ins GPR32:$dst, i32imm:$imm, brtarget:$BrDst),
237                    "if $dst "#OpcodeStr#" $imm goto $BrDst",
238                    [(BPFbrcc i32:$dst, i32immSExt32:$imm, Cond, bb:$BrDst)]> {
239   bits<4> dst;
240   bits<16> BrDst;
241   bits<32> imm;
243   let Inst{51-48} = dst;
244   let Inst{47-32} = BrDst;
245   let Inst{31-0} = imm;
246   let BPFClass = BPF_JMP32;
249 multiclass J<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond, PatLeaf Cond32> {
250   def _rr : JMP_RR<Opc, OpcodeStr, Cond>;
251   def _ri : JMP_RI<Opc, OpcodeStr, Cond>;
252   def _rr_32 : JMP_RR_32<Opc, OpcodeStr, Cond32>;
253   def _ri_32 : JMP_RI_32<Opc, OpcodeStr, Cond32>;
256 let isBranch = 1, isTerminator = 1, hasDelaySlot=0 in {
257 // cmp+goto instructions
258 defm JEQ  : J<BPF_JEQ, "==",  BPF_CC_EQ, BPF_CC_EQ_32>;
259 defm JUGT : J<BPF_JGT, ">", BPF_CC_GTU, BPF_CC_GTU_32>;
260 defm JUGE : J<BPF_JGE, ">=", BPF_CC_GEU, BPF_CC_GEU_32>;
261 defm JNE  : J<BPF_JNE, "!=",  BPF_CC_NE, BPF_CC_NE_32>;
262 defm JSGT : J<BPF_JSGT, "s>", BPF_CC_GT, BPF_CC_GT_32>;
263 defm JSGE : J<BPF_JSGE, "s>=", BPF_CC_GE, BPF_CC_GE_32>;
264 defm JULT : J<BPF_JLT, "<", BPF_CC_LTU, BPF_CC_LTU_32>;
265 defm JULE : J<BPF_JLE, "<=", BPF_CC_LEU, BPF_CC_LEU_32>;
266 defm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT, BPF_CC_LT_32>;
267 defm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE, BPF_CC_LE_32>;
270 // ALU instructions
271 class ALU_RI<BPFOpClass Class, BPFArithOp Opc, int off,
272              dag outs, dag ins, string asmstr, list<dag> pattern>
273     : TYPE_ALU_JMP<Opc.Value, BPF_K.Value, outs, ins, asmstr, pattern> {
274   bits<4> dst;
275   bits<32> imm;
277   let Inst{51-48} = dst;
278   let Inst{47-32} = off;
279   let Inst{31-0} = imm;
280   let BPFClass = Class;
283 class ALU_RR<BPFOpClass Class, BPFArithOp Opc, int off,
284              dag outs, dag ins, string asmstr, list<dag> pattern>
285     : TYPE_ALU_JMP<Opc.Value, BPF_X.Value, outs, ins, asmstr, pattern> {
286   bits<4> dst;
287   bits<4> src;
289   let Inst{55-52} = src;
290   let Inst{51-48} = dst;
291   let Inst{47-32} = off;
292   let BPFClass = Class;
295 multiclass ALU<BPFArithOp Opc, int off, string OpcodeStr, SDNode OpNode> {
296   def _rr : ALU_RR<BPF_ALU64, Opc, off,
297                    (outs GPR:$dst),
298                    (ins GPR:$src2, GPR:$src),
299                    "$dst "#OpcodeStr#" $src",
300                    [(set GPR:$dst, (OpNode i64:$src2, i64:$src))]>;
301   def _ri : ALU_RI<BPF_ALU64, Opc, off,
302                    (outs GPR:$dst),
303                    (ins GPR:$src2, i64imm:$imm),
304                    "$dst "#OpcodeStr#" $imm",
305                    [(set GPR:$dst, (OpNode GPR:$src2, i64immSExt32:$imm))]>;
306   def _rr_32 : ALU_RR<BPF_ALU, Opc, off,
307                    (outs GPR32:$dst),
308                    (ins GPR32:$src2, GPR32:$src),
309                    "$dst "#OpcodeStr#" $src",
310                    [(set GPR32:$dst, (OpNode i32:$src2, i32:$src))]>;
311   def _ri_32 : ALU_RI<BPF_ALU, Opc, off,
312                    (outs GPR32:$dst),
313                    (ins GPR32:$src2, i32imm:$imm),
314                    "$dst "#OpcodeStr#" $imm",
315                    [(set GPR32:$dst, (OpNode GPR32:$src2, i32immSExt32:$imm))]>;
318 let Constraints = "$dst = $src2" in {
319 let isAsCheapAsAMove = 1 in {
320   defm ADD : ALU<BPF_ADD, 0, "+=", add>;
321   defm SUB : ALU<BPF_SUB, 0, "-=", sub>;
322   defm OR  : ALU<BPF_OR, 0, "|=", or>;
323   defm AND : ALU<BPF_AND, 0, "&=", and>;
324   defm SLL : ALU<BPF_LSH, 0, "<<=", shl>;
325   defm SRL : ALU<BPF_RSH, 0, ">>=", srl>;
326   defm XOR : ALU<BPF_XOR, 0, "^=", xor>;
327   defm SRA : ALU<BPF_ARSH, 0, "s>>=", sra>;
329   defm MUL : ALU<BPF_MUL, 0, "*=", mul>;
330   defm DIV : ALU<BPF_DIV, 0, "/=", udiv>;
331   defm MOD : ALU<BPF_MOD, 0, "%=", urem>;
333   let Predicates = [BPFHasSdivSmod] in {
334     defm SDIV : ALU<BPF_DIV, 1, "s/=", sdiv>;
335     defm SMOD : ALU<BPF_MOD, 1, "s%=", srem>;
336   }
339 class NEG_RR<BPFOpClass Class, BPFArithOp Opc,
340              dag outs, dag ins, string asmstr, list<dag> pattern>
341     : TYPE_ALU_JMP<Opc.Value, 0, outs, ins, asmstr, pattern> {
342   bits<4> dst;
344   let Inst{51-48} = dst;
345   let BPFClass = Class;
348 let Constraints = "$dst = $src", isAsCheapAsAMove = 1 in {
349   def NEG_64: NEG_RR<BPF_ALU64, BPF_NEG, (outs GPR:$dst), (ins GPR:$src),
350                      "$dst = -$src",
351                      [(set GPR:$dst, (ineg i64:$src))]>;
352   def NEG_32: NEG_RR<BPF_ALU, BPF_NEG, (outs GPR32:$dst), (ins GPR32:$src),
353                      "$dst = -$src",
354                      [(set GPR32:$dst, (ineg i32:$src))]>;
357 class LD_IMM64<bits<4> Pseudo, string OpcodeStr>
358     : TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value,
359                  (outs GPR:$dst),
360                  (ins u64imm:$imm),
361                  "$dst "#OpcodeStr#" ${imm} ll",
362                  [(set GPR:$dst, (i64 imm:$imm))]> {
364   bits<4> dst;
365   bits<64> imm;
367   let Inst{51-48} = dst;
368   let Inst{55-52} = Pseudo;
369   let Inst{47-32} = 0;
370   let Inst{31-0} = imm{31-0};
371   let BPFClass = BPF_LD;
374 let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
375 def LD_imm64 : LD_IMM64<0, "=">;
376 def MOV_rr : ALU_RR<BPF_ALU64, BPF_MOV, 0,
377                     (outs GPR:$dst),
378                     (ins GPR:$src),
379                     "$dst = $src",
380                     []>;
381 def MOV_ri : ALU_RI<BPF_ALU64, BPF_MOV, 0,
382                     (outs GPR:$dst),
383                     (ins i64imm:$imm),
384                     "$dst = $imm",
385                     [(set GPR:$dst, (i64 i64immSExt32:$imm))]>;
386 def MOV_rr_32 : ALU_RR<BPF_ALU, BPF_MOV, 0,
387                     (outs GPR32:$dst),
388                     (ins GPR32:$src),
389                     "$dst = $src",
390                     []>;
391 def MOV_ri_32 : ALU_RI<BPF_ALU, BPF_MOV, 0,
392                     (outs GPR32:$dst),
393                     (ins i32imm:$imm),
394                     "$dst = $imm",
395                     [(set GPR32:$dst, (i32 i32immSExt32:$imm))]>;
397 let Predicates = [BPFHasMovsx] in {
398   def MOVSX_rr_8 : ALU_RR<BPF_ALU64, BPF_MOV, 8,
399                       (outs GPR:$dst), (ins GPR:$src),
400                       "$dst = (s8)$src",
401                       [(set GPR:$dst, (sext_inreg GPR:$src, i8))]>;
402   def MOVSX_rr_16 : ALU_RR<BPF_ALU64, BPF_MOV, 16,
403                       (outs GPR:$dst), (ins GPR:$src),
404                       "$dst = (s16)$src",
405                       [(set GPR:$dst, (sext_inreg GPR:$src, i16))]>;
406   def MOVSX_rr_32 : ALU_RR<BPF_ALU64, BPF_MOV, 32,
407                       (outs GPR:$dst), (ins GPR:$src),
408                       "$dst = (s32)$src",
409                       [(set GPR:$dst, (sext_inreg GPR:$src, i32))]>;
410   def MOVSX_rr_32_8 : ALU_RR<BPF_ALU, BPF_MOV, 8,
411                       (outs GPR32:$dst), (ins GPR32:$src),
412                       "$dst = (s8)$src",
413                       [(set GPR32:$dst, (sext_inreg GPR32:$src, i8))]>;
414   def MOVSX_rr_32_16 : ALU_RR<BPF_ALU, BPF_MOV, 16,
415                       (outs GPR32:$dst), (ins GPR32:$src),
416                       "$dst = (s16)$src",
417                       [(set GPR32:$dst, (sext_inreg GPR32:$src, i16))]>;
421 def FI_ri
422     : TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value,
423                  (outs GPR:$dst),
424                  (ins MEMri:$addr),
425                  "lea\t$dst, $addr",
426                  [(set i64:$dst, FIri:$addr)]> {
427   // This is a tentative instruction, and will be replaced
428   // with MOV_rr and ADD_ri in PEI phase
429   let Inst{51-48} = 0;
430   let Inst{55-52} = 2;
431   let Inst{47-32} = 0;
432   let Inst{31-0} = 0;
433   let BPFClass = BPF_LD;
434   bit isPseudo = true;
437 def LD_pseudo
438     : TYPE_LD_ST<BPF_IMM.Value, BPF_DW.Value,
439                  (outs GPR:$dst),
440                  (ins i64imm:$pseudo, u64imm:$imm),
441                  "ld_pseudo\t$dst, $pseudo, $imm",
442                  [(set GPR:$dst, (int_bpf_pseudo imm:$pseudo, imm:$imm))]> {
444   bits<4> dst;
445   bits<64> imm;
446   bits<4> pseudo;
448   let Inst{51-48} = dst;
449   let Inst{55-52} = pseudo;
450   let Inst{47-32} = 0;
451   let Inst{31-0} = imm{31-0};
452   let BPFClass = BPF_LD;
455 // STORE instructions
456 class STORE<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
457     : TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value,
458                  (outs),
459                  (ins GPR:$src, MEMri:$addr),
460                  "*("#OpcodeStr#" *)($addr) = $src",
461                  Pattern> {
462   bits<4> src;
463   bits<20> addr;
465   let Inst{51-48} = addr{19-16}; // base reg
466   let Inst{55-52} = src;
467   let Inst{47-32} = addr{15-0}; // offset
468   let BPFClass = BPF_STX;
471 class STOREi64<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
472     : STORE<Opc, OpcodeStr, [(OpNode GPR:$src, ADDRri:$addr)]>;
474 let Predicates = [BPFNoALU32] in {
475   def STW : STOREi64<BPF_W, "u32", truncstorei32>;
476   def STH : STOREi64<BPF_H, "u16", truncstorei16>;
477   def STB : STOREi64<BPF_B, "u8", truncstorei8>;
479 def STD : STOREi64<BPF_DW, "u64", store>;
481 class STORE_imm<BPFWidthModifer SizeOp,
482                 string OpcodeStr, dag Pattern>
483     : TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value,
484                  (outs),
485                  (ins i64imm:$imm, MEMri:$addr),
486                  "*("#OpcodeStr#" *)($addr) = $imm",
487                  [Pattern]> {
488   bits<20> addr;
489   bits<32> imm;
491   let Inst{51-48} = addr{19-16}; // base reg
492   let Inst{47-32} = addr{15-0};  // offset
493   let Inst{31-0} = imm;
494   let BPFClass = BPF_ST;
497 let Predicates = [BPFHasStoreImm] in {
498   // Opcode (BPF_ST | BPF_MEM | BPF_DW) implies sign extension for
499   // value stored to memory:
500   // - it is fine to generate such write when immediate is -1
501   // - it is incorrect to generate such write when immediate is
502   //   +0xffff_ffff.
503   //
504   // In the latter case two instructions would be generated instead of
505   // one BPF_ST:
506   //   rA = 0xffffffff ll     ; LD_imm64
507   //   *(u64 *)(rB + 0) = rA  ; STX
508   //
509   // For BPF_{B,H,W} the size of value stored matches size of the immediate.
510   def STD_imm : STORE_imm<BPF_DW, "u64", (store         (i64 i64immSExt32:$imm), ADDRri:$addr)>;
511   def STW_imm : STORE_imm<BPF_W,  "u32", (truncstorei32 (i64 i64immZExt32:$imm), ADDRri:$addr)>;
512   def STH_imm : STORE_imm<BPF_H,  "u16", (truncstorei16 (i64 i64immZExt32:$imm), ADDRri:$addr)>;
513   def STB_imm : STORE_imm<BPF_B,  "u8",  (truncstorei8  (i64 i64immZExt32:$imm), ADDRri:$addr)>;
516 let Predicates = [BPFHasALU32, BPFHasStoreImm] in {
517   def : Pat<(store (i32 imm:$src), ADDRri:$dst),
518             (STW_imm (imm_to_i64 $src), ADDRri:$dst)>;
519   def : Pat<(truncstorei16 (i32 imm:$src), ADDRri:$dst),
520             (STH_imm (imm_to_i64 imm:$src), ADDRri:$dst)>;
521   def : Pat<(truncstorei8 (i32 imm:$src), ADDRri:$dst),
522             (STB_imm (imm_to_i64 imm:$src), ADDRri:$dst)>;
525 // LOAD instructions
526 class LOAD<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, list<dag> Pattern>
527     : TYPE_LD_ST<ModOp.Value, SizeOp.Value,
528                  (outs GPR:$dst),
529                  (ins MEMri:$addr),
530                  "$dst = *("#OpcodeStr#" *)($addr)",
531                  Pattern> {
532   bits<4> dst;
533   bits<20> addr;
535   let Inst{51-48} = dst;
536   let Inst{55-52} = addr{19-16};
537   let Inst{47-32} = addr{15-0};
538   let BPFClass = BPF_LDX;
541 class LOADi64<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, PatFrag OpNode>
542     : LOAD<SizeOp, ModOp, OpcodeStr, [(set i64:$dst, (OpNode ADDRri:$addr))]>;
544 let isCodeGenOnly = 1 in {
545   class CORE_LD<RegisterClass RegClass, string Sz>
546                 : TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value,
547                              (outs RegClass:$dst),
548                              (ins u64imm:$opcode, GPR:$src, u64imm:$offset),
549                              "$dst = core_ld"#Sz#"($opcode, $src, $offset)",
550                              []>;
551   def CORE_LD64 : CORE_LD<GPR, "64">;
552   def CORE_LD32 : CORE_LD<GPR32, "32">;
553   def CORE_ST   : TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value,
554                              (outs),
555                              (ins gpr_or_imm:$src, u64imm:$opcode, GPR:$ptr, u64imm:$offset),
556                              "core_st($src, $opcode, $ptr, $offset)",
557                              []>;
558   let Constraints = "$dst = $src" in {
559     def CORE_SHIFT : ALU_RR<BPF_ALU64, BPF_LSH, 0,
560                              (outs GPR:$dst),
561                              (ins u64imm:$opcode, GPR:$src, u64imm:$offset),
562                              "$dst = core_shift($opcode, $src, $offset)",
563                              []>;
564   }
567 let Predicates = [BPFNoALU32] in {
568   def LDW : LOADi64<BPF_W, BPF_MEM, "u32", zextloadi32>;
569   def LDH : LOADi64<BPF_H, BPF_MEM, "u16", zextloadi16>;
570   def LDB : LOADi64<BPF_B, BPF_MEM, "u8", zextloadi8>;
573 let Predicates = [BPFHasLdsx] in {
574   def LDWSX : LOADi64<BPF_W, BPF_MEMSX, "s32", sextloadi32>;
575   def LDHSX : LOADi64<BPF_H, BPF_MEMSX, "s16", sextloadi16>;
576   def LDBSX : LOADi64<BPF_B, BPF_MEMSX, "s8",  sextloadi8>;
579 def LDD : LOADi64<BPF_DW, BPF_MEM, "u64", load>;
581 class BRANCH<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
582     : TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
583                    (outs),
584                    (ins brtarget:$BrDst),
585                    !strconcat(OpcodeStr, " $BrDst"),
586                    Pattern> {
587   bits<16> BrDst;
589   let Inst{47-32} = BrDst;
590   let BPFClass = BPF_JMP;
593 class BRANCH_LONG<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
594     : TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
595                    (outs),
596                    (ins brtarget:$BrDst),
597                    !strconcat(OpcodeStr, " $BrDst"),
598                    Pattern> {
599   bits<32> BrDst;
601   let Inst{31-0} = BrDst;
602   let BPFClass = BPF_JMP32;
605 class CALL<string OpcodeStr>
606     : TYPE_ALU_JMP<BPF_CALL.Value, BPF_K.Value,
607                    (outs),
608                    (ins calltarget:$BrDst),
609                    !strconcat(OpcodeStr, " $BrDst"),
610                    []> {
611   bits<32> BrDst;
613   let Inst{31-0} = BrDst;
614   let BPFClass = BPF_JMP;
617 class CALLX<string OpcodeStr>
618     : TYPE_ALU_JMP<BPF_CALL.Value, BPF_X.Value,
619                    (outs),
620                    (ins GPR:$BrDst),
621                    !strconcat(OpcodeStr, " $BrDst"),
622                    []> {
623   bits<32> BrDst;
625   let Inst{31-0} = BrDst;
626   let BPFClass = BPF_JMP;
629 // Jump always
630 let isBranch = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1 in {
631   def JMP : BRANCH<BPF_JA, "goto", [(br bb:$BrDst)]>;
632   def JMPL : BRANCH_LONG<BPF_JA, "gotol", []>;
635 // Jump and link
636 let isCall=1, hasDelaySlot=0, Uses = [R11],
637     // Potentially clobbered registers
638     Defs = [R0, R1, R2, R3, R4, R5] in {
639   def JAL  : CALL<"call">;
640   def JALX  : CALLX<"callx">;
643 class NOP_I<string OpcodeStr>
644     : TYPE_ALU_JMP<BPF_MOV.Value, BPF_X.Value,
645                    (outs),
646                    (ins i32imm:$imm),
647                    !strconcat(OpcodeStr, "\t$imm"),
648                    []> {
649   // mov r0, r0 == nop
650   let Inst{55-52} = 0;
651   let Inst{51-48} = 0;
652   let BPFClass = BPF_ALU64;
655 let hasSideEffects = 0, isCodeGenOnly = 1 in
656   def NOP : NOP_I<"nop">;
658 class RET<string OpcodeStr>
659     : TYPE_ALU_JMP<BPF_EXIT.Value, BPF_K.Value,
660                    (outs),
661                    (ins),
662                    !strconcat(OpcodeStr, ""),
663                    [(BPFretglue)]> {
664   let Inst{31-0} = 0;
665   let BPFClass = BPF_JMP;
668 let isReturn = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1,
669     isNotDuplicable = 1 in {
670   def RET : RET<"exit">;
673 // ADJCALLSTACKDOWN/UP pseudo insns
674 let Defs = [R11], Uses = [R11], isCodeGenOnly = 1 in {
675 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2),
676                               "#ADJCALLSTACKDOWN $amt1 $amt2",
677                               [(BPFcallseq_start timm:$amt1, timm:$amt2)]>;
678 def ADJCALLSTACKUP   : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2),
679                               "#ADJCALLSTACKUP $amt1 $amt2",
680                               [(BPFcallseq_end timm:$amt1, timm:$amt2)]>;
683 let usesCustomInserter = 1, isCodeGenOnly = 1 in {
684   def Select : Pseudo<(outs GPR:$dst),
685                       (ins GPR:$lhs, GPR:$rhs, i64imm:$imm, GPR:$src, GPR:$src2),
686                       "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2",
687                       [(set i64:$dst,
688                        (BPFselectcc i64:$lhs, i64:$rhs, (i64 imm:$imm), i64:$src, i64:$src2))]>;
689   def Select_Ri : Pseudo<(outs GPR:$dst),
690                       (ins GPR:$lhs, i64imm:$rhs, i64imm:$imm, GPR:$src, GPR:$src2),
691                       "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2",
692                       [(set i64:$dst,
693                        (BPFselectcc i64:$lhs, (i64immSExt32:$rhs), (i64 imm:$imm), i64:$src, i64:$src2))]>;
694   def Select_64_32 : Pseudo<(outs GPR32:$dst),
695                       (ins GPR:$lhs, GPR:$rhs, i64imm:$imm, GPR32:$src, GPR32:$src2),
696                       "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2",
697                       [(set i32:$dst,
698                        (BPFselectcc i64:$lhs, i64:$rhs, (i64 imm:$imm), i32:$src, i32:$src2))]>;
699   def Select_Ri_64_32 : Pseudo<(outs GPR32:$dst),
700                       (ins GPR:$lhs, i64imm:$rhs, i64imm:$imm, GPR32:$src, GPR32:$src2),
701                       "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2",
702                       [(set i32:$dst,
703                        (BPFselectcc i64:$lhs, (i64immSExt32:$rhs), (i64 imm:$imm), i32:$src, i32:$src2))]>;
704   def Select_32 : Pseudo<(outs GPR32:$dst),
705                       (ins GPR32:$lhs, GPR32:$rhs, i32imm:$imm, GPR32:$src, GPR32:$src2),
706                       "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2",
707                       [(set i32:$dst,
708                        (BPFselectcc i32:$lhs, i32:$rhs, (i32 imm:$imm), i32:$src, i32:$src2))]>;
709   def Select_Ri_32 : Pseudo<(outs GPR32:$dst),
710                       (ins GPR32:$lhs, i32imm:$rhs, i32imm:$imm, GPR32:$src, GPR32:$src2),
711                       "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2",
712                       [(set i32:$dst,
713                        (BPFselectcc i32:$lhs, (i32immSExt32:$rhs), (i32 imm:$imm), i32:$src, i32:$src2))]>;
714   def Select_32_64 : Pseudo<(outs GPR:$dst),
715                       (ins GPR32:$lhs, GPR32:$rhs, i32imm:$imm, GPR:$src, GPR:$src2),
716                       "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2",
717                       [(set i64:$dst,
718                        (BPFselectcc i32:$lhs, i32:$rhs, (i32 imm:$imm), i64:$src, i64:$src2))]>;
719   def Select_Ri_32_64 : Pseudo<(outs GPR:$dst),
720                       (ins GPR32:$lhs, i32imm:$rhs, i32imm:$imm, GPR:$src, GPR:$src2),
721                       "# Select PSEUDO $dst = $lhs $imm $rhs ? $src : $src2",
722                       [(set i64:$dst,
723                        (BPFselectcc i32:$lhs, (i32immSExt32:$rhs), (i32 imm:$imm), i64:$src, i64:$src2))]>;
726 // load 64-bit global addr into register
727 def : Pat<(BPFWrapper tglobaladdr:$in), (LD_imm64 tglobaladdr:$in)>;
729 // 0xffffFFFF doesn't fit into simm32, optimize common case
730 def : Pat<(i64 (and (i64 GPR:$src), 0xffffFFFF)),
731           (SRL_ri (SLL_ri (i64 GPR:$src), 32), 32)>;
733 // Calls
734 def : Pat<(BPFcall tglobaladdr:$dst), (JAL tglobaladdr:$dst)>;
735 def : Pat<(BPFcall texternalsym:$dst), (JAL texternalsym:$dst)>;
736 def : Pat<(BPFcall imm:$dst), (JAL imm:$dst)>;
737 def : Pat<(BPFcall GPR:$dst), (JALX GPR:$dst)>;
739 // Loads
740 let Predicates = [BPFNoALU32] in {
741   def : Pat<(i64 (extloadi8  ADDRri:$src)), (i64 (LDB ADDRri:$src))>;
742   def : Pat<(i64 (extloadi16 ADDRri:$src)), (i64 (LDH ADDRri:$src))>;
743   def : Pat<(i64 (extloadi32 ADDRri:$src)), (i64 (LDW ADDRri:$src))>;
746 // Atomic XADD for BPFNoALU32
747 class XADD<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
748     : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
749                  (outs GPR:$dst),
750                  (ins MEMri:$addr, GPR:$val),
751                  "lock *("#OpcodeStr#" *)($addr) += $val",
752                  [(set GPR:$dst, (OpNode ADDRri:$addr, GPR:$val))]> {
753   bits<4> dst;
754   bits<20> addr;
756   let Inst{51-48} = addr{19-16}; // base reg
757   let Inst{55-52} = dst;
758   let Inst{47-32} = addr{15-0}; // offset
759   let Inst{7-4} = BPF_ADD.Value;
760   let BPFClass = BPF_STX;
763 let Constraints = "$dst = $val" in {
764   let Predicates = [BPFNoALU32] in {
765     def XADDW : XADD<BPF_W, "u32", atomic_load_add_32>;
766   }
769 // Atomic add, and, or, xor
770 class ATOMIC_NOFETCH<BPFArithOp Opc, string Opstr>
771     : TYPE_LD_ST<BPF_ATOMIC.Value, BPF_DW.Value,
772                  (outs GPR:$dst),
773                  (ins MEMri:$addr, GPR:$val),
774                  "lock *(u64 *)($addr) " #Opstr# "= $val",
775                  []> {
776   bits<4> dst;
777   bits<20> addr;
779   let Inst{51-48} = addr{19-16}; // base reg
780   let Inst{55-52} = dst;
781   let Inst{47-32} = addr{15-0}; // offset
782   let Inst{7-4} = Opc.Value;
783   let BPFClass = BPF_STX;
786 class ATOMIC32_NOFETCH<BPFArithOp Opc, string Opstr>
787     : TYPE_LD_ST<BPF_ATOMIC.Value, BPF_W.Value,
788                  (outs GPR32:$dst),
789                  (ins MEMri:$addr, GPR32:$val),
790                  "lock *(u32 *)($addr) " #Opstr# "= $val",
791                  []> {
792   bits<4> dst;
793   bits<20> addr;
795   let Inst{51-48} = addr{19-16}; // base reg
796   let Inst{55-52} = dst;
797   let Inst{47-32} = addr{15-0}; // offset
798   let Inst{7-4} = Opc.Value;
799   let BPFClass = BPF_STX;
802 let Constraints = "$dst = $val" in {
803   let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
804     def XADDW32 : ATOMIC32_NOFETCH<BPF_ADD, "+">;
805     def XANDW32 : ATOMIC32_NOFETCH<BPF_AND, "&">;
806     def XORW32  : ATOMIC32_NOFETCH<BPF_OR, "|">;
807     def XXORW32 : ATOMIC32_NOFETCH<BPF_XOR, "^">;
808   }
810   def XADDD  : ATOMIC_NOFETCH<BPF_ADD, "+">;
811   def XANDD  : ATOMIC_NOFETCH<BPF_AND, "&">;
812   def XORD   : ATOMIC_NOFETCH<BPF_OR, "|">;
813   def XXORD  : ATOMIC_NOFETCH<BPF_XOR, "^">;
816 // Atomic Fetch-and-<add, and, or, xor> operations
817 class XFALU64<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr,
818               string OpcStr, PatFrag OpNode>
819     : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
820                  (outs GPR:$dst),
821                  (ins MEMri:$addr, GPR:$val),
822                  "$dst = atomic_fetch_"#OpcStr#"(("#OpcodeStr#" *)($addr), $val)",
823                  [(set GPR:$dst, (OpNode ADDRri:$addr, GPR:$val))]> {
824   bits<4> dst;
825   bits<20> addr;
827   let Inst{51-48} = addr{19-16}; // base reg
828   let Inst{55-52} = dst;
829   let Inst{47-32} = addr{15-0}; // offset
830   let Inst{7-4} = Opc.Value;
831   let Inst{3-0} = BPF_FETCH.Value;
832   let BPFClass = BPF_STX;
835 class XFALU32<BPFWidthModifer SizeOp, BPFArithOp Opc, string OpcodeStr,
836               string OpcStr, PatFrag OpNode>
837     : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
838                  (outs GPR32:$dst),
839                  (ins MEMri:$addr, GPR32:$val),
840                  "$dst = atomic_fetch_"#OpcStr#"(("#OpcodeStr#" *)($addr), $val)",
841                  [(set GPR32:$dst, (OpNode ADDRri:$addr, GPR32:$val))]> {
842   bits<4> dst;
843   bits<20> addr;
845   let Inst{51-48} = addr{19-16}; // base reg
846   let Inst{55-52} = dst;
847   let Inst{47-32} = addr{15-0}; // offset
848   let Inst{7-4} = Opc.Value;
849   let Inst{3-0} = BPF_FETCH.Value;
850   let BPFClass = BPF_STX;
853 let Constraints = "$dst = $val" in {
854   let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
855     def XFADDW32 : XFALU32<BPF_W, BPF_ADD, "u32", "add", atomic_load_add_32>;
856     def XFANDW32 : XFALU32<BPF_W, BPF_AND, "u32", "and", atomic_load_and_32>;
857     def XFORW32  : XFALU32<BPF_W, BPF_OR,  "u32", "or",  atomic_load_or_32>;
858     def XFXORW32 : XFALU32<BPF_W, BPF_XOR, "u32", "xor", atomic_load_xor_32>;
859   }
861   def XFADDD : XFALU64<BPF_DW, BPF_ADD, "u64", "add", atomic_load_add_64>;
862   def XFANDD : XFALU64<BPF_DW, BPF_AND, "u64", "and", atomic_load_and_64>;
863   def XFORD  : XFALU64<BPF_DW, BPF_OR,  "u64", "or",  atomic_load_or_64>;
864   def XFXORD : XFALU64<BPF_DW, BPF_XOR, "u64", "xor", atomic_load_xor_64>;
867 // atomic_load_sub can be represented as a neg followed
868 // by an atomic_load_add.
869 def : Pat<(atomic_load_sub_32 ADDRri:$addr, GPR32:$val),
870           (XFADDW32 ADDRri:$addr, (NEG_32 GPR32:$val))>;
871 def : Pat<(atomic_load_sub_64 ADDRri:$addr, GPR:$val),
872           (XFADDD ADDRri:$addr, (NEG_64 GPR:$val))>;
874 // Atomic Exchange
875 class XCHG<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
876     : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
877                  (outs GPR:$dst),
878                  (ins MEMri:$addr, GPR:$val),
879                  "$dst = xchg_"#OpcodeStr#"($addr, $val)",
880                  [(set GPR:$dst, (OpNode ADDRri:$addr,GPR:$val))]> {
881   bits<4> dst;
882   bits<20> addr;
884   let Inst{51-48} = addr{19-16}; // base reg
885   let Inst{55-52} = dst;
886   let Inst{47-32} = addr{15-0}; // offset
887   let Inst{7-4} = BPF_XCHG.Value;
888   let Inst{3-0} = BPF_FETCH.Value;
889   let BPFClass = BPF_STX;
892 class XCHG32<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
893     : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
894                  (outs GPR32:$dst),
895                  (ins MEMri:$addr, GPR32:$val),
896                  "$dst = xchg32_"#OpcodeStr#"($addr, $val)",
897                  [(set GPR32:$dst, (OpNode ADDRri:$addr,GPR32:$val))]> {
898   bits<4> dst;
899   bits<20> addr;
901   let Inst{51-48} = addr{19-16}; // base reg
902   let Inst{55-52} = dst;
903   let Inst{47-32} = addr{15-0}; // offset
904   let Inst{7-4} = BPF_XCHG.Value;
905   let Inst{3-0} = BPF_FETCH.Value;
906   let BPFClass = BPF_STX;
909 let Constraints = "$dst = $val" in {
910   let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
911     def XCHGW32 : XCHG32<BPF_W, "32", atomic_swap_32>;
912   }
914   def XCHGD : XCHG<BPF_DW, "64", atomic_swap_64>;
917 // Compare-And-Exchange
918 class CMPXCHG<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
919     : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
920                  (outs),
921                  (ins MEMri:$addr, GPR:$new),
922                  "r0 = cmpxchg_"#OpcodeStr#"($addr, r0, $new)",
923                  [(set R0, (OpNode ADDRri:$addr, R0, GPR:$new))]> {
924   bits<4> new;
925   bits<20> addr;
927   let Inst{51-48} = addr{19-16}; // base reg
928   let Inst{55-52} = new;
929   let Inst{47-32} = addr{15-0}; // offset
930   let Inst{7-4} = BPF_CMPXCHG.Value;
931   let Inst{3-0} = BPF_FETCH.Value;
932   let BPFClass = BPF_STX;
935 class CMPXCHG32<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
936     : TYPE_LD_ST<BPF_ATOMIC.Value, SizeOp.Value,
937                  (outs),
938                  (ins MEMri:$addr, GPR32:$new),
939                  "w0 = cmpxchg32_"#OpcodeStr#"($addr, w0, $new)",
940                  [(set W0, (OpNode ADDRri:$addr, W0, GPR32:$new))]> {
941   bits<4> new;
942   bits<20> addr;
944   let Inst{51-48} = addr{19-16}; // base reg
945   let Inst{55-52} = new;
946   let Inst{47-32} = addr{15-0}; // offset
947   let Inst{7-4} = BPF_CMPXCHG.Value;
948   let Inst{3-0} = BPF_FETCH.Value;
949   let BPFClass = BPF_STX;
952 let Predicates = [BPFHasALU32], Defs = [W0], Uses = [W0],
953     DecoderNamespace = "BPFALU32" in {
954   def CMPXCHGW32 : CMPXCHG32<BPF_W, "32", atomic_cmp_swap_32>;
957 let Defs = [R0], Uses = [R0] in {
958   def CMPXCHGD : CMPXCHG<BPF_DW, "64", atomic_cmp_swap_64>;
961 // bswap16, bswap32, bswap64
962 class BSWAP<BPFOpClass Class, bits<32> SizeOp, string OpcodeStr, BPFSrcType SrcType, list<dag> Pattern>
963     : TYPE_ALU_JMP<BPF_END.Value, SrcType.Value,
964                    (outs GPR:$dst),
965                    (ins GPR:$src),
966                    "$dst = "#OpcodeStr#" $src",
967                    Pattern> {
968   bits<4> dst;
970   let Inst{51-48} = dst;
971   let Inst{31-0} = SizeOp;
972   let BPFClass = Class;
976 let Constraints = "$dst = $src" in {
977   let Predicates = [BPFHasBswap] in {
978     def BSWAP16 : BSWAP<BPF_ALU64, 16, "bswap16", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
979     def BSWAP32 : BSWAP<BPF_ALU64, 32, "bswap32", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
980     def BSWAP64 : BSWAP<BPF_ALU64, 64, "bswap64", BPF_TO_LE, [(set GPR:$dst, (bswap GPR:$src))]>;
981   }
983   let Predicates = [BPFNoBswap] in {
984     let Predicates = [BPFIsLittleEndian] in {
985         def BE16 : BSWAP<BPF_ALU, 16, "be16", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
986         def BE32 : BSWAP<BPF_ALU, 32, "be32", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
987         def BE64 : BSWAP<BPF_ALU, 64, "be64", BPF_TO_BE, [(set GPR:$dst, (bswap GPR:$src))]>;
988     }
989     let Predicates = [BPFIsBigEndian] in {
990         def LE16 : BSWAP<BPF_ALU, 16, "le16", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
991         def LE32 : BSWAP<BPF_ALU, 32, "le32", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
992         def LE64 : BSWAP<BPF_ALU, 64, "le64", BPF_TO_LE, [(set GPR:$dst, (bswap GPR:$src))]>;
993     }
994   }
997 let Defs = [R0, R1, R2, R3, R4, R5], Uses = [R6], hasSideEffects = 1,
998     hasExtraDefRegAllocReq = 1, hasExtraSrcRegAllocReq = 1, mayLoad = 1 in {
999 class LOAD_ABS<BPFWidthModifer SizeOp, string OpcodeStr, Intrinsic OpNode>
1000     : TYPE_LD_ST<BPF_ABS.Value, SizeOp.Value,
1001                  (outs),
1002                  (ins GPR:$skb, i64imm:$imm),
1003                  "r0 = *("#OpcodeStr#" *)skb[$imm]",
1004                  [(set R0, (OpNode GPR:$skb, i64immSExt32:$imm))]> {
1005   bits<32> imm;
1007   let Inst{31-0} = imm;
1008   let BPFClass = BPF_LD;
1011 class LOAD_IND<BPFWidthModifer SizeOp, string OpcodeStr, Intrinsic OpNode>
1012     : TYPE_LD_ST<BPF_IND.Value, SizeOp.Value,
1013                  (outs),
1014                  (ins GPR:$skb, GPR:$val),
1015                  "r0 = *("#OpcodeStr#" *)skb[$val]",
1016                  [(set R0, (OpNode GPR:$skb, GPR:$val))]> {
1017   bits<4> val;
1019   let Inst{55-52} = val;
1020   let BPFClass = BPF_LD;
1024 def LD_ABS_B : LOAD_ABS<BPF_B, "u8", int_bpf_load_byte>;
1025 def LD_ABS_H : LOAD_ABS<BPF_H, "u16", int_bpf_load_half>;
1026 def LD_ABS_W : LOAD_ABS<BPF_W, "u32", int_bpf_load_word>;
1028 def LD_IND_B : LOAD_IND<BPF_B, "u8", int_bpf_load_byte>;
1029 def LD_IND_H : LOAD_IND<BPF_H, "u16", int_bpf_load_half>;
1030 def LD_IND_W : LOAD_IND<BPF_W, "u32", int_bpf_load_word>;
1032 let isCodeGenOnly = 1 in {
1033   def MOV_32_64 : ALU_RR<BPF_ALU, BPF_MOV, 0,
1034                          (outs GPR:$dst), (ins GPR32:$src),
1035                          "$dst = $src", []>;
1038 let Predicates = [BPFNoMovsx] in {
1039   def : Pat<(i64 (sext GPR32:$src)),
1040             (SRA_ri (SLL_ri (MOV_32_64 GPR32:$src), 32), 32)>;
1043 let Predicates = [BPFHasMovsx] in {
1044   def : Pat<(i64 (sext GPR32:$src)),
1045             (MOVSX_rr_32 (MOV_32_64 GPR32:$src))>;
1048 def : Pat<(i64 (zext GPR32:$src)), (MOV_32_64 GPR32:$src)>;
1050 // For i64 -> i32 truncation, use the 32-bit subregister directly.
1051 def : Pat<(i32 (trunc GPR:$src)),
1052           (i32 (EXTRACT_SUBREG GPR:$src, sub_32))>;
1054 // For i32 -> i64 anyext, we don't care about the high bits.
1055 def : Pat<(i64 (anyext GPR32:$src)),
1056           (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>;
1058 class STORE32<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
1059     : TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value,
1060                  (outs),
1061                  (ins GPR32:$src, MEMri:$addr),
1062                  "*("#OpcodeStr#" *)($addr) = $src",
1063                  Pattern> {
1064   bits<4> src;
1065   bits<20> addr;
1067   let Inst{51-48} = addr{19-16}; // base reg
1068   let Inst{55-52} = src;
1069   let Inst{47-32} = addr{15-0}; // offset
1070   let BPFClass = BPF_STX;
1073 class STOREi32<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
1074     : STORE32<Opc, OpcodeStr, [(OpNode GPR32:$src, ADDRri:$addr)]>;
1076 let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
1077   def STW32 : STOREi32<BPF_W, "u32", store>;
1078   def STH32 : STOREi32<BPF_H, "u16", truncstorei16>;
1079   def STB32 : STOREi32<BPF_B, "u8", truncstorei8>;
1082 class LOAD32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, list<dag> Pattern>
1083     : TYPE_LD_ST<ModOp.Value, SizeOp.Value,
1084                 (outs GPR32:$dst),
1085                 (ins MEMri:$addr),
1086                 "$dst = *("#OpcodeStr#" *)($addr)",
1087                 Pattern> {
1088   bits<4> dst;
1089   bits<20> addr;
1091   let Inst{51-48} = dst;
1092   let Inst{55-52} = addr{19-16};
1093   let Inst{47-32} = addr{15-0};
1094   let BPFClass = BPF_LDX;
1097 class LOADi32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, PatFrag OpNode>
1098     : LOAD32<SizeOp, ModOp, OpcodeStr, [(set i32:$dst, (OpNode ADDRri:$addr))]>;
1100 let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
1101   def LDW32 : LOADi32<BPF_W, BPF_MEM, "u32", load>;
1102   def LDH32 : LOADi32<BPF_H, BPF_MEM, "u16", zextloadi16>;
1103   def LDB32 : LOADi32<BPF_B, BPF_MEM, "u8", zextloadi8>;
1106 let Predicates = [BPFHasALU32] in {
1107   def : Pat<(truncstorei8 GPR:$src, ADDRri:$dst),
1108             (STB32 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>;
1109   def : Pat<(truncstorei16 GPR:$src, ADDRri:$dst),
1110             (STH32 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>;
1111   def : Pat<(truncstorei32 GPR:$src, ADDRri:$dst),
1112             (STW32 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>;
1113   def : Pat<(i32 (extloadi8 ADDRri:$src)), (i32 (LDB32 ADDRri:$src))>;
1114   def : Pat<(i32 (extloadi16 ADDRri:$src)), (i32 (LDH32 ADDRri:$src))>;
1116   let Predicates = [BPFHasLdsx] in {
1117     def : Pat<(i32 (sextloadi8 ADDRri:$src)), (EXTRACT_SUBREG (LDBSX ADDRri:$src), sub_32)>;
1118     def : Pat<(i32 (sextloadi16 ADDRri:$src)), (EXTRACT_SUBREG (LDHSX ADDRri:$src), sub_32)>;
1119   }
1121   def : Pat<(i64 (zextloadi8  ADDRri:$src)),
1122             (SUBREG_TO_REG (i64 0), (LDB32 ADDRri:$src), sub_32)>;
1123   def : Pat<(i64 (zextloadi16 ADDRri:$src)),
1124             (SUBREG_TO_REG (i64 0), (LDH32 ADDRri:$src), sub_32)>;
1125   def : Pat<(i64 (zextloadi32 ADDRri:$src)),
1126             (SUBREG_TO_REG (i64 0), (LDW32 ADDRri:$src), sub_32)>;
1127   def : Pat<(i64 (extloadi8  ADDRri:$src)),
1128             (SUBREG_TO_REG (i64 0), (LDB32 ADDRri:$src), sub_32)>;
1129   def : Pat<(i64 (extloadi16 ADDRri:$src)),
1130             (SUBREG_TO_REG (i64 0), (LDH32 ADDRri:$src), sub_32)>;
1131   def : Pat<(i64 (extloadi32 ADDRri:$src)),
1132             (SUBREG_TO_REG (i64 0), (LDW32 ADDRri:$src), sub_32)>;
1135 let usesCustomInserter = 1, isCodeGenOnly = 1 in {
1136     def MEMCPY : Pseudo<
1137       (outs),
1138       (ins GPR:$dst, GPR:$src, i64imm:$len, i64imm:$align, variable_ops),
1139       "#memcpy dst: $dst, src: $src, len: $len, align: $align",
1140       [(BPFmemcpy GPR:$dst, GPR:$src, imm:$len, imm:$align)]>;