############################################################################### # BPF Processor Specification for Ghidra ############################################################################### define space ram type=ram_space size=4 default; define space packet type=ram_space size=4; define space mem type=ram_space size=4; define space register type=register_space size=4; define register offset=0 size=4 [ A X RS R PC ]; define register offset=0 size=2 [ AH _ XH _ RSH _ RH _ PCH _ ]; define register offset=0 size=1 [ AB _ _ _ XB _ _ _ RSB _ _ _ RB _ _ _ PCB _ _ _ ]; # Instruction encoding: Insop:8, dst_reg:4, src_reg:4, off:16, imm:32 - from lsb to msb define token instr(64) imm=(32, 63) jf=(24, 31) signed jt=(16, 23) signed op_src_K_X=(3, 3) op_alu_jmp_opcode=(4, 7) op_alu_jmp_source=(3, 3) op_alu_mode=(4, 7) op_ld_st_mode=(5, 7) op_ld_st_size=(3, 4) op_insn_class=(0, 2) ; :LD imm is imm & op_ld_st_mode=0x0 & op_ld_st_size=0x0 & op_insn_class=0x0 { A=imm; } :LDH imm is imm & op_ld_st_mode=0x0 & op_ld_st_size=0x1 & op_insn_class=0x0 { AH=imm:2; A = A & 0xffff; } :LDB imm is imm & op_ld_st_mode=0x0 & op_ld_st_size=0x2 & op_insn_class=0x0 { AB=imm:1; A = A & 0xff;} :LDX imm is imm & op_ld_st_mode=0x0 & op_ld_st_size=0x0 & op_insn_class=0x1 { X=imm; } :LDXH imm is imm & op_ld_st_mode=0x0 & op_ld_st_size=0x1 & op_insn_class=0x1 { XH=imm:2; X = X & 0xffff; } :LDXB imm is imm & op_ld_st_mode=0x0 & op_ld_st_size=0x2 & op_insn_class=0x1 { XB=imm:1; X = X & 0xff;} :LD imm is imm & op_ld_st_mode=0x1 & op_ld_st_size=0x0 & op_insn_class=0x0 { A=*[packet]:4 imm:4; } :LDH imm is imm & op_ld_st_mode=0x1 & op_ld_st_size=0x1 & op_insn_class=0x0 { A=*[packet]:2 imm:4; A = A & 0xffff; } :LDB imm is imm & op_ld_st_mode=0x1 & op_ld_st_size=0x2 & op_insn_class=0x0 { A=*[packet]:1 imm:4; A = A & 0xff;} :LDX imm is imm & op_ld_st_mode=0x1 & op_ld_st_size=0x0 & op_insn_class=0x1 { X=*[packet]:4 imm:4; } :LDXH imm is imm & op_ld_st_mode=0x1 & op_ld_st_size=0x1 & op_insn_class=0x1 { X=*[packet]:2 imm:4; X = X & 0xffff; } :LDXB imm is imm & op_ld_st_mode=0x1 & op_ld_st_size=0x2 & op_insn_class=0x1 { X=*[packet]:1 imm:4; X = X & 0xff;} :ST imm is imm & op_insn_class=0x2 { *[mem]:4 imm:4=A:4; } :STX imm is imm & op_insn_class=0x3 { *[mem]:4 imm:4=X:4; } :LDI imm is imm & op_ld_st_mode=0x2 & op_ld_st_size=0x0 & op_insn_class=0x0 { A=*[packet]:4 (imm:4 + X); } :LDIH imm is imm & op_ld_st_mode=0x2 & op_ld_st_size=0x1 & op_insn_class=0x0 { A=*[packet]:2 (imm:4 + X); A = A & 0xffff; } :LDIB imm is imm & op_ld_st_mode=0x2 & op_ld_st_size=0x2 & op_insn_class=0x0 { A=*[packet]:1 (imm:4 + X); A = A & 0xff; } :LD imm is imm & op_ld_st_mode=0x3 & op_ld_st_size=0x0 & op_insn_class=0x0 { A=*[mem]:4 imm:4; } :LDH imm is imm & op_ld_st_mode=0x3 & op_ld_st_size=0x1 & op_insn_class=0x0 { A=*[mem]:2 imm:4; A = A & 0xffff; } :LDB imm is imm & op_ld_st_mode=0x3 & op_ld_st_size=0x2 & op_insn_class=0x0 { A=*[mem]:1 imm:4; A = A & 0xff; } :LDX imm is imm & op_ld_st_mode=0x3 & op_ld_st_size=0x0 & op_insn_class=0x1 { X=*[mem]:4 imm:4; } :LDXH imm is imm & op_ld_st_mode=0x3 & op_ld_st_size=0x1 & op_insn_class=0x1 { X=*[mem]:2 imm:4; X = X & 0xffff; } :LDXB imm is imm & op_ld_st_mode=0x3 & op_ld_st_size=0x2 & op_insn_class=0x1 { X=*[mem]:1 imm:4; X = X & 0xff; } # ALU :ADD imm is imm & op_alu_mode=0x0 & op_insn_class=0x4 & op_src_K_X = 0x0 { A= A + imm; } :ADD X is X & op_alu_mode=0x0 & op_insn_class=0x4 & op_src_K_X = 0x1 { A= A + X; } :SUB imm is imm & op_alu_mode=0x1 & op_insn_class=0x4 & op_src_K_X = 0x0 { A= A - imm; } :SUB X is X & op_alu_mode=0x1 & op_insn_class=0x4 & op_src_K_X = 0x1 { A= A - X; } :MUL imm is imm & op_alu_mode=0x2 & op_insn_class=0x4 & op_src_K_X = 0x0 { A= A * imm; } :MUL X is X & op_alu_mode=0x2 & op_insn_class=0x4 & op_src_K_X = 0x1 { A= A * X; } :DIV imm is imm & op_alu_mode=0x3 & op_insn_class=0x4 & op_src_K_X = 0x0 { A= A / imm; } :DIV X is X & op_alu_mode=0x3 & op_insn_class=0x4 & op_src_K_X = 0x1 { A= A / X; } :OR imm is imm & op_alu_mode=0x4 & op_insn_class=0x4 & op_src_K_X = 0x0 { A= A | imm; } :OR X is X & op_alu_mode=0x4 & op_insn_class=0x4 & op_src_K_X = 0x1 { A= A | X; } :AND imm is imm & op_alu_mode=0x5 & op_insn_class=0x4 & op_src_K_X = 0x0 { A= A & imm; } :AND X is X & op_alu_mode=0x5 & op_insn_class=0x4 & op_src_K_X = 0x1 { A= A & X; } :LSH imm is imm & op_alu_mode=0x6 & op_insn_class=0x4 & op_src_K_X = 0x0 { A= A << imm; } :LSH X is X & op_alu_mode=0x6 & op_insn_class=0x4 & op_src_K_X = 0x1 { A= A << X; } :RSH imm is imm & op_alu_mode=0x7 & op_insn_class=0x4 & op_src_K_X = 0x0 { A= A >> imm; } :RSH X is X & op_alu_mode=0x7 & op_insn_class=0x4 & op_src_K_X = 0x1 { A= A >> X; } :NEG is op_alu_mode=0x8 & op_insn_class=0x4 & op_src_K_X = 0x0 { A= -A; } :MOD imm is imm & op_alu_mode=0x9 & op_insn_class=0x4 & op_src_K_X = 0x0 { A= A % imm; } :MOD X is X & op_alu_mode=0x9 & op_insn_class=0x4 & op_src_K_X = 0x1 { A= A % X; } :XOR imm is imm & op_alu_mode=0xa & op_insn_class=0x4 & op_src_K_X = 0x0 { A= A ^ imm; } :XOR X is X & op_alu_mode=0xa & op_insn_class=0x4 & op_src_K_X = 0x1 { A= A ^ X; } :TAX is op_insn_class=0x7 & op_src_K_X = 0x0 { A= X; } :TXA is op_insn_class=0x7 & op_src_K_X = 0x1 { X= A; } :LD_MSH imm is imm & op_ld_st_mode=0x5 & op_ld_st_size=0x0 & op_insn_class=0x0 { local t_val = *[packet]:4 imm:4; t_val = t_val&0xf; t_val = t_val << 2; A = t_val; } :LDH_MSH imm is imm & op_ld_st_mode=0x5 & op_ld_st_size=0x1 & op_insn_class=0x0 { local t_val = *[packet]:2 imm:4; t_val = t_val&0xf; t_val = t_val << 2; AH = t_val; } :LDB_MSH imm is imm & op_ld_st_mode=0x5 & op_ld_st_size=0x2 & op_insn_class=0x0 { local t_val = *[packet]:1 imm:4; t_val = t_val&0xf; t_val = t_val << 2; AB = t_val; } :LDX_MSH imm is imm & op_ld_st_mode=0x5 & op_ld_st_size=0x0 & op_insn_class=0x1 { local t_val = *[packet]:4 imm:4; t_val = t_val&0xf; t_val = t_val << 2; X = t_val; } :LDXH_MSH imm is imm & op_ld_st_mode=0x5 & op_ld_st_size=0x1 & op_insn_class=0x1 { local t_val = *[packet]:2 imm:4; t_val = t_val&0xf; t_val = t_val << 2; XH = t_val; X = X & 0xffff; } :LDXB_MSH imm is imm & op_ld_st_mode=0x5 & op_ld_st_size=0x2 & op_insn_class=0x1 { local t_val = *[packet]:1 imm:4; t_val = t_val&0xf; t_val = t_val << 2; XB = t_val; X = X & 0xff; } #Branch instructions ############################################################################### joff: reloc is imm [ reloc = inst_next + imm * 8; ] { export *:8 reloc; } jtoff: reloc is jt [ reloc = inst_next + jt * 8; ] { export *:8 reloc; } jfoff: reloc is jf [ reloc = inst_next + jf * 8; ] { export *:8 reloc; } :JA joff is joff & op_alu_jmp_opcode=0x0 & op_alu_jmp_source=0 & op_insn_class=0x5 { goto joff; } :JEQ jtoff, jfoff, imm is imm & jtoff & jfoff & op_alu_jmp_opcode=0x1 & op_alu_jmp_source=0 & op_insn_class=0x5 { if (A==imm) goto jtoff; goto jfoff; } :JEQ jtoff, jfoff, X is X & jtoff & jfoff & op_alu_jmp_opcode=0x1 & op_alu_jmp_source=1 & op_insn_class=0x5 { if (A==X) goto jtoff; goto jfoff; } :JGT jtoff, jfoff, imm is imm & jtoff & jfoff & op_alu_jmp_opcode=0x2 & op_alu_jmp_source=0 & op_insn_class=0x5 { if (A > imm) goto jtoff; goto jfoff; } :JGT jtoff, jfoff, X is X & jtoff & jfoff & op_alu_jmp_opcode=0x2 & op_alu_jmp_source=1 & op_insn_class=0x5 { if (A > X) goto jtoff; goto jfoff; } :JGE jtoff, jfoff, imm is imm & jtoff & jfoff & op_alu_jmp_opcode=0x3 & op_alu_jmp_source=0 & op_insn_class=0x5 { if (A >= imm) goto jtoff; goto jfoff; } :JGE jtoff, jfoff, X is X & jtoff & jfoff & op_alu_jmp_opcode=0x3 & op_alu_jmp_source=1 & op_insn_class=0x5 { if (A >= X) goto jtoff; goto jfoff; } :JSET jtoff, jfoff, imm is imm & jtoff & jfoff & op_alu_jmp_opcode=0x4 & op_alu_jmp_source=0 & op_insn_class=0x5 { if ((A&imm) != 0) goto jtoff; goto jfoff; } :JSET jtoff, jfoff, X is X & jtoff & jfoff & op_alu_jmp_opcode=0x4 & op_alu_jmp_source=1 & op_insn_class=0x5 { if ((A&X) != 0) goto jtoff; goto jfoff; } :RETW imm is imm & op_ld_st_size=0 & op_insn_class=0x6 { R = imm; return [*:8 RS]; }