LoongArch: BPF: Support signed div instructions
authorHengqi Chen <hengqi.chen@gmail.com>
Wed, 8 Nov 2023 06:12:21 +0000 (14:12 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Wed, 8 Nov 2023 06:12:21 +0000 (14:12 +0800)
Add support for signed div instructions.

Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/net/bpf_jit.c

index 050fcf233a34a189cc12942da7837b88c3162e90..7c0d129b82a4a45f6e404c676b27da8e85619d1a 100644 (file)
@@ -553,20 +553,36 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
        /* dst = dst / src */
        case BPF_ALU | BPF_DIV | BPF_X:
        case BPF_ALU64 | BPF_DIV | BPF_X:
-               emit_zext_32(ctx, dst, is32);
-               move_reg(ctx, t1, src);
-               emit_zext_32(ctx, t1, is32);
-               emit_insn(ctx, divdu, dst, dst, t1);
-               emit_zext_32(ctx, dst, is32);
+               if (!off) {
+                       emit_zext_32(ctx, dst, is32);
+                       move_reg(ctx, t1, src);
+                       emit_zext_32(ctx, t1, is32);
+                       emit_insn(ctx, divdu, dst, dst, t1);
+                       emit_zext_32(ctx, dst, is32);
+               } else {
+                       emit_sext_32(ctx, dst, is32);
+                       move_reg(ctx, t1, src);
+                       emit_sext_32(ctx, t1, is32);
+                       emit_insn(ctx, divd, dst, dst, t1);
+                       emit_sext_32(ctx, dst, is32);
+               }
                break;
 
        /* dst = dst / imm */
        case BPF_ALU | BPF_DIV | BPF_K:
        case BPF_ALU64 | BPF_DIV | BPF_K:
-               move_imm(ctx, t1, imm, is32);
-               emit_zext_32(ctx, dst, is32);
-               emit_insn(ctx, divdu, dst, dst, t1);
-               emit_zext_32(ctx, dst, is32);
+               if (!off) {
+                       move_imm(ctx, t1, imm, is32);
+                       emit_zext_32(ctx, dst, is32);
+                       emit_insn(ctx, divdu, dst, dst, t1);
+                       emit_zext_32(ctx, dst, is32);
+               } else {
+                       move_imm(ctx, t1, imm, false);
+                       emit_sext_32(ctx, t1, is32);
+                       emit_sext_32(ctx, dst, is32);
+                       emit_insn(ctx, divd, dst, dst, t1);
+                       emit_sext_32(ctx, dst, is32);
+               }
                break;
 
        /* dst = dst % src */