AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/10/05 19:18 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "KMSANReasoning": "",
  "NeedsKMSAN": false,
  "Reasoning": "The patch adds an eBPF JIT compiler for the m68k architecture under arch/m68k/ along with Documentation and MAINTAINERS entries. Because the target architecture is amd64, all modified code is exclusive to another architecture and unreachable.",
  "WorthFuzzing": false
}

1/1 2026/10/05 19:18 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 54e984b2d1eb23947dd44e227b5ba78369381572\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Mon Oct 5 19:18:54 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/Documentation/features/core/eBPF-JIT/arch-support.txt b/Documentation/features/core/eBPF-JIT/arch-support.txt\nindex 83f77f55fc87b..dacb50aef0550 100644\n--- a/Documentation/features/core/eBPF-JIT/arch-support.txt\n+++ b/Documentation/features/core/eBPF-JIT/arch-support.txt\n@@ -13,7 +13,7 @@\n     |        csky: | TODO |\n     |     hexagon: | TODO |\n     |   loongarch: |  ok  |\n-    |        m68k: | TODO |\n+    |        m68k: |  ok  |\n     |  microblaze: | TODO |\n     |        mips: |  ok  |\n     |       nios2: | TODO |\ndiff --git a/MAINTAINERS b/MAINTAINERS\nindex ac037cbd4e21b..a8ce1906a5da8 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -4848,6 +4848,12 @@ L:\tbpf@vger.kernel.org\n S:\tMaintained\n F:\tarch/loongarch/net/\n \n+BPF JIT for M68K\n+M:\tKuan-Wei Chiu \u003cvisitorckw@gmail.com\u003e\n+L:\tbpf@vger.kernel.org\n+S:\tMaintained\n+F:\tarch/m68k/net/\n+\n BPF JIT for MIPS (32-BIT AND 64-BIT)\n M:\tJohan Almbladh \u003cjohan.almbladh@anyfinetworks.com\u003e\n M:\tPaul Burton \u003cpaulburton@kernel.org\u003e\ndiff --git a/arch/m68k/Kbuild b/arch/m68k/Kbuild\nindex 7762af9f6defe..058ad41a728c5 100644\n--- a/arch/m68k/Kbuild\n+++ b/arch/m68k/Kbuild\n@@ -1,5 +1,5 @@\n # SPDX-License-Identifier: GPL-2.0-only\n-obj-y\t\t\t\t+= kernel/ mm/\n+obj-y\t\t\t\t+= kernel/ mm/ net/\n obj-$(CONFIG_Q40)\t\t+= q40/\n obj-$(CONFIG_AMIGA)\t\t+= amiga/\n obj-$(CONFIG_ATARI)\t\t+= atari/\ndiff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig\nindex 11835eb59d94d..f334fca80f3f2 100644\n--- a/arch/m68k/Kconfig\n+++ b/arch/m68k/Kconfig\n@@ -31,6 +31,7 @@ config M68K\n \tselect HAVE_ARCH_SECCOMP_FILTER\n \tselect HAVE_ASM_MODVERSIONS\n \tselect HAVE_DEBUG_BUGVERBOSE\n+\tselect HAVE_EBPF_JIT if MMU\n \tselect HAVE_EFFICIENT_UNALIGNED_ACCESS if !CPU_HAS_NO_UNALIGNED\n \tselect HAVE_LD_DEAD_CODE_DATA_ELIMINATION\n \tselect HAVE_MOD_ARCH_SPECIFIC\ndiff --git a/arch/m68k/net/Makefile b/arch/m68k/net/Makefile\nnew file mode 100644\nindex 0000000000000..ec5b147633167\n--- /dev/null\n+++ b/arch/m68k/net/Makefile\n@@ -0,0 +1,2 @@\n+# SPDX-License-Identifier: GPL-2.0-only\n+obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o\ndiff --git a/arch/m68k/net/bpf_jit_comp.c b/arch/m68k/net/bpf_jit_comp.c\nnew file mode 100644\nindex 0000000000000..6c40d358acd42\n--- /dev/null\n+++ b/arch/m68k/net/bpf_jit_comp.c\n@@ -0,0 +1,1840 @@\n+// SPDX-License-Identifier: GPL-2.0-only\n+/*\n+ * BPF JIT compiler for m68k\n+ *\n+ * Copyright (C) 2026 Kuan-Wei Chiu \u003cvisitorckw@gmail.com\u003e\n+ */\n+\n+#include \u003clinux/bpf.h\u003e\n+#include \u003clinux/filter.h\u003e\n+#include \u003clinux/irqflags.h\u003e\n+#include \u003clinux/slab.h\u003e\n+#include \u003casm/cacheflush.h\u003e\n+#include \u003clinux/math64.h\u003e\n+#include \u003clinux/limits.h\u003e\n+\n+#define STACK_OFFSET(k) (-4 - (4 * (k)))\n+\n+enum {\n+\tBPF_R1_HI, BPF_R1_LO,\n+\tBPF_R2_HI, BPF_R2_LO,\n+\tBPF_R3_HI, BPF_R3_LO,\n+\tBPF_R4_HI, BPF_R4_LO,\n+\tBPF_R5_HI, BPF_R5_LO,\n+\tBPF_R6_HI, BPF_R6_LO,\n+\tBPF_R7_HI, BPF_R7_LO,\n+\tBPF_R8_HI, BPF_R8_LO,\n+\tBPF_R9_HI, BPF_R9_LO,\n+\tBPF_R10_HI, BPF_R10_LO,\n+\tBPF_AX_HI, BPF_AX_LO,\n+\tBPF_TC_HI, BPF_TC_LO,\n+\tBPF_JIT_SCRATCH_REGS,\n+};\n+\n+#define SCRATCH_SIZE (BPF_JIT_SCRATCH_REGS * 4)\n+\n+#define TMP_REG_1 14\n+#define TMP_REG_2 15\n+\n+#define M68K_D0 0\n+#define M68K_D1 1\n+#define M68K_D2 2\n+#define M68K_D3 3\n+#define M68K_D4 4\n+#define M68K_D5 5\n+\n+static const s8 bpf2m68k[16][2] = {\n+\t[BPF_REG_0]  = {M68K_D1, M68K_D0},\n+\t[BPF_REG_1]  = {STACK_OFFSET(BPF_R1_HI),  STACK_OFFSET(BPF_R1_LO)},\n+\t[BPF_REG_2]  = {STACK_OFFSET(BPF_R2_HI),  STACK_OFFSET(BPF_R2_LO)},\n+\t[BPF_REG_3]  = {STACK_OFFSET(BPF_R3_HI),  STACK_OFFSET(BPF_R3_LO)},\n+\t[BPF_REG_4]  = {STACK_OFFSET(BPF_R4_HI),  STACK_OFFSET(BPF_R4_LO)},\n+\t[BPF_REG_5]  = {STACK_OFFSET(BPF_R5_HI),  STACK_OFFSET(BPF_R5_LO)},\n+\t[BPF_REG_6]  = {STACK_OFFSET(BPF_R6_HI),  STACK_OFFSET(BPF_R6_LO)},\n+\t[BPF_REG_7]  = {STACK_OFFSET(BPF_R7_HI),  STACK_OFFSET(BPF_R7_LO)},\n+\t[BPF_REG_8]  = {STACK_OFFSET(BPF_R8_HI),  STACK_OFFSET(BPF_R8_LO)},\n+\t[BPF_REG_9]  = {STACK_OFFSET(BPF_R9_HI),  STACK_OFFSET(BPF_R9_LO)},\n+\t[BPF_REG_10] = {STACK_OFFSET(BPF_R10_HI), STACK_OFFSET(BPF_R10_LO)},\n+\t[BPF_REG_AX] = {STACK_OFFSET(BPF_AX_HI),  STACK_OFFSET(BPF_AX_LO)},\n+\t[TMP_REG_1]  = {M68K_D3, M68K_D2},\n+\t[TMP_REG_2]  = {M68K_D5, M68K_D4},\n+};\n+\n+struct jit_ctx {\n+\tconst struct bpf_prog *prog;\n+\tu16 *target;\n+\tunsigned int idx;\n+\tint *offsets;\n+};\n+\n+static noinline u32 jit_mul32(u32 a, u32 b)\n+{\n+\treturn a * b;\n+}\n+\n+static noinline u32 jit_div32(u32 a, u32 b)\n+{\n+\treturn b ? a / b : 0;\n+}\n+\n+static noinline u32 jit_mod32(u32 a, u32 b)\n+{\n+\treturn b ? a % b : a;\n+}\n+\n+static noinline s32 jit_sdiv32(s32 a, s32 b)\n+{\n+\tif (b == 0)\n+\t\treturn 0;\n+\tif (a == S32_MIN \u0026\u0026 b == -1)\n+\t\treturn S32_MIN;\n+\treturn a / b;\n+}\n+\n+static noinline s32 jit_smod32(s32 a, s32 b)\n+{\n+\tif (b == 0)\n+\t\treturn a;\n+\tif (a == S32_MIN \u0026\u0026 b == -1)\n+\t\treturn 0;\n+\treturn a % b;\n+}\n+\n+static noinline u64 jit_mul64(u64 a, u64 b)\n+{\n+\treturn a * b;\n+}\n+\n+static noinline u64 jit_div64(u64 a, u64 b)\n+{\n+\treturn b ? div64_u64(a, b) : 0;\n+}\n+\n+static noinline s64 jit_sdiv64(s64 a, s64 b)\n+{\n+\tif (b == 0)\n+\t\treturn 0;\n+\tif (a == S64_MIN \u0026\u0026 b == -1)\n+\t\treturn S64_MIN;\n+\treturn div64_s64(a, b);\n+}\n+\n+static noinline u64 jit_mod64(u64 a, u64 b)\n+{\n+\tu64 rem;\n+\n+\tif (b == 0)\n+\t\treturn a;\n+\tdiv64_u64_rem(a, b, \u0026rem);\n+\treturn rem;\n+}\n+\n+static noinline s64 jit_smod64(s64 a, s64 b)\n+{\n+\tif (b == 0)\n+\t\treturn a;\n+\tif (a == S64_MIN \u0026\u0026 b == -1)\n+\t\treturn 0;\n+\treturn a - div64_s64(a, b) * b;\n+}\n+\n+static u32 jit_atomic32(u32 *ptr, u32 val, u32 op, u32 cmp)\n+{\n+\tunsigned long flags;\n+\tu32 old;\n+\n+\tlocal_irq_save(flags);\n+\told = *ptr;\n+\tswitch (op) {\n+\tcase BPF_ADD:\n+\tcase BPF_ADD | BPF_FETCH:\n+\t\t*ptr += val;\n+\t\tbreak;\n+\tcase BPF_AND:\n+\tcase BPF_AND | BPF_FETCH:\n+\t\t*ptr \u0026= val;\n+\t\tbreak;\n+\tcase BPF_OR:\n+\tcase BPF_OR | BPF_FETCH:\n+\t\t*ptr |= val;\n+\t\tbreak;\n+\tcase BPF_XOR:\n+\tcase BPF_XOR | BPF_FETCH:\n+\t\t*ptr ^= val;\n+\t\tbreak;\n+\tcase BPF_XCHG:\n+\t\t*ptr = val;\n+\t\tbreak;\n+\tcase BPF_CMPXCHG:\n+\t\tif (old == cmp)\n+\t\t\t*ptr = val;\n+\t\tbreak;\n+\t}\n+\tlocal_irq_restore(flags);\n+\n+\treturn old;\n+}\n+\n+static u64 jit_atomic64(u32 *ptr, u32 val_hi, u32 val_lo, u32 op, u32 cmp_hi, u32 cmp_lo)\n+{\n+\tunsigned long flags;\n+\tu64 old, val, cmp;\n+\tu64 *ptr64 = (u64 *)ptr;\n+\n+\tval = ((u64)val_hi \u003c\u003c 32) | val_lo;\n+\tcmp = ((u64)cmp_hi \u003c\u003c 32) | cmp_lo;\n+\n+\tlocal_irq_save(flags);\n+\told = *ptr64;\n+\tswitch (op) {\n+\tcase BPF_ADD:\n+\tcase BPF_ADD | BPF_FETCH:\n+\t\t*ptr64 += val;\n+\t\tbreak;\n+\tcase BPF_AND:\n+\tcase BPF_AND | BPF_FETCH:\n+\t\t*ptr64 \u0026= val;\n+\t\tbreak;\n+\tcase BPF_OR:\n+\tcase BPF_OR | BPF_FETCH:\n+\t\t*ptr64 |= val;\n+\t\tbreak;\n+\tcase BPF_XOR:\n+\tcase BPF_XOR | BPF_FETCH:\n+\t\t*ptr64 ^= val;\n+\t\tbreak;\n+\tcase BPF_XCHG:\n+\t\t*ptr64 = val;\n+\t\tbreak;\n+\tcase BPF_CMPXCHG:\n+\t\tif (old == cmp)\n+\t\t\t*ptr64 = val;\n+\t\tbreak;\n+\t}\n+\tlocal_irq_restore(flags);\n+\n+\treturn old;\n+}\n+\n+static inline void emit_16(struct jit_ctx *ctx, u16 inst)\n+{\n+\tif (ctx-\u003etarget)\n+\t\tctx-\u003etarget[ctx-\u003eidx] = inst;\n+\tctx-\u003eidx++;\n+}\n+\n+static inline void emit_32(struct jit_ctx *ctx, u32 val)\n+{\n+\temit_16(ctx, val \u003e\u003e 16);\n+\temit_16(ctx, val \u0026 0xffff);\n+}\n+\n+static inline bool is_stacked(s8 reg)\n+{\n+\treturn reg \u003c 0;\n+}\n+\n+static s8 bpf_get_reg32(s8 bpf_reg, s8 tmp_reg, struct jit_ctx *ctx)\n+{\n+\tif (is_stacked(bpf_reg)) {\n+\t\temit_16(ctx, 0x202e | (tmp_reg \u003c\u003c 9));\t\t/* move.l d16(%fp), reg */\n+\t\temit_16(ctx, (u16)bpf_reg);\n+\t\treturn tmp_reg;\n+\t}\n+\treturn bpf_reg;\n+}\n+\n+static void bpf_put_reg32(s8 bpf_reg, s8 src_reg, struct jit_ctx *ctx)\n+{\n+\tif (is_stacked(bpf_reg)) {\n+\t\temit_16(ctx, 0x2d40 | src_reg);\t\t\t/* move.l reg, d16(%fp) */\n+\t\temit_16(ctx, (u16)bpf_reg);\n+\t} else if (bpf_reg != src_reg) {\n+\t\temit_16(ctx, 0x2000 | (bpf_reg \u003c\u003c 9) | src_reg); /* move.l src, dst */\n+\t}\n+}\n+\n+static void emit_alu32_neg(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\ts8 d_reg = bpf_get_reg32(dst[1], tmp1[1], ctx);\n+\n+\temit_16(ctx, 0x4480 | d_reg);\t\t\t\t/* neg.l d_reg */\n+\n+\tbpf_put_reg32(dst[1], d_reg, ctx);\n+\temit_16(ctx, 0x7000 | (tmp1[0] \u003c\u003c 9));\t\t\t/* moveq #0, tmp1 */\n+\tbpf_put_reg32(dst[0], tmp1[0], ctx);\n+}\n+\n+static void emit_alu64_neg(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\ts8 d_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);\n+\ts8 d_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);\n+\n+\temit_16(ctx, 0x4480 | d_lo);\t\t\t\t/* neg.l d_lo */\n+\temit_16(ctx, 0x4080 | d_hi);\t\t\t\t/* negx.l d_hi */\n+\n+\tbpf_put_reg32(dst[1], d_lo, ctx);\n+\tbpf_put_reg32(dst[0], d_hi, ctx);\n+}\n+\n+static void emit_alu32_x(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *src = bpf2m68k[insn-\u003esrc_reg];\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\tconst s8 *tmp2 = bpf2m68k[TMP_REG_2];\n+\ts8 d_reg, s_reg;\n+\n+\td_reg = bpf_get_reg32(dst[1], tmp1[1], ctx);\n+\ts_reg = bpf_get_reg32(src[1], tmp2[1], ctx);\n+\n+\tswitch (BPF_OP(insn-\u003ecode)) {\n+\tcase BPF_MOV:\n+\t\tif (insn-\u003eoff == 8 || insn-\u003eoff == 16) {\n+\t\t\tif (d_reg != s_reg)\n+\t\t\t\temit_16(ctx, 0x2000 | (d_reg \u003c\u003c 9) | s_reg); /* move.l src, dst */\n+\t\t\tif (insn-\u003eoff == 8)\n+\t\t\t\temit_16(ctx, 0x49c0 | d_reg);\t/* extb.l d_reg */\n+\t\t\telse\n+\t\t\t\temit_16(ctx, 0x48c0 | d_reg);\t/* ext.l d_reg */\n+\t\t} else {\n+\t\t\tif (d_reg != s_reg)\n+\t\t\t\temit_16(ctx, 0x2000 | (d_reg \u003c\u003c 9) | s_reg); /* move.l src, dst */\n+\t\t}\n+\t\tbreak;\n+\tcase BPF_ADD:\n+\t\temit_16(ctx, 0xd080 | (d_reg \u003c\u003c 9) | s_reg);\t/* add.l src, dst */\n+\t\tbreak;\n+\tcase BPF_SUB:\n+\t\temit_16(ctx, 0x9080 | (d_reg \u003c\u003c 9) | s_reg);\t/* sub.l src, dst */\n+\t\tbreak;\n+\tcase BPF_AND:\n+\t\temit_16(ctx, 0xc080 | (d_reg \u003c\u003c 9) | s_reg);\t/* and.l src, dst */\n+\t\tbreak;\n+\tcase BPF_OR:\n+\t\temit_16(ctx, 0x8080 | (d_reg \u003c\u003c 9) | s_reg);\t/* or.l src, dst */\n+\t\tbreak;\n+\tcase BPF_XOR:\n+\t\temit_16(ctx, 0xb180 | (s_reg \u003c\u003c 9) | d_reg);\t/* eor.l src, dst */\n+\t\tbreak;\n+\tcase BPF_LSH:\n+\tcase BPF_RSH:\n+\tcase BPF_ARSH: {\n+\t\ts8 count_reg = tmp2[1];\n+\n+\t\tif (s_reg != count_reg)\n+\t\t\temit_16(ctx, 0x2000 | (count_reg \u003c\u003c 9) | s_reg); /* move.l src, count */\n+\n+\t\temit_16(ctx, 0x0280 | count_reg);\t\t/* andi.l #imm, count */\n+\t\temit_32(ctx, 0x1f);\n+\n+\t\tif (BPF_OP(insn-\u003ecode) == BPF_LSH)\n+\t\t\temit_16(ctx, 0xe1a8 | (count_reg \u003c\u003c 9) | d_reg); /* lsl.l count, dst */\n+\t\telse if (BPF_OP(insn-\u003ecode) == BPF_RSH)\n+\t\t\temit_16(ctx, 0xe0a8 | (count_reg \u003c\u003c 9) | d_reg); /* lsr.l count, dst */\n+\t\telse\n+\t\t\temit_16(ctx, 0xe0a0 | (count_reg \u003c\u003c 9) | d_reg); /* asr.l count, dst */\n+\t\tbreak;\n+\t}\n+\t}\n+\n+\tbpf_put_reg32(dst[1], d_reg, ctx);\n+\temit_16(ctx, 0x7000 | (tmp1[0] \u003c\u003c 9));\t\t\t/* moveq #0, tmp1 */\n+\tbpf_put_reg32(dst[0], tmp1[0], ctx);\n+}\n+\n+static void emit_alu32_k(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\tconst s8 *tmp2 = bpf2m68k[TMP_REG_2];\n+\ts8 d_reg;\n+\ts32 imm = insn-\u003eimm;\n+\tbool is_moveq = (imm \u003e= -128 \u0026\u0026 imm \u003c= 127);\n+\n+\td_reg = bpf_get_reg32(dst[1], tmp1[1], ctx);\n+\n+\tswitch (BPF_OP(insn-\u003ecode)) {\n+\tcase BPF_MOV:\n+\t\tif (is_moveq) {\n+\t\t\temit_16(ctx, 0x7000 | (d_reg \u003c\u003c 9) | (imm \u0026 0xff)); /* moveq #imm, dst */\n+\t\t} else {\n+\t\t\temit_16(ctx, 0x203c | (d_reg \u003c\u003c 9));\t\t/* move.l #imm, dst */\n+\t\t\temit_32(ctx, imm);\n+\t\t}\n+\t\tbreak;\n+\tcase BPF_ADD:\n+\t\tif (is_moveq) {\n+\t\t\temit_16(ctx, 0x7000 | (tmp2[1] \u003c\u003c 9) | (imm \u0026 0xff)); /* moveq #imm, tmp2 */\n+\t\t\temit_16(ctx, 0xd080 | (d_reg \u003c\u003c 9) | tmp2[1]);\t/* add.l tmp2, dst */\n+\t\t} else {\n+\t\t\temit_16(ctx, 0x0680 | d_reg);\t\t\t/* addi.l #imm, dst */\n+\t\t\temit_32(ctx, imm);\n+\t\t}\n+\t\tbreak;\n+\tcase BPF_SUB:\n+\t\tif (is_moveq) {\n+\t\t\temit_16(ctx, 0x7000 | (tmp2[1] \u003c\u003c 9) | (imm \u0026 0xff)); /* moveq #imm, tmp2 */\n+\t\t\temit_16(ctx, 0x9080 | (d_reg \u003c\u003c 9) | tmp2[1]);\t/* sub.l tmp2, dst */\n+\t\t} else {\n+\t\t\temit_16(ctx, 0x0480 | d_reg);\t\t\t/* subi.l #imm, dst */\n+\t\t\temit_32(ctx, imm);\n+\t\t}\n+\t\tbreak;\n+\tcase BPF_AND:\n+\t\tif (is_moveq) {\n+\t\t\temit_16(ctx, 0x7000 | (tmp2[1] \u003c\u003c 9) | (imm \u0026 0xff)); /* moveq #imm, tmp2 */\n+\t\t\temit_16(ctx, 0xc080 | (d_reg \u003c\u003c 9) | tmp2[1]);\t/* and.l tmp2, dst */\n+\t\t} else {\n+\t\t\temit_16(ctx, 0x0280 | d_reg);\t\t\t/* andi.l #imm, dst */\n+\t\t\temit_32(ctx, imm);\n+\t\t}\n+\t\tbreak;\n+\tcase BPF_OR:\n+\t\tif (is_moveq) {\n+\t\t\temit_16(ctx, 0x7000 | (tmp2[1] \u003c\u003c 9) | (imm \u0026 0xff)); /* moveq #imm, tmp2 */\n+\t\t\temit_16(ctx, 0x8080 | (d_reg \u003c\u003c 9) | tmp2[1]);\t/* or.l tmp2, dst */\n+\t\t} else {\n+\t\t\temit_16(ctx, 0x0080 | d_reg);\t\t\t/* ori.l #imm, dst */\n+\t\t\temit_32(ctx, imm);\n+\t\t}\n+\t\tbreak;\n+\tcase BPF_XOR:\n+\t\tif (is_moveq) {\n+\t\t\temit_16(ctx, 0x7000 | (tmp2[1] \u003c\u003c 9) | (imm \u0026 0xff)); /* moveq #imm, tmp2 */\n+\t\t\temit_16(ctx, 0xb180 | (tmp2[1] \u003c\u003c 9) | d_reg);\t/* eor.l tmp2, dst */\n+\t\t} else {\n+\t\t\temit_16(ctx, 0x0a80 | d_reg);\t\t\t/* eori.l #imm, dst */\n+\t\t\temit_32(ctx, imm);\n+\t\t}\n+\t\tbreak;\n+\tcase BPF_LSH:\n+\tcase BPF_RSH:\n+\tcase BPF_ARSH:\n+\t\temit_16(ctx, 0x7000 | (tmp2[1] \u003c\u003c 9) | (imm \u0026 0x1f));\t/* moveq #imm, count */\n+\n+\t\tif (BPF_OP(insn-\u003ecode) == BPF_LSH)\n+\t\t\temit_16(ctx, 0xe1a8 | (tmp2[1] \u003c\u003c 9) | d_reg);\t/* lsl.l count, dst */\n+\t\telse if (BPF_OP(insn-\u003ecode) == BPF_RSH)\n+\t\t\temit_16(ctx, 0xe0a8 | (tmp2[1] \u003c\u003c 9) | d_reg);\t/* lsr.l count, dst */\n+\t\telse\n+\t\t\temit_16(ctx, 0xe0a0 | (tmp2[1] \u003c\u003c 9) | d_reg);\t/* asr.l count, dst */\n+\t\tbreak;\n+\t}\n+\n+\tbpf_put_reg32(dst[1], d_reg, ctx);\n+\temit_16(ctx, 0x7000 | (tmp1[0] \u003c\u003c 9));\t\t\t\t/* moveq #0, tmp1 */\n+\tbpf_put_reg32(dst[0], tmp1[0], ctx);\n+}\n+\n+static void emit_alu64_x(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *src = bpf2m68k[insn-\u003esrc_reg];\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\tconst s8 *tmp2 = bpf2m68k[TMP_REG_2];\n+\ts8 d_lo, d_hi, s_lo, s_hi;\n+\n+\td_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);\n+\td_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);\n+\ts_lo = bpf_get_reg32(src[1], tmp2[1], ctx);\n+\ts_hi = bpf_get_reg32(src[0], tmp2[0], ctx);\n+\n+\tswitch (BPF_OP(insn-\u003ecode)) {\n+\tcase BPF_MOV:\n+\t\tif (insn-\u003eoff == 8 || insn-\u003eoff == 16 || insn-\u003eoff == 32) {\n+\t\t\tif (d_lo != s_lo)\n+\t\t\t\temit_16(ctx, 0x2000 | (d_lo \u003c\u003c 9) | s_lo); /* move.l src, dst */\n+\n+\t\t\tif (insn-\u003eoff == 8)\n+\t\t\t\temit_16(ctx, 0x49c0 | d_lo);\t\t/* extb.l d_lo */\n+\t\t\telse if (insn-\u003eoff == 16)\n+\t\t\t\temit_16(ctx, 0x48c0 | d_lo);\t\t/* ext.l d_lo */\n+\n+\t\t\temit_16(ctx, 0x4a80 | d_lo);\t\t\t/* tst.l d_lo */\n+\t\t\temit_16(ctx, 0x5bc0 | d_hi);\t\t\t/* smi d_hi */\n+\t\t\temit_16(ctx, 0x49c0 | d_hi);\t\t\t/* extb.l d_hi */\n+\t\t} else {\n+\t\t\tif (d_lo != s_lo)\n+\t\t\t\temit_16(ctx, 0x2000 | (d_lo \u003c\u003c 9) | s_lo); /* move.l s_lo, d_lo */\n+\t\t\tif (d_hi != s_hi)\n+\t\t\t\temit_16(ctx, 0x2000 | (d_hi \u003c\u003c 9) | s_hi); /* move.l s_hi, d_hi */\n+\t\t}\n+\t\tbreak;\n+\tcase BPF_ADD:\n+\t\temit_16(ctx, 0xd080 | (d_lo \u003c\u003c 9) | s_lo);\t\t/* add.l s_lo, d_lo */\n+\t\temit_16(ctx, 0xd180 | (d_hi \u003c\u003c 9) | s_hi);\t\t/* addx.l s_hi, d_hi */\n+\t\tbreak;\n+\tcase BPF_SUB:\n+\t\temit_16(ctx, 0x9080 | (d_lo \u003c\u003c 9) | s_lo);\t\t/* sub.l s_lo, d_lo */\n+\t\temit_16(ctx, 0x9180 | (d_hi \u003c\u003c 9) | s_hi);\t\t/* subx.l s_hi, d_hi */\n+\t\tbreak;\n+\tcase BPF_AND:\n+\t\temit_16(ctx, 0xc080 | (d_lo \u003c\u003c 9) | s_lo);\t\t/* and.l s_lo, d_lo */\n+\t\temit_16(ctx, 0xc080 | (d_hi \u003c\u003c 9) | s_hi);\t\t/* and.l s_hi, d_hi */\n+\t\tbreak;\n+\tcase BPF_OR:\n+\t\temit_16(ctx, 0x8080 | (d_lo \u003c\u003c 9) | s_lo);\t\t/* or.l s_lo, d_lo */\n+\t\temit_16(ctx, 0x8080 | (d_hi \u003c\u003c 9) | s_hi);\t\t/* or.l s_hi, d_hi */\n+\t\tbreak;\n+\tcase BPF_XOR:\n+\t\temit_16(ctx, 0xb180 | (s_lo \u003c\u003c 9) | d_lo);\t\t/* eor.l s_lo, d_lo */\n+\t\temit_16(ctx, 0xb180 | (s_hi \u003c\u003c 9) | d_hi);\t\t/* eor.l s_hi, d_hi */\n+\t\tbreak;\n+\t}\n+\n+\tbpf_put_reg32(dst[1], d_lo, ctx);\n+\tbpf_put_reg32(dst[0], d_hi, ctx);\n+}\n+\n+static void emit_alu64_k(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\tconst s8 *tmp2 = bpf2m68k[TMP_REG_2];\n+\ts8 d_lo, d_hi, s_lo, s_hi;\n+\tu32 imm_lo = insn-\u003eimm;\n+\tu32 imm_hi = insn-\u003eimm \u003c 0 ? 0xffffffff : 0;\n+\n+\td_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);\n+\td_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);\n+\n+\tif (BPF_OP(insn-\u003ecode) == BPF_MOV) {\n+\t\temit_16(ctx, 0x203c | (d_lo \u003c\u003c 9));\t\t\t/* move.l #imm, d_lo */\n+\t\temit_32(ctx, imm_lo);\n+\t\temit_16(ctx, 0x203c | (d_hi \u003c\u003c 9));\t\t\t/* move.l #imm, d_hi */\n+\t\temit_32(ctx, imm_hi);\n+\t\tbpf_put_reg32(dst[1], d_lo, ctx);\n+\t\tbpf_put_reg32(dst[0], d_hi, ctx);\n+\t\treturn;\n+\t}\n+\n+\ts_lo = tmp2[1];\n+\ts_hi = tmp2[0];\n+\n+\temit_16(ctx, 0x203c | (s_lo \u003c\u003c 9));\t\t\t\t/* move.l #imm, s_lo */\n+\temit_32(ctx, imm_lo);\n+\temit_16(ctx, 0x203c | (s_hi \u003c\u003c 9));\t\t\t\t/* move.l #imm, s_hi */\n+\temit_32(ctx, imm_hi);\n+\n+\tswitch (BPF_OP(insn-\u003ecode)) {\n+\tcase BPF_ADD:\n+\t\temit_16(ctx, 0xd080 | (d_lo \u003c\u003c 9) | s_lo);\t\t/* add.l s_lo, d_lo */\n+\t\temit_16(ctx, 0xd180 | (d_hi \u003c\u003c 9) | s_hi);\t\t/* addx.l s_hi, d_hi */\n+\t\tbreak;\n+\tcase BPF_SUB:\n+\t\temit_16(ctx, 0x9080 | (d_lo \u003c\u003c 9) | s_lo);\t\t/* sub.l s_lo, d_lo */\n+\t\temit_16(ctx, 0x9180 | (d_hi \u003c\u003c 9) | s_hi);\t\t/* subx.l s_hi, d_hi */\n+\t\tbreak;\n+\tcase BPF_AND:\n+\t\temit_16(ctx, 0xc080 | (d_lo \u003c\u003c 9) | s_lo);\t\t/* and.l s_lo, d_lo */\n+\t\temit_16(ctx, 0xc080 | (d_hi \u003c\u003c 9) | s_hi);\t\t/* and.l s_hi, d_hi */\n+\t\tbreak;\n+\tcase BPF_OR:\n+\t\temit_16(ctx, 0x8080 | (d_lo \u003c\u003c 9) | s_lo);\t\t/* or.l s_lo, d_lo */\n+\t\temit_16(ctx, 0x8080 | (d_hi \u003c\u003c 9) | s_hi);\t\t/* or.l s_hi, d_hi */\n+\t\tbreak;\n+\tcase BPF_XOR:\n+\t\temit_16(ctx, 0xb180 | (s_lo \u003c\u003c 9) | d_lo);\t\t/* eor.l s_lo, d_lo */\n+\t\temit_16(ctx, 0xb180 | (s_hi \u003c\u003c 9) | d_hi);\t\t/* eor.l s_hi, d_hi */\n+\t\tbreak;\n+\t}\n+\n+\tbpf_put_reg32(dst[1], d_lo, ctx);\n+\tbpf_put_reg32(dst[0], d_hi, ctx);\n+}\n+\n+static inline void emit_lsh64(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)\n+{\n+\tif (CPU_IS_COLDFIRE) {\n+\t\temit_16(ctx, 0xd080 | (d_lo \u003c\u003c 9) | d_lo);\t\t/* add.l d_lo, d_lo */\n+\t\temit_16(ctx, 0xd180 | (d_hi \u003c\u003c 9) | d_hi);\t\t/* addx.l d_hi, d_hi */\n+\t} else {\n+\t\temit_16(ctx, 0xe388 | d_lo);\t\t\t\t/* lsll #1, d_lo */\n+\t\temit_16(ctx, 0xe390 | d_hi);\t\t\t\t/* roxl.l #1, d_hi */\n+\t}\n+}\n+\n+static inline void emit_rsh64(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)\n+{\n+\tif (CPU_IS_COLDFIRE) {\n+\t\temit_16(ctx, 0xe288 | d_lo);\t\t\t\t/* lsr.l #1, d_lo */\n+\t\temit_16(ctx, 0xe288 | d_hi);\t\t\t\t/* lsr.l #1, d_hi */\n+\t\temit_16(ctx, 0x6400);\t\t\t\t\t/* bcc 1f */\n+\t\temit_16(ctx, 0x0006);\n+\t\temit_16(ctx, 0x08c0 | d_lo);\t\t\t\t/* bset #31, d_lo */\n+\t\temit_16(ctx, 0x001f);\n+\t} else {\n+\t\temit_16(ctx, 0xe288 | d_hi);\t\t\t\t/* lsrl #1, d_hi */\n+\t\temit_16(ctx, 0xe290 | d_lo);\t\t\t\t/* roxr.l #1, d_lo */\n+\t}\n+}\n+\n+static inline void emit_arsh64(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)\n+{\n+\tif (CPU_IS_COLDFIRE) {\n+\t\temit_16(ctx, 0xe288 | d_lo);\t\t\t\t/* lsr.l #1, d_lo */\n+\t\temit_16(ctx, 0xe280 | d_hi);\t\t\t\t/* asr.l #1, d_hi */\n+\t\temit_16(ctx, 0x6400);\t\t\t\t\t/* bcc 1f */\n+\t\temit_16(ctx, 0x0006);\n+\t\temit_16(ctx, 0x08c0 | d_lo);\t\t\t\t/* bset #31, d_lo */\n+\t\temit_16(ctx, 0x001f);\n+\t} else {\n+\t\temit_16(ctx, 0xe280 | d_hi);\t\t\t\t/* asrl #1, d_hi */\n+\t\temit_16(ctx, 0xe290 | d_lo);\t\t\t\t/* roxr.l #1, d_lo */\n+\t}\n+}\n+\n+static void emit_alu64_shift(const struct bpf_insn *insn, struct jit_ctx *ctx, bool is_imm)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\tconst s8 *tmp2 = bpf2m68k[TMP_REG_2];\n+\ts8 d_lo, d_hi, count_reg;\n+\tint loop_start, done_idx;\n+\n+\td_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);\n+\td_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);\n+\tcount_reg = tmp2[1];\n+\n+\tif (is_imm) {\n+\t\temit_16(ctx, 0x203c | (count_reg \u003c\u003c 9));\t\t/* move.l #imm, count_reg */\n+\t\temit_32(ctx, insn-\u003eimm);\n+\t} else {\n+\t\tconst s8 *src = bpf2m68k[insn-\u003esrc_reg];\n+\t\ts8 s_lo = bpf_get_reg32(src[1], tmp2[1], ctx);\n+\n+\t\tif (count_reg != s_lo)\n+\t\t\temit_16(ctx, 0x2000 | (count_reg \u003c\u003c 9) | s_lo);\t/* move.l s_lo, count_reg */\n+\t}\n+\n+\temit_16(ctx, 0x0280 | count_reg);\t\t\t/* andi.l #0x3f, count_reg */\n+\temit_32(ctx, 0x3f);\n+\n+\temit_16(ctx, 0x4a80 | count_reg);\t\t\t\t/* tst.l count_reg */\n+\temit_16(ctx, 0x6700);\t\t\t\t\t\t/* beq.w done_idx */\n+\tdone_idx = ctx-\u003eidx;\n+\temit_16(ctx, 0);\n+\n+\tloop_start = ctx-\u003eidx;\n+\n+\tif (BPF_OP(insn-\u003ecode) == BPF_LSH)\n+\t\temit_lsh64(ctx, d_lo, d_hi);\n+\telse if (BPF_OP(insn-\u003ecode) == BPF_RSH)\n+\t\temit_rsh64(ctx, d_lo, d_hi);\n+\telse if (BPF_OP(insn-\u003ecode) == BPF_ARSH)\n+\t\temit_arsh64(ctx, d_lo, d_hi);\n+\n+\temit_16(ctx, 0x5380 | count_reg);\t\t\t\t/* subq.l #1, count_reg */\n+\temit_16(ctx, 0x6600);\t\t\t\t\t\t/* bne.w loop_start */\n+\temit_16(ctx, (loop_start - (int)ctx-\u003eidx) * 2);\n+\n+\tif (ctx-\u003etarget)\n+\t\tctx-\u003etarget[done_idx] = (ctx-\u003eidx - done_idx) * 2;\n+\n+\tbpf_put_reg32(dst[1], d_lo, ctx);\n+\tbpf_put_reg32(dst[0], d_hi, ctx);\n+}\n+\n+static inline void emit_to_le16(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)\n+{\n+\tif (CPU_IS_COLDFIRE) {\n+\t\temit_16(ctx, 0x71c0 | (d_lo \u003c\u003c 9) | d_lo);\t\t/* mvz.w d_lo, d_lo */\n+\t\temit_16(ctx, 0x7180 | (d_hi \u003c\u003c 9) | d_lo);\t\t/* mvz.b d_lo, d_hi */\n+\t\temit_16(ctx, 0xe088 | d_lo);\t\t\t\t/* lsr.l #8, d_lo */\n+\t\temit_16(ctx, 0xe188 | d_hi);\t\t\t\t/* lsl.l #8, d_hi */\n+\t\temit_16(ctx, 0x8080 | (d_lo \u003c\u003c 9) | d_hi);\t\t/* or.l d_hi, d_lo */\n+\t} else {\n+\t\temit_16(ctx, 0x0280 | d_lo);\t\t\t\t/* andi.l #0xffff, d_lo */\n+\t\temit_32(ctx, 0xffff);\n+\t\temit_16(ctx, 0xe058 | d_lo);\t\t\t\t/* ror.w #8, d_lo */\n+\t}\n+\n+\temit_16(ctx, 0x7000 | (d_hi \u003c\u003c 9));\t\t\t\t/* moveq #0, d_hi */\n+}\n+\n+static inline void emit_to_le32(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)\n+{\n+\tif (CPU_IS_COLDFIRE) {\n+\t\temit_16(ctx, 0x2f00 | d_lo);\t\t\t\t/* move.l d_lo, -(%sp) */\n+\t\temit_16(ctx, 0x4840 | d_lo);\t\t\t\t/* swap d_lo */\n+\t\temit_16(ctx, 0x71c0 | (d_lo \u003c\u003c 9) | d_lo);\t\t/* mvz.w d_lo, d_lo */\n+\t\temit_16(ctx, 0x7180 | (d_hi \u003c\u003c 9) | d_lo);\t\t/* mvz.b d_lo, d_hi */\n+\t\temit_16(ctx, 0xe088 | d_lo);\t\t\t\t/* lsr.l #8, d_lo */\n+\t\temit_16(ctx, 0xe188 | d_hi);\t\t\t\t/* lsl.l #8, d_hi */\n+\t\temit_16(ctx, 0x8080 | (d_hi \u003c\u003c 9) | d_lo);\t\t/* or.l d_lo, d_hi */\n+\t\temit_16(ctx, 0x2017 | (d_lo \u003c\u003c 9));\t\t\t/* move.l (%sp), d_lo */\n+\t\temit_16(ctx, 0x2e80 | d_hi);\t\t\t\t/* move.l d_hi, (%sp) */\n+\t\temit_16(ctx, 0x71c0 | (d_lo \u003c\u003c 9) | d_lo);\t\t/* mvz.w d_lo, d_lo */\n+\t\temit_16(ctx, 0x7180 | (d_hi \u003c\u003c 9) | d_lo);\t\t/* mvz.b d_lo, d_hi */\n+\t\temit_16(ctx, 0xe088 | d_lo);\t\t\t\t/* lsr.l #8, d_lo */\n+\t\temit_16(ctx, 0xe188 | d_hi);\t\t\t\t/* lsl.l #8, d_hi */\n+\t\temit_16(ctx, 0x8080 | (d_lo \u003c\u003c 9) | d_hi);\t\t/* or.l d_hi, d_lo */\n+\t\temit_16(ctx, 0x4840 | d_lo);\t\t\t\t/* swap d_lo */\n+\t\temit_16(ctx, 0x809f | (d_lo \u003c\u003c 9));\t\t\t/* or.l (%sp)+, d_lo */\n+\t} else {\n+\t\temit_16(ctx, 0xe058 | d_lo);\t\t\t\t/* ror.w #8, d_lo */\n+\t\temit_16(ctx, 0x4840 | d_lo);\t\t\t\t/* swap d_lo */\n+\t\temit_16(ctx, 0xe058 | d_lo);\t\t\t\t/* ror.w #8, d_lo */\n+\t}\n+\n+\temit_16(ctx, 0x7000 | (d_hi \u003c\u003c 9));\t\t\t\t/* moveq #0, d_hi */\n+}\n+\n+static inline void emit_to_le64(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)\n+{\n+\tif (CPU_IS_COLDFIRE) {\n+\t\temit_16(ctx, 0x2f00 | d_lo);\t\t\t\t/* move.l d_lo, -(%sp) */\n+\t\temit_16(ctx, 0x2f00 | d_hi);\t\t\t\t/* move.l d_hi, -(%sp) */\n+\n+\t\temit_16(ctx, 0x4840 | d_lo);\t\t\t\t/* swap d_lo */\n+\t\temit_16(ctx, 0x71c0 | (d_lo \u003c\u003c 9) | d_lo);\t\t/* mvz.w d_lo, d_lo */\n+\t\temit_16(ctx, 0x7180 | (d_hi \u003c\u003c 9) | d_lo);\t\t/* mvz.b d_lo, d_hi */\n+\t\temit_16(ctx, 0xe088 | d_lo);\t\t\t\t/* lsr.l #8, d_lo */\n+\t\temit_16(ctx, 0xe188 | d_hi);\t\t\t\t/* lsl.l #8, d_hi */\n+\t\temit_16(ctx, 0x8080 | (d_hi \u003c\u003c 9) | d_lo);\t\t/* or.l d_lo, d_hi */\n+\t\temit_16(ctx, 0x202f | (d_lo \u003c\u003c 9));\t\t\t/* move.l 4(%sp), d_lo */\n+\t\temit_16(ctx, 0x0004);\n+\t\temit_16(ctx, 0x2f40 | d_hi);\t\t\t\t/* move.l d_hi, 4(%sp) */\n+\t\temit_16(ctx, 0x0004);\n+\t\temit_16(ctx, 0x71c0 | (d_lo \u003c\u003c 9) | d_lo);\t\t/* mvz.w d_lo, d_lo */\n+\t\temit_16(ctx, 0x7180 | (d_hi \u003c\u003c 9) | d_lo);\t\t/* mvz.b d_lo, d_hi */\n+\t\temit_16(ctx, 0xe088 | d_lo);\t\t\t\t/* lsr.l #8, d_lo */\n+\t\temit_16(ctx, 0xe188 | d_hi);\t\t\t\t/* lsl.l #8, d_hi */\n+\t\temit_16(ctx, 0x8080 | (d_lo \u003c\u003c 9) | d_hi);\t\t/* or.l d_hi, d_lo */\n+\t\temit_16(ctx, 0x4840 | d_lo);\t\t\t\t/* swap d_lo */\n+\t\temit_16(ctx, 0x81af | (d_lo \u003c\u003c 9));\t\t\t/* or.l d_lo, 4(%sp) */\n+\t\temit_16(ctx, 0x0004);\n+\n+\t\temit_16(ctx, 0x2017 | (d_lo \u003c\u003c 9));\t\t\t/* move.l (%sp), d_lo */\n+\t\temit_16(ctx, 0x4840 | d_lo);\t\t\t\t/* swap d_lo */\n+\t\temit_16(ctx, 0x71c0 | (d_lo \u003c\u003c 9) | d_lo);\t\t/* mvz.w d_lo, d_lo */\n+\t\temit_16(ctx, 0x7180 | (d_hi \u003c\u003c 9) | d_lo);\t\t/* mvz.b d_lo, d_hi */\n+\t\temit_16(ctx, 0xe088 | d_lo);\t\t\t\t/* lsr.l #8, d_lo */\n+\t\temit_16(ctx, 0xe188 | d_hi);\t\t\t\t/* lsl.l #8, d_hi */\n+\t\temit_16(ctx, 0x8080 | (d_hi \u003c\u003c 9) | d_lo);\t\t/* or.l d_lo, d_hi */\n+\t\temit_16(ctx, 0x2017 | (d_lo \u003c\u003c 9));\t\t\t/* move.l (%sp), d_lo */\n+\t\temit_16(ctx, 0x2e80 | d_hi);\t\t\t\t/* move.l d_hi, (%sp) */\n+\t\temit_16(ctx, 0x71c0 | (d_lo \u003c\u003c 9) | d_lo);\t\t/* mvz.w d_lo, d_lo */\n+\t\temit_16(ctx, 0x7180 | (d_hi \u003c\u003c 9) | d_lo);\t\t/* mvz.b d_lo, d_hi */\n+\t\temit_16(ctx, 0xe088 | d_lo);\t\t\t\t/* lsr.l #8, d_lo */\n+\t\temit_16(ctx, 0xe188 | d_hi);\t\t\t\t/* lsl.l #8, d_hi */\n+\t\temit_16(ctx, 0x8080 | (d_lo \u003c\u003c 9) | d_hi);\t\t/* or.l d_hi, d_lo */\n+\t\temit_16(ctx, 0x4840 | d_lo);\t\t\t\t/* swap d_lo */\n+\t\temit_16(ctx, 0x809f | (d_lo \u003c\u003c 9));\t\t\t/* or.l (%sp)+, d_lo */\n+\n+\t\temit_16(ctx, 0x201f | (d_hi \u003c\u003c 9));\t\t\t/* move.l (%sp)+, d_hi */\n+\t} else {\n+\t\temit_16(ctx, 0xe058 | d_lo);\t\t\t\t/* ror.w #8, d_lo */\n+\t\temit_16(ctx, 0x4840 | d_lo);\t\t\t\t/* swap d_lo */\n+\t\temit_16(ctx, 0xe058 | d_lo);\t\t\t\t/* ror.w #8, d_lo */\n+\n+\t\temit_16(ctx, 0xe058 | d_hi);\t\t\t\t/* ror.w #8, d_hi */\n+\t\temit_16(ctx, 0x4840 | d_hi);\t\t\t\t/* swap d_hi */\n+\t\temit_16(ctx, 0xe058 | d_hi);\t\t\t\t/* ror.w #8, d_hi */\n+\n+\t\temit_16(ctx, 0xc140 | (d_hi \u003c\u003c 9) | d_lo);\t\t/* exg d_lo, d_hi */\n+\t}\n+}\n+\n+static void emit_bpf_end(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\ts8 d_lo, d_hi;\n+\tbool to_le = BPF_SRC(insn-\u003ecode) == BPF_TO_LE;\n+\tint imm = insn-\u003eimm;\n+\n+\td_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);\n+\td_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);\n+\n+\tif (to_le) {\n+\t\tswitch (imm) {\n+\t\tcase 16:\n+\t\t\temit_to_le16(ctx, d_lo, d_hi);\n+\t\t\tbreak;\n+\t\tcase 32:\n+\t\t\temit_to_le32(ctx, d_lo, d_hi);\n+\t\t\tbreak;\n+\t\tcase 64:\n+\t\t\temit_to_le64(ctx, d_lo, d_hi);\n+\t\t\tbreak;\n+\t\t}\n+\t} else {\n+\t\tswitch (imm) {\n+\t\tcase 16:\n+\t\t\temit_16(ctx, 0x0280 | d_lo);\t\t\t/* andi.l #0xffff, d_lo */\n+\t\t\temit_32(ctx, 0xffff);\n+\t\t\temit_16(ctx, 0x7000 | (d_hi \u003c\u003c 9));\t\t/* moveq #0, d_hi */\n+\t\t\tbreak;\n+\t\tcase 32:\n+\t\t\temit_16(ctx, 0x7000 | (d_hi \u003c\u003c 9));\t\t/* moveq #0, d_hi */\n+\t\t\tbreak;\n+\t\tcase 64:\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tbpf_put_reg32(dst[1], d_lo, ctx);\n+\tbpf_put_reg32(dst[0], d_hi, ctx);\n+}\n+\n+static void emit_math_call(const struct bpf_insn *insn, struct jit_ctx *ctx, bool is_64)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *src = bpf2m68k[insn-\u003esrc_reg];\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\tconst s8 *tmp2 = bpf2m68k[TMP_REG_2];\n+\ts8 d_lo, d_hi, s_lo, s_hi = 0;\n+\tvoid *func = NULL;\n+\tu8 op = BPF_OP(insn-\u003ecode);\n+\n+\td_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);\n+\td_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);\n+\n+\tif (BPF_SRC(insn-\u003ecode) == BPF_X) {\n+\t\ts_lo = bpf_get_reg32(src[1], tmp2[1], ctx);\n+\t\tif (is_64)\n+\t\t\ts_hi = bpf_get_reg32(src[0], tmp2[0], ctx);\n+\t} else {\n+\t\ts_lo = tmp2[1];\n+\t\temit_16(ctx, 0x203c | (s_lo \u003c\u003c 9));\t\t\t/* move.l #imm, s_lo */\n+\t\temit_32(ctx, insn-\u003eimm);\n+\t\tif (is_64) {\n+\t\t\ts_hi = tmp2[0];\n+\t\t\temit_16(ctx, 0x203c | (s_hi \u003c\u003c 9));\t\t/* move.l #imm, s_hi */\n+\t\t\temit_32(ctx, insn-\u003eimm \u003c 0 ? 0xffffffff : 0);\n+\t\t}\n+\t}\n+\n+\tif (is_64) {\n+\t\tswitch (op) {\n+\t\tcase BPF_MUL:\n+\t\t\tfunc = (void *)jit_mul64;\n+\t\t\tbreak;\n+\t\tcase BPF_DIV:\n+\t\t\tfunc = (void *)jit_div64;\n+\t\t\tbreak;\n+\t\tcase BPF_MOD:\n+\t\t\tfunc = (void *)jit_mod64;\n+\t\t\tbreak;\n+\t\t}\n+\t\tif (BPF_CLASS(insn-\u003ecode) == BPF_ALU64 \u0026\u0026 op == BPF_DIV \u0026\u0026 insn-\u003eoff == 1)\n+\t\t\tfunc = (void *)jit_sdiv64;\n+\t\tif (BPF_CLASS(insn-\u003ecode) == BPF_ALU64 \u0026\u0026 op == BPF_MOD \u0026\u0026 insn-\u003eoff == 1)\n+\t\t\tfunc = (void *)jit_smod64;\n+\t} else {\n+\t\tswitch (op) {\n+\t\tcase BPF_MUL:\n+\t\t\tfunc = (void *)jit_mul32;\n+\t\t\tbreak;\n+\t\tcase BPF_DIV:\n+\t\t\tfunc = (void *)jit_div32;\n+\t\t\tbreak;\n+\t\tcase BPF_MOD:\n+\t\t\tfunc = (void *)jit_mod32;\n+\t\t\tbreak;\n+\t\t}\n+\t\tif (BPF_CLASS(insn-\u003ecode) == BPF_ALU \u0026\u0026 op == BPF_DIV \u0026\u0026 insn-\u003eoff == 1)\n+\t\t\tfunc = (void *)jit_sdiv32;\n+\t\tif (BPF_CLASS(insn-\u003ecode) == BPF_ALU \u0026\u0026 op == BPF_MOD \u0026\u0026 insn-\u003eoff == 1)\n+\t\t\tfunc = (void *)jit_smod32;\n+\t}\n+\n+\tif (is_64) {\n+\t\temit_16(ctx, 0x2f01);\t\t\t\t\t/* move.l d1, -(%sp) */\n+\t\temit_16(ctx, 0x2f00);\t\t\t\t\t/* move.l d0, -(%sp) */\n+\n+\t\temit_16(ctx, 0x2f00 | s_lo);\t\t\t\t/* move.l s_lo, -(%sp) */\n+\t\temit_16(ctx, 0x2f00 | s_hi);\t\t\t\t/* move.l s_hi, -(%sp) */\n+\t\temit_16(ctx, 0x2f00 | d_lo);\t\t\t\t/* move.l d_lo, -(%sp) */\n+\t\temit_16(ctx, 0x2f00 | d_hi);\t\t\t\t/* move.l d_hi, -(%sp) */\n+\n+\t\temit_16(ctx, 0x207c);\t\t\t\t\t/* movea.l #func, %a0 */\n+\t\temit_32(ctx, (u32)func);\n+\t\temit_16(ctx, 0x4e90);\t\t\t\t\t/* jsr (%a0) */\n+\n+\t\temit_16(ctx, 0x4fef);\t\t\t\t\t/* lea 16(%sp), %sp */\n+\t\temit_16(ctx, 16);\n+\n+\t\temit_16(ctx, 0x2601);\t\t\t\t\t/* move.l %d1, %d3 */\n+\t\temit_16(ctx, 0x2400);\t\t\t\t\t/* move.l %d0, %d2 */\n+\n+\t\temit_16(ctx, 0x201f);\t\t\t\t\t/* move.l (%sp)+, d0 */\n+\t\temit_16(ctx, 0x221f);\t\t\t\t\t/* move.l (%sp)+, d1 */\n+\t} else {\n+\t\temit_16(ctx, 0x2f01);\t\t\t\t\t/* move.l d1, -(%sp) */\n+\t\temit_16(ctx, 0x2f00);\t\t\t\t\t/* move.l d0, -(%sp) */\n+\n+\t\temit_16(ctx, 0x2f00 | s_lo);\t\t\t\t/* move.l s_lo, -(%sp) */\n+\t\temit_16(ctx, 0x2f00 | d_lo);\t\t\t\t/* move.l d_lo, -(%sp) */\n+\n+\t\temit_16(ctx, 0x207c);\t\t\t\t\t/* movea.l #func, %a0 */\n+\t\temit_32(ctx, (u32)func);\n+\t\temit_16(ctx, 0x4e90);\t\t\t\t\t/* jsr (%a0) */\n+\n+\t\temit_16(ctx, 0x4fef);\t\t\t\t\t/* lea 8(%sp), %sp */\n+\t\temit_16(ctx, 8);\n+\n+\t\temit_16(ctx, 0x2600);\t\t\t\t\t/* move.l %d0, %d3 */\n+\t\temit_16(ctx, 0x7400);\t\t\t\t\t/* moveq #0, %d2 */\n+\n+\t\temit_16(ctx, 0x201f);\t\t\t\t\t/* move.l (%sp)+, d0 */\n+\t\temit_16(ctx, 0x221f);\t\t\t\t\t/* move.l (%sp)+, d1 */\n+\t}\n+\n+\tbpf_put_reg32(dst[1], M68K_D3, ctx);\n+\tbpf_put_reg32(dst[0], M68K_D2, ctx);\n+}\n+\n+static void emit_ldx(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *src = bpf2m68k[insn-\u003esrc_reg];\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\ts8 d_lo, d_hi;\n+\tbool is_mem_sx = BPF_MODE(insn-\u003ecode) == BPF_MEMSX;\n+\n+\tif (is_stacked(src[1])) {\n+\t\temit_16(ctx, 0x206e);\t\t\t\t/* movea.l d16(%fp), %a0 */\n+\t\temit_16(ctx, (u16)src[1]);\n+\t} else {\n+\t\temit_16(ctx, 0x2040 | src[1]);\t\t\t/* movea.l src, %a0 */\n+\t}\n+\n+\td_lo = is_stacked(dst[1]) ? tmp1[1] : dst[1];\n+\td_hi = is_stacked(dst[0]) ? tmp1[0] : dst[0];\n+\n+\tswitch (BPF_SIZE(insn-\u003ecode)) {\n+\tcase BPF_B:\n+\t\tif (!is_mem_sx)\n+\t\t\temit_16(ctx, 0x7000 | (d_lo \u003c\u003c 9));\t/* moveq #0, d_lo */\n+\t\temit_16(ctx, 0x1028 | (d_lo \u003c\u003c 9));\t\t/* move.b d16(%a0), d_lo */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tif (is_mem_sx)\n+\t\t\temit_16(ctx, 0x49c0 | d_lo);\t/* extb.l d_lo */\n+\t\tbreak;\n+\tcase BPF_H:\n+\t\tif (!is_mem_sx)\n+\t\t\temit_16(ctx, 0x7000 | (d_lo \u003c\u003c 9));\t/* moveq #0, d_lo */\n+\t\temit_16(ctx, 0x3028 | (d_lo \u003c\u003c 9));\t\t/* move.w d16(%a0), d_lo */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tif (is_mem_sx)\n+\t\t\temit_16(ctx, 0x48c0 | d_lo);\t/* ext.l d_lo */\n+\t\tbreak;\n+\tcase BPF_W:\n+\t\temit_16(ctx, 0x2028 | (d_lo \u003c\u003c 9));\t\t/* move.l d16(%a0), d_lo */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tbreak;\n+\tcase BPF_DW:\n+\t\temit_16(ctx, 0x2028 | (d_hi \u003c\u003c 9));\t\t/* move.l d16(%a0), d_hi */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\temit_16(ctx, 0x41e8);\t\t\t\t/* lea 4(%a0), %a0 */\n+\t\temit_16(ctx, 4);\n+\t\temit_16(ctx, 0x2028 | (d_lo \u003c\u003c 9));\t\t/* move.l d16(%a0), d_lo */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tbreak;\n+\t}\n+\n+\tif (BPF_SIZE(insn-\u003ecode) != BPF_DW) {\n+\t\tif (is_mem_sx) {\n+\t\t\temit_16(ctx, 0x4a80 | d_lo);\t\t\t/* tst.l d_lo */\n+\t\t\temit_16(ctx, 0x5bc0 | d_hi);\t\t\t/* smi d_hi */\n+\t\t\temit_16(ctx, 0x49c0 | d_hi);\t\t\t/* extb.l d_hi */\n+\t\t} else {\n+\t\t\temit_16(ctx, 0x7000 | (d_hi \u003c\u003c 9));\t/* moveq #0, d_hi */\n+\t\t}\n+\t}\n+\n+\tbpf_put_reg32(dst[1], d_lo, ctx);\n+\tbpf_put_reg32(dst[0], d_hi, ctx);\n+}\n+\n+static void emit_stx(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *src = bpf2m68k[insn-\u003esrc_reg];\n+\tconst s8 *tmp2 = bpf2m68k[TMP_REG_2];\n+\ts8 s_lo, s_hi;\n+\n+\tif (is_stacked(dst[1])) {\n+\t\temit_16(ctx, 0x206e);\t\t\t\t/* movea.l d16(%fp), %a0 */\n+\t\temit_16(ctx, (u16)dst[1]);\n+\t} else {\n+\t\temit_16(ctx, 0x2040 | dst[1]);\t\t\t/* movea.l dst, %a0 */\n+\t}\n+\n+\ts_lo = bpf_get_reg32(src[1], tmp2[1], ctx);\n+\n+\tswitch (BPF_SIZE(insn-\u003ecode)) {\n+\tcase BPF_B:\n+\t\temit_16(ctx, 0x1140 | s_lo);\t\t\t/* move.b s_lo, d16(%a0) */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tbreak;\n+\tcase BPF_H:\n+\t\temit_16(ctx, 0x3140 | s_lo);\t\t\t/* move.w s_lo, d16(%a0) */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tbreak;\n+\tcase BPF_W:\n+\t\temit_16(ctx, 0x2140 | s_lo);\t\t\t/* move.l s_lo, d16(%a0) */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tbreak;\n+\tcase BPF_DW:\n+\t\ts_hi = bpf_get_reg32(src[0], tmp2[0], ctx);\n+\t\temit_16(ctx, 0x2140 | s_hi);\t\t\t/* move.l s_hi, d16(%a0) */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\temit_16(ctx, 0x41e8);\t\t\t\t/* lea 4(%a0), %a0 */\n+\t\temit_16(ctx, 4);\n+\t\temit_16(ctx, 0x2140 | s_lo);\t\t\t/* move.l s_lo, d16(%a0) */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tbreak;\n+\t}\n+}\n+\n+static void emit_st(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *tmp = bpf2m68k[TMP_REG_1];\n+\n+\tif (is_stacked(dst[1])) {\n+\t\temit_16(ctx, 0x206e);\t\t\t\t/* movea.l d16(%fp), %a0 */\n+\t\temit_16(ctx, (u16)dst[1]);\n+\t} else {\n+\t\temit_16(ctx, 0x2040 | dst[1]);\t\t\t/* movea.l dst, %a0 */\n+\t}\n+\n+\temit_16(ctx, 0x203c | (tmp[1] \u003c\u003c 9));\t\t\t/* move.l #imm, tmp */\n+\temit_32(ctx, insn-\u003eimm);\n+\n+\tswitch (BPF_SIZE(insn-\u003ecode)) {\n+\tcase BPF_B:\n+\t\temit_16(ctx, 0x1140 | tmp[1]);\t\t\t/* move.b tmp, d16(%a0) */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tbreak;\n+\tcase BPF_H:\n+\t\temit_16(ctx, 0x3140 | tmp[1]);\t\t\t/* move.w tmp, d16(%a0) */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tbreak;\n+\tcase BPF_W:\n+\t\temit_16(ctx, 0x2140 | tmp[1]);\t\t\t/* move.l tmp, d16(%a0) */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tbreak;\n+\tcase BPF_DW:\n+\t\temit_16(ctx, 0x203c | (tmp[0] \u003c\u003c 9));\t\t/* move.l #imm, tmp */\n+\t\temit_32(ctx, insn-\u003eimm \u003c 0 ? 0xffffffff : 0);\n+\n+\t\temit_16(ctx, 0x2140 | tmp[0]);\t\t\t/* move.l tmp, d16(%a0) */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\temit_16(ctx, 0x41e8);\t\t\t\t/* lea 4(%a0), %a0 */\n+\t\temit_16(ctx, 4);\n+\t\temit_16(ctx, 0x2140 | tmp[1]);\t\t\t/* move.l tmp, d16(%a0) */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t\tbreak;\n+\t}\n+}\n+\n+static int emit_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *src = bpf2m68k[insn-\u003esrc_reg];\n+\tconst s8 *tmp2 = bpf2m68k[TMP_REG_2];\n+\n+\tswitch (insn-\u003eimm) {\n+\tcase BPF_ADD:\n+\tcase BPF_ADD | BPF_FETCH:\n+\tcase BPF_AND:\n+\tcase BPF_AND | BPF_FETCH:\n+\tcase BPF_OR:\n+\tcase BPF_OR | BPF_FETCH:\n+\tcase BPF_XOR:\n+\tcase BPF_XOR | BPF_FETCH:\n+\tcase BPF_XCHG:\n+\tcase BPF_CMPXCHG:\n+\t\tbreak;\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n+\tif (is_stacked(dst[1])) {\n+\t\temit_16(ctx, 0x206e);\t\t\t\t/* movea.l d16(%fp), %a0 */\n+\t\temit_16(ctx, (u16)dst[1]);\n+\t} else {\n+\t\temit_16(ctx, 0x2040 | dst[1]);\t\t\t/* movea.l dst, %a0 */\n+\t}\n+\n+\tif (insn-\u003eoff) {\n+\t\temit_16(ctx, 0x41e8);\t\t\t\t/* lea d16(%a0), %a0 */\n+\t\temit_16(ctx, insn-\u003eoff);\n+\t}\n+\n+\tif (BPF_SIZE(insn-\u003ecode) == BPF_W) {\n+\t\ts8 s_lo = bpf_get_reg32(src[1], tmp2[1], ctx);\n+\n+\t\tif (insn-\u003eimm != BPF_CMPXCHG) {\n+\t\t\temit_16(ctx, 0x2f01);\t\t\t/* move.l d1, -(%sp) */\n+\t\t\temit_16(ctx, 0x2f00);\t\t\t/* move.l d0, -(%sp) */\n+\t\t}\n+\n+\t\temit_16(ctx, 0x2f00 | M68K_D0);\t\t\t/* move.l %d0, -(%sp) */\n+\t\temit_16(ctx, 0x2f3c);\t\t\t\t/* move.l #imm, -(%sp) */\n+\t\temit_32(ctx, insn-\u003eimm);\n+\t\temit_16(ctx, 0x2f00 | s_lo);\t\t\t/* move.l s_lo, -(%sp) */\n+\t\temit_16(ctx, 0x2f08);\t\t\t\t/* move.l %a0, -(%sp) */\n+\n+\t\temit_16(ctx, 0x207c);\t\t\t\t/* movea.l #func, %a0 */\n+\t\temit_32(ctx, (u32)jit_atomic32);\n+\t\temit_16(ctx, 0x4e90);\t\t\t\t/* jsr (%a0) */\n+\n+\t\temit_16(ctx, 0x4fef);\t\t\t\t/* lea 16(%sp), %sp */\n+\t\temit_16(ctx, 16);\n+\n+\t\tif (insn-\u003eimm == BPF_CMPXCHG) {\n+\t\t\temit_16(ctx, 0x7200);\t\t\t/* moveq #0, %d1 */\n+\t\t} else {\n+\t\t\tbool is_fetch = (insn-\u003eimm \u0026 BPF_FETCH) || insn-\u003eimm == BPF_XCHG;\n+\n+\t\t\tif (is_fetch)\n+\t\t\t\temit_16(ctx, 0x2600);\t\t/* move.l %d0, %d3 */\n+\n+\t\t\temit_16(ctx, 0x201f);\t\t\t/* move.l (%sp)+, d0 */\n+\t\t\temit_16(ctx, 0x221f);\t\t\t/* move.l (%sp)+, d1 */\n+\n+\t\t\tif (is_fetch) {\n+\t\t\t\tbpf_put_reg32(src[1], M68K_D3, ctx);\n+\t\t\t\temit_16(ctx, 0x7400);\t\t/* moveq #0, %d2 */\n+\t\t\t\tbpf_put_reg32(src[0], M68K_D2, ctx);\n+\t\t\t}\n+\t\t}\n+\n+\t} else if (BPF_SIZE(insn-\u003ecode) == BPF_DW) {\n+\t\ts8 s_lo = bpf_get_reg32(src[1], tmp2[1], ctx);\n+\t\ts8 s_hi = bpf_get_reg32(src[0], tmp2[0], ctx);\n+\n+\t\tif (insn-\u003eimm != BPF_CMPXCHG) {\n+\t\t\temit_16(ctx, 0x2f01);\t\t\t/* move.l d1, -(%sp) */\n+\t\t\temit_16(ctx, 0x2f00);\t\t\t/* move.l d0, -(%sp) */\n+\t\t}\n+\n+\t\temit_16(ctx, 0x2f00 | M68K_D0);\t\t\t/* move.l %d0, -(%sp) */\n+\t\temit_16(ctx, 0x2f00 | M68K_D1);\t\t\t/* move.l %d1, -(%sp) */\n+\t\temit_16(ctx, 0x2f3c);\t\t\t\t/* move.l #imm, -(%sp) */\n+\t\temit_32(ctx, insn-\u003eimm);\n+\t\temit_16(ctx, 0x2f00 | s_lo);\t\t\t/* move.l s_lo, -(%sp) */\n+\t\temit_16(ctx, 0x2f00 | s_hi);\t\t\t/* move.l s_hi, -(%sp) */\n+\t\temit_16(ctx, 0x2f08);\t\t\t\t/* move.l %a0, -(%sp) */\n+\n+\t\temit_16(ctx, 0x207c);\t\t\t\t/* movea.l #func, %a0 */\n+\t\temit_32(ctx, (u32)jit_atomic64);\n+\t\temit_16(ctx, 0x4e90);\t\t\t\t/* jsr (%a0) */\n+\n+\t\temit_16(ctx, 0x4fef);\t\t\t\t/* lea 24(%sp), %sp */\n+\t\temit_16(ctx, 24);\n+\n+\t\tif (insn-\u003eimm == BPF_CMPXCHG) {\n+\t\t\tif (CPU_IS_COLDFIRE) {\n+\t\t\t\temit_16(ctx, 0x2f00);\t\t/* move.l %d0, -(%sp) */\n+\t\t\t\temit_16(ctx, 0x2001);\t\t/* move.l %d1, %d0 */\n+\t\t\t\temit_16(ctx, 0x221f);\t\t/* move.l (%sp)+, %d1 */\n+\t\t\t} else {\n+\t\t\t\temit_16(ctx, 0xc141);\t\t/* exg %d0, %d1 */\n+\t\t\t}\n+\t\t} else {\n+\t\t\tbool is_fetch = (insn-\u003eimm \u0026 BPF_FETCH) || insn-\u003eimm == BPF_XCHG;\n+\n+\t\t\tif (is_fetch) {\n+\t\t\t\temit_16(ctx, 0x2600);\t\t/* move.l %d0, %d3 */\n+\t\t\t\temit_16(ctx, 0x2401);\t\t/* move.l %d1, %d2 */\n+\t\t\t}\n+\n+\t\t\temit_16(ctx, 0x201f);\t\t\t/* move.l (%sp)+, d0 */\n+\t\t\temit_16(ctx, 0x221f);\t\t\t/* move.l (%sp)+, d1 */\n+\n+\t\t\tif (is_fetch) {\n+\t\t\t\tbpf_put_reg32(src[1], M68K_D2, ctx);\n+\t\t\t\tbpf_put_reg32(src[0], M68K_D3, ctx);\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static void emit_tail_call(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 *r2 = bpf2m68k[BPF_REG_2];\n+\tconst s8 *r3 = bpf2m68k[BPF_REG_3];\n+\tint jmp_out_1, jmp_out_2, jmp_out_3;\n+\n+\tif (is_stacked(r2[1])) {\n+\t\temit_16(ctx, 0x206e);\t\t\t\t/* movea.l d16(%fp), %a0 */\n+\t\temit_16(ctx, (u16)r2[1]);\n+\t} else {\n+\t\temit_16(ctx, 0x2040 | r2[1]);\t\t\t/* movea.l r2, %a0 */\n+\t}\n+\n+\tif (is_stacked(r3[1])) {\n+\t\temit_16(ctx, 0x242e);\t\t\t\t/* move.l d16(%fp), %d2 */\n+\t\temit_16(ctx, (u16)r3[1]);\n+\t} else {\n+\t\temit_16(ctx, 0x2400 | r3[1]);\t\t\t/* move.l r3, %d2 */\n+\t}\n+\n+\temit_16(ctx, 0xb4a8);\t\t\t\t\t/* cmp.l d16(%a0), %d2 */\n+\temit_16(ctx, offsetof(struct bpf_array, map.max_entries));\n+\temit_16(ctx, 0x6400);\t\t\t\t\t/* bcc.w jmp_out_1 */\n+\tjmp_out_1 = ctx-\u003eidx;\n+\temit_16(ctx, 0);\n+\n+\temit_16(ctx, 0x262e);\t\t\t\t\t/* move.l d16(%fp), %d3 */\n+\temit_16(ctx, (u16)STACK_OFFSET(BPF_TC_LO));\n+\temit_16(ctx, 0x4a83);\t\t\t\t\t/* tst.l %d3 */\n+\temit_16(ctx, 0x6700);\t\t\t\t\t/* beq.w jmp_out_2 */\n+\tjmp_out_2 = ctx-\u003eidx;\n+\temit_16(ctx, 0);\n+\n+\temit_16(ctx, 0x5383);\t\t\t\t\t/* subq.l #1, %d3 */\n+\temit_16(ctx, 0x2d43);\t\t\t\t\t/* move.l %d3, d16(%fp) */\n+\temit_16(ctx, (u16)STACK_OFFSET(BPF_TC_LO));\n+\n+\temit_16(ctx, 0xd482);\t\t\t\t\t/* add.l %d2, %d2 */\n+\temit_16(ctx, 0xd482);\t\t\t\t\t/* add.l %d2, %d2 */\n+\temit_16(ctx, 0x43e8);\t\t\t\t\t/* lea d16(%a0), %a1 */\n+\temit_16(ctx, offsetof(struct bpf_array, ptrs));\n+\temit_16(ctx, 0xd3c2);\t\t\t\t\t/* adda.l %d2, %a1 */\n+\n+\temit_16(ctx, 0x2051);\t\t\t\t\t/* movea.l (%a1), %a0 */\n+\n+\temit_16(ctx, 0x2408);\t\t\t\t\t/* move.l %a0, %d2 */\n+\temit_16(ctx, 0x4a82);\t\t\t\t\t/* tst.l %d2 */\n+\temit_16(ctx, 0x6700);\t\t\t\t\t/* beq.w jmp_out_3 */\n+\tjmp_out_3 = ctx-\u003eidx;\n+\temit_16(ctx, 0);\n+\n+\temit_16(ctx, 0x2068);\t\t\t\t\t/* movea.l d16(%a0), %a0 */\n+\temit_16(ctx, offsetof(struct bpf_prog, bpf_func));\n+\n+\temit_16(ctx, 0x4ee8);\t\t\t\t\t/* jmp d16(%a0) */\n+\temit_16(ctx, CPU_IS_COLDFIRE ? 48 : 44);\n+\n+\tif (ctx-\u003etarget) {\n+\t\tctx-\u003etarget[jmp_out_1] = (ctx-\u003eidx - jmp_out_1) * 2;\n+\t\tctx-\u003etarget[jmp_out_2] = (ctx-\u003eidx - jmp_out_2) * 2;\n+\t\tctx-\u003etarget[jmp_out_3] = (ctx-\u003eidx - jmp_out_3) * 2;\n+\t}\n+}\n+\n+static int emit_jmp(const struct bpf_insn *insn, struct jit_ctx *ctx, int curr_i)\n+{\n+\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\tconst s8 *src = bpf2m68k[insn-\u003esrc_reg];\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\tconst s8 *tmp2 = bpf2m68k[TMP_REG_2];\n+\ts8 d_lo, d_hi = 0, s_lo, s_hi = 0;\n+\tbool is_jmp32 = BPF_CLASS(insn-\u003ecode) == BPF_JMP32;\n+\tu8 op = BPF_OP(insn-\u003ecode);\n+\tint target_insn;\n+\n+\tif (is_jmp32 \u0026\u0026 op == BPF_JA)\n+\t\ttarget_insn = curr_i + 1 + insn-\u003eimm;\n+\telse\n+\t\ttarget_insn = curr_i + 1 + insn-\u003eoff;\n+\n+\tif (target_insn \u003c 0 || target_insn \u003e ctx-\u003eprog-\u003elen)\n+\t\treturn -EOPNOTSUPP;\n+\n+\t#define EMIT_JMP32(op_base) \\\n+\t\tdo { \\\n+\t\t\tint disp = (ctx-\u003eoffsets[target_insn] - (ctx-\u003eidx + 1)) * 2; \\\n+\t\t\temit_16(ctx, (op_base) | 0x00ff); \\\n+\t\t\temit_32(ctx, disp); \\\n+\t\t} while (0)\n+\n+\tif (op == BPF_JA) {\n+\t\tEMIT_JMP32(0x6000);\t\t\t\t/* bra.l */\n+\t\treturn 0;\n+\t}\n+\n+\td_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);\n+\tif (!is_jmp32)\n+\t\td_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);\n+\n+\tif (BPF_SRC(insn-\u003ecode) == BPF_X) {\n+\t\ts_lo = bpf_get_reg32(src[1], tmp2[1], ctx);\n+\t\tif (!is_jmp32)\n+\t\t\ts_hi = bpf_get_reg32(src[0], tmp2[0], ctx);\n+\t} else {\n+\t\ts_lo = tmp2[1];\n+\t\temit_16(ctx, 0x203c | (s_lo \u003c\u003c 9));\t\t/* move.l #imm, s_lo */\n+\t\temit_32(ctx, insn-\u003eimm);\n+\t\tif (!is_jmp32) {\n+\t\t\ts_hi = tmp2[0];\n+\t\t\temit_16(ctx, 0x203c | (s_hi \u003c\u003c 9));\t/* move.l #imm, s_hi */\n+\t\t\temit_32(ctx, insn-\u003eimm \u003c 0 ? 0xffffffff : 0);\n+\t\t}\n+\t}\n+\n+\tif (op == BPF_JSET) {\n+\t\temit_16(ctx, 0x2000 | (tmp1[1] \u003c\u003c 9) | d_lo);\t/* move.l d_lo, tmp1_lo */\n+\t\temit_16(ctx, 0xc080 | (tmp1[1] \u003c\u003c 9) | s_lo);\t/* and.l s_lo, tmp1_lo */\n+\n+\t\tif (!is_jmp32) {\n+\t\t\tEMIT_JMP32(0x6600);\t\t\t/* bne.l */\n+\t\t\temit_16(ctx, 0x2000 | (tmp1[0] \u003c\u003c 9) | d_hi); /* move.l d_hi, tmp1_hi */\n+\t\t\temit_16(ctx, 0xc080 | (tmp1[0] \u003c\u003c 9) | s_hi); /* and.l s_hi, tmp1_hi */\n+\t\t}\n+\t\tEMIT_JMP32(0x6600);\t\t\t\t/* bne.l */\n+\t\treturn 0;\n+\t}\n+\n+\tif (is_jmp32) {\n+\t\temit_16(ctx, 0xb080 | (d_lo \u003c\u003c 9) | s_lo);\t/* cmp.l s_lo, d_lo */\n+\t\tswitch (op) {\n+\t\tcase BPF_JEQ:\n+\t\t\tEMIT_JMP32(0x6700);\t\t\t/* beq.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JNE:\n+\t\t\tEMIT_JMP32(0x6600);\t\t\t/* bne.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JGT:\n+\t\t\tEMIT_JMP32(0x6200);\t\t\t/* bhi.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JGE:\n+\t\t\tEMIT_JMP32(0x6400);\t\t\t/* bcc.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JLT:\n+\t\t\tEMIT_JMP32(0x6500);\t\t\t/* bcs.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JLE:\n+\t\t\tEMIT_JMP32(0x6300);\t\t\t/* bls.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JSGT:\n+\t\t\tEMIT_JMP32(0x6e00);\t\t\t/* bgt.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JSGE:\n+\t\t\tEMIT_JMP32(0x6c00);\t\t\t/* bge.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JSLT:\n+\t\t\tEMIT_JMP32(0x6d00);\t\t\t/* blt.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JSLE:\n+\t\t\tEMIT_JMP32(0x6f00);\t\t\t/* ble.l */\n+\t\t\tbreak;\n+\t\t}\n+\t} else {\n+\t\temit_16(ctx, 0xb080 | (d_hi \u003c\u003c 9) | s_hi);\t/* cmp.l s_hi, d_hi */\n+\n+\t\tswitch (op) {\n+\t\tcase BPF_JEQ:\n+\t\t\temit_16(ctx, 0x6608);\t\t\t/* bne.s .+8 */\n+\t\t\temit_16(ctx, 0xb080 | (d_lo \u003c\u003c 9) | s_lo); /* cmp.l s_lo, d_lo */\n+\t\t\tEMIT_JMP32(0x6700);\t\t\t/* beq.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JNE:\n+\t\t\tEMIT_JMP32(0x6600);\t\t\t/* bne.l */\n+\t\t\temit_16(ctx, 0xb080 | (d_lo \u003c\u003c 9) | s_lo); /* cmp.l s_lo, d_lo */\n+\t\t\tEMIT_JMP32(0x6600);\t\t\t/* bne.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JGT:\n+\t\t\tEMIT_JMP32(0x6200);\t\t\t/* bhi.l */\n+\t\t\temit_16(ctx, 0x6508);\t\t\t/* bcs.s .+8 */\n+\t\t\temit_16(ctx, 0xb080 | (d_lo \u003c\u003c 9) | s_lo); /* cmp.l s_lo, d_lo */\n+\t\t\tEMIT_JMP32(0x6200);\t\t\t/* bhi.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JGE:\n+\t\t\tEMIT_JMP32(0x6200);\t\t\t/* bhi.l */\n+\t\t\temit_16(ctx, 0x6508);\t\t\t/* bcs.s .+8 */\n+\t\t\temit_16(ctx, 0xb080 | (d_lo \u003c\u003c 9) | s_lo); /* cmp.l s_lo, d_lo */\n+\t\t\tEMIT_JMP32(0x6400);\t\t\t/* bcc.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JLT:\n+\t\t\tEMIT_JMP32(0x6500);\t\t\t/* bcs.l */\n+\t\t\temit_16(ctx, 0x6208);\t\t\t/* bhi.s .+8 */\n+\t\t\temit_16(ctx, 0xb080 | (d_lo \u003c\u003c 9) | s_lo); /* cmp.l s_lo, d_lo */\n+\t\t\tEMIT_JMP32(0x6500);\t\t\t/* bcs.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JLE:\n+\t\t\tEMIT_JMP32(0x6500);\t\t\t/* bcs.l */\n+\t\t\temit_16(ctx, 0x6208);\t\t\t/* bhi.s .+8 */\n+\t\t\temit_16(ctx, 0xb080 | (d_lo \u003c\u003c 9) | s_lo); /* cmp.l s_lo, d_lo */\n+\t\t\tEMIT_JMP32(0x6300);\t\t\t/* bls.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JSGT:\n+\t\t\tEMIT_JMP32(0x6e00);\t\t\t/* bgt.l */\n+\t\t\temit_16(ctx, 0x6d08);\t\t\t/* blt.s .+8 */\n+\t\t\temit_16(ctx, 0xb080 | (d_lo \u003c\u003c 9) | s_lo); /* cmp.l s_lo, d_lo */\n+\t\t\tEMIT_JMP32(0x6200);\t\t\t/* bhi.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JSGE:\n+\t\t\tEMIT_JMP32(0x6e00);\t\t\t/* bgt.l */\n+\t\t\temit_16(ctx, 0x6d08);\t\t\t/* blt.s .+8 */\n+\t\t\temit_16(ctx, 0xb080 | (d_lo \u003c\u003c 9) | s_lo); /* cmp.l s_lo, d_lo */\n+\t\t\tEMIT_JMP32(0x6400);\t\t\t/* bcc.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JSLT:\n+\t\t\tEMIT_JMP32(0x6d00);\t\t\t/* blt.l */\n+\t\t\temit_16(ctx, 0x6e08);\t\t\t/* bgt.s .+8 */\n+\t\t\temit_16(ctx, 0xb080 | (d_lo \u003c\u003c 9) | s_lo); /* cmp.l s_lo, d_lo */\n+\t\t\tEMIT_JMP32(0x6500);\t\t\t/* bcs.l */\n+\t\t\tbreak;\n+\t\tcase BPF_JSLE:\n+\t\t\tEMIT_JMP32(0x6d00);\t\t\t/* blt.l */\n+\t\t\temit_16(ctx, 0x6e08);\t\t\t/* bgt.s .+8 */\n+\t\t\temit_16(ctx, 0xb080 | (d_lo \u003c\u003c 9) | s_lo); /* cmp.l s_lo, d_lo */\n+\t\t\tEMIT_JMP32(0x6300);\t\t\t/* bls.l */\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\t#undef EMIT_JMP32\n+\treturn 0;\n+}\n+\n+static int emit_call(const struct bpf_insn *insn, struct jit_ctx *ctx)\n+{\n+\tconst s8 arg_regs[] = { BPF_REG_5, BPF_REG_4, BPF_REG_3, BPF_REG_2, BPF_REG_1 };\n+\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\tbool extra_pass = ctx-\u003eprog-\u003ejited;\n+\tu64 func_addr;\n+\tbool fixed;\n+\tint i, err;\n+\n+\terr = bpf_jit_get_func_addr(ctx-\u003eprog, insn, extra_pass, \u0026func_addr, \u0026fixed);\n+\tif (err)\n+\t\treturn err;\n+\n+\tfor (i = 0; i \u003c 5; i++) {\n+\t\tconst s8 *reg = bpf2m68k[arg_regs[i]];\n+\t\ts8 d_lo = bpf_get_reg32(reg[1], tmp1[1], ctx);\n+\t\ts8 d_hi = bpf_get_reg32(reg[0], tmp1[0], ctx);\n+\n+\t\temit_16(ctx, 0x2f00 | d_lo);\t\t\t/* move.l d_lo, -(%sp) */\n+\t\temit_16(ctx, 0x2f00 | d_hi);\t\t\t/* move.l d_hi, -(%sp) */\n+\t}\n+\n+\temit_16(ctx, 0x207c);\t\t\t\t\t/* movea.l #func_addr, %a0 */\n+\temit_32(ctx, (u32)func_addr);\n+\n+\temit_16(ctx, 0x4e90);\t\t\t\t\t/* jsr (%a0) */\n+\n+\temit_16(ctx, 0x4fef);\t\t\t\t\t/* lea 40(%sp), %sp */\n+\temit_16(ctx, 40);\n+\n+\tif (insn-\u003esrc_reg != BPF_PSEUDO_CALL) {\n+\t\tif (CPU_IS_COLDFIRE) {\n+\t\t\temit_16(ctx, 0x2f00);\t\t\t/* move.l %d0, -(%sp) */\n+\t\t\temit_16(ctx, 0x2001);\t\t\t/* move.l %d1, %d0 */\n+\t\t\temit_16(ctx, 0x221f);\t\t\t/* move.l (%sp)+, %d1 */\n+\t\t} else {\n+\t\t\temit_16(ctx, 0xc340);\t\t\t/* exg %d0, %d1 */\n+\t\t}\n+\t} else {\n+\t\temit_16(ctx, 0x2d48);\t\t\t\t/* move.l %a0, d16(%fp) */\n+\t\temit_16(ctx, (u16)STACK_OFFSET(BPF_R2_HI));\n+\t\temit_16(ctx, 0x2d49);\t\t\t\t/* move.l %a1, d16(%fp) */\n+\t\temit_16(ctx, (u16)STACK_OFFSET(BPF_R2_LO));\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static void build_prologue(struct jit_ctx *ctx)\n+{\n+\tint bpf_stack = ctx-\u003eprog-\u003eis_func ?\n+\t\t\tround_up(ctx-\u003eprog-\u003eaux-\u003estack_depth, 4) : MAX_BPF_STACK;\n+\tint total_stack = SCRATCH_SIZE + bpf_stack;\n+\tint i;\n+\n+\temit_16(ctx, 0x7021);\t\t\t\t\t/* moveq #33, %d0 */\n+\n+\temit_16(ctx, 0x4e56);\t\t\t\t\t/* link %a6, #-total_stack */\n+\temit_16(ctx, -total_stack);\n+\n+\tif (CPU_IS_COLDFIRE) {\n+\t\temit_16(ctx, 0x4fef);\t\t\t\t/* lea -16(%sp), %sp */\n+\t\temit_16(ctx, 0xfff0);\n+\t\temit_16(ctx, 0x48d7);\t\t\t\t/* movem.l d2-d5, (%sp) */\n+\t\temit_16(ctx, 0x003c);\n+\t} else {\n+\t\temit_16(ctx, 0x48e7);\t\t\t\t/* movem.l d2-d5, -(%sp) */\n+\t\temit_16(ctx, 0x3c00);\n+\t}\n+\n+\temit_16(ctx, 0x2d40);\t\t\t\t\t/* move.l %d0, off(%fp) */\n+\temit_16(ctx, (u16)STACK_OFFSET(BPF_TC_LO));\n+\n+\tif (ctx-\u003eprog-\u003eis_func) {\n+\t\tconst s8 arg_regs[] = { BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5 };\n+\n+\t\tfor (i = 0; i \u003c 5; i++) {\n+\t\t\tint offset = 8 + i * 8;\n+\t\t\tconst s8 *reg = bpf2m68k[arg_regs[i]];\n+\n+\t\t\temit_16(ctx, 0x202e); /* move.l offset(%fp), %d0 */\n+\t\t\temit_16(ctx, offset);\n+\t\t\tbpf_put_reg32(reg[0], M68K_D0, ctx);\n+\n+\t\t\temit_16(ctx, 0x202e); /* move.l offset+4(%fp), %d0 */\n+\t\t\temit_16(ctx, offset + 4);\n+\t\t\tbpf_put_reg32(reg[1], M68K_D0, ctx);\n+\t\t}\n+\t} else {\n+\t\temit_16(ctx, 0x202e);\t\t\t\t/* move.l 8(%fp), %d0 */\n+\t\temit_16(ctx, 8);\n+\t\tbpf_put_reg32(bpf2m68k[BPF_REG_1][1], M68K_D0, ctx);\n+\n+\t\temit_16(ctx, 0x7000 | (M68K_D0 \u003c\u003c 9));\t\t\t/* moveq #0, %d0 */\n+\t\tbpf_put_reg32(bpf2m68k[BPF_REG_1][0], M68K_D0, ctx);\n+\t}\n+\n+\temit_16(ctx, 0x41ee);\t\t\t\t\t/* lea -SCRATCH_SIZE(%fp), %a0 */\n+\temit_16(ctx, -SCRATCH_SIZE);\n+\temit_16(ctx, 0x2008);\t\t\t\t\t/* move.l %a0, %d0 */\n+\n+\tbpf_put_reg32(bpf2m68k[BPF_REG_10][1], M68K_D0, ctx);\n+\temit_16(ctx, 0x7000 | (M68K_D0 \u003c\u003c 9));\t\t\t/* moveq #0, %d0 */\n+\tbpf_put_reg32(bpf2m68k[BPF_REG_10][0], M68K_D0, ctx);\n+}\n+\n+static void build_epilogue(struct jit_ctx *ctx)\n+{\n+\tif (ctx-\u003eprog-\u003eis_func) {\n+\t\temit_16(ctx, 0x206e);\t\t\t\t/* movea.l d16(%fp), %a0 */\n+\t\temit_16(ctx, (u16)STACK_OFFSET(BPF_R2_HI));\n+\t\temit_16(ctx, 0x226e);\t\t\t\t/* movea.l d16(%fp), %a1 */\n+\t\temit_16(ctx, (u16)STACK_OFFSET(BPF_R2_LO));\n+\t}\n+\n+\tif (CPU_IS_COLDFIRE) {\n+\t\temit_16(ctx, 0x4cd7);\t\t\t\t/* movem.l (%sp), d2-d5 */\n+\t\temit_16(ctx, 0x003c);\n+\t\temit_16(ctx, 0x4fef);\t\t\t\t/* lea 16(%sp), %sp */\n+\t\temit_16(ctx, 0x0010);\n+\t} else {\n+\t\temit_16(ctx, 0x4cdf);\t\t\t\t/* movem.l (%sp)+, d2-d5 */\n+\t\temit_16(ctx, 0x003c);\n+\t}\n+\n+\temit_16(ctx, 0x4e5e);\t\t\t\t\t/* unlk %fp */\n+\temit_16(ctx, 0x4e75);\t\t\t\t\t/* rts */\n+}\n+\n+static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, int i)\n+{\n+\tu8 code = insn-\u003ecode;\n+\n+\tswitch (code) {\n+\tcase BPF_ALU | BPF_NEG:\n+\t\temit_alu32_neg(insn, ctx);\n+\t\tbreak;\n+\tcase BPF_ALU64 | BPF_NEG:\n+\t\temit_alu64_neg(insn, ctx);\n+\t\tbreak;\n+\n+\tcase BPF_ALU | BPF_MOV | BPF_X:\n+\tcase BPF_ALU | BPF_ADD | BPF_X:\n+\tcase BPF_ALU | BPF_SUB | BPF_X:\n+\tcase BPF_ALU | BPF_AND | BPF_X:\n+\tcase BPF_ALU | BPF_OR  | BPF_X:\n+\tcase BPF_ALU | BPF_XOR | BPF_X:\n+\tcase BPF_ALU | BPF_LSH | BPF_X:\n+\tcase BPF_ALU | BPF_RSH | BPF_X:\n+\tcase BPF_ALU | BPF_ARSH | BPF_X:\n+\t\temit_alu32_x(insn, ctx);\n+\t\tbreak;\n+\n+\tcase BPF_ALU | BPF_MOV | BPF_K:\n+\tcase BPF_ALU | BPF_ADD | BPF_K:\n+\tcase BPF_ALU | BPF_SUB | BPF_K:\n+\tcase BPF_ALU | BPF_AND | BPF_K:\n+\tcase BPF_ALU | BPF_OR  | BPF_K:\n+\tcase BPF_ALU | BPF_XOR | BPF_K:\n+\tcase BPF_ALU | BPF_LSH | BPF_K:\n+\tcase BPF_ALU | BPF_RSH | BPF_K:\n+\tcase BPF_ALU | BPF_ARSH | BPF_K:\n+\t\temit_alu32_k(insn, ctx);\n+\t\tbreak;\n+\n+\tcase BPF_ALU64 | BPF_MOV | BPF_X:\n+\tcase BPF_ALU64 | BPF_ADD | BPF_X:\n+\tcase BPF_ALU64 | BPF_SUB | BPF_X:\n+\tcase BPF_ALU64 | BPF_AND | BPF_X:\n+\tcase BPF_ALU64 | BPF_OR  | BPF_X:\n+\tcase BPF_ALU64 | BPF_XOR | BPF_X:\n+\t\temit_alu64_x(insn, ctx);\n+\t\tbreak;\n+\n+\tcase BPF_ALU64 | BPF_MOV | BPF_K:\n+\tcase BPF_ALU64 | BPF_ADD | BPF_K:\n+\tcase BPF_ALU64 | BPF_SUB | BPF_K:\n+\tcase BPF_ALU64 | BPF_AND | BPF_K:\n+\tcase BPF_ALU64 | BPF_OR  | BPF_K:\n+\tcase BPF_ALU64 | BPF_XOR | BPF_K:\n+\t\temit_alu64_k(insn, ctx);\n+\t\tbreak;\n+\n+\tcase BPF_ALU64 | BPF_LSH | BPF_X:\n+\tcase BPF_ALU64 | BPF_RSH | BPF_X:\n+\tcase BPF_ALU64 | BPF_ARSH | BPF_X:\n+\t\temit_alu64_shift(insn, ctx, false);\n+\t\tbreak;\n+\n+\tcase BPF_ALU64 | BPF_LSH | BPF_K:\n+\tcase BPF_ALU64 | BPF_RSH | BPF_K:\n+\tcase BPF_ALU64 | BPF_ARSH | BPF_K:\n+\t\temit_alu64_shift(insn, ctx, true);\n+\t\tbreak;\n+\n+\tcase BPF_ALU | BPF_MUL | BPF_X:\n+\tcase BPF_ALU | BPF_DIV | BPF_X:\n+\tcase BPF_ALU | BPF_MOD | BPF_X:\n+\tcase BPF_ALU | BPF_MUL | BPF_K:\n+\tcase BPF_ALU | BPF_DIV | BPF_K:\n+\tcase BPF_ALU | BPF_MOD | BPF_K:\n+\t\temit_math_call(insn, ctx, false);\n+\t\tbreak;\n+\n+\tcase BPF_ALU64 | BPF_MUL | BPF_X:\n+\tcase BPF_ALU64 | BPF_DIV | BPF_X:\n+\tcase BPF_ALU64 | BPF_MOD | BPF_X:\n+\tcase BPF_ALU64 | BPF_MUL | BPF_K:\n+\tcase BPF_ALU64 | BPF_DIV | BPF_K:\n+\tcase BPF_ALU64 | BPF_MOD | BPF_K:\n+\t\temit_math_call(insn, ctx, true);\n+\t\tbreak;\n+\n+\tcase BPF_ALU | BPF_END | BPF_TO_BE:\n+\tcase BPF_ALU | BPF_END | BPF_TO_LE:\n+\tcase BPF_ALU64 | BPF_END | BPF_TO_BE:\n+\tcase BPF_ALU64 | BPF_END | BPF_TO_LE:\n+\t\temit_bpf_end(insn, ctx);\n+\t\tbreak;\n+\n+\tcase BPF_LD | BPF_IMM | BPF_DW: {\n+\t\tconst struct bpf_insn *insn1 = insn + 1;\n+\t\tconst s8 *dst = bpf2m68k[insn-\u003edst_reg];\n+\t\tconst s8 *tmp1 = bpf2m68k[TMP_REG_1];\n+\t\ts8 d_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);\n+\t\ts8 d_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);\n+\n+\t\temit_16(ctx, 0x203c | (d_lo \u003c\u003c 9));\t\t\t/* move.l #imm, d_lo */\n+\t\temit_32(ctx, insn-\u003eimm);\n+\t\temit_16(ctx, 0x203c | (d_hi \u003c\u003c 9));\t\t\t/* move.l #imm, d_hi */\n+\t\temit_32(ctx, insn1-\u003eimm);\n+\n+\t\tbpf_put_reg32(dst[1], d_lo, ctx);\n+\t\tbpf_put_reg32(dst[0], d_hi, ctx);\n+\t\tbreak;\n+\t}\n+\n+\tcase BPF_LDX | BPF_MEM | BPF_B:\n+\tcase BPF_LDX | BPF_MEM | BPF_H:\n+\tcase BPF_LDX | BPF_MEM | BPF_W:\n+\tcase BPF_LDX | BPF_MEM | BPF_DW:\n+\tcase BPF_LDX | BPF_MEMSX | BPF_B:\n+\tcase BPF_LDX | BPF_MEMSX | BPF_H:\n+\tcase BPF_LDX | BPF_MEMSX | BPF_W:\n+\t\temit_ldx(insn, ctx);\n+\t\tbreak;\n+\n+\tcase BPF_STX | BPF_MEM | BPF_B:\n+\tcase BPF_STX | BPF_MEM | BPF_H:\n+\tcase BPF_STX | BPF_MEM | BPF_W:\n+\tcase BPF_STX | BPF_MEM | BPF_DW:\n+\t\temit_stx(insn, ctx);\n+\t\tbreak;\n+\n+\tcase BPF_ST | BPF_MEM | BPF_B:\n+\tcase BPF_ST | BPF_MEM | BPF_H:\n+\tcase BPF_ST | BPF_MEM | BPF_W:\n+\tcase BPF_ST | BPF_MEM | BPF_DW:\n+\t\temit_st(insn, ctx);\n+\t\tbreak;\n+\n+\tcase BPF_ST | BPF_NOSPEC:\n+\t\tbreak;\n+\n+\tcase BPF_STX | BPF_ATOMIC | BPF_W:\n+\tcase BPF_STX | BPF_ATOMIC | BPF_DW:\n+\t\treturn emit_atomic(insn, ctx);\n+\n+\tcase BPF_JMP | BPF_TAIL_CALL:\n+\t\temit_tail_call(insn, ctx);\n+\t\tbreak;\n+\n+\tcase BPF_JMP | BPF_JA:\n+\tcase BPF_JMP32 | BPF_JA:\n+\tcase BPF_JMP | BPF_JEQ | BPF_X:\n+\tcase BPF_JMP | BPF_JEQ | BPF_K:\n+\tcase BPF_JMP | BPF_JNE | BPF_X:\n+\tcase BPF_JMP | BPF_JNE | BPF_K:\n+\tcase BPF_JMP | BPF_JGT | BPF_X:\n+\tcase BPF_JMP | BPF_JGT | BPF_K:\n+\tcase BPF_JMP | BPF_JGE | BPF_X:\n+\tcase BPF_JMP | BPF_JGE | BPF_K:\n+\tcase BPF_JMP | BPF_JLT | BPF_X:\n+\tcase BPF_JMP | BPF_JLT | BPF_K:\n+\tcase BPF_JMP | BPF_JLE | BPF_X:\n+\tcase BPF_JMP | BPF_JLE | BPF_K:\n+\tcase BPF_JMP | BPF_JSGT | BPF_X:\n+\tcase BPF_JMP | BPF_JSGT | BPF_K:\n+\tcase BPF_JMP | BPF_JSGE | BPF_X:\n+\tcase BPF_JMP | BPF_JSGE | BPF_K:\n+\tcase BPF_JMP | BPF_JSLT | BPF_X:\n+\tcase BPF_JMP | BPF_JSLT | BPF_K:\n+\tcase BPF_JMP | BPF_JSLE | BPF_X:\n+\tcase BPF_JMP | BPF_JSLE | BPF_K:\n+\tcase BPF_JMP | BPF_JSET | BPF_X:\n+\tcase BPF_JMP | BPF_JSET | BPF_K:\n+\tcase BPF_JMP32 | BPF_JEQ | BPF_X:\n+\tcase BPF_JMP32 | BPF_JEQ | BPF_K:\n+\tcase BPF_JMP32 | BPF_JNE | BPF_X:\n+\tcase BPF_JMP32 | BPF_JNE | BPF_K:\n+\tcase BPF_JMP32 | BPF_JGT | BPF_X:\n+\tcase BPF_JMP32 | BPF_JGT | BPF_K:\n+\tcase BPF_JMP32 | BPF_JGE | BPF_X:\n+\tcase BPF_JMP32 | BPF_JGE | BPF_K:\n+\tcase BPF_JMP32 | BPF_JLT | BPF_X:\n+\tcase BPF_JMP32 | BPF_JLT | BPF_K:\n+\tcase BPF_JMP32 | BPF_JLE | BPF_X:\n+\tcase BPF_JMP32 | BPF_JLE | BPF_K:\n+\tcase BPF_JMP32 | BPF_JSGT | BPF_X:\n+\tcase BPF_JMP32 | BPF_JSGT | BPF_K:\n+\tcase BPF_JMP32 | BPF_JSGE | BPF_X:\n+\tcase BPF_JMP32 | BPF_JSGE | BPF_K:\n+\tcase BPF_JMP32 | BPF_JSLT | BPF_X:\n+\tcase BPF_JMP32 | BPF_JSLT | BPF_K:\n+\tcase BPF_JMP32 | BPF_JSLE | BPF_X:\n+\tcase BPF_JMP32 | BPF_JSLE | BPF_K:\n+\tcase BPF_JMP32 | BPF_JSET | BPF_X:\n+\tcase BPF_JMP32 | BPF_JSET | BPF_K:\n+\t\treturn emit_jmp(insn, ctx, i);\n+\n+\tcase BPF_JMP | BPF_CALL:\n+\t\treturn emit_call(insn, ctx);\n+\n+\tcase BPF_JMP | BPF_EXIT:\n+\t\tbuild_epilogue(ctx);\n+\t\tbreak;\n+\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int build_body(struct jit_ctx *ctx)\n+{\n+\tconst struct bpf_prog *prog = ctx-\u003eprog;\n+\tint i;\n+\n+\tfor (i = 0; i \u003c prog-\u003elen; i++) {\n+\t\tconst struct bpf_insn *insn = \u0026prog-\u003einsnsi[i];\n+\t\tint ret;\n+\n+\t\tif (!ctx-\u003etarget)\n+\t\t\tctx-\u003eoffsets[i] = ctx-\u003eidx;\n+\n+\t\tret = build_insn(insn, ctx, i);\n+\t\tif (ret \u003c 0)\n+\t\t\treturn ret;\n+\n+\t\tif (insn-\u003ecode == (BPF_LD | BPF_IMM | BPF_DW)) {\n+\t\t\ti++;\n+\t\t\tif (!ctx-\u003etarget)\n+\t\t\t\tctx-\u003eoffsets[i] = ctx-\u003eidx;\n+\t\t}\n+\t}\n+\n+\tif (!ctx-\u003etarget)\n+\t\tctx-\u003eoffsets[prog-\u003elen] = ctx-\u003eidx;\n+\n+\treturn 0;\n+}\n+\n+bool bpf_jit_needs_zext(void)\n+{\n+\treturn true;\n+}\n+\n+static void jit_fill_hole(void *area, unsigned int size)\n+{\n+\tu16 *ptr;\n+\n+\tfor (ptr = area; size \u003e= 2; size -= 2)\n+\t\t*ptr++ = 0x4afc;\n+}\n+\n+struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)\n+{\n+\tstruct bpf_binary_header *header = prog-\u003eaux-\u003ejit_data;\n+\tstruct jit_ctx ctx;\n+\tunsigned int image_size;\n+\tu8 *image_ptr;\n+\tbool extra_pass = prog-\u003ejited;\n+\n+\tif (!prog-\u003ejit_requested)\n+\t\treturn prog;\n+\n+\tif (prog-\u003ejited \u0026\u0026 !prog-\u003eaux-\u003efunc)\n+\t\treturn prog;\n+\n+\tmemset(\u0026ctx, 0, sizeof(ctx));\n+\tctx.prog = prog;\n+\n+\tctx.offsets = kvcalloc(prog-\u003elen + 1, sizeof(int), GFP_KERNEL);\n+\tif (!ctx.offsets)\n+\t\tgoto out_free_hdr;\n+\n+\tbuild_prologue(\u0026ctx);\n+\tif (build_body(\u0026ctx) \u003c 0)\n+\t\tgoto out_free_hdr;\n+\tbuild_epilogue(\u0026ctx);\n+\n+\tif (extra_pass) {\n+\t\timage_ptr = (u8 *)prog-\u003ebpf_func;\n+\t\timage_size = prog-\u003ejited_len;\n+\t} else {\n+\t\timage_size = ctx.idx * 2;\n+\t\theader = bpf_jit_binary_alloc(image_size, \u0026image_ptr, 2, jit_fill_hole);\n+\t\tif (!header)\n+\t\t\tgoto out_off;\n+\t\tprog-\u003eaux-\u003ejit_data = header;\n+\t}\n+\n+\tctx.target = (u16 *)image_ptr;\n+\tctx.idx = 0;\n+\n+\tbuild_prologue(\u0026ctx);\n+\tif (build_body(\u0026ctx) \u003c 0)\n+\t\tgoto out_free_hdr;\n+\tbuild_epilogue(\u0026ctx);\n+\n+\tflush_icache_range((u32)header, (u32)(ctx.target + ctx.idx));\n+\n+\tif (bpf_jit_enable \u003e 1)\n+\t\tbpf_jit_dump(prog-\u003elen, image_size, 2, ctx.target);\n+\n+\tif ((!prog-\u003eaux-\u003efunc || extra_pass) \u0026\u0026 bpf_jit_binary_lock_ro(header))\n+\t\tgoto out_free_hdr;\n+\n+\tprog-\u003ebpf_func = (void *)ctx.target;\n+\tprog-\u003ejited = 1;\n+\tprog-\u003ejited_len = image_size;\n+\tgoto out_off;\n+\n+out_free_hdr:\n+\tif (header) {\n+\t\tbpf_jit_binary_free(header);\n+\t\tprog-\u003eaux-\u003ejit_data = NULL;\n+\t\tprog-\u003ebpf_func = NULL;\n+\t\tprog-\u003ejited = 0;\n+\t\tprog-\u003ejited_len = 0;\n+\t}\n+out_off:\n+\tkvfree(ctx.offsets);\n+\treturn prog;\n+}\n"
}

2/1 2026/10/05 19:18 agent patch-evaluator
0m Model:
core

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch adds an eBPF JIT compiler for the m68k architecture under arch/m68k/ along with Documentation and MAINTAINERS entries. Because the target architecture is amd64, all modified code is exclusive to another architecture and unreachable.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.

================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.

- REACHABILITY IS THE PRIMARY GATE:
  Fuzzing can only discover bugs in code that can actually execute in standard virtualized
  environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
  If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
  regardless of whether it adds assertions or complex logic.

- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
  Patch authors routinely label changes as "cleanups", "refactorings", or state
  "No functional change intended". Do NOT take these claims at face value.
  Code refactorings that rearrange logic, introduce helper functions, or alter state management
  in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
  If reachable executable code is modified or refactored, it MUST be fuzzed.

- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
  When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
  BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
  Even if the author believes the invariant always holds, fuzzing is essential to verify whether
  an unusual sequence of operations can violate it.

================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:

- Non-kernel and non-executable changes:
  * Modifications to Documentation/, comments, or spelling fixes.
  * User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
    that do not affect the compiled kernel image (vmlinux) or kernel modules.
  * Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
    that do not alter control flow or data structures.
  * Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
  * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
    ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
  * Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
    physical PCI hot-unplug or manual sysfs driver unbinding.
  * Code paths exclusive to architectures other than the target architecture.

================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
  * Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
    BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
  * Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
  * Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
  * Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).

================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:

- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
  Do NOT list generic, ubiquitous functions called by almost every program in the corpus
  (including, but not limited to: general memory allocators and deallocators, page fault
  and trap handlers, or core synchronization primitives; this is not an exhaustive list).
  Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
  which severely dilutes fuzzing effort away from the actual changes.

- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
  List functions that specifically implement the logic being added or altered, or direct API entrypoints
  for the subsystem feature under review.

- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
  Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
  distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
  If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
  functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).

================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit 54e984b2d1eb23947dd44e227b5ba78369381572
Author: syz-cluster <triage@syzkaller.com>
Date:   Mon Oct 5 19:18:54 2026 +0000

    syz-cluster: applied patch under review

diff --git a/Documentation/features/core/eBPF-JIT/arch-support.txt b/Documentation/features/core/eBPF-JIT/arch-support.txt
index 83f77f55fc87b..dacb50aef0550 100644
--- a/Documentation/features/core/eBPF-JIT/arch-support.txt
+++ b/Documentation/features/core/eBPF-JIT/arch-support.txt
@@ -13,7 +13,7 @@
     |        csky: | TODO |
     |     hexagon: | TODO |
     |   loongarch: |  ok  |
-    |        m68k: | TODO |
+    |        m68k: |  ok  |
     |  microblaze: | TODO |
     |        mips: |  ok  |
     |       nios2: | TODO |
diff --git a/MAINTAINERS b/MAINTAINERS
index ac037cbd4e21b..a8ce1906a5da8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4848,6 +4848,12 @@ L:	bpf@vger.kernel.org
 S:	Maintained
 F:	arch/loongarch/net/
 
+BPF JIT for M68K
+M:	Kuan-Wei Chiu <visitorckw@gmail.com>
+L:	bpf@vger.kernel.org
+S:	Maintained
+F:	arch/m68k/net/
+
 BPF JIT for MIPS (32-BIT AND 64-BIT)
 M:	Johan Almbladh <johan.almbladh@anyfinetworks.com>
 M:	Paul Burton <paulburton@kernel.org>
diff --git a/arch/m68k/Kbuild b/arch/m68k/Kbuild
index 7762af9f6defe..058ad41a728c5 100644
--- a/arch/m68k/Kbuild
+++ b/arch/m68k/Kbuild
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-y				+= kernel/ mm/
+obj-y				+= kernel/ mm/ net/
 obj-$(CONFIG_Q40)		+= q40/
 obj-$(CONFIG_AMIGA)		+= amiga/
 obj-$(CONFIG_ATARI)		+= atari/
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 11835eb59d94d..f334fca80f3f2 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -31,6 +31,7 @@ config M68K
 	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ASM_MODVERSIONS
 	select HAVE_DEBUG_BUGVERBOSE
+	select HAVE_EBPF_JIT if MMU
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS if !CPU_HAS_NO_UNALIGNED
 	select HAVE_LD_DEAD_CODE_DATA_ELIMINATION
 	select HAVE_MOD_ARCH_SPECIFIC
diff --git a/arch/m68k/net/Makefile b/arch/m68k/net/Makefile
new file mode 100644
index 0000000000000..ec5b147633167
--- /dev/null
+++ b/arch/m68k/net/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o
diff --git a/arch/m68k/net/bpf_jit_comp.c b/arch/m68k/net/bpf_jit_comp.c
new file mode 100644
index 0000000000000..6c40d358acd42
--- /dev/null
+++ b/arch/m68k/net/bpf_jit_comp.c
@@ -0,0 +1,1840 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * BPF JIT compiler for m68k
+ *
+ * Copyright (C) 2026 Kuan-Wei Chiu <visitorckw@gmail.com>
+ */
+
+#include <linux/bpf.h>
+#include <linux/filter.h>
+#include <linux/irqflags.h>
+#include <linux/slab.h>
+#include <asm/cacheflush.h>
+#include <linux/math64.h>
+#include <linux/limits.h>
+
+#define STACK_OFFSET(k) (-4 - (4 * (k)))
+
+enum {
+	BPF_R1_HI, BPF_R1_LO,
+	BPF_R2_HI, BPF_R2_LO,
+	BPF_R3_HI, BPF_R3_LO,
+	BPF_R4_HI, BPF_R4_LO,
+	BPF_R5_HI, BPF_R5_LO,
+	BPF_R6_HI, BPF_R6_LO,
+	BPF_R7_HI, BPF_R7_LO,
+	BPF_R8_HI, BPF_R8_LO,
+	BPF_R9_HI, BPF_R9_LO,
+	BPF_R10_HI, BPF_R10_LO,
+	BPF_AX_HI, BPF_AX_LO,
+	BPF_TC_HI, BPF_TC_LO,
+	BPF_JIT_SCRATCH_REGS,
+};
+
+#define SCRATCH_SIZE (BPF_JIT_SCRATCH_REGS * 4)
+
+#define TMP_REG_1 14
+#define TMP_REG_2 15
+
+#define M68K_D0 0
+#define M68K_D1 1
+#define M68K_D2 2
+#define M68K_D3 3
+#define M68K_D4 4
+#define M68K_D5 5
+
+static const s8 bpf2m68k[16][2] = {
+	[BPF_REG_0]  = {M68K_D1, M68K_D0},
+	[BPF_REG_1]  = {STACK_OFFSET(BPF_R1_HI),  STACK_OFFSET(BPF_R1_LO)},
+	[BPF_REG_2]  = {STACK_OFFSET(BPF_R2_HI),  STACK_OFFSET(BPF_R2_LO)},
+	[BPF_REG_3]  = {STACK_OFFSET(BPF_R3_HI),  STACK_OFFSET(BPF_R3_LO)},
+	[BPF_REG_4]  = {STACK_OFFSET(BPF_R4_HI),  STACK_OFFSET(BPF_R4_LO)},
+	[BPF_REG_5]  = {STACK_OFFSET(BPF_R5_HI),  STACK_OFFSET(BPF_R5_LO)},
+	[BPF_REG_6]  = {STACK_OFFSET(BPF_R6_HI),  STACK_OFFSET(BPF_R6_LO)},
+	[BPF_REG_7]  = {STACK_OFFSET(BPF_R7_HI),  STACK_OFFSET(BPF_R7_LO)},
+	[BPF_REG_8]  = {STACK_OFFSET(BPF_R8_HI),  STACK_OFFSET(BPF_R8_LO)},
+	[BPF_REG_9]  = {STACK_OFFSET(BPF_R9_HI),  STACK_OFFSET(BPF_R9_LO)},
+	[BPF_REG_10] = {STACK_OFFSET(BPF_R10_HI), STACK_OFFSET(BPF_R10_LO)},
+	[BPF_REG_AX] = {STACK_OFFSET(BPF_AX_HI),  STACK_OFFSET(BPF_AX_LO)},
+	[TMP_REG_1]  = {M68K_D3, M68K_D2},
+	[TMP_REG_2]  = {M68K_D5, M68K_D4},
+};
+
+struct jit_ctx {
+	const struct bpf_prog *prog;
+	u16 *target;
+	unsigned int idx;
+	int *offsets;
+};
+
+static noinline u32 jit_mul32(u32 a, u32 b)
+{
+	return a * b;
+}
+
+static noinline u32 jit_div32(u32 a, u32 b)
+{
+	return b ? a / b : 0;
+}
+
+static noinline u32 jit_mod32(u32 a, u32 b)
+{
+	return b ? a % b : a;
+}
+
+static noinline s32 jit_sdiv32(s32 a, s32 b)
+{
+	if (b == 0)
+		return 0;
+	if (a == S32_MIN && b == -1)
+		return S32_MIN;
+	return a / b;
+}
+
+static noinline s32 jit_smod32(s32 a, s32 b)
+{
+	if (b == 0)
+		return a;
+	if (a == S32_MIN && b == -1)
+		return 0;
+	return a % b;
+}
+
+static noinline u64 jit_mul64(u64 a, u64 b)
+{
+	return a * b;
+}
+
+static noinline u64 jit_div64(u64 a, u64 b)
+{
+	return b ? div64_u64(a, b) : 0;
+}
+
+static noinline s64 jit_sdiv64(s64 a, s64 b)
+{
+	if (b == 0)
+		return 0;
+	if (a == S64_MIN && b == -1)
+		return S64_MIN;
+	return div64_s64(a, b);
+}
+
+static noinline u64 jit_mod64(u64 a, u64 b)
+{
+	u64 rem;
+
+	if (b == 0)
+		return a;
+	div64_u64_rem(a, b, &rem);
+	return rem;
+}
+
+static noinline s64 jit_smod64(s64 a, s64 b)
+{
+	if (b == 0)
+		return a;
+	if (a == S64_MIN && b == -1)
+		return 0;
+	return a - div64_s64(a, b) * b;
+}
+
+static u32 jit_atomic32(u32 *ptr, u32 val, u32 op, u32 cmp)
+{
+	unsigned long flags;
+	u32 old;
+
+	local_irq_save(flags);
+	old = *ptr;
+	switch (op) {
+	case BPF_ADD:
+	case BPF_ADD | BPF_FETCH:
+		*ptr += val;
+		break;
+	case BPF_AND:
+	case BPF_AND | BPF_FETCH:
+		*ptr &= val;
+		break;
+	case BPF_OR:
+	case BPF_OR | BPF_FETCH:
+		*ptr |= val;
+		break;
+	case BPF_XOR:
+	case BPF_XOR | BPF_FETCH:
+		*ptr ^= val;
+		break;
+	case BPF_XCHG:
+		*ptr = val;
+		break;
+	case BPF_CMPXCHG:
+		if (old == cmp)
+			*ptr = val;
+		break;
+	}
+	local_irq_restore(flags);
+
+	return old;
+}
+
+static u64 jit_atomic64(u32 *ptr, u32 val_hi, u32 val_lo, u32 op, u32 cmp_hi, u32 cmp_lo)
+{
+	unsigned long flags;
+	u64 old, val, cmp;
+	u64 *ptr64 = (u64 *)ptr;
+
+	val = ((u64)val_hi << 32) | val_lo;
+	cmp = ((u64)cmp_hi << 32) | cmp_lo;
+
+	local_irq_save(flags);
+	old = *ptr64;
+	switch (op) {
+	case BPF_ADD:
+	case BPF_ADD | BPF_FETCH:
+		*ptr64 += val;
+		break;
+	case BPF_AND:
+	case BPF_AND | BPF_FETCH:
+		*ptr64 &= val;
+		break;
+	case BPF_OR:
+	case BPF_OR | BPF_FETCH:
+		*ptr64 |= val;
+		break;
+	case BPF_XOR:
+	case BPF_XOR | BPF_FETCH:
+		*ptr64 ^= val;
+		break;
+	case BPF_XCHG:
+		*ptr64 = val;
+		break;
+	case BPF_CMPXCHG:
+		if (old == cmp)
+			*ptr64 = val;
+		break;
+	}
+	local_irq_restore(flags);
+
+	return old;
+}
+
+static inline void emit_16(struct jit_ctx *ctx, u16 inst)
+{
+	if (ctx->target)
+		ctx->target[ctx->idx] = inst;
+	ctx->idx++;
+}
+
+static inline void emit_32(struct jit_ctx *ctx, u32 val)
+{
+	emit_16(ctx, val >> 16);
+	emit_16(ctx, val & 0xffff);
+}
+
+static inline bool is_stacked(s8 reg)
+{
+	return reg < 0;
+}
+
+static s8 bpf_get_reg32(s8 bpf_reg, s8 tmp_reg, struct jit_ctx *ctx)
+{
+	if (is_stacked(bpf_reg)) {
+		emit_16(ctx, 0x202e | (tmp_reg << 9));		/* move.l d16(%fp), reg */
+		emit_16(ctx, (u16)bpf_reg);
+		return tmp_reg;
+	}
+	return bpf_reg;
+}
+
+static void bpf_put_reg32(s8 bpf_reg, s8 src_reg, struct jit_ctx *ctx)
+{
+	if (is_stacked(bpf_reg)) {
+		emit_16(ctx, 0x2d40 | src_reg);			/* move.l reg, d16(%fp) */
+		emit_16(ctx, (u16)bpf_reg);
+	} else if (bpf_reg != src_reg) {
+		emit_16(ctx, 0x2000 | (bpf_reg << 9) | src_reg); /* move.l src, dst */
+	}
+}
+
+static void emit_alu32_neg(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	s8 d_reg = bpf_get_reg32(dst[1], tmp1[1], ctx);
+
+	emit_16(ctx, 0x4480 | d_reg);				/* neg.l d_reg */
+
+	bpf_put_reg32(dst[1], d_reg, ctx);
+	emit_16(ctx, 0x7000 | (tmp1[0] << 9));			/* moveq #0, tmp1 */
+	bpf_put_reg32(dst[0], tmp1[0], ctx);
+}
+
+static void emit_alu64_neg(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	s8 d_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);
+	s8 d_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);
+
+	emit_16(ctx, 0x4480 | d_lo);				/* neg.l d_lo */
+	emit_16(ctx, 0x4080 | d_hi);				/* negx.l d_hi */
+
+	bpf_put_reg32(dst[1], d_lo, ctx);
+	bpf_put_reg32(dst[0], d_hi, ctx);
+}
+
+static void emit_alu32_x(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *src = bpf2m68k[insn->src_reg];
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	const s8 *tmp2 = bpf2m68k[TMP_REG_2];
+	s8 d_reg, s_reg;
+
+	d_reg = bpf_get_reg32(dst[1], tmp1[1], ctx);
+	s_reg = bpf_get_reg32(src[1], tmp2[1], ctx);
+
+	switch (BPF_OP(insn->code)) {
+	case BPF_MOV:
+		if (insn->off == 8 || insn->off == 16) {
+			if (d_reg != s_reg)
+				emit_16(ctx, 0x2000 | (d_reg << 9) | s_reg); /* move.l src, dst */
+			if (insn->off == 8)
+				emit_16(ctx, 0x49c0 | d_reg);	/* extb.l d_reg */
+			else
+				emit_16(ctx, 0x48c0 | d_reg);	/* ext.l d_reg */
+		} else {
+			if (d_reg != s_reg)
+				emit_16(ctx, 0x2000 | (d_reg << 9) | s_reg); /* move.l src, dst */
+		}
+		break;
+	case BPF_ADD:
+		emit_16(ctx, 0xd080 | (d_reg << 9) | s_reg);	/* add.l src, dst */
+		break;
+	case BPF_SUB:
+		emit_16(ctx, 0x9080 | (d_reg << 9) | s_reg);	/* sub.l src, dst */
+		break;
+	case BPF_AND:
+		emit_16(ctx, 0xc080 | (d_reg << 9) | s_reg);	/* and.l src, dst */
+		break;
+	case BPF_OR:
+		emit_16(ctx, 0x8080 | (d_reg << 9) | s_reg);	/* or.l src, dst */
+		break;
+	case BPF_XOR:
+		emit_16(ctx, 0xb180 | (s_reg << 9) | d_reg);	/* eor.l src, dst */
+		break;
+	case BPF_LSH:
+	case BPF_RSH:
+	case BPF_ARSH: {
+		s8 count_reg = tmp2[1];
+
+		if (s_reg != count_reg)
+			emit_16(ctx, 0x2000 | (count_reg << 9) | s_reg); /* move.l src, count */
+
+		emit_16(ctx, 0x0280 | count_reg);		/* andi.l #imm, count */
+		emit_32(ctx, 0x1f);
+
+		if (BPF_OP(insn->code) == BPF_LSH)
+			emit_16(ctx, 0xe1a8 | (count_reg << 9) | d_reg); /* lsl.l count, dst */
+		else if (BPF_OP(insn->code) == BPF_RSH)
+			emit_16(ctx, 0xe0a8 | (count_reg << 9) | d_reg); /* lsr.l count, dst */
+		else
+			emit_16(ctx, 0xe0a0 | (count_reg << 9) | d_reg); /* asr.l count, dst */
+		break;
+	}
+	}
+
+	bpf_put_reg32(dst[1], d_reg, ctx);
+	emit_16(ctx, 0x7000 | (tmp1[0] << 9));			/* moveq #0, tmp1 */
+	bpf_put_reg32(dst[0], tmp1[0], ctx);
+}
+
+static void emit_alu32_k(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	const s8 *tmp2 = bpf2m68k[TMP_REG_2];
+	s8 d_reg;
+	s32 imm = insn->imm;
+	bool is_moveq = (imm >= -128 && imm <= 127);
+
+	d_reg = bpf_get_reg32(dst[1], tmp1[1], ctx);
+
+	switch (BPF_OP(insn->code)) {
+	case BPF_MOV:
+		if (is_moveq) {
+			emit_16(ctx, 0x7000 | (d_reg << 9) | (imm & 0xff)); /* moveq #imm, dst */
+		} else {
+			emit_16(ctx, 0x203c | (d_reg << 9));		/* move.l #imm, dst */
+			emit_32(ctx, imm);
+		}
+		break;
+	case BPF_ADD:
+		if (is_moveq) {
+			emit_16(ctx, 0x7000 | (tmp2[1] << 9) | (imm & 0xff)); /* moveq #imm, tmp2 */
+			emit_16(ctx, 0xd080 | (d_reg << 9) | tmp2[1]);	/* add.l tmp2, dst */
+		} else {
+			emit_16(ctx, 0x0680 | d_reg);			/* addi.l #imm, dst */
+			emit_32(ctx, imm);
+		}
+		break;
+	case BPF_SUB:
+		if (is_moveq) {
+			emit_16(ctx, 0x7000 | (tmp2[1] << 9) | (imm & 0xff)); /* moveq #imm, tmp2 */
+			emit_16(ctx, 0x9080 | (d_reg << 9) | tmp2[1]);	/* sub.l tmp2, dst */
+		} else {
+			emit_16(ctx, 0x0480 | d_reg);			/* subi.l #imm, dst */
+			emit_32(ctx, imm);
+		}
+		break;
+	case BPF_AND:
+		if (is_moveq) {
+			emit_16(ctx, 0x7000 | (tmp2[1] << 9) | (imm & 0xff)); /* moveq #imm, tmp2 */
+			emit_16(ctx, 0xc080 | (d_reg << 9) | tmp2[1]);	/* and.l tmp2, dst */
+		} else {
+			emit_16(ctx, 0x0280 | d_reg);			/* andi.l #imm, dst */
+			emit_32(ctx, imm);
+		}
+		break;
+	case BPF_OR:
+		if (is_moveq) {
+			emit_16(ctx, 0x7000 | (tmp2[1] << 9) | (imm & 0xff)); /* moveq #imm, tmp2 */
+			emit_16(ctx, 0x8080 | (d_reg << 9) | tmp2[1]);	/* or.l tmp2, dst */
+		} else {
+			emit_16(ctx, 0x0080 | d_reg);			/* ori.l #imm, dst */
+			emit_32(ctx, imm);
+		}
+		break;
+	case BPF_XOR:
+		if (is_moveq) {
+			emit_16(ctx, 0x7000 | (tmp2[1] << 9) | (imm & 0xff)); /* moveq #imm, tmp2 */
+			emit_16(ctx, 0xb180 | (tmp2[1] << 9) | d_reg);	/* eor.l tmp2, dst */
+		} else {
+			emit_16(ctx, 0x0a80 | d_reg);			/* eori.l #imm, dst */
+			emit_32(ctx, imm);
+		}
+		break;
+	case BPF_LSH:
+	case BPF_RSH:
+	case BPF_ARSH:
+		emit_16(ctx, 0x7000 | (tmp2[1] << 9) | (imm & 0x1f));	/* moveq #imm, count */
+
+		if (BPF_OP(insn->code) == BPF_LSH)
+			emit_16(ctx, 0xe1a8 | (tmp2[1] << 9) | d_reg);	/* lsl.l count, dst */
+		else if (BPF_OP(insn->code) == BPF_RSH)
+			emit_16(ctx, 0xe0a8 | (tmp2[1] << 9) | d_reg);	/* lsr.l count, dst */
+		else
+			emit_16(ctx, 0xe0a0 | (tmp2[1] << 9) | d_reg);	/* asr.l count, dst */
+		break;
+	}
+
+	bpf_put_reg32(dst[1], d_reg, ctx);
+	emit_16(ctx, 0x7000 | (tmp1[0] << 9));				/* moveq #0, tmp1 */
+	bpf_put_reg32(dst[0], tmp1[0], ctx);
+}
+
+static void emit_alu64_x(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *src = bpf2m68k[insn->src_reg];
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	const s8 *tmp2 = bpf2m68k[TMP_REG_2];
+	s8 d_lo, d_hi, s_lo, s_hi;
+
+	d_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);
+	d_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);
+	s_lo = bpf_get_reg32(src[1], tmp2[1], ctx);
+	s_hi = bpf_get_reg32(src[0], tmp2[0], ctx);
+
+	switch (BPF_OP(insn->code)) {
+	case BPF_MOV:
+		if (insn->off == 8 || insn->off == 16 || insn->off == 32) {
+			if (d_lo != s_lo)
+				emit_16(ctx, 0x2000 | (d_lo << 9) | s_lo); /* move.l src, dst */
+
+			if (insn->off == 8)
+				emit_16(ctx, 0x49c0 | d_lo);		/* extb.l d_lo */
+			else if (insn->off == 16)
+				emit_16(ctx, 0x48c0 | d_lo);		/* ext.l d_lo */
+
+			emit_16(ctx, 0x4a80 | d_lo);			/* tst.l d_lo */
+			emit_16(ctx, 0x5bc0 | d_hi);			/* smi d_hi */
+			emit_16(ctx, 0x49c0 | d_hi);			/* extb.l d_hi */
+		} else {
+			if (d_lo != s_lo)
+				emit_16(ctx, 0x2000 | (d_lo << 9) | s_lo); /* move.l s_lo, d_lo */
+			if (d_hi != s_hi)
+				emit_16(ctx, 0x2000 | (d_hi << 9) | s_hi); /* move.l s_hi, d_hi */
+		}
+		break;
+	case BPF_ADD:
+		emit_16(ctx, 0xd080 | (d_lo << 9) | s_lo);		/* add.l s_lo, d_lo */
+		emit_16(ctx, 0xd180 | (d_hi << 9) | s_hi);		/* addx.l s_hi, d_hi */
+		break;
+	case BPF_SUB:
+		emit_16(ctx, 0x9080 | (d_lo << 9) | s_lo);		/* sub.l s_lo, d_lo */
+		emit_16(ctx, 0x9180 | (d_hi << 9) | s_hi);		/* subx.l s_hi, d_hi */
+		break;
+	case BPF_AND:
+		emit_16(ctx, 0xc080 | (d_lo << 9) | s_lo);		/* and.l s_lo, d_lo */
+		emit_16(ctx, 0xc080 | (d_hi << 9) | s_hi);		/* and.l s_hi, d_hi */
+		break;
+	case BPF_OR:
+		emit_16(ctx, 0x8080 | (d_lo << 9) | s_lo);		/* or.l s_lo, d_lo */
+		emit_16(ctx, 0x8080 | (d_hi << 9) | s_hi);		/* or.l s_hi, d_hi */
+		break;
+	case BPF_XOR:
+		emit_16(ctx, 0xb180 | (s_lo << 9) | d_lo);		/* eor.l s_lo, d_lo */
+		emit_16(ctx, 0xb180 | (s_hi << 9) | d_hi);		/* eor.l s_hi, d_hi */
+		break;
+	}
+
+	bpf_put_reg32(dst[1], d_lo, ctx);
+	bpf_put_reg32(dst[0], d_hi, ctx);
+}
+
+static void emit_alu64_k(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	const s8 *tmp2 = bpf2m68k[TMP_REG_2];
+	s8 d_lo, d_hi, s_lo, s_hi;
+	u32 imm_lo = insn->imm;
+	u32 imm_hi = insn->imm < 0 ? 0xffffffff : 0;
+
+	d_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);
+	d_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);
+
+	if (BPF_OP(insn->code) == BPF_MOV) {
+		emit_16(ctx, 0x203c | (d_lo << 9));			/* move.l #imm, d_lo */
+		emit_32(ctx, imm_lo);
+		emit_16(ctx, 0x203c | (d_hi << 9));			/* move.l #imm, d_hi */
+		emit_32(ctx, imm_hi);
+		bpf_put_reg32(dst[1], d_lo, ctx);
+		bpf_put_reg32(dst[0], d_hi, ctx);
+		return;
+	}
+
+	s_lo = tmp2[1];
+	s_hi = tmp2[0];
+
+	emit_16(ctx, 0x203c | (s_lo << 9));				/* move.l #imm, s_lo */
+	emit_32(ctx, imm_lo);
+	emit_16(ctx, 0x203c | (s_hi << 9));				/* move.l #imm, s_hi */
+	emit_32(ctx, imm_hi);
+
+	switch (BPF_OP(insn->code)) {
+	case BPF_ADD:
+		emit_16(ctx, 0xd080 | (d_lo << 9) | s_lo);		/* add.l s_lo, d_lo */
+		emit_16(ctx, 0xd180 | (d_hi << 9) | s_hi);		/* addx.l s_hi, d_hi */
+		break;
+	case BPF_SUB:
+		emit_16(ctx, 0x9080 | (d_lo << 9) | s_lo);		/* sub.l s_lo, d_lo */
+		emit_16(ctx, 0x9180 | (d_hi << 9) | s_hi);		/* subx.l s_hi, d_hi */
+		break;
+	case BPF_AND:
+		emit_16(ctx, 0xc080 | (d_lo << 9) | s_lo);		/* and.l s_lo, d_lo */
+		emit_16(ctx, 0xc080 | (d_hi << 9) | s_hi);		/* and.l s_hi, d_hi */
+		break;
+	case BPF_OR:
+		emit_16(ctx, 0x8080 | (d_lo << 9) | s_lo);		/* or.l s_lo, d_lo */
+		emit_16(ctx, 0x8080 | (d_hi << 9) | s_hi);		/* or.l s_hi, d_hi */
+		break;
+	case BPF_XOR:
+		emit_16(ctx, 0xb180 | (s_lo << 9) | d_lo);		/* eor.l s_lo, d_lo */
+		emit_16(ctx, 0xb180 | (s_hi << 9) | d_hi);		/* eor.l s_hi, d_hi */
+		break;
+	}
+
+	bpf_put_reg32(dst[1], d_lo, ctx);
+	bpf_put_reg32(dst[0], d_hi, ctx);
+}
+
+static inline void emit_lsh64(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)
+{
+	if (CPU_IS_COLDFIRE) {
+		emit_16(ctx, 0xd080 | (d_lo << 9) | d_lo);		/* add.l d_lo, d_lo */
+		emit_16(ctx, 0xd180 | (d_hi << 9) | d_hi);		/* addx.l d_hi, d_hi */
+	} else {
+		emit_16(ctx, 0xe388 | d_lo);				/* lsll #1, d_lo */
+		emit_16(ctx, 0xe390 | d_hi);				/* roxl.l #1, d_hi */
+	}
+}
+
+static inline void emit_rsh64(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)
+{
+	if (CPU_IS_COLDFIRE) {
+		emit_16(ctx, 0xe288 | d_lo);				/* lsr.l #1, d_lo */
+		emit_16(ctx, 0xe288 | d_hi);				/* lsr.l #1, d_hi */
+		emit_16(ctx, 0x6400);					/* bcc 1f */
+		emit_16(ctx, 0x0006);
+		emit_16(ctx, 0x08c0 | d_lo);				/* bset #31, d_lo */
+		emit_16(ctx, 0x001f);
+	} else {
+		emit_16(ctx, 0xe288 | d_hi);				/* lsrl #1, d_hi */
+		emit_16(ctx, 0xe290 | d_lo);				/* roxr.l #1, d_lo */
+	}
+}
+
+static inline void emit_arsh64(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)
+{
+	if (CPU_IS_COLDFIRE) {
+		emit_16(ctx, 0xe288 | d_lo);				/* lsr.l #1, d_lo */
+		emit_16(ctx, 0xe280 | d_hi);				/* asr.l #1, d_hi */
+		emit_16(ctx, 0x6400);					/* bcc 1f */
+		emit_16(ctx, 0x0006);
+		emit_16(ctx, 0x08c0 | d_lo);				/* bset #31, d_lo */
+		emit_16(ctx, 0x001f);
+	} else {
+		emit_16(ctx, 0xe280 | d_hi);				/* asrl #1, d_hi */
+		emit_16(ctx, 0xe290 | d_lo);				/* roxr.l #1, d_lo */
+	}
+}
+
+static void emit_alu64_shift(const struct bpf_insn *insn, struct jit_ctx *ctx, bool is_imm)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	const s8 *tmp2 = bpf2m68k[TMP_REG_2];
+	s8 d_lo, d_hi, count_reg;
+	int loop_start, done_idx;
+
+	d_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);
+	d_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);
+	count_reg = tmp2[1];
+
+	if (is_imm) {
+		emit_16(ctx, 0x203c | (count_reg << 9));		/* move.l #imm, count_reg */
+		emit_32(ctx, insn->imm);
+	} else {
+		const s8 *src = bpf2m68k[insn->src_reg];
+		s8 s_lo = bpf_get_reg32(src[1], tmp2[1], ctx);
+
+		if (count_reg != s_lo)
+			emit_16(ctx, 0x2000 | (count_reg << 9) | s_lo);	/* move.l s_lo, count_reg */
+	}
+
+	emit_16(ctx, 0x0280 | count_reg);			/* andi.l #0x3f, count_reg */
+	emit_32(ctx, 0x3f);
+
+	emit_16(ctx, 0x4a80 | count_reg);				/* tst.l count_reg */
+	emit_16(ctx, 0x6700);						/* beq.w done_idx */
+	done_idx = ctx->idx;
+	emit_16(ctx, 0);
+
+	loop_start = ctx->idx;
+
+	if (BPF_OP(insn->code) == BPF_LSH)
+		emit_lsh64(ctx, d_lo, d_hi);
+	else if (BPF_OP(insn->code) == BPF_RSH)
+		emit_rsh64(ctx, d_lo, d_hi);
+	else if (BPF_OP(insn->code) == BPF_ARSH)
+		emit_arsh64(ctx, d_lo, d_hi);
+
+	emit_16(ctx, 0x5380 | count_reg);				/* subq.l #1, count_reg */
+	emit_16(ctx, 0x6600);						/* bne.w loop_start */
+	emit_16(ctx, (loop_start - (int)ctx->idx) * 2);
+
+	if (ctx->target)
+		ctx->target[done_idx] = (ctx->idx - done_idx) * 2;
+
+	bpf_put_reg32(dst[1], d_lo, ctx);
+	bpf_put_reg32(dst[0], d_hi, ctx);
+}
+
+static inline void emit_to_le16(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)
+{
+	if (CPU_IS_COLDFIRE) {
+		emit_16(ctx, 0x71c0 | (d_lo << 9) | d_lo);		/* mvz.w d_lo, d_lo */
+		emit_16(ctx, 0x7180 | (d_hi << 9) | d_lo);		/* mvz.b d_lo, d_hi */
+		emit_16(ctx, 0xe088 | d_lo);				/* lsr.l #8, d_lo */
+		emit_16(ctx, 0xe188 | d_hi);				/* lsl.l #8, d_hi */
+		emit_16(ctx, 0x8080 | (d_lo << 9) | d_hi);		/* or.l d_hi, d_lo */
+	} else {
+		emit_16(ctx, 0x0280 | d_lo);				/* andi.l #0xffff, d_lo */
+		emit_32(ctx, 0xffff);
+		emit_16(ctx, 0xe058 | d_lo);				/* ror.w #8, d_lo */
+	}
+
+	emit_16(ctx, 0x7000 | (d_hi << 9));				/* moveq #0, d_hi */
+}
+
+static inline void emit_to_le32(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)
+{
+	if (CPU_IS_COLDFIRE) {
+		emit_16(ctx, 0x2f00 | d_lo);				/* move.l d_lo, -(%sp) */
+		emit_16(ctx, 0x4840 | d_lo);				/* swap d_lo */
+		emit_16(ctx, 0x71c0 | (d_lo << 9) | d_lo);		/* mvz.w d_lo, d_lo */
+		emit_16(ctx, 0x7180 | (d_hi << 9) | d_lo);		/* mvz.b d_lo, d_hi */
+		emit_16(ctx, 0xe088 | d_lo);				/* lsr.l #8, d_lo */
+		emit_16(ctx, 0xe188 | d_hi);				/* lsl.l #8, d_hi */
+		emit_16(ctx, 0x8080 | (d_hi << 9) | d_lo);		/* or.l d_lo, d_hi */
+		emit_16(ctx, 0x2017 | (d_lo << 9));			/* move.l (%sp), d_lo */
+		emit_16(ctx, 0x2e80 | d_hi);				/* move.l d_hi, (%sp) */
+		emit_16(ctx, 0x71c0 | (d_lo << 9) | d_lo);		/* mvz.w d_lo, d_lo */
+		emit_16(ctx, 0x7180 | (d_hi << 9) | d_lo);		/* mvz.b d_lo, d_hi */
+		emit_16(ctx, 0xe088 | d_lo);				/* lsr.l #8, d_lo */
+		emit_16(ctx, 0xe188 | d_hi);				/* lsl.l #8, d_hi */
+		emit_16(ctx, 0x8080 | (d_lo << 9) | d_hi);		/* or.l d_hi, d_lo */
+		emit_16(ctx, 0x4840 | d_lo);				/* swap d_lo */
+		emit_16(ctx, 0x809f | (d_lo << 9));			/* or.l (%sp)+, d_lo */
+	} else {
+		emit_16(ctx, 0xe058 | d_lo);				/* ror.w #8, d_lo */
+		emit_16(ctx, 0x4840 | d_lo);				/* swap d_lo */
+		emit_16(ctx, 0xe058 | d_lo);				/* ror.w #8, d_lo */
+	}
+
+	emit_16(ctx, 0x7000 | (d_hi << 9));				/* moveq #0, d_hi */
+}
+
+static inline void emit_to_le64(struct jit_ctx *ctx, s8 d_lo, s8 d_hi)
+{
+	if (CPU_IS_COLDFIRE) {
+		emit_16(ctx, 0x2f00 | d_lo);				/* move.l d_lo, -(%sp) */
+		emit_16(ctx, 0x2f00 | d_hi);				/* move.l d_hi, -(%sp) */
+
+		emit_16(ctx, 0x4840 | d_lo);				/* swap d_lo */
+		emit_16(ctx, 0x71c0 | (d_lo << 9) | d_lo);		/* mvz.w d_lo, d_lo */
+		emit_16(ctx, 0x7180 | (d_hi << 9) | d_lo);		/* mvz.b d_lo, d_hi */
+		emit_16(ctx, 0xe088 | d_lo);				/* lsr.l #8, d_lo */
+		emit_16(ctx, 0xe188 | d_hi);				/* lsl.l #8, d_hi */
+		emit_16(ctx, 0x8080 | (d_hi << 9) | d_lo);		/* or.l d_lo, d_hi */
+		emit_16(ctx, 0x202f | (d_lo << 9));			/* move.l 4(%sp), d_lo */
+		emit_16(ctx, 0x0004);
+		emit_16(ctx, 0x2f40 | d_hi);				/* move.l d_hi, 4(%sp) */
+		emit_16(ctx, 0x0004);
+		emit_16(ctx, 0x71c0 | (d_lo << 9) | d_lo);		/* mvz.w d_lo, d_lo */
+		emit_16(ctx, 0x7180 | (d_hi << 9) | d_lo);		/* mvz.b d_lo, d_hi */
+		emit_16(ctx, 0xe088 | d_lo);				/* lsr.l #8, d_lo */
+		emit_16(ctx, 0xe188 | d_hi);				/* lsl.l #8, d_hi */
+		emit_16(ctx, 0x8080 | (d_lo << 9) | d_hi);		/* or.l d_hi, d_lo */
+		emit_16(ctx, 0x4840 | d_lo);				/* swap d_lo */
+		emit_16(ctx, 0x81af | (d_lo << 9));			/* or.l d_lo, 4(%sp) */
+		emit_16(ctx, 0x0004);
+
+		emit_16(ctx, 0x2017 | (d_lo << 9));			/* move.l (%sp), d_lo */
+		emit_16(ctx, 0x4840 | d_lo);				/* swap d_lo */
+		emit_16(ctx, 0x71c0 | (d_lo << 9) | d_lo);		/* mvz.w d_lo, d_lo */
+		emit_16(ctx, 0x7180 | (d_hi << 9) | d_lo);		/* mvz.b d_lo, d_hi */
+		emit_16(ctx, 0xe088 | d_lo);				/* lsr.l #8, d_lo */
+		emit_16(ctx, 0xe188 | d_hi);				/* lsl.l #8, d_hi */
+		emit_16(ctx, 0x8080 | (d_hi << 9) | d_lo);		/* or.l d_lo, d_hi */
+		emit_16(ctx, 0x2017 | (d_lo << 9));			/* move.l (%sp), d_lo */
+		emit_16(ctx, 0x2e80 | d_hi);				/* move.l d_hi, (%sp) */
+		emit_16(ctx, 0x71c0 | (d_lo << 9) | d_lo);		/* mvz.w d_lo, d_lo */
+		emit_16(ctx, 0x7180 | (d_hi << 9) | d_lo);		/* mvz.b d_lo, d_hi */
+		emit_16(ctx, 0xe088 | d_lo);				/* lsr.l #8, d_lo */
+		emit_16(ctx, 0xe188 | d_hi);				/* lsl.l #8, d_hi */
+		emit_16(ctx, 0x8080 | (d_lo << 9) | d_hi);		/* or.l d_hi, d_lo */
+		emit_16(ctx, 0x4840 | d_lo);				/* swap d_lo */
+		emit_16(ctx, 0x809f | (d_lo << 9));			/* or.l (%sp)+, d_lo */
+
+		emit_16(ctx, 0x201f | (d_hi << 9));			/* move.l (%sp)+, d_hi */
+	} else {
+		emit_16(ctx, 0xe058 | d_lo);				/* ror.w #8, d_lo */
+		emit_16(ctx, 0x4840 | d_lo);				/* swap d_lo */
+		emit_16(ctx, 0xe058 | d_lo);				/* ror.w #8, d_lo */
+
+		emit_16(ctx, 0xe058 | d_hi);				/* ror.w #8, d_hi */
+		emit_16(ctx, 0x4840 | d_hi);				/* swap d_hi */
+		emit_16(ctx, 0xe058 | d_hi);				/* ror.w #8, d_hi */
+
+		emit_16(ctx, 0xc140 | (d_hi << 9) | d_lo);		/* exg d_lo, d_hi */
+	}
+}
+
+static void emit_bpf_end(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	s8 d_lo, d_hi;
+	bool to_le = BPF_SRC(insn->code) == BPF_TO_LE;
+	int imm = insn->imm;
+
+	d_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);
+	d_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);
+
+	if (to_le) {
+		switch (imm) {
+		case 16:
+			emit_to_le16(ctx, d_lo, d_hi);
+			break;
+		case 32:
+			emit_to_le32(ctx, d_lo, d_hi);
+			break;
+		case 64:
+			emit_to_le64(ctx, d_lo, d_hi);
+			break;
+		}
+	} else {
+		switch (imm) {
+		case 16:
+			emit_16(ctx, 0x0280 | d_lo);			/* andi.l #0xffff, d_lo */
+			emit_32(ctx, 0xffff);
+			emit_16(ctx, 0x7000 | (d_hi << 9));		/* moveq #0, d_hi */
+			break;
+		case 32:
+			emit_16(ctx, 0x7000 | (d_hi << 9));		/* moveq #0, d_hi */
+			break;
+		case 64:
+			break;
+		}
+	}
+
+	bpf_put_reg32(dst[1], d_lo, ctx);
+	bpf_put_reg32(dst[0], d_hi, ctx);
+}
+
+static void emit_math_call(const struct bpf_insn *insn, struct jit_ctx *ctx, bool is_64)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *src = bpf2m68k[insn->src_reg];
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	const s8 *tmp2 = bpf2m68k[TMP_REG_2];
+	s8 d_lo, d_hi, s_lo, s_hi = 0;
+	void *func = NULL;
+	u8 op = BPF_OP(insn->code);
+
+	d_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);
+	d_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);
+
+	if (BPF_SRC(insn->code) == BPF_X) {
+		s_lo = bpf_get_reg32(src[1], tmp2[1], ctx);
+		if (is_64)
+			s_hi = bpf_get_reg32(src[0], tmp2[0], ctx);
+	} else {
+		s_lo = tmp2[1];
+		emit_16(ctx, 0x203c | (s_lo << 9));			/* move.l #imm, s_lo */
+		emit_32(ctx, insn->imm);
+		if (is_64) {
+			s_hi = tmp2[0];
+			emit_16(ctx, 0x203c | (s_hi << 9));		/* move.l #imm, s_hi */
+			emit_32(ctx, insn->imm < 0 ? 0xffffffff : 0);
+		}
+	}
+
+	if (is_64) {
+		switch (op) {
+		case BPF_MUL:
+			func = (void *)jit_mul64;
+			break;
+		case BPF_DIV:
+			func = (void *)jit_div64;
+			break;
+		case BPF_MOD:
+			func = (void *)jit_mod64;
+			break;
+		}
+		if (BPF_CLASS(insn->code) == BPF_ALU64 && op == BPF_DIV && insn->off == 1)
+			func = (void *)jit_sdiv64;
+		if (BPF_CLASS(insn->code) == BPF_ALU64 && op == BPF_MOD && insn->off == 1)
+			func = (void *)jit_smod64;
+	} else {
+		switch (op) {
+		case BPF_MUL:
+			func = (void *)jit_mul32;
+			break;
+		case BPF_DIV:
+			func = (void *)jit_div32;
+			break;
+		case BPF_MOD:
+			func = (void *)jit_mod32;
+			break;
+		}
+		if (BPF_CLASS(insn->code) == BPF_ALU && op == BPF_DIV && insn->off == 1)
+			func = (void *)jit_sdiv32;
+		if (BPF_CLASS(insn->code) == BPF_ALU && op == BPF_MOD && insn->off == 1)
+			func = (void *)jit_smod32;
+	}
+
+	if (is_64) {
+		emit_16(ctx, 0x2f01);					/* move.l d1, -(%sp) */
+		emit_16(ctx, 0x2f00);					/* move.l d0, -(%sp) */
+
+		emit_16(ctx, 0x2f00 | s_lo);				/* move.l s_lo, -(%sp) */
+		emit_16(ctx, 0x2f00 | s_hi);				/* move.l s_hi, -(%sp) */
+		emit_16(ctx, 0x2f00 | d_lo);				/* move.l d_lo, -(%sp) */
+		emit_16(ctx, 0x2f00 | d_hi);				/* move.l d_hi, -(%sp) */
+
+		emit_16(ctx, 0x207c);					/* movea.l #func, %a0 */
+		emit_32(ctx, (u32)func);
+		emit_16(ctx, 0x4e90);					/* jsr (%a0) */
+
+		emit_16(ctx, 0x4fef);					/* lea 16(%sp), %sp */
+		emit_16(ctx, 16);
+
+		emit_16(ctx, 0x2601);					/* move.l %d1, %d3 */
+		emit_16(ctx, 0x2400);					/* move.l %d0, %d2 */
+
+		emit_16(ctx, 0x201f);					/* move.l (%sp)+, d0 */
+		emit_16(ctx, 0x221f);					/* move.l (%sp)+, d1 */
+	} else {
+		emit_16(ctx, 0x2f01);					/* move.l d1, -(%sp) */
+		emit_16(ctx, 0x2f00);					/* move.l d0, -(%sp) */
+
+		emit_16(ctx, 0x2f00 | s_lo);				/* move.l s_lo, -(%sp) */
+		emit_16(ctx, 0x2f00 | d_lo);				/* move.l d_lo, -(%sp) */
+
+		emit_16(ctx, 0x207c);					/* movea.l #func, %a0 */
+		emit_32(ctx, (u32)func);
+		emit_16(ctx, 0x4e90);					/* jsr (%a0) */
+
+		emit_16(ctx, 0x4fef);					/* lea 8(%sp), %sp */
+		emit_16(ctx, 8);
+
+		emit_16(ctx, 0x2600);					/* move.l %d0, %d3 */
+		emit_16(ctx, 0x7400);					/* moveq #0, %d2 */
+
+		emit_16(ctx, 0x201f);					/* move.l (%sp)+, d0 */
+		emit_16(ctx, 0x221f);					/* move.l (%sp)+, d1 */
+	}
+
+	bpf_put_reg32(dst[1], M68K_D3, ctx);
+	bpf_put_reg32(dst[0], M68K_D2, ctx);
+}
+
+static void emit_ldx(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *src = bpf2m68k[insn->src_reg];
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	s8 d_lo, d_hi;
+	bool is_mem_sx = BPF_MODE(insn->code) == BPF_MEMSX;
+
+	if (is_stacked(src[1])) {
+		emit_16(ctx, 0x206e);				/* movea.l d16(%fp), %a0 */
+		emit_16(ctx, (u16)src[1]);
+	} else {
+		emit_16(ctx, 0x2040 | src[1]);			/* movea.l src, %a0 */
+	}
+
+	d_lo = is_stacked(dst[1]) ? tmp1[1] : dst[1];
+	d_hi = is_stacked(dst[0]) ? tmp1[0] : dst[0];
+
+	switch (BPF_SIZE(insn->code)) {
+	case BPF_B:
+		if (!is_mem_sx)
+			emit_16(ctx, 0x7000 | (d_lo << 9));	/* moveq #0, d_lo */
+		emit_16(ctx, 0x1028 | (d_lo << 9));		/* move.b d16(%a0), d_lo */
+		emit_16(ctx, insn->off);
+		if (is_mem_sx)
+			emit_16(ctx, 0x49c0 | d_lo);	/* extb.l d_lo */
+		break;
+	case BPF_H:
+		if (!is_mem_sx)
+			emit_16(ctx, 0x7000 | (d_lo << 9));	/* moveq #0, d_lo */
+		emit_16(ctx, 0x3028 | (d_lo << 9));		/* move.w d16(%a0), d_lo */
+		emit_16(ctx, insn->off);
+		if (is_mem_sx)
+			emit_16(ctx, 0x48c0 | d_lo);	/* ext.l d_lo */
+		break;
+	case BPF_W:
+		emit_16(ctx, 0x2028 | (d_lo << 9));		/* move.l d16(%a0), d_lo */
+		emit_16(ctx, insn->off);
+		break;
+	case BPF_DW:
+		emit_16(ctx, 0x2028 | (d_hi << 9));		/* move.l d16(%a0), d_hi */
+		emit_16(ctx, insn->off);
+		emit_16(ctx, 0x41e8);				/* lea 4(%a0), %a0 */
+		emit_16(ctx, 4);
+		emit_16(ctx, 0x2028 | (d_lo << 9));		/* move.l d16(%a0), d_lo */
+		emit_16(ctx, insn->off);
+		break;
+	}
+
+	if (BPF_SIZE(insn->code) != BPF_DW) {
+		if (is_mem_sx) {
+			emit_16(ctx, 0x4a80 | d_lo);			/* tst.l d_lo */
+			emit_16(ctx, 0x5bc0 | d_hi);			/* smi d_hi */
+			emit_16(ctx, 0x49c0 | d_hi);			/* extb.l d_hi */
+		} else {
+			emit_16(ctx, 0x7000 | (d_hi << 9));	/* moveq #0, d_hi */
+		}
+	}
+
+	bpf_put_reg32(dst[1], d_lo, ctx);
+	bpf_put_reg32(dst[0], d_hi, ctx);
+}
+
+static void emit_stx(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *src = bpf2m68k[insn->src_reg];
+	const s8 *tmp2 = bpf2m68k[TMP_REG_2];
+	s8 s_lo, s_hi;
+
+	if (is_stacked(dst[1])) {
+		emit_16(ctx, 0x206e);				/* movea.l d16(%fp), %a0 */
+		emit_16(ctx, (u16)dst[1]);
+	} else {
+		emit_16(ctx, 0x2040 | dst[1]);			/* movea.l dst, %a0 */
+	}
+
+	s_lo = bpf_get_reg32(src[1], tmp2[1], ctx);
+
+	switch (BPF_SIZE(insn->code)) {
+	case BPF_B:
+		emit_16(ctx, 0x1140 | s_lo);			/* move.b s_lo, d16(%a0) */
+		emit_16(ctx, insn->off);
+		break;
+	case BPF_H:
+		emit_16(ctx, 0x3140 | s_lo);			/* move.w s_lo, d16(%a0) */
+		emit_16(ctx, insn->off);
+		break;
+	case BPF_W:
+		emit_16(ctx, 0x2140 | s_lo);			/* move.l s_lo, d16(%a0) */
+		emit_16(ctx, insn->off);
+		break;
+	case BPF_DW:
+		s_hi = bpf_get_reg32(src[0], tmp2[0], ctx);
+		emit_16(ctx, 0x2140 | s_hi);			/* move.l s_hi, d16(%a0) */
+		emit_16(ctx, insn->off);
+		emit_16(ctx, 0x41e8);				/* lea 4(%a0), %a0 */
+		emit_16(ctx, 4);
+		emit_16(ctx, 0x2140 | s_lo);			/* move.l s_lo, d16(%a0) */
+		emit_16(ctx, insn->off);
+		break;
+	}
+}
+
+static void emit_st(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *tmp = bpf2m68k[TMP_REG_1];
+
+	if (is_stacked(dst[1])) {
+		emit_16(ctx, 0x206e);				/* movea.l d16(%fp), %a0 */
+		emit_16(ctx, (u16)dst[1]);
+	} else {
+		emit_16(ctx, 0x2040 | dst[1]);			/* movea.l dst, %a0 */
+	}
+
+	emit_16(ctx, 0x203c | (tmp[1] << 9));			/* move.l #imm, tmp */
+	emit_32(ctx, insn->imm);
+
+	switch (BPF_SIZE(insn->code)) {
+	case BPF_B:
+		emit_16(ctx, 0x1140 | tmp[1]);			/* move.b tmp, d16(%a0) */
+		emit_16(ctx, insn->off);
+		break;
+	case BPF_H:
+		emit_16(ctx, 0x3140 | tmp[1]);			/* move.w tmp, d16(%a0) */
+		emit_16(ctx, insn->off);
+		break;
+	case BPF_W:
+		emit_16(ctx, 0x2140 | tmp[1]);			/* move.l tmp, d16(%a0) */
+		emit_16(ctx, insn->off);
+		break;
+	case BPF_DW:
+		emit_16(ctx, 0x203c | (tmp[0] << 9));		/* move.l #imm, tmp */
+		emit_32(ctx, insn->imm < 0 ? 0xffffffff : 0);
+
+		emit_16(ctx, 0x2140 | tmp[0]);			/* move.l tmp, d16(%a0) */
+		emit_16(ctx, insn->off);
+		emit_16(ctx, 0x41e8);				/* lea 4(%a0), %a0 */
+		emit_16(ctx, 4);
+		emit_16(ctx, 0x2140 | tmp[1]);			/* move.l tmp, d16(%a0) */
+		emit_16(ctx, insn->off);
+		break;
+	}
+}
+
+static int emit_atomic(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *src = bpf2m68k[insn->src_reg];
+	const s8 *tmp2 = bpf2m68k[TMP_REG_2];
+
+	switch (insn->imm) {
+	case BPF_ADD:
+	case BPF_ADD | BPF_FETCH:
+	case BPF_AND:
+	case BPF_AND | BPF_FETCH:
+	case BPF_OR:
+	case BPF_OR | BPF_FETCH:
+	case BPF_XOR:
+	case BPF_XOR | BPF_FETCH:
+	case BPF_XCHG:
+	case BPF_CMPXCHG:
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	if (is_stacked(dst[1])) {
+		emit_16(ctx, 0x206e);				/* movea.l d16(%fp), %a0 */
+		emit_16(ctx, (u16)dst[1]);
+	} else {
+		emit_16(ctx, 0x2040 | dst[1]);			/* movea.l dst, %a0 */
+	}
+
+	if (insn->off) {
+		emit_16(ctx, 0x41e8);				/* lea d16(%a0), %a0 */
+		emit_16(ctx, insn->off);
+	}
+
+	if (BPF_SIZE(insn->code) == BPF_W) {
+		s8 s_lo = bpf_get_reg32(src[1], tmp2[1], ctx);
+
+		if (insn->imm != BPF_CMPXCHG) {
+			emit_16(ctx, 0x2f01);			/* move.l d1, -(%sp) */
+			emit_16(ctx, 0x2f00);			/* move.l d0, -(%sp) */
+		}
+
+		emit_16(ctx, 0x2f00 | M68K_D0);			/* move.l %d0, -(%sp) */
+		emit_16(ctx, 0x2f3c);				/* move.l #imm, -(%sp) */
+		emit_32(ctx, insn->imm);
+		emit_16(ctx, 0x2f00 | s_lo);			/* move.l s_lo, -(%sp) */
+		emit_16(ctx, 0x2f08);				/* move.l %a0, -(%sp) */
+
+		emit_16(ctx, 0x207c);				/* movea.l #func, %a0 */
+		emit_32(ctx, (u32)jit_atomic32);
+		emit_16(ctx, 0x4e90);				/* jsr (%a0) */
+
+		emit_16(ctx, 0x4fef);				/* lea 16(%sp), %sp */
+		emit_16(ctx, 16);
+
+		if (insn->imm == BPF_CMPXCHG) {
+			emit_16(ctx, 0x7200);			/* moveq #0, %d1 */
+		} else {
+			bool is_fetch = (insn->imm & BPF_FETCH) || insn->imm == BPF_XCHG;
+
+			if (is_fetch)
+				emit_16(ctx, 0x2600);		/* move.l %d0, %d3 */
+
+			emit_16(ctx, 0x201f);			/* move.l (%sp)+, d0 */
+			emit_16(ctx, 0x221f);			/* move.l (%sp)+, d1 */
+
+			if (is_fetch) {
+				bpf_put_reg32(src[1], M68K_D3, ctx);
+				emit_16(ctx, 0x7400);		/* moveq #0, %d2 */
+				bpf_put_reg32(src[0], M68K_D2, ctx);
+			}
+		}
+
+	} else if (BPF_SIZE(insn->code) == BPF_DW) {
+		s8 s_lo = bpf_get_reg32(src[1], tmp2[1], ctx);
+		s8 s_hi = bpf_get_reg32(src[0], tmp2[0], ctx);
+
+		if (insn->imm != BPF_CMPXCHG) {
+			emit_16(ctx, 0x2f01);			/* move.l d1, -(%sp) */
+			emit_16(ctx, 0x2f00);			/* move.l d0, -(%sp) */
+		}
+
+		emit_16(ctx, 0x2f00 | M68K_D0);			/* move.l %d0, -(%sp) */
+		emit_16(ctx, 0x2f00 | M68K_D1);			/* move.l %d1, -(%sp) */
+		emit_16(ctx, 0x2f3c);				/* move.l #imm, -(%sp) */
+		emit_32(ctx, insn->imm);
+		emit_16(ctx, 0x2f00 | s_lo);			/* move.l s_lo, -(%sp) */
+		emit_16(ctx, 0x2f00 | s_hi);			/* move.l s_hi, -(%sp) */
+		emit_16(ctx, 0x2f08);				/* move.l %a0, -(%sp) */
+
+		emit_16(ctx, 0x207c);				/* movea.l #func, %a0 */
+		emit_32(ctx, (u32)jit_atomic64);
+		emit_16(ctx, 0x4e90);				/* jsr (%a0) */
+
+		emit_16(ctx, 0x4fef);				/* lea 24(%sp), %sp */
+		emit_16(ctx, 24);
+
+		if (insn->imm == BPF_CMPXCHG) {
+			if (CPU_IS_COLDFIRE) {
+				emit_16(ctx, 0x2f00);		/* move.l %d0, -(%sp) */
+				emit_16(ctx, 0x2001);		/* move.l %d1, %d0 */
+				emit_16(ctx, 0x221f);		/* move.l (%sp)+, %d1 */
+			} else {
+				emit_16(ctx, 0xc141);		/* exg %d0, %d1 */
+			}
+		} else {
+			bool is_fetch = (insn->imm & BPF_FETCH) || insn->imm == BPF_XCHG;
+
+			if (is_fetch) {
+				emit_16(ctx, 0x2600);		/* move.l %d0, %d3 */
+				emit_16(ctx, 0x2401);		/* move.l %d1, %d2 */
+			}
+
+			emit_16(ctx, 0x201f);			/* move.l (%sp)+, d0 */
+			emit_16(ctx, 0x221f);			/* move.l (%sp)+, d1 */
+
+			if (is_fetch) {
+				bpf_put_reg32(src[1], M68K_D2, ctx);
+				bpf_put_reg32(src[0], M68K_D3, ctx);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static void emit_tail_call(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 *r2 = bpf2m68k[BPF_REG_2];
+	const s8 *r3 = bpf2m68k[BPF_REG_3];
+	int jmp_out_1, jmp_out_2, jmp_out_3;
+
+	if (is_stacked(r2[1])) {
+		emit_16(ctx, 0x206e);				/* movea.l d16(%fp), %a0 */
+		emit_16(ctx, (u16)r2[1]);
+	} else {
+		emit_16(ctx, 0x2040 | r2[1]);			/* movea.l r2, %a0 */
+	}
+
+	if (is_stacked(r3[1])) {
+		emit_16(ctx, 0x242e);				/* move.l d16(%fp), %d2 */
+		emit_16(ctx, (u16)r3[1]);
+	} else {
+		emit_16(ctx, 0x2400 | r3[1]);			/* move.l r3, %d2 */
+	}
+
+	emit_16(ctx, 0xb4a8);					/* cmp.l d16(%a0), %d2 */
+	emit_16(ctx, offsetof(struct bpf_array, map.max_entries));
+	emit_16(ctx, 0x6400);					/* bcc.w jmp_out_1 */
+	jmp_out_1 = ctx->idx;
+	emit_16(ctx, 0);
+
+	emit_16(ctx, 0x262e);					/* move.l d16(%fp), %d3 */
+	emit_16(ctx, (u16)STACK_OFFSET(BPF_TC_LO));
+	emit_16(ctx, 0x4a83);					/* tst.l %d3 */
+	emit_16(ctx, 0x6700);					/* beq.w jmp_out_2 */
+	jmp_out_2 = ctx->idx;
+	emit_16(ctx, 0);
+
+	emit_16(ctx, 0x5383);					/* subq.l #1, %d3 */
+	emit_16(ctx, 0x2d43);					/* move.l %d3, d16(%fp) */
+	emit_16(ctx, (u16)STACK_OFFSET(BPF_TC_LO));
+
+	emit_16(ctx, 0xd482);					/* add.l %d2, %d2 */
+	emit_16(ctx, 0xd482);					/* add.l %d2, %d2 */
+	emit_16(ctx, 0x43e8);					/* lea d16(%a0), %a1 */
+	emit_16(ctx, offsetof(struct bpf_array, ptrs));
+	emit_16(ctx, 0xd3c2);					/* adda.l %d2, %a1 */
+
+	emit_16(ctx, 0x2051);					/* movea.l (%a1), %a0 */
+
+	emit_16(ctx, 0x2408);					/* move.l %a0, %d2 */
+	emit_16(ctx, 0x4a82);					/* tst.l %d2 */
+	emit_16(ctx, 0x6700);					/* beq.w jmp_out_3 */
+	jmp_out_3 = ctx->idx;
+	emit_16(ctx, 0);
+
+	emit_16(ctx, 0x2068);					/* movea.l d16(%a0), %a0 */
+	emit_16(ctx, offsetof(struct bpf_prog, bpf_func));
+
+	emit_16(ctx, 0x4ee8);					/* jmp d16(%a0) */
+	emit_16(ctx, CPU_IS_COLDFIRE ? 48 : 44);
+
+	if (ctx->target) {
+		ctx->target[jmp_out_1] = (ctx->idx - jmp_out_1) * 2;
+		ctx->target[jmp_out_2] = (ctx->idx - jmp_out_2) * 2;
+		ctx->target[jmp_out_3] = (ctx->idx - jmp_out_3) * 2;
+	}
+}
+
+static int emit_jmp(const struct bpf_insn *insn, struct jit_ctx *ctx, int curr_i)
+{
+	const s8 *dst = bpf2m68k[insn->dst_reg];
+	const s8 *src = bpf2m68k[insn->src_reg];
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	const s8 *tmp2 = bpf2m68k[TMP_REG_2];
+	s8 d_lo, d_hi = 0, s_lo, s_hi = 0;
+	bool is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32;
+	u8 op = BPF_OP(insn->code);
+	int target_insn;
+
+	if (is_jmp32 && op == BPF_JA)
+		target_insn = curr_i + 1 + insn->imm;
+	else
+		target_insn = curr_i + 1 + insn->off;
+
+	if (target_insn < 0 || target_insn > ctx->prog->len)
+		return -EOPNOTSUPP;
+
+	#define EMIT_JMP32(op_base) \
+		do { \
+			int disp = (ctx->offsets[target_insn] - (ctx->idx + 1)) * 2; \
+			emit_16(ctx, (op_base) | 0x00ff); \
+			emit_32(ctx, disp); \
+		} while (0)
+
+	if (op == BPF_JA) {
+		EMIT_JMP32(0x6000);				/* bra.l */
+		return 0;
+	}
+
+	d_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);
+	if (!is_jmp32)
+		d_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);
+
+	if (BPF_SRC(insn->code) == BPF_X) {
+		s_lo = bpf_get_reg32(src[1], tmp2[1], ctx);
+		if (!is_jmp32)
+			s_hi = bpf_get_reg32(src[0], tmp2[0], ctx);
+	} else {
+		s_lo = tmp2[1];
+		emit_16(ctx, 0x203c | (s_lo << 9));		/* move.l #imm, s_lo */
+		emit_32(ctx, insn->imm);
+		if (!is_jmp32) {
+			s_hi = tmp2[0];
+			emit_16(ctx, 0x203c | (s_hi << 9));	/* move.l #imm, s_hi */
+			emit_32(ctx, insn->imm < 0 ? 0xffffffff : 0);
+		}
+	}
+
+	if (op == BPF_JSET) {
+		emit_16(ctx, 0x2000 | (tmp1[1] << 9) | d_lo);	/* move.l d_lo, tmp1_lo */
+		emit_16(ctx, 0xc080 | (tmp1[1] << 9) | s_lo);	/* and.l s_lo, tmp1_lo */
+
+		if (!is_jmp32) {
+			EMIT_JMP32(0x6600);			/* bne.l */
+			emit_16(ctx, 0x2000 | (tmp1[0] << 9) | d_hi); /* move.l d_hi, tmp1_hi */
+			emit_16(ctx, 0xc080 | (tmp1[0] << 9) | s_hi); /* and.l s_hi, tmp1_hi */
+		}
+		EMIT_JMP32(0x6600);				/* bne.l */
+		return 0;
+	}
+
+	if (is_jmp32) {
+		emit_16(ctx, 0xb080 | (d_lo << 9) | s_lo);	/* cmp.l s_lo, d_lo */
+		switch (op) {
+		case BPF_JEQ:
+			EMIT_JMP32(0x6700);			/* beq.l */
+			break;
+		case BPF_JNE:
+			EMIT_JMP32(0x6600);			/* bne.l */
+			break;
+		case BPF_JGT:
+			EMIT_JMP32(0x6200);			/* bhi.l */
+			break;
+		case BPF_JGE:
+			EMIT_JMP32(0x6400);			/* bcc.l */
+			break;
+		case BPF_JLT:
+			EMIT_JMP32(0x6500);			/* bcs.l */
+			break;
+		case BPF_JLE:
+			EMIT_JMP32(0x6300);			/* bls.l */
+			break;
+		case BPF_JSGT:
+			EMIT_JMP32(0x6e00);			/* bgt.l */
+			break;
+		case BPF_JSGE:
+			EMIT_JMP32(0x6c00);			/* bge.l */
+			break;
+		case BPF_JSLT:
+			EMIT_JMP32(0x6d00);			/* blt.l */
+			break;
+		case BPF_JSLE:
+			EMIT_JMP32(0x6f00);			/* ble.l */
+			break;
+		}
+	} else {
+		emit_16(ctx, 0xb080 | (d_hi << 9) | s_hi);	/* cmp.l s_hi, d_hi */
+
+		switch (op) {
+		case BPF_JEQ:
+			emit_16(ctx, 0x6608);			/* bne.s .+8 */
+			emit_16(ctx, 0xb080 | (d_lo << 9) | s_lo); /* cmp.l s_lo, d_lo */
+			EMIT_JMP32(0x6700);			/* beq.l */
+			break;
+		case BPF_JNE:
+			EMIT_JMP32(0x6600);			/* bne.l */
+			emit_16(ctx, 0xb080 | (d_lo << 9) | s_lo); /* cmp.l s_lo, d_lo */
+			EMIT_JMP32(0x6600);			/* bne.l */
+			break;
+		case BPF_JGT:
+			EMIT_JMP32(0x6200);			/* bhi.l */
+			emit_16(ctx, 0x6508);			/* bcs.s .+8 */
+			emit_16(ctx, 0xb080 | (d_lo << 9) | s_lo); /* cmp.l s_lo, d_lo */
+			EMIT_JMP32(0x6200);			/* bhi.l */
+			break;
+		case BPF_JGE:
+			EMIT_JMP32(0x6200);			/* bhi.l */
+			emit_16(ctx, 0x6508);			/* bcs.s .+8 */
+			emit_16(ctx, 0xb080 | (d_lo << 9) | s_lo); /* cmp.l s_lo, d_lo */
+			EMIT_JMP32(0x6400);			/* bcc.l */
+			break;
+		case BPF_JLT:
+			EMIT_JMP32(0x6500);			/* bcs.l */
+			emit_16(ctx, 0x6208);			/* bhi.s .+8 */
+			emit_16(ctx, 0xb080 | (d_lo << 9) | s_lo); /* cmp.l s_lo, d_lo */
+			EMIT_JMP32(0x6500);			/* bcs.l */
+			break;
+		case BPF_JLE:
+			EMIT_JMP32(0x6500);			/* bcs.l */
+			emit_16(ctx, 0x6208);			/* bhi.s .+8 */
+			emit_16(ctx, 0xb080 | (d_lo << 9) | s_lo); /* cmp.l s_lo, d_lo */
+			EMIT_JMP32(0x6300);			/* bls.l */
+			break;
+		case BPF_JSGT:
+			EMIT_JMP32(0x6e00);			/* bgt.l */
+			emit_16(ctx, 0x6d08);			/* blt.s .+8 */
+			emit_16(ctx, 0xb080 | (d_lo << 9) | s_lo); /* cmp.l s_lo, d_lo */
+			EMIT_JMP32(0x6200);			/* bhi.l */
+			break;
+		case BPF_JSGE:
+			EMIT_JMP32(0x6e00);			/* bgt.l */
+			emit_16(ctx, 0x6d08);			/* blt.s .+8 */
+			emit_16(ctx, 0xb080 | (d_lo << 9) | s_lo); /* cmp.l s_lo, d_lo */
+			EMIT_JMP32(0x6400);			/* bcc.l */
+			break;
+		case BPF_JSLT:
+			EMIT_JMP32(0x6d00);			/* blt.l */
+			emit_16(ctx, 0x6e08);			/* bgt.s .+8 */
+			emit_16(ctx, 0xb080 | (d_lo << 9) | s_lo); /* cmp.l s_lo, d_lo */
+			EMIT_JMP32(0x6500);			/* bcs.l */
+			break;
+		case BPF_JSLE:
+			EMIT_JMP32(0x6d00);			/* blt.l */
+			emit_16(ctx, 0x6e08);			/* bgt.s .+8 */
+			emit_16(ctx, 0xb080 | (d_lo << 9) | s_lo); /* cmp.l s_lo, d_lo */
+			EMIT_JMP32(0x6300);			/* bls.l */
+			break;
+		}
+	}
+	#undef EMIT_JMP32
+	return 0;
+}
+
+static int emit_call(const struct bpf_insn *insn, struct jit_ctx *ctx)
+{
+	const s8 arg_regs[] = { BPF_REG_5, BPF_REG_4, BPF_REG_3, BPF_REG_2, BPF_REG_1 };
+	const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+	bool extra_pass = ctx->prog->jited;
+	u64 func_addr;
+	bool fixed;
+	int i, err;
+
+	err = bpf_jit_get_func_addr(ctx->prog, insn, extra_pass, &func_addr, &fixed);
+	if (err)
+		return err;
+
+	for (i = 0; i < 5; i++) {
+		const s8 *reg = bpf2m68k[arg_regs[i]];
+		s8 d_lo = bpf_get_reg32(reg[1], tmp1[1], ctx);
+		s8 d_hi = bpf_get_reg32(reg[0], tmp1[0], ctx);
+
+		emit_16(ctx, 0x2f00 | d_lo);			/* move.l d_lo, -(%sp) */
+		emit_16(ctx, 0x2f00 | d_hi);			/* move.l d_hi, -(%sp) */
+	}
+
+	emit_16(ctx, 0x207c);					/* movea.l #func_addr, %a0 */
+	emit_32(ctx, (u32)func_addr);
+
+	emit_16(ctx, 0x4e90);					/* jsr (%a0) */
+
+	emit_16(ctx, 0x4fef);					/* lea 40(%sp), %sp */
+	emit_16(ctx, 40);
+
+	if (insn->src_reg != BPF_PSEUDO_CALL) {
+		if (CPU_IS_COLDFIRE) {
+			emit_16(ctx, 0x2f00);			/* move.l %d0, -(%sp) */
+			emit_16(ctx, 0x2001);			/* move.l %d1, %d0 */
+			emit_16(ctx, 0x221f);			/* move.l (%sp)+, %d1 */
+		} else {
+			emit_16(ctx, 0xc340);			/* exg %d0, %d1 */
+		}
+	} else {
+		emit_16(ctx, 0x2d48);				/* move.l %a0, d16(%fp) */
+		emit_16(ctx, (u16)STACK_OFFSET(BPF_R2_HI));
+		emit_16(ctx, 0x2d49);				/* move.l %a1, d16(%fp) */
+		emit_16(ctx, (u16)STACK_OFFSET(BPF_R2_LO));
+	}
+
+	return 0;
+}
+
+static void build_prologue(struct jit_ctx *ctx)
+{
+	int bpf_stack = ctx->prog->is_func ?
+			round_up(ctx->prog->aux->stack_depth, 4) : MAX_BPF_STACK;
+	int total_stack = SCRATCH_SIZE + bpf_stack;
+	int i;
+
+	emit_16(ctx, 0x7021);					/* moveq #33, %d0 */
+
+	emit_16(ctx, 0x4e56);					/* link %a6, #-total_stack */
+	emit_16(ctx, -total_stack);
+
+	if (CPU_IS_COLDFIRE) {
+		emit_16(ctx, 0x4fef);				/* lea -16(%sp), %sp */
+		emit_16(ctx, 0xfff0);
+		emit_16(ctx, 0x48d7);				/* movem.l d2-d5, (%sp) */
+		emit_16(ctx, 0x003c);
+	} else {
+		emit_16(ctx, 0x48e7);				/* movem.l d2-d5, -(%sp) */
+		emit_16(ctx, 0x3c00);
+	}
+
+	emit_16(ctx, 0x2d40);					/* move.l %d0, off(%fp) */
+	emit_16(ctx, (u16)STACK_OFFSET(BPF_TC_LO));
+
+	if (ctx->prog->is_func) {
+		const s8 arg_regs[] = { BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5 };
+
+		for (i = 0; i < 5; i++) {
+			int offset = 8 + i * 8;
+			const s8 *reg = bpf2m68k[arg_regs[i]];
+
+			emit_16(ctx, 0x202e); /* move.l offset(%fp), %d0 */
+			emit_16(ctx, offset);
+			bpf_put_reg32(reg[0], M68K_D0, ctx);
+
+			emit_16(ctx, 0x202e); /* move.l offset+4(%fp), %d0 */
+			emit_16(ctx, offset + 4);
+			bpf_put_reg32(reg[1], M68K_D0, ctx);
+		}
+	} else {
+		emit_16(ctx, 0x202e);				/* move.l 8(%fp), %d0 */
+		emit_16(ctx, 8);
+		bpf_put_reg32(bpf2m68k[BPF_REG_1][1], M68K_D0, ctx);
+
+		emit_16(ctx, 0x7000 | (M68K_D0 << 9));			/* moveq #0, %d0 */
+		bpf_put_reg32(bpf2m68k[BPF_REG_1][0], M68K_D0, ctx);
+	}
+
+	emit_16(ctx, 0x41ee);					/* lea -SCRATCH_SIZE(%fp), %a0 */
+	emit_16(ctx, -SCRATCH_SIZE);
+	emit_16(ctx, 0x2008);					/* move.l %a0, %d0 */
+
+	bpf_put_reg32(bpf2m68k[BPF_REG_10][1], M68K_D0, ctx);
+	emit_16(ctx, 0x7000 | (M68K_D0 << 9));			/* moveq #0, %d0 */
+	bpf_put_reg32(bpf2m68k[BPF_REG_10][0], M68K_D0, ctx);
+}
+
+static void build_epilogue(struct jit_ctx *ctx)
+{
+	if (ctx->prog->is_func) {
+		emit_16(ctx, 0x206e);				/* movea.l d16(%fp), %a0 */
+		emit_16(ctx, (u16)STACK_OFFSET(BPF_R2_HI));
+		emit_16(ctx, 0x226e);				/* movea.l d16(%fp), %a1 */
+		emit_16(ctx, (u16)STACK_OFFSET(BPF_R2_LO));
+	}
+
+	if (CPU_IS_COLDFIRE) {
+		emit_16(ctx, 0x4cd7);				/* movem.l (%sp), d2-d5 */
+		emit_16(ctx, 0x003c);
+		emit_16(ctx, 0x4fef);				/* lea 16(%sp), %sp */
+		emit_16(ctx, 0x0010);
+	} else {
+		emit_16(ctx, 0x4cdf);				/* movem.l (%sp)+, d2-d5 */
+		emit_16(ctx, 0x003c);
+	}
+
+	emit_16(ctx, 0x4e5e);					/* unlk %fp */
+	emit_16(ctx, 0x4e75);					/* rts */
+}
+
+static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, int i)
+{
+	u8 code = insn->code;
+
+	switch (code) {
+	case BPF_ALU | BPF_NEG:
+		emit_alu32_neg(insn, ctx);
+		break;
+	case BPF_ALU64 | BPF_NEG:
+		emit_alu64_neg(insn, ctx);
+		break;
+
+	case BPF_ALU | BPF_MOV | BPF_X:
+	case BPF_ALU | BPF_ADD | BPF_X:
+	case BPF_ALU | BPF_SUB | BPF_X:
+	case BPF_ALU | BPF_AND | BPF_X:
+	case BPF_ALU | BPF_OR  | BPF_X:
+	case BPF_ALU | BPF_XOR | BPF_X:
+	case BPF_ALU | BPF_LSH | BPF_X:
+	case BPF_ALU | BPF_RSH | BPF_X:
+	case BPF_ALU | BPF_ARSH | BPF_X:
+		emit_alu32_x(insn, ctx);
+		break;
+
+	case BPF_ALU | BPF_MOV | BPF_K:
+	case BPF_ALU | BPF_ADD | BPF_K:
+	case BPF_ALU | BPF_SUB | BPF_K:
+	case BPF_ALU | BPF_AND | BPF_K:
+	case BPF_ALU | BPF_OR  | BPF_K:
+	case BPF_ALU | BPF_XOR | BPF_K:
+	case BPF_ALU | BPF_LSH | BPF_K:
+	case BPF_ALU | BPF_RSH | BPF_K:
+	case BPF_ALU | BPF_ARSH | BPF_K:
+		emit_alu32_k(insn, ctx);
+		break;
+
+	case BPF_ALU64 | BPF_MOV | BPF_X:
+	case BPF_ALU64 | BPF_ADD | BPF_X:
+	case BPF_ALU64 | BPF_SUB | BPF_X:
+	case BPF_ALU64 | BPF_AND | BPF_X:
+	case BPF_ALU64 | BPF_OR  | BPF_X:
+	case BPF_ALU64 | BPF_XOR | BPF_X:
+		emit_alu64_x(insn, ctx);
+		break;
+
+	case BPF_ALU64 | BPF_MOV | BPF_K:
+	case BPF_ALU64 | BPF_ADD | BPF_K:
+	case BPF_ALU64 | BPF_SUB | BPF_K:
+	case BPF_ALU64 | BPF_AND | BPF_K:
+	case BPF_ALU64 | BPF_OR  | BPF_K:
+	case BPF_ALU64 | BPF_XOR | BPF_K:
+		emit_alu64_k(insn, ctx);
+		break;
+
+	case BPF_ALU64 | BPF_LSH | BPF_X:
+	case BPF_ALU64 | BPF_RSH | BPF_X:
+	case BPF_ALU64 | BPF_ARSH | BPF_X:
+		emit_alu64_shift(insn, ctx, false);
+		break;
+
+	case BPF_ALU64 | BPF_LSH | BPF_K:
+	case BPF_ALU64 | BPF_RSH | BPF_K:
+	case BPF_ALU64 | BPF_ARSH | BPF_K:
+		emit_alu64_shift(insn, ctx, true);
+		break;
+
+	case BPF_ALU | BPF_MUL | BPF_X:
+	case BPF_ALU | BPF_DIV | BPF_X:
+	case BPF_ALU | BPF_MOD | BPF_X:
+	case BPF_ALU | BPF_MUL | BPF_K:
+	case BPF_ALU | BPF_DIV | BPF_K:
+	case BPF_ALU | BPF_MOD | BPF_K:
+		emit_math_call(insn, ctx, false);
+		break;
+
+	case BPF_ALU64 | BPF_MUL | BPF_X:
+	case BPF_ALU64 | BPF_DIV | BPF_X:
+	case BPF_ALU64 | BPF_MOD | BPF_X:
+	case BPF_ALU64 | BPF_MUL | BPF_K:
+	case BPF_ALU64 | BPF_DIV | BPF_K:
+	case BPF_ALU64 | BPF_MOD | BPF_K:
+		emit_math_call(insn, ctx, true);
+		break;
+
+	case BPF_ALU | BPF_END | BPF_TO_BE:
+	case BPF_ALU | BPF_END | BPF_TO_LE:
+	case BPF_ALU64 | BPF_END | BPF_TO_BE:
+	case BPF_ALU64 | BPF_END | BPF_TO_LE:
+		emit_bpf_end(insn, ctx);
+		break;
+
+	case BPF_LD | BPF_IMM | BPF_DW: {
+		const struct bpf_insn *insn1 = insn + 1;
+		const s8 *dst = bpf2m68k[insn->dst_reg];
+		const s8 *tmp1 = bpf2m68k[TMP_REG_1];
+		s8 d_lo = bpf_get_reg32(dst[1], tmp1[1], ctx);
+		s8 d_hi = bpf_get_reg32(dst[0], tmp1[0], ctx);
+
+		emit_16(ctx, 0x203c | (d_lo << 9));			/* move.l #imm, d_lo */
+		emit_32(ctx, insn->imm);
+		emit_16(ctx, 0x203c | (d_hi << 9));			/* move.l #imm, d_hi */
+		emit_32(ctx, insn1->imm);
+
+		bpf_put_reg32(dst[1], d_lo, ctx);
+		bpf_put_reg32(dst[0], d_hi, ctx);
+		break;
+	}
+
+	case BPF_LDX | BPF_MEM | BPF_B:
+	case BPF_LDX | BPF_MEM | BPF_H:
+	case BPF_LDX | BPF_MEM | BPF_W:
+	case BPF_LDX | BPF_MEM | BPF_DW:
+	case BPF_LDX | BPF_MEMSX | BPF_B:
+	case BPF_LDX | BPF_MEMSX | BPF_H:
+	case BPF_LDX | BPF_MEMSX | BPF_W:
+		emit_ldx(insn, ctx);
+		break;
+
+	case BPF_STX | BPF_MEM | BPF_B:
+	case BPF_STX | BPF_MEM | BPF_H:
+	case BPF_STX | BPF_MEM | BPF_W:
+	case BPF_STX | BPF_MEM | BPF_DW:
+		emit_stx(insn, ctx);
+		break;
+
+	case BPF_ST | BPF_MEM | BPF_B:
+	case BPF_ST | BPF_MEM | BPF_H:
+	case BPF_ST | BPF_MEM | BPF_W:
+	case BPF_ST | BPF_MEM | BPF_DW:
+		emit_st(insn, ctx);
+		break;
+
+	case BPF_ST | BPF_NOSPEC:
+		break;
+
+	case BPF_STX | BPF_ATOMIC | BPF_W:
+	case BPF_STX | BPF_ATOMIC | BPF_DW:
+		return emit_atomic(insn, ctx);
+
+	case BPF_JMP | BPF_TAIL_CALL:
+		emit_tail_call(insn, ctx);
+		break;
+
+	case BPF_JMP | BPF_JA:
+	case BPF_JMP32 | BPF_JA:
+	case BPF_JMP | BPF_JEQ | BPF_X:
+	case BPF_JMP | BPF_JEQ | BPF_K:
+	case BPF_JMP | BPF_JNE | BPF_X:
+	case BPF_JMP | BPF_JNE | BPF_K:
+	case BPF_JMP | BPF_JGT | BPF_X:
+	case BPF_JMP | BPF_JGT | BPF_K:
+	case BPF_JMP | BPF_JGE | BPF_X:
+	case BPF_JMP | BPF_JGE | BPF_K:
+	case BPF_JMP | BPF_JLT | BPF_X:
+	case BPF_JMP | BPF_JLT | BPF_K:
+	case BPF_JMP | BPF_JLE | BPF_X:
+	case BPF_JMP | BPF_JLE | BPF_K:
+	case BPF_JMP | BPF_JSGT | BPF_X:
+	case BPF_JMP | BPF_JSGT | BPF_K:
+	case BPF_JMP | BPF_JSGE | BPF_X:
+	case BPF_JMP | BPF_JSGE | BPF_K:
+	case BPF_JMP | BPF_JSLT | BPF_X:
+	case BPF_JMP | BPF_JSLT | BPF_K:
+	case BPF_JMP | BPF_JSLE | BPF_X:
+	case BPF_JMP | BPF_JSLE | BPF_K:
+	case BPF_JMP | BPF_JSET | BPF_X:
+	case BPF_JMP | BPF_JSET | BPF_K:
+	case BPF_JMP32 | BPF_JEQ | BPF_X:
+	case BPF_JMP32 | BPF_JEQ | BPF_K:
+	case BPF_JMP32 | BPF_JNE | BPF_X:
+	case BPF_JMP32 | BPF_JNE | BPF_K:
+	case BPF_JMP32 | BPF_JGT | BPF_X:
+	case BPF_JMP32 | BPF_JGT | BPF_K:
+	case BPF_JMP32 | BPF_JGE | BPF_X:
+	case BPF_JMP32 | BPF_JGE | BPF_K:
+	case BPF_JMP32 | BPF_JLT | BPF_X:
+	case BPF_JMP32 | BPF_JLT | BPF_K:
+	case BPF_JMP32 | BPF_JLE | BPF_X:
+	case BPF_JMP32 | BPF_JLE | BPF_K:
+	case BPF_JMP32 | BPF_JSGT | BPF_X:
+	case BPF_JMP32 | BPF_JSGT | BPF_K:
+	case BPF_JMP32 | BPF_JSGE | BPF_X:
+	case BPF_JMP32 | BPF_JSGE | BPF_K:
+	case BPF_JMP32 | BPF_JSLT | BPF_X:
+	case BPF_JMP32 | BPF_JSLT | BPF_K:
+	case BPF_JMP32 | BPF_JSLE | BPF_X:
+	case BPF_JMP32 | BPF_JSLE | BPF_K:
+	case BPF_JMP32 | BPF_JSET | BPF_X:
+	case BPF_JMP32 | BPF_JSET | BPF_K:
+		return emit_jmp(insn, ctx, i);
+
+	case BPF_JMP | BPF_CALL:
+		return emit_call(insn, ctx);
+
+	case BPF_JMP | BPF_EXIT:
+		build_epilogue(ctx);
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int build_body(struct jit_ctx *ctx)
+{
+	const struct bpf_prog *prog = ctx->prog;
+	int i;
+
+	for (i = 0; i < prog->len; i++) {
+		const struct bpf_insn *insn = &prog->insnsi[i];
+		int ret;
+
+		if (!ctx->target)
+			ctx->offsets[i] = ctx->idx;
+
+		ret = build_insn(insn, ctx, i);
+		if (ret < 0)
+			return ret;
+
+		if (insn->code == (BPF_LD | BPF_IMM | BPF_DW)) {
+			i++;
+			if (!ctx->target)
+				ctx->offsets[i] = ctx->idx;
+		}
+	}
+
+	if (!ctx->target)
+		ctx->offsets[prog->len] = ctx->idx;
+
+	return 0;
+}
+
+bool bpf_jit_needs_zext(void)
+{
+	return true;
+}
+
+static void jit_fill_hole(void *area, unsigned int size)
+{
+	u16 *ptr;
+
+	for (ptr = area; size >= 2; size -= 2)
+		*ptr++ = 0x4afc;
+}
+
+struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
+{
+	struct bpf_binary_header *header = prog->aux->jit_data;
+	struct jit_ctx ctx;
+	unsigned int image_size;
+	u8 *image_ptr;
+	bool extra_pass = prog->jited;
+
+	if (!prog->jit_requested)
+		return prog;
+
+	if (prog->jited && !prog->aux->func)
+		return prog;
+
+	memset(&ctx, 0, sizeof(ctx));
+	ctx.prog = prog;
+
+	ctx.offsets = kvcalloc(prog->len + 1, sizeof(int), GFP_KERNEL);
+	if (!ctx.offsets)
+		goto out_free_hdr;
+
+	build_prologue(&ctx);
+	if (build_body(&ctx) < 0)
+		goto out_free_hdr;
+	build_epilogue(&ctx);
+
+	if (extra_pass) {
+		image_ptr = (u8 *)prog->bpf_func;
+		image_size = prog->jited_len;
+	} else {
+		image_size = ctx.idx * 2;
+		header = bpf_jit_binary_alloc(image_size, &image_ptr, 2, jit_fill_hole);
+		if (!header)
+			goto out_off;
+		prog->aux->jit_data = header;
+	}
+
+	ctx.target = (u16 *)image_ptr;
+	ctx.idx = 0;
+
+	build_prologue(&ctx);
+	if (build_body(&ctx) < 0)
+		goto out_free_hdr;
+	build_epilogue(&ctx);
+
+	flush_icache_range((u32)header, (u32)(ctx.target + ctx.idx));
+
+	if (bpf_jit_enable > 1)
+		bpf_jit_dump(prog->len, image_size, 2, ctx.target);
+
+	if ((!prog->aux->func || extra_pass) && bpf_jit_binary_lock_ro(header))
+		goto out_free_hdr;
+
+	prog->bpf_func = (void *)ctx.target;
+	prog->jited = 1;
+	prog->jited_len = image_size;
+	goto out_off;
+
+out_free_hdr:
+	if (header) {
+		bpf_jit_binary_free(header);
+		prog->aux->jit_data = NULL;
+		prog->bpf_func = NULL;
+		prog->jited = 0;
+		prog->jited_len = 0;
+	}
+out_off:
+	kvfree(ctx.offsets);
+	return prog;
+}

3/2 2026/10/05 19:18 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 34681
							output: 23
							thoughts: 675
						

Thoughts:
**Evaluating the Patch Series**

Okay, let's break this down. The task is to evaluate this patch series, focusing on whether it's worth fuzzing. The target architecture is amd64, which is crucial.

First, I examined the patch diff: it introduces eBPF JIT support for m68k.  That's a red flag immediately. The files modified are: documentation updates, a MAINTAINERS entry, and a bunch of files under `arch/m68k/`.  Specifically, `Documentation/features/core/eBPF-JIT/arch-support.txt`, the MAINTAINERS file, `arch/m68k/Kbuild`, `arch/m68k/Kconfig`, `arch/m68k/net/Makefile`, and `arch/m68k/net/bpf_jit_comp.c`.

The initial impression is that this is *exclusively* an m68k thing, and I'd be looking for reasons this might apply to the current target architecture (amd64) for any code that would be considered executable.

Then, I focused on the target: amd64.  The instructions provide negative criteria.  We need to return WorthFuzzing=false if all changes fall into certain categories. The relevant ones here are: "Non-kernel and non-executable changes" and "Code paths exclusive to architectures other than the target architecture."

After reviewing the patch content, it's clear: nothing modified is *intended* to run on amd64.  The documentation changes are non-executable. The MAINTAINERS update is non-executable. The rest is *all* m68k-specific code. There are no modifications to code that would be generically compiled or used in a way that includes amd64.

To be absolutely sure, I mentally checked for any dependencies, common headers, or indirect modifications. `arch/m68k/` is only built when `ARCH=m68k`. It's not part of the build for amd64 (x86_64). There are *no* modifications to kernel/bpf, net/core, or any other generic code that would be included in the build for the amd64 target.

The conclusion is this patch series is limited to m68k support. It falls squarely within the negative criteria: the changes are either documentation or code paths exclusive to an architecture other than the target architecture (amd64).  Therefore, I'd set WorthFuzzing=false. A quick visual confirmation of the git diff wouldn't hurt, but I'm confident in the assessment.



4/2 2026/10/05 19:19 tool grepper
0m Args:
{
  "Expression": "BPF JIT for M68K"
}

Results:
{
  "Output": "MAINTAINERS=4849=F:\tarch/loongarch/net/\nMAINTAINERS-4850-\nMAINTAINERS:4851:BPF JIT for M68K\nMAINTAINERS-4852-M:\tKuan-Wei Chiu \u003cvisitorckw@gmail.com\u003e\n"
}

5/2 2026/10/05 19:19 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 36039
							output: 85
							thoughts: 287
						

Thoughts:
**My Assessment: Patch is Not Worth Fuzzing**

Okay, here's how I'm evaluating this patch. Everything boils down to m68k architecture-specific code and documentation. I'm focusing on the following files: `Documentation/features/core/eBPF-JIT/arch-support.txt`, the `MAINTAINERS` file, `arch/m68k/Kbuild`, `arch/m68k/Kconfig`, `arch/m68k/net/Makefile`, and `arch/m68k/net/bpf_jit_comp.c`. It's all clearly segregated within the m68k architecture directory.

My target architecture is amd64, and I'm using the established criteria. Section 2 states that I should return `WorthFuzzing=false` ONLY if the changes meet one or more specific conditions. Specifically, I'm keying into this clause: "Code paths exclusive to architectures other than the target architecture".

Given the eBPF JIT compiler is being introduced *specifically* for the m68k architecture, plus the accompanying documentation and `MAINTAINERS` updates, it is completely inaccessible to amd64, which is my target. The m68k code cannot be compiled or executed on amd64. That is, it is an unreachable execution path on the target.

Therefore, the decision is straightforward: `WorthFuzzing = false`. There are no symbols to focus on, and no specific configurations to enable. The reasoning is direct: the patch's changes are exclusively related to the m68k architecture and are therefore not applicable to or testable on the amd64 target. Time to call `set-results`.



6/2 2026/10/05 19:19 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch adds an eBPF JIT compiler for the m68k architecture under arch/m68k/ along with Documentation and MAINTAINERS entries. Because the target architecture is amd64, all modified code is exclusive to another architecture and unreachable.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch adds an eBPF JIT compiler for the m68k architecture under arch/m68k/ along with Documentation and MAINTAINERS entries. Because the target architecture is amd64, all modified code is exclusive to another architecture and unreachable.",
  "WorthFuzzing": false
}

7/1 2026/10/05 19:19 action If
0m Args:
{
  "WorthFuzzing": false
}

Results:
null

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)