More encoder progress

This commit is contained in:
Joel Höner 2017-07-10 23:43:52 +02:00
parent 3498a33944
commit 743048852c
2 changed files with 220 additions and 42 deletions

View File

@ -61,6 +61,8 @@ extern "C" {
/* Structs */ /* Structs */
/* ============================================================================================== */ /* ============================================================================================== */
#define ZYDIS_ENCODER_MAX_OPERANDS (5)
typedef struct ZydisEncoderOperand_ typedef struct ZydisEncoderOperand_
{ {
ZydisOperandType type; ZydisOperandType type;
@ -94,7 +96,7 @@ typedef struct ZydisEncoderRequest_
ZydisInstructionAttributes attributes; ZydisInstructionAttributes attributes;
ZydisInstructionEncoding encoding; ZydisInstructionEncoding encoding;
uint8_t operandCount; uint8_t operandCount;
ZydisEncoderOperand operands[5]; ZydisEncoderOperand operands[ZYDIS_ENCODER_MAX_OPERANDS];
// TODO: AVX stuff // TODO: AVX stuff
// TODO: MVEX stuff // TODO: MVEX stuff
@ -119,7 +121,7 @@ ZYDIS_EXPORT ZydisStatus ZydisEncoderDecodedInstructionToRequest(
* @return A zydis status code. * @return A zydis status code.
*/ */
ZYDIS_EXPORT ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen, ZYDIS_EXPORT ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
ZydisEncoderRequest* request); const ZydisEncoderRequest* request);
/* ============================================================================================== */ /* ============================================================================================== */

View File

@ -35,6 +35,8 @@
/* Internal context and table types */ /* Internal context and table types */
/* ============================================================================================== */ /* ============================================================================================== */
typedef uint32_t ZydisSemanticOperandTypeMask;
struct ZydisPrefixAcceptMapping struct ZydisPrefixAcceptMapping
{ {
uint64_t has; uint64_t has;
@ -71,11 +73,13 @@ typedef struct ZydisEncoderContext_
uint8_t* buffer; uint8_t* buffer;
size_t bufferLen; size_t bufferLen;
size_t writeOffs; size_t writeOffs;
ZydisEncoderRequest* req; const ZydisEncoderRequest* req;
const ZydisEncodableInstruction* matchingInsn; const ZydisEncodableInstruction* matchingInsn;
const ZydisInstructionDefinition* matchingDef; const ZydisInstructionDefinition* matchingDef;
uint8_t matchingOperandCount; uint8_t matchingOperandCount;
const ZydisOperandDefinition* matchingOperands; const ZydisOperandDefinition* matchingOperands;
ZydisInstructionAttributes derivedAttrs;
ZydisBool emitMandatoryPrefix; ZydisBool emitMandatoryPrefix;
uint8_t mandatoryPrefix; uint8_t mandatoryPrefix;
uint8_t dispBitSize; uint8_t dispBitSize;
@ -498,7 +502,7 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
case 'X': ctx->raw.rex.X = topBit; break; case 'X': ctx->raw.rex.X = topBit; break;
default: ZYDIS_UNREACHABLE; default: ZYDIS_UNREACHABLE;
} }
if (topBit) ctx->req->attributes |= ZYDIS_ATTRIB_HAS_REX; if (topBit) ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
break; break;
case ZYDIS_INSTRUCTION_ENCODING_VEX: case ZYDIS_INSTRUCTION_ENCODING_VEX:
switch (topBitLoc) switch (topBitLoc)
@ -569,28 +573,28 @@ static ZydisStatus ZydisPrepareSegmentPrefix(ZydisEncoderContext* ctx,
switch (segment) switch (segment)
{ {
case ZYDIS_REGISTER_ES: case ZYDIS_REGISTER_ES:
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_ES; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
break; break;
case ZYDIS_REGISTER_SS: case ZYDIS_REGISTER_SS:
if (!ZydisIsStackReg(base)) if (!ZydisIsStackReg(base))
{ {
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_SS; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
} }
break; break;
case ZYDIS_REGISTER_CS: case ZYDIS_REGISTER_CS:
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_CS; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
break; break;
case ZYDIS_REGISTER_DS: case ZYDIS_REGISTER_DS:
if (ZydisIsStackReg(base)) if (ZydisIsStackReg(base))
{ {
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_DS; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
} }
break; break;
case ZYDIS_REGISTER_FS: case ZYDIS_REGISTER_FS:
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_FS; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
break; break;
case ZYDIS_REGISTER_GS: case ZYDIS_REGISTER_GS:
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_GS; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
break; break;
default: default:
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO: Better status. return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO: Better status.
@ -629,7 +633,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
ctx->raw.sib.index = 0x04 /* none */; ctx->raw.sib.index = 0x04 /* none */;
ctx->raw.sib.scale = 0x00 /* * 1 */; ctx->raw.sib.scale = 0x00 /* * 1 */;
ctx->raw.sib.base = 0x05; ctx->raw.sib.base = 0x05;
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SIB; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SIB;
} }
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
@ -657,7 +661,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
if (operand->mem.base == ZYDIS_REGISTER_EIP) if (operand->mem.base == ZYDIS_REGISTER_EIP)
{ {
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
} }
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
@ -676,7 +680,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
case 16: case 16:
break; // Nothing to do. break; // Nothing to do.
case 32: case 32:
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
break; break;
case 64: case 64:
// AMD64 doesn't allow for 16 bit addressing. // AMD64 doesn't allow for 16 bit addressing.
@ -693,7 +697,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
case 32: case 32:
break; // Nothing to do. break; // Nothing to do.
case 64: case 64:
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
default: default:
return ZYDIS_STATUS_INVALID_PARAMETER; // TODO return ZYDIS_STATUS_INVALID_PARAMETER; // TODO
} }
@ -741,7 +745,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
ctx->raw.sib.index = 0x04 /* no index */; ctx->raw.sib.index = 0x04 /* no index */;
} }
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SIB; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SIB;
} }
// Has displacement or is rBP and we have no SIB? // Has displacement or is rBP and we have no SIB?
@ -811,7 +815,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
ctx->raw.modrm.mod = 0x03 /* reg */; ctx->raw.modrm.mod = 0x03 /* reg */;
} }
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_MODRM; ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_MODRM;
break; break;
} }
case ZYDIS_OPERAND_ENCODING_OPCODE: case ZYDIS_OPERAND_ENCODING_OPCODE:
@ -820,7 +824,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
if (reg == -1) return ZYDIS_STATUS_INVALID_PARAMETER; if (reg == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
ctx->raw.opcode += reg & 0x07; ctx->raw.opcode += reg & 0x07;
ctx->raw.rex.B = (reg & 0x08) >> 3; ctx->raw.rex.B = (reg & 0x08) >> 3;
if (ctx->raw.rex.B) ctx->req->attributes |= ZYDIS_ATTRIB_HAS_REX; if (ctx->raw.rex.B) ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
break; break;
} }
case ZYDIS_OPERAND_ENCODING_NDSNDD: case ZYDIS_OPERAND_ENCODING_NDSNDD:
@ -902,16 +906,95 @@ static ZydisStatus ZydisPrepareMandatoryPrefixes(ZydisEncoderContext* ctx)
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
} }
static ZydisStatus ZydisDetermineInstructionEncoding(ZydisEncoderRequest* ctx) static ZydisStatus ZydisDeriveSemanticOperandTypeMask(
ZydisEncoderContext* ctx, const ZydisEncoderOperand* op,
ZydisSemanticOperandTypeMask* mask)
{ {
ZYDIS_ASSERT(op);
ZYDIS_ASSERT(ctx); ZYDIS_ASSERT(ctx);
ZYDIS_ASSERT(mask);
for (const ZydisEncoderOperand *op = ctx->operands, switch (op->type)
*end = ctx->operands + ctx->operandCount
; op < end
; ++op)
{ {
case ZYDIS_OPERAND_TYPE_REGISTER:
switch (ZydisRegisterGetClass(op->reg))
{
case ZYDIS_REGCLASS_GPR8:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_GPR8;
break;
case ZYDIS_REGCLASS_GPR16:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_GPR16 |
1 << ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32 |
1 << ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32;
break;
case ZYDIS_REGCLASS_GPR32:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_GPR32 |
1 << ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64 |
1 << ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64 |
1 << ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32;
break;
case ZYDIS_REGCLASS_GPR64:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_GPR64 |
1 << ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64 |
1 << ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64;
break;
case ZYDIS_REGCLASS_X87:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_FPR;
break;
case ZYDIS_REGCLASS_MMX:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_MMX;
break;
case ZYDIS_REGCLASS_XMM:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_XMM;
break;
case ZYDIS_REGCLASS_YMM:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_YMM;
break;
case ZYDIS_REGCLASS_ZMM:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_ZMM;
break;
case ZYDIS_REGCLASS_FLAGS:
case ZYDIS_REGCLASS_IP:
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
case ZYDIS_REGCLASS_SEGMENT:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_SREG;
break;
case ZYDIS_REGCLASS_TEST:
// TODO
ZYDIS_UNREACHABLE;
case ZYDIS_REGCLASS_CONTROL:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_CR;
break;
case ZYDIS_REGCLASS_DEBUG:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_DR;
break;
case ZYDIS_REGCLASS_MASK:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_MASK;
break;
case ZYDIS_REGCLASS_BOUND:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_BND;
break;
default:
ZYDIS_UNREACHABLE;
}
*mask |= ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG;
break;
case ZYDIS_OPERAND_TYPE_MEMORY:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_MEM |
1 << ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX |
1 << ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY |
1 << ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ |
1 << ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM;
break;
case ZYDIS_OPERAND_TYPE_POINTER:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_PTR;
break;
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_IMM |
1 << ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1;
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
} }
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
@ -933,15 +1016,66 @@ static ZydisStatus ZydisFindMatchingDef(
default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
} }
// Walk list of requested operands, derive possible encodings
// and perform additional sanity checks.
ZydisSemanticOperandTypeMask semOperandTypeMasks[ZYDIS_ENCODER_MAX_OPERANDS];
ZydisBool requireOperandSizeOverride = ZYDIS_FALSE;
//ZydisBool requireAddressSizeOverride = ZYDIS_FALSE;
for (uint8_t i = 0; i < req->operandCount; ++i)
{
const ZydisEncoderOperand* curReqOperand = req->operands + i;
if (curReqOperand->type == ZYDIS_OPERAND_TYPE_REGISTER)
{
switch (ZydisRegisterGetClass(curReqOperand->reg))
{
case ZYDIS_REGCLASS_GPR16:
switch (req->machineMode)
{
case 16: break; // Nothing to do.
case 32:
case 64: requireOperandSizeOverride = ZYDIS_TRUE; break;
default: return ZYDIS_STATUS_INVALID_PARAMETER;
}
break;
case ZYDIS_REGCLASS_GPR32:
switch (req->machineMode)
{
case 16: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION;
case 32:
case 64: break; // Nothing to do.
default: return ZYDIS_STATUS_INVALID_PARAMETER;
}
break;
case ZYDIS_REGCLASS_GPR64:
switch (req->machineMode)
{
case 16:
case 32: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION;
case 64: break;
default: return ZYDIS_STATUS_INVALID_PARAMETER;
}
break;
default:
; // Don't care.
}
}
ZYDIS_CHECK(ZydisDeriveSemanticOperandTypeMask(
ctx, req->operands + i, semOperandTypeMasks + i
));
}
// Walk list of candidates. // Walk list of candidates.
const ZydisEncodableInstruction* insns = NULL; const ZydisEncodableInstruction* insns = NULL;
uint8_t insnCount = ZydisGetEncodableInstructions(req->mnemonic, &insns); uint8_t insnCount = ZydisGetEncodableInstructions(req->mnemonic, &insns);
if (!insnCount) return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO if (!insnCount) return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
ZYDIS_ASSERT(insns); ZYDIS_ASSERT(insns);
for (uint8_t i = 0; i < insnCount; ++i) for (const ZydisEncodableInstruction *candidateInsn = insns,
*insnsEnd = insns + insnCount
; candidateInsn < insnsEnd
; ++candidateInsn)
{ {
const ZydisEncodableInstruction* candidateInsn = insns + i;
if (!(candidateInsn->mode & modeFlag)) goto _nextInsn; if (!(candidateInsn->mode & modeFlag)) goto _nextInsn;
const ZydisInstructionDefinition* candidateDef = NULL; const ZydisInstructionDefinition* candidateDef = NULL;
@ -999,11 +1133,53 @@ static ZydisStatus ZydisFindMatchingDef(
ZydisStatus ZydisEncoderDecodedInstructionToRequest( ZydisStatus ZydisEncoderDecodedInstructionToRequest(
const ZydisDecodedInstruction* in, ZydisEncoderRequest* out) const ZydisDecodedInstruction* in, ZydisEncoderRequest* out)
{ {
ZYDIS_ASSERT(in); if (!in || !out || in->operandCount > ZYDIS_ARRAY_SIZE(in->operands))
ZYDIS_ASSERT(out); {
return ZYDIS_STATUS_INVALID_PARAMETER;
}
(void) in; (void) out; out->machineMode = in->machineMode;
// TODO out->mnemonic = in->mnemonic;
out->attributes = in->attributes;
out->encoding = in->encoding;
out->operandCount = 0;
for (uint8_t iIn = 0
; iIn < in->operandCount && out->operandCount < ZYDIS_ARRAY_SIZE(out->operands)
; ++iIn)
{
const ZydisDecodedOperand* inOp = in->operands + iIn;
ZydisEncoderOperand* outOp = out->operands + out->operandCount;
if (inOp->visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN) continue;
outOp->type = inOp->type;
switch (inOp->type)
{
case ZYDIS_OPERAND_TYPE_REGISTER:
outOp->reg = inOp->reg;
break;
case ZYDIS_OPERAND_TYPE_MEMORY:
outOp->mem.segment = inOp->mem.segment;
outOp->mem.base = inOp->mem.base;
outOp->mem.index = inOp->mem.index;
outOp->mem.scale = inOp->mem.scale;
outOp->mem.disp = inOp->mem.disp.value;
outOp->mem.dispSize = in->raw.disp.size;
break;
case ZYDIS_OPERAND_TYPE_POINTER:
outOp->ptr.segment = inOp->ptr.segment;
outOp->ptr.offset = inOp->ptr.offset;
break;
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
outOp->imm.u = inOp->imm.value.u;
outOp->immSize = in->raw.imm->size;
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
++out->operandCount;
}
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
} }
@ -1011,7 +1187,7 @@ ZydisStatus ZydisEncoderDecodedInstructionToRequest(
#endif #endif
ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen, ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
ZydisEncoderRequest* request) const ZydisEncoderRequest* request)
{ {
if (!request || !bufferLen || request->operandCount > ZYDIS_ARRAY_SIZE(request->operands)) if (!request || !bufferLen || request->operandCount > ZYDIS_ARRAY_SIZE(request->operands))
{ {
@ -1028,7 +1204,7 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
*bufferLen = 0; *bufferLen = 0;
// Mask out attributes that can't be set explicitly by user. // Mask out attributes that can't be set explicitly by user.
request->attributes &= ZYDIS_USER_ENCODABLE_ATTRIB_MASK; ctx.derivedAttrs = request->attributes & ZYDIS_USER_ENCODABLE_ATTRIB_MASK;
// Search matching instruction, collect information about what needs to be // Search matching instruction, collect information about what needs to be
// encoded, what prefixes are required, etc. // encoded, what prefixes are required, etc.
@ -1054,13 +1230,13 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
switch (ctx.matchingInsn->encoding) switch (ctx.matchingInsn->encoding)
{ {
case ZYDIS_INSTRUCTION_ENCODING_EVEX: case ZYDIS_INSTRUCTION_ENCODING_EVEX:
request->attributes |= ZYDIS_ATTRIB_HAS_EVEX; ctx.derivedAttrs |= ZYDIS_ATTRIB_HAS_EVEX;
break; break;
case ZYDIS_INSTRUCTION_ENCODING_VEX: case ZYDIS_INSTRUCTION_ENCODING_VEX:
request->attributes |= ZYDIS_ATTRIB_HAS_VEX; ctx.derivedAttrs |= ZYDIS_ATTRIB_HAS_VEX;
break; break;
case ZYDIS_INSTRUCTION_ENCODING_XOP: case ZYDIS_INSTRUCTION_ENCODING_XOP:
request->attributes |= ZYDIS_ATTRIB_HAS_XOP; ctx.derivedAttrs |= ZYDIS_ATTRIB_HAS_XOP;
break; break;
default: default:
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
@ -1074,7 +1250,7 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
if (ctx.matchingInsn->rexW) if (ctx.matchingInsn->rexW)
{ {
ctx.raw.rex.W = 1; ctx.raw.rex.W = 1;
request->attributes |= ZYDIS_ATTRIB_HAS_REX; ctx.derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
} }
ZYDIS_CHECK(ZydisPrepareMandatoryPrefixes(&ctx)); ZYDIS_CHECK(ZydisPrepareMandatoryPrefixes(&ctx));
@ -1101,13 +1277,13 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
// &ctx.matchingDef->operands[i] // &ctx.matchingDef->operands[i]
// )); // ));
//} //}
//
// Do actual encoding work. // Do actual encoding work.
ZYDIS_CHECK(ZydisEmitLegacyPrefixes(&ctx)); ZYDIS_CHECK(ZydisEmitLegacyPrefixes(&ctx));
if (request->attributes & ZYDIS_ATTRIB_HAS_REX ) ZYDIS_CHECK(ZydisEmitREX (&ctx)); if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_REX ) ZYDIS_CHECK(ZydisEmitREX (&ctx));
if (request->attributes & ZYDIS_ATTRIB_HAS_VEX ) ZYDIS_CHECK(ZydisEmitVEX (&ctx)); if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_VEX ) ZYDIS_CHECK(ZydisEmitVEX (&ctx));
if (request->attributes & ZYDIS_ATTRIB_HAS_EVEX ) ZYDIS_CHECK(ZydisEmitEVEX (&ctx)); if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_EVEX ) ZYDIS_CHECK(ZydisEmitEVEX (&ctx));
if (request->attributes & ZYDIS_ATTRIB_HAS_XOP ) ZYDIS_CHECK(ZydisEmitXOP (&ctx)); if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_XOP ) ZYDIS_CHECK(ZydisEmitXOP (&ctx));
if (ctx.emitMandatoryPrefix) ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.mandatoryPrefix)); if (ctx.emitMandatoryPrefix) ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.mandatoryPrefix));
@ -1118,8 +1294,8 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.raw.opcode)); ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.raw.opcode));
if (request->attributes & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEmitModRM(&ctx)); if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEmitModRM(&ctx));
if (request->attributes & ZYDIS_ATTRIB_HAS_SIB ) ZYDIS_CHECK(ZydisEmitSIB (&ctx)); if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_SIB ) ZYDIS_CHECK(ZydisEmitSIB (&ctx));
if (ctx.dispBitSize ) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.disp, ctx.dispBitSize )); if (ctx.dispBitSize ) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.disp, ctx.dispBitSize ));
if (ctx.immBitSizes[0]) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.imms[0], ctx.immBitSizes[0])); if (ctx.immBitSizes[0]) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.imms[0], ctx.immBitSizes[0]));