From b14f768b681d52640735f39724c0efa1d31a5f87 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sun, 21 Dec 2014 21:57:30 -0600 Subject: [PATCH] Fix FxPick code emission - Fixed: Integer constants passed to pick() need to manually generate load instructions, since FxConstant::Emit() will just return a constant register with its value. - Fixed: VMFunctionBuilder::RegAvailability::Reuse() didn't actually calculate a proper mask. Also added another assert to this function. --- src/thingdef/thingdef_expression.cpp | 28 ++++++++++++++++++---------- src/zscript/vmbuilder.cpp | 3 ++- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 2395b0d0eb..f95bfcdafd 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -2203,17 +2203,25 @@ ExpEmit FxPick::Emit(VMFunctionBuilder *build) for (unsigned i = 0; i < choices.Size(); ++i) { build->BackpatchToHere(jumptable + i); - ExpEmit casereg = choices[i]->Emit(build); - if (casereg.RegNum != resultreg.RegNum) - { // The result of the case is in a different register from what - // was expected. Copy it to the one we wanted. - - resultreg.Reuse(build); // This is really just for the assert in Reuse() - build->Emit(OP_MOVE, resultreg.RegNum, casereg.RegNum, 0); - resultreg.Free(build); + if (choices[i]->isConstant()) + { + int val = static_cast(choices[i])->GetValue().GetInt(); + build->EmitLoadInt(resultreg.RegNum, val); + } + else + { + ExpEmit casereg = choices[i]->Emit(build); + if (casereg.RegNum != resultreg.RegNum) + { // The result of the case is in a different register from what + // was expected. Copy it to the one we wanted. + + resultreg.Reuse(build); // This is really just for the assert in Reuse() + build->Emit(OP_MOVE, resultreg.RegNum, casereg.RegNum, 0); + resultreg.Free(build); + } + // Free this register so the remaining cases can use it. + casereg.Free(build); } - // Free this register so the remaining cases can use it. - casereg.Free(build); // All but the final case needs a jump to the end of the expression's code. if (i + 1 < choices.Size()) { diff --git a/src/zscript/vmbuilder.cpp b/src/zscript/vmbuilder.cpp index 2dff77cfcc..d17efc1d98 100644 --- a/src/zscript/vmbuilder.cpp +++ b/src/zscript/vmbuilder.cpp @@ -423,8 +423,9 @@ void VMFunctionBuilder::RegAvailability::Return(int reg, int count) bool VMFunctionBuilder::RegAvailability::Reuse(int reg) { assert(reg >= 0 && reg <= 255); + assert(reg < MostUsed && "Attempt to reuse a register that was never used"); - VM_UWORD mask = reg & 31; + VM_UWORD mask = 1 << (reg & 31); int word = reg / 32; if (Used[word] & mask)