- struct bytecode_runtime *bytecode = filter_data;
- void *pc, *next_pc, *start_pc;
- int ret = -EINVAL;
- int retval = 0;
- struct reg reg[NR_REG];
- int i;
-
- for (i = 0; i < NR_REG; i++) {
- reg[i].type = REG_S64;
- reg[i].v = 0;
- reg[i].d = 0.0;
- reg[i].str = NULL;
- reg[i].seq_len = 0;
- reg[i].literal = 0;
- }
-
- start_pc = &bytecode->data[0];
- for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
- pc = next_pc) {
- dbg_printf("Executing op %s (%u)\n",
- print_op((unsigned int) *(filter_opcode_t *) pc),
- (unsigned int) *(filter_opcode_t *) pc);
- switch (*(filter_opcode_t *) pc) {
- case FILTER_OP_UNKNOWN:
- default:
- ERR("unknown bytecode op %u\n",
- (unsigned int) *(filter_opcode_t *) pc);
- ret = -EINVAL;
- goto end;
-
- case FILTER_OP_RETURN:
- retval = !!reg[0].v;
- ret = 0;
- goto end;
-
- /* binary */
- case FILTER_OP_MUL:
- case FILTER_OP_DIV:
- case FILTER_OP_MOD:
- case FILTER_OP_PLUS:
- case FILTER_OP_MINUS:
- case FILTER_OP_RSHIFT:
- case FILTER_OP_LSHIFT:
- case FILTER_OP_BIN_AND:
- case FILTER_OP_BIN_OR:
- case FILTER_OP_BIN_XOR:
- ERR("unsupported bytecode op %u\n",
- (unsigned int) *(filter_opcode_t *) pc);
- ret = -EINVAL;
- goto end;
-
- case FILTER_OP_EQ:
- {
- switch (reg[REG_R0].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_STRING:
- reg[REG_R0].v = (reg_strcmp(reg, "==") == 0);
- break;
- case REG_S64:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_S64:
- reg[REG_R0].v = (reg[REG_R0].v == reg[REG_R1].v);
- break;
- case REG_DOUBLE:
- reg[REG_R0].v = (reg[REG_R0].v == reg[REG_R1].d);
- break;
- }
- break;
- case REG_DOUBLE:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_S64:
- reg[REG_R0].v = (reg[REG_R0].d == reg[REG_R1].v);
- break;
- case REG_DOUBLE:
- reg[REG_R0].v = (reg[REG_R0].d == reg[REG_R1].d);
- break;
- }
- break;
- }
- reg[REG_R0].type = REG_S64;
- next_pc += sizeof(struct binary_op);
- break;
- }
- case FILTER_OP_NE:
- {
- switch (reg[REG_R0].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_STRING:
- reg[REG_R0].v = (reg_strcmp(reg, "!=") != 0);
- break;
- case REG_S64:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_S64:
- reg[REG_R0].v = (reg[REG_R0].v != reg[REG_R1].v);
- break;
- case REG_DOUBLE:
- reg[REG_R0].v = (reg[REG_R0].v != reg[REG_R1].d);
- break;
- }
- break;
- case REG_DOUBLE:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_S64:
- reg[REG_R0].v = (reg[REG_R0].d != reg[REG_R1].v);
- break;
- case REG_DOUBLE:
- reg[REG_R0].v = (reg[REG_R0].d != reg[REG_R1].d);
- break;
- }
- break;
- }
- reg[REG_R0].type = REG_S64;
- next_pc += sizeof(struct binary_op);
- break;
- }
- case FILTER_OP_GT:
- {
- switch (reg[REG_R0].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_STRING:
- reg[REG_R0].v = (reg_strcmp(reg, ">") > 0);
- break;
- case REG_S64:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_S64:
- reg[REG_R0].v = (reg[REG_R0].v > reg[REG_R1].v);
- break;
- case REG_DOUBLE:
- reg[REG_R0].v = (reg[REG_R0].v > reg[REG_R1].d);
- break;
- }
- break;
- case REG_DOUBLE:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_S64:
- reg[REG_R0].v = (reg[REG_R0].d > reg[REG_R1].v);
- break;
- case REG_DOUBLE:
- reg[REG_R0].v = (reg[REG_R0].d > reg[REG_R1].d);
- break;
- }
- break;
- }
- reg[REG_R0].type = REG_S64;
- next_pc += sizeof(struct binary_op);
- break;
- }
- case FILTER_OP_LT:
- {
- switch (reg[REG_R0].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_STRING:
- reg[REG_R0].v = (reg_strcmp(reg, "<") < 0);
- break;
- case REG_S64:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_S64:
- reg[REG_R0].v = (reg[REG_R0].v < reg[REG_R1].v);
- break;
- case REG_DOUBLE:
- reg[REG_R0].v = (reg[REG_R0].v < reg[REG_R1].d);
- break;
- }
- break;
- case REG_DOUBLE:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_S64:
- reg[REG_R0].v = (reg[REG_R0].d < reg[REG_R1].v);
- break;
- case REG_DOUBLE:
- reg[REG_R0].v = (reg[REG_R0].d < reg[REG_R1].d);
- break;
- }
- break;
- }
- reg[REG_R0].type = REG_S64;
- next_pc += sizeof(struct binary_op);
- break;
- }
- case FILTER_OP_GE:
- {
- switch (reg[REG_R0].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_STRING:
- reg[REG_R0].v = (reg_strcmp(reg, ">=") >= 0);
- break;
- case REG_S64:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_S64:
- reg[REG_R0].v = (reg[REG_R0].v >= reg[REG_R1].v);
- break;
- case REG_DOUBLE:
- reg[REG_R0].v = (reg[REG_R0].v >= reg[REG_R1].d);
- break;
- }
- break;
- case REG_DOUBLE:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_S64:
- reg[REG_R0].v = (reg[REG_R0].d >= reg[REG_R1].v);
- break;
- case REG_DOUBLE:
- reg[REG_R0].v = (reg[REG_R0].d >= reg[REG_R1].d);
- break;
- }
- break;
- }
- reg[REG_R0].type = REG_S64;
- next_pc += sizeof(struct binary_op);
- break;
- }
- case FILTER_OP_LE:
- {
- switch (reg[REG_R0].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_STRING:
- reg[REG_R0].v = (reg_strcmp(reg, "<=") <= 0);
- break;
- case REG_S64:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;
-
- case REG_S64:
- reg[REG_R0].v = (reg[REG_R0].v <= reg[REG_R1].v);
- break;
- case REG_DOUBLE:
- reg[REG_R0].v = (reg[REG_R0].v <= reg[REG_R1].d);
- break;
- }
- break;
- case REG_DOUBLE:
- switch (reg[REG_R1].type) {
- default:
- ERR("unknown register type\n");
- ret = -EINVAL;
- goto end;