mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 12:32:20 +02:00
Fixed actualization of illegal offset scales
This commit is contained in:
parent
92e189826b
commit
7d680c2a48
2 changed files with 283 additions and 248 deletions
|
@ -3636,7 +3636,7 @@ BeMCOperand BeMCContext::AllocVirtualReg(BeType* type, int refCount, bool mustBe
|
||||||
|
|
||||||
if (mDebugging)
|
if (mDebugging)
|
||||||
{
|
{
|
||||||
if (mcOperand.mVRegIdx == 263)
|
if (mcOperand.mVRegIdx == 97)
|
||||||
{
|
{
|
||||||
NOP;
|
NOP;
|
||||||
}
|
}
|
||||||
|
@ -5180,13 +5180,10 @@ uint8 BeMCContext::GetREX(const BeMCOperand& r, const BeMCOperand& rm, bool is64
|
||||||
if (vregInfo->IsDirectRelTo())
|
if (vregInfo->IsDirectRelTo())
|
||||||
return GetREX(r, vregInfo->mRelTo, is64Bit);
|
return GetREX(r, vregInfo->mRelTo, is64Bit);
|
||||||
|
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(rm, rmInfo);
|
||||||
int bScale = 1;
|
is64BitExRM |= ((rmInfo.mRegA >= X64Reg_R8) && (rmInfo.mRegA <= X64Reg_R15)) || ((rmInfo.mRegA >= X64Reg_R8D) && (rmInfo.mRegA <= X64Reg_R15D));
|
||||||
int disp = 0;
|
hasSibExRM |= ((rmInfo.mRegB >= X64Reg_R8) && (rmInfo.mRegB <= X64Reg_R15)) || ((rmInfo.mRegB >= X64Reg_R8D) && (rmInfo.mRegB <= X64Reg_R15D));
|
||||||
GetRMParams(rm, regA, regB, bScale, disp);
|
|
||||||
is64BitExRM |= ((regA >= X64Reg_R8) && (regA <= X64Reg_R15)) || ((regA >= X64Reg_R8D) && (regA <= X64Reg_R15D));
|
|
||||||
hasSibExRM |= ((regB >= X64Reg_R8) && (regB <= X64Reg_R15)) || ((regB >= X64Reg_R8D) && (regB <= X64Reg_R15D));
|
|
||||||
}
|
}
|
||||||
else if (rm.IsSymbol())
|
else if (rm.IsSymbol())
|
||||||
{
|
{
|
||||||
|
@ -5354,10 +5351,10 @@ int BeMCContext::GetRegSize(int regNum)
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
BeMCRMMode BeMCContext::ValidateRMResult(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB, int& bScale, int& disp, int* errorVReg, BeMCRMMode result, bool doValidate)
|
void BeMCContext::ValidateRMResult(const BeMCOperand& operand, BeRMParamsInfo& rmInfo, bool doValidate)
|
||||||
{
|
{
|
||||||
if (!doValidate)
|
if (!doValidate)
|
||||||
return result;
|
return;
|
||||||
|
|
||||||
//TODO: WTF- this previous version just seems to be wrong! Why did think this was true? the REX.X and REX.B flags fix these
|
//TODO: WTF- this previous version just seems to be wrong! Why did think this was true? the REX.X and REX.B flags fix these
|
||||||
// in a SIB, the base can't be R13 (which is RBP+REX), and the scaled index can't be R12 (which is RSP+REX)
|
// in a SIB, the base can't be R13 (which is RBP+REX), and the scaled index can't be R12 (which is RSP+REX)
|
||||||
|
@ -5376,40 +5373,45 @@ BeMCRMMode BeMCContext::ValidateRMResult(const BeMCOperand& operand, X64CPURegis
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// In a SIB, the base can't be RBP, and the scaled index can't be RSP
|
// In a SIB, the base can't be RBP, and the scaled index can't be RSP
|
||||||
if ((regB != X64Reg_None) &&
|
if ((rmInfo.mRegB != X64Reg_None) &&
|
||||||
((regA == X64Reg_RBP) || (regB == X64Reg_RSP)))
|
((rmInfo.mRegA == X64Reg_RBP) || (rmInfo.mRegB == X64Reg_RSP)))
|
||||||
{
|
{
|
||||||
// We can't just swap the regs if we have a scale applied
|
// We can't just swap the regs if we have a scale applied
|
||||||
if (bScale != 1)
|
if (rmInfo.mBScale != 1)
|
||||||
{
|
{
|
||||||
if (errorVReg != NULL)
|
rmInfo.mErrorVReg = -2; // Scale error
|
||||||
*errorVReg = -2; // Scale error
|
rmInfo.mMode = BeMCRMMode_Invalid;
|
||||||
return BeMCRMMode_Invalid;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BF_SWAP(regA, regB);
|
BF_SWAP(rmInfo.mRegA, rmInfo.mRegB);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB, int& bScale, int& disp, int* errorVReg, bool doValidate)
|
void BeMCContext::GetRMParams(const BeMCOperand& operand, BeRMParamsInfo& rmInfo, bool doValidate)
|
||||||
{
|
{
|
||||||
BeMCRMMode rmMode = BeMCRMMode_Invalid;
|
BeMCRMMode rmMode = BeMCRMMode_Invalid;
|
||||||
if (operand.mKind == BeMCOperandKind_NativeReg)
|
if (operand.mKind == BeMCOperandKind_NativeReg)
|
||||||
{
|
{
|
||||||
if (regA == X64Reg_None)
|
if (rmInfo.mRegA == X64Reg_None)
|
||||||
regA = operand.mReg;
|
rmInfo.mRegA = operand.mReg;
|
||||||
else if (regB == X64Reg_None)
|
else if (rmInfo.mRegB == X64Reg_None)
|
||||||
regB = operand.mReg;
|
rmInfo.mRegB = operand.mReg;
|
||||||
else
|
else
|
||||||
return BeMCRMMode_Invalid;
|
{
|
||||||
return ValidateRMResult(operand, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate);
|
rmInfo.mMode = BeMCRMMode_Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rmInfo.mMode = BeMCRMMode_Direct;
|
||||||
|
return ValidateRMResult(operand, rmInfo, doValidate);
|
||||||
}
|
}
|
||||||
else if (operand.IsImmediateInt())
|
else if (operand.IsImmediateInt())
|
||||||
{
|
{
|
||||||
disp += (int)operand.mImmediate;
|
rmInfo.mDisp += (int)operand.mImmediate;
|
||||||
return ValidateRMResult(operand, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate);
|
rmInfo.mMode = BeMCRMMode_Direct;
|
||||||
|
return ValidateRMResult(operand, rmInfo, doValidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operand.mKind == BeMCOperandKind_VReg)
|
if (operand.mKind == BeMCOperandKind_VReg)
|
||||||
|
@ -5420,20 +5422,25 @@ BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister&
|
||||||
auto reg = vregInfo->mReg;
|
auto reg = vregInfo->mReg;
|
||||||
if (reg != X64Reg_None)
|
if (reg != X64Reg_None)
|
||||||
{
|
{
|
||||||
if (regA == X64Reg_None)
|
if (rmInfo.mRegA == X64Reg_None)
|
||||||
regA = reg;
|
rmInfo.mRegA = reg;
|
||||||
else if (regB == X64Reg_None)
|
else if (rmInfo.mRegB == X64Reg_None)
|
||||||
regB = reg;
|
rmInfo.mRegB = reg;
|
||||||
else
|
else
|
||||||
return BeMCRMMode_Invalid;
|
{
|
||||||
return ValidateRMResult(operand, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate);
|
rmInfo.mMode = BeMCRMMode_Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rmInfo.mMode = BeMCRMMode_Direct;
|
||||||
|
return ValidateRMResult(operand, rmInfo, doValidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = GetRMParams(BeMCOperand::ToAddr(operand), regA, regB, bScale, disp, errorVReg, doValidate);
|
GetRMParams(BeMCOperand::ToAddr(operand), rmInfo, doValidate);
|
||||||
if (result == BeMCRMMode_Invalid)
|
if (rmInfo.mMode == BeMCRMMode_Invalid)
|
||||||
return BeMCRMMode_Invalid;
|
return;
|
||||||
BF_ASSERT(result == BeMCRMMode_Direct);
|
BF_ASSERT(rmInfo.mMode == BeMCRMMode_Direct);
|
||||||
return ValidateRMResult(BeMCOperand::ToAddr(operand), regA, regB, bScale, disp, errorVReg, BeMCRMMode_Deref, doValidate);
|
rmInfo.mMode = BeMCRMMode_Deref;
|
||||||
|
return ValidateRMResult(BeMCOperand::ToAddr(operand), rmInfo, doValidate);
|
||||||
}
|
}
|
||||||
// Fall through
|
// Fall through
|
||||||
}
|
}
|
||||||
|
@ -5446,13 +5453,14 @@ BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister&
|
||||||
if (vregInfo->IsDirectRelToAny())
|
if (vregInfo->IsDirectRelToAny())
|
||||||
{
|
{
|
||||||
if (vregInfo->mRelTo.mKind == BeMCOperandKind_VReg)
|
if (vregInfo->mRelTo.mKind == BeMCOperandKind_VReg)
|
||||||
return GetRMParams(BeMCOperand::FromVRegAddr(vregInfo->mRelTo.mVRegIdx), regA, regB, bScale, disp, errorVReg, doValidate);
|
return GetRMParams(BeMCOperand::FromVRegAddr(vregInfo->mRelTo.mVRegIdx), rmInfo, doValidate);
|
||||||
else if (vregInfo->mRelTo.mKind == BeMCOperandKind_VRegLoad)
|
else if (vregInfo->mRelTo.mKind == BeMCOperandKind_VRegLoad)
|
||||||
return GetRMParams(BeMCOperand::FromVReg(vregInfo->mRelTo.mVRegIdx), regA, regB, bScale, disp, errorVReg, doValidate);
|
return GetRMParams(BeMCOperand::FromVReg(vregInfo->mRelTo.mVRegIdx), rmInfo, doValidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
*errorVReg = operand.mVRegIdx;
|
rmInfo.mErrorVReg = operand.mVRegIdx;
|
||||||
return BeMCRMMode_Invalid;
|
rmInfo.mMode = BeMCRMMode_Invalid;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BF_ASSERT(!vregInfo->mIsExpr);
|
BF_ASSERT(!vregInfo->mIsExpr);
|
||||||
|
@ -5461,17 +5469,18 @@ BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister&
|
||||||
|
|
||||||
if ((vregInfo->mIsRetVal) && (mCompositeRetVRegIdx != -1) && (mCompositeRetVRegIdx != operand.mVRegIdx))
|
if ((vregInfo->mIsRetVal) && (mCompositeRetVRegIdx != -1) && (mCompositeRetVRegIdx != operand.mVRegIdx))
|
||||||
{
|
{
|
||||||
return GetRMParams(BeMCOperand::FromVReg(mCompositeRetVRegIdx), regA, regB, bScale, disp, errorVReg, doValidate);
|
return GetRMParams(BeMCOperand::FromVReg(mCompositeRetVRegIdx), rmInfo, doValidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
reg = mUseBP ? X64Reg_RBP : X64Reg_RSP;
|
reg = mUseBP ? X64Reg_RBP : X64Reg_RSP;
|
||||||
disp = mStackSize + vregInfo->mFrameOffset;
|
rmInfo.mDisp = mStackSize + vregInfo->mFrameOffset;
|
||||||
|
|
||||||
if (regA == X64Reg_None)
|
if (rmInfo.mRegA == X64Reg_None)
|
||||||
regA = reg;
|
rmInfo.mRegA = reg;
|
||||||
else if (regB == X64Reg_None)
|
else if (rmInfo.mRegB == X64Reg_None)
|
||||||
regB = reg;
|
rmInfo.mRegB = reg;
|
||||||
return ValidateRMResult(operand, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate);
|
rmInfo.mMode = BeMCRMMode_Direct;
|
||||||
|
return ValidateRMResult(operand, rmInfo, doValidate);
|
||||||
}
|
}
|
||||||
else if (operand.mKind == BeMCOperandKind_VRegLoad)
|
else if (operand.mKind == BeMCOperandKind_VRegLoad)
|
||||||
{
|
{
|
||||||
|
@ -5480,21 +5489,23 @@ BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister&
|
||||||
{
|
{
|
||||||
auto reg = vregInfo->mReg;
|
auto reg = vregInfo->mReg;
|
||||||
if (reg == X64Reg_None)
|
if (reg == X64Reg_None)
|
||||||
{
|
{
|
||||||
if (errorVReg != NULL)
|
rmInfo.mErrorVReg = operand.mVRegIdx;
|
||||||
*errorVReg = operand.mVRegIdx;
|
rmInfo.mMode = BeMCRMMode_Invalid;
|
||||||
return BeMCRMMode_Invalid;
|
return;
|
||||||
}
|
}
|
||||||
if (regA == X64Reg_None)
|
if (rmInfo.mRegA == X64Reg_None)
|
||||||
regA = reg;
|
rmInfo.mRegA = reg;
|
||||||
else if (regB == X64Reg_None)
|
else if (rmInfo.mRegB == X64Reg_None)
|
||||||
regB = reg;
|
rmInfo.mRegB = reg;
|
||||||
return ValidateRMResult(operand, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Deref, doValidate);
|
rmInfo.mMode = BeMCRMMode_Deref;
|
||||||
|
return ValidateRMResult(operand, rmInfo, doValidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return BeMCRMMode_Invalid;
|
rmInfo.mMode = BeMCRMMode_Invalid;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto vregInfo = mVRegInfo[operand.mVRegIdx];
|
auto vregInfo = mVRegInfo[operand.mVRegIdx];
|
||||||
|
@ -5502,101 +5513,114 @@ BeMCRMMode BeMCContext::GetRMParams(const BeMCOperand& operand, X64CPURegister&
|
||||||
|
|
||||||
if (vregInfo->mRelTo)
|
if (vregInfo->mRelTo)
|
||||||
{
|
{
|
||||||
auto oldRegA = regA;
|
auto oldRegA = rmInfo.mRegA;
|
||||||
auto result = GetRMParams(vregInfo->mRelTo, regA, regB, bScale, disp, errorVReg, false);
|
GetRMParams(vregInfo->mRelTo, rmInfo, false);
|
||||||
if (result == BeMCRMMode_Invalid)
|
if (rmInfo.mMode == BeMCRMMode_Invalid)
|
||||||
{
|
{
|
||||||
if ((errorVReg != NULL) && (*errorVReg == -1))
|
if (rmInfo.mErrorVReg == -1)
|
||||||
{
|
{
|
||||||
*errorVReg = operand.mVRegIdx;
|
rmInfo.mErrorVReg = operand.mVRegIdx;
|
||||||
}
|
}
|
||||||
return BeMCRMMode_Invalid;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == BeMCRMMode_Deref)
|
if (rmInfo.mMode == BeMCRMMode_Deref)
|
||||||
{
|
{
|
||||||
// A deref can only stand alone, and no double-derefs
|
// A deref can only stand alone, and no double-derefs
|
||||||
if ((vregInfo->mRelOffset) || (vregInfo->mRelOffsetScale != 1) || (operand.mKind == BeMCOperandKind_VRegLoad))
|
if ((vregInfo->mRelOffset) || (vregInfo->mRelOffsetScale != 1) || (operand.mKind == BeMCOperandKind_VRegLoad))
|
||||||
{
|
{
|
||||||
if (errorVReg != NULL)
|
|
||||||
{
|
BF_ASSERT(vregInfo->mRelTo.IsVRegAny());
|
||||||
BF_ASSERT(vregInfo->mRelTo.IsVRegAny());
|
rmInfo.mErrorVReg = vregInfo->mRelTo.mVRegIdx;
|
||||||
*errorVReg = vregInfo->mRelTo.mVRegIdx;
|
// For some reason we had changed this to:
|
||||||
// For some reason we had changed this to:
|
//*errorVReg = operand.mVRegIdx;
|
||||||
//*errorVReg = operand.mVRegIdx;
|
// This doesn't work, it's the deref that we want to isolate, otherwise we just end up creating another invalid expression
|
||||||
// This doesn't work, it's the deref that we want to isolate, otherwise we just end up creating another invalid expression
|
rmInfo.mMode = BeMCRMMode_Invalid;
|
||||||
}
|
return;
|
||||||
return BeMCRMMode_Invalid;
|
|
||||||
}
|
}
|
||||||
if (operand.mKind == BeMCOperandKind_VRegAddr)
|
if (operand.mKind == BeMCOperandKind_VRegAddr)
|
||||||
return ValidateRMResult(vregInfo->mRelTo, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate);
|
{
|
||||||
|
rmInfo.mMode = BeMCRMMode_Direct;
|
||||||
|
return ValidateRMResult(vregInfo->mRelTo, rmInfo, doValidate);
|
||||||
|
}
|
||||||
else if (operand.mKind == BeMCOperandKind_VReg)
|
else if (operand.mKind == BeMCOperandKind_VReg)
|
||||||
return ValidateRMResult(vregInfo->mRelTo, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Deref, doValidate);
|
{
|
||||||
|
rmInfo.mMode = BeMCRMMode_Deref;
|
||||||
|
return ValidateRMResult(vregInfo->mRelTo, rmInfo, doValidate);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
NotImpl();
|
NotImpl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vregInfo->mRelOffset)
|
if (vregInfo->mRelOffset)
|
||||||
{
|
{
|
||||||
bool relToComplicated = (regB != X64Reg_None) || (bScale != 1);
|
if (vregInfo->mRelOffsetScale != 1)
|
||||||
auto result = GetRMParams(vregInfo->mRelOffset, regA, regB, bScale, disp, errorVReg, false);
|
rmInfo.mVRegWithScaledOffset = operand.mVRegIdx;
|
||||||
if (result == BeMCRMMode_Invalid)
|
|
||||||
{
|
bool relToComplicated = (rmInfo.mRegB != X64Reg_None) || (rmInfo.mBScale != 1);
|
||||||
if (errorVReg != NULL)
|
GetRMParams(vregInfo->mRelOffset, rmInfo, false);
|
||||||
{
|
if (rmInfo.mMode == BeMCRMMode_Invalid)
|
||||||
// Pick the "most complicated" between relOffset and relTo?
|
{
|
||||||
if (relToComplicated)
|
// Pick the "most complicated" between relOffset and relTo?
|
||||||
{
|
if (relToComplicated)
|
||||||
BF_ASSERT(vregInfo->mRelTo.IsVRegAny());
|
{
|
||||||
*errorVReg = vregInfo->mRelTo.mVRegIdx;
|
BF_ASSERT(vregInfo->mRelTo.IsVRegAny());
|
||||||
}
|
rmInfo.mErrorVReg = vregInfo->mRelTo.mVRegIdx;
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
BF_ASSERT(vregInfo->mRelOffset.IsVRegAny());
|
|
||||||
*errorVReg = vregInfo->mRelOffset.mVRegIdx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return BeMCRMMode_Invalid;
|
|
||||||
}
|
|
||||||
if (result == BeMCRMMode_Deref) // Deref only allowed on relTo
|
|
||||||
{
|
|
||||||
if (errorVReg != NULL)
|
|
||||||
{
|
{
|
||||||
BF_ASSERT(vregInfo->mRelOffset.IsVRegAny());
|
BF_ASSERT(vregInfo->mRelOffset.IsVRegAny());
|
||||||
*errorVReg = vregInfo->mRelOffset.mVRegIdx;
|
rmInfo.mErrorVReg = vregInfo->mRelOffset.mVRegIdx;
|
||||||
}
|
}
|
||||||
return BeMCRMMode_Invalid;
|
rmInfo.mMode = BeMCRMMode_Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rmInfo.mMode == BeMCRMMode_Deref) // Deref only allowed on relTo
|
||||||
|
{
|
||||||
|
BF_ASSERT(vregInfo->mRelOffset.IsVRegAny());
|
||||||
|
rmInfo.mErrorVReg = vregInfo->mRelOffset.mVRegIdx;
|
||||||
|
rmInfo.mMode = BeMCRMMode_Invalid;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool success = true;
|
bool success = true;
|
||||||
if (vregInfo->mRelOffsetScale != 1)
|
if (vregInfo->mRelOffsetScale != 1)
|
||||||
{
|
{
|
||||||
if (bScale != 1)
|
if (rmInfo.mBScale != 1)
|
||||||
success = false;
|
success = false;
|
||||||
bScale = vregInfo->mRelOffsetScale;
|
rmInfo.mBScale = vregInfo->mRelOffsetScale;
|
||||||
if ((bScale != 2) && (bScale != 4) && (bScale != 8))
|
if ((rmInfo.mBScale != 2) && (rmInfo.mBScale != 4) && (rmInfo.mBScale != 8))
|
||||||
success = false;
|
success = false;
|
||||||
if (regB == X64Reg_None)
|
if (rmInfo.mRegB == X64Reg_None)
|
||||||
{
|
{
|
||||||
regB = regA;
|
rmInfo.mRegB = rmInfo.mRegA;
|
||||||
regA = X64Reg_None;
|
rmInfo.mRegA = X64Reg_None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
if ((errorVReg != NULL) && (*errorVReg == -1))
|
if (rmInfo.mErrorVReg == -1)
|
||||||
*errorVReg = operand.mVRegIdx;
|
rmInfo.mErrorVReg = operand.mVRegIdx;
|
||||||
}
|
}
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
if (operand.mKind == BeMCOperandKind_VRegLoad)
|
if (operand.mKind == BeMCOperandKind_VRegLoad)
|
||||||
return ValidateRMResult(vregInfo->mRelOffset, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Deref, doValidate);
|
{
|
||||||
|
rmInfo.mMode = BeMCRMMode_Deref;
|
||||||
|
return ValidateRMResult(vregInfo->mRelOffset, rmInfo, doValidate);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return ValidateRMResult(vregInfo->mRelOffset, regA, regB, bScale, disp, errorVReg, BeMCRMMode_Direct, doValidate);
|
{
|
||||||
|
rmInfo.mMode = BeMCRMMode_Direct;
|
||||||
|
return ValidateRMResult(vregInfo->mRelOffset, rmInfo, doValidate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return BeMCRMMode_Invalid;
|
{
|
||||||
|
rmInfo.mMode = BeMCRMMode_Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BeMCContext::DisableRegister(const BeMCOperand& operand, X64CPURegister reg)
|
void BeMCContext::DisableRegister(const BeMCOperand& operand, X64CPURegister reg)
|
||||||
|
@ -5641,24 +5665,20 @@ void BeMCContext::MarkInvalidRMRegs(const BeMCOperand& operand)
|
||||||
|
|
||||||
void BeMCContext::GetUsedRegs(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB)
|
void BeMCContext::GetUsedRegs(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB)
|
||||||
{
|
{
|
||||||
int scale = 1;
|
BeRMParamsInfo rmInfo;
|
||||||
int offset = 0;
|
GetRMParams(operand, rmInfo);
|
||||||
GetRMParams(operand, regA, regB, scale, offset, NULL);
|
if (rmInfo.mRegA != X64Reg_None)
|
||||||
if (regA != X64Reg_None)
|
regA = ResizeRegister(rmInfo.mRegA, 8);
|
||||||
regA = ResizeRegister(regA, 8);
|
if (rmInfo.mRegB != X64Reg_None)
|
||||||
if (regB != X64Reg_None)
|
regB = ResizeRegister(rmInfo.mRegB, 8);
|
||||||
regB = ResizeRegister(regB, 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BeMCRMMode BeMCContext::GetRMForm(const BeMCOperand& operand, bool& isMulti)
|
BeMCRMMode BeMCContext::GetRMForm(const BeMCOperand& operand, bool& isMulti)
|
||||||
{
|
{
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(operand, rmInfo);
|
||||||
int bScale = 1;
|
isMulti = (rmInfo.mRegB != X64Reg_None) || (rmInfo.mDisp != 0);
|
||||||
int disp = 0;
|
return rmInfo.mMode;
|
||||||
auto result = GetRMParams(operand, regA, regB, bScale, disp);
|
|
||||||
isMulti = (regB != X64Reg_None) || (disp != 0);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BeMCContext::GetValAddr(const BeMCOperand& operand, X64CPURegister& reg, int& offset)
|
void BeMCContext::GetValAddr(const BeMCOperand& operand, X64CPURegister& reg, int& offset)
|
||||||
|
@ -5935,14 +5955,11 @@ void BeMCContext::EmitModRM(int rx, BeMCOperand rm, int relocOfs)
|
||||||
if ((rm.IsVReg()) && (vregInfo->IsDirectRelToAny()))
|
if ((rm.IsVReg()) && (vregInfo->IsDirectRelToAny()))
|
||||||
return EmitModRM(rx, vregInfo->mRelTo, relocOfs);
|
return EmitModRM(rx, vregInfo->mRelTo, relocOfs);
|
||||||
|
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(rm, rmInfo);
|
||||||
int bScale = 1;
|
|
||||||
int disp = 0;
|
|
||||||
auto resultType = GetRMParams(rm, regA, regB, bScale, disp);
|
|
||||||
//BF_ASSERT(resultType != BeMCRMMode_Invalid);
|
//BF_ASSERT(resultType != BeMCRMMode_Invalid);
|
||||||
BF_ASSERT(resultType == BeMCRMMode_Deref);
|
BF_ASSERT(rmInfo.mMode == BeMCRMMode_Deref);
|
||||||
EmitModRMRel(rx, regA, regB, bScale, disp);
|
EmitModRMRel(rx, rmInfo.mRegA, rmInfo.mRegB, rmInfo.mBScale, rmInfo.mDisp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -5998,13 +6015,10 @@ void BeMCContext::EmitModRM_Addr(BeMCOperand r, BeMCOperand rm)
|
||||||
auto relVRegInfo = GetVRegInfo(vregInfo->mRelTo);
|
auto relVRegInfo = GetVRegInfo(vregInfo->mRelTo);
|
||||||
if (relVRegInfo->mRelTo)
|
if (relVRegInfo->mRelTo)
|
||||||
{
|
{
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(rm, rmInfo);
|
||||||
int bScale = 1;
|
BF_ASSERT(rmInfo.mMode != BeMCRMMode_Invalid);
|
||||||
int disp = 0;
|
EmitModRMRel(EncodeRegNum(r.mReg), rmInfo.mRegA, rmInfo.mRegB, rmInfo.mBScale, rmInfo.mDisp);
|
||||||
auto resultType = GetRMParams(rm, regA, regB, bScale, disp);
|
|
||||||
BF_ASSERT(resultType != BeMCRMMode_Invalid);
|
|
||||||
EmitModRMRel(EncodeRegNum(r.mReg), regA, regB, bScale, disp);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -8256,8 +8270,25 @@ void BeMCContext::DoActualization()
|
||||||
{
|
{
|
||||||
int vregIdx = inst->mArg0.mVRegIdx;
|
int vregIdx = inst->mArg0.mVRegIdx;
|
||||||
auto vregInfo = GetVRegInfo(inst->mArg0);
|
auto vregInfo = GetVRegInfo(inst->mArg0);
|
||||||
|
|
||||||
|
if (vregInfo->mWantsExprOffsetActualize)
|
||||||
|
{
|
||||||
|
vregInfo->mWantsExprOffsetActualize = false;
|
||||||
|
|
||||||
|
auto offsetType = GetType(vregInfo->mRelOffset);
|
||||||
|
|
||||||
|
auto scratchReg = AllocVirtualReg(offsetType, 2, false);
|
||||||
|
CreateDefineVReg(scratchReg, instIdx++);
|
||||||
|
|
||||||
|
AllocInst(BeMCInstKind_Mov, scratchReg, vregInfo->mRelOffset, instIdx++);
|
||||||
|
AllocInst(BeMCInstKind_IMul, scratchReg, BeMCOperand::FromImmediate(vregInfo->mRelOffsetScale), instIdx++);
|
||||||
|
|
||||||
|
vregInfo->mRelOffset = scratchReg;
|
||||||
|
vregInfo->mRelOffsetScale = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((vregInfo->mWantsExprActualize) || (forceMove))
|
if ((vregInfo->mWantsExprActualize) || (forceMove))
|
||||||
{
|
{
|
||||||
if (vregInfo->mDbgVariable != NULL)
|
if (vregInfo->mDbgVariable != NULL)
|
||||||
{
|
{
|
||||||
// Wait until dbgDecl so we can potentially set to VRegAddr
|
// Wait until dbgDecl so we can potentially set to VRegAddr
|
||||||
|
@ -8289,7 +8320,7 @@ void BeMCContext::DoActualization()
|
||||||
CreateDefineVReg(scratchReg, instIdx++ + 1);
|
CreateDefineVReg(scratchReg, instIdx++ + 1);
|
||||||
AllocInst(BeMCInstKind_Mov, BeMCOperand::FromVReg(vregIdx), scratchReg, instIdx++ + 1);
|
AllocInst(BeMCInstKind_Mov, BeMCOperand::FromVReg(vregIdx), scratchReg, instIdx++ + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8411,6 +8442,14 @@ bool BeMCContext::DoLegalization()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mDebugging)
|
||||||
|
{
|
||||||
|
if (inst->mArg1.mVRegIdx == 61)
|
||||||
|
{
|
||||||
|
NOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check operands
|
// Check operands
|
||||||
if ((!inst->IsPsuedo()) && (arg0Type != NULL) && (!arg0Type->IsComposite()))
|
if ((!inst->IsPsuedo()) && (arg0Type != NULL) && (!arg0Type->IsComposite()))
|
||||||
{
|
{
|
||||||
|
@ -8424,17 +8463,13 @@ bool BeMCContext::DoLegalization()
|
||||||
{
|
{
|
||||||
bool isMulti = false;
|
bool isMulti = false;
|
||||||
|
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(remappedOperand, rmInfo);
|
||||||
int bScale = 1;
|
|
||||||
int disp = 0;
|
|
||||||
int errorVReg = -1;
|
|
||||||
auto rmForm = GetRMParams(remappedOperand, regA, regB, bScale, disp, &errorVReg);
|
|
||||||
|
|
||||||
bool badOperand = false;
|
bool badOperand = false;
|
||||||
bool scratchForceReg = false;
|
bool scratchForceReg = false;
|
||||||
|
|
||||||
if (rmForm == BeMCRMMode_Invalid)
|
if (rmInfo.mMode == BeMCRMMode_Invalid)
|
||||||
{
|
{
|
||||||
badOperand = true;
|
badOperand = true;
|
||||||
scratchForceReg = true;
|
scratchForceReg = true;
|
||||||
|
@ -8455,8 +8490,8 @@ bool BeMCContext::DoLegalization()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((rmForm == BeMCRMMode_Direct) &&
|
if ((rmInfo.mMode == BeMCRMMode_Direct) &&
|
||||||
((regB != X64Reg_None) || (bScale != 1) || (disp != 0)))
|
((rmInfo.mRegB != X64Reg_None) || (rmInfo.mBScale != 1) || (rmInfo.mDisp != 0)))
|
||||||
{
|
{
|
||||||
badOperand = true;
|
badOperand = true;
|
||||||
}
|
}
|
||||||
|
@ -8502,8 +8537,13 @@ bool BeMCContext::DoLegalization()
|
||||||
|
|
||||||
if (badOperand)
|
if (badOperand)
|
||||||
{
|
{
|
||||||
//if (vregExprChangeSet.find(errorVReg) == vregExprChangeSet.end())
|
if ((rmInfo.mErrorVReg == -2) && (rmInfo.mVRegWithScaledOffset != -1))
|
||||||
if (!vregExprChangeSet.Contains(errorVReg))
|
{
|
||||||
|
auto offsetVRegInfo = mVRegInfo[rmInfo.mVRegWithScaledOffset];
|
||||||
|
offsetVRegInfo->mWantsExprOffsetActualize = true;
|
||||||
|
hasPendingActualizations = true;
|
||||||
|
}
|
||||||
|
else if (!vregExprChangeSet.Contains(rmInfo.mErrorVReg))
|
||||||
{
|
{
|
||||||
auto remappedVRegInfo = mVRegInfo[remappedOperand.mVRegIdx];
|
auto remappedVRegInfo = mVRegInfo[remappedOperand.mVRegIdx];
|
||||||
BeMCOperand savedOperand = BeMCOperand::FromVReg(remappedOperand.mVRegIdx);
|
BeMCOperand savedOperand = BeMCOperand::FromVReg(remappedOperand.mVRegIdx);
|
||||||
|
@ -8553,7 +8593,7 @@ bool BeMCContext::DoLegalization()
|
||||||
replacedOpr = true;
|
replacedOpr = true;
|
||||||
isFinalRun = false;
|
isFinalRun = false;
|
||||||
if (debugging)
|
if (debugging)
|
||||||
OutputDebugStrF(" BadOperand %d\n", errorVReg);
|
OutputDebugStrF(" BadOperand %d\n", rmInfo.mErrorVReg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9039,16 +9079,13 @@ bool BeMCContext::DoLegalization()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(inst->mArg0, rmInfo);
|
||||||
int bScale = 1;
|
bool isValid = rmInfo.mMode != BeMCRMMode_Invalid;
|
||||||
int disp = 0;
|
|
||||||
int errorVRegIdx = -1;
|
|
||||||
bool isValid = GetRMParams(inst->mArg0, regA, regB, bScale, disp, &errorVRegIdx) != BeMCRMMode_Invalid;
|
|
||||||
|
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
{
|
{
|
||||||
if (errorVRegIdx == -1)
|
if (rmInfo.mErrorVReg == -1)
|
||||||
{
|
{
|
||||||
BF_ASSERT(!vregInfo->mRelOffset);
|
BF_ASSERT(!vregInfo->mRelOffset);
|
||||||
if (vregInfo->mType->IsPointer())
|
if (vregInfo->mType->IsPointer())
|
||||||
|
@ -9074,7 +9111,7 @@ bool BeMCContext::DoLegalization()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (errorVRegIdx == -2)
|
else if (rmInfo.mErrorVReg == -2)
|
||||||
{
|
{
|
||||||
vregExprChangeSet.Add(inst->mArg0.mVRegIdx);
|
vregExprChangeSet.Add(inst->mArg0.mVRegIdx);
|
||||||
MarkInvalidRMRegs(inst->mArg0);
|
MarkInvalidRMRegs(inst->mArg0);
|
||||||
|
@ -9085,7 +9122,7 @@ bool BeMCContext::DoLegalization()
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (vregExprChangeSet.find(errorVRegIdx) != vregExprChangeSet.end())
|
//if (vregExprChangeSet.find(errorVRegIdx) != vregExprChangeSet.end())
|
||||||
if (vregExprChangeSet.Contains(errorVRegIdx))
|
if (vregExprChangeSet.Contains(rmInfo.mErrorVReg))
|
||||||
{
|
{
|
||||||
// This means we have already modified some dependent vregs, so we may be legalized already.
|
// This means we have already modified some dependent vregs, so we may be legalized already.
|
||||||
// Wait till next iteration to determine that.
|
// Wait till next iteration to determine that.
|
||||||
|
@ -9097,9 +9134,9 @@ bool BeMCContext::DoLegalization()
|
||||||
// The only valid form is [<reg>*<1/2/4/8>+<imm>]
|
// The only valid form is [<reg>*<1/2/4/8>+<imm>]
|
||||||
// If we violate that then we have to break it up
|
// If we violate that then we have to break it up
|
||||||
//if ((vregInfo->mRelOffsetScale != 1) && (vregInfo->mRelOffsetScale != 2) && (vregInfo->mRelOffsetScale != 4) && (vregInfo->mRelOffsetScale != 8))
|
//if ((vregInfo->mRelOffsetScale != 1) && (vregInfo->mRelOffsetScale != 2) && (vregInfo->mRelOffsetScale != 4) && (vregInfo->mRelOffsetScale != 8))
|
||||||
if ((!isValid) && (errorVRegIdx == inst->mArg0.mVRegIdx))
|
if ((!isValid) && (rmInfo.mErrorVReg == inst->mArg0.mVRegIdx))
|
||||||
{
|
{
|
||||||
vregExprChangeSet.Add(errorVRegIdx);
|
vregExprChangeSet.Add(rmInfo.mErrorVReg);
|
||||||
if ((vregInfo->mRelOffsetScale != 1) && (vregInfo->mRelOffsetScale != 2) && (vregInfo->mRelOffsetScale != 4) && (vregInfo->mRelOffsetScale != 8))
|
if ((vregInfo->mRelOffsetScale != 1) && (vregInfo->mRelOffsetScale != 2) && (vregInfo->mRelOffsetScale != 4) && (vregInfo->mRelOffsetScale != 8))
|
||||||
{
|
{
|
||||||
auto relOffsetType = GetType(vregInfo->mRelOffset);
|
auto relOffsetType = GetType(vregInfo->mRelOffset);
|
||||||
|
@ -9123,13 +9160,13 @@ bool BeMCContext::DoLegalization()
|
||||||
}
|
}
|
||||||
else if (!isValid)
|
else if (!isValid)
|
||||||
{
|
{
|
||||||
auto errorVRegInfo = mVRegInfo[errorVRegIdx];
|
auto errorVRegInfo = mVRegInfo[rmInfo.mErrorVReg];
|
||||||
|
|
||||||
if ((errorVRegInfo->mIsExpr) && (!errorVRegInfo->IsDirectRelTo()))
|
if ((errorVRegInfo->mIsExpr) && (!errorVRegInfo->IsDirectRelTo()))
|
||||||
{
|
{
|
||||||
errorVRegInfo->mWantsExprActualize = true;
|
errorVRegInfo->mWantsExprActualize = true;
|
||||||
hasPendingActualizations = true;
|
hasPendingActualizations = true;
|
||||||
vregExprChangeSet.Add(errorVRegIdx);
|
vregExprChangeSet.Add(rmInfo.mErrorVReg);
|
||||||
isFinalRun = false;
|
isFinalRun = false;
|
||||||
if (debugging)
|
if (debugging)
|
||||||
OutputDebugStrF(" RM not valid, actualize\n");
|
OutputDebugStrF(" RM not valid, actualize\n");
|
||||||
|
@ -9173,7 +9210,7 @@ bool BeMCContext::DoLegalization()
|
||||||
// This may be a local variable that failed to be assigned to a reg, create a scratch local with a forced reg
|
// This may be a local variable that failed to be assigned to a reg, create a scratch local with a forced reg
|
||||||
auto scratchReg = AllocVirtualReg(errorVRegInfo->mType, 2, false);
|
auto scratchReg = AllocVirtualReg(errorVRegInfo->mType, 2, false);
|
||||||
auto scratchVRegInfo = mVRegInfo[scratchReg.mVRegIdx];
|
auto scratchVRegInfo = mVRegInfo[scratchReg.mVRegIdx];
|
||||||
auto errorVReg = BeMCOperand::FromVReg(errorVRegIdx);
|
auto errorVReg = BeMCOperand::FromVReg(rmInfo.mErrorVReg);
|
||||||
|
|
||||||
if ((vregInfo->mRelTo == errorVReg) || (vregInfo->mRelOffset == errorVReg))
|
if ((vregInfo->mRelTo == errorVReg) || (vregInfo->mRelOffset == errorVReg))
|
||||||
{
|
{
|
||||||
|
@ -9223,44 +9260,39 @@ bool BeMCContext::DoLegalization()
|
||||||
auto vregInfo = mVRegInfo[vregIdx];
|
auto vregInfo = mVRegInfo[vregIdx];
|
||||||
auto dbgVar = vregInfo->mDbgVariable;
|
auto dbgVar = vregInfo->mDbgVariable;
|
||||||
|
|
||||||
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regA = X64Reg_None;
|
|
||||||
X64CPURegister regB = X64Reg_None;
|
|
||||||
int scale = 1;
|
|
||||||
int disp = 0;
|
|
||||||
BeMCRMMode mode;
|
|
||||||
|
|
||||||
if (dbgVar->mIsValue)
|
if (dbgVar->mIsValue)
|
||||||
mode = GetRMParams(inst->mArg0, regA, regB, scale, disp);
|
GetRMParams(inst->mArg0, rmInfo);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (inst->mArg0.mKind == BeMCOperandKind_VRegAddr)
|
if (inst->mArg0.mKind == BeMCOperandKind_VRegAddr)
|
||||||
mode = GetRMParams(BeMCOperand::ToLoad(inst->mArg0), regA, regB, scale, disp);
|
GetRMParams(BeMCOperand::ToLoad(inst->mArg0), rmInfo);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mode = GetRMParams(inst->mArg0, regA, regB, scale, disp);
|
GetRMParams(inst->mArg0, rmInfo);
|
||||||
if ((mode != BeMCRMMode_Direct) && (scale != 1) && (disp != 0))
|
if ((rmInfo.mMode != BeMCRMMode_Direct) && (rmInfo.mBScale != 1) && (rmInfo.mDisp != 0))
|
||||||
isInvalid = true;
|
isInvalid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == BeMCRMMode_Invalid)
|
if (rmInfo.mMode == BeMCRMMode_Invalid)
|
||||||
{
|
{
|
||||||
if (vregInfo->mType->mSize != 0)
|
if (vregInfo->mType->mSize != 0)
|
||||||
{
|
{
|
||||||
isInvalid = true;
|
isInvalid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mode == BeMCRMMode_Direct)
|
else if (rmInfo.mMode == BeMCRMMode_Direct)
|
||||||
{
|
{
|
||||||
if ((regB != X64Reg_None) || (disp != 0) || (scale != 1))
|
if ((rmInfo.mRegB != X64Reg_None) || (rmInfo.mDisp != 0) || (rmInfo.mBScale != 1))
|
||||||
{
|
{
|
||||||
isInvalid = true;
|
isInvalid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mode == BeMCRMMode_Deref)
|
else if (rmInfo.mMode == BeMCRMMode_Deref)
|
||||||
{
|
{
|
||||||
if ((regB != X64Reg_None) || (scale != 1))
|
if ((rmInfo.mRegB != X64Reg_None) || (rmInfo.mBScale != 1))
|
||||||
{
|
{
|
||||||
isInvalid = true;
|
isInvalid = true;
|
||||||
}
|
}
|
||||||
|
@ -9319,12 +9351,9 @@ bool BeMCContext::DoLegalization()
|
||||||
{
|
{
|
||||||
auto mcArg = BeMCOperand::FromEncoded(*argIdxPtr);
|
auto mcArg = BeMCOperand::FromEncoded(*argIdxPtr);
|
||||||
|
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(mcArg, rmInfo);
|
||||||
int bScale = 1;
|
if ((rmInfo.mMode != BeMCRMMode_Direct) || (rmInfo.mRegB != X64Reg_None) || (rmInfo.mRegA == X64Reg_R11))
|
||||||
int disp = 0;
|
|
||||||
auto form = GetRMParams(mcArg, regA, regB, bScale, disp);
|
|
||||||
if ((form != BeMCRMMode_Direct) || (regB != X64Reg_None) || (regA == X64Reg_R11))
|
|
||||||
{
|
{
|
||||||
BeMCOperand scratchReg = AllocVirtualReg(GetType(mcArg), 2, true);
|
BeMCOperand scratchReg = AllocVirtualReg(GetType(mcArg), 2, true);
|
||||||
auto vregInfo = GetVRegInfo(scratchReg);
|
auto vregInfo = GetVRegInfo(scratchReg);
|
||||||
|
@ -9346,12 +9375,9 @@ bool BeMCContext::DoLegalization()
|
||||||
{
|
{
|
||||||
if (inst->mArg1)
|
if (inst->mArg1)
|
||||||
{
|
{
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(inst->mArg1, rmInfo);
|
||||||
int bScale = 1;
|
if ((rmInfo.mMode != BeMCRMMode_Direct) || (rmInfo.mRegB != X64Reg_None) || (rmInfo.mRegA == X64Reg_R11) || (rmInfo.mDisp != 0))
|
||||||
int disp = 0;
|
|
||||||
auto form = GetRMParams(inst->mArg1, regA, regB, bScale, disp);
|
|
||||||
if ((form != BeMCRMMode_Direct) || (regB != X64Reg_None) || (regA == X64Reg_R11) || (disp != 0))
|
|
||||||
{
|
{
|
||||||
BeMCOperand scratchReg = AllocVirtualReg(GetType(inst->mArg1), 2, true);
|
BeMCOperand scratchReg = AllocVirtualReg(GetType(inst->mArg1), 2, true);
|
||||||
auto vregInfo = GetVRegInfo(scratchReg);
|
auto vregInfo = GetVRegInfo(scratchReg);
|
||||||
|
@ -9914,12 +9940,9 @@ bool BeMCContext::DoLegalization()
|
||||||
isFinalRun = false;
|
isFinalRun = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(inst->mArg0, rmInfo);
|
||||||
int bScale = 1;
|
if (rmInfo.mMode == BeMCRMMode_Invalid)
|
||||||
int disp = 0;
|
|
||||||
auto form = GetRMParams(inst->mArg0, regA, regB, bScale, disp);
|
|
||||||
if (form == BeMCRMMode_Invalid)
|
|
||||||
{
|
{
|
||||||
if (inst->mArg0.IsSymbol())
|
if (inst->mArg0.IsSymbol())
|
||||||
{
|
{
|
||||||
|
@ -10081,18 +10104,14 @@ bool BeMCContext::DoLegalization()
|
||||||
BeMCOperand& origOperand = (oprIdx == 0) ? inst->mArg0 : inst->mArg1;
|
BeMCOperand& origOperand = (oprIdx == 0) ? inst->mArg0 : inst->mArg1;
|
||||||
if (origOperand.IsVRegAny())
|
if (origOperand.IsVRegAny())
|
||||||
{
|
{
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(origOperand, rmInfo);
|
||||||
int bScale = 1;
|
|
||||||
int disp = 0;
|
|
||||||
int errorVReg = -1;
|
|
||||||
auto rmForm = GetRMParams(origOperand, regA, regB, bScale, disp, &errorVReg);
|
|
||||||
|
|
||||||
auto vregInfo = GetVRegInfo(origOperand);
|
auto vregInfo = GetVRegInfo(origOperand);
|
||||||
bool isValid = true;
|
bool isValid = true;
|
||||||
if (oprIdx == 1)
|
if (oprIdx == 1)
|
||||||
{
|
{
|
||||||
if (rmForm != BeMCRMMode_Direct)
|
if (rmInfo.mMode != BeMCRMMode_Direct)
|
||||||
{
|
{
|
||||||
auto newVReg = ReplaceWithNewVReg(origOperand, instIdx, true, true);
|
auto newVReg = ReplaceWithNewVReg(origOperand, instIdx, true, true);
|
||||||
auto newVRegInfo = GetVRegInfo(newVReg);
|
auto newVRegInfo = GetVRegInfo(newVReg);
|
||||||
|
@ -10111,16 +10130,12 @@ bool BeMCContext::DoLegalization()
|
||||||
BeMCOperand& origOperand = (oprIdx == 0) ? inst->mArg0 : inst->mArg1;
|
BeMCOperand& origOperand = (oprIdx == 0) ? inst->mArg0 : inst->mArg1;
|
||||||
if (origOperand.IsVRegAny())
|
if (origOperand.IsVRegAny())
|
||||||
{
|
{
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(origOperand, rmInfo);
|
||||||
int bScale = 1;
|
|
||||||
int disp = 0;
|
|
||||||
int errorVReg = -1;
|
|
||||||
auto rmForm = GetRMParams(origOperand, regA, regB, bScale, disp, &errorVReg);
|
|
||||||
|
|
||||||
auto vregInfo = GetVRegInfo(origOperand);
|
auto vregInfo = GetVRegInfo(origOperand);
|
||||||
|
|
||||||
if ((ResizeRegister(regA, 8) == X64Reg_RAX) || (ResizeRegister(regB, 8) == X64Reg_RAX))
|
if ((ResizeRegister(rmInfo.mRegA, 8) == X64Reg_RAX) || (ResizeRegister(rmInfo.mRegB, 8) == X64Reg_RAX))
|
||||||
{
|
{
|
||||||
if (!vregInfo->mIsExpr)
|
if (!vregInfo->mIsExpr)
|
||||||
{
|
{
|
||||||
|
@ -10150,7 +10165,7 @@ bool BeMCContext::DoLegalization()
|
||||||
bool isValid = true;
|
bool isValid = true;
|
||||||
if (oprIdx == 1)
|
if (oprIdx == 1)
|
||||||
{
|
{
|
||||||
if (rmForm != BeMCRMMode_Direct)
|
if (rmInfo.mMode != BeMCRMMode_Direct)
|
||||||
{
|
{
|
||||||
int safeIdx = FindSafeInstInsertPos(instIdx, true);
|
int safeIdx = FindSafeInstInsertPos(instIdx, true);
|
||||||
auto newVReg = ReplaceWithNewVReg(origOperand, safeIdx, true, true);
|
auto newVReg = ReplaceWithNewVReg(origOperand, safeIdx, true, true);
|
||||||
|
@ -11396,14 +11411,11 @@ void BeMCContext::DoRegFinalization()
|
||||||
instEndIdx = instIdx;
|
instEndIdx = instIdx;
|
||||||
if (inst->mKind == BeMCInstKind_Call)
|
if (inst->mKind == BeMCInstKind_Call)
|
||||||
{
|
{
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(inst->mArg0, rmInfo);
|
||||||
int bScale = 1;
|
|
||||||
int disp = 0;
|
|
||||||
GetRMParams(inst->mArg0, regA, regB, bScale, disp);
|
|
||||||
|
|
||||||
if (((regA != X64Reg_None) && (regA != X64Reg_RAX) && (regStomped[regA])) ||
|
if (((rmInfo.mRegA != X64Reg_None) && (rmInfo.mRegA != X64Reg_RAX) && (regStomped[rmInfo.mRegA])) ||
|
||||||
((regB != X64Reg_None) && (regStomped[regB])))
|
((rmInfo.mRegB != X64Reg_None) && (regStomped[rmInfo.mRegB])))
|
||||||
{
|
{
|
||||||
BF_ASSERT(pass == 0);
|
BF_ASSERT(pass == 0);
|
||||||
|
|
||||||
|
@ -12159,11 +12171,8 @@ bool BeMCContext::EmitPackedXMMInst(BeMCInstForm instForm, BeMCInst* inst, uint8
|
||||||
|
|
||||||
void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src)
|
void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src)
|
||||||
{
|
{
|
||||||
X64CPURegister regA = X64Reg_None;
|
BeRMParamsInfo rmInfo;
|
||||||
X64CPURegister regB = X64Reg_None;
|
GetRMParams(dest, rmInfo);
|
||||||
int bScale = 1;
|
|
||||||
int disp = 0;
|
|
||||||
auto form = GetRMParams(dest, regA, regB, bScale, disp);
|
|
||||||
|
|
||||||
BF_ASSERT(src.mKind == BeMCOperandKind_ConstAgg);
|
BF_ASSERT(src.mKind == BeMCOperandKind_ConstAgg);
|
||||||
auto aggConstant = src.mConstant;
|
auto aggConstant = src.mConstant;
|
||||||
|
@ -12262,21 +12271,21 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src)
|
||||||
if (repSize >= 16)
|
if (repSize >= 16)
|
||||||
{
|
{
|
||||||
bool regSaved = false;
|
bool regSaved = false;
|
||||||
if ((regA == X64Reg_RAX) ||
|
if ((rmInfo.mRegA == X64Reg_RAX) ||
|
||||||
(regA == X64Reg_RCX) ||
|
(rmInfo.mRegA == X64Reg_RCX) ||
|
||||||
(regA == X64Reg_RDI))
|
(rmInfo.mRegA == X64Reg_RDI))
|
||||||
{
|
{
|
||||||
BF_ASSERT(regB == X64Reg_None);
|
BF_ASSERT(rmInfo.mRegB == X64Reg_None);
|
||||||
// mov R11, regA
|
// mov R11, regA
|
||||||
Emit(0x49); Emit(0x89);
|
Emit(0x49); Emit(0x89);
|
||||||
EmitModRM(BeMCOperand::FromReg(regA), BeMCOperand::FromReg(X64Reg_R11));
|
EmitModRM(BeMCOperand::FromReg(rmInfo.mRegA), BeMCOperand::FromReg(X64Reg_R11));
|
||||||
regSaved = true;
|
regSaved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// lea rdi, <dest+curOfs>
|
// lea rdi, <dest+curOfs>
|
||||||
EmitREX(BeMCOperand::FromReg(X64Reg_RDI), dest, true);
|
EmitREX(BeMCOperand::FromReg(X64Reg_RDI), dest, true);
|
||||||
Emit(0x8D);
|
Emit(0x8D);
|
||||||
EmitModRMRel(EncodeRegNum(X64Reg_RDI), regA, regB, 1, disp + curOfs);
|
EmitModRMRel(EncodeRegNum(X64Reg_RDI), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + curOfs);
|
||||||
|
|
||||||
// mov al, <val>
|
// mov al, <val>
|
||||||
Emit(0xB0); Emit(val);
|
Emit(0xB0); Emit(val);
|
||||||
|
@ -12292,7 +12301,7 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src)
|
||||||
{
|
{
|
||||||
// mov regA, R11
|
// mov regA, R11
|
||||||
Emit(0x4C); Emit(0x89);
|
Emit(0x4C); Emit(0x89);
|
||||||
EmitModRM(BeMCOperand::FromReg(X64Reg_R11), BeMCOperand::FromReg(regA));
|
EmitModRM(BeMCOperand::FromReg(X64Reg_R11), BeMCOperand::FromReg(rmInfo.mRegA));
|
||||||
}
|
}
|
||||||
|
|
||||||
curOfs += repSize;
|
curOfs += repSize;
|
||||||
|
@ -12306,7 +12315,7 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src)
|
||||||
// mov <dest+curOfs>, R11
|
// mov <dest+curOfs>, R11
|
||||||
EmitREX(BeMCOperand::FromReg(X64Reg_R11), dest, true);
|
EmitREX(BeMCOperand::FromReg(X64Reg_R11), dest, true);
|
||||||
Emit(0x89);
|
Emit(0x89);
|
||||||
EmitModRMRel(EncodeRegNum(X64Reg_R11), regA, regB, 1, disp + curOfs);
|
EmitModRMRel(EncodeRegNum(X64Reg_R11), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + curOfs);
|
||||||
curOfs += 8;
|
curOfs += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12319,7 +12328,7 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src)
|
||||||
// mov <dest+curOfs>, R11d
|
// mov <dest+curOfs>, R11d
|
||||||
EmitREX(BeMCOperand::FromReg(X64Reg_R11D), dest, false);
|
EmitREX(BeMCOperand::FromReg(X64Reg_R11D), dest, false);
|
||||||
Emit(0x89);
|
Emit(0x89);
|
||||||
EmitModRMRel(EncodeRegNum(X64Reg_R11D), regA, regB, 1, disp + curOfs);
|
EmitModRMRel(EncodeRegNum(X64Reg_R11D), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + curOfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; curOfs <= memSize - 2; curOfs += 2)
|
for (; curOfs <= memSize - 2; curOfs += 2)
|
||||||
|
@ -12331,7 +12340,7 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src)
|
||||||
// mov <dest+curOfs>, R11w
|
// mov <dest+curOfs>, R11w
|
||||||
Emit(0x66); EmitREX(BeMCOperand::FromReg(X64Reg_R11W), dest, false);
|
Emit(0x66); EmitREX(BeMCOperand::FromReg(X64Reg_R11W), dest, false);
|
||||||
Emit(0x89);
|
Emit(0x89);
|
||||||
EmitModRMRel(EncodeRegNum(X64Reg_R11W), regA, regB, 1, disp + curOfs);
|
EmitModRMRel(EncodeRegNum(X64Reg_R11W), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + curOfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; curOfs <= memSize - 1; curOfs += 1)
|
for (; curOfs <= memSize - 1; curOfs += 1)
|
||||||
|
@ -12343,7 +12352,7 @@ void BeMCContext::EmitAggMov(const BeMCOperand& dest, const BeMCOperand& src)
|
||||||
// mov <dest+curOfs>, R11b
|
// mov <dest+curOfs>, R11b
|
||||||
EmitREX(BeMCOperand::FromReg(X64Reg_R11B), dest, false);
|
EmitREX(BeMCOperand::FromReg(X64Reg_R11B), dest, false);
|
||||||
Emit(0x89 - 1);
|
Emit(0x89 - 1);
|
||||||
EmitModRMRel(EncodeRegNum(X64Reg_R11B), regA, regB, 1, disp + curOfs);
|
EmitModRMRel(EncodeRegNum(X64Reg_R11B), rmInfo.mRegA, rmInfo.mRegB, 1, rmInfo.mDisp + curOfs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15470,7 +15479,7 @@ void BeMCContext::Generate(BeFunction* function)
|
||||||
mDbgPreferredRegs[32] = X64Reg_R8;*/
|
mDbgPreferredRegs[32] = X64Reg_R8;*/
|
||||||
|
|
||||||
//mDbgPreferredRegs[8] = X64Reg_RAX;
|
//mDbgPreferredRegs[8] = X64Reg_RAX;
|
||||||
//mDebugging = (function->mName == "?FindSourceViewPanel@IDEApp@IDE@bf@@QEAAPEAVSourceViewPanel@ui@23@PEAVString@System@3@@Z");
|
//mDebugging = (function->mName == "?Main@Program@bf@@SAXPEAV?$Array1@PEAVString@System@bf@@@System@2@@Z");
|
||||||
// || (function->mName == "?__BfStaticCtor@roboto_font@Drawing@ClassicUO_assistant@bf@@SAXXZ")
|
// || (function->mName == "?__BfStaticCtor@roboto_font@Drawing@ClassicUO_assistant@bf@@SAXXZ")
|
||||||
// || (function->mName == "?Hey@Blurg@bf@@SAXXZ")
|
// || (function->mName == "?Hey@Blurg@bf@@SAXXZ")
|
||||||
// ;
|
// ;
|
||||||
|
|
|
@ -788,6 +788,7 @@ public:
|
||||||
bool mDoConservativeLife; // Keep alive through 'init' as well as 'uninit'
|
bool mDoConservativeLife; // Keep alive through 'init' as well as 'uninit'
|
||||||
bool mIsExpr; // Not an actual value, something like 'mRelTo + mRelOffset'
|
bool mIsExpr; // Not an actual value, something like 'mRelTo + mRelOffset'
|
||||||
bool mWantsExprActualize;
|
bool mWantsExprActualize;
|
||||||
|
bool mWantsExprOffsetActualize;
|
||||||
bool mChainLifetimeEnd; // Kill relTo's when we are killed
|
bool mChainLifetimeEnd; // Kill relTo's when we are killed
|
||||||
bool mForceMem;
|
bool mForceMem;
|
||||||
bool mForceReg;
|
bool mForceReg;
|
||||||
|
@ -827,6 +828,7 @@ public:
|
||||||
mType = NULL;
|
mType = NULL;
|
||||||
mIsExpr = false;
|
mIsExpr = false;
|
||||||
mWantsExprActualize = false;
|
mWantsExprActualize = false;
|
||||||
|
mWantsExprOffsetActualize = false;
|
||||||
mChainLifetimeEnd = false;
|
mChainLifetimeEnd = false;
|
||||||
mFrameOffset = INT_MIN;
|
mFrameOffset = INT_MIN;
|
||||||
mHasDynLife = false;
|
mHasDynLife = false;
|
||||||
|
@ -1274,6 +1276,30 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BeRMParamsInfo
|
||||||
|
{
|
||||||
|
X64CPURegister mRegA;
|
||||||
|
X64CPURegister mRegB;
|
||||||
|
int mBScale;
|
||||||
|
int mDisp;
|
||||||
|
BeMCRMMode mMode;
|
||||||
|
|
||||||
|
int mErrorVReg;
|
||||||
|
int mVRegWithScaledOffset;
|
||||||
|
|
||||||
|
BeRMParamsInfo()
|
||||||
|
{
|
||||||
|
mRegA = X64Reg_None;
|
||||||
|
mRegB = X64Reg_None;
|
||||||
|
mBScale = 1;
|
||||||
|
mDisp = 0;
|
||||||
|
mMode = BeMCRMMode_Invalid;
|
||||||
|
|
||||||
|
mErrorVReg = -1;
|
||||||
|
mVRegWithScaledOffset = -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// This class only processes one function per instantiation
|
// This class only processes one function per instantiation
|
||||||
class BeMCContext
|
class BeMCContext
|
||||||
{
|
{
|
||||||
|
@ -1409,8 +1435,8 @@ public:
|
||||||
|
|
||||||
uint8 EncodeRegNum(X64CPURegister regNum);
|
uint8 EncodeRegNum(X64CPURegister regNum);
|
||||||
int GetRegSize(int regNum);
|
int GetRegSize(int regNum);
|
||||||
BeMCRMMode ValidateRMResult(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB, int& bScale, int& disp, int* errorVReg, BeMCRMMode result, bool doValidate = true);
|
void ValidateRMResult(const BeMCOperand& operand, BeRMParamsInfo& rmInfo, bool doValidate = true);
|
||||||
BeMCRMMode GetRMParams(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB, int& bScale, int& disp, int* errorVReg = NULL, bool doValidate = true);
|
void GetRMParams(const BeMCOperand& operand, BeRMParamsInfo& rmInfo, bool doValidate = true);
|
||||||
void DisableRegister(const BeMCOperand& operand, X64CPURegister reg);
|
void DisableRegister(const BeMCOperand& operand, X64CPURegister reg);
|
||||||
void MarkInvalidRMRegs(const BeMCOperand& operand);
|
void MarkInvalidRMRegs(const BeMCOperand& operand);
|
||||||
void GetUsedRegs(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB); // Expands regs
|
void GetUsedRegs(const BeMCOperand& operand, X64CPURegister& regA, X64CPURegister& regB); // Expands regs
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue