More clean-up in the encoder

This commit is contained in:
Joel Höner 2017-07-10 14:34:25 +02:00
parent 8fa80f0b86
commit 3498a33944
3 changed files with 171 additions and 197 deletions

View File

@ -63,6 +63,10 @@ enum ZydisStatusCode
* @brief An attempt was made to perform an invalid operation.
*/
ZYDIS_STATUS_INVALID_OPERATION,
/**
* @brief A buffer passed to a function was too small to complete the requested operation.
*/
ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE,
/* ------------------------------------------------------------------------------------------ */
/* Decoder */
@ -123,15 +127,6 @@ enum ZydisStatusCode
ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION,
/* ------------------------------------------------------------------------------------------ */
/* Formatter */
/* ------------------------------------------------------------------------------------------ */
/**
* @brief A buffer passed to a function was too small to complete the requested operation.
*/
ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE,
/* ------------------------------------------------------------------------------------------ */
/* Misc */
/* ------------------------------------------------------------------------------------------ */

View File

@ -25,7 +25,8 @@
***************************************************************************************************/
#include <Zydis/Encoder.h>
#include <InstructionTable.h>
#include <SharedData.h>
#include <EncoderData.h>
#include <string.h>
#include <stdint.h>
@ -34,59 +35,6 @@
/* Internal context and table types */
/* ============================================================================================== */
typedef struct ZydisEncoderTableOperand_
{
ZydisOperandEncoding encoding;
ZydisSemanticOperandType type;
} ZydisEncoderTableOperand;
typedef uint8_t ZydisModRMMod;
enum ZydisModRMMods
{
ZYDIS_MODRM_MOD_NONE,
ZYDIS_MODRM_MOD_REGISTER,
ZYDIS_MODRM_MOD_MEMORY,
};
typedef uint8_t ZydisModeConstraint;
enum ZydisModeConstraints
{
ZYDIS_MODE_CONSTR_NONE,
ZYDIS_MODE_CONSTR_EXCLUDE64,
ZYDIS_MODE_CONSTR_REQUIRE64,
};
typedef uint8_t ZydisPrefixBit;
enum ZydisPrefixBits
{
// TODO: Use defines instead?
ZYDIS_PREFBIT_VEX_L = 0x01,
ZYDIS_PREFBIT_REX_W = 0x02,
ZYDIS_PREFBIT_EVEX_L2 = 0x04,
ZYDIS_PREFBIT_EVEX_B = 0x08,
};
typedef struct ZydisEncoderTableEntry_
{
uint16_t mnemonic;
uint8_t opcode;
ZydisInstructionEncoding encoding;
uint8_t operandCount;
ZydisEncoderTableOperand operands[5];
ZydisOpcodeMap map;
ZydisInstructionAttributes attribs;
ZydisModeConstraint modeConstraint;
ZydisPrefixBit prefixBits;
uint8_t mandatoryPrefix; // 0x00 = None
uint8_t modrmReg; // 0xFF = None
const char* cmt;
} ZydisEncoderTableEntry;
#include <Generated/EncoderTable.inc>
struct ZydisPrefixAcceptMapping
{
uint64_t has;
@ -124,8 +72,11 @@ typedef struct ZydisEncoderContext_
size_t bufferLen;
size_t writeOffs;
ZydisEncoderRequest* req;
const ZydisEncoderTableEntry* matchingEntry;
ZydisBool shouldEmitMandatoryPrefix;
const ZydisEncodableInstruction* matchingInsn;
const ZydisInstructionDefinition* matchingDef;
uint8_t matchingOperandCount;
const ZydisOperandDefinition* matchingOperands;
ZydisBool emitMandatoryPrefix;
uint8_t mandatoryPrefix;
uint8_t dispBitSize;
uint64_t disp;
@ -466,14 +417,15 @@ static ZydisStatus ZydisEmitSIB(ZydisEncoderContext* ctx)
static ZydisStatus ZydisPrepareOpcode(ZydisEncoderContext* ctx)
{
ZYDIS_ASSERT(ctx);
ZYDIS_ASSERT(ctx->matchingEntry);
ZYDIS_ASSERT(ctx->matchingDef);
ZYDIS_ASSERT(ctx->req);
// Put opcode map prefix(es), if required.
switch (ctx->req->encoding)
{
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
switch (ctx->matchingEntry->map)
switch (ctx->matchingInsn->opcodeMap)
{
case ZYDIS_OPCODE_MAP_0F:
ctx->opcodeMapPrefix[ctx->opcodeMapPrefixLen++] = 0x0F;
@ -493,16 +445,16 @@ static ZydisStatus ZydisPrepareOpcode(ZydisEncoderContext* ctx)
}
break;
case ZYDIS_INSTRUCTION_ENCODING_VEX:
ctx->raw.vex.m_mmmm = ctx->matchingEntry->map;
ctx->raw.vex.m_mmmm = ctx->matchingInsn->opcodeMap;
ZYDIS_ASSERT(ctx->raw.vex.m_mmmm <= 0x03);
break;
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
ctx->raw.evex.mm = ctx->matchingEntry->map;
ctx->raw.evex.mm = ctx->matchingInsn->opcodeMap;
ZYDIS_ASSERT(ctx->raw.evex.mm <= 0x03);
break;
case ZYDIS_INSTRUCTION_ENCODING_XOP:
ctx->raw.xop.m_mmmm =
ctx->matchingEntry->map - ZYDIS_OPCODE_MAP_XOP8 + 0x08;
ctx->matchingInsn->opcodeMap - ZYDIS_OPCODE_MAP_XOP8 + 0x08;
ZYDIS_ASSERT(ctx->raw.xop.m_mmmm >= 0x08);
ZYDIS_ASSERT(ctx->raw.xop.m_mmmm <= 0x0B);
break;
@ -513,14 +465,6 @@ static ZydisStatus ZydisPrepareOpcode(ZydisEncoderContext* ctx)
return ZYDIS_STATUS_SUCCESS;
}
static ZydisStatus ZydisSimplifyOperandType(ZydisSemanticOperandType semType,
ZydisOperandType* simpleType)
{
ZYDIS_ASSERT(simpleType);
return ZYDIS_STATUS_SUCCESS;
}
static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
ZydisRegister reg, char topBitLoc)
{
@ -543,16 +487,15 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
// No top bit? Quick exit.
if (!topBit) return ZYDIS_STATUS_SUCCESS;
uint8_t* topBitDst = NULL;
switch (ctx->req->encoding)
{
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
switch (topBitLoc)
{
case 'B': topBitDst = &ctx->raw.rex.B; break;
case 'R': topBitDst = &ctx->raw.rex.R; break;
case 'X': topBitDst = &ctx->raw.rex.X; break;
case 'B': ctx->raw.rex.B = topBit; break;
case 'R': ctx->raw.rex.R = topBit; break;
case 'X': ctx->raw.rex.X = topBit; break;
default: ZYDIS_UNREACHABLE;
}
if (topBit) ctx->req->attributes |= ZYDIS_ATTRIB_HAS_REX;
@ -560,27 +503,27 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
case ZYDIS_INSTRUCTION_ENCODING_VEX:
switch (topBitLoc)
{
case 'B': topBitDst = &ctx->raw.vex.B; break;
case 'R': topBitDst = &ctx->raw.vex.R; break;
case 'X': topBitDst = &ctx->raw.vex.X; break;
case 'B': ctx->raw.vex.B = topBit; break;
case 'R': ctx->raw.vex.R = topBit; break;
case 'X': ctx->raw.vex.X = topBit; break;
default: ZYDIS_UNREACHABLE;
}
break;
case ZYDIS_INSTRUCTION_ENCODING_XOP:
switch (topBitLoc)
{
case 'B': topBitDst = &ctx->raw.xop.B; break;
case 'R': topBitDst = &ctx->raw.xop.R; break;
case 'X': topBitDst = &ctx->raw.xop.X; break;
case 'B': ctx->raw.xop.B = topBit; break;
case 'R': ctx->raw.xop.R = topBit; break;
case 'X': ctx->raw.xop.X = topBit; break;
default: ZYDIS_UNREACHABLE;
}
break;
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
switch (topBitLoc)
{
case 'B': topBitDst = &ctx->raw.evex.B; break;
case 'R': topBitDst = &ctx->raw.evex.R; break;
case 'X': topBitDst = &ctx->raw.evex.X; break;
case 'B': ctx->raw.evex.B = topBit; break;
case 'R': ctx->raw.evex.R = topBit; break;
case 'X': ctx->raw.evex.X = topBit; break;
default: ZYDIS_UNREACHABLE;
}
break;
@ -588,8 +531,6 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
}
*topBitDst = topBit;
return ZYDIS_STATUS_SUCCESS;
}
@ -659,11 +600,12 @@ static ZydisStatus ZydisPrepareSegmentPrefix(ZydisEncoderContext* ctx,
}
static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
ZydisEncoderOperand* operand, const ZydisEncoderTableOperand* tableEntry)
ZydisEncoderOperand* operand, const ZydisOperandDefinition* operandDef)
{
ZYDIS_ASSERT(ctx);
ZYDIS_ASSERT(ctx->req);
ZYDIS_ASSERT(operand);
ZYDIS_ASSERT(tableEntry);
ZYDIS_ASSERT(operandDef);
ZYDIS_CHECK(ZydisPrepareSegmentPrefix(ctx, operand->mem.segment, operand->mem.base));
@ -821,33 +763,29 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
}
static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
ZydisEncoderOperand* operand, const ZydisEncoderTableOperand* tableEntry)
ZydisEncoderOperand* operand, const ZydisOperandDefinition* operandDef)
{
ZYDIS_ASSERT(ctx);
ZYDIS_ASSERT(operand);
ZYDIS_ASSERT(tableEntry);
ZYDIS_ASSERT(operandDef);
ZYDIS_ASSERT(operandDef->type != ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG);
ZYDIS_ASSERT(operandDef->type != ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM);
ZYDIS_ASSERT(operandDef->type != ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1);
switch (tableEntry->encoding)
switch (operandDef->op.encoding)
{
case ZYDIS_OPERAND_ENCODING_NONE:
{
// For some encodings, we have to switch on the sem op type.
// TODO
//switch (tableEntry->type)
//{
//case ZYDIS_SEM_OPERAND_TYPE_MOFFS16:
//case ZYDIS_SEM_OPERAND_TYPE_MOFFS32:
//case ZYDIS_SEM_OPERAND_TYPE_MOFFS64:
// ZYDIS_CHECK(ZydisPrepareSegmentPrefix(
// ctx, operand->mem.segment, ZYDIS_REGISTER_NONE
// ));
// ctx->imms[0] = operand->mem.disp;
// ctx->immBitSizes[0] = operand->mem.dispSize;
// break;
//default:
// // Hidden operand, nothing to encode.
// break;
//}
break;
if (operandDef->type == ZYDIS_SEMANTIC_OPTYPE_MOFFS)
{
ZYDIS_CHECK(ZydisPrepareSegmentPrefix(
ctx, operand->mem.segment, ZYDIS_REGISTER_NONE
));
ctx->imms[0] = operand->mem.disp;
ctx->immBitSizes[0] = operand->mem.dispSize;
}
} break;
case ZYDIS_OPERAND_ENCODING_MODRM_REG:
{
ZYDIS_ASSERT(!ctx->raw.modrm.reg);
@ -864,7 +802,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
// Memory operand?
if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
{
ZYDIS_CHECK(ZydisPrepareMemoryOperand(ctx, operand, tableEntry));
ZYDIS_CHECK(ZydisPrepareMemoryOperand(ctx, operand, operandDef));
}
// Nope, register.
else if (operand->type == ZYDIS_OPERAND_TYPE_REGISTER)
@ -937,92 +875,113 @@ static ZydisStatus ZydisPrepareMandatoryPrefixes(ZydisEncoderContext* ctx)
ZYDIS_ASSERT(ctx);
// Is a prefix mandatory? 0x00 is a sentinel value for `None` in the table.
if (ctx->matchingEntry->mandatoryPrefix != 0x00)
uint8_t prefix = ctx->matchingInsn->mandatoryPrefix;
if (prefix != 0x00)
{
uint8_t bitCompressedPrefix = 0x00;
switch (ctx->matchingEntry->mandatoryPrefix)
{
case 0x66: bitCompressedPrefix = 0x01; break;
case 0xF3: bitCompressedPrefix = 0x02; break;
case 0xF2: bitCompressedPrefix = 0x03; break;
default: ZYDIS_UNREACHABLE;
}
switch (ctx->req->encoding)
{
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
ctx->shouldEmitMandatoryPrefix = ZYDIS_TRUE;
ctx->mandatoryPrefix = ctx->matchingEntry->mandatoryPrefix;
ctx->emitMandatoryPrefix = ZYDIS_TRUE;
ctx->mandatoryPrefix = prefix;
break;
case ZYDIS_INSTRUCTION_ENCODING_VEX:
ctx->raw.vex.pp = bitCompressedPrefix;
ctx->raw.vex.pp = prefix;
break;
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
ctx->raw.evex.pp = bitCompressedPrefix;
ctx->raw.evex.pp = prefix;
break;
case ZYDIS_INSTRUCTION_ENCODING_XOP:
ctx->raw.xop.pp = bitCompressedPrefix;
ctx->raw.xop.pp = prefix;
break;
default:
ZYDIS_UNREACHABLE;
}
}
return ZYDIS_STATUS_SUCCESS;
}
static ZydisStatus ZydisDeriveEncodingForOp(ZydisOperandDefinition* operand)
static ZydisStatus ZydisDetermineInstructionEncoding(ZydisEncoderRequest* ctx)
{
ZYDIS_ASSERT(operand);
ZYDIS_ASSERT(ctx);
switch (operand->type)
for (const ZydisEncoderOperand *op = ctx->operands,
*end = ctx->operands + ctx->operandCount
; op < end
; ++op)
{
default:
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
}
return ZYDIS_STATUS_SUCCESS;
}
static ZydisStatus ZydisFindMatchingDef(const ZydisEncoderRequest* req,
const ZydisEncoderTableEntry** matchingEntry)
static ZydisStatus ZydisFindMatchingDef(
ZydisEncoderContext* ctx, const ZydisEncoderRequest* req)
{
ZYDIS_ASSERT(ctx);
ZYDIS_ASSERT(req);
ZYDIS_ASSERT(matchingEntry);
// Locate entries with matching mnemonic.
// TODO: Do binary search / hash based lookup instead.
for (size_t i = 0; i < ZYDIS_ARRAY_SIZE(kEncoderTable); ++i)
// Translate requested mode to flags.
uint8_t modeFlag;
switch (req->encoding)
{
const ZydisEncoderTableEntry* curEntry = &kEncoderTable[i];
if (curEntry->mnemonic != req->mnemonic ||
curEntry->operandCount != req->operandCount ||
curEntry->encoding != req->encoding ||
(req->machineMode == 64 &&
curEntry->modeConstraint == ZYDIS_MODE_CONSTR_EXCLUDE64) ||
(req->machineMode != 64 &&
curEntry->modeConstraint == ZYDIS_MODE_CONSTR_REQUIRE64))
case 16: modeFlag = 0x01; break;
case 32: modeFlag = 0x02; break;
case 64: modeFlag = 0x04; break;
default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
}
// Walk list of candidates.
const ZydisEncodableInstruction* insns = NULL;
uint8_t insnCount = ZydisGetEncodableInstructions(req->mnemonic, &insns);
if (!insnCount) return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
ZYDIS_ASSERT(insns);
for (uint8_t i = 0; i < insnCount; ++i)
{
const ZydisEncodableInstruction* candidateInsn = insns + i;
if (!(candidateInsn->mode & modeFlag)) goto _nextInsn;
const ZydisInstructionDefinition* candidateDef = NULL;
ZydisGetInstructionDefinition(
candidateInsn->encoding, insns->definitionReference, &candidateDef);
ZydisOperandDefinition* candidateOperands = NULL;
uint8_t defOperandCount = ZydisGetOperandDefinitions(candidateDef, &candidateOperands);
if (req->operandCount > defOperandCount) goto _nextInsn;
const ZydisOperandDefinition* curDefOperand = candidateOperands;
for (uint8_t k = 0; k < req->operandCount; ++k)
{
continue;
curDefOperand = candidateOperands + k;
const ZydisEncoderOperand* curReqOperand = req->operands + k;
// Visible operands are always in the front. When we encounter the first hidden
// operand in the definition and haven't exhausted the request operands yet,
// it's safe to assume this isn't the instruction we're looking for.
if (curDefOperand->visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN) goto _nextInsn;
if (curDefOperand->type != curReqOperand->type) continue;
// blah blah more checks
}
// Check operands.
for (size_t k = 0; k < curEntry->operandCount; ++k)
// Make sure we compared either all operands or the remaining operands are hidden.
if (req->operandCount != defOperandCount &&
(curDefOperand + 1)->visibility != ZYDIS_OPERAND_VISIBILITY_HIDDEN)
{
// TODO: Match operand size.
const ZydisEncoderTableOperand* curEncoderOp = &curEntry->operands[k];
const ZydisEncoderOperand* curReqOp = &req->operands[k];
if (curReqOp->encoding != curEncoderOp->encoding) goto continueTopLevel;
//ZydisOperandType simpleType;
//ZYDIS_CHECK(ZydisSimplifyOperandType(curEncoderOp->type, &simpleType));
//if (curReqOp->type != simpleType) goto continueTopLevel;
if (curReqOp->temp != curEncoderOp->type) goto continueTopLevel;
goto _nextInsn;
}
// Still here? We found our entry!
*matchingEntry = curEntry;
// Still here? Looks like we found our instruction, then!
ctx->matchingInsn = candidateInsn;
ctx->matchingDef = candidateDef;
ctx->matchingOperandCount = req->operandCount;
return ZYDIS_STATUS_SUCCESS;
continueTopLevel:
_nextInsn:
;
}
@ -1035,10 +994,29 @@ static ZydisStatus ZydisFindMatchingDef(const ZydisEncoderRequest* req,
/* Implementation of public functions */
/* ============================================================================================== */
#ifdef ZYDIS_ENABLE_FEATURE_DECODER
ZydisStatus ZydisEncoderDecodedInstructionToRequest(
const ZydisDecodedInstruction* in, ZydisEncoderRequest* out)
{
ZYDIS_ASSERT(in);
ZYDIS_ASSERT(out);
(void) in; (void) out;
// TODO
return ZYDIS_STATUS_SUCCESS;
}
#endif
ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
ZydisEncoderRequest* request)
{
if (!request || !bufferLen) return ZYDIS_STATUS_INVALID_PARAMETER;
if (!request || !bufferLen || request->operandCount > ZYDIS_ARRAY_SIZE(request->operands))
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
if (!buffer || !*bufferLen) return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
ZydisEncoderContext ctx;
@ -1054,25 +1032,26 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
// Search matching instruction, collect information about what needs to be
// encoded, what prefixes are required, etc.
ZYDIS_CHECK(ZydisFindMatchingDef(request, &ctx.matchingEntry));
ctx.raw.opcode = ctx.matchingEntry->opcode;
ZYDIS_CHECK(ZydisFindMatchingDef(&ctx, request));
ctx.raw.opcode = ctx.matchingInsn->opcode;
// Check compatibility of requested prefixes to found instruction.
if (ctx.req->attributes)
{
for (size_t i = 0; i < ZYDIS_ARRAY_SIZE(prefixAcceptMap); ++i)
{
if (ctx.req->attributes & prefixAcceptMap[i].has &&
!(ctx.matchingEntry->attribs & prefixAcceptMap[i].accepts))
{
// TODO: Better status.
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION;
}
}
}
// TODO
//if (ctx.req->attributes)
//{
// for (size_t i = 0; i < ZYDIS_ARRAY_SIZE(prefixAcceptMap); ++i)
// {
// if (ctx.req->attributes & prefixAcceptMap[i].has &&
// !(ctx.matchingDef->attribs & prefixAcceptMap[i].accepts))
// {
// // TODO: Better status.
// return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION;
// }
// }
//}
// Determine required prefixes.
switch (ctx.matchingEntry->encoding)
switch (ctx.matchingInsn->encoding)
{
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
request->attributes |= ZYDIS_ATTRIB_HAS_EVEX;
@ -1088,11 +1067,11 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
}
// Prepare prefix bits.
ZydisPrefixBit pb = ctx.matchingEntry->prefixBits;
ctx.raw.evex.B = (pb & ZYDIS_PREFBIT_EVEX_B ) ? 1 : 0;
ctx.raw.evex.L2 = (pb & ZYDIS_PREFBIT_EVEX_L2) ? 1 : 0;
ctx.raw.vex.L = (pb & ZYDIS_PREFBIT_VEX_L ) ? 1 : 0;
if (pb & ZYDIS_PREFBIT_REX_W)
ctx.raw.evex.B = ctx.matchingInsn->evexB;
ctx.raw.evex.L = ctx.matchingInsn->vectorLength & 0x01;
ctx.raw.evex.L2 = ctx.matchingInsn->vectorLength & 0x02;
ctx.raw.vex.L = ctx.matchingInsn->vectorLength & 0x01;
if (ctx.matchingInsn->rexW)
{
ctx.raw.rex.W = 1;
request->attributes |= ZYDIS_ATTRIB_HAS_REX;
@ -1103,9 +1082,9 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
ZYDIS_CHECK(ZydisPrepareOpcode(&ctx));
// Some instructions have additional opcode bits encoded in ModRM.reg.
if (ctx.matchingEntry->modrmReg != 0xFF)
if (ctx.matchingInsn->modrmReg != 0xFF)
{
ctx.raw.modrm.reg = ctx.matchingEntry->modrmReg;
ctx.raw.modrm.reg = ctx.matchingInsn->modrmReg;
}
// Analyze and prepare operands.
@ -1115,14 +1094,14 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
return ZYDIS_STATUS_INVALID_PARAMETER;
}
for (size_t i = 0; i < ctx.matchingEntry->operandCount; ++i)
{
ZYDIS_CHECK(ZydisPrepareOperand(
&ctx, &request->operands[i],
&ctx.matchingEntry->operands[i]
));
}
//for (size_t i = 0; i < ctx.matchingDef->operandCount; ++i)
//{
// ZYDIS_CHECK(ZydisPrepareOperand(
// &ctx, &request->operands[i],
// &ctx.matchingDef->operands[i]
// ));
//}
//
// Do actual encoding work.
ZYDIS_CHECK(ZydisEmitLegacyPrefixes(&ctx));
if (request->attributes & ZYDIS_ATTRIB_HAS_REX ) ZYDIS_CHECK(ZydisEmitREX (&ctx));
@ -1130,7 +1109,7 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
if (request->attributes & ZYDIS_ATTRIB_HAS_EVEX ) ZYDIS_CHECK(ZydisEmitEVEX (&ctx));
if (request->attributes & ZYDIS_ATTRIB_HAS_XOP ) ZYDIS_CHECK(ZydisEmitXOP (&ctx));
if (ctx.shouldEmitMandatoryPrefix) ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.mandatoryPrefix));
if (ctx.emitMandatoryPrefix) ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.mandatoryPrefix));
for (uint8_t i = 0; i < ctx.opcodeMapPrefixLen; ++i)
{

View File

@ -139,7 +139,7 @@ typedef struct ZydisOperandDefinition_
ZydisInternalElementType elementType ZYDIS_BITFIELD(5);
union
{
uint8_t encoding;
ZydisOperandEncoding encoding;
struct
{
uint8_t type ZYDIS_BITFIELD(3);