GP-2292: The Decompiler now supports simplification of more forms of

optimized modulo/remainder calculations
This commit is contained in:
caheckman 2022-09-02 16:23:08 -04:00 committed by Ryan Kurtz
parent a438a1e1ea
commit 7a2810a649
6 changed files with 688 additions and 2 deletions

View file

@ -5065,9 +5065,14 @@ void ActionDatabase::universalAction(Architecture *conf)
actprop->addRule( new RuleDivTermAdd2("analysis") );
actprop->addRule( new RuleDivOpt("analysis") );
actprop->addRule( new RuleSignForm("analysis") );
actprop->addRule( new RuleSignForm2("analysis") );
actprop->addRule( new RuleSignDiv2("analysis") );
actprop->addRule( new RuleDivChain("analysis") );
actprop->addRule( new RuleSignNearMult("analysis") );
actprop->addRule( new RuleModOpt("analysis") );
actprop->addRule( new RuleSignMod2nOpt("analysis") );
actprop->addRule( new RuleSignMod2nOpt2("analysis") );
actprop->addRule( new RuleSignMod2Opt("analysis") );
actprop->addRule( new RuleSwitchSingle("analysis") );
actprop->addRule( new RuleCondNegate("analysis") );
actprop->addRule( new RuleBoolNegate("analysis") );

View file

@ -2957,7 +2957,7 @@ int4 RuleMultiCollapse::applyOp(PcodeOp *op,Funcdata &data)
else
nofunc = true; // Unwritten cannot match by functional equal
}
else if (*defcopyr == *copyr) continue; // A matching branch
else if (defcopyr == copyr) continue; // A matching branch
else if ((defcopyr!=copyr)&&(!nofunc)&&functionalEquality(defcopyr,copyr)) {
// Cannot match MULTIEQUAL by functional equality
// if (nofunc) return 0; // Not allowed to match by func equal
@ -6710,6 +6710,11 @@ int4 RuleSubRight::applyOp(PcodeOp *op,Funcdata &data)
if (outvn->getSize() + c == a->getSize()) {
// If SUB is "hi" lump the SUB and shift together
d += lone->getIn(1)->getOffset();
if (d >= a->getSize() * 8) {
if (opc2 == CPUI_INT_RIGHT)
return 0; // Result should have been 0
d = a->getSize() * 8 - 1; // sign extraction
}
data.opUnlink(op);
op = lone;
data.opSetOpcode(op,CPUI_SUBPIECE);
@ -6932,7 +6937,7 @@ int4 RuleSubNormal::applyOp(PcodeOp *op,Funcdata &data)
return 1;
}
else
k = insize-c-outsize; // Or we can shrunk the cut
k = insize-c-outsize; // Or we can shrink the cut
}
// if n == k*8, then a shift is unnecessary
@ -6943,6 +6948,11 @@ int4 RuleSubNormal::applyOp(PcodeOp *op,Funcdata &data)
data.opSetInput(op,data.newConstant(4,c),1);
return 1;
}
else if (n >= outsize * 8) {
n = outsize * 8; // Can only shift so far
if (opc == CPUI_INT_SRIGHT)
n -= 1;
}
PcodeOp *newop = data.newOp(2,op->getAddr());
data.opSetOpcode(newop,CPUI_SUBPIECE);
@ -7570,6 +7580,59 @@ int4 RuleSignDiv2::applyOp(PcodeOp *op,Funcdata &data)
return 1;
}
/// \class RuleDivChain
/// \brief Collapse two consecutive divisions: `(x / c1) / c2 => x / (c1*c2)`
void RuleDivChain::getOpList(vector<uint4> &oplist) const
{
oplist.push_back(CPUI_INT_DIV);
oplist.push_back(CPUI_INT_SDIV);
}
int4 RuleDivChain::applyOp(PcodeOp *op,Funcdata &data)
{
OpCode opc2 = op->code();
Varnode *constVn2 = op->getIn(1);
if (!constVn2->isConstant()) return 0;
Varnode *vn = op->getIn(0);
if (!vn->isWritten()) return 0;
PcodeOp *divOp = vn->getDef();
OpCode opc1 = divOp->code();
if (opc1 != opc2 && (opc2 != CPUI_INT_DIV || opc1 != CPUI_INT_RIGHT))
return 0;
Varnode *constVn1 = divOp->getIn(1);
if (!constVn1->isConstant()) return 0;
// If the intermediate result is being used elsewhere, don't apply
// Its likely collapsing the divisions will interfere with the modulo rules
if (vn->loneDescend() == (PcodeOp *)0) return 0;
uintb val1;
if (opc1 == opc2) {
val1 = constVn1->getOffset();
}
else { // Unsigned case with INT_RIGHT
int4 sa = constVn1->getOffset();
val1 = 1;
val1 <<= sa;
}
Varnode *baseVn = divOp->getIn(0);
if (baseVn->isFree()) return 0;
int4 sz = vn->getSize();
uintb val2 = constVn2->getOffset();
uintb resval = (val1 * val2) & calc_mask(sz);
if (resval == 0) return 0;
if (signbit_negative(val1, sz))
val1 = (~val1 + 1) & calc_mask(sz);
if (signbit_negative(val2, sz))
val2 = (~val2 + 1) & calc_mask(sz);
int4 bitcount = mostsigbit_set(val1) + mostsigbit_set(val2) + 2;
if (opc2 == CPUI_INT_DIV && bitcount > sz * 8 ) return 0; // Unsigned overflow
if (opc2 == CPUI_INT_SDIV && bitcount > sz * 8 - 2) return 0; // Signed overflow
data.opSetInput(op, baseVn, 0);
data.opSetInput(op,data.newConstant(sz, resval), 1);
return 1;
}
/// \class RuleSignForm
/// \brief Normalize sign extraction: `sub(sext(V),c) => V s>> 31`
void RuleSignForm::getOpList(vector<uint4> &oplist) const
@ -7601,6 +7664,63 @@ int4 RuleSignForm::applyOp(PcodeOp *op,Funcdata &data)
return 1;
}
/// \class RuleSignForm2
/// \brief Normalize sign extraction: `sub(sext(V) * small,c) s>> 31 => V s>> 31`
///
/// V and small must be small enough so that there is no overflow in the INT_MULT.
/// The SUBPIECE must be extracting the high part of the INT_MULT.
void RuleSignForm2::getOpList(vector<uint4> &oplist) const
{
oplist.push_back(CPUI_INT_SRIGHT);
}
int4 RuleSignForm2::applyOp(PcodeOp *op,Funcdata &data)
{
Varnode *constVn = op->getIn(1);
if (!constVn->isConstant()) return 0;
Varnode *inVn = op->getIn(0);
int4 sizeout = inVn->getSize();
if ((int4)constVn->getOffset() != sizeout*8 -1) return 0;
if (!inVn->isWritten()) return 0;
PcodeOp *subOp = inVn->getDef();
if (subOp->code() != CPUI_SUBPIECE) return 0;
int4 c = subOp->getIn(1)->getOffset();
Varnode *multOut = subOp->getIn(0);
int4 multSize = multOut->getSize();
if (c + sizeout != multSize) return 0; // Must be extracting high part
if (!multOut->isWritten()) return 0;
PcodeOp *multOp = multOut->getDef();
if (multOp->code() != CPUI_INT_MULT) return 0;
int4 slot;
PcodeOp *sextOp;
for(slot=0;slot<2;++slot) { // Search for the INT_SEXT
Varnode *vn = multOp->getIn(slot);
if (!vn->isWritten()) continue;
sextOp = vn->getDef();
if (sextOp->code() == CPUI_INT_SEXT) break;
}
if (slot > 1) return 0;
Varnode *a = sextOp->getIn(0);
if (a->isFree() || a->getSize() != sizeout) return 0;
Varnode *otherVn = multOp->getIn(1-slot);
// otherVn must be a positive integer and small enough so the INT_MULT can't overflow into the sign-bit
if (otherVn->isConstant()) {
if (otherVn->getOffset() > calc_mask(sizeout)) return 0;
if (2 * sizeout > multSize) return 0;
}
else if (otherVn->isWritten()) {
PcodeOp *zextOp = otherVn->getDef();
if (zextOp->code() != CPUI_INT_ZEXT) return 0;
if (zextOp->getIn(0)->getSize() + sizeout > multSize) return 0;
}
else
return 0;
data.opSetInput(op, a, 0);
return 0;
}
/// \class RuleSignNearMult
/// \brief Simplify division form: `(V + (V s>> 0x1f)>>(32-n)) & (-1<<n) => (V s/ 2^n) * 2^n`
void RuleSignNearMult::getOpList(vector<uint4> &oplist) const
@ -7723,6 +7843,338 @@ int4 RuleModOpt::applyOp(PcodeOp *op,Funcdata &data)
return 0;
}
/// \class RuleSignMod2nOpt
/// \brief Convert INT_SREM forms: `(V + (sign >> (64-n)) & (2^n-1)) - (sign >> (64-n) => V s% 2^n`
///
/// Note: `sign = V s>> 63` The INT_AND may be performed on a truncated result and then reextended.
void RuleSignMod2nOpt::getOpList(vector<uint4> &oplist) const
{
oplist.push_back(CPUI_INT_RIGHT);
}
int4 RuleSignMod2nOpt::applyOp(PcodeOp *op,Funcdata &data)
{
if (!op->getIn(1)->isConstant()) return 0;
int4 shiftAmt = op->getIn(1)->getOffset();
Varnode *a = checkSignExtraction(op->getIn(0));
if (a == (Varnode *)0 || a->isFree()) return 0;
Varnode *correctVn = op->getOut();
int4 n = a->getSize() * 8 - shiftAmt;
uintb mask = 1;
mask = (mask << n) - 1;
list<PcodeOp *>::const_iterator iter;
for(iter=correctVn->beginDescend();iter!=correctVn->endDescend();++iter) {
PcodeOp *multop = *iter;
if (multop->code() != CPUI_INT_MULT) continue;
Varnode *negone = multop->getIn(1);
if (!negone->isConstant()) continue;
if (negone->getOffset() != calc_mask(correctVn->getSize())) continue;
PcodeOp *baseOp = multop->getOut()->loneDescend();
if (baseOp == (PcodeOp *)0) continue;
if (baseOp->code() != CPUI_INT_ADD) continue;
int4 slot = 1 - baseOp->getSlot(multop->getOut());
Varnode *andOut = baseOp->getIn(slot);
if (!andOut->isWritten()) continue;
PcodeOp *andOp = andOut->getDef();
int4 truncSize = -1;
if (andOp->code() == CPUI_INT_ZEXT) { // Look for intervening extension after INT_AND
andOut = andOp->getIn(0);
if (!andOut->isWritten()) continue;
andOp = andOut->getDef();
if (andOp->code() != CPUI_INT_AND) continue;
truncSize = andOut->getSize(); // If so we have a truncated form
}
else if (andOp->code() != CPUI_INT_AND)
continue;
Varnode *constVn = andOp->getIn(1);
if (!constVn->isConstant()) continue;
if (constVn->getOffset() != mask) continue;
Varnode *addOut = andOp->getIn(0);
if (!addOut->isWritten()) continue;
PcodeOp *addOp = addOut->getDef();
if (addOp->code() != CPUI_INT_ADD) continue;
// Search for "a" as one of the inputs to addOp
int4 aSlot;
for(aSlot=0;aSlot < 2;++aSlot) {
Varnode *vn = addOp->getIn(aSlot);
if (truncSize >= 0) {
if (!vn->isWritten()) continue;
PcodeOp *subOp = vn->getDef();
if (subOp->code() != CPUI_SUBPIECE) continue;
if (subOp->getIn(1)->getOffset() != 0) continue;
vn = subOp->getIn(0);
}
if (a == vn) break;
}
if (aSlot > 1) continue;
// Verify that the other input to addOp is an INT_RIGHT by shiftAmt
Varnode *extVn = addOp->getIn(1-aSlot);
if (!extVn->isWritten()) continue;
PcodeOp *shiftOp = extVn->getDef();
if (shiftOp->code() != CPUI_INT_RIGHT) continue;
constVn = shiftOp->getIn(1);
if (!constVn->isConstant()) continue;
int4 shiftval = constVn->getOffset();
if (truncSize >= 0)
shiftval += (a->getSize() - truncSize) * 8;
if (shiftval != shiftAmt) continue;
// Verify that the input to INT_RIGHT is a sign extraction of "a"
extVn = checkSignExtraction(shiftOp->getIn(0));
if (extVn == (Varnode *)0) continue;
if (truncSize >= 0) {
if (!extVn->isWritten()) continue;
PcodeOp *subOp = extVn->getDef();
if (subOp->code() != CPUI_SUBPIECE) continue;
if ((int4)subOp->getIn(1)->getOffset() != truncSize) continue;
extVn = subOp->getIn(0);
}
if (a != extVn) continue;
data.opSetOpcode(baseOp, CPUI_INT_SREM);
data.opSetInput(baseOp, a, 0);
data.opSetInput(baseOp, data.newConstant(a->getSize(), mask+1), 1);
return 1;
}
return 0;
}
/// \brief Verify that the given Varnode is a sign extraction of the form `V s>> 63`
///
/// If not, null is returned. Otherwise the Varnode whose sign is extracted is returned.
/// \param outVn is the given Varnode
/// \return the Varnode being extracted or null
Varnode *RuleSignMod2nOpt::checkSignExtraction(Varnode *outVn)
{
if (!outVn->isWritten()) return 0;
PcodeOp *signOp = outVn->getDef();
if (signOp->code() != CPUI_INT_SRIGHT)
return (Varnode *)0;
Varnode *constVn = signOp->getIn(1);
if (!constVn->isConstant())
return (Varnode *)0;
int4 val = constVn->getOffset();
Varnode *resVn = signOp->getIn(0);
int4 insize = resVn->getSize();
if (val != insize*8 - 1)
return (Varnode *)0;
return resVn;
}
/// \class RuleSignMod2Opt
/// \brief Convert INT_SREM form: `(V - sign)&1 + sign => V s% 2`
///
/// Note: `sign = V s>> 63` The INT_AND may be performed on a truncated result and then reextended.
/// This is a specialized form of RuleSignMod2nOpt.
void RuleSignMod2Opt::getOpList(vector<uint4> &oplist) const
{
oplist.push_back(CPUI_INT_AND);
}
int4 RuleSignMod2Opt::applyOp(PcodeOp *op,Funcdata &data)
{
Varnode *constVn = op->getIn(1);
if (!constVn->isConstant()) return 0;
if (constVn->getOffset() != 1) return 0;
Varnode *addOut = op->getIn(0);
if (!addOut->isWritten()) return 0;
PcodeOp *addOp = addOut->getDef();
if (addOp->code() != CPUI_INT_ADD) return 0;
int4 multSlot;
PcodeOp *multOp;
bool trunc = false;
for(multSlot = 0;multSlot < 2;++multSlot) {
Varnode *vn = addOp->getIn(multSlot);
if (!vn->isWritten()) continue;
multOp = vn->getDef();
if (multOp->code() != CPUI_INT_MULT) continue;
constVn = multOp->getIn(1);
if (!constVn->isConstant()) continue;
if (constVn->getOffset() == calc_mask(constVn->getSize())) break; // Check for INT_MULT by -1
}
if (multSlot > 1) return 0;
Varnode *base = RuleSignMod2nOpt::checkSignExtraction(multOp->getIn(0));
if (base == (Varnode *)0) return 0;
Varnode *otherBase = addOp->getIn(1-multSlot);
if (base != otherBase) {
if (!base->isWritten() || !otherBase->isWritten()) return 0;
PcodeOp *subOp = base->getDef();
if (subOp->code() != CPUI_SUBPIECE) return 0;
int4 truncAmt = subOp->getIn(1)->getOffset();
if (truncAmt + base->getSize() != subOp->getIn(0)->getSize()) return 0; // Must truncate all but high part
base = subOp->getIn(0);
subOp = otherBase->getDef();
if (subOp->code() != CPUI_SUBPIECE) return 0;
if (subOp->getIn(1)->getOffset() != 0) return 0;
otherBase = subOp->getIn(0);
if (otherBase != base) return 0;
trunc = true;
}
if (base->isFree()) return 0;
Varnode *andOut = op->getOut();
if (trunc) {
PcodeOp *extOp = andOut->loneDescend();
if (extOp == (PcodeOp *)0 || extOp->code() != CPUI_INT_ZEXT) return 0;
andOut = extOp->getOut();
}
list<PcodeOp *>::const_iterator iter;
for(iter=andOut->beginDescend();iter!=andOut->endDescend();++iter) {
PcodeOp *rootOp = *iter;
if (rootOp->code() != CPUI_INT_ADD) continue;
int4 slot = rootOp->getSlot(andOut);
otherBase = RuleSignMod2nOpt::checkSignExtraction(rootOp->getIn(1-slot));
if (otherBase != base) continue;
data.opSetOpcode(rootOp, CPUI_INT_SREM);
data.opSetInput(rootOp,base,0);
data.opSetInput(rootOp,data.newConstant(base->getSize(), 2),1);
return 1;
}
return 0;
}
/// \class RuleSignMod2nOpt2
/// \brief Convert INT_SREM form: `V - (Vadj & ~(2^n-1)) => V s% 2^n`
///
/// Note: `Vadj = (V<0) ? V + 2^n-1 : V`
void RuleSignMod2nOpt2::getOpList(vector<uint4> &oplist) const
{
oplist.push_back(CPUI_INT_MULT);
}
int4 RuleSignMod2nOpt2::applyOp(PcodeOp *op,Funcdata &data)
{
Varnode *constVn = op->getIn(1);
if (!constVn->isConstant()) return 0;
uintb mask = calc_mask(constVn->getSize());
if (constVn->getOffset() != mask) return 0; // Must be INT_MULT by -1
Varnode *andOut = op->getIn(0);
if (!andOut->isWritten()) return 0;
PcodeOp *andOp = andOut->getDef();
if (andOp->code() != CPUI_INT_AND) return 0;
constVn = andOp->getIn(1);
if (!constVn->isConstant()) return 0;
uintb npow = (~constVn->getOffset() + 1) & mask;
if (popcount(npow) != 1) return 0; // constVn must be of form 11111..000..
if (npow == 1) return 0;
Varnode *adjVn = andOp->getIn(0);
if (!adjVn->isWritten()) return 0;
PcodeOp *adjOp = adjVn->getDef();
Varnode *base;
if (adjOp->code() == CPUI_INT_ADD) {
if (npow != 2) return 0; // Special mod 2 form
base = checkSignExtForm(adjOp);
}
else if (adjOp->code() == CPUI_MULTIEQUAL) {
base = checkMultiequalForm(adjOp, npow);
}
else
return 0;
if (base == (Varnode *)0) return 0;
if (base->isFree()) return 0;
Varnode *multOut = op->getOut();
list<PcodeOp *>::const_iterator iter;
for(iter=multOut->beginDescend();iter!=multOut->endDescend();++iter) {
PcodeOp *rootOp = *iter;
if (rootOp->code() != CPUI_INT_ADD) continue;
int4 slot = rootOp->getSlot(multOut);
if (rootOp->getIn(1-slot) != base) continue;
if (slot == 0)
data.opSetInput(rootOp,base,0);
data.opSetInput(rootOp, data.newConstant(base->getSize(),npow), 1);
data.opSetOpcode(rootOp, CPUI_INT_SREM);
return 1;
}
return 0;
}
/// \brief Verify a form of `V - (V s>> 0x3f)`
///
/// \param op is the possible root INT_ADD of the form
/// \return the Varnode V in the form, or null if the form doesn't match
Varnode *RuleSignMod2nOpt2::checkSignExtForm(PcodeOp *op)
{
int4 slot;
for(slot=0;slot<2;++slot) {
Varnode *minusVn = op->getIn(slot);
if (!minusVn->isWritten()) continue;
PcodeOp *multOp = minusVn->getDef();
if (multOp->code() != CPUI_INT_MULT) continue;
Varnode *constVn = multOp->getIn(1);
if (!constVn->isConstant()) continue;
if (constVn->getOffset() != calc_mask(constVn->getSize())) continue;
Varnode *base = op->getIn(1-slot);
Varnode *signExt = multOp->getIn(0);
if (!signExt->isWritten()) continue;
PcodeOp *shiftOp = signExt->getDef();
if (shiftOp->code() != CPUI_INT_SRIGHT) continue;
if (shiftOp->getIn(0) != base) continue;
constVn = shiftOp->getIn(1);
if (!constVn->isConstant()) continue;
if ((int4)constVn->getOffset() != 8*base->getSize() - 1) continue;
return base;
}
return (Varnode *)0;
}
/// \brief Verify an \e if block like `V = (V s< 0) ? V + 2^n-1 : V`
///
/// \param op is the MULTIEQUAL
/// \param npos is the constant 2^n
/// \return the Varnode V in the form, or null if the form doesn't match
Varnode *RuleSignMod2nOpt2::checkMultiequalForm(PcodeOp *op,uintb npow)
{
if (op->numInput() != 2) return (Varnode *)0;
npow -= 1; // 2^n - 1
int4 slot;
Varnode *base;
for(slot=0;slot<op->numInput();++slot) {
Varnode *addOut = op->getIn(slot);
if (!addOut->isWritten()) continue;
PcodeOp *addOp = addOut->getDef();
if (addOp->code() != CPUI_INT_ADD) continue;
Varnode *constVn = addOp->getIn(1);
if (!constVn->isConstant()) continue;
if (constVn->getOffset() != npow) continue;
base = addOp->getIn(0);
Varnode *otherBase = op->getIn(1-slot);
if (otherBase == base)
break;
}
if (slot > 1) return (Varnode *)0;
BlockBasic *bl = op->getParent();
int4 innerSlot = 0;
BlockBasic *inner = (BlockBasic*)bl->getIn(innerSlot);
if (inner->sizeOut() != 1 || inner->sizeIn() != 1) {
innerSlot = 1;
inner = (BlockBasic*)bl->getIn(innerSlot);
if (inner->sizeOut() != 1 || inner->sizeIn() != 1)
return (Varnode *)0;
}
BlockBasic *decision = (BlockBasic*)inner->getIn(0);
if (bl->getIn(1 - innerSlot) != decision) return (Varnode *)0;
PcodeOp *cbranch = decision->lastOp();
if (cbranch == (PcodeOp*)0 || cbranch->code() != CPUI_CBRANCH) return (Varnode *)0;
Varnode *boolVn = cbranch->getIn(1);
if (!boolVn->isWritten()) return (Varnode *)0;
PcodeOp *lessOp = boolVn->getDef();
if (lessOp->code() != CPUI_INT_SLESS) return (Varnode *)0;
if (!lessOp->getIn(1)->isConstant()) return (Varnode *)0;
if (lessOp->getIn(1)->getOffset() != 0) return (Varnode *)0;
FlowBlock *negBlock = cbranch->isBooleanFlip() ? decision->getFalseOut() : decision->getTrueOut();
int4 negSlot = (negBlock == inner) ? innerSlot : (1-innerSlot);
if (negSlot != slot) return (Varnode *)0;
return base;
}
/// \class RuleSegment
/// \brief Propagate constants through a SEGMENTOP
void RuleSegment::getOpList(vector<uint4> &oplist) const

View file

@ -1237,6 +1237,17 @@ public:
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
};
class RuleDivChain : public Rule {
public:
RuleDivChain(const string &g) : Rule( g, 0, "divchain") {} ///< Constructor
virtual Rule *clone(const ActionGroupList &grouplist) const {
if (!grouplist.contains(getGroup())) return (Rule *)0;
return new RuleDivChain(getGroup());
}
virtual void getOpList(vector<uint4> &oplist) const;
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
};
class RuleSignForm : public Rule {
public:
RuleSignForm(const string &g) : Rule( g, 0, "signform") {} ///< Constructor
@ -1248,6 +1259,17 @@ public:
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
};
class RuleSignForm2 : public Rule {
public:
RuleSignForm2(const string &g) : Rule( g, 0, "signform2") {} ///< Constructor
virtual Rule *clone(const ActionGroupList &grouplist) const {
if (!grouplist.contains(getGroup())) return (Rule *)0;
return new RuleSignForm2(getGroup());
}
virtual void getOpList(vector<uint4> &oplist) const;
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
};
class RuleSignNearMult : public Rule {
public:
RuleSignNearMult(const string &g) : Rule( g, 0, "signnearmult") {} ///< Constructor
@ -1270,6 +1292,42 @@ public:
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
};
class RuleSignMod2nOpt : public Rule {
public:
RuleSignMod2nOpt(const string &g) : Rule( g, 0, "signmod2nopt") {} ///< Constructor
virtual Rule *clone(const ActionGroupList &grouplist) const {
if (!grouplist.contains(getGroup())) return (Rule *)0;
return new RuleSignMod2nOpt(getGroup());
}
virtual void getOpList(vector<uint4> &oplist) const;
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
static Varnode *checkSignExtraction(Varnode *outVn);
};
class RuleSignMod2Opt : public Rule {
public:
RuleSignMod2Opt(const string &g) : Rule( g, 0, "signmod2opt") {} ///< Constructor
virtual Rule *clone(const ActionGroupList &grouplist) const {
if (!grouplist.contains(getGroup())) return (Rule *)0;
return new RuleSignMod2Opt(getGroup());
}
virtual void getOpList(vector<uint4> &oplist) const;
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
};
class RuleSignMod2nOpt2 : public Rule {
static Varnode *checkMultiequalForm(PcodeOp *op,uintb npow);
static Varnode *checkSignExtForm(PcodeOp *op);
public:
RuleSignMod2nOpt2(const string &g) : Rule( g, 0, "signmod2nopt2") {} ///< Constructor
virtual Rule *clone(const ActionGroupList &grouplist) const {
if (!grouplist.contains(getGroup())) return (Rule *)0;
return new RuleSignMod2nOpt2(getGroup());
}
virtual void getOpList(vector<uint4> &oplist) const;
virtual int4 applyOp(PcodeOp *op,Funcdata &data);
};
class RuleSegment : public Rule {
public:
RuleSegment(const string &g) : Rule( g, 0, "segment") {} ///< Constructor