diff --git a/src/scripting/vm/jit.cpp b/src/scripting/vm/jit.cpp index 2ee5f9d5e2..bd130c0caf 100644 --- a/src/scripting/vm/jit.cpp +++ b/src/scripting/vm/jit.cpp @@ -159,20 +159,7 @@ bool JitCompiler::CanJit(VMScriptFunction *sfunc) // Partially implemented functions: auto pc = sfunc->Code + i; - if (sfunc->Code[i].op == OP_CAST) - { - switch (C) - { - case CAST_I2F: - case CAST_U2F: - case CAST_F2I: - case CAST_F2U: - break; - default: - return false; - } - } - else if (sfunc->Code[i].op == OP_PARAM) + if (sfunc->Code[i].op == OP_PARAM) { if (!!(B & REGT_MULTIREG3) || !!(B & REGT_MULTIREG2)) return false; diff --git a/src/scripting/vm/jit_move.cpp b/src/scripting/vm/jit_move.cpp index f93f776384..9a7bfbc795 100644 --- a/src/scripting/vm/jit_move.cpp +++ b/src/scripting/vm/jit_move.cpp @@ -1,5 +1,8 @@ #include "jitintern.h" +#include "v_video.h" +#include "s_sound.h" +#include "r_state.h" void JitCompiler::EmitMOVE() { @@ -38,88 +41,138 @@ void JitCompiler::EmitMOVEV3() void JitCompiler::EmitCAST() { + static void (*i2s)(FString *a, int b) = [](FString *a, int b) { a->Format("%d", b); }; + static void (*u2s)(FString *a, int b) = [](FString *a, int b) { a->Format("%u", b); }; + static void (*f2s)(FString *a, double b) = [](FString *a, double b) { a->Format("%.5f", b); }; + static void (*v22s)(FString *a, double b, double b1) = [](FString *a, double b, double b1) { a->Format("(%.5f, %.5f)", b, b1); }; + static void (*v32s)(FString *a, double b, double b1, double b2) = [](FString *a, double b, double b1, double b2) { a->Format("(%.5f, %.5f, %.5f)", b, b1, b2); }; + static void (*p2s)(FString *a, void *b) = [](FString *a, void *b) { if (b == nullptr) *a = "null"; else a->Format("%p", b); }; + static int (*s2i)(FString *b) = [](FString *b) -> int { return (VM_SWORD)b->ToLong(); }; + static double (*s2f)(FString *b) = [](FString *b) -> double { return b->ToDouble(); }; + static int (*s2n)(FString *b) = [](FString *b) -> int { return b->Len() == 0 ? FName(NAME_None) : FName(*b); }; + static void (*n2s)(FString *a, int b) = [](FString *a, int b) { FName name = FName(ENamedName(b)); *a = name.IsValidName() ? name.GetChars() : ""; }; + static int (*s2co)(FString *b) = [](FString *b) -> int { return V_GetColor(nullptr, *b); }; + static void (*co2s)(FString *a, int b) = [](FString *a, int b) { PalEntry c(b); a->Format("%02x %02x %02x", c.r, c.g, c.b); }; + static int (*s2so)(FString *b) = [](FString *b) -> int { return FSoundID(*b); }; + static void (*so2s)(FString *a, int b) = [](FString *a, int b) { *a = S_sfx[b].name; }; + static void (*sid2s)(FString *a, unsigned int b) = [](FString *a, unsigned int b) { *a = (b >= sprites.Size()) ? "TNT1" : sprites[b].name; }; + static void (*tid2s)(FString *a, int b) = [](FString *a, int b) { auto tex = TexMan[*(FTextureID*)&b]; *a = (tex == nullptr) ? "(null)" : tex->Name.GetChars(); }; + + typedef asmjit::FuncSignature2 FuncI2S, FuncU2S, FuncN2S, FuncCo2S, FuncSo2S, FuncSid2S, FuncTid2S; + typedef asmjit::FuncSignature2 FuncF2S; + typedef asmjit::FuncSignature3 FuncV22S; + typedef asmjit::FuncSignature4 FuncV32S; + typedef asmjit::FuncSignature2 FuncP2S; + typedef asmjit::FuncSignature1 FuncS2I, FuncS2N, FuncS2Co, FuncS2So; + typedef asmjit::FuncSignature1 FuncS2F; + + asmjit::X86Gp tmp; + asmjit::CCFuncCall *call = nullptr; + switch (C) { case CAST_I2F: cc.cvtsi2sd(regF[A], regD[B]); break; case CAST_U2F: - { - auto tmp = cc.newInt64(); + tmp = cc.newInt64(); cc.xor_(tmp, tmp); cc.mov(tmp.r32(), regD[B]); cc.cvtsi2sd(regF[A], tmp); break; - } case CAST_F2I: cc.cvttsd2si(regD[A], regF[B]); break; case CAST_F2U: - { - auto tmp = cc.newInt64(); + tmp = cc.newInt64(); cc.cvttsd2si(tmp, regF[B]); cc.mov(regD[A], tmp.r32()); break; - } - /*case CAST_I2S: - reg.s[A].Format("%d", reg.d[B]); + case CAST_I2S: + call = cc.call(ToMemAddress(reinterpret_cast(i2s)), FuncI2S()); + call->setArg(0, regS[A]); + call->setArg(1, regD[B]); break; case CAST_U2S: - reg.s[A].Format("%u", reg.d[B]); + call = cc.call(ToMemAddress(reinterpret_cast(u2s)), FuncU2S()); + call->setArg(0, regS[A]); + call->setArg(1, regD[B]); break; case CAST_F2S: - reg.s[A].Format("%.5f", reg.f[B]); // keep this small. For more precise conversion there should be a conversion function. + call = cc.call(ToMemAddress(reinterpret_cast(f2s)), FuncF2S()); + call->setArg(0, regS[A]); + call->setArg(1, regF[B]); break; case CAST_V22S: - reg.s[A].Format("(%.5f, %.5f)", reg.f[B], reg.f[b + 1]); + call = cc.call(ToMemAddress(reinterpret_cast(v22s)), FuncV22S()); + call->setArg(0, regS[A]); + call->setArg(1, regF[B]); + call->setArg(2, regF[B + 1]); break; case CAST_V32S: - reg.s[A].Format("(%.5f, %.5f, %.5f)", reg.f[B], reg.f[b + 1], reg.f[b + 2]); + call = cc.call(ToMemAddress(reinterpret_cast(v32s)), FuncV32S()); + call->setArg(0, regS[A]); + call->setArg(1, regF[B]); + call->setArg(2, regF[B + 1]); + call->setArg(3, regF[B + 2]); break; case CAST_P2S: - { - if (reg.a[B] == nullptr) reg.s[A] = "null"; - else reg.s[A].Format("%p", reg.a[B]); + call = cc.call(ToMemAddress(reinterpret_cast(p2s)), FuncP2S()); + call->setArg(0, regS[A]); + call->setArg(1, regA[B]); break; - } case CAST_S2I: - reg.d[A] = (VM_SWORD)reg.s[B].ToLong(); + call = cc.call(ToMemAddress(reinterpret_cast(s2i)), FuncS2I()); + call->setRet(0, regD[A]); + call->setArg(0, regS[B]); break; case CAST_S2F: - reg.f[A] = reg.s[B].ToDouble(); + call = cc.call(ToMemAddress(reinterpret_cast(s2f)), FuncS2F()); + call->setRet(0, regF[A]); + call->setArg(0, regS[B]); break; case CAST_S2N: - reg.d[A] = reg.s[B].Len() == 0 ? FName(NAME_None) : FName(reg.s[B]); + call = cc.call(ToMemAddress(reinterpret_cast(s2n)), FuncS2N()); + call->setRet(0, regD[A]); + call->setArg(0, regS[B]); break; case CAST_N2S: - { - FName name = FName(ENamedName(reg.d[B])); - reg.s[A] = name.IsValidName() ? name.GetChars() : ""; + call = cc.call(ToMemAddress(reinterpret_cast(n2s)), FuncN2S()); + call->setArg(0, regS[A]); + call->setArg(1, regD[B]); break; - } case CAST_S2Co: - reg.d[A] = V_GetColor(NULL, reg.s[B]); + call = cc.call(ToMemAddress(reinterpret_cast(s2co)), FuncS2Co()); + call->setRet(0, regD[A]); + call->setArg(0, regS[B]); break; case CAST_Co2S: - reg.s[A].Format("%02x %02x %02x", PalEntry(reg.d[B]).r, PalEntry(reg.d[B]).g, PalEntry(reg.d[B]).b); + call = cc.call(ToMemAddress(reinterpret_cast(co2s)), FuncCo2S()); + call->setArg(0, regS[A]); + call->setArg(1, regD[B]); break; case CAST_S2So: - reg.d[A] = FSoundID(reg.s[B]); + call = cc.call(ToMemAddress(reinterpret_cast(s2so)), FuncS2So()); + call->setRet(0, regD[A]); + call->setArg(0, regS[B]); break; case CAST_So2S: - reg.s[A] = S_sfx[reg.d[B]].name; + call = cc.call(ToMemAddress(reinterpret_cast(so2s)), FuncSo2S()); + call->setArg(0, regS[A]); + call->setArg(1, regD[B]); break; case CAST_SID2S: - reg.s[A] = unsigned(reg.d[B]) >= sprites.Size() ? "TNT1" : sprites[reg.d[B]].name; + call = cc.call(ToMemAddress(reinterpret_cast(sid2s)), FuncSid2S()); + call->setArg(0, regS[A]); + call->setArg(1, regD[B]); break; case CAST_TID2S: - { - auto tex = TexMan[*(FTextureID*)&(reg.d[B])]; - reg.s[A] = tex == nullptr ? "(null)" : tex->Name.GetChars(); + call = cc.call(ToMemAddress(reinterpret_cast(tid2s)), FuncTid2S()); + call->setArg(0, regS[A]); + call->setArg(1, regD[B]); break; - }*/ default: - assert(0); + I_FatalError("Unknown OP_CAST type\n"); } }