arch/mips/net/bpf_jit_comp32.c

Source file repositories/reference/linux-study-clean/arch/mips/net/bpf_jit_comp32.c

File Facts

System
Linux kernel
Corpus path
arch/mips/net/bpf_jit_comp32.c
Extension
.c
Size
54970 bytes
Lines
1907
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (op) {
		case BPF_ADD:
			op = BPF_SUB;
			imm = -imm;
			break;
		case BPF_SUB:
			op = BPF_ADD;
			imm = -imm;
			break;
		}

	/* Move immediate to temporary register */
	emit_mov_i(ctx, src, imm);

	switch (op) {
	/* dst = dst + imm */
	case BPF_ADD:
		emit(ctx, addu, lo(dst), lo(dst), src);
		emit(ctx, sltu, MIPS_R_T9, lo(dst), src);
		emit(ctx, addu, hi(dst), hi(dst), MIPS_R_T9);
		if (imm < 0)
			emit(ctx, addiu, hi(dst), hi(dst), -1);
		break;
	/* dst = dst - imm */
	case BPF_SUB:
		emit(ctx, sltu, MIPS_R_T9, lo(dst), src);
		emit(ctx, subu, lo(dst), lo(dst), src);
		emit(ctx, subu, hi(dst), hi(dst), MIPS_R_T9);
		if (imm < 0)
			emit(ctx, addiu, hi(dst), hi(dst), 1);
		break;
	/* dst = dst | imm */
	case BPF_OR:
		emit(ctx, or, lo(dst), lo(dst), src);
		if (imm < 0)
			emit(ctx, addiu, hi(dst), MIPS_R_ZERO, -1);
		break;
	/* dst = dst & imm */
	case BPF_AND:
		emit(ctx, and, lo(dst), lo(dst), src);
		if (imm >= 0)
			emit(ctx, move, hi(dst), MIPS_R_ZERO);
		break;
	/* dst = dst ^ imm */
	case BPF_XOR:
		emit(ctx, xor, lo(dst), lo(dst), src);
		if (imm < 0) {
			emit(ctx, subu, hi(dst), MIPS_R_ZERO, hi(dst));
			emit(ctx, addiu, hi(dst), hi(dst), -1);
		}
		break;
	}
	clobber_reg64(ctx, dst);
}

/* ALU register operation (64-bit) */
static void emit_alu_r64(struct jit_context *ctx,
			 const u8 dst[], const u8 src[], u8 op)
{
	switch (BPF_OP(op)) {
	/* dst = dst + src */
	case BPF_ADD:
		if (src == dst) {
			emit(ctx, srl, MIPS_R_T9, lo(dst), 31);
			emit(ctx, addu, lo(dst), lo(dst), lo(dst));
		} else {
			emit(ctx, addu, lo(dst), lo(dst), lo(src));
			emit(ctx, sltu, MIPS_R_T9, lo(dst), lo(src));
		}
		emit(ctx, addu, hi(dst), hi(dst), hi(src));
		emit(ctx, addu, hi(dst), hi(dst), MIPS_R_T9);
		break;
	/* dst = dst - src */
	case BPF_SUB:
		emit(ctx, sltu, MIPS_R_T9, lo(dst), lo(src));
		emit(ctx, subu, lo(dst), lo(dst), lo(src));
		emit(ctx, subu, hi(dst), hi(dst), hi(src));
		emit(ctx, subu, hi(dst), hi(dst), MIPS_R_T9);
		break;
	/* dst = dst | src */
	case BPF_OR:
		emit(ctx, or, lo(dst), lo(dst), lo(src));
		emit(ctx, or, hi(dst), hi(dst), hi(src));
		break;
	/* dst = dst & src */
	case BPF_AND:
		emit(ctx, and, lo(dst), lo(dst), lo(src));
		emit(ctx, and, hi(dst), hi(dst), hi(src));
		break;
	/* dst = dst ^ src */

Annotation

Implementation Notes