Candidate release of source code.

This commit is contained in:
Dan 2019-03-26 13:45:32 -04:00
parent db81e6b3b0
commit 79d8f164f8
12449 changed files with 2800756 additions and 16 deletions

View file

@ -0,0 +1,545 @@
/* ###
* 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.
*/
/// \file printlanguage.hh
/// \brief Classes for printing tokens in a high-level language
#ifndef __PRINT_LANGUAGE__
#define __PRINT_LANGUAGE__
#include "capability.hh"
#include "cast.hh"
#include "prettyprint.hh"
class PrintLanguage;
/// \brief Base class for high-level language capabilities
///
/// This class is overridden to introduce a new high-level language back-end
/// to the system. A static singleton is instantiated to automatically
/// register the new capability with the system. A static array keeps track of
/// all the registered capabilities.
///
/// The singleton is registered with a name, which the user can use to select the language, and
/// it acts as a factory for the main language printing class for the capability,
/// which must be derived from PrintLanguage. The factory method for the capability to override
/// is buildLanguage().
class PrintLanguageCapability : public CapabilityPoint {
static vector<PrintLanguageCapability *> thelist; ///< The static array of registered high-level languages
protected:
string name; ///< Unique identifier for language capability
bool isdefault; ///< Set to \b true to treat \b this as the default language
public:
const string &getName(void) const { return name; } ///< Get the high-level language name
virtual void initialize(void);
/// \brief Build the main PrintLanguage object corresponding to \b this capability
///
/// An Architecture will call this once. All decompiling from this Architecture will use this same emitter.
/// \param glb is the Architecture that will own the new emitter
/// \return the instantiated PrintLanguage emittter
virtual PrintLanguage *buildLanguage(Architecture *glb)=0;
static PrintLanguageCapability *getDefault(void); ///< Retrieve the default language capability
static PrintLanguageCapability *findCapability(const string &name); ///< Find a language capability by name
};
class BlockGraph;
class BlockBasic;
class BlockList;
class BlockCopy;
class BlockGoto;
class BlockIf;
class BlockCondition;
class BlockWhileDo;
class BlockDoWhile;
class BlockInfLoop;
class BlockSwitch;
class Scope;
class Symbol;
class EquateSymbol;
class Comment;
/// \brief A token representing an operator in the high-level language
///
/// The token knows how to print itself and other syntax information like
/// precedence level and associativity within the language, desired spacing,
/// and how operator groups its input expressions. Note that an operator has
/// a broader meaning than just p-code operators in this context.
class OpToken {
public:
/// \brief The possible types of operator token
enum tokentype {
binary, ///< Binary operator form (printed between its inputs)
unary_prefix, ///< Unary operator form (printed before its input)
postsurround, ///< Function or array operator form
presurround, ///< Modifier form (like a cast operation)
space, ///< No explicitly printed token
};
const char *print; ///< Printing characters for the token
int4 stage; ///< Additional elements consumed from the RPN stack when emitting this token
int4 precedence; ///< Precedence level of this token (higher binds more tightly)
bool associative; ///< True if the operator is associative
tokentype type; ///< The basic token type
int4 spacing; ///< Spaces to print around operator
int4 bump; ///< Spaces to indent if we break here
OpToken *negate; ///< The token representing the negation of this token
bool parentheses(const OpToken &op2,int4 stage) const;
};
/// \brief The base class API for emitting a high-level language
///
/// Instances of this object are responsible for converting a function's
/// (transformed) data-flow graph into the final stream of tokens of a high-level
/// source code language. There a few main entry points including:
/// - docFunction()
/// - docAllGlobals()
/// - docTypeDefinitions()
///
/// The system is responsible for printing:
/// - Control-flow structures
/// - Expressions
/// - Type declarations
/// - Function prototypes
/// - Comments
///
/// As part of all this printing, the system is also responsible for
/// - Emitting integers, floats, and character constants
/// - Placing parentheses within expressions to properly represent data-flow
/// - Deciding whether \e cast operations need an explicit cast token
/// - Indenting and line wrapping
///
/// To accomplish this, the API is broken up into three sections. The first section
/// are the main entry point 'doc' methods. The second section are 'emit' methods, which
/// are responsible for printing a representation of a particular high-level code construct.
/// The third section are 'push' and 'op' methods, which are responsible for walking expression trees.
/// The order in which tokens are emitted for an expression is determined by a
/// Reverse Polish Notation (RPN) stack, that the 'push' methods manipulate. Operators and variables
/// are \e pushed onto this stack and are ultimately \e emitted in the correct order.
///
/// The base class provides a generic \e printing \e modifications stack and a \e symbol \e scope
/// stack to provide a printing context mechanism for derived classes.
class PrintLanguage {
public:
/// \brief Possible context sensitive modifiers to how tokens get emitted
enum modifiers {
force_hex = 1, ///< Force printing of hex
force_dec = 2, ///< Force printing of dec
bestfit = 4, ///< Decide on most aesthetic form
force_scinote = 8, ///< Force scientific notation for floats
force_pointer = 0x10, ///< Force '*' notation for pointers
print_load_value = 0x20, ///< Hide pointer deref for load with other ops
print_store_value = 0x40, ///< Hide pointer deref for store with other ops
no_branch = 0x80, ///< Do not print branch instruction
only_branch = 0x100, ///< Print only the branch instruction
comma_separate = 0x200, ///< Statements within condition
flat = 0x400, ///< Do not print block structure
falsebranch = 0x800, ///< Print the false branch (for flat)
nofallthru = 0x1000, ///< Fall-thru no longer exists
negatetoken = 0x2000, ///< Print the token representing the negation of current token
hide_thisparam = 0x4000 ///< Do not print the 'this' parameter in argument lists
};
/// \brief Possible types of Atom
enum tagtype {
syntax, ///< Emit atom as syntax
vartoken, ///< Emit atom as variable
functoken, ///< Emit atom as function name
optoken, ///< Emit atom as operator
typetoken, ///< Emit atom as operator
fieldtoken, ///< Emit atom as structure field
blanktoken ///< For anonymous types
};
/// \brief An entry on the reverse polish notation (RPN) stack
struct ReversePolish {
const OpToken *tok; ///< The operator token
int4 visited; ///< The current stage of printing for the operator
bool paren; ///< True if parentheses are required
const PcodeOp *op; ///< The PcodeOp associated with the operator token
int4 id; ///< The id of the token group which \b this belongs to
mutable int4 id2; ///< The id of the token group \b this surrounds (for surround operator tokens)
};
/// \brief A pending data-flow node; waiting to be placed on the reverse polish notation stack
///
/// This holds an \e implied Varnode in the data-flow graph, which prints as the expression producing
/// the value in the Varnode.
struct NodePending {
const Varnode *vn; ///< The implied Varnode
const PcodeOp *op; ///< The single operator consuming value from the implied Varnode
uint4 vnmod; ///< Printing modifications to enforce on the expression
/// \brief Construct a pending data-flow node
NodePending(const Varnode *v,const PcodeOp *o,uint4 m) {
vn = v; op = o; vnmod = m; }
};
/// \brief A single non-operator token emitted by the decompiler
///
/// These play the role of variable tokens on the RPN stack with the operator tokens.
/// The term \e variable has a broader meaning than just a Varnode. An Atom can also be a data-type
/// name, a function name, or a structure field etc.
struct Atom {
const string &name; ///< The actual printed characters of the token
tagtype type; ///< The type of Atom
EmitXml::syntax_highlight highlight; ///< The type of highlighting to use when emitting the token
const PcodeOp *op; ///< A p-code operation associated with the token
union {
const Varnode *vn; ///< A Varnode associated with the token
const Funcdata *fd; ///< A function associated with the token
const Datatype *ct; ///< A type associated with the token
} ptr_second; ///< Other meta-data associated with the token
int4 offset; ///< The offset (within the parent structure) for a \e field token
/// \brief Construct a token with no associated data-flow annotations
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl)
: name(nm) { type = t; highlight = hl; }
/// \brief Construct a token for a data-type name
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl,const Datatype *c)
: name(nm) { type = t; highlight = hl; ptr_second.ct = c; }
/// \brief Construct a token for a field name
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl,const Datatype *c,int4 off)
: name(nm) { type = t; highlight = hl; ptr_second.ct = c; offset = off; }
/// \brief Construct a token with an associated PcodeOp
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl,const PcodeOp *o)
: name(nm) { type = t; highlight = hl; op = o; }
/// \brief Construct a token with an associated PcodeOp and Varnode
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl,const PcodeOp *o,const Varnode *v)
: name(nm) { type=t; highlight = hl; ptr_second.vn = v; op = o; }
/// \brief Construct a token for a function name
Atom(const string &nm,tagtype t,EmitXml::syntax_highlight hl,const PcodeOp *o,const Funcdata *f)
: name(nm) { type=t; highlight = hl; op = o; ptr_second.fd = f; }
};
private:
string name; ///< The name of the high-level language
vector<uint4> modstack; ///< Printing modification stack
vector<Scope *> scopestack; ///< The symbol scope stack
Scope *curscope; ///< The current symbol scope
vector<ReversePolish> revpol; ///< The Reverse Polish Notation (RPN) token stack
vector<NodePending> nodepend; ///< Data-flow nodes waiting to be pushed onto the RPN stack
int4 pending; ///< Number of data-flow nodes waiting to be pushed
int4 line_commentindent; ///< Number of characters a comment line should be indented
string commentstart; ///< Delimiter characters for the start of a comment
string commentend; ///< Delimiter characters (if any) for the end of a comment
protected:
Architecture *glb; ///< The Architecture owning the language emitter
CastStrategy *castStrategy; ///< The strategy for emitting explicit \e case operations
EmitXml *emit; ///< The low-level token emitter
uint4 mods; ///< Currently active printing modifications
uint4 instr_comment_type; ///< Type of instruction comments to display
uint4 head_comment_type; ///< Type of header comments to display
#ifdef CPUI_DEBUG
bool isStackEmpty(void) const { return (nodepend.empty()&&revpol.empty()); } ///< Return \b true if the RPN stack is empty
bool isModStackEmpty(void) const { return modstack.empty(); } ///< Return \b true if the printing modification stack is empty
#endif
// Routines that are probably consistent across languages
bool isSet(uint4 m) const { return ((mods & m)!=0); } ///< Is the given printing modification active
void pushScope(Scope *sc) { scopestack.push_back(sc); curscope = sc; } ///< Push a new symbol scope
void popScope(void) { scopestack.pop_back(); curscope = scopestack.back(); } ///< Pop to the previous symbol scope
void pushMod(void) { modstack.push_back(mods); } ///< Push current printing modifications to the stack
void popMod(void) { mods = modstack.back(); modstack.pop_back(); } ///< Pop to the previous printing modifications
void setMod(uint4 m) { mods |= m; } ///< Activate the given printing modification
void unsetMod(uint4 m) { mods &= ~m; } ///< Deactivate the given printing modification
void pushOp(const OpToken *tok,const PcodeOp *op); ///< Push an operator token onto the RPN stack
void pushAtom(const Atom &atom); ///< Push a variable token onto the RPN stack
void pushVnImplied(const Varnode *vn,const PcodeOp *op,uint4 m); ///< Push an implied variable onto the RPN stack
void pushVnExplicit(const Varnode *vn,const PcodeOp *op); ///< Push an explicit variable onto the RPN stack
void pushVnLHS(const Varnode *vn,const PcodeOp *op); ///< Push a variable as the left-hand side of an expression
void emitOp(const ReversePolish &entry); ///< Send an operator token from the RPN to the emitter
void emitAtom(const Atom &atom); ///< Send an variable token from the RPN to the emitter
static bool unicodeNeedsEscape(int4 codepoint); ///< Determine if the given codepoint needs to be escaped
static void writeUtf8(ostream &s,int4 codepoint); ///< Write unicode character to stream in UTF8 encoding
static int4 readUtf16(const uint1 *buf,bool bigend); ///< Read a 2-byte UTF16 element from a byte array
static int4 getCodepoint(const uint1 *buf,int4 charsize,bool bigend,int4 &skip);
bool escapeCharacterData(ostream &s,const uint1 *buf,int4 count,int4 charsize,bool bigend) const;
void recurse(void); ///< Emit from the RPN stack as much as possible
void opBinary(const OpToken *tok,const PcodeOp *op); ///< Push a binary operator onto the RPN stack
void opUnary(const OpToken *tok,const PcodeOp *op); ///< Push a unary operator onto the RPN stack
int4 getPending(void) const { return pending; } ///< Get the number of pending nodes yet to be put on the RPN stack
/// \brief Print a single unicode character as a \e character \e constant for the high-level language
///
/// For most languages, this prints the character surrounded by single quotes.
/// \param s is the output stream
/// \param onechar is the unicode code point of the character to print
virtual void printUnicode(ostream &s,int4 onechar) const=0;
/// \brief Push a data-type name onto the RPN expression stack.
///
/// The data-type is generally emitted as if for a cast.
/// \param ct is the data-type to push
virtual void pushType(const Datatype *ct)=0;
/// \brief Push a constant onto the RPN stack.
///
/// The value is ultimately emitted based on its data-type and other associated mark-up
/// \param val is the value of the constant
/// \param ct is the data-type of the constant
/// \param vn is the Varnode holding the constant (optional)
/// \param op is the PcodeOp using the constant (optional)
virtual void pushConstant(uintb val,const Datatype *ct,
const Varnode *vn,const PcodeOp *op)=0;
/// \brief Push a constant marked up by and EquateSymbol onto the RPN stack
///
/// The equate may substitute a name or force a conversion for the constant
/// \param val is the value of the constant
/// \param sz is the number of bytes to use for the encoding
/// \param sym is the EquateSymbol that marks up the constant
/// \param vn is the Varnode holding the constant (optional)
/// \param op is the PcodeOp using the constant (optional)
virtual bool pushEquate(uintb val,int4 sz,const EquateSymbol *sym,const Varnode *vn,const PcodeOp *op)=0;
/// \brief Push an address which is not in the normal data-flow.
///
/// The given Varnode is treated as an address, which may or may not have a symbol name.
/// \param vn is the annotation Varnode
/// \param op is the PcodeOp which takes the annotation as input
virtual void pushAnnotation(const Varnode *vn,const PcodeOp *op)=0;
/// \brief Push a specific Symbol onto the RPN stack
///
/// \param sym is the given Symbol
/// \param vn is the Varnode holding the Symbol value
/// \param op is a PcodeOp associated with the Varnode
virtual void pushSymbol(const Symbol *sym,const Varnode *vn,
const PcodeOp *op)=0;
/// \brief Push an address as a substitute for a Symbol onto the RPN stack
///
/// If there is no Symbol or other name source for an explicit variable,
/// this method is used to print something to represent the variable based on its storage address.
/// \param addr is the storage address
/// \param vn is the Varnode representing the variable (if present)
/// \param op is a PcodeOp associated with the variable
virtual void pushUnnamedLocation(const Address &addr,
const Varnode *vn,const PcodeOp *op)=0;
/// \brief Push a variable that represents only part of a symbol onto the RPN stack
///
/// Generally \e member syntax specifying a field within a structure gets emitted.
/// \param sym is the root Symbol
/// \param off is the byte offset, within the Symbol, of the partial variable
/// \param sz is the number of bytes in the partial variable
/// \param vn is the Varnode holding the partial value
/// \param op is a PcodeOp associate with the Varnode
/// \param outtype is the data-type expected by expression using the partial variable
virtual void pushPartialSymbol(const Symbol *sym,int4 off,int4 sz,
const Varnode *vn,const PcodeOp *op,Datatype *outtype)=0;
/// \brief Push an identifier for a variable that mismatches with its Symbol
///
/// This happens when a Varnode overlaps, but is not contained by a Symbol.
/// This most commonly happens when the size of a Symbol is unknown
/// \param sym is the overlapped symbol
/// \param off is the byte offset of the variable relative to the symbol
/// \param sz is the size of the variable in bytes
/// \param vn is the Varnode representing the variable
/// \param op is a PcodeOp associated with the Varnode
virtual void pushMismatchSymbol(const Symbol *sym,int4 off,int4 sz,
const Varnode *vn,const PcodeOp *op)=0;
virtual void emitLineComment(int4 indent,const Comment *comm); ///< Emit a comment line
/// \brief Emit a variable declaration
///
/// This can be part of a full a statement, or just the declaration of a function parameter
/// \param sym is the Symbol to be declared
virtual void emitVarDecl(const Symbol *sym)=0;
/// \brief Emit a variable declaration statement
///
/// \param sym is the Symbol to be declared
virtual void emitVarDeclStatement(const Symbol *sym)=0;
/// \brief Emit all the variable declarations for a given scope
///
/// A subset of all variables can be declared by specifying a category,
/// 0 for parameters, -1 for everything.
/// \param scope is the given Scope
/// \param cat is the category of variable to declare
virtual bool emitScopeVarDecls(const Scope *scope,int4 cat)=0;
/// \brief Emit a full expression
///
/// This can be an assignment statement, if the given PcodeOp has an output Varnode,
/// or it can be a statement with no left-hand side.
/// \param op is the given PcodeOp performing the final operation of the expression
virtual void emitExpression(const PcodeOp *op)=0;
/// \brief Emit a function declaration
///
/// This prints the formal defining prototype for a function.
/// \param fd is the Funcdata object representing the function to be emitted
virtual void emitFunctionDeclaration(const Funcdata *fd)=0;
/// \brief Check whether a given boolean Varnode can be printed in negated form.
///
/// In many situations a boolean value can be inverted by flipping the operator
/// token producing it to a complementary token.
/// \param vn is the given boolean Varnode
/// \return \b true if the value can be easily inverted
virtual bool checkPrintNegation(const Varnode *vn)=0;
public:
PrintLanguage(Architecture *g,const string &nm); ///< Constructor
virtual ~PrintLanguage(void); ///< Destructor
const string &getName(void) const { return name; } ///< Get the language name
CastStrategy *getCastStrategy(void) const { return castStrategy; } ///< Get the casting strategy for the language
ostream *getOutputStream(void) const { return emit->getOutputStream(); } ///< Get the output stream being emitted to
void setOutputStream(ostream *t) { emit->setOutputStream(t); } ///< Set the output stream to emit to
void setScope(Scope *sc) { curscope = sc; } ///< Set the current Symbol scope
void setMaxLineSize(int4 mls) { emit->setMaxLineSize(mls); } ///< Set the maximum number of characters per line
void setIndentIncrement(int4 inc) { emit->setIndentIncrement(inc); } ///< Set the number of characters to indent per level of code nesting
void setLineCommentIndent(int4 val); ///< Set the number of characters to indent comment lines
void setCommentDelimeter(const string &start,const string &stop,
bool usecommentfill); ///< Establish comment delimiters for the language
uint4 getInstructionComment(void) const { return instr_comment_type; } ///< Get the type of comments suitable within the body of a function
void setInstructionComment(uint4 val) { instr_comment_type = val; } ///< Set the type of comments suitable within the body of a function
uint4 getHeaderComment(void) const { return head_comment_type; } ///< Get the type of comments suitable for a function header
void setHeaderComment(uint4 val) { head_comment_type = val; } ///< Set the type of comments suitable for a function header
bool emitsXml(void) const { return emit->emitsXml(); } ///< Does the low-level emitter, emit XML markup
void setXML(bool val); ///< Set whether the low-level emitter, emits XML markup
void setFlat(bool val); ///< Set whether nesting code structure should be emitted
virtual void adjustTypeOperators(void)=0; ///< Set basic data-type information for p-code operators
virtual void clear(void); ///< Clear the RPN stack and the low-level emitter
virtual void setIntegerFormat(const string &nm); ///< Set the default integer format
/// \brief Set the way comments are displayed in decompiler output
///
/// This method can either be provided a formal name or a \e sample of the initial delimiter,
/// then it will choose from among the schemes it knows
/// \param nm is the configuration description
virtual void setCommentStyle(const string &nm)=0;
/// \brief Decide is the given byte array looks like a character string
///
/// This looks for encodings and/or a terminator that is appropriate for the high-level language
/// \param buf is a pointer to the byte array
/// \param size is the number of bytes in the array
/// \param charsize is the size in bytes of the encoding element (i.e. UTF8, UTF16, etc.) to assume
virtual bool isCharacterConstant(const uint1 *buf,int4 size,int4 charsize) const=0;
/// \brief Emit definitions of data-types
///
/// \param typegrp is the container for the data-types that should be defined
virtual void docTypeDefinitions(const TypeFactory *typegrp)=0;
/// \brief Emit declarations of global variables
virtual void docAllGlobals(void)=0;
/// \brief Emit the declaration for a single (global) Symbol
///
/// \param sym is the Symbol to declare
virtual void docSingleGlobal(const Symbol *sym)=0;
/// \brief Emit the declaration (and body) of a function
///
/// \param fd is the function to emit
virtual void docFunction(const Funcdata *fd)=0;
virtual void emitBlockBasic(const BlockBasic *bb)=0; ///< Emit statements in a basic block
virtual void emitBlockGraph(const BlockGraph *bl)=0; ///< Emit (an unspecified) list of blocks
virtual void emitBlockCopy(const BlockCopy *bl)=0; ///< Emit a basic block (with any labels)
virtual void emitBlockGoto(const BlockGoto *bl)=0; ///< Emit a block ending with a goto statement
virtual void emitBlockLs(const BlockList *bl)=0; ///< Emit a sequence of blocks
virtual void emitBlockCondition(const BlockCondition *bl)=0; ///< Emit a conditional statement
virtual void emitBlockIf(const BlockIf *bl)=0; ///< Emit an if/else style construct
virtual void emitBlockWhileDo(const BlockWhileDo *bl)=0; ///< Emit a loop structure, check at top
virtual void emitBlockDoWhile(const BlockDoWhile *bl)=0; ///< Emit a loop structure, check at bottom
virtual void emitBlockInfLoop(const BlockInfLoop *bl)=0; ///< Emit an infinite loop structure
virtual void emitBlockSwitch(const BlockSwitch *bl)=0; ///< Emit a switch structure
virtual void opCopy(const PcodeOp *op)=0; ///< Emit a COPY operator
virtual void opLoad(const PcodeOp *op)=0; ///< Emit a LOAD operator
virtual void opStore(const PcodeOp *op)=0; ///< Emit a STORE operator
virtual void opBranch(const PcodeOp *op)=0; ///< Emit a BRANCH operator
virtual void opCbranch(const PcodeOp *op)=0; ///< Emit a CBRANCH operator
virtual void opBranchind(const PcodeOp *op)=0; ///< Emit a BRANCHIND operator
virtual void opCall(const PcodeOp *op)=0; ///< Emit a CALL operator
virtual void opCallind(const PcodeOp *op)=0; ///< Emit a CALLIND operator
virtual void opCallother(const PcodeOp *op)=0; ///< Emit a CALLOTHER operator
virtual void opConstructor(const PcodeOp *op,bool withNew)=0; ///< Emit an operator constructing an object
virtual void opReturn(const PcodeOp *op)=0; ///< Emit a RETURN operator
virtual void opIntEqual(const PcodeOp *op)=0; ///< Emit a INT_EQUAL operator
virtual void opIntNotEqual(const PcodeOp *op)=0; ///< Emit a INT_NOTEQUAL operator
virtual void opIntSless(const PcodeOp *op)=0; ///< Emit a INT_SLESS operator
virtual void opIntSlessEqual(const PcodeOp *op)=0; ///< Emit a INT_SLESSEQUAL operator
virtual void opIntLess(const PcodeOp *op)=0; ///< Emit a INT_LESS operator
virtual void opIntLessEqual(const PcodeOp *op)=0; ///< Emit a INT_LESSEQUAL operator
virtual void opIntZext(const PcodeOp *op)=0; ///< Emit a INT_ZEXT operator
virtual void opIntSext(const PcodeOp *op)=0; ///< Emit a INT_SEXT operator
virtual void opIntAdd(const PcodeOp *op)=0; ///< Emit a INT_ADD operator
virtual void opIntSub(const PcodeOp *op)=0; ///< Emit a INT_SUB operator
virtual void opIntCarry(const PcodeOp *op)=0; ///< Emit a INT_CARRY operator
virtual void opIntScarry(const PcodeOp *op)=0; ///< Emit a INT_SCARRY operator
virtual void opIntSborrow(const PcodeOp *op)=0; ///< Emit a INT_SBORROW operator
virtual void opInt2Comp(const PcodeOp *op)=0; ///< Emit a INT_2COMP operator
virtual void opIntNegate(const PcodeOp *op)=0; ///< Emit a INT_NEGATE operator
virtual void opIntXor(const PcodeOp *op)=0; ///< Emit a INT_XOR operator
virtual void opIntAnd(const PcodeOp *op)=0; ///< Emit a INT_AND operator
virtual void opIntOr(const PcodeOp *op)=0; ///< Emit a INT_OR operator
virtual void opIntLeft(const PcodeOp *op)=0; ///< Emit a INT_LEFT operator
virtual void opIntRight(const PcodeOp *op)=0; ///< Emit a INT_RIGHT operator
virtual void opIntSright(const PcodeOp *op)=0; ///< Emit a INT_SRIGHT operator
virtual void opIntMult(const PcodeOp *op)=0; ///< Emit a INT_MULT operator
virtual void opIntDiv(const PcodeOp *op)=0; ///< Emit a INT_DIV operator
virtual void opIntSdiv(const PcodeOp *op)=0; ///< Emit a INT_SDIV operator
virtual void opIntRem(const PcodeOp *op)=0; ///< Emit a INT_REM operator
virtual void opIntSrem(const PcodeOp *op)=0; ///< Emit a INT_SREM operator
virtual void opBoolNegate(const PcodeOp *op)=0; ///< Emit a BOOL_NEGATE operator
virtual void opBoolXor(const PcodeOp *op)=0; ///< Emit a BOOL_XOR operator
virtual void opBoolAnd(const PcodeOp *op)=0; ///< Emit a BOOL_AND operator
virtual void opBoolOr(const PcodeOp *op)=0; ///< Emit a BOOL_OR operator
virtual void opFloatEqual(const PcodeOp *op)=0; ///< Emit a FLOAT_EQUAL operator
virtual void opFloatNotEqual(const PcodeOp *op)=0; ///< Emit a FLOAT_NOTEQUAL operator
virtual void opFloatLess(const PcodeOp *op)=0; ///< Emit a FLOAT_LESS operator
virtual void opFloatLessEqual(const PcodeOp *op)=0; ///< Emit a FLOAT_LESSEQUAL operator
virtual void opFloatNan(const PcodeOp *op)=0; ///< Emit a FLOAT_NAN operator
virtual void opFloatAdd(const PcodeOp *op)=0; ///< Emit a FLOAT_ADD operator
virtual void opFloatDiv(const PcodeOp *op)=0; ///< Emit a FLOAT_DIV operator
virtual void opFloatMult(const PcodeOp *op)=0; ///< Emit a FLOAT_MULT operator
virtual void opFloatSub(const PcodeOp *op)=0; ///< Emit a FLOAT_SUB operator
virtual void opFloatNeg(const PcodeOp *op)=0; ///< Emit a FLOAT_NEG operator
virtual void opFloatAbs(const PcodeOp *op)=0; ///< Emit a FLOAT_ABS operator
virtual void opFloatSqrt(const PcodeOp *op)=0; ///< Emit a FLOAT_SQRT operator
virtual void opFloatInt2Float(const PcodeOp *op)=0; ///< Emit a FLOAT_INT2FLOAT operator
virtual void opFloatFloat2Float(const PcodeOp *op)=0; ///< Emit a FLOAT_FLOAT2FLOAT operator
virtual void opFloatTrunc(const PcodeOp *op)=0; ///< Emit a FLOAT_TRUNC operator
virtual void opFloatCeil(const PcodeOp *op)=0; ///< Emit a FLOAT_CEIL operator
virtual void opFloatFloor(const PcodeOp *op)=0; ///< Emit a FLOAT_FLOOR operator
virtual void opFloatRound(const PcodeOp *op)=0; ///< Emit a FLOAT_ROUND operator
virtual void opMultiequal(const PcodeOp *op)=0; ///< Emit a MULTIEQUAL operator
virtual void opIndirect(const PcodeOp *op)=0; ///< Emit a INDIRECT operator
virtual void opPiece(const PcodeOp *op)=0; ///< Emit a PIECE operator
virtual void opSubpiece(const PcodeOp *op)=0; ///< Emit a SUBPIECE operator
virtual void opCast(const PcodeOp *op)=0; ///< Emit a CAST operator
virtual void opPtradd(const PcodeOp *op)=0; ///< Emit a PTRADD operator
virtual void opPtrsub(const PcodeOp *op)=0; ///< Emit a PTRSUB operator
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
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
};
#endif