mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-28 23:20:48 +00:00
fix for result based sign-bit extraction in optimized division
This commit is contained in:
parent
d18f09101c
commit
29221c10a8
@ -584,6 +584,11 @@ int4 RuleShiftBitops::applyOp(PcodeOp *op,Funcdata &data)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \class RuleRightShiftAnd
|
||||||
|
/// \brief Simplify INT_RIGHT and INT_SRIGHT ops where an INT_AND mask becomes unnecessary
|
||||||
|
///
|
||||||
|
/// - `( V & 0xf000 ) >> 24 => V >> 24`
|
||||||
|
/// - `( V & 0xf000 ) s>> 24 => V s>> 24`
|
||||||
void RuleRightShiftAnd::getOpList(vector<uint4> &oplist) const
|
void RuleRightShiftAnd::getOpList(vector<uint4> &oplist) const
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -5275,6 +5280,10 @@ Varnode *RuleSLess2Zero::getHiBit(PcodeOp *op)
|
|||||||
/// - `SUB(V,#hi) s< 0 => V s< 0`
|
/// - `SUB(V,#hi) s< 0 => V s< 0`
|
||||||
/// - `-1 s< ~V => V s< 0`
|
/// - `-1 s< ~V => V s< 0`
|
||||||
/// - `~V s< 0 => -1 s< V`
|
/// - `~V s< 0 => -1 s< V`
|
||||||
|
/// - `(V & 0xf000) s< 0 => V s< 0`
|
||||||
|
/// - `-1 s< (V & 0xf000) => -1 s< V
|
||||||
|
/// - `CONCAT(V,W) s< 0 => V s< 0`
|
||||||
|
/// - `-1 s< CONCAT(V,W) => -1 s> V`
|
||||||
///
|
///
|
||||||
/// There is a second set of forms where one side of the comparison is
|
/// There is a second set of forms where one side of the comparison is
|
||||||
/// built out of a high and low piece, where the high piece determines the
|
/// built out of a high and low piece, where the high piece determines the
|
||||||
@ -6810,6 +6819,35 @@ uintb RuleDivOpt::calcDivisor(uintb n,uint8 y,int4 xsize)
|
|||||||
return (uintb)d;
|
return (uintb)d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Replace sign-bit extractions from the first given Varnode with the second Varnode
|
||||||
|
///
|
||||||
|
/// Look for either:
|
||||||
|
/// - `V >> 0x1f`
|
||||||
|
/// - `V s>> 0x1f`
|
||||||
|
///
|
||||||
|
/// \param firstVn is the first given Varnode
|
||||||
|
/// \param replaceVn is the Varnode to replace it with in each extraction
|
||||||
|
/// \param data is the function holding the Varnodes
|
||||||
|
void RuleDivOpt::moveSignBitExtraction(Varnode *firstVn,Varnode *replaceVn,Funcdata &data)
|
||||||
|
|
||||||
|
{
|
||||||
|
list<PcodeOp *>::const_iterator iter = firstVn->beginDescend();
|
||||||
|
while(iter!=firstVn->endDescend()) {
|
||||||
|
PcodeOp *op = *iter;
|
||||||
|
++iter; // Increment before modifying the op
|
||||||
|
OpCode opc = op->code();
|
||||||
|
if (opc == CPUI_INT_RIGHT || opc == CPUI_INT_SRIGHT) {
|
||||||
|
Varnode *constVn = op->getIn(1);
|
||||||
|
if (constVn->isConstant()) {
|
||||||
|
int4 sa = firstVn->getSize() * 8 - 1;
|
||||||
|
if (sa == (int4)constVn->getOffset()) {
|
||||||
|
data.opSetInput(op,replaceVn,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// \class RuleDivOpt
|
/// \class RuleDivOpt
|
||||||
/// \brief Convert INT_MULT and shift forms into INT_DIV or INT_SDIV
|
/// \brief Convert INT_MULT and shift forms into INT_DIV or INT_SDIV
|
||||||
///
|
///
|
||||||
@ -6855,6 +6893,7 @@ int4 RuleDivOpt::applyOp(PcodeOp *op,Funcdata &data)
|
|||||||
data.opSetInput(op,resVn,0);
|
data.opSetInput(op,resVn,0);
|
||||||
data.opSetInput(op,data.newConstant(4, 0),1);
|
data.opSetInput(op,data.newConstant(4, 0),1);
|
||||||
op = newop; // Main transform now changes newop
|
op = newop; // Main transform now changes newop
|
||||||
|
outSize = inVn->getSize();
|
||||||
}
|
}
|
||||||
if (extOpc == CPUI_INT_ZEXT) { // Unsigned division
|
if (extOpc == CPUI_INT_ZEXT) { // Unsigned division
|
||||||
data.opSetInput(op,inVn,0);
|
data.opSetInput(op,inVn,0);
|
||||||
@ -6862,6 +6901,7 @@ int4 RuleDivOpt::applyOp(PcodeOp *op,Funcdata &data)
|
|||||||
data.opSetOpcode(op,CPUI_INT_DIV);
|
data.opSetOpcode(op,CPUI_INT_DIV);
|
||||||
}
|
}
|
||||||
else { // Sign division
|
else { // Sign division
|
||||||
|
moveSignBitExtraction(op->getOut(), inVn, data);
|
||||||
PcodeOp *divop = data.newOp(2,op->getAddr());
|
PcodeOp *divop = data.newOp(2,op->getAddr());
|
||||||
data.opSetOpcode(divop,CPUI_INT_SDIV);
|
data.opSetOpcode(divop,CPUI_INT_SDIV);
|
||||||
Varnode *newout = data.newUniqueOut(outSize,divop);
|
Varnode *newout = data.newUniqueOut(outSize,divop);
|
||||||
@ -6871,9 +6911,9 @@ int4 RuleDivOpt::applyOp(PcodeOp *op,Funcdata &data)
|
|||||||
// Build the sign value correction
|
// Build the sign value correction
|
||||||
PcodeOp *sgnop = data.newOp(2,op->getAddr());
|
PcodeOp *sgnop = data.newOp(2,op->getAddr());
|
||||||
data.opSetOpcode(sgnop,CPUI_INT_SRIGHT);
|
data.opSetOpcode(sgnop,CPUI_INT_SRIGHT);
|
||||||
Varnode *sgnvn = data.newUniqueOut(inVn->getSize(),sgnop);
|
Varnode *sgnvn = data.newUniqueOut(outSize,sgnop);
|
||||||
data.opSetInput(sgnop,inVn,0);
|
data.opSetInput(sgnop,inVn,0);
|
||||||
data.opSetInput(sgnop,data.newConstant(inVn->getSize(),outSize*8-1),1);
|
data.opSetInput(sgnop,data.newConstant(outSize,outSize*8-1),1);
|
||||||
data.opInsertBefore(sgnop,op);
|
data.opInsertBefore(sgnop,op);
|
||||||
// Add the correction into the division op
|
// Add the correction into the division op
|
||||||
data.opSetInput(op,newout,0);
|
data.opSetInput(op,newout,0);
|
||||||
|
@ -1140,6 +1140,7 @@ public:
|
|||||||
|
|
||||||
class RuleDivOpt : public Rule {
|
class RuleDivOpt : public Rule {
|
||||||
static uintb calcDivisor(uintb n,uint8 y,int4 xsize); ///< Calculate the divisor
|
static uintb calcDivisor(uintb n,uint8 y,int4 xsize); ///< Calculate the divisor
|
||||||
|
static void moveSignBitExtraction(Varnode *firstVn,Varnode *replaceVn,Funcdata &data);
|
||||||
public:
|
public:
|
||||||
RuleDivOpt(const string &g) : Rule( g, 0, "divopt") {} ///< Constructor
|
RuleDivOpt(const string &g) : Rule( g, 0, "divopt") {} ///< Constructor
|
||||||
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
virtual Rule *clone(const ActionGroupList &grouplist) const {
|
||||||
|
Loading…
Reference in New Issue
Block a user