mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
Create and use LZCOUNT Pcode op
This commit is contained in:
parent
865cd22cab
commit
14880b53c4
47 changed files with 288 additions and 247 deletions
|
@ -3617,6 +3617,7 @@ void ActionDeadCode::propagateConsumed(vector<Varnode *> &worklist)
|
||||||
pushConsumed(b,op->getIn(2), worklist);
|
pushConsumed(b,op->getIn(2), worklist);
|
||||||
break;
|
break;
|
||||||
case CPUI_POPCOUNT:
|
case CPUI_POPCOUNT:
|
||||||
|
case CPUI_LZCOUNT:
|
||||||
a = 16 * op->getIn(0)->getSize() - 1; // Mask for possible bits that could be set
|
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
|
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
|
b = (a == 0) ? 0 : ~((uintb)0); // if any consumed, treat all input bits as consumed
|
||||||
|
|
|
@ -55,7 +55,8 @@ const uint4 DynamicHash::transtable[] = {
|
||||||
|
|
||||||
0, // CAST is skipped
|
0, // CAST is skipped
|
||||||
CPUI_INT_ADD, CPUI_INT_ADD, // PTRADD and PTRSUB hash same as INT_ADD
|
CPUI_INT_ADD, CPUI_INT_ADD, // PTRADD and PTRSUB hash same as INT_ADD
|
||||||
CPUI_SEGMENTOP, CPUI_CPOOLREF, CPUI_NEW, CPUI_INSERT, CPUI_EXTRACT, CPUI_POPCOUNT
|
CPUI_SEGMENTOP, CPUI_CPOOLREF, CPUI_NEW, CPUI_INSERT, CPUI_EXTRACT,
|
||||||
|
CPUI_POPCOUNT, CPUI_LZCOUNT
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -645,6 +645,10 @@ uintb PcodeOp::getNZMaskLocal(bool cliploop) const
|
||||||
resmask = coveringmask((uintb)sz1);
|
resmask = coveringmask((uintb)sz1);
|
||||||
resmask &= fullmask;
|
resmask &= fullmask;
|
||||||
break;
|
break;
|
||||||
|
case CPUI_LZCOUNT:
|
||||||
|
resmask = coveringmask(getIn(0)->getSize() * 8);
|
||||||
|
resmask &= fullmask;
|
||||||
|
break;
|
||||||
case CPUI_SUBPIECE:
|
case CPUI_SUBPIECE:
|
||||||
resmask = getIn(0)->getNZMask();
|
resmask = getIn(0)->getNZMask();
|
||||||
sz1 = (int4)getIn(1)->getOffset();
|
sz1 = (int4)getIn(1)->getOffset();
|
||||||
|
|
|
@ -102,6 +102,7 @@ void OpBehavior::registerInstructions(vector<OpBehavior *> &inst,const Translate
|
||||||
inst[CPUI_INSERT] = new OpBehavior(CPUI_INSERT,false);
|
inst[CPUI_INSERT] = new OpBehavior(CPUI_INSERT,false);
|
||||||
inst[CPUI_EXTRACT] = new OpBehavior(CPUI_EXTRACT,false);
|
inst[CPUI_EXTRACT] = new OpBehavior(CPUI_EXTRACT,false);
|
||||||
inst[CPUI_POPCOUNT] = new OpBehaviorPopcount();
|
inst[CPUI_POPCOUNT] = new OpBehaviorPopcount();
|
||||||
|
inst[CPUI_LZCOUNT] = new OpBehaviorLzcount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \param sizeout is the size of the output in bytes
|
/// \param sizeout is the size of the output in bytes
|
||||||
|
@ -757,3 +758,8 @@ uintb OpBehaviorPopcount::evaluateUnary(int4 sizeout,int4 sizein,uintb in1) cons
|
||||||
return (uintb)popcount(in1);
|
return (uintb)popcount(in1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uintb OpBehaviorLzcount::evaluateUnary(int4 sizeout,int4 sizein,uintb in1) const
|
||||||
|
|
||||||
|
{
|
||||||
|
return (uintb)(count_leading_zeros(in1) - 8*(sizeof(uintb) - sizein));
|
||||||
|
}
|
||||||
|
|
|
@ -511,4 +511,11 @@ public:
|
||||||
virtual uintb evaluateUnary(int4 sizeout,int4 sizein,uintb in1) const;
|
virtual uintb evaluateUnary(int4 sizeout,int4 sizein,uintb in1) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// CPUI_LZCOUNT behavior
|
||||||
|
class OpBehaviorLzcount : public OpBehavior {
|
||||||
|
public:
|
||||||
|
OpBehaviorLzcount(void) : OpBehavior(CPUI_LZCOUNT,true) {} ///< Constructor
|
||||||
|
virtual uintb evaluateUnary(int4 sizeout,int4 sizein,uintb in1) const;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,14 +42,14 @@ static const char *opcode_name[] = {
|
||||||
"TRUNC", "CEIL", "FLOOR", "ROUND",
|
"TRUNC", "CEIL", "FLOOR", "ROUND",
|
||||||
"BUILD", "DELAY_SLOT", "PIECE", "SUBPIECE", "CAST",
|
"BUILD", "DELAY_SLOT", "PIECE", "SUBPIECE", "CAST",
|
||||||
"LABEL", "CROSSBUILD", "SEGMENTOP", "CPOOLREF", "NEW",
|
"LABEL", "CROSSBUILD", "SEGMENTOP", "CPOOLREF", "NEW",
|
||||||
"INSERT", "EXTRACT", "POPCOUNT"
|
"INSERT", "EXTRACT", "POPCOUNT", "LZCOUNT"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int4 opcode_indices[] = {
|
static const int4 opcode_indices[] = {
|
||||||
0, 39, 37, 40, 38, 4, 6, 60, 7, 8, 9, 64, 5, 57, 1, 68, 66,
|
0, 39, 37, 40, 38, 4, 6, 60, 7, 8, 9, 64, 5, 57, 1, 68, 66,
|
||||||
61, 71, 55, 52, 47, 48, 41, 43, 44, 49, 46, 51, 42, 53, 50, 58, 70,
|
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,
|
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, 72, 10, 59,
|
23, 22, 34, 18, 13, 14, 36, 31, 20, 26, 17, 65, 2, 73, 69, 62, 72, 10, 59,
|
||||||
67, 3, 63, 56, 45
|
67, 3, 63, 56, 45
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -123,8 +123,9 @@ enum OpCode {
|
||||||
CPUI_INSERT = 70, ///< Insert a bit-range
|
CPUI_INSERT = 70, ///< Insert a bit-range
|
||||||
CPUI_EXTRACT = 71, ///< Extract a bit-range
|
CPUI_EXTRACT = 71, ///< Extract a bit-range
|
||||||
CPUI_POPCOUNT = 72, ///< Count the 1-bits
|
CPUI_POPCOUNT = 72, ///< Count the 1-bits
|
||||||
|
CPUI_LZCOUNT = 73, ///< Count the leading 0-bits
|
||||||
|
|
||||||
CPUI_MAX = 73 ///< Value indicating the end of the op-code values
|
CPUI_MAX = 74 ///< 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
|
extern const char *get_opname(OpCode opc); ///< Convert an OpCode to the name as a string
|
||||||
|
|
|
@ -329,6 +329,7 @@ public:
|
||||||
virtual void opInsertOp(const PcodeOp *op);
|
virtual void opInsertOp(const PcodeOp *op);
|
||||||
virtual void opExtractOp(const PcodeOp *op);
|
virtual void opExtractOp(const PcodeOp *op);
|
||||||
virtual void opPopcountOp(const PcodeOp *op) { opFunc(op); }
|
virtual void opPopcountOp(const PcodeOp *op) { opFunc(op); }
|
||||||
|
virtual void opLzcountOp(const PcodeOp *op) { opFunc(op); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Set of print commands for displaying an open brace '{' and setting a new indent level
|
/// \brief Set of print commands for displaying an open brace '{' and setting a new indent level
|
||||||
|
|
|
@ -554,6 +554,7 @@ public:
|
||||||
virtual void opInsertOp(const PcodeOp *op)=0; ///< Emit an INSERT 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 opExtractOp(const PcodeOp *op)=0; ///< Emit an EXTRACT operator
|
||||||
virtual void opPopcountOp(const PcodeOp *op)=0; ///< Emit a POPCOUNT operator
|
virtual void opPopcountOp(const PcodeOp *op)=0; ///< Emit a POPCOUNT operator
|
||||||
|
virtual void opLzcountOp(const PcodeOp *op)=0; ///< Emit a LZCOUNT operator
|
||||||
virtual string unnamedField(int4 off,int4 size); ///< Generate an artificial field name
|
virtual string unnamedField(int4 off,int4 size); ///< Generate an artificial field name
|
||||||
|
|
||||||
static int4 mostNaturalBase(uintb val); ///< Determine the most natural base for an integer
|
static int4 mostNaturalBase(uintb val); ///< Determine the most natural base for an integer
|
||||||
|
|
|
@ -785,6 +785,9 @@ void ConsistencyChecker::printOpName(ostream &s,OpTpl *op)
|
||||||
case CPUI_POPCOUNT:
|
case CPUI_POPCOUNT:
|
||||||
s << "Count bits(popcount)";
|
s << "Count bits(popcount)";
|
||||||
break;
|
break;
|
||||||
|
case CPUI_LZCOUNT:
|
||||||
|
s << "Count leading zero bits(lzcount)";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@
|
||||||
%right '!' '~'
|
%right '!' '~'
|
||||||
%token OP_ZEXT OP_CARRY OP_BORROW OP_SEXT OP_SCARRY OP_SBORROW OP_NAN OP_ABS
|
%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_SQRT OP_CEIL OP_FLOOR OP_ROUND OP_INT2FLOAT OP_FLOAT2FLOAT
|
||||||
%token OP_TRUNC OP_CPOOLREF OP_NEW OP_POPCOUNT
|
%token OP_TRUNC OP_CPOOLREF OP_NEW OP_POPCOUNT OP_LZCOUNT
|
||||||
|
|
||||||
%token BADINTEGER GOTO_KEY CALL_KEY RETURN_KEY IF_KEY
|
%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
|
%token DEFINE_KEY ATTACH_KEY MACRO_KEY SPACE_KEY TYPE_KEY RAM_KEY DEFAULT_KEY
|
||||||
|
@ -444,6 +444,7 @@ expr: varnode { $$ = new ExprTree($1); }
|
||||||
| OP_NEW '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_NEW,$3); }
|
| OP_NEW '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_NEW,$3); }
|
||||||
| OP_NEW '(' expr ',' expr ')' { $$ = slgh->pcode.createOp(CPUI_NEW,$3,$5); }
|
| OP_NEW '(' expr ',' expr ')' { $$ = slgh->pcode.createOp(CPUI_NEW,$3,$5); }
|
||||||
| OP_POPCOUNT '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_POPCOUNT,$3); }
|
| OP_POPCOUNT '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_POPCOUNT,$3); }
|
||||||
|
| OP_LZCOUNT '(' expr ')' { $$ = slgh->pcode.createOp(CPUI_LZCOUNT,$3); }
|
||||||
| specificsymbol '(' integervarnode ')' { $$ = slgh->pcode.createOp(CPUI_SUBPIECE,new ExprTree($1->getVarnode()),new ExprTree($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 { $$ = 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; }
|
| specificsymbol '[' INTEGER ',' INTEGER ']' { $$ = slgh->pcode.createBitRange($1,(uint4)*$3,(uint4)*$5); delete $3, delete $5; }
|
||||||
|
|
|
@ -641,6 +641,7 @@ with { BEGIN(pattern); withsection = 1; slgh->calcContextLayout(); return WITH
|
||||||
<sem>cpool { return OP_CPOOLREF; }
|
<sem>cpool { return OP_CPOOLREF; }
|
||||||
<sem>newobject { return OP_NEW; }
|
<sem>newobject { return OP_NEW; }
|
||||||
<sem>popcount { return OP_POPCOUNT; }
|
<sem>popcount { return OP_POPCOUNT; }
|
||||||
|
<sem>lzcount { return OP_LZCOUNT; }
|
||||||
<sem>if { return IF_KEY; }
|
<sem>if { return IF_KEY; }
|
||||||
<sem>goto { return GOTO_KEY; }
|
<sem>goto { return GOTO_KEY; }
|
||||||
<sem>call { return CALL_KEY; }
|
<sem>call { return CALL_KEY; }
|
||||||
|
|
|
@ -102,6 +102,7 @@ void TypeOp::registerInstructions(vector<TypeOp *> &inst,TypeFactory *tlst,
|
||||||
inst[CPUI_INSERT] = new TypeOpInsert(tlst);
|
inst[CPUI_INSERT] = new TypeOpInsert(tlst);
|
||||||
inst[CPUI_EXTRACT] = new TypeOpExtract(tlst);
|
inst[CPUI_EXTRACT] = new TypeOpExtract(tlst);
|
||||||
inst[CPUI_POPCOUNT] = new TypeOpPopcount(tlst);
|
inst[CPUI_POPCOUNT] = new TypeOpPopcount(tlst);
|
||||||
|
inst[CPUI_LZCOUNT] = new TypeOpLzcount(tlst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change basic data-type info (signed vs unsigned) and operator names ( '>>' vs '>>>' )
|
/// Change basic data-type info (signed vs unsigned) and operator names ( '>>' vs '>>>' )
|
||||||
|
@ -2323,3 +2324,10 @@ TypeOpPopcount::TypeOpPopcount(TypeFactory *t)
|
||||||
opflags = PcodeOp::unary;
|
opflags = PcodeOp::unary;
|
||||||
behave = new OpBehaviorPopcount();
|
behave = new OpBehaviorPopcount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeOpLzcount::TypeOpLzcount(TypeFactory *t)
|
||||||
|
: TypeOpFunc(t,CPUI_LZCOUNT,"LZCOUNT",TYPE_INT,TYPE_UNKNOWN)
|
||||||
|
{
|
||||||
|
opflags = PcodeOp::unary;
|
||||||
|
behave = new OpBehaviorLzcount();
|
||||||
|
}
|
||||||
|
|
|
@ -857,4 +857,11 @@ public:
|
||||||
virtual void push(PrintLanguage *lng,const PcodeOp *op,const PcodeOp *readOp) const { lng->opPopcountOp(op); }
|
virtual void push(PrintLanguage *lng,const PcodeOp *op,const PcodeOp *readOp) const { lng->opPopcountOp(op); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Information about the LZCOUNT op-code
|
||||||
|
class TypeOpLzcount : public TypeOpFunc {
|
||||||
|
public:
|
||||||
|
TypeOpLzcount(TypeFactory *t); ///< Constructor
|
||||||
|
virtual void push(PrintLanguage *lng,const PcodeOp *op,const PcodeOp *readOp) const { lng->opLzcountOp(op); }
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<article id="pcoderef_title">
|
<article id="pcoderef_title">
|
||||||
<info>
|
<info>
|
||||||
<title>P-Code Reference Manual</title>
|
<title>P-Code Reference Manual</title>
|
||||||
<releaseinfo>Last updated September 5, 2019</releaseinfo>
|
<releaseinfo>Last updated March 2, 2023</releaseinfo>
|
||||||
</info>
|
</info>
|
||||||
<table xml:id="mytoc.htmltable" width="90%" frame='none'>
|
<table xml:id="mytoc.htmltable" width="90%" frame='none'>
|
||||||
<col width="25%"/>
|
<col width="25%"/>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
<td><link linkend="cpui_int_sub">INT_SUB</link></td>
|
<td><link linkend="cpui_int_sub">INT_SUB</link></td>
|
||||||
<td><link linkend="cpui_float_equal">FLOAT_EQUAL</link></td>
|
<td><link linkend="cpui_float_equal">FLOAT_EQUAL</link></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>P
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><link linkend="cpui_store">STORE</link></td>
|
<td><link linkend="cpui_store">STORE</link></td>
|
||||||
<td><link linkend="cpui_int_carry">INT_CARRY</link></td>
|
<td><link linkend="cpui_int_carry">INT_CARRY</link></td>
|
||||||
|
@ -90,52 +90,58 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><link linkend="cpui_int_equal">INT_EQUAL</link></td>
|
<td><link linkend="cpui_lzcount">LZCOUNT</link></td>
|
||||||
<td><link linkend="cpui_int_mult">INT_MULT</link></td>
|
<td><link linkend="cpui_int_mult">INT_MULT</link></td>
|
||||||
<td><link linkend="cpui_float_floor">FLOAT_FLOOR</link></td>
|
<td><link linkend="cpui_float_floor">FLOAT_FLOOR</link></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><link linkend="cpui_int_notequal">INT_NOTEQUAL</link></td>
|
<td><link linkend="cpui_int_equal">INT_EQUAL</link></td>
|
||||||
<td><link linkend="cpui_int_div">INT_DIV</link></td>
|
<td><link linkend="cpui_int_div">INT_DIV</link></td>
|
||||||
<td><link linkend="cpui_float_round">FLOAT_ROUND</link></td>
|
<td><link linkend="cpui_float_round">FLOAT_ROUND</link></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><link linkend="cpui_int_less">INT_LESS</link></td>
|
<td><link linkend="cpui_int_notequal">INT_NOTEQUAL</link></td>
|
||||||
<td><link linkend="cpui_int_rem">INT_REM</link></td>
|
<td><link linkend="cpui_int_rem">INT_REM</link></td>
|
||||||
<td><link linkend="cpui_float_nan">FLOAT_NAN</link></td>
|
<td><link linkend="cpui_float_nan">FLOAT_NAN</link></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><link linkend="cpui_int_sless">INT_SLESS</link></td>
|
<td><link linkend="cpui_int_less">INT_LESS</link></td>
|
||||||
<td><link linkend="cpui_int_sdiv">INT_SDIV</link></td>
|
<td><link linkend="cpui_int_sdiv">INT_SDIV</link></td>
|
||||||
<td><link linkend="cpui_int2float">INT2FLOAT</link></td>
|
<td><link linkend="cpui_int2float">INT2FLOAT</link></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><link linkend="cpui_int_lessequal">INT_LESSEQUAL</link></td>
|
<td><link linkend="cpui_int_sless">INT_SLESS</link></td>
|
||||||
<td><link linkend="cpui_int_srem">INT_SREM</link></td>
|
<td><link linkend="cpui_int_srem">INT_SREM</link></td>
|
||||||
<td><link linkend="cpui_float2float">FLOAT2FLOAT</link></td>
|
<td><link linkend="cpui_float2float">FLOAT2FLOAT</link></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><link linkend="cpui_int_slessequal">INT_SLESSEQUAL</link></td>
|
<td><link linkend="cpui_int_lessequal">INT_LESSEQUAL</link></td>
|
||||||
<td><link linkend="cpui_bool_negate">BOOL_NEGATE</link></td>
|
<td><link linkend="cpui_bool_negate">BOOL_NEGATE</link></td>
|
||||||
<td><link linkend="cpui_trunc">TRUNC</link></td>
|
<td><link linkend="cpui_trunc">TRUNC</link></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><link linkend="cpui_int_zext">INT_ZEXT</link></td>
|
<td><link linkend="cpui_int_slessequal">INT_SLESSEQUAL</link></td>
|
||||||
<td><link linkend="cpui_bool_xor">BOOL_XOR</link></td>
|
<td><link linkend="cpui_bool_xor">BOOL_XOR</link></td>
|
||||||
<td><link linkend="cpui_cpoolref">CPOOLREF</link></td>
|
<td><link linkend="cpui_cpoolref">CPOOLREF</link></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><link linkend="cpui_int_sext">INT_SEXT</link></td>
|
<td><link linkend="cpui_int_zext">INT_ZEXT</link></td>
|
||||||
<td><link linkend="cpui_bool_and">BOOL_AND</link></td>
|
<td><link linkend="cpui_bool_and">BOOL_AND</link></td>
|
||||||
<td><link linkend="cpui_new">NEW</link></td>
|
<td><link linkend="cpui_new">NEW</link></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><link linkend="cpui_int_sext">INT_SEXT</link></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<sect1 id="index">
|
<sect1 id="index">
|
||||||
|
@ -977,6 +983,50 @@ count is zero extended into the output varnode.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="cpui_lzcount"><title>LZCOUNT</title>
|
||||||
|
<informalexample>
|
||||||
|
<table xml:id="lzcount.htmltable" frame="above" width="80%" rules="groups">
|
||||||
|
<col width="23%"/>
|
||||||
|
<col width="15%"/>
|
||||||
|
<col width="61%"/>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="2"><emphasis role="bold">Parameters</emphasis></td>
|
||||||
|
<td><emphasis role="bold">Description</emphasis></td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align='right'>input0</td>
|
||||||
|
<td/>
|
||||||
|
<td>Input varnode to count.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align='right'>output</td>
|
||||||
|
<td/>
|
||||||
|
<td>Resulting integer varnode containing count.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="2"><emphasis role="bold">Semantic statement</emphasis></td>
|
||||||
|
<td/>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td/>
|
||||||
|
<td colspan="2"><code>output = lzcount(input0);</code></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</informalexample>
|
||||||
|
<para>
|
||||||
|
This operator counts the number of zeros starting at the most significant bit.
|
||||||
|
For instance, for a 4-byte varnode, a value of 0 returns 32, a value of 1
|
||||||
|
returns 31, and the value 2<superscript>31</superscript> returns 0.
|
||||||
|
The resulting count is zero extended into the output varnode.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="cpui_int_equal"><title>INT_EQUAL</title>
|
<sect2 id="cpui_int_equal"><title>INT_EQUAL</title>
|
||||||
<informalexample>
|
<informalexample>
|
||||||
<table xml:id="intequal.htmltable" frame="above" width="80%" rules="groups">
|
<table xml:id="intequal.htmltable" frame="above" width="80%" rules="groups">
|
||||||
|
@ -4058,6 +4108,11 @@ to SLEIGH <emphasis role="bold">bitrange</emphasis> syntax such as output = inpu
|
||||||
<td><code>popcount(v0)</code></td>
|
<td><code>popcount(v0)</code></td>
|
||||||
<td>Count 1 bits in v0.</td>
|
<td>Count 1 bits in v0.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>LZCOUNT</td>
|
||||||
|
<td><code>lzcount(v0)</code></td>
|
||||||
|
<td>Counts the number of leading zero bits in v0.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>INT_EQUAL</td>
|
<td>INT_EQUAL</td>
|
||||||
<td><code>v0 == v1</code></td>
|
<td><code>v0 == v1</code></td>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<title>SLEIGH</title>
|
<title>SLEIGH</title>
|
||||||
<subtitle>A Language for Rapid Processor Specification</subtitle>
|
<subtitle>A Language for Rapid Processor Specification</subtitle>
|
||||||
<pubdate>Originally published December 16, 2005</pubdate>
|
<pubdate>Originally published December 16, 2005</pubdate>
|
||||||
<releaseinfo>Last updated August 24, 2022</releaseinfo>
|
<releaseinfo>Last updated March 2, 2023</releaseinfo>
|
||||||
</info>
|
</info>
|
||||||
<simplesect id="sleigh_history">
|
<simplesect id="sleigh_history">
|
||||||
<info>
|
<info>
|
||||||
|
@ -279,7 +279,8 @@ general purpose processor instruction sets. They break up into groups.
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Logical</td>
|
<td>Logical</td>
|
||||||
<td><code>INT_NEGATE, INT_XOR, INT_AND, INT_OR, INT_LEFT, INT_RIGHT, INT_SRIGHT, POPCOUNT</code></td>
|
<td><code>INT_NEGATE, INT_XOR, INT_AND, INT_OR, INT_LEFT, INT_RIGHT, INT_SRIGHT,
|
||||||
|
POPCOUNT, LZCOUNT</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Integer Comparison</td>
|
<td>Integer Comparison</td>
|
||||||
|
@ -3856,6 +3857,12 @@ to lowest.
|
||||||
<td>Count the number of 1 bits in v0.
|
<td>Count the number of 1 bits in v0.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>LZCOUNT</code></td>
|
||||||
|
<td><code>lzcount(v0)</code></td>
|
||||||
|
<td>Count the number of leading 0 bits in v0.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>(simulated)</code></td>
|
<td><code>(simulated)</code></td>
|
||||||
<td><code>v0[6,1]</code></td>
|
<td><code>v0[6,1]</code></td>
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
/* ###
|
|
||||||
* IP: GHIDRA
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package ghidra.pcode.emulate.callother;
|
|
||||||
|
|
||||||
import ghidra.pcode.emulate.Emulate;
|
|
||||||
import ghidra.pcode.memstate.MemoryState;
|
|
||||||
import ghidra.pcodeCPort.error.LowlevelError;
|
|
||||||
import ghidra.program.model.pcode.Varnode;
|
|
||||||
|
|
||||||
public class CountLeadingOnesOpBehavior implements OpBehaviorOther {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void evaluate(Emulate emu, Varnode out, Varnode[] inputs) {
|
|
||||||
|
|
||||||
if (out == null) {
|
|
||||||
throw new LowlevelError("CALLOTHER: Count Leading Ones op missing required output");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputs.length != 2 || inputs[1].getSize() == 0 || inputs[1].isConstant()) {
|
|
||||||
throw new LowlevelError(
|
|
||||||
"CALLOTHER: Count Leading Ones op requires one non-constant varnode input");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add support for larger varnode sizes
|
|
||||||
|
|
||||||
Varnode in = inputs[1];
|
|
||||||
if (in.getSize() > 8 || out.getSize() > 8) {
|
|
||||||
throw new LowlevelError(
|
|
||||||
"CALLOTHER: Count Leading Ones op only supports varnodes of size 8-bytes or less");
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryState memoryState = emu.getMemoryState();
|
|
||||||
|
|
||||||
long value = memoryState.getValue(in);
|
|
||||||
long mask = 1L << ((in.getSize() * 8) - 1);
|
|
||||||
long count = 0;
|
|
||||||
while ( (mask & value) != 0 ) {
|
|
||||||
++count;
|
|
||||||
value = value << 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memoryState.setValue(out, count);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
/* ###
|
|
||||||
* IP: GHIDRA
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package ghidra.pcode.emulate.callother;
|
|
||||||
|
|
||||||
import ghidra.pcode.emulate.Emulate;
|
|
||||||
import ghidra.pcode.memstate.MemoryState;
|
|
||||||
import ghidra.pcodeCPort.error.LowlevelError;
|
|
||||||
import ghidra.program.model.pcode.Varnode;
|
|
||||||
|
|
||||||
public class CountLeadingZerosOpBehavior implements OpBehaviorOther {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void evaluate(Emulate emu, Varnode out, Varnode[] inputs) {
|
|
||||||
|
|
||||||
if (out == null) {
|
|
||||||
throw new LowlevelError("CALLOTHER: Count Leading Zeros op missing required output");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputs.length != 2 || inputs[1].getSize() == 0 || inputs[1].isConstant()) {
|
|
||||||
throw new LowlevelError(
|
|
||||||
"CALLOTHER: Count Leading Zeros op requires one non-constant varnode input");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add support for larger varnode sizes
|
|
||||||
|
|
||||||
Varnode in = inputs[1];
|
|
||||||
if (in.getSize() > 8 || out.getSize() > 8) {
|
|
||||||
throw new LowlevelError(
|
|
||||||
"CALLOTHER: Count Leading Zeros op only supports varnodes of size 8-bytes or less");
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryState memoryState = emu.getMemoryState();
|
|
||||||
|
|
||||||
long value = memoryState.getValue(in);
|
|
||||||
long mask = 1L << ((in.getSize() * 8) - 1);
|
|
||||||
long count = 0;
|
|
||||||
while (mask != 0) {
|
|
||||||
if ((mask & value) != 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++count;
|
|
||||||
mask >>>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memoryState.setValue(out, count);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -104,6 +104,7 @@ public class OpBehaviorFactory {
|
||||||
opBehaviorMap.put(PcodeOp.INSERT, new SpecialOpBehavior(PcodeOp.INSERT));
|
opBehaviorMap.put(PcodeOp.INSERT, new SpecialOpBehavior(PcodeOp.INSERT));
|
||||||
opBehaviorMap.put(PcodeOp.EXTRACT, new SpecialOpBehavior(PcodeOp.EXTRACT));
|
opBehaviorMap.put(PcodeOp.EXTRACT, new SpecialOpBehavior(PcodeOp.EXTRACT));
|
||||||
opBehaviorMap.put(PcodeOp.POPCOUNT, new OpBehaviorPopcount());
|
opBehaviorMap.put(PcodeOp.POPCOUNT, new OpBehaviorPopcount());
|
||||||
|
opBehaviorMap.put(PcodeOp.LZCOUNT, new OpBehaviorLzcount());
|
||||||
}
|
}
|
||||||
|
|
||||||
private OpBehaviorFactory() {
|
private OpBehaviorFactory() {
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.pcode.opbehavior;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import ghidra.program.model.pcode.PcodeOp;
|
||||||
|
|
||||||
|
public class OpBehaviorLzcount extends UnaryOpBehavior {
|
||||||
|
|
||||||
|
public OpBehaviorLzcount() {
|
||||||
|
super(PcodeOp.LZCOUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long evaluateUnary(int sizeout, int sizein, long val) {
|
||||||
|
long mask = 1L << ((sizein * 8) - 1);
|
||||||
|
long count = 0;
|
||||||
|
while (mask != 0) {
|
||||||
|
if ((mask & val) != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++count;
|
||||||
|
mask >>>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigInteger evaluateUnary(int sizeout, int sizein, BigInteger unsignedIn1) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -113,6 +113,7 @@ public enum OpCode {
|
||||||
CPUI_INSERT,
|
CPUI_INSERT,
|
||||||
CPUI_EXTRACT,
|
CPUI_EXTRACT,
|
||||||
CPUI_POPCOUNT,
|
CPUI_POPCOUNT,
|
||||||
|
CPUI_LZCOUNT,
|
||||||
|
|
||||||
CPUI_MAX;
|
CPUI_MAX;
|
||||||
|
|
||||||
|
@ -203,7 +204,8 @@ public enum OpCode {
|
||||||
"UNUSED1", "FLOAT_NAN", "FLOAT_ADD", "FLOAT_DIV", "FLOAT_MULT", "FLOAT_SUB",
|
"UNUSED1", "FLOAT_NAN", "FLOAT_ADD", "FLOAT_DIV", "FLOAT_MULT", "FLOAT_SUB",
|
||||||
"FLOAT_NEG", "FLOAT_ABS", "FLOAT_SQRT", "INT2FLOAT", "FLOAT2FLOAT", "TRUNC", "CEIL",
|
"FLOAT_NEG", "FLOAT_ABS", "FLOAT_SQRT", "INT2FLOAT", "FLOAT2FLOAT", "TRUNC", "CEIL",
|
||||||
"FLOOR", "ROUND", "BUILD", "DELAY_SLOT", "PIECE", "SUBPIECE", "CAST", "LABEL",
|
"FLOOR", "ROUND", "BUILD", "DELAY_SLOT", "PIECE", "SUBPIECE", "CAST", "LABEL",
|
||||||
"CROSSBUILD", "SEGMENTOP", "CPOOLREF", "NEW", "INSERT", "EXTRACT", "POPCOUNT" };
|
"CROSSBUILD", "SEGMENTOP", "CPOOLREF", "NEW", "INSERT", "EXTRACT", "POPCOUNT",
|
||||||
|
"LZCOUNT" };
|
||||||
|
|
||||||
public static String get_opname(OpCode op) {
|
public static String get_opname(OpCode op) {
|
||||||
return opcode_name[op.ordinal()];
|
return opcode_name[op.ordinal()];
|
||||||
|
@ -212,7 +214,7 @@ public enum OpCode {
|
||||||
static final int opcode_indices[] = { 0, 39, 37, 40, 38, 4, 6, 60, 7, 8, 9, 64, 5, 57, 1, 68, 66,
|
static final int opcode_indices[] = { 0, 39, 37, 40, 38, 4, 6, 60, 7, 8, 9, 64, 5, 57, 1, 68, 66,
|
||||||
61, 71, 55, 52, 47, 48, 41, 43, 44, 49, 46, 51, 42, 53, 50, 58, 70, 54, 24, 19, 27, 21,
|
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,
|
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, 72, 10, 59, 67, 3, 63, 56, 45 };
|
65, 2, 73, 69, 62, 72, 10, 59, 67, 3, 63, 56, 45 };
|
||||||
|
|
||||||
public static OpCode get_opcode(String nm) { // Use binary search to find name
|
public static OpCode get_opcode(String nm) { // Use binary search to find name
|
||||||
int min = 1; // Don't include BLANK
|
int min = 1; // Don't include BLANK
|
||||||
|
|
|
@ -996,6 +996,9 @@ public abstract class PcodeCompile {
|
||||||
if ("popcount".equals(name) && hasOperands(1, operands, location, name)) {
|
if ("popcount".equals(name) && hasOperands(1, operands, location, name)) {
|
||||||
return createOp(location, OpCode.CPUI_POPCOUNT, r);
|
return createOp(location, OpCode.CPUI_POPCOUNT, r);
|
||||||
}
|
}
|
||||||
|
if ("lzcount".equals(name) && hasOperands(1, operands, location, name)) {
|
||||||
|
return createOp(location, OpCode.CPUI_LZCOUNT, r);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1073,6 +1076,9 @@ public abstract class PcodeCompile {
|
||||||
if ("popcount".equals(name)) {
|
if ("popcount".equals(name)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if ("lzcount".equals(name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class DynamicHash {
|
||||||
0, // CAST is skipped
|
0, // CAST is skipped
|
||||||
PcodeOp.INT_ADD, PcodeOp.INT_ADD, // PTRADD and PTRSUB hash same as INT_ADD
|
PcodeOp.INT_ADD, PcodeOp.INT_ADD, // PTRADD and PTRSUB hash same as INT_ADD
|
||||||
PcodeOp.SEGMENTOP, PcodeOp.CPOOLREF, PcodeOp.NEW, PcodeOp.INSERT, PcodeOp.EXTRACT,
|
PcodeOp.SEGMENTOP, PcodeOp.CPOOLREF, PcodeOp.NEW, PcodeOp.INSERT, PcodeOp.EXTRACT,
|
||||||
PcodeOp.POPCOUNT };
|
PcodeOp.POPCOUNT, PcodeOp.LZCOUNT };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An edge between a Varnode and a PcodeOp
|
* An edge between a Varnode and a PcodeOp
|
||||||
|
|
|
@ -132,8 +132,9 @@ public class PcodeOp {
|
||||||
public static final int INSERT = 70;
|
public static final int INSERT = 70;
|
||||||
public static final int EXTRACT = 71;
|
public static final int EXTRACT = 71;
|
||||||
public static final int POPCOUNT = 72;
|
public static final int POPCOUNT = 72;
|
||||||
|
public static final int LZCOUNT = 73;
|
||||||
|
|
||||||
public static final int PCODE_MAX = 73;
|
public static final int PCODE_MAX = 74;
|
||||||
|
|
||||||
private static Hashtable<String, Integer> opcodeTable;
|
private static Hashtable<String, Integer> opcodeTable;
|
||||||
|
|
||||||
|
@ -689,6 +690,8 @@ public class PcodeOp {
|
||||||
return "EXTRACT";
|
return "EXTRACT";
|
||||||
case POPCOUNT:
|
case POPCOUNT:
|
||||||
return "POPCOUNT";
|
return "POPCOUNT";
|
||||||
|
case LZCOUNT:
|
||||||
|
return "LZCOUNT";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return "INVALID_OP";
|
return "INVALID_OP";
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
<processor_spec>
|
<processor_spec>
|
||||||
<properties>
|
<properties>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.m68kEmulateInstructionStateModifier"/>
|
|
||||||
<property key="assemblyRating:68000:BE:32:default" value="PLATINUM"/>
|
<property key="assemblyRating:68000:BE:32:default" value="PLATINUM"/>
|
||||||
</properties>
|
</properties>
|
||||||
<programcounter register="PC"/>
|
<programcounter register="PC"/>
|
||||||
|
|
|
@ -825,8 +825,6 @@ with : extGUARD=1 {
|
||||||
logflags(); tmp:4 = e2l; getbitfield(tmp, f_off, f_wd); f_reg = tmp; resbitflags(f_reg, f_wd-1);
|
logflags(); tmp:4 = e2l; getbitfield(tmp, f_off, f_wd); f_reg = tmp; resbitflags(f_reg, f_wd-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
define pcodeop countLeadingZeros;
|
|
||||||
|
|
||||||
:bfffo e2l{f_off:f_wd},f_reg is opbig=0xed & op67=3 & $(DAT_DIR_CTL_ADDR_MODES); f_off & f_wd & f_reg & flddo=0 & fldoffdat=0 & flddw=0 & fldwddat=0; e2l
|
:bfffo e2l{f_off:f_wd},f_reg is opbig=0xed & op67=3 & $(DAT_DIR_CTL_ADDR_MODES); f_off & f_wd & f_reg & flddo=0 & fldoffdat=0 & flddw=0 & fldwddat=0; e2l
|
||||||
[ savmod2=savmod1; regtsan=regtfan; ] {
|
[ savmod2=savmod1; regtsan=regtfan; ] {
|
||||||
# "Find First One in Bit Field" pronounced "boo-foe"
|
# "Find First One in Bit Field" pronounced "boo-foe"
|
||||||
|
@ -839,7 +837,7 @@ define pcodeop countLeadingZeros;
|
||||||
ZF = (tmp == 0);
|
ZF = (tmp == 0);
|
||||||
VF = 0;
|
VF = 0;
|
||||||
CF = 0;
|
CF = 0;
|
||||||
tmp2:4 = countLeadingZeros(tmp);
|
tmp2:4 = lzcount(tmp);
|
||||||
# NB- it seems the MSB left most bit is really at offset 0,
|
# NB- it seems the MSB left most bit is really at offset 0,
|
||||||
# and the right LSB is at offset 31
|
# and the right LSB is at offset 31
|
||||||
tmp3:4 = tmp2 % 32:4; # need mod for when there are all zeros, when tmp2 would = 32
|
tmp3:4 = tmp2 % 32:4; # need mod for when there are all zeros, when tmp2 would = 32
|
||||||
|
|
|
@ -17,7 +17,6 @@ package ghidra.program.emulation;
|
||||||
|
|
||||||
import ghidra.pcode.emulate.Emulate;
|
import ghidra.pcode.emulate.Emulate;
|
||||||
import ghidra.pcode.emulate.EmulateInstructionStateModifier;
|
import ghidra.pcode.emulate.EmulateInstructionStateModifier;
|
||||||
import ghidra.pcode.emulate.callother.CountLeadingZerosOpBehavior;
|
|
||||||
import ghidra.pcode.emulate.callother.OpBehaviorOther;
|
import ghidra.pcode.emulate.callother.OpBehaviorOther;
|
||||||
import ghidra.pcode.memstate.MemoryState;
|
import ghidra.pcode.memstate.MemoryState;
|
||||||
import ghidra.pcodeCPort.error.LowlevelError;
|
import ghidra.pcodeCPort.error.LowlevelError;
|
||||||
|
@ -45,10 +44,6 @@ public class m68kEmulateInstructionStateModifier extends EmulateInstructionState
|
||||||
ISA_MODE0 = new RegisterValue(isaModeReg, BigInteger.ZERO);
|
ISA_MODE0 = new RegisterValue(isaModeReg, BigInteger.ZERO);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// These classes are defined here:
|
|
||||||
// ghidra/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/emulate/callother
|
|
||||||
|
|
||||||
registerPcodeOpBehavior("countLeadingZeros", new CountLeadingZerosOpBehavior());
|
|
||||||
registerPcodeOpBehavior("findFirstOne", new FindFirstOneOpBehavior());
|
registerPcodeOpBehavior("findFirstOne", new FindFirstOneOpBehavior());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,6 @@ define context contextreg
|
||||||
ARMcondCk = (35,35) # Finished ARM condition check phase
|
ARMcondCk = (35,35) # Finished ARM condition check phase
|
||||||
;
|
;
|
||||||
|
|
||||||
define pcodeop count_leading_zeroes;
|
|
||||||
define pcodeop coprocessor_function;
|
define pcodeop coprocessor_function;
|
||||||
define pcodeop coprocessor_function2;
|
define pcodeop coprocessor_function2;
|
||||||
define pcodeop coprocessor_load;
|
define pcodeop coprocessor_load;
|
||||||
|
|
|
@ -1608,7 +1608,7 @@ define pcodeop IndexCheck;
|
||||||
:clz^ItCond Rd0811,Rm0003 is TMode=1 & ItCond & op4=0xfab & Rm0003; op12=15 & Rd0811
|
:clz^ItCond Rd0811,Rm0003 is TMode=1 & ItCond & op4=0xfab & Rm0003; op12=15 & Rd0811
|
||||||
{
|
{
|
||||||
build ItCond;
|
build ItCond;
|
||||||
Rd0811 = count_leading_zeroes(Rm0003);
|
Rd0811 = lzcount(Rm0003);
|
||||||
}
|
}
|
||||||
|
|
||||||
:cmn^ItCond Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=8 & thc0404=1 & Rn0003; thc1515=0 & thc0811=15) & ThumbExpandImm12
|
:cmn^ItCond Rn0003,ThumbExpandImm12 is TMode=1 & ItCond & (op11=0x1e & thc0909=0 & sop0508=8 & thc0404=1 & Rn0003; thc1515=0 & thc0811=15) & ThumbExpandImm12
|
||||||
|
|
|
@ -2484,7 +2484,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
|
||||||
{
|
{
|
||||||
build COND;
|
build COND;
|
||||||
build rm;
|
build rm;
|
||||||
Rd = count_leading_zeroes(rm);
|
Rd = lzcount(rm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@endif # VERSION_5
|
@endif # VERSION_5
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.math.BigInteger;
|
||||||
|
|
||||||
import ghidra.pcode.emulate.Emulate;
|
import ghidra.pcode.emulate.Emulate;
|
||||||
import ghidra.pcode.emulate.EmulateInstructionStateModifier;
|
import ghidra.pcode.emulate.EmulateInstructionStateModifier;
|
||||||
import ghidra.pcode.emulate.callother.CountLeadingZerosOpBehavior;
|
|
||||||
import ghidra.pcode.error.LowlevelError;
|
import ghidra.pcode.error.LowlevelError;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
@ -46,8 +45,6 @@ public class ARMEmulateInstructionStateModifier extends EmulateInstructionStateM
|
||||||
aMode = new RegisterValue(TModeReg, BigInteger.ZERO);
|
aMode = new RegisterValue(TModeReg, BigInteger.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerPcodeOpBehavior("count_leading_zeroes", new CountLeadingZerosOpBehavior());
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We could registerPcodeOpBehavior for one or more of the following pcodeop's:
|
* We could registerPcodeOpBehavior for one or more of the following pcodeop's:
|
||||||
*
|
*
|
||||||
|
@ -85,7 +82,6 @@ public class ARMEmulateInstructionStateModifier extends EmulateInstructionStateM
|
||||||
coprocessor_store2
|
coprocessor_store2
|
||||||
coprocessor_storelong
|
coprocessor_storelong
|
||||||
coprocessor_storelong2
|
coprocessor_storelong2
|
||||||
count_leading_zeroes
|
|
||||||
disableDataAbortInterrupts
|
disableDataAbortInterrupts
|
||||||
disableFIQinterrupts
|
disableFIQinterrupts
|
||||||
disableIRQinterrupts
|
disableIRQinterrupts
|
||||||
|
|
|
@ -1001,12 +1001,6 @@ define pcodeop getCopRegH;
|
||||||
define pcodeop setCopReg;
|
define pcodeop setCopReg;
|
||||||
define pcodeop setCopRegH;
|
define pcodeop setCopRegH;
|
||||||
|
|
||||||
# countLeadingOnes(val)
|
|
||||||
define pcodeop countLeadingOnes;
|
|
||||||
|
|
||||||
# countLeadingZeros(val)
|
|
||||||
define pcodeop countLeadingZeros;
|
|
||||||
|
|
||||||
# extractField(value, msbd, lsb)
|
# extractField(value, msbd, lsb)
|
||||||
define pcodeop extractField;
|
define pcodeop extractField;
|
||||||
|
|
||||||
|
|
|
@ -980,13 +980,13 @@ define pcodeop SYNC;
|
||||||
# 0111 00ss ssst tttt dddd d000 0010 0001
|
# 0111 00ss ssst tttt dddd d000 0010 0001
|
||||||
:clo RD, RSsrc is $(AMODE) & REL6=0 & prime=0x1C & sa=0x0 & fct=0x21 & RD & RSsrc {
|
:clo RD, RSsrc is $(AMODE) & REL6=0 & prime=0x1C & sa=0x0 & fct=0x21 & RD & RSsrc {
|
||||||
# Count leading ones in a word
|
# Count leading ones in a word
|
||||||
RD = countLeadingOnes( RSsrc );
|
RD = lzcount( ~RSsrc );
|
||||||
}
|
}
|
||||||
|
|
||||||
# 0111 00ss ssst tttt dddd d000 0010 0000
|
# 0111 00ss ssst tttt dddd d000 0010 0000
|
||||||
:clz RD, RSsrc is $(AMODE) & REL6=0 & prime=0x1C & sa=0x0 & fct=0x20 & RD & RSsrc {
|
:clz RD, RSsrc is $(AMODE) & REL6=0 & prime=0x1C & sa=0x0 & fct=0x20 & RD & RSsrc {
|
||||||
# Count leading zeros in a word
|
# Count leading zeros in a word
|
||||||
RD = countLeadingZeros( RSsrc );
|
RD = lzcount( RSsrc );
|
||||||
}
|
}
|
||||||
|
|
||||||
# 0000 00ss ssst tttt 0000 0000 0001 1010
|
# 0000 00ss ssst tttt 0000 0000 0001 1010
|
||||||
|
@ -1573,11 +1573,11 @@ define pcodeop SYNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
:clo RD, RSsrc is $(AMODE) & REL6=1 & prime=0x00 & op=0 & sa=0x1 & fct=0x11 & RD & RSsrc {
|
:clo RD, RSsrc is $(AMODE) & REL6=1 & prime=0x00 & op=0 & sa=0x1 & fct=0x11 & RD & RSsrc {
|
||||||
RD = countLeadingOnes( RSsrc );
|
RD = lzcount( ~RSsrc );
|
||||||
}
|
}
|
||||||
|
|
||||||
:clz RD, RSsrc is $(AMODE) & REL6=1 & prime=0x00 & op=0 & sa=0x1 & fct=0x10 & RD & RSsrc {
|
:clz RD, RSsrc is $(AMODE) & REL6=1 & prime=0x00 & op=0 & sa=0x1 & fct=0x10 & RD & RSsrc {
|
||||||
RD = countLeadingZeros( RSsrc );
|
RD = lzcount( RSsrc );
|
||||||
}
|
}
|
||||||
|
|
||||||
:div RD, RS32src, RT32src is $(AMODE) & REL6=1 & prime=0x00 & fct=0x1A & fct2=0x02 & RD & RS32src & RT32src {
|
:div RD, RS32src, RT32src is $(AMODE) & REL6=1 & prime=0x00 & fct=0x1A & fct2=0x02 & RD & RS32src & RT32src {
|
||||||
|
|
|
@ -7,11 +7,11 @@
|
||||||
|
|
||||||
# 0111 00ss ssst tttt dddd d000 0010 0101
|
# 0111 00ss ssst tttt dddd d000 0010 0101
|
||||||
:dclo RD, RSsrc is $(AMODE) & ((REL6=0 & prime=0x1C & sa=0x0 & fct=0x25) | (REL6=1 & prime=0x00 & sa=0x1 & fct=0x13 & op=0)) & RD & RSsrc {
|
:dclo RD, RSsrc is $(AMODE) & ((REL6=0 & prime=0x1C & sa=0x0 & fct=0x25) | (REL6=1 & prime=0x00 & sa=0x1 & fct=0x13 & op=0)) & RD & RSsrc {
|
||||||
RD = countLeadingOnes( RSsrc );
|
RD = lzcount( ~RSsrc );
|
||||||
}
|
}
|
||||||
# 0111 00ss ssst tttt dddd d000 0010 0100
|
# 0111 00ss ssst tttt dddd d000 0010 0100
|
||||||
:dclz RD, RSsrc is $(AMODE) & ((REL6=0 & prime=0x1C & sa=0x0 & fct=0x24) | (REL6=1 & prime=0x00 & sa=0x1 & fct=0x12 & op=0)) & RD & RSsrc {
|
:dclz RD, RSsrc is $(AMODE) & ((REL6=0 & prime=0x1C & sa=0x0 & fct=0x24) | (REL6=1 & prime=0x00 & sa=0x1 & fct=0x12 & op=0)) & RD & RSsrc {
|
||||||
RD = countLeadingZeros( RSsrc );
|
RD = lzcount( RSsrc );
|
||||||
}
|
}
|
||||||
|
|
||||||
# 0111 11ss ssst tttt mmmm mLLL LL00 0011
|
# 0111 11ss ssst tttt mmmm mLLL LL00 0011
|
||||||
|
|
|
@ -697,11 +697,11 @@ STORE_TOP16: STORE_SREG^ra,EXT_CODE4E(sp) is mic_listr6 & REL6=1 & STORE_SREG &
|
||||||
}
|
}
|
||||||
|
|
||||||
:clo mic_rt32_5, RS0L is ISA_MODE=1 & RELP=0 & mic_op=0b000000 & mic_rt32_5 & RS0L ; micb_poolax=0b111100 & micb_axf=0b0100101100 {
|
:clo mic_rt32_5, RS0L is ISA_MODE=1 & RELP=0 & mic_op=0b000000 & mic_rt32_5 & RS0L ; micb_poolax=0b111100 & micb_axf=0b0100101100 {
|
||||||
mic_rt32_5 = countLeadingOnes( RS0L );
|
mic_rt32_5 = lzcount( ~RS0L );
|
||||||
}
|
}
|
||||||
|
|
||||||
:clz mic_rt32_5, RS0L is ISA_MODE=1 & RELP=0 & mic_op=0b000000 & mic_rt32_5 & RS0L ; micb_poolax=0b111100 & micb_axf=0b0101101100 {
|
:clz mic_rt32_5, RS0L is ISA_MODE=1 & RELP=0 & mic_op=0b000000 & mic_rt32_5 & RS0L ; micb_poolax=0b111100 & micb_axf=0b0101101100 {
|
||||||
mic_rt32_5 = countLeadingZeros( RS0L );
|
mic_rt32_5 = lzcount( RS0L );
|
||||||
}
|
}
|
||||||
|
|
||||||
:cop2 EXT_MU23 is ISA_MODE=1 & RELP=0 & mic_op=0b000000 & mic_code ; micb_cop=0b010 & EXT_MU23 [ ext_32_code=mic_code; ] {
|
:cop2 EXT_MU23 is ISA_MODE=1 & RELP=0 & mic_op=0b000000 & mic_code ; micb_cop=0b010 & EXT_MU23 [ ext_32_code=mic_code; ] {
|
||||||
|
@ -1676,11 +1676,11 @@ STORE_TOP16: STORE_SREG^ra,EXT_CODE4E(sp) is mic_listr6 & REL6=1 & STORE_SREG &
|
||||||
}
|
}
|
||||||
|
|
||||||
:dclo mic_rt32_5, mic_rs32_0 is ISA_MODE=1 & RELP=0 & mic_op=0b010110 & mic_rt32_5 & mic_rs32_0 ; micb_poolax=0b111100 & micb_axf=0b0100101100 {
|
:dclo mic_rt32_5, mic_rs32_0 is ISA_MODE=1 & RELP=0 & mic_op=0b010110 & mic_rt32_5 & mic_rs32_0 ; micb_poolax=0b111100 & micb_axf=0b0100101100 {
|
||||||
mic_rt32_5 = countLeadingOnes( mic_rs32_0 );
|
mic_rt32_5 = lzcount( ~mic_rs32_0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
:dclz mic_rt32_5, mic_rs32_0 is ISA_MODE=1 & RELP=0 & mic_op=0b010110 & mic_rt32_5 & mic_rs32_0 ; micb_poolax=0b111100 & micb_axf=0b0101101100 {
|
:dclz mic_rt32_5, mic_rs32_0 is ISA_MODE=1 & RELP=0 & mic_op=0b010110 & mic_rt32_5 & mic_rs32_0 ; micb_poolax=0b111100 & micb_axf=0b0101101100 {
|
||||||
mic_rt32_5 = countLeadingZeros( mic_rs32_0 );
|
mic_rt32_5 = lzcount( mic_rs32_0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
:dext mic_rt32_5, mic_rs32_0, micb_pos, SIZEP is ISA_MODE=1 & RELP=0 & mic_op=0b010110 & REL6=1 & mic_rt32_5 & mic_rs32_0 ; micb_poolax=0b101100 & micb_pos & SIZEP {
|
:dext mic_rt32_5, mic_rs32_0, micb_pos, SIZEP is ISA_MODE=1 & RELP=0 & mic_op=0b010110 & REL6=1 & mic_rt32_5 & mic_rs32_0 ; micb_poolax=0b101100 & micb_pos & SIZEP {
|
||||||
|
|
|
@ -19,8 +19,6 @@ import java.math.BigInteger;
|
||||||
|
|
||||||
import ghidra.pcode.emulate.Emulate;
|
import ghidra.pcode.emulate.Emulate;
|
||||||
import ghidra.pcode.emulate.EmulateInstructionStateModifier;
|
import ghidra.pcode.emulate.EmulateInstructionStateModifier;
|
||||||
import ghidra.pcode.emulate.callother.CountLeadingOnesOpBehavior;
|
|
||||||
import ghidra.pcode.emulate.callother.CountLeadingZerosOpBehavior;
|
|
||||||
import ghidra.pcode.error.LowlevelError;
|
import ghidra.pcode.error.LowlevelError;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.lang.Register;
|
import ghidra.program.model.lang.Register;
|
||||||
|
@ -49,13 +47,6 @@ public class MIPSEmulateInstructionStateModifier extends EmulateInstructionState
|
||||||
ISA_MODE0 = new RegisterValue(isaModeReg, BigInteger.ZERO);
|
ISA_MODE0 = new RegisterValue(isaModeReg, BigInteger.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
// These classes are defined here:
|
|
||||||
// ghidra/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/emulate/callother
|
|
||||||
|
|
||||||
registerPcodeOpBehavior("countLeadingZeros", new CountLeadingZerosOpBehavior());
|
|
||||||
|
|
||||||
registerPcodeOpBehavior("countLeadingOnes", new CountLeadingOnesOpBehavior());
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We could registerPcodeOpBehavior for one or more of the following
|
* We could registerPcodeOpBehavior for one or more of the following
|
||||||
* pcodeop's:
|
* pcodeop's:
|
||||||
|
|
|
@ -1415,7 +1415,6 @@ attach variables vrC_8_15 [vr0_8_15 vr1_8_15 vr2_8_15 vr3_8_15 vr4_8_15 vr5_8_15
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
define pcodeop clearHistory;
|
define pcodeop clearHistory;
|
||||||
define pcodeop countLeadingZeros;
|
|
||||||
define pcodeop countTrailingZeros;
|
define pcodeop countTrailingZeros;
|
||||||
define pcodeop dataCacheBlockAllocate;
|
define pcodeop dataCacheBlockAllocate;
|
||||||
define pcodeop dataCacheBlockFlush;
|
define pcodeop dataCacheBlockFlush;
|
||||||
|
|
|
@ -814,13 +814,13 @@
|
||||||
#cntlzd r0,r0 0x7c 00 00 74
|
#cntlzd r0,r0 0x7c 00 00 74
|
||||||
:cntlzd A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=58 & Rc=0
|
:cntlzd A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=58 & Rc=0
|
||||||
{
|
{
|
||||||
A = countLeadingZeros(S);
|
A = lzcount(S);
|
||||||
}
|
}
|
||||||
|
|
||||||
#cntlzd. r0,r0 0x7c 00 00 75
|
#cntlzd. r0,r0 0x7c 00 00 75
|
||||||
:cntlzd. A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=58 & Rc=1
|
:cntlzd. A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=58 & Rc=1
|
||||||
{
|
{
|
||||||
A = countLeadingZeros(S);
|
A = lzcount(S);
|
||||||
cr0flags(A);
|
cr0flags(A);
|
||||||
}
|
}
|
||||||
@endif
|
@endif
|
||||||
|
@ -828,13 +828,13 @@
|
||||||
#cntlzw r0,r0 0x7c 00 00 34
|
#cntlzw r0,r0 0x7c 00 00 34
|
||||||
:cntlzw A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=26 & Rc=0
|
:cntlzw A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=26 & Rc=0
|
||||||
{
|
{
|
||||||
A = countLeadingZeros(S:4);
|
A = lzcount(S:4);
|
||||||
}
|
}
|
||||||
|
|
||||||
#cntlzw. r0,r0 0x7c 00 00 35
|
#cntlzw. r0,r0 0x7c 00 00 35
|
||||||
:cntlzw. A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=26 & Rc=1
|
:cntlzw. A,S is OP=31 & S & A & BITS_11_15=0 & XOP_1_10=26 & Rc=1
|
||||||
{
|
{
|
||||||
A = countLeadingZeros(S:4);
|
A = lzcount(S:4);
|
||||||
cr0flags(A);
|
cr0flags(A);
|
||||||
}
|
}
|
||||||
#===========================================================
|
#===========================================================
|
||||||
|
|
|
@ -19,7 +19,6 @@ import java.math.BigInteger;
|
||||||
|
|
||||||
import ghidra.pcode.emulate.Emulate;
|
import ghidra.pcode.emulate.Emulate;
|
||||||
import ghidra.pcode.emulate.EmulateInstructionStateModifier;
|
import ghidra.pcode.emulate.EmulateInstructionStateModifier;
|
||||||
import ghidra.pcode.emulate.callother.CountLeadingZerosOpBehavior;
|
|
||||||
import ghidra.pcode.emulate.callother.OpBehaviorOther;
|
import ghidra.pcode.emulate.callother.OpBehaviorOther;
|
||||||
import ghidra.pcode.memstate.MemoryState;
|
import ghidra.pcode.memstate.MemoryState;
|
||||||
import ghidra.pcodeCPort.error.LowlevelError;
|
import ghidra.pcodeCPort.error.LowlevelError;
|
||||||
|
@ -30,7 +29,6 @@ public class PPCEmulateInstructionStateModifier extends EmulateInstructionStateM
|
||||||
public PPCEmulateInstructionStateModifier(Emulate emu) {
|
public PPCEmulateInstructionStateModifier(Emulate emu) {
|
||||||
super(emu);
|
super(emu);
|
||||||
|
|
||||||
registerPcodeOpBehavior("countLeadingZeros", new CountLeadingZerosOpBehavior());
|
|
||||||
registerPcodeOpBehavior("vectorPermute", new vectorPermuteOpBehavior());
|
registerPcodeOpBehavior("vectorPermute", new vectorPermuteOpBehavior());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -490,8 +490,6 @@ define pcodeop cache_index_ivld;
|
||||||
define pcodeop cache_index_wb;
|
define pcodeop cache_index_wb;
|
||||||
define pcodeop cache_index_wi;
|
define pcodeop cache_index_wi;
|
||||||
define pcodeop round16;
|
define pcodeop round16;
|
||||||
define pcodeop leading_ones;
|
|
||||||
define pcodeop leading_zeros;
|
|
||||||
define pcodeop leading_signs;
|
define pcodeop leading_signs;
|
||||||
define pcodeop crc32;
|
define pcodeop crc32;
|
||||||
|
|
||||||
|
@ -1840,7 +1838,7 @@ SC: [a10]const0815Z10zz is PCPMode=0 & a10 & const0815Z10zz & op0003=8 & op0404=
|
||||||
# CLO D[c], D[a] (RR)
|
# CLO D[c], D[a] (RR)
|
||||||
:clo Rd2831,Rd0811 is PCPMode=0 & Rd0811 & op0007=0xf & op1215=0x0 ; Rd2831 & op1627=0x1c0
|
:clo Rd2831,Rd0811 is PCPMode=0 & Rd0811 & op0007=0xf & op1215=0x0 ; Rd2831 & op1627=0x1c0
|
||||||
{
|
{
|
||||||
Rd2831 = leading_ones(Rd0811);
|
Rd2831 = lzcount(~Rd0811);
|
||||||
}
|
}
|
||||||
|
|
||||||
# CLO.H D[c], D[a] (RR)
|
# CLO.H D[c], D[a] (RR)
|
||||||
|
@ -1848,8 +1846,8 @@ SC: [a10]const0815Z10zz is PCPMode=0 & a10 & const0815Z10zz & op0003=8 & op0404=
|
||||||
{
|
{
|
||||||
local tmp1:4 = zext(Rd0811[16,16]);
|
local tmp1:4 = zext(Rd0811[16,16]);
|
||||||
local tmp0:4 = zext(Rd0811[0,16]);
|
local tmp0:4 = zext(Rd0811[0,16]);
|
||||||
Rd2831[16,16] = leading_ones(tmp1);
|
Rd2831[16,16] = lzcount(~tmp1);
|
||||||
Rd2831[0,16] = leading_ones(tmp0);
|
Rd2831[0,16] = lzcount(~tmp0);
|
||||||
}
|
}
|
||||||
|
|
||||||
# CLS D[c], D[a] (RR)
|
# CLS D[c], D[a] (RR)
|
||||||
|
@ -1870,13 +1868,13 @@ SC: [a10]const0815Z10zz is PCPMode=0 & a10 & const0815Z10zz & op0003=8 & op0404=
|
||||||
# CLZ D[c], D[a] (RR)
|
# CLZ D[c], D[a] (RR)
|
||||||
:clz Rd2831,Rd0811 is PCPMode=0 & Rd0811 & op0007=0xf & op1215=0x0 ; Rd2831 & op1627=0x1b0
|
:clz Rd2831,Rd0811 is PCPMode=0 & Rd0811 & op0007=0xf & op1215=0x0 ; Rd2831 & op1627=0x1b0
|
||||||
{
|
{
|
||||||
Rd2831 = leading_zeros(Rd0811);
|
Rd2831 = lzcount(Rd0811);
|
||||||
}
|
}
|
||||||
|
|
||||||
# CLZ.H D[c], D[a] (RR)
|
# CLZ.H D[c], D[a] (RR)
|
||||||
:clz.h Rd2831,Rd0811 is PCPMode=0 & Rd0811 & op0007=0xf & op1215=0x0 ; Rd2831 & op1627=0x7c0
|
:clz.h Rd2831,Rd0811 is PCPMode=0 & Rd0811 & op0007=0xf & op1215=0x0 ; Rd2831 & op1627=0x7c0
|
||||||
{
|
{
|
||||||
local result:4 = (leading_zeros(Rd0811[16,16]) << 16) | leading_zeros(Rd0811[0,16]);
|
local result:4 = (lzcount(Rd0811[16,16]) << 16) | lzcount(Rd0811[0,16]);
|
||||||
Rd2831 = result;
|
Rd2831 = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,57 +11,22 @@ macro lzcntflags(input, output) {
|
||||||
|
|
||||||
:LZCNT Reg16, rm16 is vexMode=0 & opsize=0 & $(PRE_66) & $(PRE_F3) & byte=0x0F; byte=0xBD; Reg16 ... & rm16 {
|
:LZCNT Reg16, rm16 is vexMode=0 & opsize=0 & $(PRE_66) & $(PRE_F3) & byte=0x0F; byte=0xBD; Reg16 ... & rm16 {
|
||||||
|
|
||||||
countTmp:2 = 0;
|
Reg16 = lzcount(rm16);
|
||||||
inputTmp:2 = rm16;
|
lzcntflags(rm16, Reg16);
|
||||||
|
|
||||||
<loopbegin>
|
|
||||||
if ((inputTmp & 0x8000) != 0) goto <loopend>;
|
|
||||||
|
|
||||||
countTmp = countTmp + 1;
|
|
||||||
inputTmp = (inputTmp << 1) | 1;
|
|
||||||
goto <loopbegin>;
|
|
||||||
|
|
||||||
<loopend>
|
|
||||||
lzcntflags(rm16, countTmp);
|
|
||||||
Reg16 = countTmp;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:LZCNT Reg32, rm32 is vexMode=0 & opsize=1 & $(PRE_F3) & byte=0x0F; byte=0xBD; Reg32 ... & check_Reg32_dest ... & rm32 {
|
:LZCNT Reg32, rm32 is vexMode=0 & opsize=1 & $(PRE_F3) & byte=0x0F; byte=0xBD; Reg32 ... & check_Reg32_dest ... & rm32 {
|
||||||
|
|
||||||
countTmp:4 = 0;
|
Reg32 = lzcount(rm32);
|
||||||
inputTmp:4 = rm32;
|
lzcntflags(rm32, Reg32);
|
||||||
|
|
||||||
<loopbegin>
|
|
||||||
if ((inputTmp & 0x80000000) != 0) goto <loopend>;
|
|
||||||
|
|
||||||
countTmp = countTmp + 1;
|
|
||||||
inputTmp = (inputTmp << 1) | 1;
|
|
||||||
goto <loopbegin>;
|
|
||||||
|
|
||||||
<loopend>
|
|
||||||
lzcntflags(rm32, countTmp);
|
|
||||||
Reg32 = countTmp;
|
|
||||||
build check_Reg32_dest;
|
build check_Reg32_dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ifdef IA64
|
@ifdef IA64
|
||||||
:LZCNT Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBD; Reg64 ... & rm64 {
|
:LZCNT Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBD; Reg64 ... & rm64 {
|
||||||
|
|
||||||
countTmp:8 = 0;
|
Reg64 = lzcount(rm64);
|
||||||
inputTmp:8 = rm64;
|
lzcntflags(rm64, Reg64);
|
||||||
|
|
||||||
<loopbegin>
|
|
||||||
if ((inputTmp & 0x8000000000000000) != 0) goto <loopend>;
|
|
||||||
|
|
||||||
countTmp = countTmp + 1;
|
|
||||||
inputTmp = (inputTmp << 1) | 1;
|
|
||||||
goto <loopbegin>;
|
|
||||||
|
|
||||||
<loopend>
|
|
||||||
lzcntflags(rm64, countTmp);
|
|
||||||
Reg64 = countTmp;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
|
@ -661,6 +661,7 @@ exprSingle returns Expression:
|
||||||
| pcodeop='floor' '(' op1=expr ')'
|
| pcodeop='floor' '(' op1=expr ')'
|
||||||
| pcodeop='round' '(' op1=expr ')'
|
| pcodeop='round' '(' op1=expr ')'
|
||||||
| pcodeop='popcount' '(' op1=expr ')'
|
| pcodeop='popcount' '(' op1=expr ')'
|
||||||
|
| pcodeop='lzcount' '(' op1=expr ')'
|
||||||
| pcodeop='cpool' '(' op1=expr ',' op2=expr ',' op3=expr ')'
|
| pcodeop='cpool' '(' op1=expr ',' op2=expr ',' op3=expr ')'
|
||||||
| pcodeop='newobject' '(' op1=newObjParams ')'
|
| pcodeop='newobject' '(' op1=newObjParams ')'
|
||||||
| op=[macroOrPcode] op1=paramlist
|
| op=[macroOrPcode] op1=paramlist
|
||||||
|
|
|
@ -676,6 +676,49 @@ count is zero extended into the output varnode.
|
||||||
</div>
|
</div>
|
||||||
<div class="sect2">
|
<div class="sect2">
|
||||||
<div class="titlepage"><div><div><h3 class="title">
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
|
<a name="cpui_lzcount"></a>LZCOUNT</h3></div></div></div>
|
||||||
|
<div class="informalexample"><div class="table">
|
||||||
|
<a name="lzcount.htmltable"></a><table xml:id="lzcount.htmltable" frame="above" width="80%" rules="groups">
|
||||||
|
<col width="23%">
|
||||||
|
<col width="15%">
|
||||||
|
<col width="61%">
|
||||||
|
<thead><tr>
|
||||||
|
<td align="center" colspan="2"><span class="bold"><strong>Parameters</strong></span></td>
|
||||||
|
<td><span class="bold"><strong>Description</strong></span></td>
|
||||||
|
</tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="right">input0</td>
|
||||||
|
<td></td>
|
||||||
|
<td>Input varnode to count.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="right">output</td>
|
||||||
|
<td></td>
|
||||||
|
<td>Resulting integer varnode containing count.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="2"><span class="bold"><strong>Semantic statement</strong></span></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td colspan="2"><code class="code">output = lzcount(input0);</code></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div></div>
|
||||||
|
<p>
|
||||||
|
This operator counts the number of zeros starting at the most significant bit.
|
||||||
|
For instance, for a 4-byte varnode, a value of 0 returns 32, a value of 1
|
||||||
|
returns 31, and the value 2<sup>31</sup> returns 0.
|
||||||
|
The resulting count is zero extended into the output varnode.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="sect2">
|
||||||
|
<div class="titlepage"><div><div><h3 class="title">
|
||||||
<a name="cpui_int_equal"></a>INT_EQUAL</h3></div></div></div>
|
<a name="cpui_int_equal"></a>INT_EQUAL</h3></div></div></div>
|
||||||
<div class="informalexample"><div class="table">
|
<div class="informalexample"><div class="table">
|
||||||
<a name="intequal.htmltable"></a><table xml:id="intequal.htmltable" frame="above" width="80%" rules="groups">
|
<a name="intequal.htmltable"></a><table xml:id="intequal.htmltable" frame="above" width="80%" rules="groups">
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<div>
|
<div>
|
||||||
<div><h1 class="title">
|
<div><h1 class="title">
|
||||||
<a name="pcoderef_title"></a>P-Code Reference Manual</h1></div>
|
<a name="pcoderef_title"></a>P-Code Reference Manual</h1></div>
|
||||||
<div><p class="releaseinfo">Last updated September 5, 2019</p></div>
|
<div><p class="releaseinfo">Last updated March 2, 2023</p></div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
</div>
|
</div>
|
||||||
|
@ -117,52 +117,58 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_equal" title="INT_EQUAL">INT_EQUAL</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_lzcount" title="LZCOUNT">LZCOUNT</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_mult" title="INT_MULT">INT_MULT</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_mult" title="INT_MULT">INT_MULT</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_float_floor" title="FLOAT_FLOOR">FLOAT_FLOOR</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_float_floor" title="FLOAT_FLOOR">FLOAT_FLOOR</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_notequal" title="INT_NOTEQUAL">INT_NOTEQUAL</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_equal" title="INT_EQUAL">INT_EQUAL</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_div" title="INT_DIV">INT_DIV</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_div" title="INT_DIV">INT_DIV</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_float_round" title="FLOAT_ROUND">FLOAT_ROUND</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_float_round" title="FLOAT_ROUND">FLOAT_ROUND</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_less" title="INT_LESS">INT_LESS</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_notequal" title="INT_NOTEQUAL">INT_NOTEQUAL</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_rem" title="INT_REM">INT_REM</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_rem" title="INT_REM">INT_REM</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_float_nan" title="FLOAT_NAN">FLOAT_NAN</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_float_nan" title="FLOAT_NAN">FLOAT_NAN</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_sless" title="INT_SLESS">INT_SLESS</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_less" title="INT_LESS">INT_LESS</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_sdiv" title="INT_SDIV">INT_SDIV</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_sdiv" title="INT_SDIV">INT_SDIV</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int2float" title="INT2FLOAT">INT2FLOAT</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int2float" title="INT2FLOAT">INT2FLOAT</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_lessequal" title="INT_LESSEQUAL">INT_LESSEQUAL</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_sless" title="INT_SLESS">INT_SLESS</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_srem" title="INT_SREM">INT_SREM</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_srem" title="INT_SREM">INT_SREM</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_float2float" title="FLOAT2FLOAT">FLOAT2FLOAT</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_float2float" title="FLOAT2FLOAT">FLOAT2FLOAT</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_slessequal" title="INT_SLESSEQUAL">INT_SLESSEQUAL</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_lessequal" title="INT_LESSEQUAL">INT_LESSEQUAL</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_bool_negate" title="BOOL_NEGATE">BOOL_NEGATE</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_bool_negate" title="BOOL_NEGATE">BOOL_NEGATE</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_trunc" title="TRUNC">TRUNC</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_trunc" title="TRUNC">TRUNC</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_zext" title="INT_ZEXT">INT_ZEXT</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_slessequal" title="INT_SLESSEQUAL">INT_SLESSEQUAL</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_bool_xor" title="BOOL_XOR">BOOL_XOR</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_bool_xor" title="BOOL_XOR">BOOL_XOR</a></td>
|
||||||
<td><a class="link" href="pseudo-ops.html#cpui_cpoolref" title="CPOOLREF">CPOOLREF</a></td>
|
<td><a class="link" href="pseudo-ops.html#cpui_cpoolref" title="CPOOLREF">CPOOLREF</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_int_sext" title="INT_SEXT">INT_SEXT</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_int_zext" title="INT_ZEXT">INT_ZEXT</a></td>
|
||||||
<td><a class="link" href="pcodedescription.html#cpui_bool_and" title="BOOL_AND">BOOL_AND</a></td>
|
<td><a class="link" href="pcodedescription.html#cpui_bool_and" title="BOOL_AND">BOOL_AND</a></td>
|
||||||
<td><a class="link" href="pseudo-ops.html#cpui_new" title="NEW">NEW</a></td>
|
<td><a class="link" href="pseudo-ops.html#cpui_new" title="NEW">NEW</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><a class="link" href="pcodedescription.html#cpui_int_sext" title="INT_SEXT">INT_SEXT</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -139,6 +139,11 @@
|
||||||
<td><code class="code">popcount(v0)</code></td>
|
<td><code class="code">popcount(v0)</code></td>
|
||||||
<td>Count 1 bits in v0.</td>
|
<td>Count 1 bits in v0.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>LZCOUNT</td>
|
||||||
|
<td><code class="code">lzcount(v0)</code></td>
|
||||||
|
<td>Counts the number of leading zero bits in v0.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>INT_EQUAL</td>
|
<td>INT_EQUAL</td>
|
||||||
<td><code class="code">v0 == v1</code></td>
|
<td><code class="code">v0 == v1</code></td>
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<div><h1 class="title">
|
<div><h1 class="title">
|
||||||
<a name="sleigh_title"></a>SLEIGH</h1></div>
|
<a name="sleigh_title"></a>SLEIGH</h1></div>
|
||||||
<div><h3 class="subtitle"><i>A Language for Rapid Processor Specification</i></h3></div>
|
<div><h3 class="subtitle"><i>A Language for Rapid Processor Specification</i></h3></div>
|
||||||
<div><p class="releaseinfo">Last updated August 24, 2022</p></div>
|
<div><p class="releaseinfo">Last updated March 2, 2023</p></div>
|
||||||
<div><p class="pubdate">Originally published December 16, 2005</p></div>
|
<div><p class="pubdate">Originally published December 16, 2005</p></div>
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -372,7 +372,8 @@ general purpose processor instruction sets. They break up into groups.
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Logical</td>
|
<td>Logical</td>
|
||||||
<td><code class="code">INT_NEGATE, INT_XOR, INT_AND, INT_OR, INT_LEFT, INT_RIGHT, INT_SRIGHT, POPCOUNT</code></td>
|
<td><code class="code">INT_NEGATE, INT_XOR, INT_AND, INT_OR, INT_LEFT, INT_RIGHT, INT_SRIGHT,
|
||||||
|
POPCOUNT, LZCOUNT</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Integer Comparison</td>
|
<td>Integer Comparison</td>
|
||||||
|
|
|
@ -83,6 +83,12 @@ to lowest.
|
||||||
<td>Count the number of 1 bits in v0.
|
<td>Count the number of 1 bits in v0.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code class="code">LZCOUNT</code></td>
|
||||||
|
<td><code class="code">lzcount(v0)</code></td>
|
||||||
|
<td>Count the number of leading 0 bits in v0.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code class="code">(simulated)</code></td>
|
<td><code class="code">(simulated)</code></td>
|
||||||
<td><code class="code">v0[6,1]</code></td>
|
<td><code class="code">v0[6,1]</code></td>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue