static int emit_branch_r64()

in net/bpf_jit_comp32.c [564:650]


static int emit_branch_r64(const s8 *src1, const s8 *src2, s32 rvoff,
			   struct rv_jit_context *ctx, const u8 op)
{
	int e, s = ctx->ninsns;
	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
	const s8 *tmp2 = bpf2rv32[TMP_REG_2];

	const s8 *rs1 = bpf_get_reg64(src1, tmp1, ctx);
	const s8 *rs2 = bpf_get_reg64(src2, tmp2, ctx);

	/*
	 * NO_JUMP skips over the rest of the instructions and the
	 * emit_jump_and_link, meaning the BPF branch is not taken.
	 * JUMP skips directly to the emit_jump_and_link, meaning
	 * the BPF branch is taken.
	 *
	 * The fallthrough case results in the BPF branch being taken.
	 */
#define NO_JUMP(idx) (6 + (2 * (idx)))
#define JUMP(idx) (2 + (2 * (idx)))

	switch (op) {
	case BPF_JEQ:
		emit(rv_bne(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
		emit(rv_bne(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
		break;
	case BPF_JGT:
		emit(rv_bgtu(hi(rs1), hi(rs2), JUMP(2)), ctx);
		emit(rv_bltu(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
		emit(rv_bleu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
		break;
	case BPF_JLT:
		emit(rv_bltu(hi(rs1), hi(rs2), JUMP(2)), ctx);
		emit(rv_bgtu(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
		emit(rv_bgeu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
		break;
	case BPF_JGE:
		emit(rv_bgtu(hi(rs1), hi(rs2), JUMP(2)), ctx);
		emit(rv_bltu(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
		emit(rv_bltu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
		break;
	case BPF_JLE:
		emit(rv_bltu(hi(rs1), hi(rs2), JUMP(2)), ctx);
		emit(rv_bgtu(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
		emit(rv_bgtu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
		break;
	case BPF_JNE:
		emit(rv_bne(hi(rs1), hi(rs2), JUMP(1)), ctx);
		emit(rv_beq(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
		break;
	case BPF_JSGT:
		emit(rv_bgt(hi(rs1), hi(rs2), JUMP(2)), ctx);
		emit(rv_blt(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
		emit(rv_bleu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
		break;
	case BPF_JSLT:
		emit(rv_blt(hi(rs1), hi(rs2), JUMP(2)), ctx);
		emit(rv_bgt(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
		emit(rv_bgeu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
		break;
	case BPF_JSGE:
		emit(rv_bgt(hi(rs1), hi(rs2), JUMP(2)), ctx);
		emit(rv_blt(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
		emit(rv_bltu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
		break;
	case BPF_JSLE:
		emit(rv_blt(hi(rs1), hi(rs2), JUMP(2)), ctx);
		emit(rv_bgt(hi(rs1), hi(rs2), NO_JUMP(1)), ctx);
		emit(rv_bgtu(lo(rs1), lo(rs2), NO_JUMP(0)), ctx);
		break;
	case BPF_JSET:
		emit(rv_and(RV_REG_T0, hi(rs1), hi(rs2)), ctx);
		emit(rv_bne(RV_REG_T0, RV_REG_ZERO, JUMP(2)), ctx);
		emit(rv_and(RV_REG_T0, lo(rs1), lo(rs2)), ctx);
		emit(rv_beq(RV_REG_T0, RV_REG_ZERO, NO_JUMP(0)), ctx);
		break;
	}

#undef NO_JUMP
#undef JUMP

	e = ctx->ninsns;
	/* Adjust for extra insns. */
	rvoff -= ninsns_rvoff(e - s);
	emit_jump_and_link(RV_REG_ZERO, rvoff, true, ctx);
	return 0;
}