mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
bpf: x86: Factor out emission of REX byte
The JIT case for encoding atomic ops is about to get more complicated. In order to make the review & resulting code easier, let's factor out some shared helpers. Signed-off-by: Brendan Jackman <jackmanb@google.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20210114181751.768687-3-jackmanb@google.com
This commit is contained in:
parent
11c11d0751
commit
74007cfc1f
1 changed files with 23 additions and 16 deletions
|
@ -702,6 +702,21 @@ static void emit_insn_suffix(u8 **pprog, u32 ptr_reg, u32 val_reg, int off)
|
||||||
*pprog = prog;
|
*pprog = prog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emit a REX byte if it will be necessary to address these registers
|
||||||
|
*/
|
||||||
|
static void maybe_emit_mod(u8 **pprog, u32 dst_reg, u32 src_reg, bool is64)
|
||||||
|
{
|
||||||
|
u8 *prog = *pprog;
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
|
if (is64)
|
||||||
|
EMIT1(add_2mod(0x48, dst_reg, src_reg));
|
||||||
|
else if (is_ereg(dst_reg) || is_ereg(src_reg))
|
||||||
|
EMIT1(add_2mod(0x40, dst_reg, src_reg));
|
||||||
|
*pprog = prog;
|
||||||
|
}
|
||||||
|
|
||||||
/* LDX: dst_reg = *(u8*)(src_reg + off) */
|
/* LDX: dst_reg = *(u8*)(src_reg + off) */
|
||||||
static void emit_ldx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
|
static void emit_ldx(u8 **pprog, u32 size, u32 dst_reg, u32 src_reg, int off)
|
||||||
{
|
{
|
||||||
|
@ -854,10 +869,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
||||||
case BPF_OR: b2 = 0x09; break;
|
case BPF_OR: b2 = 0x09; break;
|
||||||
case BPF_XOR: b2 = 0x31; break;
|
case BPF_XOR: b2 = 0x31; break;
|
||||||
}
|
}
|
||||||
if (BPF_CLASS(insn->code) == BPF_ALU64)
|
maybe_emit_mod(&prog, dst_reg, src_reg,
|
||||||
EMIT1(add_2mod(0x48, dst_reg, src_reg));
|
BPF_CLASS(insn->code) == BPF_ALU64);
|
||||||
else if (is_ereg(dst_reg) || is_ereg(src_reg))
|
|
||||||
EMIT1(add_2mod(0x40, dst_reg, src_reg));
|
|
||||||
EMIT2(b2, add_2reg(0xC0, dst_reg, src_reg));
|
EMIT2(b2, add_2reg(0xC0, dst_reg, src_reg));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1302,20 +1315,16 @@ xadd:
|
||||||
case BPF_JMP32 | BPF_JSGE | BPF_X:
|
case BPF_JMP32 | BPF_JSGE | BPF_X:
|
||||||
case BPF_JMP32 | BPF_JSLE | BPF_X:
|
case BPF_JMP32 | BPF_JSLE | BPF_X:
|
||||||
/* cmp dst_reg, src_reg */
|
/* cmp dst_reg, src_reg */
|
||||||
if (BPF_CLASS(insn->code) == BPF_JMP)
|
maybe_emit_mod(&prog, dst_reg, src_reg,
|
||||||
EMIT1(add_2mod(0x48, dst_reg, src_reg));
|
BPF_CLASS(insn->code) == BPF_JMP);
|
||||||
else if (is_ereg(dst_reg) || is_ereg(src_reg))
|
|
||||||
EMIT1(add_2mod(0x40, dst_reg, src_reg));
|
|
||||||
EMIT2(0x39, add_2reg(0xC0, dst_reg, src_reg));
|
EMIT2(0x39, add_2reg(0xC0, dst_reg, src_reg));
|
||||||
goto emit_cond_jmp;
|
goto emit_cond_jmp;
|
||||||
|
|
||||||
case BPF_JMP | BPF_JSET | BPF_X:
|
case BPF_JMP | BPF_JSET | BPF_X:
|
||||||
case BPF_JMP32 | BPF_JSET | BPF_X:
|
case BPF_JMP32 | BPF_JSET | BPF_X:
|
||||||
/* test dst_reg, src_reg */
|
/* test dst_reg, src_reg */
|
||||||
if (BPF_CLASS(insn->code) == BPF_JMP)
|
maybe_emit_mod(&prog, dst_reg, src_reg,
|
||||||
EMIT1(add_2mod(0x48, dst_reg, src_reg));
|
BPF_CLASS(insn->code) == BPF_JMP);
|
||||||
else if (is_ereg(dst_reg) || is_ereg(src_reg))
|
|
||||||
EMIT1(add_2mod(0x40, dst_reg, src_reg));
|
|
||||||
EMIT2(0x85, add_2reg(0xC0, dst_reg, src_reg));
|
EMIT2(0x85, add_2reg(0xC0, dst_reg, src_reg));
|
||||||
goto emit_cond_jmp;
|
goto emit_cond_jmp;
|
||||||
|
|
||||||
|
@ -1351,10 +1360,8 @@ xadd:
|
||||||
case BPF_JMP32 | BPF_JSLE | BPF_K:
|
case BPF_JMP32 | BPF_JSLE | BPF_K:
|
||||||
/* test dst_reg, dst_reg to save one extra byte */
|
/* test dst_reg, dst_reg to save one extra byte */
|
||||||
if (imm32 == 0) {
|
if (imm32 == 0) {
|
||||||
if (BPF_CLASS(insn->code) == BPF_JMP)
|
maybe_emit_mod(&prog, dst_reg, dst_reg,
|
||||||
EMIT1(add_2mod(0x48, dst_reg, dst_reg));
|
BPF_CLASS(insn->code) == BPF_JMP);
|
||||||
else if (is_ereg(dst_reg))
|
|
||||||
EMIT1(add_2mod(0x40, dst_reg, dst_reg));
|
|
||||||
EMIT2(0x85, add_2reg(0xC0, dst_reg, dst_reg));
|
EMIT2(0x85, add_2reg(0xC0, dst_reg, dst_reg));
|
||||||
goto emit_cond_jmp;
|
goto emit_cond_jmp;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue