- 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); ExpEmit to(build, REGT_INT);
from.Free(build); from.Free(build);
// Preload result with 0. // Preload result with 0.
build->Emit(OP_LI, to.RegNum, 0); build->Emit(OP_CASTB, to.RegNum, from.RegNum, from.RegType == REGT_INT ? CASTB_I : from.RegType == REGT_FLOAT ? CASTB_F : CASTB_A);
// 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);
return to; return to;
} }
else else

View file

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

View file

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

View file

@ -419,12 +419,12 @@ begin:
if (C == CAST_I2F) if (C == CAST_I2F)
{ {
ASSERTF(a); ASSERTD(B); ASSERTF(a); ASSERTD(B);
reg.f[A] = reg.d[B]; reg.f[a] = reg.d[B];
} }
else if (C == CAST_F2I) else if (C == CAST_F2I)
{ {
ASSERTD(a); ASSERTF(B); ASSERTD(a); ASSERTF(B);
reg.d[A] = (int)reg.f[B]; reg.d[a] = (int)reg.f[B];
} }
else else
{ {
@ -432,6 +432,29 @@ begin:
} }
NEXTOP; 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): OP(TEST):
ASSERTD(a); ASSERTD(a);
if (reg.d[a] != BC) 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(MOVEV2, mov2, RFRF, NOP, 0, 0), // fA = fB (2 elements)
xx(MOVEV3, mov3, RFRF, NOP, 0, 0), // fA = fB (3 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(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. // Control flow.
xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++ xx(TEST, test, RII16, NOP, 0, 0), // if (dA != BC) then pc++