You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
369 lines
13 KiB
369 lines
13 KiB
/* BEGIN_LEGAL
|
|
|
|
Copyright (c) 2021 Intel Corporation
|
|
|
|
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.
|
|
|
|
END_LEGAL */
|
|
/// @file xed-inst.h
|
|
|
|
|
|
#if !defined(XED_INST_H)
|
|
# define XED_INST_H
|
|
|
|
#include "xed-util.h"
|
|
#include "xed-portability.h"
|
|
#include "xed-category-enum.h" // generated
|
|
#include "xed-extension-enum.h" //generated
|
|
#include "xed-iclass-enum.h" //generated
|
|
#include "xed-operand-enum.h" // generated
|
|
#include "xed-operand-visibility-enum.h" //generated
|
|
#include "xed-operand-action-enum.h" // generated
|
|
#include "xed-operand-convert-enum.h" // generated
|
|
#include "xed-operand-type-enum.h" // generated
|
|
#include "xed-nonterminal-enum.h" // a generated file
|
|
#include "xed-operand-width-enum.h" // a generated file
|
|
#include "xed-operand-element-xtype-enum.h" // a generated file
|
|
#include "xed-reg-enum.h" // a generated file
|
|
#include "xed-attribute-enum.h" // a generated file
|
|
#include "xed-exception-enum.h" // a generated file
|
|
#include "xed-iform-enum.h" // a generated file
|
|
#include "xed-iform-map.h"
|
|
#include "xed-attributes.h"
|
|
|
|
struct xed_decoded_inst_s; //fwd-decl
|
|
|
|
typedef void (*xed_operand_extractor_fn_t)(struct xed_decoded_inst_s* xds);
|
|
|
|
|
|
/// @ingroup DEC
|
|
/// Constant information about an individual generic operand, like an
|
|
///operand template, describing the operand properties. See @ref DEC for
|
|
///API information.
|
|
typedef struct xed_operand_s
|
|
{
|
|
xed_uint8_t _name; // xed_operand_enum_t
|
|
|
|
// implicit, explicit, suppressed
|
|
xed_uint8_t _operand_visibility; // xed_operand_visibility_enum_t
|
|
xed_uint8_t _rw; // read or written // xed_operand_action_enum_t
|
|
|
|
// width code, could be invalid (then use register name)
|
|
xed_uint8_t _oc2; // xed_operand_width_enum_t
|
|
|
|
// IMM, IMM_CONST, NT_LOOKUP_FN, REG, ERROR
|
|
xed_uint8_t _type; //xed_operand_type_enum_t
|
|
xed_uint8_t _xtype; // xed data type: u32, f32, etc. //xed_operand_element_xtype_enum_t
|
|
xed_uint8_t _cvt_idx; // decoration index
|
|
xed_uint8_t _nt;
|
|
union {
|
|
xed_uint32_t _imm; // value for some constant immmed
|
|
xed_nonterminal_enum_t _nt; // for nt_lookup_fn's
|
|
xed_reg_enum_t _reg; // register name
|
|
} _u;
|
|
} xed_operand_t;
|
|
|
|
/// @name xed_inst_t Template Operands Access
|
|
//@{
|
|
/// @ingroup DEC
|
|
static XED_INLINE xed_operand_enum_t
|
|
xed_operand_name(const xed_operand_t* p) {
|
|
return (xed_operand_enum_t)p->_name;
|
|
}
|
|
|
|
|
|
/// @ingroup DEC
|
|
static XED_INLINE xed_operand_visibility_enum_t
|
|
xed_operand_operand_visibility( const xed_operand_t* p) {
|
|
return (xed_operand_visibility_enum_t)(p->_operand_visibility);
|
|
}
|
|
|
|
|
|
/// @ingroup DEC
|
|
/// @return The #xed_operand_type_enum_t of the operand template.
|
|
/// This is probably not what you want.
|
|
static XED_INLINE xed_operand_type_enum_t
|
|
xed_operand_type(const xed_operand_t* p) {
|
|
return (xed_operand_type_enum_t)p->_type;
|
|
}
|
|
|
|
/// @ingroup DEC
|
|
/// @return The #xed_operand_element_xtype_enum_t of the operand template.
|
|
/// This is probably not what you want.
|
|
static XED_INLINE xed_operand_element_xtype_enum_t
|
|
xed_operand_xtype(const xed_operand_t* p) {
|
|
return (xed_operand_element_xtype_enum_t)p->_xtype;
|
|
}
|
|
|
|
|
|
/// @ingroup DEC
|
|
static XED_INLINE xed_operand_width_enum_t
|
|
xed_operand_width(const xed_operand_t* p) {
|
|
return (xed_operand_width_enum_t)p->_oc2;
|
|
}
|
|
|
|
/// @ingroup DEC
|
|
/// @param p an operand template, #xed_operand_t.
|
|
/// @param eosz effective operand size of the instruction, 1 | 2 | 3 for
|
|
/// 16 | 32 | 64 bits respectively. 0 is invalid.
|
|
/// @return the actual width of operand in bits.
|
|
/// See xed_decoded_inst_operand_length_bits() for a more general solution.
|
|
XED_DLL_EXPORT xed_uint32_t
|
|
xed_operand_width_bits(const xed_operand_t* p,
|
|
const xed_uint32_t eosz);
|
|
|
|
/// @ingroup DEC
|
|
static XED_INLINE xed_nonterminal_enum_t
|
|
xed_operand_nonterminal_name(const xed_operand_t* p) {
|
|
if (p->_nt)
|
|
return p->_u._nt;
|
|
return XED_NONTERMINAL_INVALID;
|
|
}
|
|
|
|
/// @ingroup DEC
|
|
/// Careful with this one -- use #xed_decoded_inst_get_reg()! This one is
|
|
/// probably not what you think it is. It is only used for hard-coded
|
|
/// registers implicit in the instruction encoding. Most likely you want to
|
|
/// get the #xed_operand_enum_t and then look up the instruction using
|
|
/// #xed_decoded_inst_get_reg(). The hard-coded registers are also available
|
|
/// that way.
|
|
/// @param p an operand template, #xed_operand_t.
|
|
/// @return the implicit or suppressed registers, type #xed_reg_enum_t
|
|
static XED_INLINE xed_reg_enum_t xed_operand_reg(const xed_operand_t* p) {
|
|
if (xed_operand_type(p) == XED_OPERAND_TYPE_REG)
|
|
return p->_u._reg;
|
|
return XED_REG_INVALID;
|
|
}
|
|
|
|
|
|
|
|
/// @ingroup DEC
|
|
/// Careful with this one; See #xed_operand_is_register().
|
|
/// @param p an operand template, #xed_operand_t.
|
|
/// @return 1 if the operand template represents are register-type
|
|
/// operand.
|
|
///
|
|
/// Related functions:
|
|
/// Use #xed_decoded_inst_get_reg() to get the decoded name of /// the
|
|
/// register, #xed_reg_enum_t. Use #xed_operand_is_register() to test
|
|
/// #xed_operand_enum_t names.
|
|
static XED_INLINE xed_uint_t
|
|
xed_operand_template_is_register(const xed_operand_t* p) {
|
|
return p->_nt || p->_type == XED_OPERAND_TYPE_REG;
|
|
}
|
|
|
|
/// @ingroup DEC
|
|
/// @param p an operand template, #xed_operand_t.
|
|
/// These operands represent branch displacements, memory displacements and
|
|
/// various immediates
|
|
static XED_INLINE xed_uint32_t xed_operand_imm(const xed_operand_t* p) {
|
|
if (xed_operand_type(p) == XED_OPERAND_TYPE_IMM_CONST)
|
|
return p->_u._imm;
|
|
return 0;
|
|
}
|
|
|
|
/// @ingroup DEC
|
|
/// Print the operand p into the buffer buf, of length buflen.
|
|
/// @param p an operand template, #xed_operand_t.
|
|
/// @param buf buffer that gets filled in
|
|
/// @param buflen maximum buffer length
|
|
XED_DLL_EXPORT void
|
|
xed_operand_print(const xed_operand_t* p, char* buf, int buflen);
|
|
//@}
|
|
|
|
/// @name xed_inst_t Template Operand Enum Name Classification
|
|
//@{
|
|
/// @ingroup DEC
|
|
/// Tests the enum for inclusion in XED_OPERAND_REG0 through XED_OPERAND_REG9.
|
|
/// @param name the operand name, type #xed_operand_enum_t
|
|
/// @return 1 if the operand name is REG0...REG9, 0 otherwise.
|
|
///
|
|
///Note there are other registers for memory addressing; See
|
|
/// #xed_operand_is_memory_addressing_register .
|
|
static XED_INLINE xed_uint_t xed_operand_is_register(xed_operand_enum_t name) {
|
|
return name >= XED_OPERAND_REG0 && name <= XED_OPERAND_REG9;
|
|
}
|
|
/// @ingroup DEC
|
|
/// Tests the enum for inclusion in XED_OPERAND_{BASE0,BASE1,INDEX,SEG0,SEG1}
|
|
/// @param name the operand name, type #xed_operand_enum_t
|
|
/// @return 1 if the operand name is for a memory addressing register operand, 0
|
|
/// otherwise. See also #xed_operand_is_register .
|
|
static XED_INLINE xed_uint_t
|
|
xed_operand_is_memory_addressing_register(xed_operand_enum_t name) {
|
|
return ( name == XED_OPERAND_BASE0 ||
|
|
name == XED_OPERAND_INDEX ||
|
|
name == XED_OPERAND_SEG0 ||
|
|
name == XED_OPERAND_BASE1 ||
|
|
name == XED_OPERAND_SEG1 );
|
|
}
|
|
|
|
//@}
|
|
|
|
/// @name xed_inst_t Template Operand Read/Written
|
|
//@{
|
|
/// @ingroup DEC
|
|
/// DEPRECATED: Returns the raw R/W action. There are many cases for conditional reads
|
|
/// and writes. See #xed_decoded_inst_operand_action().
|
|
static XED_INLINE xed_operand_action_enum_t
|
|
xed_operand_rw(const xed_operand_t* p) {
|
|
return (xed_operand_action_enum_t)p->_rw;
|
|
}
|
|
|
|
/// @ingroup DEC
|
|
/// If the operand is read, including conditional reads
|
|
XED_DLL_EXPORT xed_uint_t xed_operand_read(const xed_operand_t* p);
|
|
/// @ingroup DEC
|
|
/// If the operand is read-only, including conditional reads
|
|
XED_DLL_EXPORT xed_uint_t xed_operand_read_only(const xed_operand_t* p);
|
|
/// @ingroup DEC
|
|
/// If the operand is written, including conditional writes
|
|
XED_DLL_EXPORT xed_uint_t xed_operand_written(const xed_operand_t* p);
|
|
/// @ingroup DEC
|
|
/// If the operand is written-only, including conditional writes
|
|
XED_DLL_EXPORT xed_uint_t xed_operand_written_only(const xed_operand_t* p);
|
|
/// @ingroup DEC
|
|
/// If the operand is read-and-written, conditional reads and conditional writes
|
|
XED_DLL_EXPORT xed_uint_t xed_operand_read_and_written(const xed_operand_t* p);
|
|
/// @ingroup DEC
|
|
/// If the operand has a conditional read (may also write)
|
|
XED_DLL_EXPORT xed_uint_t xed_operand_conditional_read(const xed_operand_t* p);
|
|
/// @ingroup DEC
|
|
/// If the operand has a conditional write (may also read)
|
|
XED_DLL_EXPORT xed_uint_t xed_operand_conditional_write(const xed_operand_t* p);
|
|
//@}
|
|
|
|
|
|
/// @ingroup DEC
|
|
/// constant information about a decoded instruction form, including
|
|
/// the pointer to the constant operand properties #xed_operand_t for this
|
|
/// instruction form.
|
|
typedef struct xed_inst_s {
|
|
|
|
|
|
// rflags info -- index in to the 2 tables of flags information.
|
|
// If _flag_complex is true, then the data are in the
|
|
// xed_flags_complex_table[]. Otherwise, the data are in the
|
|
// xed_flags_simple_table[].
|
|
|
|
//xed_instruction_fixed_bit_confirmer_fn_t _confirmer;
|
|
|
|
// number of operands in the operands array
|
|
xed_uint8_t _noperands;
|
|
xed_uint8_t _cpl; // the nominal CPL for the instruction.
|
|
xed_uint8_t _flag_complex; /* 1/0 valued, bool type */
|
|
xed_uint8_t _exceptions; //xed_exception_enum_t
|
|
|
|
xed_uint16_t _flag_info_index;
|
|
|
|
xed_uint16_t _iform_enum; //xed_iform_enum_t
|
|
// index into the xed_operand[] array of xed_operand_t structures
|
|
xed_uint16_t _operand_base;
|
|
// index to table of xed_attributes_t structures
|
|
xed_uint16_t _attributes;
|
|
|
|
} xed_inst_t;
|
|
|
|
/// @name xed_inst_t Template Instruction Information
|
|
//@{
|
|
/// @ingroup DEC
|
|
/// xed_inst_cpl() is DEPRECATED. Please use
|
|
/// "xed_decoded_inst_get_attribute(xedd, XED_ATTRIBUTE_RING0)"
|
|
/// instead.
|
|
///Return the current privilege level (CPL) required for execution, 0 or
|
|
///3. If the value is zero, then the instruction can only execute in ring 0.
|
|
XED_DLL_EXPORT unsigned int xed_inst_cpl(const xed_inst_t* p) ;
|
|
|
|
|
|
//These next few are not doxygen commented because I want people to use the
|
|
//higher level interface in xed-decoded-inst.h.
|
|
static XED_INLINE xed_iform_enum_t xed_inst_iform_enum(const xed_inst_t* p) {
|
|
return (xed_iform_enum_t)p->_iform_enum;
|
|
}
|
|
|
|
static XED_INLINE xed_iclass_enum_t xed_inst_iclass(const xed_inst_t* p) {
|
|
return xed_iform_to_iclass(xed_inst_iform_enum(p));
|
|
}
|
|
|
|
static XED_INLINE xed_category_enum_t xed_inst_category(const xed_inst_t* p) {
|
|
return xed_iform_to_category(xed_inst_iform_enum(p));
|
|
}
|
|
|
|
static XED_INLINE xed_extension_enum_t xed_inst_extension(const xed_inst_t* p) {
|
|
return xed_iform_to_extension(xed_inst_iform_enum(p));
|
|
}
|
|
static XED_INLINE xed_isa_set_enum_t xed_inst_isa_set(const xed_inst_t* p) {
|
|
return xed_iform_to_isa_set(xed_inst_iform_enum(p));
|
|
}
|
|
|
|
|
|
|
|
///@ingroup DEC
|
|
/// Number of instruction operands
|
|
static XED_INLINE unsigned int xed_inst_noperands(const xed_inst_t* p) {
|
|
return p->_noperands;
|
|
}
|
|
|
|
///@ingroup DEC
|
|
/// Obtain a pointer to an individual operand
|
|
XED_DLL_EXPORT const xed_operand_t*
|
|
xed_inst_operand(const xed_inst_t* p, unsigned int i);
|
|
|
|
|
|
|
|
XED_DLL_EXPORT xed_uint32_t xed_inst_flag_info_index(const xed_inst_t* p);
|
|
|
|
//@}
|
|
|
|
/// @name xed_inst_t Attribute access
|
|
//@{
|
|
/// @ingroup DEC
|
|
/// Scan for the attribute attr and return 1 if it is found, 0 otherwise.
|
|
XED_DLL_EXPORT xed_uint32_t
|
|
xed_inst_get_attribute(const xed_inst_t* p,
|
|
xed_attribute_enum_t attr);
|
|
|
|
/// @ingroup DEC
|
|
/// Return the attributes bit vector
|
|
XED_DLL_EXPORT xed_attributes_t
|
|
xed_inst_get_attributes(const xed_inst_t* p);
|
|
|
|
|
|
/// @ingroup DEC
|
|
/// Return the maximum number of defined attributes, independent of any
|
|
/// instruction.
|
|
XED_DLL_EXPORT unsigned int xed_attribute_max(void);
|
|
|
|
/// @ingroup DEC
|
|
/// Return the i'th global attribute in a linear sequence, independent of
|
|
/// any instruction. This is used for scanning and printing all attributes.
|
|
XED_DLL_EXPORT xed_attribute_enum_t xed_attribute(unsigned int i);
|
|
|
|
//@}
|
|
|
|
/// @name Exceptions
|
|
//@{
|
|
/// @ingroup DEC
|
|
/// Return #xed_exception_enum_t if present for the specified instruction.
|
|
/// This is currently only used for SSE and AVX instructions.
|
|
static XED_INLINE
|
|
xed_exception_enum_t xed_inst_exception(const xed_inst_t* p) {
|
|
return (xed_exception_enum_t)p->_exceptions;
|
|
}
|
|
|
|
//@}
|
|
/// @ingroup DEC
|
|
/// Return the base of instruction table.
|
|
XED_DLL_EXPORT const xed_inst_t* xed_inst_table_base(void);
|
|
|
|
#endif
|