提交 db0a4b3b 编写于 作者: J Jiong Wang 提交者: Alexei Starovoitov

nfp: bpf: correct the behavior for shifts by zero

Shifts by zero do nothing, and should be treated as nops.

Even though compiler is not supposed to generate such instructions and
manual written assembly is unlikely to have them, but they are legal
instructions and have defined behavior.

This patch correct existing shifts code-gen to make sure they do nothing
when shift amount is zero except when the instruction is ALU32 for which
high bits need to be cleared.

For shift amount bigger than type size, already, NFP JIT back-end errors
out for immediate shift and only low 5 bits will be taken into account for
indirect shift which is the same as x86.
Reviewed-by: NJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: NJiong Wang <jiong.wang@netronome.com>
Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
上级 2a118154
...@@ -1967,6 +1967,9 @@ static int neg_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) ...@@ -1967,6 +1967,9 @@ static int neg_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
*/ */
static int __shl_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt) static int __shl_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
{ {
if (!shift_amt)
return 0;
if (shift_amt < 32) { if (shift_amt < 32) {
emit_shf(nfp_prog, reg_both(dst + 1), reg_a(dst + 1), emit_shf(nfp_prog, reg_both(dst + 1), reg_a(dst + 1),
SHF_OP_NONE, reg_b(dst), SHF_SC_R_DSHF, SHF_OP_NONE, reg_b(dst), SHF_SC_R_DSHF,
...@@ -2079,6 +2082,9 @@ static int shl_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) ...@@ -2079,6 +2082,9 @@ static int shl_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
*/ */
static int __shr_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt) static int __shr_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
{ {
if (!shift_amt)
return 0;
if (shift_amt < 32) { if (shift_amt < 32) {
emit_shf(nfp_prog, reg_both(dst), reg_a(dst + 1), SHF_OP_NONE, emit_shf(nfp_prog, reg_both(dst), reg_a(dst + 1), SHF_OP_NONE,
reg_b(dst), SHF_SC_R_DSHF, shift_amt); reg_b(dst), SHF_SC_R_DSHF, shift_amt);
...@@ -2180,6 +2186,9 @@ static int shr_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) ...@@ -2180,6 +2186,9 @@ static int shr_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
*/ */
static int __ashr_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt) static int __ashr_imm64(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
{ {
if (!shift_amt)
return 0;
if (shift_amt < 32) { if (shift_amt < 32) {
emit_shf(nfp_prog, reg_both(dst), reg_a(dst + 1), SHF_OP_NONE, emit_shf(nfp_prog, reg_both(dst), reg_a(dst + 1), SHF_OP_NONE,
reg_b(dst), SHF_SC_R_DSHF, shift_amt); reg_b(dst), SHF_SC_R_DSHF, shift_amt);
...@@ -2388,10 +2397,13 @@ static int neg_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) ...@@ -2388,10 +2397,13 @@ static int neg_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
static int __ashr_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt) static int __ashr_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
{ {
/* Set signedness bit (MSB of result). */ if (shift_amt) {
emit_alu(nfp_prog, reg_none(), reg_a(dst), ALU_OP_OR, reg_imm(0)); /* Set signedness bit (MSB of result). */
emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_ASHR, reg_b(dst), emit_alu(nfp_prog, reg_none(), reg_a(dst), ALU_OP_OR,
SHF_SC_R_SHF, shift_amt); reg_imm(0));
emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_ASHR,
reg_b(dst), SHF_SC_R_SHF, shift_amt);
}
wrp_immed(nfp_prog, reg_both(dst + 1), 0); wrp_immed(nfp_prog, reg_both(dst + 1), 0);
return 0; return 0;
...@@ -2433,12 +2445,10 @@ static int shl_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) ...@@ -2433,12 +2445,10 @@ static int shl_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;
if (!insn->imm) if (insn->imm)
return 1; /* TODO: zero shift means indirect */ emit_shf(nfp_prog, reg_both(insn->dst_reg * 2),
reg_none(), SHF_OP_NONE, reg_b(insn->dst_reg * 2),
emit_shf(nfp_prog, reg_both(insn->dst_reg * 2), SHF_SC_L_SHF, insn->imm);
reg_none(), SHF_OP_NONE, reg_b(insn->dst_reg * 2),
SHF_SC_L_SHF, insn->imm);
wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0); wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0);
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册