- extended the register limit for 'param'.

The instruction one free instruction byte so it's now using that to extend its argument's register range to 65535.
For param this is needed because it passes strings by reference and creating an implicit temporary copy for string constants does not work here.
This commit is contained in:
Christoph Oelckers 2018-10-14 09:13:26 +02:00
parent eee0946bc5
commit dd719f0f14
6 changed files with 134 additions and 113 deletions

View file

@ -632,26 +632,26 @@ static int GetLine (void)
// misc1 = vrange (arg +3), misc2 = hrange (arg+4) // misc1 = vrange (arg +3), misc2 = hrange (arg+4)
static int CreateMushroomFunc(VMFunctionBuilder &buildit, int value1, int value2) static int CreateMushroomFunc(VMFunctionBuilder &buildit, int value1, int value2)
{ // A_Mushroom { // A_Mushroom
buildit.Emit(OP_PARAM, 0, REGT_NIL, 0); // spawntype buildit.Emit(OP_PARAM, REGT_NIL, 0); // spawntype
buildit.Emit(OP_PARAM, 0, REGT_NIL, 0); // numspawns buildit.Emit(OP_PARAM, REGT_NIL, 0); // numspawns
buildit.Emit(OP_PARAMI, 1); // flag buildit.Emit(OP_PARAMI, 1); // flag
// vrange // vrange
if (value1 == 0) if (value1 == 0)
{ {
buildit.Emit(OP_PARAM, 0, REGT_NIL, 0); buildit.Emit(OP_PARAM, REGT_NIL, 0);
} }
else else
{ {
buildit.Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(DEHToDouble(value1))); buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(DEHToDouble(value1)));
} }
// hrange // hrange
if (value2 == 0) if (value2 == 0)
{ {
buildit.Emit(OP_PARAM, 0, REGT_NIL, 0); buildit.Emit(OP_PARAM, REGT_NIL, 0);
} }
else else
{ {
buildit.Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(DEHToDouble(value2))); buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(DEHToDouble(value2)));
} }
return 5; return 5;
} }
@ -667,9 +667,9 @@ static int CreateSpawnFunc(VMFunctionBuilder &buildit, int value1, int value2)
int typereg = buildit.GetConstantAddress(InfoNames[value1-1]); int typereg = buildit.GetConstantAddress(InfoNames[value1-1]);
int heightreg = buildit.GetConstantFloat(value2); int heightreg = buildit.GetConstantFloat(value2);
buildit.Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, typereg); // itemtype buildit.Emit(OP_PARAM, REGT_POINTER | REGT_KONST, typereg); // itemtype
buildit.Emit(OP_PARAM, 0, REGT_NIL, 0); // distance buildit.Emit(OP_PARAM, REGT_NIL, 0); // distance
buildit.Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, heightreg); // height buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, heightreg); // height
// The rest of the parameters to A_SpawnItem can just keep their defaults // The rest of the parameters to A_SpawnItem can just keep their defaults
return 3; return 3;
} }
@ -677,14 +677,14 @@ static int CreateSpawnFunc(VMFunctionBuilder &buildit, int value1, int value2)
// misc1 = angle (in degrees) (arg +0 but factor in current actor angle too) // misc1 = angle (in degrees) (arg +0 but factor in current actor angle too)
static int CreateTurnFunc(VMFunctionBuilder &buildit, int value1, int value2) static int CreateTurnFunc(VMFunctionBuilder &buildit, int value1, int value2)
{ // A_Turn { // A_Turn
buildit.Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(value1)); // angle buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(value1)); // angle
return 1; return 1;
} }
// misc1 = angle (in degrees) (arg +0) // misc1 = angle (in degrees) (arg +0)
static int CreateFaceFunc(VMFunctionBuilder &buildit, int value1, int value2) static int CreateFaceFunc(VMFunctionBuilder &buildit, int value1, int value2)
{ // A_FaceTarget { // A_FaceTarget
buildit.Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(value1)); // angle buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, buildit.GetConstantFloat(value1)); // angle
return 1; return 1;
} }
@ -708,9 +708,9 @@ static int CreatePlaySoundFunc(VMFunctionBuilder &buildit, int value1, int value
buildit.EmitParamInt(SoundMap[value1-1]); // soundid buildit.EmitParamInt(SoundMap[value1-1]); // soundid
buildit.Emit(OP_PARAMI, CHAN_BODY); // channel buildit.Emit(OP_PARAMI, CHAN_BODY); // channel
buildit.Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, float1); // volume buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, float1); // volume
buildit.Emit(OP_PARAMI, false); // looping buildit.Emit(OP_PARAMI, false); // looping
buildit.Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, attenreg); // attenuation buildit.Emit(OP_PARAM, REGT_FLOAT | REGT_KONST, attenreg); // attenuation
return 5; return 5;
} }
@ -720,7 +720,7 @@ static int CreateRandomJumpFunc(VMFunctionBuilder &buildit, int value1, int valu
int statereg = buildit.GetConstantAddress(FindState(value1)); int statereg = buildit.GetConstantAddress(FindState(value1));
buildit.EmitParamInt(value2); // maxchance buildit.EmitParamInt(value2); // maxchance
buildit.Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, statereg); // jumpto buildit.Emit(OP_PARAM, REGT_POINTER | REGT_KONST, statereg); // jumpto
return 2; return 2;
} }
@ -742,11 +742,11 @@ static int CreateNailBombFunc(VMFunctionBuilder &buildit, int value1, int value2
{ // A_Explode { // A_Explode
// This one does not actually have MBF-style parameters. But since // This one does not actually have MBF-style parameters. But since
// we're aliasing it to an extension of A_Explode... // we're aliasing it to an extension of A_Explode...
buildit.Emit(OP_PARAM, 0, REGT_NIL, 0); // damage buildit.Emit(OP_PARAM, REGT_NIL, 0); // damage
buildit.Emit(OP_PARAM, 0, REGT_NIL, 0); // distance buildit.Emit(OP_PARAM, REGT_NIL, 0); // distance
buildit.Emit(OP_PARAM, 0, REGT_NIL, 0); // flags buildit.Emit(OP_PARAM, REGT_NIL, 0); // flags
buildit.Emit(OP_PARAM, 0, REGT_NIL, 0); // alert buildit.Emit(OP_PARAM, REGT_NIL, 0); // alert
buildit.Emit(OP_PARAM, 0, REGT_NIL, 0); // fulldamagedistance buildit.Emit(OP_PARAM, REGT_NIL, 0); // fulldamagedistance
buildit.Emit(OP_PARAMI, 30); // nails buildit.Emit(OP_PARAMI, 30); // nails
buildit.Emit(OP_PARAMI, 10); // naildamage buildit.Emit(OP_PARAMI, 10); // naildamage
return 7; return 7;
@ -802,7 +802,7 @@ void SetDehParams(FState *state, int codepointer)
// Emit code to pass the standard action function parameters. // Emit code to pass the standard action function parameters.
for (int i = 0; i < numargs; i++) for (int i = 0; i < numargs; i++)
{ {
buildit.Emit(OP_PARAM, 0, REGT_POINTER, i); buildit.Emit(OP_PARAM, REGT_POINTER, i);
} }
// Emit code for action parameters. // Emit code for action parameters.
int argcount = MBFCodePointerFactories[codepointer](buildit, value1, value2); int argcount = MBFCodePointerFactories[codepointer](buildit, value1, value2);

View file

@ -519,12 +519,12 @@ static int EmitParameter(VMFunctionBuilder *build, FxExpression *operand, const
if (where.RegType == REGT_NIL) if (where.RegType == REGT_NIL)
{ {
pos.Message(MSG_ERROR, "Attempted to pass a non-value"); pos.Message(MSG_ERROR, "Attempted to pass a non-value");
build->Emit(OP_PARAM, 0, where.RegType, where.RegNum); build->Emit(OP_PARAM, where.RegType, where.RegNum);
return 1; return 1;
} }
else else
{ {
build->Emit(OP_PARAM, 0, EncodeRegType(where), where.RegNum); build->Emit(OP_PARAM, EncodeRegType(where), where.RegNum);
if (tempstrings != nullptr && where.RegType == REGT_STRING && !where.Fixed && !where.Konst) if (tempstrings != nullptr && where.RegType == REGT_STRING && !where.Fixed && !where.Konst)
{ {
tempstrings->Push(where); // keep temp strings until after the function call. tempstrings->Push(where); // keep temp strings until after the function call.
@ -5549,7 +5549,7 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build)
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng)); build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
if (min != nullptr && max != nullptr) if (min != nullptr && max != nullptr)
{ {
EmitParameter(build, min, ScriptPosition); EmitParameter(build, min, ScriptPosition);
@ -5670,7 +5670,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
assert(((PSymbolVMFunction *)sym)->Function != nullptr); assert(((PSymbolVMFunction *)sym)->Function != nullptr);
callfunc = ((PSymbolVMFunction *)sym)->Function; callfunc = ((PSymbolVMFunction *)sym)->Function;
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng)); build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
build->EmitParamInt(0); build->EmitParamInt(0);
build->EmitParamInt(choices.Size() - 1); build->EmitParamInt(choices.Size() - 1);
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 3, 1); build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc), 3, 1);
@ -5800,7 +5800,7 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build)
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng)); build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
if (min != nullptr && max != nullptr) if (min != nullptr && max != nullptr)
{ {
EmitParameter(build, min, ScriptPosition); EmitParameter(build, min, ScriptPosition);
@ -5895,7 +5895,7 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build)
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng)); build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
EmitParameter(build, mask, ScriptPosition); EmitParameter(build, mask, ScriptPosition);
build->Emit(opcode, build->GetConstantAddress(callfunc), 2, 1); build->Emit(opcode, build->GetConstantAddress(callfunc), 2, 1);
@ -5978,7 +5978,7 @@ ExpEmit FxRandomSeed::Emit(VMFunctionBuilder *build)
if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use if (build->FramePointer.Fixed) EmitTail = false; // do not tail call if the stack is in use
int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K); int opcode = (EmitTail ? OP_TAIL_K : OP_CALL_K);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng)); build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng));
EmitParameter(build, seed, ScriptPosition); EmitParameter(build, seed, ScriptPosition);
build->Emit(opcode, build->GetConstantAddress(callfunc), 2, 0); build->Emit(opcode, build->GetConstantAddress(callfunc), 2, 0);
@ -8644,7 +8644,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
build->Emit(OP_PARAMI, abs(Special)); // pass special number build->Emit(OP_PARAMI, abs(Special)); // pass special number
ExpEmit selfemit(Self->Emit(build)); ExpEmit selfemit(Self->Emit(build));
build->Emit(OP_PARAM, 0, selfemit.Konst ? REGT_POINTER | REGT_KONST : REGT_POINTER, selfemit.RegNum); // pass special number build->Emit(OP_PARAM, selfemit.Konst ? REGT_POINTER | REGT_KONST : REGT_POINTER, selfemit.RegNum); // pass special number
for (; i < ArgList.Size(); ++i) for (; i < ArgList.Size(); ++i)
{ {
FxExpression *argex = ArgList[i]; FxExpression *argex = ArgList[i];
@ -8664,7 +8664,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
else else
{ {
ExpEmit arg(argex->Emit(build)); ExpEmit arg(argex->Emit(build));
build->Emit(OP_PARAM, 0, arg.RegType, arg.RegNum); build->Emit(OP_PARAM, arg.RegType, arg.RegNum);
arg.Free(build); arg.Free(build);
} }
} }
@ -9086,11 +9086,11 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
if ((selfemit.Fixed && selfemit.Target) || selfemit.RegType == REGT_STRING) if ((selfemit.Fixed && selfemit.Target) || selfemit.RegType == REGT_STRING)
{ {
// Address of a local variable. // Address of a local variable.
build->Emit(OP_PARAM, 0, selfemit.RegType | REGT_ADDROF, selfemit.RegNum); build->Emit(OP_PARAM, selfemit.RegType | REGT_ADDROF, selfemit.RegNum);
} }
else else
{ {
build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum); build->Emit(OP_PARAM, selfemit.RegType, selfemit.RegNum);
} }
count += 1; count += 1;
if (Function->Variants[0].Flags & VARF_Action) if (Function->Variants[0].Flags & VARF_Action)
@ -9098,14 +9098,14 @@ ExpEmit FxVMFunctionCall::Emit(VMFunctionBuilder *build)
static_assert(NAP == 3, "This code needs to be updated if NAP changes"); static_assert(NAP == 3, "This code needs to be updated if NAP changes");
if (build->NumImplicits == NAP && selfemit.RegNum == 0) // only pass this function's stateowner and stateinfo if the subfunction is run in self's context. if (build->NumImplicits == NAP && selfemit.RegNum == 0) // only pass this function's stateowner and stateinfo if the subfunction is run in self's context.
{ {
build->Emit(OP_PARAM, 0, REGT_POINTER, 1); build->Emit(OP_PARAM, REGT_POINTER, 1);
build->Emit(OP_PARAM, 0, REGT_POINTER, 2); build->Emit(OP_PARAM, REGT_POINTER, 2);
} }
else else
{ {
// pass self as stateowner, otherwise all attempts of the subfunction to retrieve a state from a name would fail. // pass self as stateowner, otherwise all attempts of the subfunction to retrieve a state from a name would fail.
build->Emit(OP_PARAM, 0, selfemit.RegType, selfemit.RegNum); build->Emit(OP_PARAM, selfemit.RegType, selfemit.RegNum);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(nullptr)); build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(nullptr));
} }
count += 2; count += 2;
} }
@ -10696,7 +10696,7 @@ ExpEmit FxReturnStatement::Emit(VMFunctionBuilder *build)
assert(pstr->mDestructor != nullptr); assert(pstr->mDestructor != nullptr);
ExpEmit reg(build, REGT_POINTER); ExpEmit reg(build, REGT_POINTER);
build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(build->ConstructedStructs[i]->StackOffset)); build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(build->ConstructedStructs[i]->StackOffset));
build->Emit(OP_PARAM, 0, reg.RegType, reg.RegNum); build->Emit(OP_PARAM, reg.RegType, reg.RegNum);
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), 1, 0); build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), 1, 0);
reg.Free(build); reg.Free(build);
} }
@ -10893,8 +10893,8 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
ExpEmit clsname = basex->Emit(build); ExpEmit clsname = basex->Emit(build);
assert(!clsname.Konst); assert(!clsname.Konst);
ExpEmit dest(build, REGT_POINTER); ExpEmit dest(build, REGT_POINTER);
build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum); build->Emit(OP_PARAM, clsname.RegType, clsname.RegNum);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast<PClass *>(desttype))); build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(const_cast<PClass *>(desttype)));
// Call the BuiltinNameToClass function to convert from 'name' to class. // Call the BuiltinNameToClass function to convert from 'name' to class.
VMFunction *callfunc; VMFunction *callfunc;
@ -11002,8 +11002,8 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
{ {
ExpEmit clsname = basex->Emit(build); ExpEmit clsname = basex->Emit(build);
build->Emit(OP_PARAM, 0, clsname.RegType, clsname.RegNum); build->Emit(OP_PARAM, clsname.RegType, clsname.RegNum);
build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(desttype)); build->Emit(OP_PARAM, REGT_POINTER | REGT_KONST, build->GetConstantAddress(desttype));
VMFunction *callfunc; VMFunction *callfunc;
PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast); PSymbol *sym = FindBuiltinFunction(NAME_BuiltinClassCast, BuiltinClassCast);
@ -11388,7 +11388,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build)
{ {
ExpEmit reg(build, REGT_POINTER); ExpEmit reg(build, REGT_POINTER);
build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset)); build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset));
build->Emit(OP_PARAM, 0, reg.RegType, reg.RegNum); build->Emit(OP_PARAM, reg.RegType, reg.RegNum);
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mConstructor), 1, 0); build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mConstructor), 1, 0);
reg.Free(build); reg.Free(build);
} }
@ -11414,7 +11414,7 @@ void FxLocalVariableDeclaration::Release(VMFunctionBuilder *build)
{ {
ExpEmit reg(build, REGT_POINTER); ExpEmit reg(build, REGT_POINTER);
build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset)); build->Emit(OP_ADDA_RK, reg.RegNum, build->FramePointer.RegNum, build->GetConstantInt(StackOffset));
build->Emit(OP_PARAM, 0, reg.RegType, reg.RegNum); build->Emit(OP_PARAM, reg.RegType, reg.RegNum);
build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), 1, 0); build->Emit(OP_CALL_K, build->GetConstantAddress(pstr->mDestructor), 1, 0);
reg.Free(build); reg.Free(build);
} }

View file

@ -593,39 +593,19 @@ size_t VMFunctionBuilder::Emit(int opcode, int opa, int opb, int opc)
} }
if (opc > 255) if (opc > 255)
{ {
if (opcode == OP_PARAM && (opb & REGT_KONST) && opc <= 32767) if (opRemap[opcode].kReg != 4 || opc > 32767)
{ {
int regtype = opb & REGT_TYPE; I_Error("Register limit exceeded");
opb = regtype;
ExpEmit emit(this, regtype);
Emit(opcodes[regtype], emit.RegNum, opc);
opc = emit.RegNum;
emit.Free(this);
}
else
{
if (opRemap[opcode].kReg != 4 || opc > 32767)
{
I_Error("Register limit exceeded");
}
int regtype = opRemap[opcode].kType;
ExpEmit emit(this, regtype);
Emit(opcodes[regtype], emit.RegNum, opc);
opcode = opRemap[opcode].altOp;
opc = emit.RegNum;
emit.Free(this);
} }
int regtype = opRemap[opcode].kType;
ExpEmit emit(this, regtype);
Emit(opcodes[regtype], emit.RegNum, opc);
opcode = opRemap[opcode].altOp;
opc = emit.RegNum;
emit.Free(this);
} }
if (opcode == OP_PARAM) if (opcode == OP_CALL || opcode == OP_CALL_K || opcode == OP_TAIL || opcode == OP_TAIL_K)
{
int chg;
if (opb & REGT_MULTIREG2) chg = 2;
else if (opb&REGT_MULTIREG3) chg = 3;
else chg = 1;
ParamChange(chg);
}
else if (opcode == OP_CALL || opcode == OP_CALL_K || opcode == OP_TAIL || opcode == OP_TAIL_K)
{ {
ParamChange(-opb); ParamChange(-opb);
} }
@ -641,6 +621,16 @@ size_t VMFunctionBuilder::Emit(int opcode, int opa, VM_SHALF opbc)
{ {
assert(opcode >= 0 && opcode < NUM_OPS); assert(opcode >= 0 && opcode < NUM_OPS);
assert(opa >= 0 && opa <= 255); assert(opa >= 0 && opa <= 255);
if (opcode == OP_PARAM)
{
int chg;
if (opa & REGT_MULTIREG2) chg = 2;
else if (opa & REGT_MULTIREG3) chg = 3;
else chg = 1;
ParamChange(chg);
}
//assert(opbc >= -32768 && opbc <= 32767); always true due to parameter's width //assert(opbc >= -32768 && opbc <= 32767); always true due to parameter's width
VMOP op; VMOP op;
op.op = opcode; op.op = opcode;
@ -681,7 +671,7 @@ size_t VMFunctionBuilder::EmitParamInt(int value)
} }
else else
{ {
return Emit(OP_PARAM, 0, REGT_INT | REGT_KONST, GetConstantInt(value)); return Emit(OP_PARAM, REGT_INT | REGT_KONST, GetConstantInt(value));
} }
} }

View file

@ -82,7 +82,7 @@
#define I24 MODE_ABCJOINT #define I24 MODE_ABCJOINT
#define I8 MODE_AIMMZ | MODE_BUNUSED | MODE_CUNUSED #define I8 MODE_AIMMZ | MODE_BUNUSED | MODE_CUNUSED
#define I8I16 MODE_AIMMZ | MODE_BCIMMZ #define I8I16 MODE_AIMMZ | MODE_BCIMMZ
#define __BCP MODE_AUNUSED | MODE_BCJOINT | MODE_BCPARAM #define __BCP MODE_PARAM24
#define RPI8 MODE_AP | MODE_BIMMZ | MODE_CUNUSED #define RPI8 MODE_AP | MODE_BIMMZ | MODE_CUNUSED
#define KPI8 MODE_AKP | MODE_BIMMZ | MODE_CUNUSED #define KPI8 MODE_AKP | MODE_BIMMZ | MODE_CUNUSED
#define RPI8I8 MODE_AP | MODE_BIMMZ | MODE_CIMMZ #define RPI8I8 MODE_AP | MODE_BIMMZ | MODE_CIMMZ
@ -292,7 +292,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
a &= CMP_CHECK | CMP_APPROX; a &= CMP_CHECK | CMP_APPROX;
cmp = true; cmp = true;
} }
if (code[i].op == OP_PARAM && code[i].b & REGT_ADDROF) if (code[i].op == OP_PARAM && code[i].a & REGT_ADDROF)
{ {
name = "parama"; name = "parama";
} }
@ -340,6 +340,20 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
} }
break; break;
} }
case OP_PARAM:
{
col = print_reg(out, col, code[i].i24 & 0xffffff, MODE_PARAM24, 16, func);
break;
}
case OP_RESULT:
{
// Default handling for this broke after changing OP_PARAM...
col = print_reg(out, col, code[i].i16u, MODE_PARAM, 16, func);
break;
}
case OP_RET: case OP_RET:
if (code[i].b != REGT_NIL) if (code[i].b != REGT_NIL)
{ {
@ -583,14 +597,31 @@ static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const
return col+printf_wrapper(out, "%d", arg); return col+printf_wrapper(out, "%d", arg);
case MODE_PARAM: case MODE_PARAM:
{ case MODE_PARAM24:
int regtype, regnum; {
int regtype, regnum;
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
if (mode == MODE_PARAM)
{
regtype = (arg >> 8) & 255; regtype = (arg >> 8) & 255;
regnum = arg & 255; regnum = arg & 255;
}
else
{
regtype = (arg >> 16) & 255;
regnum = arg & 65535;
}
#else #else
if (mode == MODE_PARAM)
{
regtype = arg & 255; regtype = arg & 255;
regnum = (arg >> 8) & 255; regnum = (arg >> 8) & 255;
}
else
{
regtype = arg & 255;
regnum = (arg >> 8) & 65535;
}
#endif #endif
switch (regtype & (REGT_TYPE | REGT_KONST | REGT_MULTIREG)) switch (regtype & (REGT_TYPE | REGT_KONST | REGT_MULTIREG))
{ {

View file

@ -582,77 +582,77 @@ static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret)
assert(f->NumParam < sfunc->MaxParam); assert(f->NumParam < sfunc->MaxParam);
{ {
VMValue *param = &reg.param[f->NumParam++]; VMValue *param = &reg.param[f->NumParam++];
b = B; b = BC;
if (b == REGT_NIL) if (a == REGT_NIL)
{ {
::new(param) VMValue(); ::new(param) VMValue();
} }
else else
{ {
switch(b) switch(a)
{ {
case REGT_INT: case REGT_INT:
assert(C < f->NumRegD); assert(b < f->NumRegD);
::new(param) VMValue(reg.d[C]); ::new(param) VMValue(reg.d[b]);
break; break;
case REGT_INT | REGT_ADDROF: case REGT_INT | REGT_ADDROF:
assert(C < f->NumRegD); assert(b < f->NumRegD);
::new(param) VMValue(&reg.d[C]); ::new(param) VMValue(&reg.d[b]);
break; break;
case REGT_INT | REGT_KONST: case REGT_INT | REGT_KONST:
assert(C < sfunc->NumKonstD); assert(b < sfunc->NumKonstD);
::new(param) VMValue(konstd[C]); ::new(param) VMValue(konstd[b]);
break; break;
case REGT_STRING: case REGT_STRING:
assert(C < f->NumRegS); assert(b < f->NumRegS);
::new(param) VMValue(&reg.s[C]); ::new(param) VMValue(&reg.s[b]);
break; break;
case REGT_STRING | REGT_ADDROF: case REGT_STRING | REGT_ADDROF:
assert(C < f->NumRegS); assert(b < f->NumRegS);
::new(param) VMValue((void*)&reg.s[C]); // Note that this may not use the FString* version of the constructor! ::new(param) VMValue((void*)&reg.s[b]); // Note that this may not use the FString* version of the constructor!
break; break;
case REGT_STRING | REGT_KONST: case REGT_STRING | REGT_KONST:
assert(C < sfunc->NumKonstS); assert(b < sfunc->NumKonstS);
::new(param) VMValue(&konsts[C]); ::new(param) VMValue(&konsts[b]);
break; break;
case REGT_POINTER: case REGT_POINTER:
assert(C < f->NumRegA); assert(b < f->NumRegA);
::new(param) VMValue(reg.a[C]); ::new(param) VMValue(reg.a[b]);
break; break;
case REGT_POINTER | REGT_ADDROF: case REGT_POINTER | REGT_ADDROF:
assert(C < f->NumRegA); assert(b < f->NumRegA);
::new(param) VMValue(&reg.a[C]); ::new(param) VMValue(&reg.a[b]);
break; break;
case REGT_POINTER | REGT_KONST: case REGT_POINTER | REGT_KONST:
assert(C < sfunc->NumKonstA); assert(b < sfunc->NumKonstA);
::new(param) VMValue(konsta[C].v); ::new(param) VMValue(konsta[b].v);
break; break;
case REGT_FLOAT: case REGT_FLOAT:
assert(C < f->NumRegF); assert(b < f->NumRegF);
::new(param) VMValue(reg.f[C]); ::new(param) VMValue(reg.f[b]);
break; break;
case REGT_FLOAT | REGT_MULTIREG2: case REGT_FLOAT | REGT_MULTIREG2:
assert(C < f->NumRegF - 1); assert(b < f->NumRegF - 1);
assert(f->NumParam < sfunc->MaxParam); assert(f->NumParam < sfunc->MaxParam);
::new(param) VMValue(reg.f[C]); ::new(param) VMValue(reg.f[b]);
::new(param + 1) VMValue(reg.f[C + 1]); ::new(param + 1) VMValue(reg.f[b + 1]);
f->NumParam++; f->NumParam++;
break; break;
case REGT_FLOAT | REGT_MULTIREG3: case REGT_FLOAT | REGT_MULTIREG3:
assert(C < f->NumRegF - 2); assert(b < f->NumRegF - 2);
assert(f->NumParam < sfunc->MaxParam - 1); assert(f->NumParam < sfunc->MaxParam - 1);
::new(param) VMValue(reg.f[C]); ::new(param) VMValue(reg.f[b]);
::new(param + 1) VMValue(reg.f[C + 1]); ::new(param + 1) VMValue(reg.f[b + 1]);
::new(param + 2) VMValue(reg.f[C + 2]); ::new(param + 2) VMValue(reg.f[b + 2]);
f->NumParam += 2; f->NumParam += 2;
break; break;
case REGT_FLOAT | REGT_ADDROF: case REGT_FLOAT | REGT_ADDROF:
assert(C < f->NumRegF); assert(b < f->NumRegF);
::new(param) VMValue(&reg.f[C]); ::new(param) VMValue(&reg.f[b]);
break; break;
case REGT_FLOAT | REGT_KONST: case REGT_FLOAT | REGT_KONST:
assert(C < sfunc->NumKonstF); assert(b < sfunc->NumKonstF);
::new(param) VMValue(konstf[C]); ::new(param) VMValue(konstf[b]);
break; break;
default: default:
assert(0); assert(0);

View file

@ -162,6 +162,7 @@ enum EVMOpMode
MODE_CMP, MODE_CMP,
MODE_PARAM, MODE_PARAM,
MODE_PARAM24,
MODE_THROW, MODE_THROW,
MODE_CATCH, MODE_CATCH,
MODE_CAST, MODE_CAST,
@ -208,7 +209,8 @@ enum EVMOpMode
MODE_CIMMS = MODE_IMMS << MODE_CSHIFT, MODE_CIMMS = MODE_IMMS << MODE_CSHIFT,
MODE_CIMMZ = MODE_IMMZ << MODE_CSHIFT, MODE_CIMMZ = MODE_IMMZ << MODE_CSHIFT,
MODE_BCJOINT = (MODE_JOINT << MODE_BSHIFT) | (MODE_JOINT << MODE_CSHIFT), MODE_ABCJOINT = (MODE_JOINT << MODE_ASHIFT) | (MODE_JOINT << MODE_BSHIFT) | (MODE_JOINT << MODE_CSHIFT),
MODE_BCJOINT = (MODE_JOINT << MODE_BSHIFT) | (MODE_JOINT << MODE_CSHIFT),
MODE_BCKI = MODE_KI << MODE_BCSHIFT, MODE_BCKI = MODE_KI << MODE_BCSHIFT,
MODE_BCKF = MODE_KF << MODE_BCSHIFT, MODE_BCKF = MODE_KF << MODE_BCSHIFT,
MODE_BCKS = MODE_KS << MODE_BCSHIFT, MODE_BCKS = MODE_KS << MODE_BCSHIFT,
@ -219,8 +221,6 @@ enum EVMOpMode
MODE_BCTHROW = MODE_THROW << MODE_BCSHIFT, MODE_BCTHROW = MODE_THROW << MODE_BCSHIFT,
MODE_BCCATCH = MODE_CATCH << MODE_BCSHIFT, MODE_BCCATCH = MODE_CATCH << MODE_BCSHIFT,
MODE_BCCAST = MODE_CAST << MODE_BCSHIFT, MODE_BCCAST = MODE_CAST << MODE_BCSHIFT,
MODE_ABCJOINT = (MODE_JOINT << MODE_ASHIFT) | MODE_BCJOINT,
}; };
struct VMOpInfo struct VMOpInfo