Commit 61dd8f00 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Daniel Borkmann

nfp: bpf: tabularize generations of compare operations

There are quite a few compare instructions now, use a table
to translate BPF instruction code to NFP instruction parameters
instead of parameterizing helpers.  This saves LOC and makes
future extensions easier.
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 6c59500c
...@@ -1214,45 +1214,79 @@ wrp_test_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, ...@@ -1214,45 +1214,79 @@ wrp_test_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
return 0; return 0;
} }
static int static const struct jmp_code_map {
wrp_cmp_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, enum br_mask br_mask;
enum br_mask br_mask, bool swap) bool swap;
} jmp_code_map[] = {
[BPF_JGT >> 4] = { BR_BLO, true },
[BPF_JGE >> 4] = { BR_BHS, false },
[BPF_JLT >> 4] = { BR_BLO, false },
[BPF_JLE >> 4] = { BR_BHS, true },
[BPF_JSGT >> 4] = { BR_BLT, true },
[BPF_JSGE >> 4] = { BR_BGE, false },
[BPF_JSLT >> 4] = { BR_BLT, false },
[BPF_JSLE >> 4] = { BR_BGE, true },
};
static const struct jmp_code_map *nfp_jmp_code_get(struct nfp_insn_meta *meta)
{
unsigned int op;
op = BPF_OP(meta->insn.code) >> 4;
/* br_mask of 0 is BR_BEQ which we don't use in jump code table */
if (WARN_ONCE(op >= ARRAY_SIZE(jmp_code_map) ||
!jmp_code_map[op].br_mask,
"no code found for jump instruction"))
return NULL;
return &jmp_code_map[op];
}
static int cmp_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{ {
const struct bpf_insn *insn = &meta->insn; const struct bpf_insn *insn = &meta->insn;
u64 imm = insn->imm; /* sign extend */ u64 imm = insn->imm; /* sign extend */
const struct jmp_code_map *code;
u8 reg = insn->dst_reg * 2; u8 reg = insn->dst_reg * 2;
swreg tmp_reg; swreg tmp_reg;
code = nfp_jmp_code_get(meta);
if (!code)
return -EINVAL;
tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog)); tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
if (!swap) if (!code->swap)
emit_alu(nfp_prog, reg_none(), reg_a(reg), ALU_OP_SUB, tmp_reg); emit_alu(nfp_prog, reg_none(), reg_a(reg), ALU_OP_SUB, tmp_reg);
else else
emit_alu(nfp_prog, reg_none(), tmp_reg, ALU_OP_SUB, reg_a(reg)); emit_alu(nfp_prog, reg_none(), tmp_reg, ALU_OP_SUB, reg_a(reg));
tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog)); tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
if (!swap) if (!code->swap)
emit_alu(nfp_prog, reg_none(), emit_alu(nfp_prog, reg_none(),
reg_a(reg + 1), ALU_OP_SUB_C, tmp_reg); reg_a(reg + 1), ALU_OP_SUB_C, tmp_reg);
else else
emit_alu(nfp_prog, reg_none(), emit_alu(nfp_prog, reg_none(),
tmp_reg, ALU_OP_SUB_C, reg_a(reg + 1)); tmp_reg, ALU_OP_SUB_C, reg_a(reg + 1));
emit_br(nfp_prog, br_mask, insn->off, 0); emit_br(nfp_prog, code->br_mask, insn->off, 0);
return 0; return 0;
} }
static int static int cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
wrp_cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
enum br_mask br_mask, bool swap)
{ {
const struct bpf_insn *insn = &meta->insn; const struct bpf_insn *insn = &meta->insn;
const struct jmp_code_map *code;
u8 areg, breg; u8 areg, breg;
code = nfp_jmp_code_get(meta);
if (!code)
return -EINVAL;
areg = insn->dst_reg * 2; areg = insn->dst_reg * 2;
breg = insn->src_reg * 2; breg = insn->src_reg * 2;
if (swap) { if (code->swap) {
areg ^= breg; areg ^= breg;
breg ^= areg; breg ^= areg;
areg ^= breg; areg ^= breg;
...@@ -1261,7 +1295,7 @@ wrp_cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, ...@@ -1261,7 +1295,7 @@ wrp_cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
emit_alu(nfp_prog, reg_none(), reg_a(areg), ALU_OP_SUB, reg_b(breg)); emit_alu(nfp_prog, reg_none(), reg_a(areg), ALU_OP_SUB, reg_b(breg));
emit_alu(nfp_prog, reg_none(), emit_alu(nfp_prog, reg_none(),
reg_a(areg + 1), ALU_OP_SUB_C, reg_b(breg + 1)); reg_a(areg + 1), ALU_OP_SUB_C, reg_b(breg + 1));
emit_br(nfp_prog, br_mask, insn->off, 0); emit_br(nfp_prog, code->br_mask, insn->off, 0);
return 0; return 0;
} }
...@@ -2283,46 +2317,6 @@ static int jeq_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) ...@@ -2283,46 +2317,6 @@ static int jeq_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
return 0; return 0;
} }
static int jgt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_imm(nfp_prog, meta, BR_BLO, true);
}
static int jge_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_imm(nfp_prog, meta, BR_BHS, false);
}
static int jlt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_imm(nfp_prog, meta, BR_BLO, false);
}
static int jle_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_imm(nfp_prog, meta, BR_BHS, true);
}
static int jsgt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_imm(nfp_prog, meta, BR_BLT, true);
}
static int jsge_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_imm(nfp_prog, meta, BR_BGE, false);
}
static int jslt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_imm(nfp_prog, meta, BR_BLT, false);
}
static int jsle_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_imm(nfp_prog, meta, BR_BGE, true);
}
static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{ {
const struct bpf_insn *insn = &meta->insn; const struct bpf_insn *insn = &meta->insn;
...@@ -2392,46 +2386,6 @@ static int jeq_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) ...@@ -2392,46 +2386,6 @@ static int jeq_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
return 0; return 0;
} }
static int jgt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_reg(nfp_prog, meta, BR_BLO, true);
}
static int jge_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_reg(nfp_prog, meta, BR_BHS, false);
}
static int jlt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_reg(nfp_prog, meta, BR_BLO, false);
}
static int jle_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_reg(nfp_prog, meta, BR_BHS, true);
}
static int jsgt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_reg(nfp_prog, meta, BR_BLT, true);
}
static int jsge_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_reg(nfp_prog, meta, BR_BGE, false);
}
static int jslt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_reg(nfp_prog, meta, BR_BLT, false);
}
static int jsle_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{
return wrp_cmp_reg(nfp_prog, meta, BR_BGE, true);
}
static int jset_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) static int jset_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
{ {
return wrp_test_reg(nfp_prog, meta, ALU_OP_AND, BR_BNE); return wrp_test_reg(nfp_prog, meta, ALU_OP_AND, BR_BNE);
...@@ -2520,25 +2474,25 @@ static const instr_cb_t instr_cb[256] = { ...@@ -2520,25 +2474,25 @@ static const instr_cb_t instr_cb[256] = {
[BPF_ST | BPF_MEM | BPF_DW] = mem_st8, [BPF_ST | BPF_MEM | BPF_DW] = mem_st8,
[BPF_JMP | BPF_JA | BPF_K] = jump, [BPF_JMP | BPF_JA | BPF_K] = jump,
[BPF_JMP | BPF_JEQ | BPF_K] = jeq_imm, [BPF_JMP | BPF_JEQ | BPF_K] = jeq_imm,
[BPF_JMP | BPF_JGT | BPF_K] = jgt_imm, [BPF_JMP | BPF_JGT | BPF_K] = cmp_imm,
[BPF_JMP | BPF_JGE | BPF_K] = jge_imm, [BPF_JMP | BPF_JGE | BPF_K] = cmp_imm,
[BPF_JMP | BPF_JLT | BPF_K] = jlt_imm, [BPF_JMP | BPF_JLT | BPF_K] = cmp_imm,
[BPF_JMP | BPF_JLE | BPF_K] = jle_imm, [BPF_JMP | BPF_JLE | BPF_K] = cmp_imm,
[BPF_JMP | BPF_JSGT | BPF_K] = jsgt_imm, [BPF_JMP | BPF_JSGT | BPF_K] = cmp_imm,
[BPF_JMP | BPF_JSGE | BPF_K] = jsge_imm, [BPF_JMP | BPF_JSGE | BPF_K] = cmp_imm,
[BPF_JMP | BPF_JSLT | BPF_K] = jslt_imm, [BPF_JMP | BPF_JSLT | BPF_K] = cmp_imm,
[BPF_JMP | BPF_JSLE | BPF_K] = jsle_imm, [BPF_JMP | BPF_JSLE | BPF_K] = cmp_imm,
[BPF_JMP | BPF_JSET | BPF_K] = jset_imm, [BPF_JMP | BPF_JSET | BPF_K] = jset_imm,
[BPF_JMP | BPF_JNE | BPF_K] = jne_imm, [BPF_JMP | BPF_JNE | BPF_K] = jne_imm,
[BPF_JMP | BPF_JEQ | BPF_X] = jeq_reg, [BPF_JMP | BPF_JEQ | BPF_X] = jeq_reg,
[BPF_JMP | BPF_JGT | BPF_X] = jgt_reg, [BPF_JMP | BPF_JGT | BPF_X] = cmp_reg,
[BPF_JMP | BPF_JGE | BPF_X] = jge_reg, [BPF_JMP | BPF_JGE | BPF_X] = cmp_reg,
[BPF_JMP | BPF_JLT | BPF_X] = jlt_reg, [BPF_JMP | BPF_JLT | BPF_X] = cmp_reg,
[BPF_JMP | BPF_JLE | BPF_X] = jle_reg, [BPF_JMP | BPF_JLE | BPF_X] = cmp_reg,
[BPF_JMP | BPF_JSGT | BPF_X] = jsgt_reg, [BPF_JMP | BPF_JSGT | BPF_X] = cmp_reg,
[BPF_JMP | BPF_JSGE | BPF_X] = jsge_reg, [BPF_JMP | BPF_JSGE | BPF_X] = cmp_reg,
[BPF_JMP | BPF_JSLT | BPF_X] = jslt_reg, [BPF_JMP | BPF_JSLT | BPF_X] = cmp_reg,
[BPF_JMP | BPF_JSLE | BPF_X] = jsle_reg, [BPF_JMP | BPF_JSLE | BPF_X] = cmp_reg,
[BPF_JMP | BPF_JSET | BPF_X] = jset_reg, [BPF_JMP | BPF_JSET | BPF_X] = jset_reg,
[BPF_JMP | BPF_JNE | BPF_X] = jne_reg, [BPF_JMP | BPF_JNE | BPF_X] = jne_reg,
[BPF_JMP | BPF_CALL] = call, [BPF_JMP | BPF_CALL] = call,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment