|
@@ -449,10 +449,21 @@ static inline void emit_udiv(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx)
|
|
|
return;
|
|
|
}
|
|
|
#endif
|
|
|
- if (rm != ARM_R0)
|
|
|
- emit(ARM_MOV_R(ARM_R0, rm), ctx);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * For BPF_ALU | BPF_DIV | BPF_K instructions, rm is ARM_R4
|
|
|
+ * (r_A) and rn is ARM_R0 (r_scratch) so load rn first into
|
|
|
+ * ARM_R1 to avoid accidentally overwriting ARM_R0 with rm
|
|
|
+ * before using it as a source for ARM_R1.
|
|
|
+ *
|
|
|
+ * For BPF_ALU | BPF_DIV | BPF_X rm is ARM_R4 (r_A) and rn is
|
|
|
+ * ARM_R5 (r_X) so there is no particular register overlap
|
|
|
+ * issues.
|
|
|
+ */
|
|
|
if (rn != ARM_R1)
|
|
|
emit(ARM_MOV_R(ARM_R1, rn), ctx);
|
|
|
+ if (rm != ARM_R0)
|
|
|
+ emit(ARM_MOV_R(ARM_R0, rm), ctx);
|
|
|
|
|
|
ctx->seen |= SEEN_CALL;
|
|
|
emit_mov_i(ARM_R3, (u32)jit_udiv, ctx);
|