static void emit_alu_r64()

in net/bpf_jit_comp32.c [406:509]


static void emit_alu_r64(const s8 *dst, const s8 *src,
			 struct rv_jit_context *ctx, const u8 op)
{
	const s8 *tmp1 = bpf2rv32[TMP_REG_1];
	const s8 *tmp2 = bpf2rv32[TMP_REG_2];
	const s8 *rd = bpf_get_reg64(dst, tmp1, ctx);
	const s8 *rs = bpf_get_reg64(src, tmp2, ctx);

	switch (op) {
	case BPF_MOV:
		emit(rv_addi(lo(rd), lo(rs), 0), ctx);
		emit(rv_addi(hi(rd), hi(rs), 0), ctx);
		break;
	case BPF_ADD:
		if (rd == rs) {
			emit(rv_srli(RV_REG_T0, lo(rd), 31), ctx);
			emit(rv_slli(hi(rd), hi(rd), 1), ctx);
			emit(rv_or(hi(rd), RV_REG_T0, hi(rd)), ctx);
			emit(rv_slli(lo(rd), lo(rd), 1), ctx);
		} else {
			emit(rv_add(lo(rd), lo(rd), lo(rs)), ctx);
			emit(rv_sltu(RV_REG_T0, lo(rd), lo(rs)), ctx);
			emit(rv_add(hi(rd), hi(rd), hi(rs)), ctx);
			emit(rv_add(hi(rd), hi(rd), RV_REG_T0), ctx);
		}
		break;
	case BPF_SUB:
		emit(rv_sub(RV_REG_T1, hi(rd), hi(rs)), ctx);
		emit(rv_sltu(RV_REG_T0, lo(rd), lo(rs)), ctx);
		emit(rv_sub(hi(rd), RV_REG_T1, RV_REG_T0), ctx);
		emit(rv_sub(lo(rd), lo(rd), lo(rs)), ctx);
		break;
	case BPF_AND:
		emit(rv_and(lo(rd), lo(rd), lo(rs)), ctx);
		emit(rv_and(hi(rd), hi(rd), hi(rs)), ctx);
		break;
	case BPF_OR:
		emit(rv_or(lo(rd), lo(rd), lo(rs)), ctx);
		emit(rv_or(hi(rd), hi(rd), hi(rs)), ctx);
		break;
	case BPF_XOR:
		emit(rv_xor(lo(rd), lo(rd), lo(rs)), ctx);
		emit(rv_xor(hi(rd), hi(rd), hi(rs)), ctx);
		break;
	case BPF_MUL:
		emit(rv_mul(RV_REG_T0, hi(rs), lo(rd)), ctx);
		emit(rv_mul(hi(rd), hi(rd), lo(rs)), ctx);
		emit(rv_mulhu(RV_REG_T1, lo(rd), lo(rs)), ctx);
		emit(rv_add(hi(rd), hi(rd), RV_REG_T0), ctx);
		emit(rv_mul(lo(rd), lo(rd), lo(rs)), ctx);
		emit(rv_add(hi(rd), hi(rd), RV_REG_T1), ctx);
		break;
	case BPF_LSH:
		emit(rv_addi(RV_REG_T0, lo(rs), -32), ctx);
		emit(rv_blt(RV_REG_T0, RV_REG_ZERO, 8), ctx);
		emit(rv_sll(hi(rd), lo(rd), RV_REG_T0), ctx);
		emit(rv_addi(lo(rd), RV_REG_ZERO, 0), ctx);
		emit(rv_jal(RV_REG_ZERO, 16), ctx);
		emit(rv_addi(RV_REG_T1, RV_REG_ZERO, 31), ctx);
		emit(rv_srli(RV_REG_T0, lo(rd), 1), ctx);
		emit(rv_sub(RV_REG_T1, RV_REG_T1, lo(rs)), ctx);
		emit(rv_srl(RV_REG_T0, RV_REG_T0, RV_REG_T1), ctx);
		emit(rv_sll(hi(rd), hi(rd), lo(rs)), ctx);
		emit(rv_or(hi(rd), RV_REG_T0, hi(rd)), ctx);
		emit(rv_sll(lo(rd), lo(rd), lo(rs)), ctx);
		break;
	case BPF_RSH:
		emit(rv_addi(RV_REG_T0, lo(rs), -32), ctx);
		emit(rv_blt(RV_REG_T0, RV_REG_ZERO, 8), ctx);
		emit(rv_srl(lo(rd), hi(rd), RV_REG_T0), ctx);
		emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx);
		emit(rv_jal(RV_REG_ZERO, 16), ctx);
		emit(rv_addi(RV_REG_T1, RV_REG_ZERO, 31), ctx);
		emit(rv_slli(RV_REG_T0, hi(rd), 1), ctx);
		emit(rv_sub(RV_REG_T1, RV_REG_T1, lo(rs)), ctx);
		emit(rv_sll(RV_REG_T0, RV_REG_T0, RV_REG_T1), ctx);
		emit(rv_srl(lo(rd), lo(rd), lo(rs)), ctx);
		emit(rv_or(lo(rd), RV_REG_T0, lo(rd)), ctx);
		emit(rv_srl(hi(rd), hi(rd), lo(rs)), ctx);
		break;
	case BPF_ARSH:
		emit(rv_addi(RV_REG_T0, lo(rs), -32), ctx);
		emit(rv_blt(RV_REG_T0, RV_REG_ZERO, 8), ctx);
		emit(rv_sra(lo(rd), hi(rd), RV_REG_T0), ctx);
		emit(rv_srai(hi(rd), hi(rd), 31), ctx);
		emit(rv_jal(RV_REG_ZERO, 16), ctx);
		emit(rv_addi(RV_REG_T1, RV_REG_ZERO, 31), ctx);
		emit(rv_slli(RV_REG_T0, hi(rd), 1), ctx);
		emit(rv_sub(RV_REG_T1, RV_REG_T1, lo(rs)), ctx);
		emit(rv_sll(RV_REG_T0, RV_REG_T0, RV_REG_T1), ctx);
		emit(rv_srl(lo(rd), lo(rd), lo(rs)), ctx);
		emit(rv_or(lo(rd), RV_REG_T0, lo(rd)), ctx);
		emit(rv_sra(hi(rd), hi(rd), lo(rs)), ctx);
		break;
	case BPF_NEG:
		emit(rv_sub(lo(rd), RV_REG_ZERO, lo(rd)), ctx);
		emit(rv_sltu(RV_REG_T0, RV_REG_ZERO, lo(rd)), ctx);
		emit(rv_sub(hi(rd), RV_REG_ZERO, hi(rd)), ctx);
		emit(rv_sub(hi(rd), hi(rd), RV_REG_T0), ctx);
		break;
	}

	bpf_put_reg64(dst, rd, ctx);
}