2018-09-13 00:29:04 +00:00
|
|
|
|
|
|
|
#include "jitintern.h"
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Load constants.
|
|
|
|
|
|
|
|
void JitCompiler::EmitLI()
|
|
|
|
{
|
|
|
|
cc.mov(regD[A], BCs);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLK()
|
|
|
|
{
|
|
|
|
cc.mov(regD[A], konstd[BC]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLKF()
|
|
|
|
{
|
2018-10-07 07:02:28 +00:00
|
|
|
auto base = newTempIntPtr();
|
2018-09-18 16:13:53 +00:00
|
|
|
cc.mov(base, asmjit::imm_ptr(konstf + BC));
|
2018-09-15 13:38:16 +00:00
|
|
|
cc.movsd(regF[A], asmjit::x86::qword_ptr(base));
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLKS()
|
|
|
|
{
|
2018-09-17 10:00:25 +00:00
|
|
|
auto call = CreateCall<void, FString*, FString*>(&JitCompiler::CallAssignString);
|
2018-09-13 00:29:04 +00:00
|
|
|
call->setArg(0, regS[A]);
|
2018-09-18 16:13:53 +00:00
|
|
|
call->setArg(1, asmjit::imm_ptr(konsts + BC));
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLKP()
|
|
|
|
{
|
|
|
|
cc.mov(regA[A], (int64_t)konsta[BC].v);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLK_R()
|
|
|
|
{
|
2018-10-07 07:02:28 +00:00
|
|
|
auto base = newTempIntPtr();
|
2018-09-18 16:13:53 +00:00
|
|
|
cc.mov(base, asmjit::imm_ptr(konstd + C));
|
2018-09-15 13:38:16 +00:00
|
|
|
cc.mov(regD[A], asmjit::x86::ptr(base, regD[B], 2));
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLKF_R()
|
|
|
|
{
|
2018-10-07 07:02:28 +00:00
|
|
|
auto base = newTempIntPtr();
|
2018-09-18 16:13:53 +00:00
|
|
|
cc.mov(base, asmjit::imm_ptr(konstf + C));
|
2018-09-15 13:38:16 +00:00
|
|
|
cc.movsd(regF[A], asmjit::x86::qword_ptr(base, regD[B], 3));
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLKS_R()
|
|
|
|
{
|
2018-10-07 07:02:28 +00:00
|
|
|
auto base = newTempIntPtr();
|
2018-09-18 16:13:53 +00:00
|
|
|
cc.mov(base, asmjit::imm_ptr(konsts + C));
|
2018-10-07 07:02:28 +00:00
|
|
|
auto ptr = newTempIntPtr();
|
2018-10-07 18:55:06 +00:00
|
|
|
if (cc.is64Bit())
|
|
|
|
cc.lea(ptr, asmjit::x86::ptr(base, regD[B], 3));
|
|
|
|
else
|
|
|
|
cc.lea(ptr, asmjit::x86::ptr(base, regD[B], 2));
|
2018-09-17 10:00:25 +00:00
|
|
|
auto call = CreateCall<void, FString*, FString*>(&JitCompiler::CallAssignString);
|
2018-09-14 23:25:13 +00:00
|
|
|
call->setArg(0, regS[A]);
|
|
|
|
call->setArg(1, ptr);
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLKP_R()
|
|
|
|
{
|
2018-10-07 07:02:28 +00:00
|
|
|
auto base = newTempIntPtr();
|
2018-09-18 16:13:53 +00:00
|
|
|
cc.mov(base, asmjit::imm_ptr(konsta + C));
|
2018-10-07 18:55:06 +00:00
|
|
|
if (cc.is64Bit())
|
|
|
|
cc.mov(regA[A], asmjit::x86::ptr(base, regD[B], 3));
|
|
|
|
else
|
|
|
|
cc.mov(regA[A], asmjit::x86::ptr(base, regD[B], 2));
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLFP()
|
|
|
|
{
|
2018-09-16 01:39:54 +00:00
|
|
|
cc.lea(regA[A], asmjit::x86::ptr(vmframe, offsetExtra));
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitMETA()
|
|
|
|
{
|
2018-11-10 21:48:20 +00:00
|
|
|
auto label = EmitThrowExceptionLabel(X_READ_NIL);
|
2018-09-13 00:29:04 +00:00
|
|
|
cc.test(regA[B], regA[B]);
|
2018-11-10 21:48:20 +00:00
|
|
|
cc.je(label);
|
2018-09-13 00:29:04 +00:00
|
|
|
|
2018-10-07 07:02:28 +00:00
|
|
|
auto result = newResultIntPtr();
|
2018-09-17 10:00:25 +00:00
|
|
|
auto call = CreateCall<uint8_t*, DObject*>([](DObject *o) { return o->GetClass()->Meta; });
|
2018-10-07 04:29:54 +00:00
|
|
|
call->setRet(0, result);
|
2018-09-13 00:29:04 +00:00
|
|
|
call->setArg(0, regA[B]);
|
2018-10-07 04:29:54 +00:00
|
|
|
cc.mov(regA[A], result);
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitCLSS()
|
|
|
|
{
|
2018-11-10 21:48:20 +00:00
|
|
|
auto label = EmitThrowExceptionLabel(X_READ_NIL);
|
2018-09-13 00:29:04 +00:00
|
|
|
cc.test(regA[B], regA[B]);
|
2018-11-10 21:48:20 +00:00
|
|
|
cc.je(label);
|
2018-09-13 00:29:04 +00:00
|
|
|
|
2018-10-07 07:02:28 +00:00
|
|
|
auto result = newResultIntPtr();
|
2018-09-17 10:00:25 +00:00
|
|
|
auto call = CreateCall<PClass*, DObject*>([](DObject *o) { return o->GetClass(); });
|
2018-10-07 04:29:54 +00:00
|
|
|
call->setRet(0, result);
|
2018-09-13 00:29:04 +00:00
|
|
|
call->setArg(0, regA[B]);
|
2018-10-07 04:29:54 +00:00
|
|
|
cc.mov(regA[A], result);
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Load from memory. rA = *(rB + rkC)
|
|
|
|
|
|
|
|
void JitCompiler::EmitLB()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.movsx(regD[A], asmjit::x86::byte_ptr(regA[B], konstd[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLB_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.movsx(regD[A], asmjit::x86::byte_ptr(regA[B], regD[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLH()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.movsx(regD[A], asmjit::x86::word_ptr(regA[B], konstd[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLH_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.movsx(regD[A], asmjit::x86::word_ptr(regA[B], regD[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLW()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.mov(regD[A], asmjit::x86::dword_ptr(regA[B], konstd[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLW_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.mov(regD[A], asmjit::x86::dword_ptr(regA[B], regD[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLBU()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.movzx(regD[A], asmjit::x86::byte_ptr(regA[B], konstd[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLBU_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.movzx(regD[A].r8Lo(), asmjit::x86::byte_ptr(regA[B], regD[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLHU()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.movzx(regD[A].r16(), asmjit::x86::word_ptr(regA[B], konstd[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLHU_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.movzx(regD[A].r16(), asmjit::x86::word_ptr(regA[B], regD[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLSP()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
2018-10-11 01:53:11 +00:00
|
|
|
cc.xorpd(regF[A], regF[A]);
|
|
|
|
cc.cvtss2sd(regF[A], asmjit::x86::dword_ptr(regA[B], konstd[C]));
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLSP_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
2018-10-11 01:53:11 +00:00
|
|
|
cc.xorpd(regF[A], regF[A]);
|
|
|
|
cc.cvtss2sd(regF[A], asmjit::x86::dword_ptr(regA[B], regD[C]));
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLDP()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.movsd(regF[A], asmjit::x86::qword_ptr(regA[B], konstd[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLDP_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.movsd(regF[A], asmjit::x86::qword_ptr(regA[B], regD[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLS()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
2018-10-07 07:02:28 +00:00
|
|
|
auto ptr = newTempIntPtr();
|
2018-09-15 20:09:43 +00:00
|
|
|
cc.lea(ptr, asmjit::x86::ptr(regA[B], konstd[C]));
|
2018-09-17 10:00:25 +00:00
|
|
|
auto call = CreateCall<void, FString*, FString*>(&JitCompiler::CallAssignString);
|
2018-09-13 00:29:04 +00:00
|
|
|
call->setArg(0, regS[A]);
|
|
|
|
call->setArg(1, ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLS_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
2018-10-07 07:02:28 +00:00
|
|
|
auto ptr = newTempIntPtr();
|
2018-09-15 20:09:43 +00:00
|
|
|
cc.lea(ptr, asmjit::x86::ptr(regA[B], regD[C]));
|
2018-09-17 10:00:25 +00:00
|
|
|
auto call = CreateCall<void, FString*, FString*>(&JitCompiler::CallAssignString);
|
2018-09-13 00:29:04 +00:00
|
|
|
call->setArg(0, regS[A]);
|
|
|
|
call->setArg(1, ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLO()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
|
2018-10-07 07:02:28 +00:00
|
|
|
auto ptr = newTempIntPtr();
|
2018-09-13 00:29:04 +00:00
|
|
|
cc.mov(ptr, asmjit::x86::ptr(regA[B], konstd[C]));
|
|
|
|
|
2018-10-07 07:02:28 +00:00
|
|
|
auto result = newResultIntPtr();
|
2018-09-17 10:00:25 +00:00
|
|
|
auto call = CreateCall<DObject*,DObject*>([](DObject *p) { return GC::ReadBarrier(p); });
|
2018-10-07 04:29:54 +00:00
|
|
|
call->setRet(0, result);
|
2018-09-13 00:29:04 +00:00
|
|
|
call->setArg(0, ptr);
|
2018-10-07 04:29:54 +00:00
|
|
|
cc.mov(regA[A], result);
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLO_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
|
2018-10-07 07:02:28 +00:00
|
|
|
auto ptr = newTempIntPtr();
|
2018-09-13 00:29:04 +00:00
|
|
|
cc.mov(ptr, asmjit::x86::ptr(regA[B], regD[C]));
|
|
|
|
|
2018-10-07 07:02:28 +00:00
|
|
|
auto result = newResultIntPtr();
|
2018-09-17 10:00:25 +00:00
|
|
|
auto call = CreateCall<DObject*, DObject*>([](DObject *p) { return GC::ReadBarrier(p); });
|
2018-10-07 04:29:54 +00:00
|
|
|
call->setRet(0, result);
|
2018-09-13 00:29:04 +00:00
|
|
|
call->setArg(0, ptr);
|
2018-10-07 04:29:54 +00:00
|
|
|
cc.mov(regA[A], result);
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLP()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.mov(regA[A], asmjit::x86::ptr(regA[B], konstd[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLP_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.mov(regA[A], asmjit::x86::ptr(regA[B], regD[C]));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLV2()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
2018-10-07 07:02:28 +00:00
|
|
|
auto tmp = newTempIntPtr();
|
2018-11-15 21:07:27 +00:00
|
|
|
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], konstd[C]));
|
2018-09-13 00:29:04 +00:00
|
|
|
cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp));
|
|
|
|
cc.movsd(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLV2_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
2018-10-07 07:02:28 +00:00
|
|
|
auto tmp = newTempIntPtr();
|
2018-11-15 21:07:27 +00:00
|
|
|
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C]));
|
2018-09-13 00:29:04 +00:00
|
|
|
cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp));
|
|
|
|
cc.movsd(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLV3()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
2018-10-07 07:02:28 +00:00
|
|
|
auto tmp = newTempIntPtr();
|
2018-11-15 21:07:27 +00:00
|
|
|
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], konstd[C]));
|
2018-09-13 00:29:04 +00:00
|
|
|
cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp));
|
|
|
|
cc.movsd(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8));
|
|
|
|
cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLV3_R()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
2018-10-07 07:02:28 +00:00
|
|
|
auto tmp = newTempIntPtr();
|
2018-11-15 21:07:27 +00:00
|
|
|
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C]));
|
2018-09-13 00:29:04 +00:00
|
|
|
cc.movsd(regF[A], asmjit::x86::qword_ptr(tmp));
|
|
|
|
cc.movsd(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8));
|
|
|
|
cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16));
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLCS()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
2018-10-07 07:02:28 +00:00
|
|
|
auto ptr = newTempIntPtr();
|
2018-09-15 20:09:43 +00:00
|
|
|
cc.lea(ptr, asmjit::x86::ptr(regA[B], konstd[C]));
|
2018-09-17 10:00:25 +00:00
|
|
|
auto call = CreateCall<void, FString*, char**>([](FString* to, char** from) { *to = *from; });
|
2018-09-13 00:29:04 +00:00
|
|
|
call->setArg(0, regS[A]);
|
|
|
|
call->setArg(1, ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLCS_R()
|
|
|
|
{
|
2018-09-14 23:25:13 +00:00
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
2018-10-07 07:02:28 +00:00
|
|
|
auto ptr = newTempIntPtr();
|
2018-09-15 20:09:43 +00:00
|
|
|
cc.lea(ptr, asmjit::x86::ptr(regA[B], regD[C]));
|
2018-09-17 10:00:25 +00:00
|
|
|
auto call = CreateCall<void, FString*, char**>([](FString* to, char** from) { *to = *from; });
|
2018-09-14 23:25:13 +00:00
|
|
|
call->setArg(0, regS[A]);
|
|
|
|
call->setArg(1, ptr);
|
2018-09-13 00:29:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void JitCompiler::EmitLBIT()
|
|
|
|
{
|
|
|
|
EmitNullPointerThrow(B, X_READ_NIL);
|
|
|
|
cc.movsx(regD[A], asmjit::x86::byte_ptr(regA[B]));
|
|
|
|
cc.and_(regD[A], C);
|
|
|
|
cc.cmp(regD[A], 0);
|
|
|
|
cc.setne(regD[A]);
|
|
|
|
}
|