|
@@ -648,3 +648,93 @@ load_ind:
|
|
case BPF_S_ALU_OR_X:
|
|
case BPF_S_ALU_OR_X:
|
|
update_on_xread(ctx);
|
|
update_on_xread(ctx);
|
|
emit(ARM_ORR_R(r_A, r_A, r_X), ctx);
|
|
emit(ARM_ORR_R(r_A, r_A, r_X), ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_ALU_XOR_K:
|
|
|
|
+ /* A ^= K; */
|
|
|
|
+ OP_IMM3(ARM_EOR, r_A, r_A, k, ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_ANC_ALU_XOR_X:
|
|
|
|
+ case BPF_S_ALU_XOR_X:
|
|
|
|
+ /* A ^= X */
|
|
|
|
+ update_on_xread(ctx);
|
|
|
|
+ emit(ARM_EOR_R(r_A, r_A, r_X), ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_ALU_AND_K:
|
|
|
|
+ /* A &= K */
|
|
|
|
+ OP_IMM3(ARM_AND, r_A, r_A, k, ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_ALU_AND_X:
|
|
|
|
+ update_on_xread(ctx);
|
|
|
|
+ emit(ARM_AND_R(r_A, r_A, r_X), ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_ALU_LSH_K:
|
|
|
|
+ if (unlikely(k > 31))
|
|
|
|
+ return -1;
|
|
|
|
+ emit(ARM_LSL_I(r_A, r_A, k), ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_ALU_LSH_X:
|
|
|
|
+ update_on_xread(ctx);
|
|
|
|
+ emit(ARM_LSL_R(r_A, r_A, r_X), ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_ALU_RSH_K:
|
|
|
|
+ if (unlikely(k > 31))
|
|
|
|
+ return -1;
|
|
|
|
+ emit(ARM_LSR_I(r_A, r_A, k), ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_ALU_RSH_X:
|
|
|
|
+ update_on_xread(ctx);
|
|
|
|
+ emit(ARM_LSR_R(r_A, r_A, r_X), ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_ALU_NEG:
|
|
|
|
+ /* A = -A */
|
|
|
|
+ emit(ARM_RSB_I(r_A, r_A, 0), ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_JMP_JA:
|
|
|
|
+ /* pc += K */
|
|
|
|
+ emit(ARM_B(b_imm(i + k + 1, ctx)), ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_JMP_JEQ_K:
|
|
|
|
+ /* pc += (A == K) ? pc->jt : pc->jf */
|
|
|
|
+ condt = ARM_COND_EQ;
|
|
|
|
+ goto cmp_imm;
|
|
|
|
+ case BPF_S_JMP_JGT_K:
|
|
|
|
+ /* pc += (A > K) ? pc->jt : pc->jf */
|
|
|
|
+ condt = ARM_COND_HI;
|
|
|
|
+ goto cmp_imm;
|
|
|
|
+ case BPF_S_JMP_JGE_K:
|
|
|
|
+ /* pc += (A >= K) ? pc->jt : pc->jf */
|
|
|
|
+ condt = ARM_COND_HS;
|
|
|
|
+cmp_imm:
|
|
|
|
+ imm12 = imm8m(k);
|
|
|
|
+ if (imm12 < 0) {
|
|
|
|
+ emit_mov_i_no8m(r_scratch, k, ctx);
|
|
|
|
+ emit(ARM_CMP_R(r_A, r_scratch), ctx);
|
|
|
|
+ } else {
|
|
|
|
+ emit(ARM_CMP_I(r_A, imm12), ctx);
|
|
|
|
+ }
|
|
|
|
+cond_jump:
|
|
|
|
+ if (inst->jt)
|
|
|
|
+ _emit(condt, ARM_B(b_imm(i + inst->jt + 1,
|
|
|
|
+ ctx)), ctx);
|
|
|
|
+ if (inst->jf)
|
|
|
|
+ _emit(condt ^ 1, ARM_B(b_imm(i + inst->jf + 1,
|
|
|
|
+ ctx)), ctx);
|
|
|
|
+ break;
|
|
|
|
+ case BPF_S_JMP_JEQ_X:
|
|
|
|
+ /* pc += (A == X) ? pc->jt : pc->jf */
|
|
|
|
+ condt = ARM_COND_EQ;
|
|
|
|
+ goto cmp_x;
|
|
|
|
+ case BPF_S_JMP_JGT_X:
|
|
|
|
+ /* pc += (A > X) ? pc->jt : pc->jf */
|
|
|
|
+ condt = ARM_COND_HI;
|
|
|
|
+ goto cmp_x;
|
|
|
|
+ case BPF_S_JMP_JGE_X:
|
|
|
|
+ /* pc += (A >= X) ? pc->jt : pc->jf */
|
|
|
|
+ condt = ARM_COND_CS;
|
|
|
|
+cmp_x:
|
|
|
|
+ update_on_xread(ctx);
|
|
|
|
+ emit(ARM_CMP_R(r_A, r_X), ctx);
|
|
|
|
+ goto cond_jump;
|
|
|
|
+ case BPF_S_JMP_JSET_K:
|
|
|
|
+ /* pc += (A & K) ? pc->jt : pc->jf */
|
|
|
|
+ condt = ARM_COND_NE;
|