mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 23:32:02 +00:00
- implement string version of OP_CAST
This commit is contained in:
parent
102c00ce13
commit
da040e818c
2 changed files with 87 additions and 47 deletions
|
@ -159,20 +159,7 @@ bool JitCompiler::CanJit(VMScriptFunction *sfunc)
|
||||||
// Partially implemented functions:
|
// Partially implemented functions:
|
||||||
|
|
||||||
auto pc = sfunc->Code + i;
|
auto pc = sfunc->Code + i;
|
||||||
if (sfunc->Code[i].op == OP_CAST)
|
if (sfunc->Code[i].op == OP_PARAM)
|
||||||
{
|
|
||||||
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 (!!(B & REGT_MULTIREG3) || !!(B & REGT_MULTIREG2))
|
if (!!(B & REGT_MULTIREG3) || !!(B & REGT_MULTIREG2))
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
|
||||||
#include "jitintern.h"
|
#include "jitintern.h"
|
||||||
|
#include "v_video.h"
|
||||||
|
#include "s_sound.h"
|
||||||
|
#include "r_state.h"
|
||||||
|
|
||||||
void JitCompiler::EmitMOVE()
|
void JitCompiler::EmitMOVE()
|
||||||
{
|
{
|
||||||
|
@ -38,88 +41,138 @@ void JitCompiler::EmitMOVEV3()
|
||||||
|
|
||||||
void JitCompiler::EmitCAST()
|
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<void, FString*, int> FuncI2S, FuncU2S, FuncN2S, FuncCo2S, FuncSo2S, FuncSid2S, FuncTid2S;
|
||||||
|
typedef asmjit::FuncSignature2<void, FString*, double> FuncF2S;
|
||||||
|
typedef asmjit::FuncSignature3<void, FString*, double, double> FuncV22S;
|
||||||
|
typedef asmjit::FuncSignature4<void, FString*, double, double, double> FuncV32S;
|
||||||
|
typedef asmjit::FuncSignature2<void, FString*, void*> FuncP2S;
|
||||||
|
typedef asmjit::FuncSignature1<int, FString*> FuncS2I, FuncS2N, FuncS2Co, FuncS2So;
|
||||||
|
typedef asmjit::FuncSignature1<double, FString*> FuncS2F;
|
||||||
|
|
||||||
|
asmjit::X86Gp tmp;
|
||||||
|
asmjit::CCFuncCall *call = nullptr;
|
||||||
|
|
||||||
switch (C)
|
switch (C)
|
||||||
{
|
{
|
||||||
case CAST_I2F:
|
case CAST_I2F:
|
||||||
cc.cvtsi2sd(regF[A], regD[B]);
|
cc.cvtsi2sd(regF[A], regD[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_U2F:
|
case CAST_U2F:
|
||||||
{
|
tmp = cc.newInt64();
|
||||||
auto tmp = cc.newInt64();
|
|
||||||
cc.xor_(tmp, tmp);
|
cc.xor_(tmp, tmp);
|
||||||
cc.mov(tmp.r32(), regD[B]);
|
cc.mov(tmp.r32(), regD[B]);
|
||||||
cc.cvtsi2sd(regF[A], tmp);
|
cc.cvtsi2sd(regF[A], tmp);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case CAST_F2I:
|
case CAST_F2I:
|
||||||
cc.cvttsd2si(regD[A], regF[B]);
|
cc.cvttsd2si(regD[A], regF[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_F2U:
|
case CAST_F2U:
|
||||||
{
|
tmp = cc.newInt64();
|
||||||
auto tmp = cc.newInt64();
|
|
||||||
cc.cvttsd2si(tmp, regF[B]);
|
cc.cvttsd2si(tmp, regF[B]);
|
||||||
cc.mov(regD[A], tmp.r32());
|
cc.mov(regD[A], tmp.r32());
|
||||||
break;
|
break;
|
||||||
}
|
case CAST_I2S:
|
||||||
/*case CAST_I2S:
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(i2s)), FuncI2S());
|
||||||
reg.s[A].Format("%d", reg.d[B]);
|
call->setArg(0, regS[A]);
|
||||||
|
call->setArg(1, regD[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_U2S:
|
case CAST_U2S:
|
||||||
reg.s[A].Format("%u", reg.d[B]);
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(u2s)), FuncU2S());
|
||||||
|
call->setArg(0, regS[A]);
|
||||||
|
call->setArg(1, regD[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_F2S:
|
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<const void*>(f2s)), FuncF2S());
|
||||||
|
call->setArg(0, regS[A]);
|
||||||
|
call->setArg(1, regF[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_V22S:
|
case CAST_V22S:
|
||||||
reg.s[A].Format("(%.5f, %.5f)", reg.f[B], reg.f[b + 1]);
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(v22s)), FuncV22S());
|
||||||
|
call->setArg(0, regS[A]);
|
||||||
|
call->setArg(1, regF[B]);
|
||||||
|
call->setArg(2, regF[B + 1]);
|
||||||
break;
|
break;
|
||||||
case CAST_V32S:
|
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<const void*>(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;
|
break;
|
||||||
case CAST_P2S:
|
case CAST_P2S:
|
||||||
{
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(p2s)), FuncP2S());
|
||||||
if (reg.a[B] == nullptr) reg.s[A] = "null";
|
call->setArg(0, regS[A]);
|
||||||
else reg.s[A].Format("%p", reg.a[B]);
|
call->setArg(1, regA[B]);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case CAST_S2I:
|
case CAST_S2I:
|
||||||
reg.d[A] = (VM_SWORD)reg.s[B].ToLong();
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(s2i)), FuncS2I());
|
||||||
|
call->setRet(0, regD[A]);
|
||||||
|
call->setArg(0, regS[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_S2F:
|
case CAST_S2F:
|
||||||
reg.f[A] = reg.s[B].ToDouble();
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(s2f)), FuncS2F());
|
||||||
|
call->setRet(0, regF[A]);
|
||||||
|
call->setArg(0, regS[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_S2N:
|
case CAST_S2N:
|
||||||
reg.d[A] = reg.s[B].Len() == 0 ? FName(NAME_None) : FName(reg.s[B]);
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(s2n)), FuncS2N());
|
||||||
|
call->setRet(0, regD[A]);
|
||||||
|
call->setArg(0, regS[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_N2S:
|
case CAST_N2S:
|
||||||
{
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(n2s)), FuncN2S());
|
||||||
FName name = FName(ENamedName(reg.d[B]));
|
call->setArg(0, regS[A]);
|
||||||
reg.s[A] = name.IsValidName() ? name.GetChars() : "";
|
call->setArg(1, regD[B]);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case CAST_S2Co:
|
case CAST_S2Co:
|
||||||
reg.d[A] = V_GetColor(NULL, reg.s[B]);
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(s2co)), FuncS2Co());
|
||||||
|
call->setRet(0, regD[A]);
|
||||||
|
call->setArg(0, regS[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_Co2S:
|
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<const void*>(co2s)), FuncCo2S());
|
||||||
|
call->setArg(0, regS[A]);
|
||||||
|
call->setArg(1, regD[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_S2So:
|
case CAST_S2So:
|
||||||
reg.d[A] = FSoundID(reg.s[B]);
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(s2so)), FuncS2So());
|
||||||
|
call->setRet(0, regD[A]);
|
||||||
|
call->setArg(0, regS[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_So2S:
|
case CAST_So2S:
|
||||||
reg.s[A] = S_sfx[reg.d[B]].name;
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(so2s)), FuncSo2S());
|
||||||
|
call->setArg(0, regS[A]);
|
||||||
|
call->setArg(1, regD[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_SID2S:
|
case CAST_SID2S:
|
||||||
reg.s[A] = unsigned(reg.d[B]) >= sprites.Size() ? "TNT1" : sprites[reg.d[B]].name;
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(sid2s)), FuncSid2S());
|
||||||
|
call->setArg(0, regS[A]);
|
||||||
|
call->setArg(1, regD[B]);
|
||||||
break;
|
break;
|
||||||
case CAST_TID2S:
|
case CAST_TID2S:
|
||||||
{
|
call = cc.call(ToMemAddress(reinterpret_cast<const void*>(tid2s)), FuncTid2S());
|
||||||
auto tex = TexMan[*(FTextureID*)&(reg.d[B])];
|
call->setArg(0, regS[A]);
|
||||||
reg.s[A] = tex == nullptr ? "(null)" : tex->Name.GetChars();
|
call->setArg(1, regD[B]);
|
||||||
break;
|
break;
|
||||||
}*/
|
|
||||||
default:
|
default:
|
||||||
assert(0);
|
I_FatalError("Unknown OP_CAST type\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue