summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaciej Żenczykowski <maze@google.com>2024-04-24 15:34:10 -0700
committerMaciej Żenczykowski <maze@google.com>2024-04-24 18:13:49 -0700
commit75d1f33b8cd8c25f8f87e116511ec57c6975a779 (patch)
tree1785bc07cc217b381c23093906da077aa44c036b
parent7cc11e08cb8ba5f2161defe5c9a3d93bdd7f158a (diff)
downloadapf-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.h2
-rw-r--r--v5/apf_interpreter.c23
-rw-r--r--v5/apf_interpreter_source.c21
3 files changed, 28 insertions, 18 deletions
diff --git a/v5/apf.h b/v5/apf.h
index 7eef431..454bf14 100644
--- a/v5/apf.h
+++ b/v5/apf.h
@@ -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;
}