Changed binary int ops to use a temporary register, fixed some opcodes.

For some reason, binary ops might reuse one of the input registers as the output register.
This is a problem for very obvious reasons.
This commit is contained in:
Chronos Ouroboros 2018-08-14 20:07:50 -03:00
parent 1a52c2ba00
commit 591783087d

View file

@ -61,6 +61,13 @@ static asmjit::JitRuntime jit;
// [pbeta] TODO: VM aborts
#define NULL_POINTER_CHECK(a,o,x)
#define BINARY_OP_INT(op,out,r,l) \
{ \
auto tmp = cc.newInt32(); \
cc.mov(tmp, r); \
cc.op(tmp, l); \
cc.mov(out, tmp); \
}
static bool CanJit(VMScriptFunction *sfunc)
{
@ -400,7 +407,7 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc)
break;
case OP_LB_R:
NULL_POINTER_CHECK (PB, RC, X_READ_NIL);
cc.movsx (regD[a], x86::byte_ptr (PB, KC));
cc.movsx (regD[a], x86::byte_ptr (PB, RC));
break;
case OP_LH: // load halfword
NULL_POINTER_CHECK (PB, KC, X_READ_NIL);
@ -408,15 +415,15 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc)
break;
case OP_LH_R:
NULL_POINTER_CHECK (PB, RC, X_READ_NIL);
cc.movsx (regD[a], x86::word_ptr (PB, KC));
cc.movsx (regD[a], x86::word_ptr (PB, RC));
break;
case OP_LW: // load word
NULL_POINTER_CHECK (PB, KC, X_READ_NIL);
cc.movsx (regD[a], x86::dword_ptr (PB, KC));
cc.mov (regD[a], x86::dword_ptr (PB, KC));
break;
case OP_LW_R:
NULL_POINTER_CHECK (PB, RC, X_READ_NIL);
cc.movsx (regD[a], x86::dword_ptr (PB, KC));
cc.mov (regD[a], x86::dword_ptr (PB, RC));
break;
case OP_LBU: // load byte unsigned
NULL_POINTER_CHECK (PB, KC, X_READ_NIL);
@ -424,7 +431,7 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc)
break;
case OP_LBU_R:
NULL_POINTER_CHECK (PB, RC, X_READ_NIL);
cc.mov (regD[a], x86::byte_ptr (PB, KC));
cc.mov (regD[a], x86::byte_ptr (PB, RC));
break;
case OP_LHU: // load halfword unsigned
NULL_POINTER_CHECK (PB, KC, X_READ_NIL);
@ -432,7 +439,7 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc)
break;
case OP_LHU_R:
NULL_POINTER_CHECK (PB, RC, X_READ_NIL);
cc.mov (regD[a], x86::word_ptr (PB, KC));
cc.mov (regD[a], x86::word_ptr (PB, RC));
break;
case OP_LSP: // load single-precision fp
NULL_POINTER_CHECK (PB, KC, X_READ_NIL);
@ -787,102 +794,83 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc)
// Integer math.
case OP_SLL_RR: // dA = dkB << diC
cc.mov(regD[a], regD[B]);
cc.shl(regD[a], regD[C]);
BINARY_OP_INT(shl, regD[a], regD[B], regD[C]);
break;
case OP_SLL_RI:
cc.mov(regD[a], regD[B]);
cc.shl(regD[a], C);
BINARY_OP_INT(shl, regD[a], regD[B], C);
break;
case OP_SLL_KR:
cc.mov(regD[a], konstd[B]);
cc.shl(regD[a], C);
BINARY_OP_INT(shl, regD[a], konstd[B], regD[C]);
break;
case OP_SRL_RR: // dA = dkB >> diC -- unsigned
cc.mov(regD[a], regD[B]);
cc.shr(regD[a], regD[C]);
BINARY_OP_INT(shr, regD[a], regD[B], regD[C]);
break;
case OP_SRL_RI:
cc.mov(regD[a], regD[B]);
cc.shr(regD[a], C);
BINARY_OP_INT(shr, regD[a], regD[B], C);
break;
case OP_SRL_KR:
cc.mov(regD[a], konstd[B]);
cc.shr(regD[a], C);
BINARY_OP_INT(shr, regD[a], regD[B], C);
break;
case OP_SRA_RR: // dA = dkB >> diC -- signed
cc.mov(regD[a], regD[B]);
cc.sar(regD[a], regD[C]);
BINARY_OP_INT(sar, regD[a], regD[B], regD[C]);
break;
case OP_SRA_RI:
cc.mov(regD[a], regD[B]);
cc.sar(regD[a], C);
BINARY_OP_INT(sar, regD[a], regD[B], C);
break;
case OP_SRA_KR:
cc.mov(regD[a], konstd[B]);
cc.sar(regD[a], regD[C]);
BINARY_OP_INT(sar, regD[a], konstd[B], regD[C]);
break;
case OP_ADD_RR: // dA = dB + dkC
cc.mov(regD[a], regD[B]);
cc.add(regD[a], regD[C]);
BINARY_OP_INT(add, regD[a], regD[B], regD[C]);
break;
case OP_ADD_RK:
cc.mov(regD[a], regD[B]);
cc.add(regD[a], konstd[C]);
BINARY_OP_INT(add, regD[a], regD[B], konstd[C]);
break;
case OP_ADDI: // dA = dB + C -- C is a signed 8-bit constant
cc.mov(regD[a], regD[B]);
cc.add(regD[a], Cs);
BINARY_OP_INT(add, regD[a], regD[B], Cs);
break;
case OP_SUB_RR: // dA = dkB - dkC
cc.mov(regD[a], regD[B]);
cc.sub(regD[a], regD[C]);
BINARY_OP_INT(sub, regD[a], regD[B], regD[C]);
break;
case OP_SUB_RK:
cc.mov(regD[a], regD[B]);
cc.sub(regD[a], konstd[C]);
BINARY_OP_INT(sub, regD[a], regD[B], konstd[C]);
break;
case OP_SUB_KR:
cc.mov(regD[a], konstd[B]);
cc.sub(regD[a], regD[C]);
BINARY_OP_INT(sub, regD[a], konstd[B], regD[C]);
break;
case OP_MUL_RR: // dA = dB * dkC
cc.mov(regD[a], regD[B]);
cc.mul(regD[a], regD[C]);
BINARY_OP_INT(mul, regD[a], regD[B], regD[C]);
break;
case OP_MUL_RK:
cc.mov(regD[a], regD[B]);
cc.mul(regD[a], konstd[C]);
BINARY_OP_INT(mul, regD[a], regD[B], konstd[C]);
break;
case OP_DIV_RR: // dA = dkB / dkC (signed)
// To do: ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
cc.mov(regD[a], regD[B]);
cc.idiv(regD[a], regD[C]);
BINARY_OP_INT(idiv, regD[a], regD[B], regD[C]);
break;
case OP_DIV_RK:
// To do: ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
cc.mov(regD[a], regD[B]);
cc.div(regD[a], konstd[C]);
BINARY_OP_INT(idiv, regD[a], regD[B], konstd[C]);
break;
case OP_DIV_KR:
// To do: ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
cc.mov(regD[a], konstd[B]);
cc.idiv(regD[a], regD[C]);
BINARY_OP_INT(idiv, regD[a], konstd[B], regD[C]);
break;
case OP_DIVU_RR: // dA = dkB / dkC (unsigned)
// To do: ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
cc.mov(regD[a], regD[B]);
cc.div(regD[a], regD[C]);
BINARY_OP_INT(div, regD[a], regD[B], regD[C]);
break;
case OP_DIVU_RK:
// To do: ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
cc.mov(regD[a], regD[B]);
cc.div(regD[a], konstd[C]);
BINARY_OP_INT(div, regD[a], regD[B], konstd[C]);
break;
case OP_DIVU_KR:
// To do: ThrowAbortException(X_DIVISION_BY_ZERO, nullptr);
cc.mov(regD[a], konstd[B]);
cc.div(regD[a], regD[C]);
BINARY_OP_INT(div, regD[a], konstd[B], regD[C]);
break;
case OP_MOD_RR: // dA = dkB % dkC (signed)
case OP_MOD_RK:
@ -892,28 +880,22 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc)
case OP_MODU_KR:
break;
case OP_AND_RR: // dA = dB & dkC
cc.mov(regD[a], regD[B]);
cc.and_(regD[a], regD[C]);
BINARY_OP_INT(and_, regD[a], regD[B], regD[C]);
break;
case OP_AND_RK:
cc.mov(regD[a], regD[B]);
cc.and_(regD[a], konstd[C]);
BINARY_OP_INT(and_, regD[a], regD[B], konstd[C]);
break;
case OP_OR_RR: // dA = dB | dkC
cc.mov(regD[a], regD[B]);
cc.or_(regD[a], regD[C]);
BINARY_OP_INT(or_, regD[a], regD[B], regD[C]);
break;
case OP_OR_RK:
cc.mov(regD[a], regD[B]);
cc.or_(regD[a], konstd[C]);
BINARY_OP_INT(or_, regD[a], regD[B], konstd[C]);
break;
case OP_XOR_RR: // dA = dB ^ dkC
cc.mov(regD[a], regD[B]);
cc.xor_(regD[a], regD[C]);
BINARY_OP_INT(xor_, regD[a], regD[B], regD[C]);
break;
case OP_XOR_RK:
cc.mov(regD[a], regD[B]);
cc.xor_(regD[a], konstd[C]);
BINARY_OP_INT(xor_, regD[a], regD[B], konstd[C]);
break;
case OP_MIN_RR: // dA = min(dB,dkC)
case OP_MIN_RK:
@ -922,9 +904,13 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc)
case OP_ABS: // dA = abs(dB)
break;
case OP_NEG: // dA = -dB
cc.xor_(regD[a], regD[a]);
cc.sub(regD[a], regD[B]);
{
auto tmp = cc.newInt32 ();
cc.xor_(tmp, tmp);
cc.sub(tmp, regD[B]);
cc.mov(regD[a], tmp);
break;
}
case OP_NOT: // dA = ~dB
cc.mov(regD[a], regD[B]);
cc.not_(regD[a]);
@ -1473,19 +1459,31 @@ JitFuncPtr JitCompile(VMScriptFunction *sfunc)
// Pointer math.
case OP_ADDA_RR: // pA = pB + dkC
cc.mov(regA[a], regA[B]);
cc.add(regA[a], regD[C]);
{
auto tmp = cc.newIntPtr();
cc.mov(tmp, regA[B]);
cc.add(tmp, regD[C]);
cc.mov(regA[a], tmp);
break;
}
case OP_ADDA_RK:
cc.mov(regA[a], regA[B]);
cc.add(regA[a], konstd[C]);
{
auto tmp = cc.newIntPtr();
cc.mov(tmp, regA[B]);
cc.add(tmp, konstd[C]);
cc.mov(regA[a], tmp);
break;
}
case OP_SUBA: // dA = pB - pC
cc.mov(regA[a], regA[B]);
cc.sub(regA[a], regD[C]);
{
auto tmp = cc.newIntPtr();
cc.mov(tmp, regA[B]);
cc.sub(tmp, regD[C]);
cc.mov(regA[a], tmp);
break;
}
case OP_EQA_R: // if ((pB == pkC) != A) then pc++
case OP_EQA_K: