mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-1683 Extensions to SUBPIECE/shift rules
This commit is contained in:
parent
d0a8291e93
commit
aa85bba5d7
3 changed files with 70 additions and 11 deletions
|
@ -4736,7 +4736,7 @@ int4 RuleSubCancel::applyOp(PcodeOp *op,Funcdata &data)
|
|||
}
|
||||
|
||||
/// \class RuleShiftSub
|
||||
/// \brief Simplify SUBPIECE applied to INT_LEFT: `sub( V << 8*c, c) => sub(V,0)`
|
||||
/// \brief Simplify SUBPIECE applied to INT_LEFT: `sub( V << 8*k, c) => sub(V,c-k)`
|
||||
void RuleShiftSub::getOpList(vector<uint4> &oplist) const
|
||||
|
||||
{
|
||||
|
@ -4749,13 +4749,20 @@ int4 RuleShiftSub::applyOp(PcodeOp *op,Funcdata &data)
|
|||
if (!op->getIn(0)->isWritten()) return 0;
|
||||
PcodeOp *shiftop = op->getIn(0)->getDef();
|
||||
if (shiftop->code() != CPUI_INT_LEFT) return 0;
|
||||
if (!shiftop->getIn(1)->isConstant()) return 0;
|
||||
if (8*op->getIn(1)->getOffset() != shiftop->getIn(1)->getOffset())
|
||||
return 0;
|
||||
Varnode *sa = shiftop->getIn(1);
|
||||
if (!sa->isConstant()) return 0;
|
||||
int4 n = sa->getOffset();
|
||||
if ((n & 7) != 0) return 0; // Must shift by a multiple of 8 bits
|
||||
int4 c = op->getIn(1)->getOffset();
|
||||
Varnode *vn = shiftop->getIn(0);
|
||||
if (vn->isFree()) return 0;
|
||||
int4 insize = vn->getSize();
|
||||
int4 outsize = op->getOut()->getSize();
|
||||
c -= n/8;
|
||||
if (c < 0 || c + outsize > insize) // Check if this is a natural truncation
|
||||
return 0;
|
||||
data.opSetInput(op,vn,0);
|
||||
data.opSetInput(op,data.newConstant(op->getIn(1)->getSize(),0),1);
|
||||
data.opSetInput(op,data.newConstant(op->getIn(1)->getSize(),c),1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -6879,7 +6886,8 @@ int4 RuleExtensionPush::applyOp(PcodeOp *op,Funcdata &data)
|
|||
/// \brief Pull-back SUBPIECE through INT_RIGHT and INT_SRIGHT
|
||||
///
|
||||
/// The form looks like:
|
||||
/// - `sub( V>>c ,d ) => sub( V, d+k/8 ) >> (c-k) where k = (c/8)*8`
|
||||
/// - `sub( V>>n ,c ) => sub( V, c+k/8 ) >> (n-k) where k = (n/8)*8` or
|
||||
/// - `sub( V>>n, c ) => ext( sub( V, c+k/8 ) ) if n is big`
|
||||
void RuleSubNormal::getOpList(vector<uint4> &oplist) const
|
||||
|
||||
{
|
||||
|
@ -6901,13 +6909,35 @@ int4 RuleSubNormal::applyOp(PcodeOp *op,Funcdata &data)
|
|||
int4 n = shiftop->getIn(1)->getOffset();
|
||||
int4 c = op->getIn(1)->getOffset();
|
||||
int4 k = (n/8);
|
||||
int4 insize = a->getSize();
|
||||
int4 outsize = op->getOut()->getSize();
|
||||
// If totalcut + remain > original input, shrink cut
|
||||
if (k+c+outsize > shiftout->getSize())
|
||||
k = shiftout->getSize()-c-outsize;
|
||||
|
||||
// Total shift + outsize must be greater equal to size of input
|
||||
if ((n+8*c+8*outsize < 8*a->getSize())&&(n != k*8)) return 0;
|
||||
if ((n+8*c+8*outsize < 8*insize)&&(n != k*8)) return 0;
|
||||
|
||||
// If totalcut + remain > original input
|
||||
if (k+c+outsize > insize) {
|
||||
int4 truncSize = insize - c - k;
|
||||
if (n == k*8 && truncSize > 0 && popcount(truncSize)==1) {
|
||||
// We need an additional extension
|
||||
c += k;
|
||||
PcodeOp *newop = data.newOp(2,op->getAddr());
|
||||
opc = (opc == CPUI_INT_SRIGHT) ? CPUI_INT_SEXT : CPUI_INT_ZEXT;
|
||||
data.opSetOpcode(newop,CPUI_SUBPIECE);
|
||||
data.newUniqueOut(truncSize,newop);
|
||||
data.opSetInput(newop,a,0);
|
||||
data.opSetInput(newop,data.newConstant(4,c),1);
|
||||
data.opInsertBefore(newop,op);
|
||||
|
||||
data.opSetInput(op,newop->getOut(),0);
|
||||
data.opRemoveInput(op,1);
|
||||
data.opSetOpcode(op,opc);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
k = insize-c-outsize; // Or we can shrunk the cut
|
||||
}
|
||||
|
||||
// if n == k*8, then a shift is unnecessary
|
||||
c += k;
|
||||
n -= k*8;
|
||||
|
@ -6919,7 +6949,7 @@ int4 RuleSubNormal::applyOp(PcodeOp *op,Funcdata &data)
|
|||
|
||||
PcodeOp *newop = data.newOp(2,op->getAddr());
|
||||
data.opSetOpcode(newop,CPUI_SUBPIECE);
|
||||
data.newUniqueOut(op->getOut()->getSize(),newop);
|
||||
data.newUniqueOut(outsize,newop);
|
||||
data.opSetInput(newop,a,0);
|
||||
data.opSetInput(newop,data.newConstant(4,c),1);
|
||||
data.opInsertBefore(newop,op);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue