diff options
author | Maciej Żenczykowski <maze@google.com> | 2024-04-24 15:34:10 -0700 |
---|---|---|
committer | Maciej Żenczykowski <maze@google.com> | 2024-04-24 18:13:49 -0700 |
commit | 75d1f33b8cd8c25f8f87e116511ec57c6975a779 (patch) | |
tree | 1785bc07cc217b381c23093906da077aa44c036b | |
parent | 7cc11e08cb8ba5f2161defe5c9a3d93bdd7f158a (diff) | |
download | apf-75d1f33b8cd8c25f8f87e116511ec57c6975a779.tar.gz |
v5: add JBSMATCH multi match support
After:
text data bss dec hex filename
4128 0 0 4128 1020 apf_interpreter.arm.o
text data bss dec hex filename
5354 0 0 5354 14ea apf_interpreter.x86.o
Test: TreeHugger, manually
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: Ib558903a8dd7d92f0dd84a47521af94eb53b4216
-rw-r--r-- | v5/apf.h | 2 | ||||
-rw-r--r-- | v5/apf_interpreter.c | 23 | ||||
-rw-r--r-- | v5/apf_interpreter_source.c | 21 |
3 files changed, 28 insertions, 18 deletions
@@ -185,7 +185,7 @@ typedef union { #define JLT_OPCODE 18 // Compare less than and branch, e.g. "jlt R0,5,label" #define JSET_OPCODE 19 // Compare any bits set and branch, e.g. "jset R0,5,label" #define JBSMATCH_OPCODE 20 // Compare byte sequence [R=0 not] equal, e.g. "jbsne R0,2,label,0x1122" - // NOTE: Only APFv6+ implements R=1 'jbseq' version + // NOTE: Only APFv6+ implements R=1 'jbseq' version and multi match #define EXT_OPCODE 21 // Immediate value is one of *_EXT_OPCODE #define LDDW_OPCODE 22 // Load 4 bytes from data address (register + signed imm): "lddw R0, [5+R1]" // LDDW/STDW in APFv6+ *mode* load/store from counter specified in imm. diff --git a/v5/apf_interpreter.c b/v5/apf_interpreter.c index 077665b..93124e0 100644 --- a/v5/apf_interpreter.c +++ b/v5/apf_interpreter.c @@ -241,7 +241,7 @@ typedef union { #define JLT_OPCODE 18 /* Compare less than and branch, e.g. "jlt R0,5,label" */ #define JSET_OPCODE 19 /* Compare any bits set and branch, e.g. "jset R0,5,label" */ #define JBSMATCH_OPCODE 20 /* Compare byte sequence [R=0 not] equal, e.g. "jbsne R0,2,label,0x1122" */ - /* NOTE: Only APFv6+ implements R=1 'jbseq' version */ + /* NOTE: Only APFv6+ implements R=1 'jbseq' version and multi match */ #define EXT_OPCODE 21 /* Immediate value is one of *_EXT_OPCODE */ #define LDDW_OPCODE 22 /* Load 4 bytes from data address (register + signed imm): "lddw R0, [5+R1]" */ /* LDDW/STDW in APFv6+ *mode* load/store from counter specified in imm. */ @@ -804,21 +804,26 @@ static int do_apf_run(apf_context* ctx) { case JBSMATCH_OPCODE: { /* Load second immediate field. */ u32 cmp_imm = decode_imm(ctx, imm_len); /* 2nd imm, at worst 8 bytes past prog_len */ - const u32 last_packet_offs = ctx->R[0] + cmp_imm - 1; + u32 cnt = (cmp_imm >> 11) + 1; /* 1+, up to 32 fits in u16 */ + u32 len = cmp_imm & 2047; /* 0..2047 */ + u32 bytes = cnt * len; + const u32 last_packet_offs = ctx->R[0] + len - 1; Boolean do_jump = !reg_num; - /* cmp_imm is size in bytes of data to compare. */ + /* bytes = cnt * len is size in bytes of data to compare. */ /* pc is offset of program bytes to compare. */ /* imm is jump target offset. */ /* R0 is offset of packet bytes to compare. */ - if (cmp_imm > 0xFFFF) return EXCEPTION; - /* pc < program_len < ram_len < 2GiB, thus pc + cmp_imm cannot wrap */ - if (!IN_RAM_BOUNDS(ctx->pc + cmp_imm - 1)) return EXCEPTION; + if (bytes > 0xFFFF) return EXCEPTION; + /* pc < program_len < ram_len < 2GiB, thus pc + bytes cannot wrap */ + if (!IN_RAM_BOUNDS(ctx->pc + bytes - 1)) return EXCEPTION; ASSERT_IN_PACKET_BOUNDS(ctx->R[0]); ASSERT_RETURN(last_packet_offs >= ctx->R[0]); ASSERT_IN_PACKET_BOUNDS(last_packet_offs); - do_jump ^= !memcmp(ctx->program + ctx->pc, ctx->packet + ctx->R[0], cmp_imm); - /* skip past comparison bytes */ - ctx->pc += cmp_imm; + while (cnt--) { + do_jump ^= !memcmp(ctx->program + ctx->pc, ctx->packet + ctx->R[0], len); + /* skip past comparison bytes */ + ctx->pc += len; + } if (do_jump) ctx->pc += imm; break; } diff --git a/v5/apf_interpreter_source.c b/v5/apf_interpreter_source.c index 5f1d4fa..949b57b 100644 --- a/v5/apf_interpreter_source.c +++ b/v5/apf_interpreter_source.c @@ -269,21 +269,26 @@ static int do_apf_run(apf_context* ctx) { case JBSMATCH_OPCODE: { // Load second immediate field. u32 cmp_imm = decode_imm(ctx, imm_len); // 2nd imm, at worst 8 bytes past prog_len - const u32 last_packet_offs = ctx->R[0] + cmp_imm - 1; + u32 cnt = (cmp_imm >> 11) + 1; // 1+, up to 32 fits in u16 + u32 len = cmp_imm & 2047; // 0..2047 + u32 bytes = cnt * len; + const u32 last_packet_offs = ctx->R[0] + len - 1; bool do_jump = !reg_num; - // cmp_imm is size in bytes of data to compare. + // bytes = cnt * len is size in bytes of data to compare. // pc is offset of program bytes to compare. // imm is jump target offset. // R0 is offset of packet bytes to compare. - if (cmp_imm > 0xFFFF) return EXCEPTION; - // pc < program_len < ram_len < 2GiB, thus pc + cmp_imm cannot wrap - if (!IN_RAM_BOUNDS(ctx->pc + cmp_imm - 1)) return EXCEPTION; + if (bytes > 0xFFFF) return EXCEPTION; + // pc < program_len < ram_len < 2GiB, thus pc + bytes cannot wrap + if (!IN_RAM_BOUNDS(ctx->pc + bytes - 1)) return EXCEPTION; ASSERT_IN_PACKET_BOUNDS(ctx->R[0]); ASSERT_RETURN(last_packet_offs >= ctx->R[0]); ASSERT_IN_PACKET_BOUNDS(last_packet_offs); - do_jump ^= !memcmp(ctx->program + ctx->pc, ctx->packet + ctx->R[0], cmp_imm); - // skip past comparison bytes - ctx->pc += cmp_imm; + while (cnt--) { + do_jump ^= !memcmp(ctx->program + ctx->pc, ctx->packet + ctx->R[0], len); + // skip past comparison bytes + ctx->pc += len; + } if (do_jump) ctx->pc += imm; break; } |