mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
AllowedLanes in Architecture
This commit is contained in:
parent
31eab44f54
commit
90182c6251
6 changed files with 79 additions and 3 deletions
|
@ -811,6 +811,24 @@ void Architecture::parseIncidentalCopy(const Element *el)
|
|||
}
|
||||
}
|
||||
|
||||
/// Look for \<register> tags that have a \e vector_lane_size attribute.
|
||||
/// Record these so that the decompiler can split large registers into appropriate lane size pieces.
|
||||
/// \param el is the XML element
|
||||
void Architecture::parseLaneSizes(const Element *el)
|
||||
|
||||
{
|
||||
const List &list(el->getChildren());
|
||||
List::const_iterator iter;
|
||||
|
||||
AllowedLanes allowedLanes; // Only allocate once
|
||||
for(iter=list.begin();iter!=list.end();++iter) {
|
||||
if (allowedLanes.restoreXml(*iter, this)) {
|
||||
lanerecords.push_back(allowedLanes);
|
||||
}
|
||||
}
|
||||
lanerecords.sort();
|
||||
}
|
||||
|
||||
/// Create a stack space and a stack-pointer register from this \<stackpointer> element
|
||||
/// \param el is the XML element
|
||||
void Architecture::parseStackPointer(const Element *el)
|
||||
|
@ -976,6 +994,7 @@ void Architecture::parseProcessorConfig(DocumentStorage &store)
|
|||
else if (elname == "segmentop")
|
||||
userops.parseSegmentOp(*iter,this);
|
||||
else if (elname == "register_data") {
|
||||
parseLaneSizes(*iter);
|
||||
}
|
||||
else if (elname == "segmented_address") {
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "comment.hh"
|
||||
#include "userop.hh"
|
||||
#include "options.hh"
|
||||
#include "transform.hh"
|
||||
#include "prefersplit.hh"
|
||||
|
||||
#ifdef CPUI_STATISTICS
|
||||
|
@ -151,6 +152,7 @@ public:
|
|||
vector<TypeOp *> inst; ///< Registered p-code instructions
|
||||
UserOpManage userops; ///< Specifically registered user-defined p-code ops
|
||||
vector<PreferSplitRecord> splitrecords; ///< registers that we would prefer to see split for this processor
|
||||
list<AllowedLanes> lanerecords; ///< Vector registers that have preferred lane sizes
|
||||
ActionDatabase allacts; ///< Actions that can be applied in this architecture
|
||||
bool loadersymbols_parsed; ///< True if loader symbols have been read
|
||||
#ifdef CPUI_STATISTICS
|
||||
|
@ -260,6 +262,7 @@ protected:
|
|||
void parseVolatile(const Element *el); ///< Apply volatile region configuration
|
||||
void parseReturnAddress(const Element *el); ///< Apply return address configuration
|
||||
void parseIncidentalCopy(const Element *el); ///< Apply incidental copy configuration
|
||||
void parseLaneSizes(const Element *el); ///< Apply lane size configuration
|
||||
void parseStackPointer(const Element *el); ///< Apply stack pointer configuration
|
||||
void parseDeadcodeDelay(const Element *el); ///< Apply dead-code delay configuration
|
||||
void parseFuncPtrAlign(const Element *el); ///< Apply function pointer alignment configuration
|
||||
|
|
|
@ -2006,7 +2006,6 @@ bool LaneDivide::buildPiece(PcodeOp *op,TransformVar *outVars,int4 numLanes,int4
|
|||
{
|
||||
int4 highLanes,highSkip;
|
||||
int4 lowLanes,lowSkip;
|
||||
TransformVar *highVars,*lowVars;
|
||||
Varnode *outVn = op->getOut();
|
||||
Varnode *highVn = op->getIn(0);
|
||||
Varnode *lowVn = op->getIn(1);
|
||||
|
@ -2245,6 +2244,7 @@ bool LaneDivide::traceForward(TransformVar *rvn,int4 numLanes,int4 skipLanes)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief Pull the logical lanes back through the defining PcodeOp of the given variable
|
||||
|
@ -2316,7 +2316,7 @@ bool LaneDivide::traceBackward(TransformVar *rvn,int4 numLanes,int4 skipLanes)
|
|||
bool LaneDivide::processNextWork(void)
|
||||
|
||||
{
|
||||
TransformVar *rvn = workList.back();
|
||||
TransformVar *rvn = workList.back().lanes;
|
||||
int4 numLanes = workList.back().numLanes;
|
||||
int4 skipLanes = workList.back().skipLanes;
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#ifndef __SUBVARIABLE_FLOW__
|
||||
#define __SUBVARIABLE_FLOW__
|
||||
|
||||
#include "transform.hh"
|
||||
#include "funcdata.hh"
|
||||
|
||||
/// \brief Class for shrinking big Varnodes carrying smaller logical values
|
||||
|
|
|
@ -231,6 +231,48 @@ bool TransformOp::attemptInsertion(Funcdata *fd)
|
|||
return true; // Already inserted
|
||||
}
|
||||
|
||||
/// Read XML of the form \<register name=".." vector_lane_sizes=".."/>
|
||||
/// \param el is the particular \e register tag
|
||||
/// \param manage is used to map register names to storage info
|
||||
/// \return \b true if the XML description provides lane sizes
|
||||
bool AllowedLanes::restoreXml(const Element *el,const AddrSpaceManager *manage)
|
||||
|
||||
{
|
||||
string laneSizes;
|
||||
for(int4 i=0;i<el->getNumAttributes();++i) {
|
||||
if (el->getAttributeName(i) == "vector_lane_sizes") {
|
||||
laneSizes = el->getAttributeValue(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (laneSizes.empty()) return false;
|
||||
storage.space = (AddrSpace *)0;
|
||||
storage.restoreXml(el, manage);
|
||||
sizes.clear();
|
||||
string::size_type pos = 0;
|
||||
while(pos != string::npos) {
|
||||
string::size_type nextPos = laneSizes.find(',',pos);
|
||||
string value;
|
||||
if (nextPos == string::npos) {
|
||||
value = laneSizes.substr(pos); // To the end of the string
|
||||
pos = nextPos;
|
||||
}
|
||||
else {
|
||||
value = laneSizes.substr(pos,(nextPos - pos));
|
||||
pos = nextPos + 1;
|
||||
if (pos >= laneSizes.size())
|
||||
pos = string::npos;
|
||||
}
|
||||
istringstream s(value);
|
||||
s.unsetf(ios::dec | ios::hex | ios::oct);
|
||||
int4 sz = -1;
|
||||
s >> sz;
|
||||
if (sz < 0) return false;
|
||||
sizes.push_back(sz);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TransformManager::~TransformManager(void)
|
||||
|
||||
{
|
||||
|
|
|
@ -84,6 +84,19 @@ public:
|
|||
TransformVar *getIn(int4 i) const { return input[i]; } ///< Get the i-th input placeholder variable for \b this
|
||||
};
|
||||
|
||||
/// \brief Describes a (register) storage location and the ways it might be split into lanes
|
||||
class AllowedLanes {
|
||||
VarnodeData storage; ///< Defining characteristics of the register
|
||||
vector<int4> sizes; ///< Size of individual lane (in bytes) for each possible lane splitting
|
||||
public:
|
||||
AllowedLanes(void) {} ///< Constructor for use with restoreXml
|
||||
bool restoreXml(const Element *el,const AddrSpaceManager *manage); ///< Restore object from XML stream
|
||||
const VarnodeData &getStorage(void) const { return storage; } ///< Get VarnodeData for storage
|
||||
int4 numSplittings(void) const { return sizes.size(); } ///< Get the number of different lane splittings
|
||||
int4 getBaseLaneSize(int4 i) const { return sizes[i]; } ///< Get the base lane size for the i-th splitting
|
||||
bool operator<(const AllowedLanes &op2) const { return (storage < op2.storage); } ///< Compare based on VarnodeData
|
||||
};
|
||||
|
||||
/// \brief Description of logical lanes within a \b big Varnode
|
||||
///
|
||||
/// A \b lane is a byte offset and size within a Varnode. Lanes within a
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue