⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 engine.cpp

📁 UC Library Extensions UnderC comes with a pocket implementation of the standard C++ libraries, wh
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    get_stack_frame(i, xs);    
    Parser::state.push_context(xs.m_fb->context);
    resume_state.m_baseSP = xs.m_baseSP;
	if (verbose) dump_fun_frame(i,xs);
}

static int
 s_stepping = 0,
 s_current_exec_line = -1,
 s_old_exec_line = -1;

static Breakpoint* s_brk = NULL;

const int STEP_WAIT=1,STEP_MAIN=2,STEPPING=3,STEPPING_OVER=4;
static FBlock* s_main_fb;
static FBlock* s_initial_fb;
static int s_initial_stack_depth;

// *add 1.2.4 Switches profiling mode; returns IC.
unsigned long instr_count = 0;
const int STEP_PROFILE = 5;

unsigned long* set_instruction_counter(bool do_profiling)
{
   s_stepping = do_profiling ? STEP_PROFILE : 0;
   return &instr_count;  
}


#ifdef _DEBUG
int sh_offs() {
   return (int)mSP-(int)_stack_;
}

CEXPORT char *sh_fun() {
  static string tmp;
  try {
    tmp = fname_from_fblock(fb);  // *change 1.2.4
    return tmp.c_str();
  }
  catch(...) {
    return "<dud>";
  }
}

char *sh_var(char *sym)
{
    static char buff[40];
    PEntry pe = Parser::symbol_lookup(sym);
    if (pe) {
        unsigned int res = *(unsigned int *)pe->global_ptr();
        sprintf(buff,"%x %d",res,res);
        return buff;
    }
    else return "not found";
}
#endif

int current_ip()
{
  return ((int)ppcode - (int)fb->pstart)/4;
}

bool start_exec()
//---------------------------
{
  static int rmode,rdata,val,nargs,tmp;
  static Opcodes opcode;
  static double fval, gval;
  static void *data;
  static int buff[TMP_BUFF_SIZE];
  NFBlock *pfb; // *fix 1.2.4 Must _not_ be static!

  while (ppcode != end_of_code) {
top:
    opcode = (Opcodes)ppcode->opcode;
    rmode  = ppcode->rmode;
    if (rmode) {
      rdata = ppcode->data;
      if (rmode == DIRECT) data = mDataSeg + rdata; else
      if (rmode == SREL)   data = baseSP + rdata;    
      else data = mOP + rdata;
    }

    switch(opcode) {
        //...pushing effective address.
    case PEA:  push((int)data);         break;
    case PERA: push(rdata);             break;

    //.....pushing onto the exec stack...........................
    case PUSHC: push(REF(char,data));   break;
    case PUSHW: push(REF(short,data));  break;
    case PUSHI: push(REF(int,data));    break;
    case PUSHF: push2(REF(float,data));     break; // push as qword 
    case PUSHD: push2(REF(double,data));    break; 
    case PUSHS: pushf(REF(float,data));     break; // push as dword
    
    //....popping off the exec stack into a variable.............
    case POPC:  REF(char,data) = pop(); break;
    case POPW:  REF(short,data) = pop();    break;  
    case POPI:  REF(int,data) = pop();  break;
    case POPF:  REF(float,data) = pop2();   break;
    case POPD:  REF(double,data) = pop2();  break;
    //....stack-relative pushes/pops
    case PUSHSC: push(REF(char,popp()));    break;
    case PUSHSW: push(REF(short,popp()));   break;
    case PUSHSI: push(REF(int,popp())); break;
    case PUSHSF: push2(REF(float,popp()));  break;
    case PUSHSD: push2(REF(double,popp())); break;
    case POPSC:  val=popp(); REF(char,val) = pop(); break;
    case POPSW:  val=popp(); REF(short,val) = pop(); break;
    case POPSI:  val=popp(); REF(int,val) = pop(); break;
    case POPSD:  val=popp();REF(double,val) = pop2(); break;

    case DROP:   drop();            break;
    case DROP2:  drop2();           break;  // *add 1.2.3b missing opcode!
    case DUP:    push(tos());       break;
    case DUP2:   push2(tos2());     break;  // *fix 1.2.4 was taken out by mistake in 1.2.3b!
    case SWAP: //....swap top two dwords on stack.... 
          val = pop();
          tmp = tos();
          tos() = val;
          push(tmp);
          break;
    case SWAPD:  // swap top qword with next dword...
	      fval = pop2();
		  val = pop();
		  push2(fval);
		  push(val);
	      break;
    //.....integer arithmetric operations.......................
    case NEG:    tos() = -tos();        break;
    case ADD:    val=pop();  tos() += val;  break;
    case SUB:    val=pop();  tos() -= val;  break;
    case MUL:    val=pop();  tos() *= val;  break;
    case DIV:    val=pop();  tos() /= val;  break;
    case IDIV:   val=pop();  (unsigned&)tos() /= val;  break;
    case AND:    val=pop();  tos() &= val;  break;  // binary and
    case OR:     val=pop();  tos() |= val;  break;  // binary or
    case XOR:    val=pop();  tos() ^= val;  break;
    case SHL:    val=pop();  tos() <<= val; break;  
    case SHR:    val=pop();  tos() >>= val; break;
    case NOT:    tos() = ! tos();           break;
    case BNOT:   tos() = ~ tos();           break;
    case EQ:     val=pop();  tos() = tos() == val;  break;
    case NEQ:     val=pop();  tos() = tos() != val; break;
    case MOD:    val=pop();  tos() = tos() % val;   break;
    case LESS:   val=pop();  tos() = tos() < val;   break;
    case GREAT:  val=pop();  tos() = tos() > val;   break;
    case LE:   val=pop();  tos() = tos() <= val;   break;
    case GE:  val=pop();  tos() = tos() >= val;   break;

    //....floating-point arithmetric
    case FNEG:   tos2() = -tos2();          break;
    case FADD: 
        fval=pop2();
        tos2() += fval;
        break;
    case FSUB:   fval=pop2(); tos2() -= fval;  break;       
    case FMUL:   fval=pop2(); tos2() *= fval;   break;      
    case FDIV:   fval=pop2(); tos2() /= fval;   break;
    case FEQ:    fval=pop2(); push(pop2() == fval); break;
    case FNEQ:    fval=pop2(); push(pop2() != fval);    break;
    case FLESS:  fval=pop2(); push(pop2() < fval);  break;
    case FGREAT: fval=pop2(); push(pop2() > fval);  break;   
    case FLE:  fval=pop2(); push(pop2() <= fval);   break;
    case FGE: fval=pop2(); push(pop2() >= fval);  break;     


    //...array operations
    case ADDCC:  val=pop();  push((int)data + sizeof(char)*val);    break;
    case ADDCW:  val=pop();  push((int)data + sizeof(short)*val);   break;
    case ADDCI:  val=pop();  push((int)data + sizeof(int)*val);     break;
    case ADDCD:  val=pop();  push((int)data + sizeof(double)*val);  break;
    case ADDPC:  val=pop();  push(REF(int,data) + sizeof(char)*val);    break;
    case ADDPW:  val=pop();  push(REF(int,data) + sizeof(short)*val);   break;
    case ADDPI:  val=pop();  push(REF(int,data) + sizeof(int)*val);     break;
    case ADDPD:  val=pop();  push(REF(int,data) + sizeof(double)*val);  break;
    // ADDSC is ADD!
    case ADDSW:  val=pop();  push(val + sizeof(short)*pop());           break;  
    case ADDSI:  val=pop();  push(val + sizeof(int)*pop());             break;
    case ADDSD:  val=pop();  push(val + sizeof(double)*pop());          break;
    case ADDSN:  val=pop();  push(val + pop()*pop());                   break;

    case COPY:   memcpy((void *)pop(),(void *)pop(),ppcode->data); break;

    //...jumps (all relative) and calls (pcode and native)........
    //...These set ppcode directly, and so we jump to the end of the loop....
    case CCALLX: // *add 1.2.0 Associate VMT with imported ptr
        PFBlock(data)->class_ptr->attach_VMT(mOP);
        goto call_the_function;
    case CCALL: //....patch the hidden VMT pointer......
        *VMT(mOP) = PFBlock(data)->class_ptr->get_VMT();
        // and fall through....
call_the_function:
    case CALL:  
        start_function(PFBlock(data));
        continue;
    case VCALL: //....lookup the proc in the VMT table....
        start_function(virtual_method_lookup(rdata));
        continue;
    case VCALLX: //....lookup proc in associated VMT table (for imports)
        start_function(virtual_method_imported_lookup(rdata));
        continue;
    case CALLN:  // native code interface
        pfb = (NFBlock *)data;
        nargs = pfb->nargs;
        if (nargs == -1) nargs = pop();
        callfn(pfb->pfn,mSP-1,nargs,mOP,pfb->flags,buff);
        mSP += nargs;
        if (pfb->flags & DC_QWORD) push2(*(double *)buff); else
        if (pfb->flags & DC_NOWORD) ;
        else push(*buff);
        break;
    case CCALLV: {// vector constructor/destructor call
        ConstructBlock *pcb = (ConstructBlock *)data;
        PPClass vtable = pcb->get_VMT();
		PClass pc = pcb->class_ptr();
        int num;
        if (pcb->dynamic()) { // i.e new[] has generated a ptr for us; 
           char *ptr = mOP - sizeof(void *);
           num = Builtin::alloc_size(ptr);
        } else num = pcb->num();
        char *old_mOP = mOP;
        for(int i = 0, sz = pcb->size(); i < num; i++) {
          if (vtable != NULL) { // patch VMT, if needed
                if (! pc->has_true_VMT()) pc->attach_VMT(vtable);
                else *VMT(mOP) = vtable;             
          }
          // push  ODS, if needed
          // *add 1.2.3 static objects get their own ODS
          // *change 1.2.9 static objects are handled at compile-time w/ the ODL 
          // (see LoadedModuleList in program.cpp)
		  if (pcb->load_ODS()) 
              mODS.push_object(pc, mOP);     
          if (Engine::execute(pcb->fblock())==CRASHED)
            throw Exception("Construction failed");
          mOP += sz;
        }
        mOP = old_mOP;
        if (pcb->dynamic()) push((int)mOP);  // leave obj on XS
        opop();                              // drop the OS
      }
      break;
  // *NOTE* The continue seems strange, but it is important to skip ppcode++!
    case CALLS:
        start_function(PFBlock(pop()));
        continue;
    case VCALLS:
        start_function(virtual_method_lookup((int)pop()));
        continue;
      JMP_case:
    case JMP:    ppcode = fb->pstart + ppcode->data; goto top;              break;
    case JZ:     if(!pop()) goto JMP_case; break;
    case JNZ:    if(pop())  goto JMP_case; break;
    case JZND:   if(!tos()) goto JMP_case; else drop(); break; 
    case JNZND:  if(tos())  goto JMP_case; else drop(); break;
    case JSWITCH: ppcode = fb->pstart + switch_jump((int *)data,pop()); goto top; 
    case RET:   
          mSP = baseSP;
          mSP += fb->nargs;
          end_function();
          break;    
    case RETI: //......returning dword..........
          val = pop();      // pop the return value
          mSP = baseSP;     // restore stack frame
          mSP += fb->nargs; // drop the args (STDCALL!)
          push(val);        // push return value
          end_function();
          break;
    case RETD: //.....returning qword............
          fval = pop2();
          mSP = baseSP;
          mSP += fb->nargs;
          push2(fval);
          end_function();
          break;
    case ADDSP: // *add 1.2.3b True cdecl calling convention implemented
		{
          int data = ppcode->data;
		  int tp = lo_byte(data);
		  int sz = hi_byte(data);
		  if (tp==1) val = pop();
		  else if (tp==2) fval = pop2();
		  mSP += sz;
          if (tp==1) push(val); 
		  else if (tp==2) push2(fval);
		}
		break;
    case UNWIND:
         {
         int* old_sp = mSP;  
         char *old_op = mOP;
         do_unwind((char *)data, mODS);
         if (old_sp != mSP || old_op != mOP) 
            cerr << "SP/OP changed!\n";
         #ifdef TRACK_ODS
         cout << "unwind " << data << ' ' << current_ip() << ' ' << sh_fun() <<endl;
         #endif
         }
         break;
    case DCAST: { // *add 0.9.5 dynamic cast
           Type t = *(Type *)data;
           Class *tc = t.as_class();  // hm...what about the (void *) possibility?
           void *ptr = (void *)pop();
           Class *oc = get_class_object(ptr);
           if (! oc->inherits_from(tc)) {
              if (t.is_pointer()) push(0);
              else {
                int ip = throw_exception(t_char_ptr,(char *)"bad cast"); // for now!!
                if (ip == -1) throw Exception("bad dynamic typecast");
                else { ppcode = fb->pstart + ip; continue; }
              }
           } else push((int)ptr);
         }
         break;
    // INC and DEC
    case INCC:   REF(char,data)++;  break;
    case INCW:   REF(short,data)++; break;
    case INCI:   REF(int,data)++;   break;
    case INCS:   tos()++;           break;
    case DECC:   REF(char,data)--;  break;
    case DECW:   REF(short,data)--; break;
    case DECI:   REF(int,data)--;   break;
    case DECS:   tos()--;           break;

   // INCP and DECP
    case INCPC:   REFP(char,data)++;    break;
    case INCPW:   REFP(short,data)++;   break;
    case INCPI:   REFP(int,data)++;     break;
    case INCPD:   REFP(double,data)++;  break;
    case DECPC:   REFP(char,data)--;    break;
    case DECPW:   REFP(short,data)--;   break;
    case DECPI:   REFP(int,data)--;     break;
    case DECPD:   REFP(double,data)--;  break;

   // INCS and DECS
    case INCSC:   REFS(char)++;     break;
    case INCSW:   REFS(short)++;        break;
    case INCSI:   REFS(int)++;      break;
    case DECSC:   REFS(char)--;     break;
    case DECSW:   REFS(short)--;        break;
    case DECSI:   REFS(int)--;      break;
  
    //...conversions...............................................
    case D2I:   push((int)pop2());          break;
    case I2D:   push2((double)pop());       break;  
    case F2D:   push2((double)popf());      break;
    case D2F:   pushf((float)pop2());       break;
    case I2F:   pushf((float)pop());        break;
    case F2I:   push((int)popf());          break;
    case I2B:   push(0xFF & pop());         break;   // *add 1.2.9 32-bit to 8-bit bool

    //...object-stack manipulation
    case LOS:
        //depth = ostack.depth();
        opush(data);
        break;
    case LOSS:
        opush((void *)pop());
        break;
    case DOS: 
        opop(); 
        break;  
    case TOSX:
        push((int)mOP);
        opop();
        break;
    case TOSD:
        mODS.push_object(*(PClass *)data, mOP);
        #ifdef TRACK_ODS
        cout << "TOSD " << (void *)mOP << ' ' << current_ip() << ' ' << sh_fun() << endl;
        #endif
        opop();
        break;
    case TPODS: // pushing temporary for functions returning object values
        {
         PClass pc = *(PClass *)data;
#ifdef DEBUG_ODS
          if (pc->has_VMT()) *VMT(mOP) = DEFER_MARKER;
#endif
          mODS.push_object(pc,mOP);
          push((int)mOP);
        #ifdef TRACK_ODS
        cout << "TPODS " << mOP << ' ' << sh_fun() << endl;
        #endif
          opop();
        }
        break;

    case PUSH_THIS:
        push((int)mOP);
        break;

    case STALC: // allocate object directly on stack (needed for MS object-passing)
    // *fix 1.2.0 The UC stack now grows downwards!
		mSP -= ppcode->data;
   	    opush(mSP);
		break;

    case THROW_EX:   {
        Type et = *(Type *)data;
        void *obj = (void *)pop();
        int ip = throw_exception(et,obj);
        if (ip == -1) { // couldn't catch the exception
        // *add 1.2.4 if the thrown type is derived from Exception,
        // then pass on the message! (Warning: this depends on Exception defined in <uc_except.h>
        // having precisely this layout, w/ a char pointer as the first field)
            if (match(Parser::mEException->type,et) != NO_MATCH) 
              throw Exception(*(char **)obj);
            else 
              throw Exception("uncaught exception");
        } // otherwise, can continue excuting at the given catch block address...
        else { ppcode = fb->pstart + ip; continue; }
       }

    case CHKVMT: // *NOTE64*
      push((int)(*(PClass *)(data))->check_object_pointer((char *)pop()));
      break;

    case VTABLE_PATCH:	   
       // *fix 1.2.8 in classes derived indirectly from imported classes,
	  // Class::update_vtable() was _not_ being called for the specific
      // class in question!
	   //  get_class_object(mOP)->update_vtable(mOP);
	   (*(PClass *)(data))->update_vtable(mOP);
      break;

    case POPIF:
    case PUSHIF: {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -