diff --git a/arch/parisc/net/bpf_jit_comp32.c b/arch/parisc/net/bpf_jit_comp32.c index 5ff0cf925fe9..eea0a34a3bfe 100644 --- a/arch/parisc/net/bpf_jit_comp32.c +++ b/arch/parisc/net/bpf_jit_comp32.c @@ -321,6 +321,8 @@ static void bpf_put_reg32(const s8 *reg, const s8 *src, extern void $$mulI(void); extern void $$divU(void); extern void $$remU(void); +extern void $$divI(void); +extern void $$remI(void); static void emit_call_millicode(void *func, const s8 arg0, const s8 arg1, u8 opcode, struct hppa_jit_context *ctx) @@ -562,12 +564,14 @@ static void emit_alu_i32(const s8 *dst, s32 imm, } static void emit_alu_r64(const s8 *dst, const s8 *src, - struct hppa_jit_context *ctx, const u8 op) + struct hppa_jit_context *ctx, const u8 op, + bool is_signed) { const s8 *tmp1 = regmap[TMP_REG_1]; const s8 *tmp2 = regmap[TMP_REG_2]; const s8 *rd; const s8 *rs = bpf_get_reg64(src, tmp2, ctx); + void *func; if (op == BPF_MOV) rd = bpf_get_reg64_ref(dst, tmp1, false, ctx); @@ -604,10 +608,12 @@ static void emit_alu_r64(const s8 *dst, const s8 *src, emit_call_libgcc_ll(__muldi3, rd, rs, op, ctx); break; case BPF_DIV: - emit_call_libgcc_ll(&hppa_div64, rd, rs, op, ctx); + func = is_signed ? &hppa_sdiv64 : &hppa_div64; + emit_call_libgcc_ll(func, rd, rs, op, ctx); break; case BPF_MOD: - emit_call_libgcc_ll(&hppa_div64_rem, rd, rs, op, ctx); + func = is_signed ? &hppa_sdiv64_rem : &hppa_div64_rem; + emit_call_libgcc_ll(func, rd, rs, op, ctx); break; case BPF_LSH: emit_call_libgcc_ll(__ashldi3, rd, rs, op, ctx); @@ -630,7 +636,8 @@ static void emit_alu_r64(const s8 *dst, const s8 *src, } static void emit_alu_r32(const s8 *dst, const s8 *src, - struct hppa_jit_context *ctx, const u8 op) + struct hppa_jit_context *ctx, const u8 op, + bool is_signed) { const s8 *tmp1 = regmap[TMP_REG_1]; const s8 *tmp2 = regmap[TMP_REG_2]; @@ -666,10 +673,12 @@ static void emit_alu_r32(const s8 *dst, const s8 *src, emit_call_millicode($$mulI, lo(rd), lo(rs), op, ctx); break; case BPF_DIV: - emit_call_millicode($$divU, lo(rd), lo(rs), op, ctx); + emit_call_millicode(is_signed ? $$divI : $$divU, + lo(rd), lo(rs), op, ctx); break; case BPF_MOD: - emit_call_millicode($$remU, lo(rd), lo(rs), op, ctx); + emit_call_millicode(is_signed ? $$remI : $$remU, + lo(rd), lo(rs), op, ctx); break; case BPF_LSH: emit(hppa_subi(0x1f, lo(rs), HPPA_REG_T0), ctx); @@ -1163,12 +1172,12 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct hppa_jit_context *ctx, emit_imm32(tmp2, imm, ctx); src = tmp2; } - emit_alu_r64(dst, src, ctx, BPF_OP(code)); + emit_alu_r64(dst, src, ctx, BPF_OP(code), off == 1); break; /* dst = -dst */ case BPF_ALU64 | BPF_NEG: - emit_alu_r64(dst, tmp2, ctx, BPF_OP(code)); + emit_alu_r64(dst, tmp2, ctx, BPF_OP(code), false); break; case BPF_ALU64 | BPF_MOV | BPF_K: @@ -1211,7 +1220,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct hppa_jit_context *ctx, emit_imm32(tmp2, imm, ctx); src = tmp2; } - emit_alu_r32(dst, src, ctx, BPF_OP(code)); + emit_alu_r32(dst, src, ctx, BPF_OP(code), off == 1); break; /* dst = dst OP imm */ @@ -1236,7 +1245,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct hppa_jit_context *ctx, * src is ignored---choose tmp2 as a dummy register since it * is not on the stack. */ - emit_alu_r32(dst, tmp2, ctx, BPF_OP(code)); + emit_alu_r32(dst, tmp2, ctx, BPF_OP(code), false); break; /* dst = BSWAP##imm(dst) */