示例#1
0
文件: vm.c 项目: shun-honda/ScriptC
long vm_execute(VMContext ctx, ScriptCInstruction inst) {
  static const void *table[] = {
#define DEFINE_TABLE(NAME) &&OP_##NAME,
    IR_EACH(DEFINE_TABLE)
#undef DEFINE_TABLE
  };

  if(inst == NULL) {
    return (long)table;
  }

  register ScriptCInstruction pc = inst+1;

  goto *GET_ADDR(pc);

  OP(exit) {
    return 0;
  }
  OP(call) {
    ctx = createVMContext(ctx, pc-inst+1);
    JUMP(inst + pc->call_point);
  }
  OP(ret) {
    long retPoint = ctx->retPoint;
    Type top = pop_sp(ctx);
    VMContext next = call_back(ctx);
    if(top->type == TYPE_INT) {
      push_i(next, top->int_val);
    } else if(top->type == TYPE_FLOAT) {
      push_d(next, top->double_val);
    } else if(top->type == TYPE_STRING) {
      push_s(next, top->string);
    } else if(top->type == TYPE_BOOL) {
      push_b(next, top->bool_val);
    } else {
      fprintf(stderr, "type error of return statement\n");
      return 1;
    }
    disposeVMContext(ctx);
    ctx = next;
    JUMP(inst + retPoint);
  }
  OP(ret_void) {
    long retPoint = ctx->retPoint;
    VMContext next = call_back(ctx);
    disposeVMContext(ctx);
    ctx = next;
    JUMP(inst + retPoint);
  }
  OP(iconst) {
    push_i(ctx, pc->int_val);
    DISPATCH_NEXT;
  }
  OP(dconst) {
    push_d(ctx, pc->double_val);
    DISPATCH_NEXT;
  }
  OP(sconst) {
    push_s(ctx, pc->string);
    DISPATCH_NEXT;
  }
  OP(bconst) {
    push_b(ctx, pc->bool_val);
    DISPATCH_NEXT;
  }
  OP(jump) {
    JUMP(inst + pc->jump);
  }
  OP(ifcmp) {
    Type top = pop_sp(ctx);
    if(top->type != TYPE_BOOL) {
      fprintf(stderr, "type error of ifcmp\n");
    }
    if(!top->bool_val) {
      JUMP(inst + pc->jump);
    }
    DISPATCH_NEXT;
  }
  OP(gt) {
    Type right = pop_sp(ctx);
    Type left = pop_sp(ctx);
    if(right->type == TYPE_INT && left->type == TYPE_INT) {
      push_b(ctx, left->int_val > right->int_val);
    } else if(right->type == TYPE_FLOAT && left->type == TYPE_FLOAT) {
      push_b(ctx, left->double_val > right->double_val);
    } else {
      fprintf(stderr, "type error of gt expression\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(ge) {
    Type right = pop_sp(ctx);
    Type left = pop_sp(ctx);
    if(right->type == TYPE_INT && left->type == TYPE_INT) {
      push_b(ctx, left->int_val >= right->int_val);
    } else if(right->type == TYPE_FLOAT && left->type == TYPE_FLOAT) {
      push_b(ctx, left->double_val >= right->double_val);
    } else {
      fprintf(stderr, "type error of ge expression\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(lt) {
    Type right = pop_sp(ctx);
    Type left = pop_sp(ctx);
    if(right->type == TYPE_INT && left->type == TYPE_INT) {
      push_b(ctx, left->int_val < right->int_val);
    } else if(right->type == TYPE_FLOAT && left->type == TYPE_FLOAT) {
      push_b(ctx, left->double_val < right->double_val);
    } else {
      fprintf(stderr, "type error of lt expression\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(le) {
    Type right = pop_sp(ctx);
    Type left = pop_sp(ctx);
    if(right->type == TYPE_INT && left->type == TYPE_INT) {
      push_b(ctx, left->int_val <= right->int_val);
    } else if(right->type == TYPE_FLOAT && left->type == TYPE_FLOAT) {
      push_b(ctx, left->double_val <= right->double_val);
    } else {
      fprintf(stderr, "type error of le expression\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(eq) {
    Type right = pop_sp(ctx);
    Type left = pop_sp(ctx);
    if(right->type == TYPE_INT && left->type == TYPE_INT) {
      push_b(ctx, left->int_val == right->int_val);
    } else if(right->type == TYPE_FLOAT && left->type == TYPE_FLOAT) {
      push_b(ctx, left->double_val == right->double_val);
    } else if(right->type == TYPE_STRING && left->type == TYPE_STRING) {
      push_b(ctx, !strcmp(left->string, right->string));
    } else if(right->type == TYPE_BOOL && left->type == TYPE_BOOL) {
      push_b(ctx, left->bool_val == right->bool_val);
    } else {
      fprintf(stderr, "type error of le expression\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(ne) {
    Type right = pop_sp(ctx);
    Type left = pop_sp(ctx);
    if(right->type == TYPE_INT && left->type == TYPE_INT) {
      push_b(ctx, left->int_val != right->int_val);
    } else if(right->type == TYPE_FLOAT && left->type == TYPE_FLOAT) {
      push_b(ctx, left->double_val != right->double_val);
    } else if(right->type == TYPE_STRING && left->type == TYPE_STRING) {
      push_b(ctx, strcmp(left->string, right->string));
    } else if(right->type == TYPE_BOOL && left->type == TYPE_BOOL) {
      push_b(ctx, left->bool_val != right->bool_val);
    } else {
      fprintf(stderr, "type error of le expression\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(add) {
    Type right = pop_sp(ctx);
    Type left = pop_sp(ctx);
    if(right->type == TYPE_INT && left->type == TYPE_INT) {
      push_i(ctx, left->int_val + right->int_val);
    } else if(right->type == TYPE_FLOAT && left->type == TYPE_FLOAT) {
      push_d(ctx, left->double_val + right->double_val);
    } else if(right->type == TYPE_STRING && left->type == TYPE_STRING) {
      strcat(left->string, right->string);
      push_s(ctx, left->string);
    } else {
      fprintf(stderr, "type error of add expression\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(sub) {
    Type right = pop_sp(ctx);
    Type left = pop_sp(ctx);
    if(right->type == TYPE_INT && left->type == TYPE_INT) {
      push_i(ctx, left->int_val - right->int_val);
    } else if(right->type == TYPE_FLOAT && left->type == TYPE_FLOAT) {
      push_d(ctx, left->double_val - right->double_val);
    } else {
      fprintf(stderr, "type error of sub expression\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(mul) {
    Type right = pop_sp(ctx);
    Type left = pop_sp(ctx);
    if(right->type == TYPE_INT && left->type == TYPE_INT) {
      push_i(ctx, left->int_val * right->int_val);
    } else if(right->type == TYPE_FLOAT && left->type == TYPE_FLOAT) {
      push_d(ctx, left->double_val * right->double_val);
    } else {
      fprintf(stderr, "type error of mul expression\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(div) {
    Type right = pop_sp(ctx);
    Type left = pop_sp(ctx);
    if(right->type == TYPE_INT && left->type == TYPE_INT) {
      push_i(ctx, left->int_val / right->int_val);
    } else if(right->type == TYPE_FLOAT && left->type == TYPE_FLOAT) {
      push_d(ctx, left->double_val / right->double_val);
    } else {
      fprintf(stderr, "type error of div expression\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(minus) {
    Type left = pop_sp(ctx);
    if(left->type == TYPE_INT) {
      push_i(ctx, -left->int_val);
    } else if(left->type == TYPE_FLOAT) {
      push_d(ctx, -left->double_val);
    } else {
      fprintf(stderr, "type error of add expression\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(loadl) {
    Type val = ctx->var_list+pc->var_id;
    if(val->type == TYPE_INT) {
      push_i(ctx, val->int_val);
    } else if(val->type == TYPE_FLOAT) {
      push_d(ctx, val->double_val);
    } else if(val->type == TYPE_STRING) {
      push_s(ctx, val->string);
    } else if(val->type == TYPE_BOOL) {
      push_b(ctx, val->bool_val);
    } else {
      fprintf(stderr, "type error of loadl\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(storea) {
    Type val = ctx->var_list+pc->var_id;
    Type top = pop_sp(ctx->prev);
    if(top->type == TYPE_INT) {
      val->int_val = top->int_val;
    } else if(top->type == TYPE_FLOAT) {
      val->double_val = top->double_val;
    } else if(top->type == TYPE_STRING) {
      val->string = top->string;
    } else if(top->type == TYPE_BOOL) {
      val->bool_val = top->bool_val;
    } else {
      fprintf(stderr, "type error of storel\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(storel) {
    Type val = ctx->var_list+pc->var_id;
    Type top = pop_sp(ctx);
    if(top->type == TYPE_INT) {
      val->int_val = top->int_val;
      val->type = TYPE_INT;
    } else if(top->type == TYPE_FLOAT) {
      val->double_val = top->double_val;
      val->type = TYPE_FLOAT;
    } else if(top->type == TYPE_STRING) {
      val->string = top->string;
      val->type = TYPE_STRING;
    } else if(top->type == TYPE_BOOL) {
      val->bool_val = top->bool_val;
      val->type = TYPE_BOOL;
    } else {
      fprintf(stderr, "type error of storel\n");
      return 1;
    }
    DISPATCH_NEXT;
  }
  OP(write) {
    Type val = pop_sp(ctx);
    if(val->type == TYPE_INT) {
      printf("%d\n", val->int_val);
    } else if(val->type == TYPE_FLOAT) {
      printf("%f\n", val->double_val);
    } else if(val->type == TYPE_STRING) {
      printf("%s\n", val->string);
    } else if(val->type == TYPE_BOOL) {
      if(val->bool_val) {
        printf("true\n");
      } else {
        printf("false\n");
      }
    }
    DISPATCH_NEXT;
  }

  return 0;
}
示例#2
0
CompileOutput *Compiler::Compile(AMXRef amx) {
  Prepare(amx);

  Disassembler disasm(amx);
  Instruction instr;
  bool error = false;

  while (!error && disasm.Decode(instr, error)) {
    if (!Process(instr)) {
      error = true;
      break;
    }

    switch (instr.opcode().GetId()) {
      case OP_LOAD_PRI:
        load_pri(instr.operand());
        break;
      case OP_LOAD_ALT:
        load_alt(instr.operand());
        break;
      case OP_LOAD_S_PRI:
        load_s_pri(instr.operand());
        break;
      case OP_LOAD_S_ALT:
        load_s_alt(instr.operand());
        break;
      case OP_LREF_PRI:
        lref_pri(instr.operand());
        break;
      case OP_LREF_ALT:
        lref_alt(instr.operand());
        break;
      case OP_LREF_S_PRI:
        lref_s_pri(instr.operand());
        break;
      case OP_LREF_S_ALT:
        lref_s_alt(instr.operand());
        break;
      case OP_LOAD_I:
        load_i();
        break;
      case OP_LODB_I:
        lodb_i(instr.operand());
        break;
      case OP_CONST_PRI:
        const_pri(instr.operand());
        break;
      case OP_CONST_ALT:
        const_alt(instr.operand());
        break;
      case OP_ADDR_PRI:
        addr_pri(instr.operand());
        break;
      case OP_ADDR_ALT:
        addr_alt(instr.operand());
        break;
      case OP_STOR_PRI:
        stor_pri(instr.operand());
        break;
      case OP_STOR_ALT:
        stor_alt(instr.operand());
        break;
      case OP_STOR_S_PRI:
        stor_s_pri(instr.operand());
        break;
      case OP_STOR_S_ALT:
        stor_s_alt(instr.operand());
        break;
      case OP_SREF_PRI:
        sref_pri(instr.operand());
        break;
      case OP_SREF_ALT:
        sref_alt(instr.operand());
        break;
      case OP_SREF_S_PRI:
        sref_s_pri(instr.operand());
        break;
      case OP_SREF_S_ALT:
        sref_s_alt(instr.operand());
        break;
      case OP_STOR_I:
        stor_i();
        break;
      case OP_STRB_I:
        strb_i(instr.operand());
        break;
      case OP_LIDX:
        lidx();
        break;
      case OP_LIDX_B:
        lidx_b(instr.operand());
        break;
      case OP_IDXADDR:
        idxaddr();
        break;
      case OP_IDXADDR_B:
        idxaddr_b(instr.operand());
        break;
      case OP_ALIGN_PRI:
        align_pri(instr.operand());
        break;
      case OP_ALIGN_ALT:
        align_alt(instr.operand());
        break;
      case OP_LCTRL:
        lctrl(instr.operand(), instr.address() + instr.size());
        break;
      case OP_SCTRL:
        sctrl(instr.operand());
        break;
      case OP_MOVE_PRI:
        move_pri();
        break;
      case OP_MOVE_ALT:
        move_alt();
        break;
      case OP_XCHG:
        xchg();
        break;
      case OP_PUSH_PRI:
        push_pri();
        break;
      case OP_PUSH_ALT:
        push_alt();
        break;
      case OP_PUSH_C:
        push_c(instr.operand());
        break;
      case OP_PUSH:
        push(instr.operand());
        break;
      case OP_PUSH_S:
        push_s(instr.operand());
        break;
      case OP_POP_PRI:
        pop_pri();
        break;
      case OP_POP_ALT:
        pop_alt();
        break;
      case OP_STACK: // value
        stack(instr.operand());
        break;
      case OP_HEAP:
        heap(instr.operand());
        break;
      case OP_PROC:
        proc();
        break;
      case OP_RET:
        ret();
        break;
      case OP_RETN:
        retn();
        break;
      case OP_JUMP_PRI:
        jump_pri();
        break;
      case OP_CALL:
      case OP_JUMP:
      case OP_JZER:
      case OP_JNZ:
      case OP_JEQ:
      case OP_JNEQ:
      case OP_JLESS:
      case OP_JLEQ:
      case OP_JGRTR:
      case OP_JGEQ:
      case OP_JSLESS:
      case OP_JSLEQ:
      case OP_JSGRTR:
      case OP_JSGEQ: {
        cell dest = instr.operand() - reinterpret_cast<cell>(amx.code());
        switch (instr.opcode().GetId()) {
          case OP_CALL:
            call(dest);
            break;
          case OP_JUMP:
            jump(dest);
            break;
          case OP_JZER:
            jzer(dest);
            break;
          case OP_JNZ:
            jnz(dest);
            break;
          case OP_JEQ:
            jeq(dest);
            break;
          case OP_JNEQ:
            jneq(dest);
            break;
          case OP_JLESS:
            jless(dest);
            break;
          case OP_JLEQ:
            jleq(dest);
            break;
          case OP_JGRTR:
            jgrtr(dest);
            break;
          case OP_JGEQ:
            jgeq(dest);
            break;
          case OP_JSLESS:
            jsless(dest);
            break;
          case OP_JSLEQ:
            jsleq(dest);
            break;
          case OP_JSGRTR:
            jsgrtr(dest);
            break;
          case OP_JSGEQ:
            jsgeq(dest);
            break;
        }
        break;
      }
      case OP_SHL:
        shl();
        break;
      case OP_SHR:
        shr();
        break;
      case OP_SSHR:
        sshr();
        break;
      case OP_SHL_C_PRI:
        shl_c_pri(instr.operand());
        break;
      case OP_SHL_C_ALT:
        shl_c_alt(instr.operand());
        break;
      case OP_SHR_C_PRI:
        shr_c_pri(instr.operand());
        break;
      case OP_SHR_C_ALT:
        shr_c_alt(instr.operand());
        break;
      case OP_SMUL:
        smul();
        break;
      case OP_SDIV:
        sdiv();
        break;
      case OP_SDIV_ALT:
        sdiv_alt();
        break;
      case OP_UMUL:
        umul();
        break;
      case OP_UDIV:
        udiv();
        break;
      case OP_UDIV_ALT:
        udiv_alt();
        break;
      case OP_ADD:
        add();
        break;
      case OP_SUB:
        sub();
        break;
      case OP_SUB_ALT:
        sub_alt();
        break;
      case OP_AND:
        and_();
        break;
      case OP_OR:
        or_();
        break;
      case OP_XOR:
        xor_();
        break;
      case OP_NOT:
        not_();
        break;
      case OP_NEG:
        neg();
        break;
      case OP_INVERT:
        invert();
        break;
      case OP_ADD_C:
        add_c(instr.operand());
        break;
      case OP_SMUL_C:
        smul_c(instr.operand());
        break;
      case OP_ZERO_PRI:
        zero_pri();
        break;
      case OP_ZERO_ALT:
        zero_alt();
        break;
      case OP_ZERO:
        zero(instr.operand());
        break;
      case OP_ZERO_S:
        zero_s(instr.operand());
        break;
      case OP_SIGN_PRI:
        sign_pri();
        break;
      case OP_SIGN_ALT:
        sign_alt();
        break;
      case OP_EQ:
        eq();
        break;
      case OP_NEQ:
        neq();
        break;
      case OP_LESS:
        less();
        break;
      case OP_LEQ:
        leq();
        break;
      case OP_GRTR:
        grtr();
        break;
      case OP_GEQ:
        geq();
        break;
      case OP_SLESS:
        sless();
        break;
      case OP_SLEQ:
        sleq();
        break;
      case OP_SGRTR:
        sgrtr();
        break;
      case OP_SGEQ:
        sgeq();
        break;
      case OP_EQ_C_PRI:
        eq_c_pri(instr.operand());
        break;
      case OP_EQ_C_ALT:
        eq_c_alt(instr.operand());
        break;
      case OP_INC_PRI:
        inc_pri();
        break;
      case OP_INC_ALT:
        inc_alt();
        break;
      case OP_INC:
        inc(instr.operand());
        break;
      case OP_INC_S:
        inc_s(instr.operand());
        break;
      case OP_INC_I:
        inc_i();
        break;
      case OP_DEC_PRI:
        dec_pri();
        break;
      case OP_DEC_ALT:
        dec_alt();
        break;
      case OP_DEC:
        dec(instr.operand());
        break;
      case OP_DEC_S:
        dec_s(instr.operand());
        break;
      case OP_DEC_I:
        dec_i();
        break;
      case OP_MOVS:
        movs(instr.operand());
        break;
      case OP_CMPS:
        cmps(instr.operand());
        break;
      case OP_FILL:
        fill(instr.operand());
        break;
      case OP_HALT:
        halt(instr.operand());
        break;
      case OP_BOUNDS:
        bounds(instr.operand());
        break;
      case OP_SYSREQ_PRI:
        sysreq_pri();
        break;
      case OP_SYSREQ_C: {
        const char *name = amx.GetNativeName(instr.operand());
        if (name == 0) {
          error = true;
        } else {
          sysreq_c(instr.operand(), name);
        }
        break;
      }
      case OP_SYSREQ_D: {
        const char *name = amx.GetNativeName(amx.FindNative(instr.operand()));
        if (name == 0) {
          error = true;
        } else {
          sysreq_d(instr.operand(), name);
        }
        break;
      }
      case OP_SWITCH:
        switch_(CaseTable(amx, instr.operand()));
        break;
      case OP_CASETBL:
        casetbl();
        break;
      case OP_SWAP_PRI:
        swap_pri();
        break;
      case OP_SWAP_ALT:
        swap_alt();
        break;
      case OP_PUSH_ADR:
        push_adr(instr.operand());
        break;
      case OP_NOP:
        nop();
        break;
      case OP_BREAK:
        break_();
        break;
    default:
      error = true;
    }
  }

  if (error && error_handler_ != 0) {
    error_handler_->Execute(instr);
  }

  return Finish(error);
}