1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

More C++ification.

llvm-svn: 206722
This commit is contained in:
Richard Smith 2014-04-20 22:10:16 +00:00
parent e7a6813c55
commit 840046247e
3 changed files with 164 additions and 224 deletions

View File

@ -21,9 +21,7 @@
namespace llvm {
namespace X86Disassembler {
/*
* Accessor functions for various fields of an Intel instruction
*/
// Accessor functions for various fields of an Intel instruction
#define modFromModRM(modRM) (((modRM) & 0xc0) >> 6)
#define regFromModRM(modRM) (((modRM) & 0x38) >> 3)
#define rmFromModRM(modRM) ((modRM) & 0x7)
@ -73,10 +71,7 @@ namespace X86Disassembler {
#define lFromXOP3of3(xop) (((xop) & 0x4) >> 2)
#define ppFromXOP3of3(xop) ((xop) & 0x3)
/*
* These enums represent Intel registers for use by the decoder.
*/
// These enums represent Intel registers for use by the decoder.
#define REGS_8BIT \
ENTRY(AL) \
ENTRY(CL) \
@ -382,13 +377,11 @@ namespace X86Disassembler {
REGS_CONTROL \
ENTRY(RIP)
/*
* EABase - All possible values of the base field for effective-address
* computations, a.k.a. the Mod and R/M fields of the ModR/M byte. We
* distinguish between bases (EA_BASE_*) and registers that just happen to be
* referred to when Mod == 0b11 (EA_REG_*).
*/
typedef enum {
/// \brief All possible values of the base field for effective-address
/// computations, a.k.a. the Mod and R/M fields of the ModR/M byte.
/// We distinguish between bases (EA_BASE_*) and registers that just happen
/// to be referred to when Mod == 0b11 (EA_REG_*).
enum EABase {
EA_BASE_NONE,
#define ENTRY(x) EA_BASE_##x,
ALL_EA_BASES
@ -397,15 +390,13 @@ typedef enum {
ALL_REGS
#undef ENTRY
EA_max
} EABase;
};
/*
* SIBIndex - All possible values of the SIB index field.
* Borrows entries from ALL_EA_BASES with the special case that
* sib is synonymous with NONE.
* Vector SIB: index can be XMM or YMM.
*/
typedef enum {
/// \brief All possible values of the SIB index field.
/// borrows entries from ALL_EA_BASES with the special case that
/// sib is synonymous with NONE.
/// Vector SIB: index can be XMM or YMM.
enum SIBIndex {
SIB_INDEX_NONE,
#define ENTRY(x) SIB_INDEX_##x,
ALL_EA_BASES
@ -414,23 +405,18 @@ typedef enum {
REGS_ZMM
#undef ENTRY
SIB_INDEX_max
} SIBIndex;
};
/*
* SIBBase - All possible values of the SIB base field.
*/
typedef enum {
/// \brief All possible values of the SIB base field.
enum SIBBase {
SIB_BASE_NONE,
#define ENTRY(x) SIB_BASE_##x,
ALL_SIB_BASES
#undef ENTRY
SIB_BASE_max
} SIBBase;
};
/*
* EADisplacement - Possible displacement types for effective-address
* computations.
*/
/// \brief Possible displacement types for effective-address computations.
typedef enum {
EA_DISP_NONE,
EA_DISP_8,
@ -438,20 +424,16 @@ typedef enum {
EA_DISP_32
} EADisplacement;
/*
* Reg - All possible values of the reg field in the ModR/M byte.
*/
typedef enum {
/// \brief All possible values of the reg field in the ModR/M byte.
enum Reg {
#define ENTRY(x) MODRM_REG_##x,
ALL_REGS
#undef ENTRY
MODRM_REG_max
} Reg;
};
/*
* SegmentOverride - All possible segment overrides.
*/
typedef enum {
/// \brief All possible segment overrides.
enum SegmentOverride {
SEG_OVERRIDE_NONE,
SEG_OVERRIDE_CS,
SEG_OVERRIDE_SS,
@ -460,196 +442,182 @@ typedef enum {
SEG_OVERRIDE_FS,
SEG_OVERRIDE_GS,
SEG_OVERRIDE_max
} SegmentOverride;
};
/*
* VEXLeadingOpcodeByte - Possible values for the VEX.m-mmmm field
*/
typedef enum {
/// \brief Possible values for the VEX.m-mmmm field
enum VEXLeadingOpcodeByte {
VEX_LOB_0F = 0x1,
VEX_LOB_0F38 = 0x2,
VEX_LOB_0F3A = 0x3
} VEXLeadingOpcodeByte;
};
typedef enum {
enum XOPMapSelect {
XOP_MAP_SELECT_8 = 0x8,
XOP_MAP_SELECT_9 = 0x9,
XOP_MAP_SELECT_A = 0xA
} XOPMapSelect;
};
/*
* VEXPrefixCode - Possible values for the VEX.pp/EVEX.pp field
*/
typedef enum {
/// \brief Possible values for the VEX.pp/EVEX.pp field
enum VEXPrefixCode {
VEX_PREFIX_NONE = 0x0,
VEX_PREFIX_66 = 0x1,
VEX_PREFIX_F3 = 0x2,
VEX_PREFIX_F2 = 0x3
} VEXPrefixCode;
};
typedef enum {
enum VectorExtensionType {
TYPE_NO_VEX_XOP = 0x0,
TYPE_VEX_2B = 0x1,
TYPE_VEX_3B = 0x2,
TYPE_EVEX = 0x3,
TYPE_XOP = 0x4
} VectorExtensionType;
};
typedef uint8_t BOOL;
/*
* byteReader_t - Type for the byte reader that the consumer must provide to
* the decoder. Reads a single byte from the instruction's address space.
* @param arg - A baton that the consumer can associate with any internal
* state that it needs.
* @param byte - A pointer to a single byte in memory that should be set to
* contain the value at address.
* @param address - The address in the instruction's address space that should
* be read from.
* @return - -1 if the byte cannot be read for any reason; 0 otherwise.
*/
typedef int (*byteReader_t)(const void* arg, uint8_t* byte, uint64_t address);
/// \brief Type for the byte reader that the consumer must provide to
/// the decoder. Reads a single byte from the instruction's address space.
/// \param arg A baton that the consumer can associate with any internal
/// state that it needs.
/// \param byte A pointer to a single byte in memory that should be set to
/// contain the value at address.
/// \param address The address in the instruction's address space that should
/// be read from.
/// \return -1 if the byte cannot be read for any reason; 0 otherwise.
typedef int (*byteReader_t)(const void *arg, uint8_t *byte, uint64_t address);
/*
* dlog_t - Type for the logging function that the consumer can provide to
* get debugging output from the decoder.
* @param arg - A baton that the consumer can associate with any internal
* state that it needs.
* @param log - A string that contains the message. Will be reused after
* the logger returns.
*/
typedef void (*dlog_t)(void* arg, const char *log);
/// \brief Type for the logging function that the consumer can provide to
/// get debugging output from the decoder.
/// \param arg A baton that the consumer can associate with any internal
/// state that it needs.
/// \param log A string that contains the message. Will be reused after
/// the logger returns.
typedef void (*dlog_t)(void *arg, const char *log);
/*
* The specification for how to extract and interpret a full instruction and
* its operands.
*/
/// The specification for how to extract and interpret a full instruction and
/// its operands.
struct InstructionSpecifier {
uint16_t operands;
};
/*
* The x86 internal instruction, which is produced by the decoder.
*/
/// The x86 internal instruction, which is produced by the decoder.
struct InternalInstruction {
/* Reader interface (C) */
// Reader interface (C)
byteReader_t reader;
/* Opaque value passed to the reader */
// Opaque value passed to the reader
const void* readerArg;
/* The address of the next byte to read via the reader */
// The address of the next byte to read via the reader
uint64_t readerCursor;
/* Logger interface (C) */
// Logger interface (C)
dlog_t dlog;
/* Opaque value passed to the logger */
// Opaque value passed to the logger
void* dlogArg;
/* General instruction information */
// General instruction information
/* The mode to disassemble for (64-bit, protected, real) */
// The mode to disassemble for (64-bit, protected, real)
DisassemblerMode mode;
/* The start of the instruction, usable with the reader */
// The start of the instruction, usable with the reader
uint64_t startLocation;
/* The length of the instruction, in bytes */
// The length of the instruction, in bytes
size_t length;
/* Prefix state */
// Prefix state
/* 1 if the prefix byte corresponding to the entry is present; 0 if not */
// 1 if the prefix byte corresponding to the entry is present; 0 if not
uint8_t prefixPresent[0x100];
/* contains the location (for use with the reader) of the prefix byte */
// contains the location (for use with the reader) of the prefix byte
uint64_t prefixLocations[0x100];
/* The value of the vector extension prefix(EVEX/VEX/XOP), if present */
// The value of the vector extension prefix(EVEX/VEX/XOP), if present
uint8_t vectorExtensionPrefix[4];
/* The type of the vector extension prefix */
// The type of the vector extension prefix
VectorExtensionType vectorExtensionType;
/* The value of the REX prefix, if present */
// The value of the REX prefix, if present
uint8_t rexPrefix;
/* The location where a mandatory prefix would have to be (i.e., right before
the opcode, or right before the REX prefix if one is present) */
// The location where a mandatory prefix would have to be (i.e., right before
// the opcode, or right before the REX prefix if one is present).
uint64_t necessaryPrefixLocation;
/* The segment override type */
// The segment override type
SegmentOverride segmentOverride;
/* 1 if the prefix byte, 0xf2 or 0xf3 is xacquire or xrelease */
// 1 if the prefix byte, 0xf2 or 0xf3 is xacquire or xrelease
BOOL xAcquireRelease;
/* Sizes of various critical pieces of data, in bytes */
// Sizes of various critical pieces of data, in bytes
uint8_t registerSize;
uint8_t addressSize;
uint8_t displacementSize;
uint8_t immediateSize;
/* Offsets from the start of the instruction to the pieces of data, which is
needed to find relocation entries for adding symbolic operands */
// Offsets from the start of the instruction to the pieces of data, which is
// needed to find relocation entries for adding symbolic operands.
uint8_t displacementOffset;
uint8_t immediateOffset;
/* opcode state */
// opcode state
/* The last byte of the opcode, not counting any ModR/M extension */
// The last byte of the opcode, not counting any ModR/M extension
uint8_t opcode;
/* The ModR/M byte of the instruction, if it is an opcode extension */
// The ModR/M byte of the instruction, if it is an opcode extension
uint8_t modRMExtension;
/* decode state */
// decode state
/* The type of opcode, used for indexing into the array of decode tables */
// The type of opcode, used for indexing into the array of decode tables
OpcodeType opcodeType;
/* The instruction ID, extracted from the decode table */
// The instruction ID, extracted from the decode table
uint16_t instructionID;
/* The specifier for the instruction, from the instruction info table */
// The specifier for the instruction, from the instruction info table
const InstructionSpecifier *spec;
/* state for additional bytes, consumed during operand decode. Pattern:
consumed___ indicates that the byte was already consumed and does not
need to be consumed again */
// state for additional bytes, consumed during operand decode. Pattern:
// consumed___ indicates that the byte was already consumed and does not
// need to be consumed again.
/* The VEX.vvvv field, which contains a third register operand for some AVX
instructions */
// The VEX.vvvv field, which contains a third register operand for some AVX
// instructions.
Reg vvvv;
/* The writemask for AVX-512 instructions which is contained in EVEX.aaa */
// The writemask for AVX-512 instructions which is contained in EVEX.aaa
Reg writemask;
/* The ModR/M byte, which contains most register operands and some portion of
all memory operands */
// The ModR/M byte, which contains most register operands and some portion of
// all memory operands.
BOOL consumedModRM;
uint8_t modRM;
/* The SIB byte, used for more complex 32- or 64-bit memory operands */
// The SIB byte, used for more complex 32- or 64-bit memory operands
BOOL consumedSIB;
uint8_t sib;
/* The displacement, used for memory operands */
// The displacement, used for memory operands
BOOL consumedDisplacement;
int32_t displacement;
/* Immediates. There can be two in some cases */
// Immediates. There can be two in some cases
uint8_t numImmediatesConsumed;
uint8_t numImmediatesTranslated;
uint64_t immediates[2];
/* A register or immediate operand encoded into the opcode */
// A register or immediate operand encoded into the opcode
Reg opcodeRegister;
/* Portions of the ModR/M byte */
// Portions of the ModR/M byte
/* These fields determine the allowable values for the ModR/M fields, which
depend on operand and address widths */
// These fields determine the allowable values for the ModR/M fields, which
// depend on operand and address widths.
EABase eaBaseBase;
EABase eaRegBase;
Reg regBase;
/* The Mod and R/M fields can encode a base for an effective address, or a
register. These are separated into two fields here */
// The Mod and R/M fields can encode a base for an effective address, or a
// register. These are separated into two fields here.
EABase eaBase;
EADisplacement eaDisplacement;
/* The reg field always encodes a register */
// The reg field always encodes a register
Reg reg;
/* SIB state */
// SIB state
SIBIndex sibIndex;
uint8_t sibScale;
SIBBase sibBase;
@ -657,22 +625,21 @@ struct InternalInstruction {
const OperandSpecifier *operands;
};
/* decodeInstruction - Decode one instruction and store the decoding results in
* a buffer provided by the consumer.
* @param insn - The buffer to store the instruction in. Allocated by the
* consumer.
* @param reader - The byteReader_t for the bytes to be read.
* @param readerArg - An argument to pass to the reader for storing context
* specific to the consumer. May be NULL.
* @param logger - The dlog_t to be used in printing status messages from the
* disassembler. May be NULL.
* @param loggerArg - An argument to pass to the logger for storing context
* specific to the logger. May be NULL.
* @param startLoc - The address (in the reader's address space) of the first
* byte in the instruction.
* @param mode - The mode (16-bit, 32-bit, 64-bit) to decode in.
* @return - Nonzero if there was an error during decode, 0 otherwise.
*/
/// \brief Decode one instruction and store the decoding results in
/// a buffer provided by the consumer.
/// \param insn The buffer to store the instruction in. Allocated by the
/// consumer.
/// \param reader The byteReader_t for the bytes to be read.
/// \param readerArg An argument to pass to the reader for storing context
/// specific to the consumer. May be NULL.
/// \param logger The dlog_t to be used in printing status messages from the
/// disassembler. May be NULL.
/// \param loggerArg An argument to pass to the logger for storing context
/// specific to the logger. May be NULL.
/// \param startLoc The address (in the reader's address space) of the first
/// byte in the instruction.
/// \param mode The mode (16-bit, 32-bit, 64-bit) to decode in.
/// \return Nonzero if there was an error during decode, 0 otherwise.
int decodeInstruction(InternalInstruction *insn,
byteReader_t reader,
const void *readerArg,
@ -682,12 +649,10 @@ int decodeInstruction(InternalInstruction *insn,
uint64_t startLoc,
DisassemblerMode mode);
/* \brief Debug - Print a message to debugs()
* @param file - The name of the file printing the debug message.
* @param line - The line number that printed the debug message.
* @param s - The message to print.
*/
/// \brief Print a message to debugs()
/// \param file The name of the file printing the debug message.
/// \param line The line number that printed the debug message.
/// \param s The message to print.
void Debug(const char *file, unsigned line, const char *s);
const char *GetInstrName(unsigned Opcode, const void *mii);

View File

@ -42,11 +42,9 @@ namespace X86Disassembler {
#define XOP9_MAP_STR "x86DisassemblerXOP9Opcodes"
#define XOPA_MAP_STR "x86DisassemblerXOPAOpcodes"
/*
* Attributes of an instruction that must be known before the opcode can be
* processed correctly. Most of these indicate the presence of particular
* prefixes, but ATTR_64BIT is simply an attribute of the decoding context.
*/
// Attributes of an instruction that must be known before the opcode can be
// processed correctly. Most of these indicate the presence of particular
// prefixes, but ATTR_64BIT is simply an attribute of the decoding context.
#define ATTRIBUTE_BITS \
ENUM_ENTRY(ATTR_NONE, 0x00) \
ENUM_ENTRY(ATTR_64BIT, (0x1 << 0)) \
@ -71,13 +69,11 @@ enum attributeBits {
};
#undef ENUM_ENTRY
/*
* Combinations of the above attributes that are relevant to instruction
* decode. Although other combinations are possible, they can be reduced to
* these without affecting the ultimately decoded instruction.
*/
// Combinations of the above attributes that are relevant to instruction
// decode. Although other combinations are possible, they can be reduced to
// these without affecting the ultimately decoded instruction.
/* Class name Rank Rationale for rank assignment */
// Class name Rank Rationale for rank assignment
#define INSTRUCTION_CONTEXTS \
ENUM_ENTRY(IC, 0, "says nothing about the instruction") \
ENUM_ENTRY(IC_64BIT, 1, "says the instruction applies in " \
@ -278,10 +274,8 @@ enum InstructionContext {
};
#undef ENUM_ENTRY
/*
* Opcode types, which determine which decode table to use, both in the Intel
* manual and also for the decoder.
*/
// Opcode types, which determine which decode table to use, both in the Intel
// manual and also for the decoder.
enum OpcodeType {
ONEBYTE = 0,
TWOBYTE = 1,
@ -292,37 +286,31 @@ enum OpcodeType {
XOPA_MAP = 6
};
/*
* The following structs are used for the hierarchical decode table. After
* determining the instruction's class (i.e., which IC_* constant applies to
* it), the decoder reads the opcode. Some instructions require specific
* values of the ModR/M byte, so the ModR/M byte indexes into the final table.
*
* If a ModR/M byte is not required, "required" is left unset, and the values
* for each instructionID are identical.
*/
// The following structs are used for the hierarchical decode table. After
// determining the instruction's class (i.e., which IC_* constant applies to
// it), the decoder reads the opcode. Some instructions require specific
// values of the ModR/M byte, so the ModR/M byte indexes into the final table.
//
// If a ModR/M byte is not required, "required" is left unset, and the values
// for each instructionID are identical.
typedef uint16_t InstrUID;
/*
* ModRMDecisionType - describes the type of ModR/M decision, allowing the
* consumer to determine the number of entries in it.
*
* MODRM_ONEENTRY - No matter what the value of the ModR/M byte is, the decoded
* instruction is the same.
* MODRM_SPLITRM - If the ModR/M byte is between 0x00 and 0xbf, the opcode
* corresponds to one instruction; otherwise, it corresponds to
* a different instruction.
* MODRM_SPLITMISC- If the ModR/M byte is between 0x00 and 0xbf, ModR/M byte
* divided by 8 is used to select instruction; otherwise, each
* value of the ModR/M byte could correspond to a different
* instruction.
* MODRM_SPLITREG - ModR/M byte divided by 8 is used to select instruction. This
corresponds to instructions that use reg field as opcode
* MODRM_FULL - Potentially, each value of the ModR/M byte could correspond
* to a different instruction.
*/
// ModRMDecisionType - describes the type of ModR/M decision, allowing the
// consumer to determine the number of entries in it.
//
// MODRM_ONEENTRY - No matter what the value of the ModR/M byte is, the decoded
// instruction is the same.
// MODRM_SPLITRM - If the ModR/M byte is between 0x00 and 0xbf, the opcode
// corresponds to one instruction; otherwise, it corresponds to
// a different instruction.
// MODRM_SPLITMISC- If the ModR/M byte is between 0x00 and 0xbf, ModR/M byte
// divided by 8 is used to select instruction; otherwise, each
// value of the ModR/M byte could correspond to a different
// instruction.
// MODRM_SPLITREG - ModR/M byte divided by 8 is used to select instruction. This
// corresponds to instructions that use reg field as opcode
// MODRM_FULL - Potentially, each value of the ModR/M byte could correspond
// to a different instruction.
#define MODRMTYPES \
ENUM_ENTRY(MODRM_ONEENTRY) \
ENUM_ENTRY(MODRM_SPLITRM) \
@ -337,10 +325,7 @@ enum ModRMDecisionType {
};
#undef ENUM_ENTRY
/*
* Physical encodings of instruction operands.
*/
// Physical encodings of instruction operands.
#define ENCODINGS \
ENUM_ENTRY(ENCODING_NONE, "") \
ENUM_ENTRY(ENCODING_REG, "Register operand in ModR/M byte.") \
@ -381,10 +366,7 @@ enum OperandEncoding {
};
#undef ENUM_ENTRY
/*
* Semantic interpretations of instruction operands.
*/
// Semantic interpretations of instruction operands.
#define TYPES \
ENUM_ENTRY(TYPE_NONE, "") \
ENUM_ENTRY(TYPE_REL8, "1-byte immediate address") \
@ -481,20 +463,14 @@ enum OperandType {
};
#undef ENUM_ENTRY
/*
* OperandSpecifier - The specification for how to extract and interpret one
* operand.
*/
/// \brief The specification for how to extract and interpret one operand.
struct OperandSpecifier {
uint8_t encoding;
uint8_t type;
};
/*
* Indicates where the opcode modifier (if any) is to be found. Extended
* opcodes with AddRegFrm have the opcode modifier in the ModR/M byte.
*/
// Indicates where the opcode modifier (if any) is to be found. Extended
// opcodes with AddRegFrm have the opcode modifier in the ModR/M byte.
#define MODIFIER_TYPES \
ENUM_ENTRY(MODIFIER_NONE)
@ -505,13 +481,11 @@ enum ModifierType {
};
#undef ENUM_ENTRY
#define X86_MAX_OPERANDS 5
static const int X86_MAX_OPERANDS = 5;
/*
* Decoding mode for the Intel disassembler. 16-bit, 32-bit, and 64-bit mode
* are supported, and represent real mode, IA-32e, and IA-32e in 64-bit mode,
* respectively.
*/
/// Decoding mode for the Intel disassembler. 16-bit, 32-bit, and 64-bit mode
/// are supported, and represent real mode, IA-32e, and IA-32e in 64-bit mode,
/// respectively.
enum DisassemblerMode {
MODE_16BIT,
MODE_32BIT,

View File

@ -16,7 +16,8 @@
#include "../../lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h"
struct InstructionSpecifier {
llvm::X86Disassembler::OperandSpecifier operands[X86_MAX_OPERANDS];
llvm::X86Disassembler::OperandSpecifier
operands[llvm::X86Disassembler::X86_MAX_OPERANDS];
llvm::X86Disassembler::InstructionContext insnContext;
std::string name;