diff options
Diffstat (limited to 'arch/x86/net')
-rw-r--r-- | arch/x86/net/bpf_jit_comp.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 26328e800869..4ed75dd81d05 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c | |||
@@ -359,15 +359,21 @@ void bpf_jit_compile(struct sk_filter *fp) | |||
359 | EMIT2(0x89, 0xd0); /* mov %edx,%eax */ | 359 | EMIT2(0x89, 0xd0); /* mov %edx,%eax */ |
360 | break; | 360 | break; |
361 | case BPF_S_ALU_MOD_K: /* A %= K; */ | 361 | case BPF_S_ALU_MOD_K: /* A %= K; */ |
362 | if (K == 1) { | ||
363 | CLEAR_A(); | ||
364 | break; | ||
365 | } | ||
362 | EMIT2(0x31, 0xd2); /* xor %edx,%edx */ | 366 | EMIT2(0x31, 0xd2); /* xor %edx,%edx */ |
363 | EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */ | 367 | EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */ |
364 | EMIT2(0xf7, 0xf1); /* div %ecx */ | 368 | EMIT2(0xf7, 0xf1); /* div %ecx */ |
365 | EMIT2(0x89, 0xd0); /* mov %edx,%eax */ | 369 | EMIT2(0x89, 0xd0); /* mov %edx,%eax */ |
366 | break; | 370 | break; |
367 | case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */ | 371 | case BPF_S_ALU_DIV_K: /* A /= K */ |
368 | EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */ | 372 | if (K == 1) |
369 | EMIT(K, 4); | 373 | break; |
370 | EMIT4(0x48, 0xc1, 0xe8, 0x20); /* shr $0x20,%rax */ | 374 | EMIT2(0x31, 0xd2); /* xor %edx,%edx */ |
375 | EMIT1(0xb9);EMIT(K, 4); /* mov imm32,%ecx */ | ||
376 | EMIT2(0xf7, 0xf1); /* div %ecx */ | ||
371 | break; | 377 | break; |
372 | case BPF_S_ALU_AND_X: | 378 | case BPF_S_ALU_AND_X: |
373 | seen |= SEEN_XREG; | 379 | seen |= SEEN_XREG; |