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

📄 ljit_x86.dasc

📁 采用C语言写的Lua的解释器的代码!Lua不用介绍了吧
💻 DASC
📖 第 1 页 / 共 5 页
字号:
	|  fld qword BASE[rkc].value	|  fld qword [kval]      } else {	|  fld qword [kval]	|  fld qword BASE[rkb].value      }    } else {      |  isnumber2 rkb, rkc      |   mov eax, BASE[rkb].value.na[1]      |  jne L_DEOPTIMIZEF      |   or eax, BASE[rkc].value.na[1]; js L_DEOPTIMIZEF      |  fld qword BASE[rkc].value      |  fld qword BASE[rkb].value    }    |1: ; fprem; fnstsw ax; sahf; jp <1    |  fstp st1    goto fpstore;  case TM_POW:    if (hastail || !kval) break;  /* Avoid this if not optimizing. */    if (rev) {  /* x^k for k > 0, k integer. */      lua_Number n = kval->n;      int k;      lua_number2int(k, n);      /* All positive integers would work. But need to limit code explosion. */      if (k > 0 && k <= 65536 && (lua_Number)k == n) {	|  isnumber idx; jne L_DEOPTIMIZEF	|  fld qword BASE[idx]	for (; (k & 1) == 0; k >>= 1) {  /* Handle leading zeroes (2^k). */	  |  fmul st0	}	if ((k >>= 1) != 0) {  /* Handle trailing bits. */	  |  fld st0	  |  fmul st0	  for (; k != 1; k >>= 1) {	    if (k & 1) {	      |  fmul st1, st0	    }	    |  fmul st0	  }	  |  fmulp st1	}	goto fpstore;      }    } else if (kval->n > (lua_Number)0) {  /* k^x for k > 0. */      int log2kval[3];  /* Enough storage for a tword (80 bits). */      log2kval[2] = 0;  /* Avoid leaking garbage. */      /* Double precision log2(k) doesn't cut it (3^x != 3 for x = 1). */      ((void (*)(int *, double))J->jsub[JSUB_LOG2_TWORD])(log2kval, kval->n);      |  mov ARG1, log2kval[0]			// Abuse stack for tword const.      |  mov ARG2, log2kval[1]      |  mov ARG3, log2kval[2]			// TODO: store2load fwd stall.      |  isnumber idx; jne L_DEOPTIMIZEF      |  fld tword [esp]      |  fmul qword BASE[idx].value		// log2(k)*x      |  fld st0; frndint; fsub st1, st0; fxch	// Split into fract/int part.      |  f2xm1; fld1; faddp st1; fscale		// (2^fract-1 +1) << int.      |  fstp st1      |.jsub LOG2_TWORD		// Calculate log2(k) with max. precision.      |// Called with (int *ptr, double k).      |  fld1; fld FPARG2			// Offset ok due to retaddr.      |  fyl2x      |  mov eax, ARG2				// Really ARG1.      |  fstp tword [eax]      |  ret      |.endjsub      goto fpstore;    }    break;  }  /* Check number type and load 1st operand. */  if (kval) {    |  isnumber idx; jne L_DEOPTIMIZEF    |  loadnvaluek kval  } else {    if (rkb == rkc) {      |  isnumber rkb    } else {      |  isnumber2 rkb, rkc    }    |  jne L_DEOPTIMIZEF    |  fld qword BASE[rkb].value  }  /* Encode arithmetic operation with 2nd operand. */  switch ((ev<<1)+rev) {  case TM_ADD<<1: case (TM_ADD<<1)+1:    if (rkb == rkc) {      |  fadd st0    } else {      |  fadd qword BASE[idx].value    }    break;  case TM_SUB<<1:    |  fsub qword BASE[idx].value    break;  case (TM_SUB<<1)+1:    |  fsubr qword BASE[idx].value    break;  case TM_MUL<<1: case (TM_MUL<<1)+1:    if (rkb == rkc) {      |  fmul st0    } else {      |  fmul qword BASE[idx].value    }    break;  case TM_DIV<<1:    |  fdiv qword BASE[idx].value    break;  case (TM_DIV<<1)+1:    |  fdivr qword BASE[idx].value    break;  case TM_POW<<1:    |  sub esp, S2LFRAME_OFFSET    |  fstp FPARG1    |  fld qword BASE[idx].value    |  fstp FPARG2    |  call &pow    |  add esp, S2LFRAME_OFFSET    break;  case (TM_POW<<1)+1:    |  sub esp, S2LFRAME_OFFSET    |  fstp FPARG2    |  fld qword BASE[idx].value    |  fstp FPARG1    |  call &pow    |  add esp, S2LFRAME_OFFSET    break;  case TM_UNM<<1: case (TM_UNM<<1)+1:    |  fchs				// No 2nd operand.    break;  default:  /* TM_LT or TM_LE. */    |  fld qword BASE[idx].value    |  fcomparepp    |  jp =>dest?(J->nextpc+1):target	// Unordered means false.    jit_assert(dest == 0 || dest == 1);  /* Really cond. */    switch (((rev^dest)<<1)+(dest^(ev == TM_LT))) {    case 0:      |  jb =>target      break;    case 1:      |  jbe =>target      break;    case 2:      |  ja =>target      break;    case 3:      |  jae =>target      break;    }    goto skipstore;  }fpstore:  /* Store result and set result type (if necessary). */  |  fstp qword BASE[dest].value  if (dest != rkb && dest != rkc) {    |  settt BASE[dest], LUA_TNUMBER  }skipstore:  if (!hastail) {    jit_deopt_target(J, 0);    return;  }  |4:  |.tail  |L_DEOPTLABEL:  // Recycle as fallback label.fallback:  /* Generic fallback for arithmetic ops. */  if (kkb) {    |  mov ecx, &kkb  } else {    |  lea ecx, BASE[rkb]  }  if (kkc) {    |  mov edx, &kkc  } else {    |  lea edx, BASE[rkc]  }  if (target) {  /* TM_LT or TM_LE. */    |  mov L->savedpc, &(J->nextins+1)    |  call &ev==TM_LT?luaV_lessthan:luaV_lessequal, L, ecx, edx    |  test eax, eax    |  mov BASE, L->base    if (dest) {  /* cond */      |  jnz =>target    } else {      |  jz =>target    }  } else {    |  addidx BASE, dest    |  mov L->savedpc, &J->nextins    |  call &luaV_arith, L, BASE, ecx, edx, ev    |  mov BASE, L->base  }  if (hastail) {    | jmp <4    |.code  }}/* ------------------------------------------------------------------------ */static void jit_fallback_len(lua_State *L, StkId ra, const TValue *rb){  switch (ttype(rb)) {  case LUA_TTABLE:    setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));    break;  case LUA_TSTRING:    setnvalue(ra, cast_num(tsvalue(rb)->len));    break;  default: {    const TValue *tm = luaT_gettmbyobj(L, rb, TM_LEN);    if (ttisfunction(tm)) {      ptrdiff_t rasave = savestack(L, ra);      setobj2s(L, L->top, tm);      setobj2s(L, L->top+1, rb);      luaD_checkstack(L, 2);      L->top += 2;      luaD_call(L, L->top - 2, 1);      ra = restorestack(L, rasave);      L->top--;      setobjs2s(L, ra, L->top);    } else {      luaG_typeerror(L, rb, "get length of");    }    break;  }  }}static void jit_op_len(jit_State *J, int dest, int rb){  switch (ttype(hint_get(J, TYPE))) {  case LUA_TTABLE:    jit_deopt_target(J, 0);    |   istable rb    |  mov TABLE:ecx, BASE[rb].value    |   jne L_DEOPTIMIZE		// TYPE hint was wrong?    |  call &luaH_getn, TABLE:ecx    |  mov TMP1, eax    |  fild dword TMP1    |  fstp qword BASE[dest].value    |  settt BASE[dest], LUA_TNUMBER    break;  case LUA_TSTRING:    jit_deopt_target(J, 0);    |   isstring rb    |  mov TSTRING:ecx, BASE[rb].value    |   jne L_DEOPTIMIZE		// TYPE hint was wrong?    |  fild aword TSTRING:ecx->tsv.len	// size_t    |  fstp qword BASE[dest].value    |  settt BASE[dest], LUA_TNUMBER    break;  default:    |  lea TVALUE:ecx, BASE[rb]    |  addidx BASE, dest    |  mov L->savedpc, &J->nextins    |  call &jit_fallback_len, L, BASE, TVALUE:ecx    |  mov BASE, L->base    break;  }}static void jit_op_not(jit_State *J, int dest, int rb){  /* l_isfalse() without a branch -- truly devious. */  /* ((value & tt) | (tt>>1)) is only zero for nil/false. */  /* Assumes: LUA_TNIL == 0, LUA_TBOOLEAN == 1, bvalue() == 0/1 */  |  mov eax, BASE[rb].tt  |  mov ecx, BASE[rb].value  |  mov edx, 1  |  and ecx, eax  |  shr eax, 1  |  or ecx, eax  |  xor eax, eax  |  cmp ecx, edx  |  adc eax, eax  |  mov BASE[dest].tt, edx  |  mov BASE[dest].value, eax}/* ------------------------------------------------------------------------ */static void jit_op_concat(jit_State *J, int dest, int first, int last){  int num = last-first+1;  if (num == 2 && ttisstring(hint_get(J, TYPE))) {  /* Optimize common case. */    |  addidx BASE, first    |  call ->CONCAT_STR2    |  setsvalue BASE[dest], eax  } else {  /* Generic fallback. */    |  mov L->savedpc, &J->nextins    |  call &luaV_concat, L, num, last    |  mov BASE, L->base    if (dest != first) {      |  copyslot BASE[dest], BASE[first]    }  }  jit_checkGC(J);  /* Always do this, even for the optimized variant. */  |.jsub CONCAT_STR2			// Concatenate two strings.  |// Call with: BASE (first). Destroys all regs. L and BASE restored.  |  mov ARG2, L			// Save L (esi).  |  mov eax, BASE[0].tt; shl eax, 4; or eax, BASE[1].tt  |  sub eax, LUA_TSTR_STR		// eax = 0 on success.  |  jne ->DEOPTIMIZE_CALLER	// Wrong types? Deoptimize.  |  |1:  |   mov GL:edi, L->l_G  |  mov TSTRING:esi, BASE[0].value	// Caveat: L (esi) is gone now!  |  mov TSTRING:edx, BASE[1].value  |  mov ecx, TSTRING:esi->tsv.len	// size_t  |  test ecx, ecx  |  jz >2				// 1st string is empty?  |  or eax, TSTRING:edx->tsv.len	// eax is known to be zero.  |  jz >4				// 2nd string is empty?  |  add eax, ecx  |  jc >9				// Length overflow?  |  cmp eax, GL:edi->buff.buffsize	// size_t  |  ja >5				// Temp buffer overflow?  |  mov edi, GL:edi->buff.buffer  |  add esi, #TSTRING  |  rep; movsb				// Copy first string.  |  mov ecx, TSTRING:edx->tsv.len  |  lea esi, TSTRING:edx[1]  |  rep; movsb				// Copy second string.  |  |  sub edi, eax			// start = end - total.  |   mov L, ARG2			// Restore L (esi). Reuse as 1st arg.  |  mov ARG3, edi  |  mov ARG4, eax  |   mov BASE, L->base			// Restore BASE.  |  jmp &luaS_newlstr  |  |2:  // 1st string is empty.  |  mov eax, TSTRING:edx		// Return 2nd string.  |3:  |  mov L, ARG2			// Restore L (esi) and BASE.  |  mov BASE, L->base  |  ret  |  |4:  // 2nd string is empty.  |  mov eax, TSTRING:esi		// Return 1st string.  |  jmp <3  |  |5:  // Resize temp buffer.  |  // No need for setting L->savedpc since only LUA_ERRMEM may be thrown.  |  mov L, ARG2			// Restore L.  |  lea ecx, GL:edi->buff  |  sub esp, FRAME_OFFSET  |  call &luaZ_openspace, L, ecx, eax  |  add esp, FRAME_OFFSET  |  xor eax, eax			// BASE (first) and L saved. eax = 0.  |  jmp <1				// Just restart.  |  |9:  // Length overflow errors are rare (> 2 GB string required).  |  mov L, ARG2			// Need L for deoptimization.  |  jmp ->DEOPTIMIZE_CALLER  |.endjsub}/* ------------------------------------------------------------------------ */static void jit_op_eq(jit_State *J, int cond, int rkb, int rkc){  int target = jit_jmp_target(J);  int condtarget = cond ? (J->nextpc+1) : target;  jit_assert(cond == 0 || cond == 1);  /* Comparison of two constants. Evaluate at compile time. */  if (ISK(rkb&rkc)) {    if ((rkb == rkc) == cond) {  /* Constants are already unique. */      |  jmp =>target    }    return;  }  if (ISK(rkb|rkc)) {  /* Compare a variable and a constant. */    const TValue *kk;    if (ISK(rkb)) { int t = rkc; rkc = rkb; rkb = t; }  /* rkc holds const. */    kk = &J->pt->k[INDEXK(rkc)];    switch (ttype(kk)) {    case LUA_TNIL:      |  isnil rkb      break;    case LUA_TBOOLEAN:      if (bvalue(kk)) {	|  mov eax, BASE[rkb].tt	|  mov ecx, BASE[rkb].value	|  dec eax	|  dec ecx	|  or eax, ecx      } else {	|  mov eax, BASE[rkb].tt	|  dec eax	|  or eax, BASE[rkb].value      }      break;    case LUA_TNUMBER:      |// Note: bitwise comparison is not faster (and needs to handle -0 == 0).      |  isnumber rkb      |  jne =>condtarget      |  fld qword BASE[rkb].value      |  fld qword [&kk->value]      |  fcomparepp      |  jp =>condtarget  // Unordered means not equal.      break;    case LUA_TSTRING:      |  isstring rkb      |  jne =>condtarget      |  cmp aword BASE[rkb].value, &rawtsvalue(kk)      break;    default: jit_assert(0); break;    }  } else {  /* Compare two variables. */    |  mov eax, BASE[rkb].tt    |  cm

⌨️ 快捷键说明

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