Use separate instructions in the bytecode for manipulating global variables versus more complex variable types. The optimization that transforms CON_DIVVAR and CON_MULVAR into CON_SHIFTVARR and CON_SHIFTVARL plus CON_INV has been disabled for now until I can debug a problem with it.

git-svn-id: https://svn.eduke32.com/eduke32@7263 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
terminx 2018-12-15 01:38:00 +00:00
parent 702d30f2b5
commit dbdf662790
3 changed files with 434 additions and 238 deletions

View File

@ -674,7 +674,37 @@ static const vec2_t varvartable[] =
{ CON_XORVARVAR, CON_XORVAR },
};
static const vec2_t globalvartable[] =
{
{ CON_SHIFTVARL, CON_SHIFTGLOBALVARL },
{ CON_SHIFTVARR, CON_SHIFTGLOBALVARR },
{ CON_RANDVAR, CON_RANDGLOBALVAR },
{ CON_MODVAR, CON_MODGLOBALVAR },
{ CON_ANDVAR, CON_ANDGLOBALVAR },
{ CON_ADDVAR, CON_ADDGLOBALVAR },
{ CON_ORVAR, CON_ORGLOBALVAR },
{ CON_SETVAR, CON_SETGLOBALVAR },
{ CON_SUBVAR, CON_SUBGLOBALVAR },
{ CON_XORVAR, CON_XORGLOBALVAR },
{ CON_MULVAR, CON_MULGLOBALVAR },
{ CON_DIVVAR, CON_DIVGLOBALVAR },
{ CON_WHILEVARL, CON_WHILEGLOBALVARL },
{ CON_WHILEVARN, CON_WHILEGLOBALVARN },
};
static inthashtable_t h_varvar = { NULL, INTHASH_SIZE(ARRAY_SIZE(varvartable)) };
static inthashtable_t h_globalvar = { NULL, INTHASH_SIZE(ARRAY_SIZE(globalvartable)) };
static inthashtable_t *const inttables[] = {
&h_varvar,
&h_globalvar,
};
static inthashtable_t *const inttables_free[] = {
&h_varvar,
&h_globalvar,
};
const tokenmap_t iter_tokens [] =
{
@ -704,7 +734,7 @@ char const * VM_GetKeywordForID(int32_t id)
if (keyword.val == id)
return keyword.token;
return "<invalid keyword>";
return id < CON_OPCODE_END ? "<internal instruction>" : "<invalid keyword>";
}
#endif
@ -3324,139 +3354,6 @@ DO_DEFSTATE:
continue;
}
case CON_ADDVARVAR:
case CON_ANDVARVAR:
case CON_DISPLAYRANDVARVAR:
case CON_DIVVARVAR:
case CON_MODVARVAR:
case CON_MULVARVAR:
case CON_ORVARVAR:
case CON_RANDVARVAR:
case CON_SETVARVAR:
case CON_SHIFTVARVARL:
case CON_SHIFTVARVARR:
case CON_SUBVARVAR:
case CON_XORVARVAR:
{
setvarvar:
auto ins = &g_scriptPtr[-1];
C_GetNextVarType(GAMEVAR_READONLY);
C_GetNextVar();
int const opcode = inthash_find(&h_varvar, *ins & VM_INSTMASK);
if (ins[2] == GV_FLAG_CONSTANT && opcode != -1)
{
if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1)
{
initprintf("%s:%d: replacing %s with %s\n", g_scriptFileName, g_lineNumber,
VM_GetKeywordForID(*ins & VM_INSTMASK), VM_GetKeywordForID(opcode));
}
g_scriptPtr--;
tw = opcode;
scriptWriteAtOffset(opcode | LINE_NUMBER, ins);
scriptWriteAtOffset(ins[3], &ins[2]);
}
continue;
}
case CON_GETACTORVAR:
case CON_GETPLAYERVAR:
case CON_SETACTORVAR:
case CON_SETPLAYERVAR:
{
// syntax [gs]etactorvar[<var>].<varx> <VAR>
// gets the value of the per-actor variable varx into VAR
if (C_GetStructureIndexes(1, NULL) == -1)
continue;
if (g_scriptPtr[-1] == g_thisActorVarID) // convert to "setvarvar"
{
g_scriptPtr--;
g_scriptPtr[-1]=CON_SETVARVAR;
if (tw == CON_SETACTORVAR || tw == CON_SETPLAYERVAR)
{
tw = inthash_find(&h_varvar, tw);
goto setvarvar;
}
else
{
g_scriptPtr++;
C_GetNextVar();
g_scriptPtr-=2;
C_GetNextVarType(GAMEVAR_READONLY);
g_scriptPtr++;
}
continue;
}
/// now pointing at 'xxx'
C_GetNextLabelName();
if (EDUKE32_PREDICT_FALSE(hash_find(&h_keywords,LAST_LABEL)>=0))
{
g_errorCnt++;
C_ReportError(ERROR_ISAKEYWORD);
continue;
}
i=GetDefID(LAST_LABEL);
if (EDUKE32_PREDICT_FALSE(i<0))
{
g_errorCnt++;
C_ReportError(ERROR_NOTAGAMEVAR);
continue;
}
if (EDUKE32_PREDICT_FALSE(aGameVars[i].flags & GAMEVAR_READONLY))
{
g_errorCnt++;
C_ReportError(ERROR_VARREADONLY);
continue;
}
switch (tw)
{
case CON_SETACTORVAR:
if (EDUKE32_PREDICT_FALSE(!(aGameVars[i].flags & GAMEVAR_PERACTOR)))
{
g_errorCnt++;
C_ReportError(-1);
initprintf("%s:%d: error: variable `%s' is not per-actor.\n",g_scriptFileName,g_lineNumber,LAST_LABEL);
continue;
}
break;
case CON_SETPLAYERVAR:
if (EDUKE32_PREDICT_FALSE(!(aGameVars[i].flags & GAMEVAR_PERPLAYER)))
{
g_errorCnt++;
C_ReportError(-1);
initprintf("%s:%d: error: variable `%s' is not per-player.\n",g_scriptFileName,g_lineNumber,LAST_LABEL);
continue;
}
break;
}
scriptWriteValue(i); // the ID of the DEF (offset into array...)
switch (tw)
{
case CON_GETACTORVAR:
case CON_GETPLAYERVAR:
C_GetNextVarType(GAMEVAR_READONLY);
break;
default:
C_GetNextVar();
break;
}
continue;
}
case CON_SETACTOR:
{
intptr_t * const ins = &g_scriptPtr[-1];
@ -3708,50 +3605,207 @@ setvarvar:
case CON_SHIFTVARR:
case CON_SUBVAR:
case CON_XORVAR:
setvar:
{
auto ins = &g_scriptPtr[-1];
C_GetNextVarType(GAMEVAR_READONLY);
C_GetNextValue(LABEL_DEFINE);
#if 0
if (tw == CON_DIVVAR || tw == CON_MULVAR)
{
intptr_t *inst = &g_scriptPtr[-1];
char *tptr = textptr;
// syntax: [rand|add|set]var <var1> <const1>
// sets var1 to const1
// adds const1 to var1 (const1 can be negative...)
//printf("Found [add|set]var at line= %d\n",g_lineNumber);
int32_t const i = ins[2];
C_GetNextVarType(GAMEVAR_READONLY);
C_GetNextValue(LABEL_DEFINE); // the number to check against...
if (tw == CON_DIVVAR || tw == CON_MULVAR)
if (i == -1)
{
int32_t i = g_scriptPtr[-1];
j = klabs(i);
int constexpr const opcode = CON_INV;
if (i == -1)
// if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1)
{
*inst = CON_INV | LINE_NUMBER;
g_scriptPtr--;
continue;
initprintf("%s:%d: %s -> %s\n", g_scriptFileName, g_lineNumber,
VM_GetKeywordForID(tw), VM_GetKeywordForID(opcode));
}
if (C_IntPow2(j))
scriptWriteAtOffset(opcode | LINE_NUMBER, ins);
g_scriptPtr--;
continue;
}
else if (C_IntPow2((j = klabs(i))))
{
int const opcode = (tw == CON_DIVVAR) ? CON_SHIFTVARR : CON_SHIFTVARL;
// if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1)
{
*inst = ((tw == CON_DIVVAR) ? CON_SHIFTVARR : CON_SHIFTVARL) | LINE_NUMBER;
g_scriptPtr[-1] = C_Pow2IntLogBase2(j);
// initprintf("%s:%d: replacing multiply/divide with shift\n",g_szScriptFileName,g_lineNumber);
initprintf("%s:%d: %s -> %s\n", g_scriptFileName, g_lineNumber,
VM_GetKeywordForID(tw), VM_GetKeywordForID(opcode));
}
if (i == j)
continue;
scriptWriteAtOffset(opcode | LINE_NUMBER, ins);
scriptWriteAtOffset(C_Pow2IntLogBase2(j), &ins[2]);
if (i != j)
{
scriptWriteValue(CON_INV | LINE_NUMBER);
textptr = tptr;
C_GetNextVarType(GAMEVAR_READONLY);
C_GetNextValue(LABEL_DEFINE);
g_scriptPtr--;
// initprintf("%s:%d: adding inversion\n",g_szScriptFileName,g_lineNumber);
scriptWriteValue(ins[1]);
initprintf("%s:%d: +++ CON_INV\n", g_scriptFileName, g_lineNumber);
}
}
}
#endif
// replace instructions with special versions that operate only on globals
if ((aGameVars[ins[1]].flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) == 0)
{
int const opcode = inthash_find(&h_globalvar, *ins & VM_INSTMASK);
if (opcode != -1)
{
//if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1)
{
initprintf("%s:%d: %s -> %s\n", g_scriptFileName, g_lineNumber,
VM_GetKeywordForID(*ins & VM_INSTMASK), VM_GetKeywordForID(opcode));
}
tw = opcode;
scriptWriteAtOffset(opcode | LINE_NUMBER, ins);
}
}
continue;
}
case CON_ADDVARVAR:
case CON_ANDVARVAR:
case CON_DISPLAYRANDVARVAR:
case CON_DIVVARVAR:
case CON_MODVARVAR:
case CON_MULVARVAR:
case CON_ORVARVAR:
case CON_RANDVARVAR:
case CON_SETVARVAR:
case CON_SHIFTVARVARL:
case CON_SHIFTVARVARR:
case CON_SUBVARVAR:
case CON_XORVARVAR:
{
setvarvar:
auto ins = &g_scriptPtr[-1];
auto tptr = textptr;
C_GetNextVarType(GAMEVAR_READONLY);
C_GetNextVar();
int const opcode = inthash_find(&h_varvar, *ins & VM_INSTMASK);
if (ins[2] == GV_FLAG_CONSTANT && opcode != -1)
{
if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1)
{
initprintf("%s:%d: %s -> %s\n", g_scriptFileName, g_lineNumber,
VM_GetKeywordForID(*ins & VM_INSTMASK), VM_GetKeywordForID(opcode));
}
tw = opcode;
scriptWriteAtOffset(opcode | LINE_NUMBER, ins);
g_scriptPtr = &ins[1];
textptr = tptr;
goto setvar;
}
continue;
}
case CON_GETACTORVAR:
case CON_GETPLAYERVAR:
case CON_SETACTORVAR:
case CON_SETPLAYERVAR:
{
// syntax [gs]etactorvar[<var>].<varx> <VAR>
// gets the value of the per-actor variable varx into VAR
if (C_GetStructureIndexes(1, NULL) == -1)
continue;
if (g_scriptPtr[-1] == g_thisActorVarID) // convert to "setvarvar"
{
g_scriptPtr--;
g_scriptPtr[-1]=CON_SETVARVAR;
if (tw == CON_SETACTORVAR || tw == CON_SETPLAYERVAR)
{
tw = inthash_find(&h_varvar, tw);
goto setvarvar;
}
else
{
g_scriptPtr++;
C_GetNextVar();
g_scriptPtr-=2;
C_GetNextVarType(GAMEVAR_READONLY);
g_scriptPtr++;
}
continue;
}
/// now pointing at 'xxx'
C_GetNextLabelName();
if (EDUKE32_PREDICT_FALSE(hash_find(&h_keywords,LAST_LABEL)>=0))
{
g_errorCnt++;
C_ReportError(ERROR_ISAKEYWORD);
continue;
}
i=GetDefID(LAST_LABEL);
if (EDUKE32_PREDICT_FALSE(i<0))
{
g_errorCnt++;
C_ReportError(ERROR_NOTAGAMEVAR);
continue;
}
if (EDUKE32_PREDICT_FALSE(aGameVars[i].flags & GAMEVAR_READONLY))
{
g_errorCnt++;
C_ReportError(ERROR_VARREADONLY);
continue;
}
switch (tw)
{
case CON_SETACTORVAR:
if (EDUKE32_PREDICT_FALSE(!(aGameVars[i].flags & GAMEVAR_PERACTOR)))
{
g_errorCnt++;
C_ReportError(-1);
initprintf("%s:%d: error: variable `%s' is not per-actor.\n",g_scriptFileName,g_lineNumber,LAST_LABEL);
continue;
}
break;
case CON_SETPLAYERVAR:
if (EDUKE32_PREDICT_FALSE(!(aGameVars[i].flags & GAMEVAR_PERPLAYER)))
{
g_errorCnt++;
C_ReportError(-1);
initprintf("%s:%d: error: variable `%s' is not per-player.\n",g_scriptFileName,g_lineNumber,LAST_LABEL);
continue;
}
break;
}
scriptWriteValue(i); // the ID of the DEF (offset into array...)
switch (tw)
{
case CON_GETACTORVAR:
case CON_GETPLAYERVAR:
C_GetNextVarType(GAMEVAR_READONLY);
break;
default:
C_GetNextVar();
break;
}
continue;
}
case CON_WRITEARRAYTOFILE:
case CON_READARRAYFROMFILE:
@ -4223,6 +4277,7 @@ setvarvar:
case CON_WHILEVARN:
{
singlevar:
auto const ins = &g_scriptPtr[-1];
auto const lastScriptPtr = &g_scriptPtr[-1] - apScript;
g_skipBranch = false;
@ -4233,6 +4288,23 @@ singlevar:
if (C_CheckMalformedBranch(lastScriptPtr))
continue;
if (aGameVars[ins[1]].flags == 0)
{
int const opcode = inthash_find(&h_globalvar, *ins & VM_INSTMASK);
if (opcode != -1)
{
if (!(g_errorCnt || g_warningCnt) && g_scriptDebug > 1)
{
initprintf("%s:%d: %s -> %s\n", g_scriptFileName, g_lineNumber,
VM_GetKeywordForID(*ins & VM_INSTMASK), VM_GetKeywordForID(opcode));
}
tw = opcode;
scriptWriteAtOffset(opcode | LINE_NUMBER, ins);
}
}
auto const offset = g_scriptPtr - apScript;
g_scriptPtr++; //Leave a spot for the fail location
@ -5954,12 +6026,14 @@ void C_PrintStats(void)
initprintf("\n");
}
// TODO: add some kind of mapping between the table and the struct holding the tokens
void scriptInitTables()
{
for (auto table : tables)
hash_init(table);
inthash_init(&h_varvar);
for (auto table : inttables)
inthash_init(table);
for (auto &keyword : vm_keywords)
hash_add(&h_keywords, keyword.token, keyword.val, 0);
@ -5969,6 +6043,9 @@ void scriptInitTables()
for (auto &varvar : varvartable)
inthash_add(&h_varvar, varvar.x, varvar.y, 0);
for (auto &globalvar : globalvartable)
inthash_add(&h_globalvar, globalvar.x, globalvar.y, 0);
}
void C_Compile(const char *fileName)
@ -6102,6 +6179,7 @@ void C_Compile(const char *fileName)
hash_free(i);
inthash_free(&h_varvar);
inthash_free(&h_globalvar);
freehashnames();
freesoundhashnames();

View File

@ -834,6 +834,7 @@ enum IterationTypes_t
ITER_END
};
// most keywords have opcodes but some opcodes don't have keywords
enum ScriptKeywords_t
{
CON_ACTION,
@ -842,6 +843,7 @@ enum ScriptKeywords_t
CON_ACTIVATECHEAT,
CON_ACTORSOUND,
CON_ADDAMMO,
CON_ADDGLOBALVAR,
CON_ADDINVENTORY,
CON_ADDKILLS,
CON_ADDLOGVAR,
@ -851,6 +853,7 @@ enum ScriptKeywords_t
CON_ADDVARVAR,
CON_ADDWEAPON,
CON_AI,
CON_ANDGLOBALVAR,
CON_ANDVAR,
CON_ANDVARVAR,
CON_ANGOFF,
@ -883,6 +886,7 @@ enum ScriptKeywords_t
CON_DISPLAYRANDVAR,
CON_DISPLAYRANDVARVAR,
CON_DIST,
CON_DIVGLOBALVAR,
CON_DIVR,
CON_DIVRU,
CON_DIVSCALE,
@ -905,11 +909,11 @@ enum ScriptKeywords_t
CON_EVENTLOADACTOR,
CON_EZSHOOT,
CON_FALL,
CON_FINDNEARACTOR3D,
CON_FINDNEARACTOR,
CON_FINDNEARACTOR3D,
CON_FINDNEARACTORZ,
CON_FINDNEARSPRITE3D,
CON_FINDNEARSPRITE,
CON_FINDNEARSPRITE3D,
CON_FINDNEARSPRITEZ,
CON_FINDOTHERPLAYER,
CON_FINDPLAYER,
@ -1051,12 +1055,14 @@ enum ScriptKeywords_t
CON_MAIL,
CON_MIKESND,
CON_MINITEXT,
CON_MODGLOBALVAR,
CON_MODVAR,
CON_MODVARVAR,
CON_MONEY,
CON_MOVE,
CON_MOVESECTOR,
CON_MOVESPRITE,
CON_MULGLOBALVAR,
CON_MULSCALE,
CON_MULVAR,
CON_MULVARVAR,
@ -1075,6 +1081,7 @@ enum ScriptKeywords_t
CON_OPERATEMASTERSWITCHES,
CON_OPERATERESPAWNS,
CON_OPERATESECTORS,
CON_ORGLOBALVAR,
CON_ORVAR,
CON_ORVARVAR,
CON_PALFROM,
@ -1097,6 +1104,7 @@ enum ScriptKeywords_t
CON_QSUBSTR,
CON_QUAKE,
CON_QUOTE,
CON_RANDGLOBALVAR,
CON_RANDVAR,
CON_RANDVARVAR,
CON_RAYINTERSECT,
@ -1136,6 +1144,7 @@ enum ScriptKeywords_t
CON_SETARRAY,
CON_SETASPECT,
CON_SETGAMEPALETTE,
CON_SETGLOBALVAR,
CON_SETINPUT,
CON_SETMUSICPOSITION,
CON_SETPLAYER,
@ -1154,6 +1163,8 @@ enum ScriptKeywords_t
CON_SETVARVAR,
CON_SETWALL,
CON_SHADETO,
CON_SHIFTGLOBALVARL,
CON_SHIFTGLOBALVARR,
CON_SHIFTVARL,
CON_SHIFTVARR,
CON_SHIFTVARVARL,
@ -1168,8 +1179,8 @@ enum ScriptKeywords_t
CON_SIZETO,
CON_SLEEPTIME,
CON_SMAXAMMO,
CON_SOUNDONCE,
CON_SOUND,
CON_SOUNDONCE,
CON_SPAWN,
CON_SPAWNCEILINGGLASS,
CON_SPAWNWALLGLASS,
@ -1183,14 +1194,15 @@ enum ScriptKeywords_t
CON_STARTCUTSCENE,
CON_STARTLEVEL,
CON_STARTSCREEN,
CON_STARTTRACKSLOT,
CON_STARTTRACK,
CON_STARTTRACKSLOT,
CON_STATE,
CON_STOPACTORSOUND,
CON_STOPALLMUSIC,
CON_STOPALLSOUNDS,
CON_STOPSOUND,
CON_STRENGTH,
CON_SUBGLOBALVAR,
CON_SUBVAR,
CON_SUBVARVAR,
CON_SWAPARRAYS,
@ -1203,18 +1215,21 @@ enum ScriptKeywords_t
CON_UPDATESECTORZ,
CON_USERQUOTE,
CON_WACKPLAYER,
CON_WHILEGLOBALVARL,
CON_WHILEGLOBALVARN,
CON_WHILEVARL,
CON_WHILEVARN,
CON_WHILEVARVARL,
CON_WHILEVARVARN,
CON_WRITEARRAYTOFILE,
CON_XORGLOBALVAR,
CON_XORVAR,
CON_XORVARVAR,
CON_ZSHOOT,
CON_OPCODE_END,
// these are the keywords that don't get written into the bytecode
// these are the keywords that don't have instructions written into the bytecode
CON_ACTOR,
CON_APPENDEVENT,
CON_BETANAME,

View File

@ -1304,10 +1304,13 @@ next_instruction:
case CON_SETVAR:
insptr++;
if ((aGameVars[*insptr].flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) == 0)
aGameVars[*insptr].global = insptr[1];
else
Gv_SetVarX(*insptr, insptr[1]);
Gv_SetVarX(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_SETGLOBALVAR:
insptr++;
aGameVars[*insptr].global = insptr[1];
insptr += 2;
continue;
@ -1324,12 +1327,36 @@ next_instruction:
}
continue;
case CON_ADDVAR:
insptr++;
Gv_AddVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_ADDGLOBALVAR:
insptr++;
aGameVars[*insptr].global += insptr[1];
insptr += 2;
continue;
case CON_ADDVARVAR:
insptr++;
tw = *insptr++;
Gv_AddVar(tw, Gv_GetVarX(*insptr++));
continue;
case CON_SUBVAR:
insptr++;
Gv_SubVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_SUBGLOBALVAR:
insptr++;
aGameVars[*insptr].global -= insptr[1];
insptr += 2;
continue;
case CON_SUBVARVAR:
insptr++;
tw = *insptr++;
@ -1352,12 +1379,46 @@ next_instruction:
VM_CONDITIONAL(tw);
continue;
case CON_MULVAR:
insptr++;
Gv_MulVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_MULGLOBALVAR:
insptr++;
aGameVars[*insptr].global *= insptr[1];
insptr += 2;
continue;
case CON_MULVARVAR:
insptr++;
tw = *insptr++;
Gv_MulVar(tw, Gv_GetVarX(*insptr++));
continue;
case CON_DIVVAR:
insptr++;
if (EDUKE32_PREDICT_FALSE(insptr[1] == 0))
{
CON_CRITICALERRPRINTF("divide by zero!\n");
continue;
}
Gv_DivVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_DIVGLOBALVAR:
insptr++;
if (EDUKE32_PREDICT_FALSE(insptr[1] == 0))
{
CON_CRITICALERRPRINTF("divide by zero!\n");
continue;
}
aGameVars[*insptr].global = tabledivide32(aGameVars[*insptr].global, insptr[1]);
insptr += 2;
continue;
case CON_DIVVARVAR:
insptr++;
{
@ -1387,35 +1448,6 @@ next_instruction:
VM_CONDITIONAL(tw != *insptr);
continue;
case CON_ADDVAR:
insptr++;
Gv_AddVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_SUBVAR:
insptr++;
Gv_SubVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_MULVAR:
insptr++;
Gv_MulVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_DIVVAR:
insptr++;
if (EDUKE32_PREDICT_FALSE(insptr[1] == 0))
{
CON_CRITICALERRPRINTF("divide by zero!\n");
continue;
}
Gv_DivVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_IFVARVARG:
insptr++;
tw = Gv_GetVarX(*insptr++);
@ -1614,13 +1646,13 @@ next_instruction:
continue;
}
case CON_WHILEVARL:
case CON_WHILEGLOBALVARN:
{
auto const savedinsptr = &insptr[2];
do
{
insptr = savedinsptr;
tw = (Gv_GetVarX(insptr[-1]) < *insptr);
tw = (aGameVars[insptr[-1]].global != *insptr);
VM_CONDITIONAL(tw);
} while (tw);
continue;
@ -1640,6 +1672,30 @@ next_instruction:
continue;
}
case CON_WHILEVARL:
{
auto const savedinsptr = &insptr[2];
do
{
insptr = savedinsptr;
tw = (Gv_GetVarX(insptr[-1]) < *insptr);
VM_CONDITIONAL(tw);
} while (tw);
continue;
}
case CON_WHILEGLOBALVARL:
{
auto const savedinsptr = &insptr[2];
do
{
insptr = savedinsptr;
tw = (aGameVars[insptr[-1]].global < *insptr);
VM_CONDITIONAL(tw);
} while (tw);
continue;
}
case CON_WHILEVARVARL:
{
auto const savedinsptr = &insptr[2];
@ -1654,33 +1710,15 @@ next_instruction:
continue;
}
case CON_MODVAR:
insptr++;
if (EDUKE32_PREDICT_FALSE(insptr[1] == 0))
{
CON_CRITICALERRPRINTF("mod by zero!\n");
continue;
}
Gv_ModVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_ANDVAR:
insptr++;
Gv_AndVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_ORVAR:
case CON_ANDGLOBALVAR:
insptr++;
Gv_OrVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_XORVAR:
insptr++;
Gv_XorVar(*insptr, insptr[1]);
aGameVars[*insptr].global &= insptr[1];
insptr += 2;
continue;
@ -1690,12 +1728,36 @@ next_instruction:
Gv_AndVar(tw, Gv_GetVarX(*insptr++));
continue;
case CON_XORVAR:
insptr++;
Gv_XorVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_XORGLOBALVAR:
insptr++;
aGameVars[*insptr].global ^= insptr[1];
insptr += 2;
continue;
case CON_XORVARVAR:
insptr++;
tw = *insptr++;
Gv_XorVar(tw, Gv_GetVarX(*insptr++));
continue;
case CON_ORVAR:
insptr++;
Gv_OrVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_ORGLOBALVAR:
insptr++;
aGameVars[*insptr].global |= insptr[1];
insptr += 2;
continue;
case CON_ORVARVAR:
insptr++;
tw = *insptr++;
@ -1708,9 +1770,9 @@ next_instruction:
insptr += 2;
continue;
case CON_SHIFTVARR:
case CON_SHIFTGLOBALVARL:
insptr++;
Gv_ShiftVarR(*insptr, insptr[1]);
aGameVars[*insptr].global <<= insptr[1];
insptr += 2;
continue;
@ -1720,12 +1782,48 @@ next_instruction:
Gv_ShiftVarL(tw, Gv_GetVarX(*insptr++));
continue;
case CON_SHIFTVARR:
insptr++;
Gv_ShiftVarR(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_SHIFTGLOBALVARR:
insptr++;
aGameVars[*insptr].global >>= insptr[1];
insptr += 2;
continue;
case CON_SHIFTVARVARR:
insptr++;
tw = *insptr++;
Gv_ShiftVarR(tw, Gv_GetVarX(*insptr++));
continue;
case CON_MODVAR:
insptr++;
if (EDUKE32_PREDICT_FALSE(insptr[1] == 0))
{
CON_CRITICALERRPRINTF("mod by zero!\n");
continue;
}
Gv_ModVar(*insptr, insptr[1]);
insptr += 2;
continue;
case CON_MODGLOBALVAR:
insptr++;
if (EDUKE32_PREDICT_FALSE(insptr[1] == 0))
{
CON_CRITICALERRPRINTF("mod by zero!\n");
continue;
}
aGameVars[*insptr].global %= insptr[1];
insptr += 2;
continue;
case CON_MODVARVAR:
insptr++;
{
@ -1743,6 +1841,24 @@ next_instruction:
continue;
}
case CON_RANDVAR:
insptr++;
Gv_SetVarX(*insptr, mulscale16(krand(), insptr[1] + 1));
insptr += 2;
continue;
case CON_RANDGLOBALVAR:
insptr++;
aGameVars[*insptr].global = mulscale16(krand(), insptr[1] + 1);
insptr += 2;
continue;
case CON_RANDVARVAR:
insptr++;
tw = *insptr++;
Gv_SetVarX(tw, mulscale16(krand(), Gv_GetVarX(*insptr++) + 1));
continue;
case CON_SETPLAYER:
insptr++;
{
@ -5461,12 +5577,6 @@ badindex:
continue;
}
case CON_RANDVAR:
insptr++;
Gv_SetVarX(*insptr, mulscale16(krand(), insptr[1] + 1));
insptr += 2;
continue;
case CON_DISPLAYRANDVAR:
insptr++;
Gv_SetVarX(*insptr, mulscale15(system_15bit_rand(), insptr[1] + 1));
@ -5532,13 +5642,6 @@ badindex:
insptr += 2;
continue;
case CON_RANDVARVAR:
insptr++;
tw = *insptr++;
Gv_SetVarX(tw, mulscale16(krand(), Gv_GetVarX(*insptr++) + 1));
continue;
case CON_DISPLAYRANDVARVAR:
insptr++;
tw = *insptr++;