From 126c7381168b1c6b8f553611d6968983a027e9d1 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 15 Oct 2009 21:59:37 +0000 Subject: [PATCH] - Added PARAMI for the common case of passing an integer constant to a function. - Made FxParameter::Emit free its operand's register. SVN r1918 (scripting) --- src/thingdef/thingdef_expression.cpp | 114 ++++++++++----------------- src/zscript/vmbuilder.cpp | 4 + src/zscript/vmdisasm.cpp | 6 ++ src/zscript/vmexec.cpp | 2 + src/zscript/vmexec.h | 7 ++ src/zscript/vmops.h | 3 +- 6 files changed, 61 insertions(+), 75 deletions(-) diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 34f4a4080..c40ba766f 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -334,6 +334,7 @@ FxParameter::FxParameter(FxExpression *operand) : FxExpression(operand->ScriptPosition) { Operand = operand; + ValueType = operand->ValueType; } //========================================================================== @@ -357,9 +358,23 @@ FxExpression *FxParameter::Resolve(FCompileContext& ctx) { CHECKRESOLVED(); SAFE_RESOLVE(Operand, ctx); + ValueType = Operand->ValueType; return this; } +static void EmitConstantInt(VMFunctionBuilder *build, int val) +{ + // If it fits in 24 bits, use PARAMI instead of PARAM. + if ((val << 8) >> 8) + { + build->Emit(OP_PARAMI, val); + } + else + { + build->Emit(OP_PARAM, 0, REGT_INT | REGT_KONST, build->GetConstantInt(val)); + } +} + ExpEmit FxParameter::Emit(VMFunctionBuilder *build) { if (Operand->isConstant()) @@ -367,7 +382,7 @@ ExpEmit FxParameter::Emit(VMFunctionBuilder *build) ExpVal val = Operand->EvalExpression(NULL); if (val.Type == VAL_Int || val.Type == VAL_Sound || val.Type == VAL_Name || val.Type == VAL_Color) { - build->Emit(OP_PARAM, 0, REGT_INT | REGT_KONST, build->GetConstantInt(val.Int)); + EmitConstantInt(build, val.Int); } else if (val.Type == VAL_Float) { @@ -398,6 +413,7 @@ ExpEmit FxParameter::Emit(VMFunctionBuilder *build) else { build->Emit(OP_PARAM, 0, where.RegType, where.RegNum); + build->FreeReg(where.RegType, where.RegNum); } } return ExpEmit(); @@ -2366,8 +2382,8 @@ FxRandom::FxRandom(FRandom * r, FxExpression *mi, FxExpression *ma, const FScrip { if (mi != NULL && ma != NULL) { - min = new FxIntCast(mi); - max = new FxIntCast(ma); + min = new FxParameter(new FxIntCast(mi)); + max = new FxParameter(new FxIntCast(ma)); } else min = max = NULL; rng = r; @@ -2397,17 +2413,11 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx) CHECKRESOLVED(); if (min && max) { - if (min->ValueType != VAL_Int) - { - min = new FxIntCast(min); - } - if (max->ValueType != VAL_Int) - { - max = new FxIntCast(max); - } RESOLVE(min, ctx); RESOLVE(max, ctx); ABORT(min && max); + assert(min->ValueType == VAL_Int); + assert(max->ValueType == VAL_Int); } return this; }; @@ -2489,28 +2499,8 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build) build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); if (min != NULL && max != NULL) { - ExpEmit op = min->Emit(build); - assert(op.RegType == REGT_INT); - if (op.Konst) - { - build->Emit(OP_PARAM, 0, REGT_INT | REGT_KONST, op.RegNum); - } - else - { - build->FreeReg(REGT_INT, op.RegNum); - build->Emit(OP_PARAM, 0, REGT_INT, op.RegNum); - } - op = max->Emit(build); - assert(op.RegType == REGT_INT); - if (op.Konst) - { - build->Emit(OP_PARAM, 0, REGT_INT | REGT_KONST, op.RegNum); - } - else - { - build->FreeReg(REGT_INT, op.RegNum); - build->Emit(OP_PARAM, 0, REGT_INT, op.RegNum); - } + min->Emit(build); + max->Emit(build); build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); } else @@ -2532,8 +2522,8 @@ FxFRandom::FxFRandom(FRandom *r, FxExpression *mi, FxExpression *ma, const FScri { if (mi != NULL && ma != NULL) { - min = mi; - max = ma; + min = new FxParameter(new FxFloatCast(mi)); + max = new FxParameter(new FxFloatCast(ma)); } } @@ -2614,28 +2604,8 @@ ExpEmit FxFRandom::Emit(VMFunctionBuilder *build) build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); if (min != NULL && max != NULL) { - ExpEmit op = min->Emit(build); - assert(op.RegType == REGT_FLOAT); - if (op.Konst) - { - build->Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, op.RegNum); - } - else - { - build->FreeReg(REGT_FLOAT, op.RegNum); - build->Emit(OP_PARAM, 0, REGT_FLOAT, op.RegNum); - } - op = max->Emit(build); - assert(op.RegType == REGT_FLOAT); - if (op.Konst) - { - build->Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, op.RegNum); - } - else - { - build->FreeReg(REGT_FLOAT, op.RegNum); - build->Emit(OP_PARAM, 0, REGT_FLOAT, op.RegNum); - } + min->Emit(build); + max->Emit(build); build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 3, 1); } else @@ -2659,6 +2629,7 @@ FxRandom2::FxRandom2(FRandom *r, FxExpression *m, const FScriptPosition &pos) rng = r; if (m) mask = new FxIntCast(m); else mask = new FxConstant(-1, pos); + mask = new FxParameter(mask); ValueType = VAL_Int; } @@ -2721,17 +2692,7 @@ ExpEmit FxRandom2::Emit(VMFunctionBuilder *build) callfunc = ((PSymbolVMFunction *)sym)->Function; build->Emit(OP_PARAM, 0, REGT_POINTER | REGT_KONST, build->GetConstantAddress(rng, ATAG_RNG)); - ExpEmit op = mask->Emit(build); - assert(op.RegType == REGT_INT); - if (op.Konst) - { - build->Emit(OP_PARAM, 0, REGT_INT | REGT_KONST, op.RegNum); - } - else - { - build->FreeReg(REGT_INT, op.RegNum); - build->Emit(OP_PARAM, 0, REGT_INT, op.RegNum); - } + mask->Emit(build); build->Emit(OP_CALL_K, build->GetConstantAddress(callfunc, ATAG_OBJECT), 2, 1); ExpEmit out(build, REGT_INT); build->Emit(OP_RESULT, 0, REGT_INT, out.RegNum); @@ -3513,17 +3474,22 @@ ExpEmit FxActionSpecialCall::Emit(VMFunctionBuilder *build) assert(Self == NULL); unsigned i = 0; - build->Emit(OP_PARAM, 0, REGT_INT | REGT_KONST, build->GetConstantInt(Special)); // pass special number + build->Emit(OP_PARAMI, Special); // pass special number build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self if (ArgList != NULL) { for (; i < ArgList->Size(); ++i) { - ExpEmit arg((*ArgList)[i]->Emit(build)); - assert(arg.RegType == REGT_INT); - build->Emit(OP_PARAM, 0, arg.RegType | (arg.Konst ? REGT_KONST : 0), arg.RegNum); - if (!arg.Konst) + FxExpression *argex = (*ArgList)[i]; + assert(argex->ValueType == VAL_Int); + if (argex->isConstant()) { + EmitConstantInt(build, argex->EvalExpression(NULL).GetInt()); + } + else + { + ExpEmit arg(argex->Emit(build)); + build->Emit(OP_PARAM, 0, arg.RegType, arg.RegNum); build->FreeReg(arg.RegType, arg.RegNum); } } @@ -3991,7 +3957,7 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build) build->Emit(OP_PARAM, 0, REGT_POINTER, 0); // pass self for (unsigned i = 0; i < names.Size(); ++i) { - build->Emit(OP_PARAM, 0, REGT_INT | REGT_KONST, build->GetConstantInt(names[i])); + EmitConstantInt(build, names[i]); } // Find the DecoFindMultiNameState function. If not found, create it and install it diff --git a/src/zscript/vmbuilder.cpp b/src/zscript/vmbuilder.cpp index 114f27d8e..450190ddf 100644 --- a/src/zscript/vmbuilder.cpp +++ b/src/zscript/vmbuilder.cpp @@ -465,6 +465,10 @@ size_t VMFunctionBuilder::Emit(int opcode, int opabc) #else *(VM_UWORD *)&Code[loc] = opcode | (opabc << 8); #endif + if (opcode == OP_PARAMI) + { + ParamChange(1); + } return loc / 4; } diff --git a/src/zscript/vmdisasm.cpp b/src/zscript/vmdisasm.cpp index 7c85b5341..108f4b726 100644 --- a/src/zscript/vmdisasm.cpp +++ b/src/zscript/vmdisasm.cpp @@ -95,8 +95,10 @@ const VMOpInfo OpInfo[NUM_OPS] = }; #ifdef WORDS_BIGENDIAN +#define ABCs(x) ((*(VM_SWORD *)(x) << 8) >> 8) #define JMPOFS(x) ((*(VM_SWORD *)(x) << 8) >> 6) #else +#define ABCs(x) (*(VM_SWORD *)(x) >> 8) #define JMPOFS(x) ((*(VM_SWORD *)(x) >> 6) & ~3) #endif @@ -214,6 +216,10 @@ void VMDisasm(FILE *out, const VM_UBYTE *code, int codesize, const VMScriptFunct col = printf_wrapper(out, "%08x", i + 4 + JMPOFS(&code[i])); break; + case OP_PARAMI: + col = printf_wrapper(out, "%d", i + 4 + ABCs(&code[i])); + break; + case OP_RET: if (code[i+2] != REGT_NIL) { diff --git a/src/zscript/vmexec.cpp b/src/zscript/vmexec.cpp index 8835afcc8..6ef11c29b 100644 --- a/src/zscript/vmexec.cpp +++ b/src/zscript/vmexec.cpp @@ -25,8 +25,10 @@ #define BCs (*(VM_SHALF *)(pc - 2)) #ifdef WORDS_BIGENDIAN +#define ABCs ((*(VM_SWORD *)(pc - 4) << 8) >> 8) #define JMPOFS(x) ((*(VM_SWORD *)(x) << 8) >> 6) #else +#define ABCs (*(VM_SWORD *)(pc - 4) >> 8) #define JMPOFS(x) ((*(VM_SWORD *)(x) >> 6) & ~3) #endif diff --git a/src/zscript/vmexec.h b/src/zscript/vmexec.h index e300e6644..f8da2f291 100644 --- a/src/zscript/vmexec.h +++ b/src/zscript/vmexec.h @@ -395,6 +395,13 @@ begin: assert(*pc == OP_JMP); pc += (1 + *((VM_SHALF *)pc + 1)) << 2; NEXTOP; + OP(PARAMI): + assert(f->NumParam < sfunc->MaxParam); + { + VMValue *param = ®.param[f->NumParam++]; + ::new(param) VMValue(ABCs); + } + NEXTOP; OP(PARAM): assert(f->NumParam < sfunc->MaxParam); { diff --git a/src/zscript/vmops.h b/src/zscript/vmops.h index 00c6f5d13..20178dfb0 100644 --- a/src/zscript/vmops.h +++ b/src/zscript/vmops.h @@ -74,6 +74,7 @@ xx(TEST, test, RII16), // if (dA != BC) then pc++ xx(JMP, jmp, I24), // pc += ABC -- The ABC fields contain a signed 24-bit offset. xx(IJMP, ijmp, RII16), // pc += dA + BC -- BC is a signed offset. The target instruction must be a JMP. xx(PARAM, param, __BCP), // push parameter encoded in BC for function call (B=regtype, C=regnum) +xx(PARAMI, parami, I24), // push immediate, signed integer for function call xx(CALL, call, RPI8I8), // Call function pkA with parameter count B and expected result count C xx(CALL_K, call, KPI8I8), xx(RESULT, result, __BCP), // Result should go in register encoded in BC (in caller, after CALL) @@ -106,7 +107,7 @@ xx(SRA_RI, sra, RIRII8), xx(SRA_KR, sra, RIKIRI), xx(ADD_RR, add, RIRIRI), // dA = dB + dkC xx(ADD_RK, add, RIRIKI), -xx(ADDI, add, RIRIIs), // dA = dB + C -- C is a signed 8-bit constant +xx(ADDI, addi, RIRIIs), // dA = dB + C -- C is a signed 8-bit constant xx(SUB_RR, sub, RIRIRI), // dA = dkB - dkC xx(SUB_RK, sub, RIRIKI), xx(SUB_KR, sub, RIKIRI),