mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Addition of INSERT,EXTRACT, and POPCOUNT opcodes to decompiler code
This commit is contained in:
parent
2cafb27574
commit
0fdd29b98d
17 changed files with 164 additions and 8 deletions
|
@ -712,6 +712,22 @@ int4 mostsigbit_set(uintb val)
|
|||
return res;
|
||||
}
|
||||
|
||||
/// Count the number (population) bits set.
|
||||
/// \param val is the given value
|
||||
/// \return the number of one bits
|
||||
int4 popcount(uintb val)
|
||||
|
||||
{
|
||||
val = (val & 0x5555555555555555L) + ((val >> 1) & 0x5555555555555555L);
|
||||
val = (val & 0x3333333333333333L) + ((val >> 2) & 0x3333333333333333L);
|
||||
val = (val & 0x0f0f0f0f0f0f0f0fL) + ((val >> 4) & 0x0f0f0f0f0f0f0f0fL);
|
||||
val = (val & 0x00ff00ff00ff00ffL) + ((val >> 8) & 0x00ff00ff00ff00ffL);
|
||||
val = (val & 0x0000ffff0000ffffL) + ((val >> 16) & 0x0000ffff0000ffffL);
|
||||
int4 res = (int4)(val & 0xff);
|
||||
res += (int4)((val >> 32) & 0xff);
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Count the number of more significant zero bits before the most significant
|
||||
/// one bit in the representation of the given value;
|
||||
/// \param val is the given value
|
||||
|
|
|
@ -495,6 +495,7 @@ extern void byte_swap(intb &val,int4 size); ///< Swap bytes in the given value
|
|||
extern uintb byte_swap(uintb val,int4 size); ///< Return the given value with bytes swapped
|
||||
extern int4 leastsigbit_set(uintb val); ///< Return index of least significant bit set in given value
|
||||
extern int4 mostsigbit_set(uintb val); ///< Return index of most significant bit set in given value
|
||||
extern int4 popcount(uintb val); ///< Return the number of one bits in the given value
|
||||
extern int4 count_leading_zeros(uintb val); ///< Return the number of leading zero bits in the given value
|
||||
|
||||
extern uintb coveringmask(uintb val); ///< Return a mask that \e covers the given value
|
||||
|
|
|
@ -3053,6 +3053,34 @@ void ActionDeadCode::propagateConsumed(vector<Varnode *> &worklist)
|
|||
pushConsumed(a,op->getIn(0),worklist);
|
||||
pushConsumed(a,op->getIn(1),worklist);
|
||||
break;
|
||||
case CPUI_INSERT:
|
||||
a = 1;
|
||||
a <<= (int4)op->getIn(3)->getOffset();
|
||||
a -= 1; // Insert mask
|
||||
pushConsumed(a,op->getIn(1),worklist);
|
||||
a <<= (int4)op->getIn(2)->getOffset();
|
||||
pushConsumed(outc & ~a, op->getIn(0), worklist);
|
||||
b = (outc == 0) ? 0 : ~((uintb)0);
|
||||
pushConsumed(b,op->getIn(2), worklist);
|
||||
pushConsumed(b,op->getIn(3), worklist);
|
||||
break;
|
||||
case CPUI_EXTRACT:
|
||||
a = 1;
|
||||
a <<= (int4)op->getIn(2)->getOffset();
|
||||
a -= 1; // Extract mask
|
||||
a &= outc; // Consumed bits of mask
|
||||
a <<= (int4)op->getIn(1)->getOffset();
|
||||
pushConsumed(a,op->getIn(0),worklist);
|
||||
b = (outc == 0) ? 0 : ~((uintb)0);
|
||||
pushConsumed(b,op->getIn(1), worklist);
|
||||
pushConsumed(b,op->getIn(2), worklist);
|
||||
break;
|
||||
case CPUI_POPCOUNT:
|
||||
a = 16 * op->getIn(0)->getSize() - 1; // Mask for possible bits that could be set
|
||||
a &= outc; // Of the bits that could be set, which are consumed
|
||||
b = (a == 0) ? 0 : ~((uintb)0); // if any consumed, treat all input bits as consumed
|
||||
pushConsumed(b,op->getIn(0), worklist);
|
||||
break;
|
||||
default:
|
||||
a = (outc==0) ? 0 : ~((uintb)0); // all or nothing
|
||||
for(int4 i=0;i<op->numInput();++i)
|
||||
|
|
|
@ -55,7 +55,7 @@ uint4 DynamicHash::transtable[] = {
|
|||
|
||||
0, // CAST is skipped
|
||||
CPUI_INT_ADD, CPUI_INT_ADD, // PTRADD and PTRSUB hash same as INT_ADD
|
||||
CPUI_SEGMENTOP, CPUI_CPOOLREF, CPUI_NEW
|
||||
CPUI_SEGMENTOP, CPUI_CPOOLREF, CPUI_NEW, CPUI_INSERT, CPUI_EXTRACT, CPUI_POPCOUNT
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -493,6 +493,11 @@ uintb PcodeOp::getNZMaskLocal(bool cliploop) const
|
|||
val = (getIn(1)->getNZMask()-1); // Result is less than modulus
|
||||
resmask = coveringmask(val);
|
||||
break;
|
||||
case CPUI_POPCOUNT:
|
||||
sz1 = popcount(getIn(0)->getNZMask());
|
||||
resmask = coveringmask((uintb)sz1);
|
||||
resmask &= fullmask;
|
||||
break;
|
||||
case CPUI_SUBPIECE:
|
||||
resmask = getIn(0)->getNZMask();
|
||||
resmask >>= 8*getIn(1)->getOffset();
|
||||
|
|
|
@ -99,6 +99,9 @@ void OpBehavior::registerInstructions(vector<OpBehavior *> &inst,const Translate
|
|||
inst[CPUI_SEGMENTOP] = new OpBehavior(CPUI_SEGMENTOP,false,true);
|
||||
inst[CPUI_CPOOLREF] = new OpBehavior(CPUI_CPOOLREF,false,true);
|
||||
inst[CPUI_NEW] = new OpBehavior(CPUI_NEW,false,true);
|
||||
inst[CPUI_INSERT] = new OpBehavior(CPUI_INSERT,false,true);
|
||||
inst[CPUI_EXTRACT] = new OpBehavior(CPUI_EXTRACT,false,true);
|
||||
inst[CPUI_POPCOUNT] = new OpBehaviorPopcount();
|
||||
}
|
||||
|
||||
/// \param sizeout is the size of the output in bytes
|
||||
|
@ -725,3 +728,9 @@ uintb OpBehaviorSubpiece::evaluateBinary(int4 sizeout,int4 sizein,uintb in1,uint
|
|||
return res;
|
||||
}
|
||||
|
||||
uintb OpBehaviorPopcount::evaluateUnary(int4 sizeout,int4 sizein,uintb in1) const
|
||||
|
||||
{
|
||||
return (uintb)popcount(in1);
|
||||
}
|
||||
|
||||
|
|
|
@ -502,5 +502,11 @@ public:
|
|||
virtual uintb evaluateBinary(int4 sizeout,int4 sizein,uintb in1,uintb in2) const;
|
||||
};
|
||||
|
||||
/// CPUI_POPCOUNT behavior
|
||||
class OpBehaviorPopcount : public OpBehavior {
|
||||
public:
|
||||
OpBehaviorPopcount(void) : OpBehavior(CPUI_POPCOUNT,true) {} ///< Constructor
|
||||
virtual uintb evaluateUnary(int4 sizeout,int4 sizein,uintb in1) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -41,14 +41,15 @@ static const char *opcode_name[] = {
|
|||
"FLOAT_ABS", "FLOAT_SQRT", "INT2FLOAT", "FLOAT2FLOAT",
|
||||
"TRUNC", "CEIL", "FLOOR", "ROUND",
|
||||
"BUILD", "DELAY_SLOT", "PIECE", "SUBPIECE", "CAST",
|
||||
"LABEL", "CROSSBUILD", "SEGMENTOP", "CPOOLREF", "NEW"
|
||||
"LABEL", "CROSSBUILD", "SEGMENTOP", "CPOOLREF", "NEW",
|
||||
"INSERT", "EXTRACT", "POPCOUNT"
|
||||
};
|
||||
|
||||
static const int4 opcode_indices[] = {
|
||||
0, 39, 37, 40, 38, 4, 6, 60, 7, 8, 9, 64, 5, 57, 1, 68, 66,
|
||||
61, 55, 52, 47, 48, 41, 43, 44, 49, 46, 51, 42, 53, 50, 58,
|
||||
61, 71, 55, 52, 47, 48, 41, 43, 44, 49, 46, 51, 42, 53, 50, 58, 70,
|
||||
54, 24, 19, 27, 21, 33, 11, 29, 15, 16, 32, 25, 12, 28, 35, 30,
|
||||
23, 22, 34, 18, 13, 14, 36, 31, 20, 26, 17, 65, 2, 69, 62, 10, 59,
|
||||
23, 22, 34, 18, 13, 14, 36, 31, 20, 26, 17, 65, 2, 69, 62, 72, 10, 59,
|
||||
67, 3, 63, 56, 45
|
||||
};
|
||||
|
||||
|
|
|
@ -120,8 +120,11 @@ enum OpCode {
|
|||
CPUI_SEGMENTOP = 67, ///< Look-up a \e segmented address
|
||||
CPUI_CPOOLREF = 68, ///< Recover a value from the \e constant \e pool
|
||||
CPUI_NEW = 69, ///< Allocate a new object (new)
|
||||
CPUI_INSERT = 70, ///< Insert a bit-range
|
||||
CPUI_EXTRACT = 71, ///< Extract a bit-range
|
||||
CPUI_POPCOUNT = 72, ///< Count the 1-bits
|
||||
|
||||
CPUI_MAX = 70 ///< Value indicating the end of the op-code values
|
||||
CPUI_MAX = 73 ///< Value indicating the end of the op-code values
|
||||
};
|
||||
|
||||
extern const char *get_opname(OpCode opc); ///< Convert an OpCode to the name as a string
|
||||
|
|
|
@ -970,6 +970,18 @@ void PrintC::opNewOp(const PcodeOp *op)
|
|||
pushVnImplied(vn0,op,mods);
|
||||
}
|
||||
|
||||
void PrintC::opInsertOp(const PcodeOp *op)
|
||||
|
||||
{
|
||||
opFunc(op); // If no other way to print it, print as functional operator
|
||||
}
|
||||
|
||||
void PrintC::opExtractOp(const PcodeOp *op)
|
||||
|
||||
{
|
||||
opFunc(op); // If no other way to print it, print as functional operator
|
||||
}
|
||||
|
||||
/// \brief Push a constant with an integer data-type to the RPN stack
|
||||
///
|
||||
/// Various checks are made to see if the integer should be printed as an \e equate
|
||||
|
|
|
@ -290,6 +290,9 @@ public:
|
|||
virtual void opSegmentOp(const PcodeOp *op);
|
||||
virtual void opCpoolRefOp(const PcodeOp *op);
|
||||
virtual void opNewOp(const PcodeOp *op);
|
||||
virtual void opInsertOp(const PcodeOp *op);
|
||||
virtual void opExtractOp(const PcodeOp *op);
|
||||
virtual void opPopcountOp(const PcodeOp *op) { opFunc(op); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -538,6 +538,9 @@ public:
|
|||
virtual void opSegmentOp(const PcodeOp *op)=0; ///< Emit a SEGMENTOP operator
|
||||
virtual void opCpoolRefOp(const PcodeOp *op)=0; ///< Emit a CPOOLREF operator
|
||||
virtual void opNewOp(const PcodeOp *op)=0; ///< Emit a NEW operator
|
||||
virtual void opInsertOp(const PcodeOp *op)=0; ///< Emit an INSERT operator
|
||||
virtual void opExtractOp(const PcodeOp *op)=0; ///< Emit an EXTRACT operator
|
||||
virtual void opPopcountOp(const PcodeOp *op)=0; ///< Emit a POPCOUNT operator
|
||||
|
||||
static int4 mostNaturalBase(uintb val); ///< Determine the most natural base for an integer
|
||||
static void formatBinary(ostream &s,uintb val); ///< Print a number in binary form
|
||||
|
|
|
@ -734,6 +734,9 @@ void ConsistencyChecker::printOpName(ostream &s,OpTpl *op)
|
|||
case CPUI_NEW:
|
||||
s << "New object(newobject)";
|
||||
break;
|
||||
case CPUI_POPCOUNT:
|
||||
s << "Count bits(popcount)";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
%right '!' '~'
|
||||
%token OP_ZEXT OP_CARRY OP_BORROW OP_SEXT OP_SCARRY OP_SBORROW OP_NAN OP_ABS
|
||||
%token OP_SQRT OP_CEIL OP_FLOOR OP_ROUND OP_INT2FLOAT OP_FLOAT2FLOAT
|
||||
%token OP_TRUNC OP_CPOOLREF OP_NEW
|
||||
%token OP_TRUNC OP_CPOOLREF OP_NEW OP_POPCOUNT
|
||||
|
||||
%token BADINTEGER GOTO_KEY CALL_KEY RETURN_KEY IF_KEY
|
||||
%token DEFINE_KEY ATTACH_KEY MACRO_KEY SPACE_KEY TYPE_KEY RAM_KEY DEFAULT_KEY
|
||||
|
@ -436,9 +436,10 @@ expr: varnode { $$ = new ExprTree($1); }
|
|||
| OP_TRUNC '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_FLOAT_TRUNC,$3); }
|
||||
| OP_CEIL '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_FLOAT_CEIL,$3); }
|
||||
| OP_FLOOR '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_FLOAT_FLOOR,$3); }
|
||||
| OP_ROUND '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_FLOAT_ROUND,$3); };
|
||||
| OP_NEW '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_NEW,$3); };
|
||||
| OP_ROUND '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_FLOAT_ROUND,$3); }
|
||||
| OP_NEW '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_NEW,$3); }
|
||||
| OP_NEW '(' expr ',' expr ')' { $$ = slgh->pcode.createOp(CPUI_NEW,$3,$5); }
|
||||
| OP_POPCOUNT '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_POPCOUNT,$3); }
|
||||
| specificsymbol '(' integervarnode ')' { $$ = slgh->pcode.createOp(CPUI_SUBPIECE,new ExprTree($1->getVarnode()),new ExprTree($3)); }
|
||||
| specificsymbol ':' INTEGER { $$ = slgh->pcode.createBitRange($1,0,(uint4)(*$3 * 8)); delete $3; }
|
||||
| specificsymbol '[' INTEGER ',' INTEGER ']' { $$ = slgh->pcode.createBitRange($1,(uint4)*$3,(uint4)*$5); delete $3, delete $5; }
|
||||
|
|
|
@ -637,6 +637,7 @@ with { BEGIN(pattern); withsection = 1; slgh->calcContextLayout(); return WITH
|
|||
<sem>trunc { return OP_TRUNC; }
|
||||
<sem>cpool { return OP_CPOOLREF; }
|
||||
<sem>newobject { return OP_NEW; }
|
||||
<sem>popcount { return OP_POPCOUNT; }
|
||||
<sem>if { return IF_KEY; }
|
||||
<sem>goto { return GOTO_KEY; }
|
||||
<sem>call { return CALL_KEY; }
|
||||
|
|
|
@ -100,6 +100,9 @@ void TypeOp::registerInstructions(vector<TypeOp *> &inst,TypeFactory *tlst,
|
|||
inst[CPUI_SEGMENTOP] = new TypeOpSegment(tlst);
|
||||
inst[CPUI_CPOOLREF] = new TypeOpCpoolref(tlst);
|
||||
inst[CPUI_NEW] = new TypeOpNew(tlst);
|
||||
inst[CPUI_INSERT] = new TypeOpInsert(tlst);
|
||||
inst[CPUI_EXTRACT] = new TypeOpExtract(tlst);
|
||||
inst[CPUI_POPCOUNT] = new TypeOpPopcount(tlst);
|
||||
}
|
||||
|
||||
/// Change basic data-type info (signed vs unsigned) and operator names ( '>>' vs '>>>' )
|
||||
|
@ -1809,3 +1812,40 @@ void TypeOpNew::printRaw(ostream &s,const PcodeOp *op)
|
|||
}
|
||||
s << ')';
|
||||
}
|
||||
|
||||
TypeOpInsert::TypeOpInsert(TypeFactory *t)
|
||||
: TypeOpFunc(t,CPUI_INSERT,"INSERT",TYPE_UNKNOWN,TYPE_INT)
|
||||
{
|
||||
opflags = PcodeOp::special;
|
||||
behave = new OpBehavior(CPUI_INSERT,false,true); // Dummy behavior
|
||||
}
|
||||
|
||||
Datatype *TypeOpInsert::getInputLocal(const PcodeOp *op,int4 slot) const
|
||||
|
||||
{
|
||||
if (slot == 0)
|
||||
return tlst->getBase(op->getIn(slot)->getSize(),TYPE_UNKNOWN);
|
||||
return TypeOpFunc::getInputLocal(op, slot);
|
||||
}
|
||||
|
||||
TypeOpExtract::TypeOpExtract(TypeFactory *t)
|
||||
: TypeOpFunc(t,CPUI_EXTRACT,"EXTRACT",TYPE_INT,TYPE_INT)
|
||||
{
|
||||
opflags = PcodeOp::special;
|
||||
behave = new OpBehavior(CPUI_EXTRACT,false,true); // Dummy behavior
|
||||
}
|
||||
|
||||
Datatype *TypeOpExtract::getInputLocal(const PcodeOp *op,int4 slot) const
|
||||
|
||||
{
|
||||
if (slot == 0)
|
||||
return tlst->getBase(op->getIn(slot)->getSize(),TYPE_UNKNOWN);
|
||||
return TypeOpFunc::getInputLocal(op, slot);
|
||||
}
|
||||
|
||||
TypeOpPopcount::TypeOpPopcount(TypeFactory *t)
|
||||
: TypeOpFunc(t,CPUI_POPCOUNT,"POPCOUNT",TYPE_INT,TYPE_UNKNOWN)
|
||||
{
|
||||
opflags = PcodeOp::unary;
|
||||
behave = new OpBehaviorPopcount();
|
||||
}
|
||||
|
|
|
@ -777,4 +777,28 @@ public:
|
|||
virtual void push(PrintLanguage *lng,const PcodeOp *op) const { lng->opNewOp(op); }
|
||||
virtual void printRaw(ostream &s,const PcodeOp *op);
|
||||
};
|
||||
|
||||
/// \brief Information about the INSERT op-code
|
||||
class TypeOpInsert : public TypeOpFunc {
|
||||
public:
|
||||
TypeOpInsert(TypeFactory *t); ///< Constructor
|
||||
virtual Datatype *getInputLocal(const PcodeOp *op,int4 slot) const;
|
||||
virtual void push(PrintLanguage *lng,const PcodeOp *op) const { lng->opInsertOp(op); }
|
||||
};
|
||||
|
||||
/// \brief Information about the EXTRACT op-code
|
||||
class TypeOpExtract : public TypeOpFunc {
|
||||
public:
|
||||
TypeOpExtract(TypeFactory *t); ///< Constructor
|
||||
virtual Datatype *getInputLocal(const PcodeOp *op,int4 slot) const;
|
||||
virtual void push(PrintLanguage *lng,const PcodeOp *op) const { lng->opExtractOp(op); }
|
||||
};
|
||||
|
||||
/// \brief Information about the POPCOUNT op-code
|
||||
class TypeOpPopcount : public TypeOpFunc {
|
||||
public:
|
||||
TypeOpPopcount(TypeFactory *t); ///< Constructor
|
||||
virtual void push(PrintLanguage *lng,const PcodeOp *op) const { lng->opPopcountOp(op); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue