|
@@ -402,8 +402,8 @@ __emit_ld_field(struct nfp_prog *nfp_prog, enum shf_sc sc,
|
|
|
}
|
|
|
|
|
|
static void
|
|
|
-emit_ld_field_any(struct nfp_prog *nfp_prog, enum shf_sc sc, u8 shift,
|
|
|
- swreg dst, u8 bmask, swreg src, bool zero)
|
|
|
+emit_ld_field_any(struct nfp_prog *nfp_prog, swreg dst, u8 bmask, swreg src,
|
|
|
+ enum shf_sc sc, u8 shift, bool zero)
|
|
|
{
|
|
|
struct nfp_insn_re_regs reg;
|
|
|
int err;
|
|
@@ -424,7 +424,7 @@ static void
|
|
|
emit_ld_field(struct nfp_prog *nfp_prog, swreg dst, u8 bmask, swreg src,
|
|
|
enum shf_sc sc, u8 shift)
|
|
|
{
|
|
|
- emit_ld_field_any(nfp_prog, sc, shift, dst, bmask, src, false);
|
|
|
+ emit_ld_field_any(nfp_prog, dst, bmask, src, sc, shift, false);
|
|
|
}
|
|
|
|
|
|
static void emit_nop(struct nfp_prog *nfp_prog)
|
|
@@ -504,70 +504,136 @@ wrp_br_special(struct nfp_prog *nfp_prog, enum br_mask mask,
|
|
|
FIELD_PREP(OP_BR_SPECIAL, special);
|
|
|
}
|
|
|
|
|
|
+static void wrp_mov(struct nfp_prog *nfp_prog, swreg dst, swreg src)
|
|
|
+{
|
|
|
+ emit_alu(nfp_prog, dst, reg_none(), ALU_OP_NONE, src);
|
|
|
+}
|
|
|
+
|
|
|
static void wrp_reg_mov(struct nfp_prog *nfp_prog, u16 dst, u16 src)
|
|
|
{
|
|
|
- emit_alu(nfp_prog, reg_both(dst), reg_none(), ALU_OP_NONE, reg_b(src));
|
|
|
+ wrp_mov(nfp_prog, reg_both(dst), reg_b(src));
|
|
|
}
|
|
|
|
|
|
static int
|
|
|
-construct_data_ind_ld(struct nfp_prog *nfp_prog, u16 offset,
|
|
|
- u16 src, bool src_valid, u8 size)
|
|
|
+data_ld(struct nfp_prog *nfp_prog, swreg offset, u8 dst_gpr, int size)
|
|
|
{
|
|
|
unsigned int i;
|
|
|
u16 shift, sz;
|
|
|
- swreg tmp_reg;
|
|
|
|
|
|
/* We load the value from the address indicated in @offset and then
|
|
|
* shift out the data we don't need. Note: this is big endian!
|
|
|
*/
|
|
|
- sz = size < 4 ? 4 : size;
|
|
|
+ sz = max(size, 4);
|
|
|
shift = size < 4 ? 4 - size : 0;
|
|
|
|
|
|
- if (src_valid) {
|
|
|
- /* Calculate the true offset (src_reg + imm) */
|
|
|
- tmp_reg = ur_load_imm_any(nfp_prog, offset, imm_b(nfp_prog));
|
|
|
- emit_alu(nfp_prog, imm_both(nfp_prog),
|
|
|
- reg_a(src), ALU_OP_ADD, tmp_reg);
|
|
|
- /* Check packet length (size guaranteed to fit b/c it's u8) */
|
|
|
- emit_alu(nfp_prog, imm_a(nfp_prog),
|
|
|
- imm_a(nfp_prog), ALU_OP_ADD, reg_imm(size));
|
|
|
- emit_alu(nfp_prog, reg_none(),
|
|
|
- plen_reg(nfp_prog), ALU_OP_SUB, imm_a(nfp_prog));
|
|
|
- wrp_br_special(nfp_prog, BR_BLO, OP_BR_GO_ABORT);
|
|
|
- /* Load data */
|
|
|
- emit_cmd(nfp_prog, CMD_TGT_READ8, CMD_MODE_32b, 0,
|
|
|
- pptr_reg(nfp_prog), imm_b(nfp_prog), sz - 1, true);
|
|
|
- } else {
|
|
|
- /* Check packet length */
|
|
|
- tmp_reg = ur_load_imm_any(nfp_prog, offset + size,
|
|
|
- imm_a(nfp_prog));
|
|
|
- emit_alu(nfp_prog, reg_none(),
|
|
|
- plen_reg(nfp_prog), ALU_OP_SUB, tmp_reg);
|
|
|
- wrp_br_special(nfp_prog, BR_BLO, OP_BR_GO_ABORT);
|
|
|
- /* Load data */
|
|
|
- tmp_reg = re_load_imm_any(nfp_prog, offset, imm_b(nfp_prog));
|
|
|
- emit_cmd(nfp_prog, CMD_TGT_READ8, CMD_MODE_32b, 0,
|
|
|
- pptr_reg(nfp_prog), tmp_reg, sz - 1, true);
|
|
|
- }
|
|
|
+ emit_cmd(nfp_prog, CMD_TGT_READ8, CMD_MODE_32b, 0,
|
|
|
+ pptr_reg(nfp_prog), offset, sz - 1, true);
|
|
|
|
|
|
i = 0;
|
|
|
if (shift)
|
|
|
- emit_shf(nfp_prog, reg_both(0), reg_none(), SHF_OP_NONE,
|
|
|
+ emit_shf(nfp_prog, reg_both(dst_gpr), reg_none(), SHF_OP_NONE,
|
|
|
reg_xfer(0), SHF_SC_R_SHF, shift * 8);
|
|
|
else
|
|
|
for (; i * 4 < size; i++)
|
|
|
- emit_alu(nfp_prog, reg_both(i),
|
|
|
- reg_none(), ALU_OP_NONE, reg_xfer(i));
|
|
|
+ wrp_mov(nfp_prog, reg_both(dst_gpr + i), reg_xfer(i));
|
|
|
|
|
|
if (i < 2)
|
|
|
- wrp_immed(nfp_prog, reg_both(1), 0);
|
|
|
+ wrp_immed(nfp_prog, reg_both(dst_gpr + 1), 0);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+data_ld_host_order(struct nfp_prog *nfp_prog, u8 src_gpr, swreg offset,
|
|
|
+ u8 dst_gpr, int size)
|
|
|
+{
|
|
|
+ unsigned int i;
|
|
|
+ u8 mask, sz;
|
|
|
+
|
|
|
+ /* We load the value from the address indicated in @offset and then
|
|
|
+ * mask out the data we don't need. Note: this is little endian!
|
|
|
+ */
|
|
|
+ sz = max(size, 4);
|
|
|
+ mask = size < 4 ? GENMASK(size - 1, 0) : 0;
|
|
|
+
|
|
|
+ emit_cmd(nfp_prog, CMD_TGT_READ32_SWAP, CMD_MODE_32b, 0,
|
|
|
+ reg_a(src_gpr), offset, sz / 4 - 1, true);
|
|
|
+
|
|
|
+ i = 0;
|
|
|
+ if (mask)
|
|
|
+ emit_ld_field_any(nfp_prog, reg_both(dst_gpr), mask,
|
|
|
+ reg_xfer(0), SHF_SC_NONE, 0, true);
|
|
|
+ else
|
|
|
+ for (; i * 4 < size; i++)
|
|
|
+ wrp_mov(nfp_prog, reg_both(dst_gpr + i), reg_xfer(i));
|
|
|
+
|
|
|
+ if (i < 2)
|
|
|
+ wrp_immed(nfp_prog, reg_both(dst_gpr + 1), 0);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+construct_data_ind_ld(struct nfp_prog *nfp_prog, u16 offset, u16 src, u8 size)
|
|
|
+{
|
|
|
+ swreg tmp_reg;
|
|
|
+
|
|
|
+ /* Calculate the true offset (src_reg + imm) */
|
|
|
+ tmp_reg = ur_load_imm_any(nfp_prog, offset, imm_b(nfp_prog));
|
|
|
+ emit_alu(nfp_prog, imm_both(nfp_prog), reg_a(src), ALU_OP_ADD, tmp_reg);
|
|
|
+
|
|
|
+ /* Check packet length (size guaranteed to fit b/c it's u8) */
|
|
|
+ emit_alu(nfp_prog, imm_a(nfp_prog),
|
|
|
+ imm_a(nfp_prog), ALU_OP_ADD, reg_imm(size));
|
|
|
+ emit_alu(nfp_prog, reg_none(),
|
|
|
+ plen_reg(nfp_prog), ALU_OP_SUB, imm_a(nfp_prog));
|
|
|
+ wrp_br_special(nfp_prog, BR_BLO, OP_BR_GO_ABORT);
|
|
|
+
|
|
|
+ /* Load data */
|
|
|
+ return data_ld(nfp_prog, imm_b(nfp_prog), 0, size);
|
|
|
+}
|
|
|
+
|
|
|
static int construct_data_ld(struct nfp_prog *nfp_prog, u16 offset, u8 size)
|
|
|
{
|
|
|
- return construct_data_ind_ld(nfp_prog, offset, 0, false, size);
|
|
|
+ swreg tmp_reg;
|
|
|
+
|
|
|
+ /* Check packet length */
|
|
|
+ tmp_reg = ur_load_imm_any(nfp_prog, offset + size, imm_a(nfp_prog));
|
|
|
+ emit_alu(nfp_prog, reg_none(), plen_reg(nfp_prog), ALU_OP_SUB, tmp_reg);
|
|
|
+ wrp_br_special(nfp_prog, BR_BLO, OP_BR_GO_ABORT);
|
|
|
+
|
|
|
+ /* Load data */
|
|
|
+ tmp_reg = re_load_imm_any(nfp_prog, offset, imm_b(nfp_prog));
|
|
|
+ return data_ld(nfp_prog, tmp_reg, 0, size);
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+data_stx_host_order(struct nfp_prog *nfp_prog, u8 dst_gpr, swreg offset,
|
|
|
+ u8 src_gpr, u8 size)
|
|
|
+{
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ for (i = 0; i * 4 < size; i++)
|
|
|
+ wrp_mov(nfp_prog, reg_xfer(i), reg_a(src_gpr + i));
|
|
|
+
|
|
|
+ emit_cmd(nfp_prog, CMD_TGT_WRITE8_SWAP, CMD_MODE_32b, 0,
|
|
|
+ reg_a(dst_gpr), offset, size - 1, true);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+data_st_host_order(struct nfp_prog *nfp_prog, u8 dst_gpr, swreg offset,
|
|
|
+ u64 imm, u8 size)
|
|
|
+{
|
|
|
+ wrp_immed(nfp_prog, reg_xfer(0), imm);
|
|
|
+ if (size == 8)
|
|
|
+ wrp_immed(nfp_prog, reg_xfer(1), imm >> 32);
|
|
|
+
|
|
|
+ emit_cmd(nfp_prog, CMD_TGT_WRITE8_SWAP, CMD_MODE_32b, 0,
|
|
|
+ reg_a(dst_gpr), offset, size - 1, true);
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static void
|
|
@@ -720,7 +786,10 @@ wrp_cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
|
|
enum br_mask br_mask, bool swap)
|
|
|
{
|
|
|
const struct bpf_insn *insn = &meta->insn;
|
|
|
- u8 areg = insn->src_reg * 2, breg = insn->dst_reg * 2;
|
|
|
+ u8 areg, breg;
|
|
|
+
|
|
|
+ areg = insn->dst_reg * 2;
|
|
|
+ breg = insn->src_reg * 2;
|
|
|
|
|
|
if (insn->off < 0) /* TODO */
|
|
|
return -EOPNOTSUPP;
|
|
@@ -739,6 +808,14 @@ wrp_cmp_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void wrp_end32(struct nfp_prog *nfp_prog, swreg reg_in, u8 gpr_out)
|
|
|
+{
|
|
|
+ emit_ld_field(nfp_prog, reg_both(gpr_out), 0xf, reg_in,
|
|
|
+ SHF_SC_R_ROT, 8);
|
|
|
+ emit_ld_field(nfp_prog, reg_both(gpr_out), 0x5, reg_a(gpr_out),
|
|
|
+ SHF_SC_R_ROT, 16);
|
|
|
+}
|
|
|
+
|
|
|
/* --- Callbacks --- */
|
|
|
static int mov_reg64(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
@@ -975,6 +1052,35 @@ static int shl_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int end_reg32(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+{
|
|
|
+ const struct bpf_insn *insn = &meta->insn;
|
|
|
+ u8 gpr = insn->dst_reg * 2;
|
|
|
+
|
|
|
+ switch (insn->imm) {
|
|
|
+ case 16:
|
|
|
+ emit_ld_field(nfp_prog, reg_both(gpr), 0x9, reg_b(gpr),
|
|
|
+ SHF_SC_R_ROT, 8);
|
|
|
+ emit_ld_field(nfp_prog, reg_both(gpr), 0xe, reg_a(gpr),
|
|
|
+ SHF_SC_R_SHF, 16);
|
|
|
+
|
|
|
+ wrp_immed(nfp_prog, reg_both(gpr + 1), 0);
|
|
|
+ break;
|
|
|
+ case 32:
|
|
|
+ wrp_end32(nfp_prog, reg_a(gpr), gpr);
|
|
|
+ wrp_immed(nfp_prog, reg_both(gpr + 1), 0);
|
|
|
+ break;
|
|
|
+ case 64:
|
|
|
+ wrp_mov(nfp_prog, imm_a(nfp_prog), reg_b(gpr + 1));
|
|
|
+
|
|
|
+ wrp_end32(nfp_prog, reg_a(gpr), gpr + 1);
|
|
|
+ wrp_end32(nfp_prog, imm_a(nfp_prog), gpr);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int imm_ld8_part2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
wrp_immed(nfp_prog, reg_both(nfp_meta_prev(meta)->insn.dst_reg * 2 + 1),
|
|
@@ -1011,79 +1117,209 @@ static int data_ld4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
static int data_ind_ld1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
return construct_data_ind_ld(nfp_prog, meta->insn.imm,
|
|
|
- meta->insn.src_reg * 2, true, 1);
|
|
|
+ meta->insn.src_reg * 2, 1);
|
|
|
}
|
|
|
|
|
|
static int data_ind_ld2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
return construct_data_ind_ld(nfp_prog, meta->insn.imm,
|
|
|
- meta->insn.src_reg * 2, true, 2);
|
|
|
+ meta->insn.src_reg * 2, 2);
|
|
|
}
|
|
|
|
|
|
static int data_ind_ld4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
return construct_data_ind_ld(nfp_prog, meta->insn.imm,
|
|
|
- meta->insn.src_reg * 2, true, 4);
|
|
|
+ meta->insn.src_reg * 2, 4);
|
|
|
}
|
|
|
|
|
|
-static int mem_ldx4_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+static int mem_ldx_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
|
|
+ u8 size)
|
|
|
{
|
|
|
- if (meta->insn.off == offsetof(struct sk_buff, len))
|
|
|
- emit_alu(nfp_prog, reg_both(meta->insn.dst_reg * 2),
|
|
|
- reg_none(), ALU_OP_NONE, plen_reg(nfp_prog));
|
|
|
- else
|
|
|
+ swreg dst = reg_both(meta->insn.dst_reg * 2);
|
|
|
+
|
|
|
+ switch (meta->insn.off) {
|
|
|
+ case offsetof(struct sk_buff, len):
|
|
|
+ if (size != FIELD_SIZEOF(struct sk_buff, len))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ wrp_mov(nfp_prog, dst, plen_reg(nfp_prog));
|
|
|
+ break;
|
|
|
+ case offsetof(struct sk_buff, data):
|
|
|
+ if (size != sizeof(void *))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ wrp_mov(nfp_prog, dst, pptr_reg(nfp_prog));
|
|
|
+ break;
|
|
|
+ case offsetof(struct sk_buff, cb) +
|
|
|
+ offsetof(struct bpf_skb_data_end, data_end):
|
|
|
+ if (size != sizeof(void *))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+ emit_alu(nfp_prog, dst,
|
|
|
+ plen_reg(nfp_prog), ALU_OP_ADD, pptr_reg(nfp_prog));
|
|
|
+ break;
|
|
|
+ default:
|
|
|
return -EOPNOTSUPP;
|
|
|
+ }
|
|
|
+
|
|
|
+ wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int mem_ldx4_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+static int mem_ldx_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
|
|
+ u8 size)
|
|
|
{
|
|
|
swreg dst = reg_both(meta->insn.dst_reg * 2);
|
|
|
|
|
|
- if (meta->insn.off != offsetof(struct xdp_md, data) &&
|
|
|
- meta->insn.off != offsetof(struct xdp_md, data_end))
|
|
|
+ if (size != sizeof(void *))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ switch (meta->insn.off) {
|
|
|
+ case offsetof(struct xdp_buff, data):
|
|
|
+ wrp_mov(nfp_prog, dst, pptr_reg(nfp_prog));
|
|
|
+ break;
|
|
|
+ case offsetof(struct xdp_buff, data_end):
|
|
|
+ emit_alu(nfp_prog, dst,
|
|
|
+ plen_reg(nfp_prog), ALU_OP_ADD, pptr_reg(nfp_prog));
|
|
|
+ break;
|
|
|
+ default:
|
|
|
return -EOPNOTSUPP;
|
|
|
+ }
|
|
|
|
|
|
- emit_alu(nfp_prog, dst, reg_none(), ALU_OP_NONE, pptr_reg(nfp_prog));
|
|
|
+ wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0);
|
|
|
|
|
|
- if (meta->insn.off == offsetof(struct xdp_md, data))
|
|
|
- return 0;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
- emit_alu(nfp_prog, dst, dst, ALU_OP_ADD, plen_reg(nfp_prog));
|
|
|
+static int
|
|
|
+mem_ldx_data(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
|
|
+ unsigned int size)
|
|
|
+{
|
|
|
+ swreg tmp_reg;
|
|
|
|
|
|
- return 0;
|
|
|
+ tmp_reg = re_load_imm_any(nfp_prog, meta->insn.off, imm_b(nfp_prog));
|
|
|
+
|
|
|
+ return data_ld_host_order(nfp_prog, meta->insn.src_reg * 2, tmp_reg,
|
|
|
+ meta->insn.dst_reg * 2, size);
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+mem_ldx(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
|
|
+ unsigned int size)
|
|
|
+{
|
|
|
+ if (meta->ptr.type == PTR_TO_CTX) {
|
|
|
+ if (nfp_prog->act == NN_ACT_XDP)
|
|
|
+ return mem_ldx_xdp(nfp_prog, meta, size);
|
|
|
+ else
|
|
|
+ return mem_ldx_skb(nfp_prog, meta, size);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (meta->ptr.type == PTR_TO_PACKET)
|
|
|
+ return mem_ldx_data(nfp_prog, meta, size);
|
|
|
+
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+}
|
|
|
+
|
|
|
+static int mem_ldx1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+{
|
|
|
+ return mem_ldx(nfp_prog, meta, 1);
|
|
|
+}
|
|
|
+
|
|
|
+static int mem_ldx2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+{
|
|
|
+ return mem_ldx(nfp_prog, meta, 2);
|
|
|
}
|
|
|
|
|
|
static int mem_ldx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
- int ret;
|
|
|
+ return mem_ldx(nfp_prog, meta, 4);
|
|
|
+}
|
|
|
|
|
|
- if (nfp_prog->act == NN_ACT_XDP)
|
|
|
- ret = mem_ldx4_xdp(nfp_prog, meta);
|
|
|
- else
|
|
|
- ret = mem_ldx4_skb(nfp_prog, meta);
|
|
|
+static int mem_ldx8(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+{
|
|
|
+ return mem_ldx(nfp_prog, meta, 8);
|
|
|
+}
|
|
|
|
|
|
- wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0);
|
|
|
+static int
|
|
|
+mem_st_data(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
|
|
+ unsigned int size)
|
|
|
+{
|
|
|
+ u64 imm = meta->insn.imm; /* sign extend */
|
|
|
+ swreg off_reg;
|
|
|
|
|
|
- return ret;
|
|
|
+ off_reg = re_load_imm_any(nfp_prog, meta->insn.off, imm_b(nfp_prog));
|
|
|
+
|
|
|
+ return data_st_host_order(nfp_prog, meta->insn.dst_reg * 2, off_reg,
|
|
|
+ imm, size);
|
|
|
}
|
|
|
|
|
|
-static int mem_stx4_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+static int mem_st(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
|
|
+ unsigned int size)
|
|
|
{
|
|
|
+ if (meta->ptr.type == PTR_TO_PACKET)
|
|
|
+ return mem_st_data(nfp_prog, meta, size);
|
|
|
+
|
|
|
return -EOPNOTSUPP;
|
|
|
}
|
|
|
|
|
|
-static int mem_stx4_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+static int mem_st1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+{
|
|
|
+ return mem_st(nfp_prog, meta, 1);
|
|
|
+}
|
|
|
+
|
|
|
+static int mem_st2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+{
|
|
|
+ return mem_st(nfp_prog, meta, 2);
|
|
|
+}
|
|
|
+
|
|
|
+static int mem_st4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+{
|
|
|
+ return mem_st(nfp_prog, meta, 4);
|
|
|
+}
|
|
|
+
|
|
|
+static int mem_st8(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
+ return mem_st(nfp_prog, meta, 8);
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+mem_stx_data(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
|
|
+ unsigned int size)
|
|
|
+{
|
|
|
+ swreg off_reg;
|
|
|
+
|
|
|
+ off_reg = re_load_imm_any(nfp_prog, meta->insn.off, imm_b(nfp_prog));
|
|
|
+
|
|
|
+ return data_stx_host_order(nfp_prog, meta->insn.dst_reg * 2, off_reg,
|
|
|
+ meta->insn.src_reg * 2, size);
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+mem_stx(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
|
|
+ unsigned int size)
|
|
|
+{
|
|
|
+ if (meta->ptr.type == PTR_TO_PACKET)
|
|
|
+ return mem_stx_data(nfp_prog, meta, size);
|
|
|
+
|
|
|
return -EOPNOTSUPP;
|
|
|
}
|
|
|
|
|
|
+static int mem_stx1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+{
|
|
|
+ return mem_stx(nfp_prog, meta, 1);
|
|
|
+}
|
|
|
+
|
|
|
+static int mem_stx2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+{
|
|
|
+ return mem_stx(nfp_prog, meta, 2);
|
|
|
+}
|
|
|
+
|
|
|
static int mem_stx4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
- if (nfp_prog->act == NN_ACT_XDP)
|
|
|
- return mem_stx4_xdp(nfp_prog, meta);
|
|
|
- return mem_stx4_skb(nfp_prog, meta);
|
|
|
+ return mem_stx(nfp_prog, meta, 4);
|
|
|
+}
|
|
|
+
|
|
|
+static int mem_stx8(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
+{
|
|
|
+ return mem_stx(nfp_prog, meta, 8);
|
|
|
}
|
|
|
|
|
|
static int jump(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
@@ -1129,22 +1365,22 @@ static int jeq_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
|
|
|
static int jgt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
- return wrp_cmp_imm(nfp_prog, meta, BR_BLO, false);
|
|
|
+ return wrp_cmp_imm(nfp_prog, meta, BR_BLO, true);
|
|
|
}
|
|
|
|
|
|
static int jge_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
- return wrp_cmp_imm(nfp_prog, meta, BR_BHS, true);
|
|
|
+ return wrp_cmp_imm(nfp_prog, meta, BR_BHS, false);
|
|
|
}
|
|
|
|
|
|
static int jlt_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
- return wrp_cmp_imm(nfp_prog, meta, BR_BHS, false);
|
|
|
+ return wrp_cmp_imm(nfp_prog, meta, BR_BLO, false);
|
|
|
}
|
|
|
|
|
|
static int jle_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
- return wrp_cmp_imm(nfp_prog, meta, BR_BLO, true);
|
|
|
+ return wrp_cmp_imm(nfp_prog, meta, BR_BHS, true);
|
|
|
}
|
|
|
|
|
|
static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
@@ -1191,6 +1427,7 @@ static int jne_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
emit_alu(nfp_prog, reg_none(), reg_a(insn->dst_reg * 2),
|
|
|
ALU_OP_OR, reg_b(insn->dst_reg * 2 + 1));
|
|
|
emit_br(nfp_prog, BR_BNE, insn->off, 0);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
|
|
@@ -1226,22 +1463,22 @@ static int jeq_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
|
|
|
static int jgt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
- return wrp_cmp_reg(nfp_prog, meta, BR_BLO, false);
|
|
|
+ return wrp_cmp_reg(nfp_prog, meta, BR_BLO, true);
|
|
|
}
|
|
|
|
|
|
static int jge_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
- return wrp_cmp_reg(nfp_prog, meta, BR_BHS, true);
|
|
|
+ return wrp_cmp_reg(nfp_prog, meta, BR_BHS, false);
|
|
|
}
|
|
|
|
|
|
static int jlt_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
- return wrp_cmp_reg(nfp_prog, meta, BR_BHS, false);
|
|
|
+ return wrp_cmp_reg(nfp_prog, meta, BR_BLO, false);
|
|
|
}
|
|
|
|
|
|
static int jle_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
|
{
|
|
|
- return wrp_cmp_reg(nfp_prog, meta, BR_BLO, true);
|
|
|
+ return wrp_cmp_reg(nfp_prog, meta, BR_BHS, true);
|
|
|
}
|
|
|
|
|
|
static int jset_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
|
|
@@ -1289,6 +1526,7 @@ static const instr_cb_t instr_cb[256] = {
|
|
|
[BPF_ALU | BPF_SUB | BPF_X] = sub_reg,
|
|
|
[BPF_ALU | BPF_SUB | BPF_K] = sub_imm,
|
|
|
[BPF_ALU | BPF_LSH | BPF_K] = shl_imm,
|
|
|
+ [BPF_ALU | BPF_END | BPF_X] = end_reg32,
|
|
|
[BPF_LD | BPF_IMM | BPF_DW] = imm_ld8,
|
|
|
[BPF_LD | BPF_ABS | BPF_B] = data_ld1,
|
|
|
[BPF_LD | BPF_ABS | BPF_H] = data_ld2,
|
|
@@ -1296,8 +1534,18 @@ static const instr_cb_t instr_cb[256] = {
|
|
|
[BPF_LD | BPF_IND | BPF_B] = data_ind_ld1,
|
|
|
[BPF_LD | BPF_IND | BPF_H] = data_ind_ld2,
|
|
|
[BPF_LD | BPF_IND | BPF_W] = data_ind_ld4,
|
|
|
+ [BPF_LDX | BPF_MEM | BPF_B] = mem_ldx1,
|
|
|
+ [BPF_LDX | BPF_MEM | BPF_H] = mem_ldx2,
|
|
|
[BPF_LDX | BPF_MEM | BPF_W] = mem_ldx4,
|
|
|
+ [BPF_LDX | BPF_MEM | BPF_DW] = mem_ldx8,
|
|
|
+ [BPF_STX | BPF_MEM | BPF_B] = mem_stx1,
|
|
|
+ [BPF_STX | BPF_MEM | BPF_H] = mem_stx2,
|
|
|
[BPF_STX | BPF_MEM | BPF_W] = mem_stx4,
|
|
|
+ [BPF_STX | BPF_MEM | BPF_DW] = mem_stx8,
|
|
|
+ [BPF_ST | BPF_MEM | BPF_B] = mem_st1,
|
|
|
+ [BPF_ST | BPF_MEM | BPF_H] = mem_st2,
|
|
|
+ [BPF_ST | BPF_MEM | BPF_W] = mem_st4,
|
|
|
+ [BPF_ST | BPF_MEM | BPF_DW] = mem_st8,
|
|
|
[BPF_JMP | BPF_JA | BPF_K] = jump,
|
|
|
[BPF_JMP | BPF_JEQ | BPF_K] = jeq_imm,
|
|
|
[BPF_JMP | BPF_JGT | BPF_K] = jgt_imm,
|
|
@@ -1434,8 +1682,7 @@ static void nfp_outro_tc_legacy(struct nfp_prog *nfp_prog)
|
|
|
* ife + tx 0x24 -> redir, count as stat1
|
|
|
*/
|
|
|
emit_br_byte_neq(nfp_prog, reg_b(0), 0xff, 0, nfp_prog->tgt_done, 2);
|
|
|
- emit_alu(nfp_prog, reg_a(0),
|
|
|
- reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
|
|
|
+ wrp_mov(nfp_prog, reg_a(0), NFP_BPF_ABI_FLAGS);
|
|
|
emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x11), SHF_SC_L_SHF, 16);
|
|
|
|
|
|
emit_br(nfp_prog, BR_UNC, nfp_prog->tgt_done, 1);
|
|
@@ -1462,8 +1709,7 @@ static void nfp_outro_tc_da(struct nfp_prog *nfp_prog)
|
|
|
|
|
|
emit_br_def(nfp_prog, nfp_prog->tgt_done, 2);
|
|
|
|
|
|
- emit_alu(nfp_prog, reg_a(0),
|
|
|
- reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
|
|
|
+ wrp_mov(nfp_prog, reg_a(0), NFP_BPF_ABI_FLAGS);
|
|
|
emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x11), SHF_SC_L_SHF, 16);
|
|
|
|
|
|
/* Target for normal exits */
|
|
@@ -1472,8 +1718,7 @@ static void nfp_outro_tc_da(struct nfp_prog *nfp_prog)
|
|
|
/* if R0 > 7 jump to abort */
|
|
|
emit_alu(nfp_prog, reg_none(), reg_imm(7), ALU_OP_SUB, reg_b(0));
|
|
|
emit_br(nfp_prog, BR_BLO, nfp_prog->tgt_abort, 0);
|
|
|
- emit_alu(nfp_prog, reg_a(0),
|
|
|
- reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
|
|
|
+ wrp_mov(nfp_prog, reg_a(0), NFP_BPF_ABI_FLAGS);
|
|
|
|
|
|
wrp_immed(nfp_prog, reg_b(2), 0x41221211);
|
|
|
wrp_immed(nfp_prog, reg_b(3), 0x41001211);
|
|
@@ -1510,8 +1755,7 @@ static void nfp_outro_xdp(struct nfp_prog *nfp_prog)
|
|
|
|
|
|
emit_br_def(nfp_prog, nfp_prog->tgt_done, 2);
|
|
|
|
|
|
- emit_alu(nfp_prog, reg_a(0),
|
|
|
- reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
|
|
|
+ wrp_mov(nfp_prog, reg_a(0), NFP_BPF_ABI_FLAGS);
|
|
|
emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_imm(0x82), SHF_SC_L_SHF, 16);
|
|
|
|
|
|
/* Target for normal exits */
|
|
@@ -1532,8 +1776,7 @@ static void nfp_outro_xdp(struct nfp_prog *nfp_prog)
|
|
|
|
|
|
emit_br_def(nfp_prog, nfp_prog->tgt_done, 2);
|
|
|
|
|
|
- emit_alu(nfp_prog, reg_a(0),
|
|
|
- reg_none(), ALU_OP_NONE, NFP_BPF_ABI_FLAGS);
|
|
|
+ wrp_mov(nfp_prog, reg_a(0), NFP_BPF_ABI_FLAGS);
|
|
|
emit_ld_field(nfp_prog, reg_a(0), 0xc, reg_b(2), SHF_SC_L_SHF, 16);
|
|
|
}
|
|
|
|