summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerin Jacob <jerinj@marvell.com>2019-09-03 16:29:35 +0530
committerThomas Monjalon <thomas@monjalon.net>2019-10-12 14:20:29 +0200
commit2b6d22fa9acd7d8835695f8da76bd22d218071ad (patch)
treede89c1a6abce71b1b69e7d278e02f97d8908a0d6
parent9f4469d9e83ab091f664278f581f65a231c1e0da (diff)
downloaddpdk-next-eventdev-2b6d22fa9acd7d8835695f8da76bd22d218071ad.zip
dpdk-next-eventdev-2b6d22fa9acd7d8835695f8da76bd22d218071ad.tar.gz
dpdk-next-eventdev-2b6d22fa9acd7d8835695f8da76bd22d218071ad.tar.xz
bpf/arm: add byte swap operations
add le16, le32, le64, be16, be32 and be64 operations. Signed-off-by: Jerin Jacob <jerinj@marvell.com> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
-rw-r--r--lib/librte_bpf/bpf_jit_arm64.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/librte_bpf/bpf_jit_arm64.c b/lib/librte_bpf/bpf_jit_arm64.c
index fcde358..ec165d6 100644
--- a/lib/librte_bpf/bpf_jit_arm64.c
+++ b/lib/librte_bpf/bpf_jit_arm64.c
@@ -6,6 +6,7 @@
#include <stdbool.h>
#include <rte_common.h>
+#include <rte_byteorder.h>
#include "bpf_impl.h"
@@ -474,6 +475,84 @@ emit_mod(struct a64_jit_ctx *ctx, bool is64, uint8_t tmp, uint8_t rd,
emit_msub(ctx, is64, rd, tmp, rm, rd);
}
+static void
+emit_zero_extend(struct a64_jit_ctx *ctx, uint8_t rd, int32_t imm)
+{
+ switch (imm) {
+ case 16:
+ /* Zero-extend 16 bits into 64 bits */
+ emit_bitfield(ctx, 1, rd, rd, 0, 15, A64_UBFM);
+ break;
+ case 32:
+ /* Zero-extend 32 bits into 64 bits */
+ emit_bitfield(ctx, 1, rd, rd, 0, 31, A64_UBFM);
+ break;
+ case 64:
+ break;
+ default:
+ /* Generate error */
+ emit_insn(ctx, 0, 1);
+ }
+}
+
+static void
+emit_rev(struct a64_jit_ctx *ctx, uint8_t rd, int32_t imm)
+{
+ uint32_t insn;
+
+ insn = 0xdac00000;
+ insn |= rd << 5;
+ insn |= rd;
+
+ switch (imm) {
+ case 16:
+ insn |= 1 << 10;
+ emit_insn(ctx, insn, check_reg(rd));
+ emit_zero_extend(ctx, rd, 16);
+ break;
+ case 32:
+ insn |= 2 << 10;
+ emit_insn(ctx, insn, check_reg(rd));
+ /* Upper 32 bits already cleared */
+ break;
+ case 64:
+ insn |= 3 << 10;
+ emit_insn(ctx, insn, check_reg(rd));
+ break;
+ default:
+ /* Generate error */
+ emit_insn(ctx, insn, 1);
+ }
+}
+
+static int
+is_be(void)
+{
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+static void
+emit_be(struct a64_jit_ctx *ctx, uint8_t rd, int32_t imm)
+{
+ if (is_be())
+ emit_zero_extend(ctx, rd, imm);
+ else
+ emit_rev(ctx, rd, imm);
+}
+
+static void
+emit_le(struct a64_jit_ctx *ctx, uint8_t rd, int32_t imm)
+{
+ if (is_be())
+ emit_rev(ctx, rd, imm);
+ else
+ emit_zero_extend(ctx, rd, imm);
+}
+
static uint8_t
ebpf_to_a64_reg(struct a64_jit_ctx *ctx, uint8_t reg)
{
@@ -896,6 +975,14 @@ emit(struct a64_jit_ctx *ctx, struct rte_bpf *bpf)
case EBPF_ALU64 | EBPF_ARSH | BPF_K:
emit_asr(ctx, is64, dst, imm);
break;
+ /* dst = be##imm(dst) */
+ case (BPF_ALU | EBPF_END | EBPF_TO_BE):
+ emit_be(ctx, dst, imm);
+ break;
+ /* dst = le##imm(dst) */
+ case (BPF_ALU | EBPF_END | EBPF_TO_LE):
+ emit_le(ctx, dst, imm);
+ break;
/* Return r0 */
case (BPF_JMP | EBPF_EXIT):
emit_epilogue(ctx);