insn->imm == (BPF_XOR | BPF_FETCH)) {
                                u8 *branch_target;
                                bool is64 = BPF_SIZE(insn->code) == BPF_DW;
+                               u32 real_src_reg = src_reg;
 
                                /*
                                 * Can't be implemented with a single x86 insn.
 
                                /* Will need RAX as a CMPXCHG operand so save R0 */
                                emit_mov_reg(&prog, true, BPF_REG_AX, BPF_REG_0);
+                               if (src_reg == BPF_REG_0)
+                                       real_src_reg = BPF_REG_AX;
+
                                branch_target = prog;
                                /* Load old value */
                                emit_ldx(&prog, BPF_SIZE(insn->code),
                                 * put the result in the AUX_REG.
                                 */
                                emit_mov_reg(&prog, is64, AUX_REG, BPF_REG_0);
-                               maybe_emit_mod(&prog, AUX_REG, src_reg, is64);
+                               maybe_emit_mod(&prog, AUX_REG, real_src_reg, is64);
                                EMIT2(simple_alu_opcodes[BPF_OP(insn->imm)],
-                                     add_2reg(0xC0, AUX_REG, src_reg));
+                                     add_2reg(0xC0, AUX_REG, real_src_reg));
                                /* Attempt to swap in new value */
                                err = emit_atomic(&prog, BPF_CMPXCHG,
                                                  dst_reg, AUX_REG, insn->off,
                                 */
                                EMIT2(X86_JNE, -(prog - branch_target) - 2);
                                /* Return the pre-modification value */
-                               emit_mov_reg(&prog, is64, src_reg, BPF_REG_0);
+                               emit_mov_reg(&prog, is64, real_src_reg, BPF_REG_0);
                                /* Restore R0 after clobbering RAX */
                                emit_mov_reg(&prog, true, BPF_REG_0, BPF_REG_AX);
                                break;
 
        },
        .result = ACCEPT,
 },
+{
+       "BPF_ATOMIC_AND with fetch - r0 as source reg",
+       .insns = {
+               /* val = 0x110; */
+               BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0x110),
+               /* old = atomic_fetch_and(&val, 0x011); */
+               BPF_MOV64_IMM(BPF_REG_0, 0x011),
+               BPF_ATOMIC_OP(BPF_DW, BPF_AND | BPF_FETCH, BPF_REG_10, BPF_REG_0, -8),
+               /* if (old != 0x110) exit(3); */
+               BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0x110, 2),
+               BPF_MOV64_IMM(BPF_REG_0, 3),
+               BPF_EXIT_INSN(),
+               /* if (val != 0x010) exit(2); */
+               BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -8),
+               BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0x010, 2),
+               BPF_MOV64_IMM(BPF_REG_1, 2),
+               BPF_EXIT_INSN(),
+               /* exit(0); */
+               BPF_MOV64_IMM(BPF_REG_0, 0),
+               BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+},