mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-07 05:20:38 +00:00
- Added fixed registers that won't be freed automatically, so that parameters
can actually be used. In the end, all temporaries should be assigned to unique virtual registers, and a register allocator can alias them to real registers, but as long as we don't do any CSE, this is good enough for now. SVN r1920 (scripting)
This commit is contained in:
parent
3cbac657d6
commit
c424c61ffc
4 changed files with 53 additions and 63 deletions
|
@ -292,6 +292,10 @@ static void FinishThingdef()
|
||||||
tcall->Parameters[j]->Resolve(ctx);
|
tcall->Parameters[j]->Resolve(ctx);
|
||||||
}
|
}
|
||||||
VMFunctionBuilder buildit;
|
VMFunctionBuilder buildit;
|
||||||
|
// Allocate registers used to pass parameters in.
|
||||||
|
// self, stateowner, state, statecalldata (all are pointers)
|
||||||
|
buildit.Registers[REGT_POINTER].Get(4);
|
||||||
|
// Emit code for action parameters.
|
||||||
for (j = 0; j < tcall->Parameters.Size(); ++j)
|
for (j = 0; j < tcall->Parameters.Size(); ++j)
|
||||||
{
|
{
|
||||||
FxExpression *p = /*new FxParameter*/(tcall->Parameters[j]);
|
FxExpression *p = /*new FxParameter*/(tcall->Parameters[j]);
|
||||||
|
@ -308,6 +312,8 @@ static void FinishThingdef()
|
||||||
tcall->ActorInfo->Class->TypeName.GetChars(),
|
tcall->ActorInfo->Class->TypeName.GetChars(),
|
||||||
tcall->FirstState, tcall->NumStates);
|
tcall->FirstState, tcall->NumStates);
|
||||||
fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks);
|
fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks);
|
||||||
|
fprintf(dump, "\nInteger regs: %-3d Float regs: %-3d Address regs: %-3d String regs: %-3d\nStack size: %d\n",
|
||||||
|
func->NumRegD, func->NumRegF, func->NumRegA, func->NumRegS, func->MaxParam);
|
||||||
VMDumpConstants(dump, func);
|
VMDumpConstants(dump, func);
|
||||||
fprintf(dump, "\nDisassembly:\n");
|
fprintf(dump, "\nDisassembly:\n");
|
||||||
VMDisasm(dump, func->Code, func->NumCodeBytes / 4, func);
|
VMDisasm(dump, func->Code, func->NumCodeBytes / 4, func);
|
||||||
|
|
|
@ -146,12 +146,13 @@ struct ExpVal
|
||||||
|
|
||||||
struct ExpEmit
|
struct ExpEmit
|
||||||
{
|
{
|
||||||
ExpEmit() : RegNum(0), RegType(REGT_NIL) {}
|
ExpEmit() : RegNum(0), RegType(REGT_NIL), Konst(false), Fixed(false) {}
|
||||||
ExpEmit(int reg, int type) : RegNum(reg), RegType(type) {}
|
ExpEmit(int reg, int type) : RegNum(reg), RegType(type), Konst(false), Fixed(false) {}
|
||||||
ExpEmit(int reg, int type, bool konst) : RegNum(reg), RegType(type), Konst(konst) {}
|
ExpEmit(int reg, int type, bool konst) : RegNum(reg), RegType(type), Konst(konst), Fixed(false) {}
|
||||||
ExpEmit(VMFunctionBuilder *build, int type);
|
ExpEmit(VMFunctionBuilder *build, int type);
|
||||||
|
void Free(VMFunctionBuilder *build);
|
||||||
|
|
||||||
BYTE RegNum, RegType, Konst;
|
BYTE RegNum, RegType, Konst:1, Fixed:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -79,10 +79,18 @@ DEFINE_MEMBER_VARIABLE(Score, AActor)
|
||||||
DEFINE_MEMBER_VARIABLE(uservar, AActor)
|
DEFINE_MEMBER_VARIABLE(uservar, AActor)
|
||||||
|
|
||||||
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
|
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
|
||||||
: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false)
|
: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExpEmit::Free(VMFunctionBuilder *build)
|
||||||
|
{
|
||||||
|
if (!Fixed && !Konst)
|
||||||
|
{
|
||||||
|
build->Registers[RegType].Return(RegNum, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// EvalExpression
|
// EvalExpression
|
||||||
|
@ -413,7 +421,7 @@ ExpEmit FxParameter::Emit(VMFunctionBuilder *build)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
build->Emit(OP_PARAM, 0, where.RegType, where.RegNum);
|
build->Emit(OP_PARAM, 0, where.RegType, where.RegNum);
|
||||||
build->FreeReg(where.RegType, where.RegNum);
|
where.Free(build);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ExpEmit();
|
return ExpEmit();
|
||||||
|
@ -664,7 +672,7 @@ ExpEmit FxFloatCast::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit from = basex->Emit(build);
|
ExpEmit from = basex->Emit(build);
|
||||||
assert(!from.Konst);
|
assert(!from.Konst);
|
||||||
assert(basex->ValueType == VAL_Int);
|
assert(basex->ValueType == VAL_Int);
|
||||||
build->FreeReg(from.RegType, from.RegNum);
|
from.Free(build);
|
||||||
ExpEmit to(build, REGT_FLOAT);
|
ExpEmit to(build, REGT_FLOAT);
|
||||||
build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_I2F);
|
build->Emit(OP_CAST, to.RegNum, from.RegNum, CAST_I2F);
|
||||||
return to;
|
return to;
|
||||||
|
@ -991,9 +999,9 @@ ExpVal FxUnaryNotBoolean::EvalExpression (AActor *self)
|
||||||
ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build)
|
ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
ExpEmit from = Operand->Emit(build);
|
ExpEmit from = Operand->Emit(build);
|
||||||
assert(from.Konst != 0);
|
assert(!from.Konst);
|
||||||
ExpEmit to(build, REGT_INT);
|
ExpEmit to(build, REGT_INT);
|
||||||
build->FreeReg(from.RegType, from.RegNum);
|
from.Free(build);
|
||||||
|
|
||||||
// Preload result with 0.
|
// Preload result with 0.
|
||||||
build->Emit(OP_LI, to.RegNum, 0, 0);
|
build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||||
|
@ -1207,11 +1215,8 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build)
|
||||||
swap(op1, op2);
|
swap(op1, op2);
|
||||||
}
|
}
|
||||||
assert(!op1.Konst);
|
assert(!op1.Konst);
|
||||||
build->FreeReg(op1.RegType, op1.RegNum);
|
op1.Free(build);
|
||||||
if (!op2.Konst)
|
op2.Free(build);
|
||||||
{
|
|
||||||
build->FreeReg(op2.RegType, op2.RegNum);
|
|
||||||
}
|
|
||||||
if (ValueType == VAL_Float)
|
if (ValueType == VAL_Float)
|
||||||
{
|
{
|
||||||
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
||||||
|
@ -1232,14 +1237,8 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
// Subtraction is not commutative, so either side may be constant (but not both).
|
// Subtraction is not commutative, so either side may be constant (but not both).
|
||||||
assert(!op1.Konst || !op2.Konst);
|
assert(!op1.Konst || !op2.Konst);
|
||||||
if (!op1.Konst)
|
op1.Free(build);
|
||||||
{
|
op2.Free(build);
|
||||||
build->FreeReg(op1.RegType, op1.RegNum);
|
|
||||||
}
|
|
||||||
if (!op2.Konst)
|
|
||||||
{
|
|
||||||
build->FreeReg(op2.RegType, op2.RegNum);
|
|
||||||
}
|
|
||||||
if (ValueType == VAL_Float)
|
if (ValueType == VAL_Float)
|
||||||
{
|
{
|
||||||
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
||||||
|
@ -1397,11 +1396,8 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build)
|
||||||
swap(op1, op2);
|
swap(op1, op2);
|
||||||
}
|
}
|
||||||
assert(!op1.Konst);
|
assert(!op1.Konst);
|
||||||
build->FreeReg(op1.RegType, op1.RegNum);
|
op1.Free(build);
|
||||||
if (!op2.Konst)
|
op2.Free(build);
|
||||||
{
|
|
||||||
build->FreeReg(op2.RegType, op2.RegNum);
|
|
||||||
}
|
|
||||||
if (ValueType == VAL_Float)
|
if (ValueType == VAL_Float)
|
||||||
{
|
{
|
||||||
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
||||||
|
@ -1423,14 +1419,8 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build)
|
||||||
// Division is not commutative, so either side may be constant (but not both).
|
// Division is not commutative, so either side may be constant (but not both).
|
||||||
assert(!op1.Konst || !op2.Konst);
|
assert(!op1.Konst || !op2.Konst);
|
||||||
assert(Operator == '%' || Operator == '/');
|
assert(Operator == '%' || Operator == '/');
|
||||||
if (!op1.Konst)
|
op1.Free(build);
|
||||||
{
|
op2.Free(build);
|
||||||
build->FreeReg(op1.RegType, op1.RegNum);
|
|
||||||
}
|
|
||||||
if (!op2.Konst)
|
|
||||||
{
|
|
||||||
build->FreeReg(op2.RegType, op2.RegNum);
|
|
||||||
}
|
|
||||||
if (ValueType == VAL_Float)
|
if (ValueType == VAL_Float)
|
||||||
{
|
{
|
||||||
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
||||||
|
@ -1574,7 +1564,7 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
build->FreeReg(op2.RegType, op2.RegNum);
|
op2.Free(build);
|
||||||
}
|
}
|
||||||
if (op1.Konst)
|
if (op1.Konst)
|
||||||
{
|
{
|
||||||
|
@ -1582,7 +1572,7 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
build->FreeReg(op1.RegType, op1.RegNum);
|
op1.Free(build);
|
||||||
}
|
}
|
||||||
ExpEmit to(build, op1.RegType);
|
ExpEmit to(build, op1.RegType);
|
||||||
|
|
||||||
|
@ -1715,10 +1705,10 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build)
|
||||||
instr = op1.RegType == REGT_INT ? OP_EQ_R :
|
instr = op1.RegType == REGT_INT ? OP_EQ_R :
|
||||||
op1.RegType == REGT_FLOAT ? OP_EQF_R :
|
op1.RegType == REGT_FLOAT ? OP_EQF_R :
|
||||||
OP_EQA_R;
|
OP_EQA_R;
|
||||||
build->FreeReg(op1.RegType, op1.RegNum);
|
op1.Free(build);
|
||||||
if (!op2.Konst)
|
if (!op2.Konst)
|
||||||
{
|
{
|
||||||
build->FreeReg(op2.RegType, op2.RegNum);
|
op2.Free(build);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1863,7 +1853,7 @@ ExpEmit FxBinaryInt::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
op2 = right->Emit(build);
|
op2 = right->Emit(build);
|
||||||
assert(!op2.Konst);
|
assert(!op2.Konst);
|
||||||
build->FreeReg(op2.RegType, op2.RegNum);
|
op2.Free(build);
|
||||||
rop = op2.RegNum;
|
rop = op2.RegNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1876,14 +1866,11 @@ ExpEmit FxBinaryInt::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
assert(!op1.Konst);
|
assert(!op1.Konst);
|
||||||
rop = op2.RegNum;
|
rop = op2.RegNum;
|
||||||
if (!op2.Konst)
|
op2.Free(build);
|
||||||
{
|
|
||||||
build->FreeReg(op2.RegType, op2.RegNum);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!op1.Konst)
|
if (!op1.Konst)
|
||||||
{
|
{
|
||||||
build->FreeReg(op1.RegType, op1.RegNum);
|
op1.Free(build);
|
||||||
if (!op2.Konst)
|
if (!op2.Konst)
|
||||||
{
|
{
|
||||||
instr = InstrMap[index][0];
|
instr = InstrMap[index][0];
|
||||||
|
@ -2058,7 +2045,7 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit op1 = left->Emit(build);
|
ExpEmit op1 = left->Emit(build);
|
||||||
assert(!op1.Konst);
|
assert(!op1.Konst);
|
||||||
int zero = build->GetConstantInt(0);
|
int zero = build->GetConstantInt(0);
|
||||||
build->FreeReg(op1.RegType, op1.RegNum);
|
op1.Free(build);
|
||||||
|
|
||||||
if (Operator == TK_AndAnd)
|
if (Operator == TK_AndAnd)
|
||||||
{
|
{
|
||||||
|
@ -2069,7 +2056,7 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build)
|
||||||
// Evaluate op2.
|
// Evaluate op2.
|
||||||
ExpEmit op2 = right->Emit(build);
|
ExpEmit op2 = right->Emit(build);
|
||||||
assert(!op2.Konst);
|
assert(!op2.Konst);
|
||||||
build->FreeReg(op2.RegType, op2.RegNum);
|
op2.Free(build);
|
||||||
|
|
||||||
ExpEmit to(build, REGT_INT);
|
ExpEmit to(build, REGT_INT);
|
||||||
build->Emit(OP_EQ_K, 0, op2.RegNum, zero);
|
build->Emit(OP_EQ_K, 0, op2.RegNum, zero);
|
||||||
|
@ -2090,7 +2077,7 @@ ExpEmit FxBinaryLogical::Emit(VMFunctionBuilder *build)
|
||||||
// Evaluate op2.
|
// Evaluate op2.
|
||||||
ExpEmit op2 = right->Emit(build);
|
ExpEmit op2 = right->Emit(build);
|
||||||
assert(!op2.Konst);
|
assert(!op2.Konst);
|
||||||
build->FreeReg(op2.RegType, op2.RegNum);
|
op2.Free(build);
|
||||||
|
|
||||||
ExpEmit to(build, REGT_INT);
|
ExpEmit to(build, REGT_INT);
|
||||||
build->Emit(OP_EQ_K, 1, op2.RegNum, zero);
|
build->Emit(OP_EQ_K, 1, op2.RegNum, zero);
|
||||||
|
@ -2250,7 +2237,7 @@ ExpEmit FxConditional::Emit(VMFunctionBuilder *build)
|
||||||
// Move result from the register returned by "false" to the one
|
// Move result from the register returned by "false" to the one
|
||||||
// returned by "true" so that only one register is returned by
|
// returned by "true" so that only one register is returned by
|
||||||
// this tree.
|
// this tree.
|
||||||
build->FreeReg(falseop.RegType, falseop.RegNum);
|
falseop.Free(build);
|
||||||
if (falseop.RegType == REGT_INT)
|
if (falseop.RegType == REGT_INT)
|
||||||
{
|
{
|
||||||
build->Emit(OP_MOVE, out.RegNum, falseop.RegNum, 0);
|
build->Emit(OP_MOVE, out.RegNum, falseop.RegNum, 0);
|
||||||
|
@ -2848,7 +2835,9 @@ ExpVal FxSelf::EvalExpression (AActor *self)
|
||||||
ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
|
ExpEmit FxSelf::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
// self is always the first pointer passed to the function;
|
// self is always the first pointer passed to the function;
|
||||||
return ExpEmit(0, REGT_POINTER);
|
ExpEmit me(0, REGT_POINTER);
|
||||||
|
me.Fixed = true;
|
||||||
|
return me;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -3059,10 +3048,7 @@ ExpEmit FxClassMember::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
if (!obj.Konst)
|
obj.Free(build);
|
||||||
{
|
|
||||||
build->FreeReg(obj.RegType, obj.RegNum);
|
|
||||||
}
|
|
||||||
ExpEmit out(build, REGT_POINTER);
|
ExpEmit out(build, REGT_POINTER);
|
||||||
build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, build->GetConstantInt((int)membervar->offset));
|
build->Emit(OP_ADDA_RK, out.RegNum, obj.RegNum, build->GetConstantInt((int)membervar->offset));
|
||||||
return out;
|
return out;
|
||||||
|
@ -3117,7 +3103,7 @@ ExpEmit FxClassMember::Emit(VMFunctionBuilder *build)
|
||||||
build->Emit(OP_LW, tmp.RegNum, obj.RegNum, offsetreg);
|
build->Emit(OP_LW, tmp.RegNum, obj.RegNum, offsetreg);
|
||||||
build->Emit(OP_CAST, loc.RegNum, tmp.RegNum, CAST_I2F);
|
build->Emit(OP_CAST, loc.RegNum, tmp.RegNum, CAST_I2F);
|
||||||
build->Emit(OP_MULF_RK, loc.RegNum, loc.RegNum, build->GetConstantFloat(90.0 / ANGLE_90));
|
build->Emit(OP_MULF_RK, loc.RegNum, loc.RegNum, build->GetConstantFloat(90.0 / ANGLE_90));
|
||||||
build->FreeReg(tmp.RegType, tmp.RegNum);
|
tmp.Free(build);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VAL_Object:
|
case VAL_Object:
|
||||||
|
@ -3129,7 +3115,7 @@ ExpEmit FxClassMember::Emit(VMFunctionBuilder *build)
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
build->FreeReg(obj.RegType, obj.RegNum);
|
obj.Free(build);
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3271,9 +3257,9 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
build->Emit(OP_SLL_RI, indexv.RegNum, indexv.RegNum, 2);
|
build->Emit(OP_SLL_RI, indexv.RegNum, indexv.RegNum, 2);
|
||||||
build->Emit(OP_BOUND, indexv.RegNum, Array->ValueType.size);
|
build->Emit(OP_BOUND, indexv.RegNum, Array->ValueType.size);
|
||||||
build->Emit(OP_LW_R, dest.RegNum, start.RegNum, indexv.RegNum);
|
build->Emit(OP_LW_R, dest.RegNum, start.RegNum, indexv.RegNum);
|
||||||
build->FreeReg(indexv.RegType, indexv.RegNum);
|
indexv.Free(build);
|
||||||
}
|
}
|
||||||
build->FreeReg(start.RegType, start.RegNum);
|
start.Free(build);
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3490,7 +3476,7 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
ExpEmit arg(argex->Emit(build));
|
ExpEmit arg(argex->Emit(build));
|
||||||
build->Emit(OP_PARAM, 0, arg.RegType, arg.RegNum);
|
build->Emit(OP_PARAM, 0, arg.RegType, arg.RegNum);
|
||||||
build->FreeReg(arg.RegType, arg.RegNum);
|
arg.Free(build);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3772,7 +3758,7 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
|
||||||
|
|
||||||
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
|
build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1);
|
||||||
build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum);
|
build->Emit(OP_RESULT, 0, REGT_POINTER, dest.RegNum);
|
||||||
build->FreeReg(clsname.RegType, clsname.RegNum);
|
clsname.Free(build);
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,6 @@ public:
|
||||||
// Track available registers.
|
// Track available registers.
|
||||||
RegAvailability Registers[4];
|
RegAvailability Registers[4];
|
||||||
|
|
||||||
// Free a register.
|
|
||||||
void FreeReg(int regtype, int regnum) { Registers[regtype].Return(regnum, 1); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct AddrKonst
|
struct AddrKonst
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue