summaryrefslogtreecommitdiff
path: root/v5/apf_interpreter.c
diff options
context:
space:
mode:
Diffstat (limited to 'v5/apf_interpreter.c')
-rw-r--r--v5/apf_interpreter.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/v5/apf_interpreter.c b/v5/apf_interpreter.c
index 00576f8..dd3850a 100644
--- a/v5/apf_interpreter.c
+++ b/v5/apf_interpreter.c
@@ -257,6 +257,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 */
#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]" */
#define STDW_OPCODE 23 /* Store 4 bytes to data address (register + signed imm): "stdw R0, [5+R1]" */
@@ -800,16 +801,17 @@ static int do_apf_run(apf_context* ctx) {
/* imm is jump target offset. */
/* REG is offset of packet bytes to compare. */
if (cmp_imm > 0xFFFF) return PASS_PACKET;
+ Boolean do_jump = !reg_num;
/* pc < program_len < ram_len < 2GiB, thus pc + cmp_imm cannot wrap */
if (!IN_RAM_BOUNDS(ctx->pc + cmp_imm - 1)) return PASS_PACKET;
ASSERT_IN_PACKET_BOUNDS(REG);
const u32 last_packet_offs = REG + cmp_imm - 1;
ASSERT_RETURN(last_packet_offs >= REG);
ASSERT_IN_PACKET_BOUNDS(last_packet_offs);
- if (memcmp(ctx->program + ctx->pc, ctx->packet + REG, cmp_imm))
- ctx->pc += imm;
+ do_jump ^= !memcmp(ctx->program + ctx->pc, ctx->packet + REG, cmp_imm);
/* skip past comparison bytes */
ctx->pc += cmp_imm;
+ if (do_jump) ctx->pc += imm;
break;
}
/* There is a difference in APFv4 and APFv6 arithmetic behaviour! */