aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/BPF/BPFInstrInfo.td
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/BPF/BPFInstrInfo.td')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/BPF/BPFInstrInfo.td277
1 files changed, 212 insertions, 65 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/BPF/BPFInstrInfo.td b/contrib/llvm-project/llvm/lib/Target/BPF/BPFInstrInfo.td
index 27bd87667b84..7d443a344901 100644
--- a/contrib/llvm-project/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/contrib/llvm-project/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -49,13 +49,29 @@ def BPFWrapper : SDNode<"BPFISD::Wrapper", SDT_BPFWrapper>;
def BPFmemcpy : SDNode<"BPFISD::MEMCPY", SDT_BPFMEMCPY,
[SDNPHasChain, SDNPInGlue, SDNPOutGlue,
SDNPMayStore, SDNPMayLoad]>;
-def BPFIsLittleEndian : Predicate<"CurDAG->getDataLayout().isLittleEndian()">;
-def BPFIsBigEndian : Predicate<"!CurDAG->getDataLayout().isLittleEndian()">;
+def BPFIsLittleEndian : Predicate<"Subtarget->isLittleEndian()">;
+def BPFIsBigEndian : Predicate<"!Subtarget->isLittleEndian()">;
def BPFHasALU32 : Predicate<"Subtarget->getHasAlu32()">;
def BPFNoALU32 : Predicate<"!Subtarget->getHasAlu32()">;
+def BPFHasLdsx : Predicate<"Subtarget->hasLdsx()">;
+def BPFHasMovsx : Predicate<"Subtarget->hasMovsx()">;
+def BPFHasBswap : Predicate<"Subtarget->hasBswap()">;
+def BPFHasSdivSmod : Predicate<"Subtarget->hasSdivSmod()">;
+def BPFNoMovsx : Predicate<"!Subtarget->hasMovsx()">;
+def BPFNoBswap : Predicate<"!Subtarget->hasBswap()">;
+def BPFHasStoreImm : Predicate<"Subtarget->hasStoreImm()">;
+
+class ImmediateAsmOperand<string name> : AsmOperandClass {
+ let Name = name;
+ let RenderMethod = "addImmOperands";
+ let DiagnosticType = !strconcat("Invalid", name);
+}
+
+def SImm16AsmOperand : ImmediateAsmOperand<"SImm16">;
def brtarget : Operand<OtherVT> {
let PrintMethod = "printBrTargetOperand";
+ let ParserMatchClass = ImmediateAsmOperand<"BrTarget">;
}
def calltarget : Operand<i64>;
@@ -63,10 +79,22 @@ def u64imm : Operand<i64> {
let PrintMethod = "printImm64Operand";
}
+def s16imm : Operand<i16> {
+ let ParserMatchClass = SImm16AsmOperand;
+}
+
+def gpr_or_imm : Operand<i64>;
+
def i64immSExt32 : PatLeaf<(i64 imm),
[{return isInt<32>(N->getSExtValue()); }]>;
def i32immSExt32 : PatLeaf<(i32 imm),
[{return isInt<32>(N->getSExtValue()); }]>;
+def i64immZExt32 : PatLeaf<(i64 imm),
+ [{return isUInt<32>(N->getZExtValue()); }]>;
+
+def imm_to_i64 : SDNodeXForm<timm, [{
+ return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
+}]>;
// Addressing modes.
def ADDRri : ComplexPattern<i64, 2, "SelectAddr", [], []>;
@@ -77,7 +105,7 @@ def MEMri : Operand<i64> {
let PrintMethod = "printMemOperand";
let EncoderMethod = "getMemoryOpValue";
let DecoderMethod = "decodeMemoryOpValue";
- let MIOperandInfo = (ops GPR, i16imm);
+ let MIOperandInfo = (ops GPR, s16imm);
}
// Conditional code predicates - used for pattern matching for jump instructions
@@ -121,6 +149,7 @@ def BPF_CC_LTU_32 : PatLeaf<(i32 imm),
[{return (N->getZExtValue() == ISD::SETULT);}]>;
def BPF_CC_LEU_32 : PatLeaf<(i32 imm),
[{return (N->getZExtValue() == ISD::SETULE);}]>;
+def NoCond : PatLeaf<(vt)> {}
// For arithmetic and jump instructions the 8-bit 'code'
// field is divided into three parts:
@@ -237,21 +266,23 @@ defm JULT : J<BPF_JLT, "<", BPF_CC_LTU, BPF_CC_LTU_32>;
defm JULE : J<BPF_JLE, "<=", BPF_CC_LEU, BPF_CC_LEU_32>;
defm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT, BPF_CC_LT_32>;
defm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE, BPF_CC_LE_32>;
+defm JSET : J<BPF_JSET, "&", NoCond, NoCond>;
}
// ALU instructions
-class ALU_RI<BPFOpClass Class, BPFArithOp Opc,
+class ALU_RI<BPFOpClass Class, BPFArithOp Opc, int off,
dag outs, dag ins, string asmstr, list<dag> pattern>
: TYPE_ALU_JMP<Opc.Value, BPF_K.Value, outs, ins, asmstr, pattern> {
bits<4> dst;
bits<32> imm;
let Inst{51-48} = dst;
+ let Inst{47-32} = off;
let Inst{31-0} = imm;
let BPFClass = Class;
}
-class ALU_RR<BPFOpClass Class, BPFArithOp Opc,
+class ALU_RR<BPFOpClass Class, BPFArithOp Opc, int off,
dag outs, dag ins, string asmstr, list<dag> pattern>
: TYPE_ALU_JMP<Opc.Value, BPF_X.Value, outs, ins, asmstr, pattern> {
bits<4> dst;
@@ -259,26 +290,27 @@ class ALU_RR<BPFOpClass Class, BPFArithOp Opc,
let Inst{55-52} = src;
let Inst{51-48} = dst;
+ let Inst{47-32} = off;
let BPFClass = Class;
}
-multiclass ALU<BPFArithOp Opc, string OpcodeStr, SDNode OpNode> {
- def _rr : ALU_RR<BPF_ALU64, Opc,
+multiclass ALU<BPFArithOp Opc, int off, string OpcodeStr, SDNode OpNode> {
+ def _rr : ALU_RR<BPF_ALU64, Opc, off,
(outs GPR:$dst),
(ins GPR:$src2, GPR:$src),
"$dst "#OpcodeStr#" $src",
[(set GPR:$dst, (OpNode i64:$src2, i64:$src))]>;
- def _ri : ALU_RI<BPF_ALU64, Opc,
+ def _ri : ALU_RI<BPF_ALU64, Opc, off,
(outs GPR:$dst),
(ins GPR:$src2, i64imm:$imm),
"$dst "#OpcodeStr#" $imm",
[(set GPR:$dst, (OpNode GPR:$src2, i64immSExt32:$imm))]>;
- def _rr_32 : ALU_RR<BPF_ALU, Opc,
+ def _rr_32 : ALU_RR<BPF_ALU, Opc, off,
(outs GPR32:$dst),
(ins GPR32:$src2, GPR32:$src),
"$dst "#OpcodeStr#" $src",
[(set GPR32:$dst, (OpNode i32:$src2, i32:$src))]>;
- def _ri_32 : ALU_RI<BPF_ALU, Opc,
+ def _ri_32 : ALU_RI<BPF_ALU, Opc, off,
(outs GPR32:$dst),
(ins GPR32:$src2, i32imm:$imm),
"$dst "#OpcodeStr#" $imm",
@@ -287,18 +319,23 @@ multiclass ALU<BPFArithOp Opc, string OpcodeStr, SDNode OpNode> {
let Constraints = "$dst = $src2" in {
let isAsCheapAsAMove = 1 in {
- defm ADD : ALU<BPF_ADD, "+=", add>;
- defm SUB : ALU<BPF_SUB, "-=", sub>;
- defm OR : ALU<BPF_OR, "|=", or>;
- defm AND : ALU<BPF_AND, "&=", and>;
- defm SLL : ALU<BPF_LSH, "<<=", shl>;
- defm SRL : ALU<BPF_RSH, ">>=", srl>;
- defm XOR : ALU<BPF_XOR, "^=", xor>;
- defm SRA : ALU<BPF_ARSH, "s>>=", sra>;
-}
- defm MUL : ALU<BPF_MUL, "*=", mul>;
- defm DIV : ALU<BPF_DIV, "/=", udiv>;
- defm MOD : ALU<BPF_MOD, "%=", urem>;
+ defm ADD : ALU<BPF_ADD, 0, "+=", add>;
+ defm SUB : ALU<BPF_SUB, 0, "-=", sub>;
+ defm OR : ALU<BPF_OR, 0, "|=", or>;
+ defm AND : ALU<BPF_AND, 0, "&=", and>;
+ defm SLL : ALU<BPF_LSH, 0, "<<=", shl>;
+ defm SRL : ALU<BPF_RSH, 0, ">>=", srl>;
+ defm XOR : ALU<BPF_XOR, 0, "^=", xor>;
+ defm SRA : ALU<BPF_ARSH, 0, "s>>=", sra>;
+}
+ defm MUL : ALU<BPF_MUL, 0, "*=", mul>;
+ defm DIV : ALU<BPF_DIV, 0, "/=", udiv>;
+ defm MOD : ALU<BPF_MOD, 0, "%=", urem>;
+
+ let Predicates = [BPFHasSdivSmod] in {
+ defm SDIV : ALU<BPF_DIV, 1, "s/=", sdiv>;
+ defm SMOD : ALU<BPF_MOD, 1, "s%=", srem>;
+ }
}
class NEG_RR<BPFOpClass Class, BPFArithOp Opc,
@@ -338,26 +375,49 @@ class LD_IMM64<bits<4> Pseudo, string OpcodeStr>
let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
def LD_imm64 : LD_IMM64<0, "=">;
-def MOV_rr : ALU_RR<BPF_ALU64, BPF_MOV,
+def MOV_rr : ALU_RR<BPF_ALU64, BPF_MOV, 0,
(outs GPR:$dst),
(ins GPR:$src),
"$dst = $src",
[]>;
-def MOV_ri : ALU_RI<BPF_ALU64, BPF_MOV,
+def MOV_ri : ALU_RI<BPF_ALU64, BPF_MOV, 0,
(outs GPR:$dst),
(ins i64imm:$imm),
"$dst = $imm",
[(set GPR:$dst, (i64 i64immSExt32:$imm))]>;
-def MOV_rr_32 : ALU_RR<BPF_ALU, BPF_MOV,
+def MOV_rr_32 : ALU_RR<BPF_ALU, BPF_MOV, 0,
(outs GPR32:$dst),
(ins GPR32:$src),
"$dst = $src",
[]>;
-def MOV_ri_32 : ALU_RI<BPF_ALU, BPF_MOV,
+def MOV_ri_32 : ALU_RI<BPF_ALU, BPF_MOV, 0,
(outs GPR32:$dst),
(ins i32imm:$imm),
"$dst = $imm",
[(set GPR32:$dst, (i32 i32immSExt32:$imm))]>;
+
+let Predicates = [BPFHasMovsx] in {
+ def MOVSX_rr_8 : ALU_RR<BPF_ALU64, BPF_MOV, 8,
+ (outs GPR:$dst), (ins GPR:$src),
+ "$dst = (s8)$src",
+ [(set GPR:$dst, (sext_inreg GPR:$src, i8))]>;
+ def MOVSX_rr_16 : ALU_RR<BPF_ALU64, BPF_MOV, 16,
+ (outs GPR:$dst), (ins GPR:$src),
+ "$dst = (s16)$src",
+ [(set GPR:$dst, (sext_inreg GPR:$src, i16))]>;
+ def MOVSX_rr_32 : ALU_RR<BPF_ALU64, BPF_MOV, 32,
+ (outs GPR:$dst), (ins GPR:$src),
+ "$dst = (s32)$src",
+ [(set GPR:$dst, (sext_inreg GPR:$src, i32))]>;
+ def MOVSX_rr_32_8 : ALU_RR<BPF_ALU, BPF_MOV, 8,
+ (outs GPR32:$dst), (ins GPR32:$src),
+ "$dst = (s8)$src",
+ [(set GPR32:$dst, (sext_inreg GPR32:$src, i8))]>;
+ def MOVSX_rr_32_16 : ALU_RR<BPF_ALU, BPF_MOV, 16,
+ (outs GPR32:$dst), (ins GPR32:$src),
+ "$dst = (s16)$src",
+ [(set GPR32:$dst, (sext_inreg GPR32:$src, i16))]>;
+}
}
def FI_ri
@@ -411,7 +471,7 @@ class STORE<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
}
class STOREi64<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
- : STORE<Opc, OpcodeStr, [(OpNode i64:$src, ADDRri:$addr)]>;
+ : STORE<Opc, OpcodeStr, [(OpNode GPR:$src, ADDRri:$addr)]>;
let Predicates = [BPFNoALU32] in {
def STW : STOREi64<BPF_W, "u32", truncstorei32>;
@@ -420,9 +480,53 @@ let Predicates = [BPFNoALU32] in {
}
def STD : STOREi64<BPF_DW, "u64", store>;
-// LOAD instructions
-class LOAD<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
+class STORE_imm<BPFWidthModifer SizeOp,
+ string OpcodeStr, dag Pattern>
: TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value,
+ (outs),
+ (ins i64imm:$imm, MEMri:$addr),
+ "*("#OpcodeStr#" *)($addr) = $imm",
+ [Pattern]> {
+ bits<20> addr;
+ bits<32> imm;
+
+ let Inst{51-48} = addr{19-16}; // base reg
+ let Inst{47-32} = addr{15-0}; // offset
+ let Inst{31-0} = imm;
+ let BPFClass = BPF_ST;
+}
+
+let Predicates = [BPFHasStoreImm] in {
+ // Opcode (BPF_ST | BPF_MEM | BPF_DW) implies sign extension for
+ // value stored to memory:
+ // - it is fine to generate such write when immediate is -1
+ // - it is incorrect to generate such write when immediate is
+ // +0xffff_ffff.
+ //
+ // In the latter case two instructions would be generated instead of
+ // one BPF_ST:
+ // rA = 0xffffffff ll ; LD_imm64
+ // *(u64 *)(rB + 0) = rA ; STX
+ //
+ // For BPF_{B,H,W} the size of value stored matches size of the immediate.
+ def STD_imm : STORE_imm<BPF_DW, "u64", (store (i64 i64immSExt32:$imm), ADDRri:$addr)>;
+ def STW_imm : STORE_imm<BPF_W, "u32", (truncstorei32 (i64 i64immZExt32:$imm), ADDRri:$addr)>;
+ def STH_imm : STORE_imm<BPF_H, "u16", (truncstorei16 (i64 i64immZExt32:$imm), ADDRri:$addr)>;
+ def STB_imm : STORE_imm<BPF_B, "u8", (truncstorei8 (i64 i64immZExt32:$imm), ADDRri:$addr)>;
+}
+
+let Predicates = [BPFHasALU32, BPFHasStoreImm] in {
+ def : Pat<(store (i32 imm:$src), ADDRri:$dst),
+ (STW_imm (imm_to_i64 $src), ADDRri:$dst)>;
+ def : Pat<(truncstorei16 (i32 imm:$src), ADDRri:$dst),
+ (STH_imm (imm_to_i64 imm:$src), ADDRri:$dst)>;
+ def : Pat<(truncstorei8 (i32 imm:$src), ADDRri:$dst),
+ (STB_imm (imm_to_i64 imm:$src), ADDRri:$dst)>;
+}
+
+// LOAD instructions
+class LOAD<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, list<dag> Pattern>
+ : TYPE_LD_ST<ModOp.Value, SizeOp.Value,
(outs GPR:$dst),
(ins MEMri:$addr),
"$dst = *("#OpcodeStr#" *)($addr)",
@@ -436,22 +540,25 @@ class LOAD<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
let BPFClass = BPF_LDX;
}
-class LOADi64<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
- : LOAD<SizeOp, OpcodeStr, [(set i64:$dst, (OpNode ADDRri:$addr))]>;
+class LOADi64<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, PatFrag OpNode>
+ : LOAD<SizeOp, ModOp, OpcodeStr, [(set i64:$dst, (OpNode ADDRri:$addr))]>;
let isCodeGenOnly = 1 in {
- def CORE_MEM : TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value,
- (outs GPR:$dst),
- (ins u64imm:$opcode, GPR:$src, u64imm:$offset),
- "$dst = core_mem($opcode, $src, $offset)",
- []>;
- def CORE_ALU32_MEM : TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value,
- (outs GPR32:$dst),
- (ins u64imm:$opcode, GPR:$src, u64imm:$offset),
- "$dst = core_alu32_mem($opcode, $src, $offset)",
- []>;
+ class CORE_LD<RegisterClass RegClass, string Sz>
+ : TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value,
+ (outs RegClass:$dst),
+ (ins u64imm:$opcode, GPR:$src, u64imm:$offset),
+ "$dst = core_ld"#Sz#"($opcode, $src, $offset)",
+ []>;
+ def CORE_LD64 : CORE_LD<GPR, "64">;
+ def CORE_LD32 : CORE_LD<GPR32, "32">;
+ def CORE_ST : TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value,
+ (outs),
+ (ins gpr_or_imm:$src, u64imm:$opcode, GPR:$ptr, u64imm:$offset),
+ "core_st($src, $opcode, $ptr, $offset)",
+ []>;
let Constraints = "$dst = $src" in {
- def CORE_SHIFT : ALU_RR<BPF_ALU64, BPF_LSH,
+ def CORE_SHIFT : ALU_RR<BPF_ALU64, BPF_LSH, 0,
(outs GPR:$dst),
(ins u64imm:$opcode, GPR:$src, u64imm:$offset),
"$dst = core_shift($opcode, $src, $offset)",
@@ -460,12 +567,18 @@ let isCodeGenOnly = 1 in {
}
let Predicates = [BPFNoALU32] in {
- def LDW : LOADi64<BPF_W, "u32", zextloadi32>;
- def LDH : LOADi64<BPF_H, "u16", zextloadi16>;
- def LDB : LOADi64<BPF_B, "u8", zextloadi8>;
+ def LDW : LOADi64<BPF_W, BPF_MEM, "u32", zextloadi32>;
+ def LDH : LOADi64<BPF_H, BPF_MEM, "u16", zextloadi16>;
+ def LDB : LOADi64<BPF_B, BPF_MEM, "u8", zextloadi8>;
}
-def LDD : LOADi64<BPF_DW, "u64", load>;
+let Predicates = [BPFHasLdsx] in {
+ def LDWSX : LOADi64<BPF_W, BPF_MEMSX, "s32", sextloadi32>;
+ def LDHSX : LOADi64<BPF_H, BPF_MEMSX, "s16", sextloadi16>;
+ def LDBSX : LOADi64<BPF_B, BPF_MEMSX, "s8", sextloadi8>;
+}
+
+def LDD : LOADi64<BPF_DW, BPF_MEM, "u64", load>;
class BRANCH<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
: TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
@@ -479,6 +592,18 @@ class BRANCH<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
let BPFClass = BPF_JMP;
}
+class BRANCH_LONG<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
+ : TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
+ (outs),
+ (ins brtarget:$BrDst),
+ !strconcat(OpcodeStr, " $BrDst"),
+ Pattern> {
+ bits<32> BrDst;
+
+ let Inst{31-0} = BrDst;
+ let BPFClass = BPF_JMP32;
+}
+
class CALL<string OpcodeStr>
: TYPE_ALU_JMP<BPF_CALL.Value, BPF_K.Value,
(outs),
@@ -506,6 +631,7 @@ class CALLX<string OpcodeStr>
// Jump always
let isBranch = 1, isTerminator = 1, hasDelaySlot=0, isBarrier = 1 in {
def JMP : BRANCH<BPF_JA, "goto", [(br bb:$BrDst)]>;
+ def JMPL : BRANCH_LONG<BPF_JA, "gotol", []>;
}
// Jump and link
@@ -835,7 +961,7 @@ let Defs = [R0], Uses = [R0] in {
}
// bswap16, bswap32, bswap64
-class BSWAP<bits<32> SizeOp, string OpcodeStr, BPFSrcType SrcType, list<dag> Pattern>
+class BSWAP<BPFOpClass Class, bits<32> SizeOp, string OpcodeStr, BPFSrcType SrcType, list<dag> Pattern>
: TYPE_ALU_JMP<BPF_END.Value, SrcType.Value,
(outs GPR:$dst),
(ins GPR:$src),
@@ -845,21 +971,29 @@ class BSWAP<bits<32> SizeOp, string OpcodeStr, BPFSrcType SrcType, list<dag> Pat
let Inst{51-48} = dst;
let Inst{31-0} = SizeOp;
- let BPFClass = BPF_ALU;
+ let BPFClass = Class;
}
let Constraints = "$dst = $src" in {
+ let Predicates = [BPFHasBswap] in {
+ def BSWAP16 : BSWAP<BPF_ALU64, 16, "bswap16", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
+ def BSWAP32 : BSWAP<BPF_ALU64, 32, "bswap32", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
+ def BSWAP64 : BSWAP<BPF_ALU64, 64, "bswap64", BPF_TO_LE, [(set GPR:$dst, (bswap GPR:$src))]>;
+ }
+
+ let Predicates = [BPFNoBswap] in {
let Predicates = [BPFIsLittleEndian] in {
- def BE16 : BSWAP<16, "be16", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
- def BE32 : BSWAP<32, "be32", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
- def BE64 : BSWAP<64, "be64", BPF_TO_BE, [(set GPR:$dst, (bswap GPR:$src))]>;
+ def BE16 : BSWAP<BPF_ALU, 16, "be16", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
+ def BE32 : BSWAP<BPF_ALU, 32, "be32", BPF_TO_BE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
+ def BE64 : BSWAP<BPF_ALU, 64, "be64", BPF_TO_BE, [(set GPR:$dst, (bswap GPR:$src))]>;
}
let Predicates = [BPFIsBigEndian] in {
- def LE16 : BSWAP<16, "le16", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
- def LE32 : BSWAP<32, "le32", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
- def LE64 : BSWAP<64, "le64", BPF_TO_LE, [(set GPR:$dst, (bswap GPR:$src))]>;
+ def LE16 : BSWAP<BPF_ALU, 16, "le16", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
+ def LE32 : BSWAP<BPF_ALU, 32, "le32", BPF_TO_LE, [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
+ def LE64 : BSWAP<BPF_ALU, 64, "le64", BPF_TO_LE, [(set GPR:$dst, (bswap GPR:$src))]>;
}
+ }
}
let Defs = [R0, R1, R2, R3, R4, R5], Uses = [R6], hasSideEffects = 1,
@@ -898,13 +1032,20 @@ def LD_IND_H : LOAD_IND<BPF_H, "u16", int_bpf_load_half>;
def LD_IND_W : LOAD_IND<BPF_W, "u32", int_bpf_load_word>;
let isCodeGenOnly = 1 in {
- def MOV_32_64 : ALU_RR<BPF_ALU, BPF_MOV,
+ def MOV_32_64 : ALU_RR<BPF_ALU, BPF_MOV, 0,
(outs GPR:$dst), (ins GPR32:$src),
"$dst = $src", []>;
}
-def : Pat<(i64 (sext GPR32:$src)),
- (SRA_ri (SLL_ri (MOV_32_64 GPR32:$src), 32), 32)>;
+let Predicates = [BPFNoMovsx] in {
+ def : Pat<(i64 (sext GPR32:$src)),
+ (SRA_ri (SLL_ri (MOV_32_64 GPR32:$src), 32), 32)>;
+}
+
+let Predicates = [BPFHasMovsx] in {
+ def : Pat<(i64 (sext GPR32:$src)),
+ (MOVSX_rr_32 (MOV_32_64 GPR32:$src))>;
+}
def : Pat<(i64 (zext GPR32:$src)), (MOV_32_64 GPR32:$src)>;
@@ -932,7 +1073,7 @@ class STORE32<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
}
class STOREi32<BPFWidthModifer Opc, string OpcodeStr, PatFrag OpNode>
- : STORE32<Opc, OpcodeStr, [(OpNode i32:$src, ADDRri:$addr)]>;
+ : STORE32<Opc, OpcodeStr, [(OpNode GPR32:$src, ADDRri:$addr)]>;
let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
def STW32 : STOREi32<BPF_W, "u32", store>;
@@ -940,8 +1081,8 @@ let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
def STB32 : STOREi32<BPF_B, "u8", truncstorei8>;
}
-class LOAD32<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
- : TYPE_LD_ST<BPF_MEM.Value, SizeOp.Value,
+class LOAD32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, list<dag> Pattern>
+ : TYPE_LD_ST<ModOp.Value, SizeOp.Value,
(outs GPR32:$dst),
(ins MEMri:$addr),
"$dst = *("#OpcodeStr#" *)($addr)",
@@ -955,13 +1096,13 @@ class LOAD32<BPFWidthModifer SizeOp, string OpcodeStr, list<dag> Pattern>
let BPFClass = BPF_LDX;
}
-class LOADi32<BPFWidthModifer SizeOp, string OpcodeStr, PatFrag OpNode>
- : LOAD32<SizeOp, OpcodeStr, [(set i32:$dst, (OpNode ADDRri:$addr))]>;
+class LOADi32<BPFWidthModifer SizeOp, BPFModeModifer ModOp, string OpcodeStr, PatFrag OpNode>
+ : LOAD32<SizeOp, ModOp, OpcodeStr, [(set i32:$dst, (OpNode ADDRri:$addr))]>;
let Predicates = [BPFHasALU32], DecoderNamespace = "BPFALU32" in {
- def LDW32 : LOADi32<BPF_W, "u32", load>;
- def LDH32 : LOADi32<BPF_H, "u16", zextloadi16>;
- def LDB32 : LOADi32<BPF_B, "u8", zextloadi8>;
+ def LDW32 : LOADi32<BPF_W, BPF_MEM, "u32", load>;
+ def LDH32 : LOADi32<BPF_H, BPF_MEM, "u16", zextloadi16>;
+ def LDB32 : LOADi32<BPF_B, BPF_MEM, "u8", zextloadi8>;
}
let Predicates = [BPFHasALU32] in {
@@ -973,6 +1114,12 @@ let Predicates = [BPFHasALU32] in {
(STW32 (EXTRACT_SUBREG GPR:$src, sub_32), ADDRri:$dst)>;
def : Pat<(i32 (extloadi8 ADDRri:$src)), (i32 (LDB32 ADDRri:$src))>;
def : Pat<(i32 (extloadi16 ADDRri:$src)), (i32 (LDH32 ADDRri:$src))>;
+
+ let Predicates = [BPFHasLdsx] in {
+ def : Pat<(i32 (sextloadi8 ADDRri:$src)), (EXTRACT_SUBREG (LDBSX ADDRri:$src), sub_32)>;
+ def : Pat<(i32 (sextloadi16 ADDRri:$src)), (EXTRACT_SUBREG (LDHSX ADDRri:$src), sub_32)>;
+ }
+
def : Pat<(i64 (zextloadi8 ADDRri:$src)),
(SUBREG_TO_REG (i64 0), (LDB32 ADDRri:$src), sub_32)>;
def : Pat<(i64 (zextloadi16 ADDRri:$src)),