- added a boolean cast VM instruction.

Although this already helps a lot with the messed up code generated for comparisons it's not really a solution for this - it still needs a proper implementation to generate efficient code.
This commit is contained in:
Christoph Oelckers 2016-12-01 01:13:53 +01:00
parent 87484950cf
commit 7688e14bec
5 changed files with 43 additions and 21 deletions

View file

@ -758,25 +758,7 @@ ExpEmit FxBoolCast::Emit(VMFunctionBuilder *build)
ExpEmit to(build, REGT_INT);
from.Free(build);
// Preload result with 0.
build->Emit(OP_LI, to.RegNum, 0);
// Check source against 0.
if (from.RegType == REGT_INT)
{
build->Emit(OP_EQ_R, 1, from.RegNum, to.RegNum);
}
else if (from.RegType == REGT_FLOAT)
{
build->Emit(OP_EQF_K, 1, from.RegNum, build->GetConstantFloat(0.));
}
else if (from.RegType == REGT_POINTER)
{
build->Emit(OP_EQA_K, 1, from.RegNum, build->GetConstantAddress(nullptr, ATAG_GENERIC));
}
build->Emit(OP_JMP, 1);
// Reload result with 1 if the comparison fell through.
build->Emit(OP_LI, to.RegNum, 1);
build->Emit(OP_CASTB, to.RegNum, from.RegNum, from.RegType == REGT_INT ? CASTB_I : from.RegType == REGT_FLOAT ? CASTB_F : CASTB_A);
return to;
}
else

View file

@ -130,6 +130,11 @@ enum
CAST_V32S,
CAST_SID2S,
CAST_TID2S,
CASTB_I,
CASTB_F,
CASTB_A,
CASTB_S
};
// Register types for VMParam

View file

@ -90,6 +90,7 @@
#define THROW MODE_AIMMZ | MODE_BCTHROW
#define CATCH MODE_AIMMZ | MODE_BCCATCH
#define CAST MODE_AX | MODE_BX | MODE_CIMMZ | MODE_BCCAST
#define CASTB MODE_AI | MODE_BX | MODE_CIMMZ | MODE_BCCAST
#define RSRSRS MODE_AS | MODE_BS | MODE_CS
#define RIRS MODE_AI | MODE_BS | MODE_CUNUSED
@ -381,10 +382,18 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
break;
default:
if ((mode & MODE_BCTYPE) == MODE_BCCAST)
{
switch (code[i].c)
{
case CASTB_I:
mode = MODE_AI | MODE_BI | MODE_CUNUSED;
break;
case CASTB_A:
mode = MODE_AI | MODE_BP | MODE_CUNUSED;
break;
case CAST_I2F:
case CAST_U2F:
mode = MODE_AF | MODE_BI | MODE_CUNUSED;
@ -398,6 +407,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
break;
case CAST_F2I:
case CAST_F2U:
case CASTB_F:
mode = MODE_AI | MODE_BF | MODE_CUNUSED;
break;
case CAST_F2S:
@ -412,6 +422,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
case CAST_S2So:
case CAST_S2N:
case CAST_S2I:
case CASTB_S:
mode = MODE_AI | MODE_BS | MODE_CUNUSED;
break;
case CAST_S2F:

View file

@ -419,12 +419,12 @@ begin:
if (C == CAST_I2F)
{
ASSERTF(a); ASSERTD(B);
reg.f[A] = reg.d[B];
reg.f[a] = reg.d[B];
}
else if (C == CAST_F2I)
{
ASSERTD(a); ASSERTF(B);
reg.d[A] = (int)reg.f[B];
reg.d[a] = (int)reg.f[B];
}
else
{
@ -432,6 +432,29 @@ begin:
}
NEXTOP;
OP(CASTB):
if (C == CASTB_I)
{
ASSERTD(a); ASSERTD(B);
reg.f[a] = !!reg.d[B];
}
else if (C == CASTB_F)
{
ASSERTD(a); ASSERTF(B);
reg.d[a] = reg.f[B] != 0;
}
else if (c == CASTB_A)
{
ASSERTD(a); ASSERTA(B);
reg.d[a] = reg.a[B] != nullptr;
}
else
{
ASSERTD(a); ASSERTS(B);
reg.d[a] = reg.s[B].Len() > 0;
}
NEXTOP;
OP(TEST):
ASSERTD(a);
if (reg.d[a] != BC)

View file

@ -83,6 +83,7 @@ xx(MOVEA, mov, RPRP, NOP, 0, 0), // aA = aB
xx(MOVEV2, mov2, RFRF, NOP, 0, 0), // fA = fB (2 elements)
xx(MOVEV3, mov3, RFRF, NOP, 0, 0), // fA = fB (3 elements)
xx(CAST, cast, CAST, NOP, 0, 0), // xA = xB, conversion specified by C
xx(CASTB, castb, CAST, NOP, 0, 0), // xA = !!xB, type specified by C
// Control flow.
xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++