From 591783087dc3930254141fa8138a1ce5e06debce Mon Sep 17 00:00:00 2001 From: Chronos Ouroboros Date: Tue, 14 Aug 2018 20:07:50 -0300 Subject: [PATCH] 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. --- src/scripting/vm/jit.cpp | 142 +++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 72 deletions(-) diff --git a/src/scripting/vm/jit.cpp b/src/scripting/vm/jit.cpp index 8a5018596..d9af0a7dc 100644 --- a/src/scripting/vm/jit.cpp +++ b/src/scripting/vm/jit.cpp @@ -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: