Skip to content

Commit 3c073f6

Browse files
committed
Optimized operand definitions
1 parent c3d048c commit 3c073f6

File tree

5 files changed

+8600
-8420
lines changed

5 files changed

+8600
-8420
lines changed

include/Zydis/Internal/SharedData.h

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,28 @@ ZYAN_STATIC_ASSERT(ZYDIS_IMPLREG_TYPE_REQUIRED_BITS <= 8);
218218
ZYAN_STATIC_ASSERT(ZYDIS_REGISTER_REQUIRED_BITS <= 16);
219219
ZYAN_STATIC_ASSERT(ZYDIS_IMPLMEM_BASE_REQUIRED_BITS <= 8);
220220

221+
/**
222+
* Defines the `ZydisOperandDetails` struct.
223+
*/
224+
typedef union ZydisOperandDetails_
225+
{
226+
ZyanU8 encoding ZYAN_BITFIELD(ZYDIS_OPERAND_ENCODING_REQUIRED_BITS);
227+
struct
228+
{
229+
ZyanU8 type ZYAN_BITFIELD(ZYDIS_IMPLREG_TYPE_REQUIRED_BITS);
230+
union
231+
{
232+
ZyanU16 reg ZYAN_BITFIELD(ZYDIS_REGISTER_REQUIRED_BITS);
233+
ZyanU8 id ZYAN_BITFIELD(6);
234+
} reg;
235+
} reg;
236+
struct
237+
{
238+
ZyanU8 seg ZYAN_BITFIELD(3);
239+
ZyanU8 base ZYAN_BITFIELD(ZYDIS_IMPLMEM_BASE_REQUIRED_BITS);
240+
} mem;
241+
} ZydisOperandDetails;
242+
221243
/**
222244
* Defines the `ZydisOperandDefinition` struct.
223245
*/
@@ -226,28 +248,11 @@ typedef struct ZydisOperandDefinition_
226248
ZyanU8 type ZYAN_BITFIELD(ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS);
227249
ZyanU8 visibility ZYAN_BITFIELD(ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS);
228250
ZyanU8 actions ZYAN_BITFIELD(ZYDIS_OPERAND_ACTION_REQUIRED_BITS);
229-
ZyanU16 size[3];
230251
ZyanU8 element_type ZYAN_BITFIELD(ZYDIS_IELEMENT_TYPE_REQUIRED_BITS);
231-
union
232-
{
233-
ZyanU8 encoding ZYAN_BITFIELD(ZYDIS_OPERAND_ENCODING_REQUIRED_BITS);
234-
struct
235-
{
236-
ZyanU8 type ZYAN_BITFIELD(ZYDIS_IMPLREG_TYPE_REQUIRED_BITS);
237-
union
238-
{
239-
ZyanU16 reg ZYAN_BITFIELD(ZYDIS_REGISTER_REQUIRED_BITS);
240-
ZyanU8 id ZYAN_BITFIELD(6);
241-
} reg;
242-
} reg;
243-
struct
244-
{
245-
ZyanU8 seg ZYAN_BITFIELD(3);
246-
ZyanU8 base ZYAN_BITFIELD(ZYDIS_IMPLMEM_BASE_REQUIRED_BITS);
247-
} mem;
248-
} op;
249252
ZyanBool is_multisource4 ZYAN_BITFIELD(1);
250253
ZyanBool ignore_seg_override ZYAN_BITFIELD(1);
254+
ZyanU8 size_reference;
255+
ZyanU8 details_reference;
251256
} ZydisOperandDefinition;
252257

253258
/* ---------------------------------------------------------------------------------------------- */
@@ -947,6 +952,25 @@ ZYDIS_NO_EXPORT void ZydisGetInstructionDefinition(ZydisInstructionEncoding enco
947952
*/
948953
ZYDIS_NO_EXPORT const ZydisOperandDefinition* ZydisGetOperandDefinitions(
949954
const ZydisInstructionDefinition* definition);
955+
956+
/**
957+
* Returns size table associated with given operand definition.
958+
*
959+
* @param definition A pointer to the operand definition.
960+
*
961+
* @return A pointer to the beginning of size table.
962+
*/
963+
ZYDIS_NO_EXPORT const ZyanU16* ZydisGetOperandSizes(const ZydisOperandDefinition *definition);
964+
965+
/**
966+
* Returns pointer to `ZydisOperandDetails` structure associated with given operand definition.
967+
*
968+
* @param definition A pointer to the operand definition.
969+
*
970+
* @return A pointer to `ZydisOperandDetails` structure.
971+
*/
972+
ZYDIS_NO_EXPORT const ZydisOperandDetails* ZydisGetOperandDetails(
973+
const ZydisOperandDefinition *definition);
950974
#endif
951975

952976
/* ---------------------------------------------------------------------------------------------- */

src/Decoder.c

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,13 +1035,14 @@ static void ZydisSetOperandSizeAndElementInfo(const ZydisDecoderContext* context
10351035
ZYAN_ASSERT(definition);
10361036

10371037
// Operand size
1038+
const ZyanU16* size = ZydisGetOperandSizes(definition);
10381039
switch (operand->type)
10391040
{
10401041
case ZYDIS_OPERAND_TYPE_REGISTER:
10411042
{
1042-
if (definition->size[context->eosz_index])
1043+
if (size[context->eosz_index])
10431044
{
1044-
operand->size = definition->size[context->eosz_index] * 8;
1045+
operand->size = size[context->eosz_index] * 8;
10451046
} else
10461047
{
10471048
// TODO: TMM register size should probably be 0
@@ -1062,22 +1063,22 @@ static void ZydisSetOperandSizeAndElementInfo(const ZydisDecoderContext* context
10621063
case ZYDIS_INSTRUCTION_ENCODING_VEX:
10631064
if (operand->mem.type == ZYDIS_MEMOP_TYPE_AGEN)
10641065
{
1065-
ZYAN_ASSERT(definition->size[context->eosz_index] == 0);
1066+
ZYAN_ASSERT(size[context->eosz_index] == 0);
10661067
operand->size = instruction->address_width;
10671068
operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
10681069
} else
10691070
{
1070-
ZYAN_ASSERT(definition->size[context->eosz_index] ||
1071+
ZYAN_ASSERT(size[context->eosz_index] ||
10711072
(instruction->meta.category == ZYDIS_CATEGORY_AMX_TILE));
1072-
operand->size = definition->size[context->eosz_index] * 8;
1073+
operand->size = size[context->eosz_index] * 8;
10731074
}
10741075
break;
10751076
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
10761077
#ifndef ZYDIS_DISABLE_AVX512
1077-
if (definition->size[context->eosz_index])
1078+
if (size[context->eosz_index])
10781079
{
10791080
// Operand size is hardcoded
1080-
operand->size = definition->size[context->eosz_index] * 8;
1081+
operand->size = size[context->eosz_index] * 8;
10811082
ZYAN_ASSERT(operand->size);
10821083
} else if (!context->evex.element_size)
10831084
{
@@ -1131,10 +1132,10 @@ static void ZydisSetOperandSizeAndElementInfo(const ZydisDecoderContext* context
11311132
break;
11321133
case ZYDIS_INSTRUCTION_ENCODING_MVEX:
11331134
#ifndef ZYDIS_DISABLE_KNC
1134-
if (definition->size[context->eosz_index])
1135+
if (size[context->eosz_index])
11351136
{
11361137
// Operand size is hardcoded
1137-
operand->size = definition->size[context->eosz_index] * 8;
1138+
operand->size = size[context->eosz_index] * 8;
11381139
} else
11391140
{
11401141
ZYAN_ASSERT(definition->element_type == ZYDIS_IELEMENT_TYPE_VARIABLE);
@@ -1247,7 +1248,7 @@ static void ZydisSetOperandSizeAndElementInfo(const ZydisDecoderContext* context
12471248
operand->size = instruction->raw.imm[0].size + instruction->raw.imm[1].size;
12481249
break;
12491250
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
1250-
operand->size = definition->size[context->eosz_index] * 8;
1251+
operand->size = size[context->eosz_index] * 8;
12511252
break;
12521253
default:
12531254
ZYAN_UNREACHABLE;
@@ -1527,11 +1528,11 @@ static ZyanStatus ZydisDecodeOperandMemory(const ZydisDecoderContext* context,
15271528
* @param context A pointer to the `ZydisDecoderContext` struct.
15281529
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
15291530
* @param operand A pointer to the `ZydisDecodedOperand` struct.
1530-
* @param definition A pointer to the `ZydisOperandDefinition` struct.
1531+
* @param definition A pointer to the `ZydisOperandDetails` struct.
15311532
*/
15321533
static void ZydisDecodeOperandImplicitRegister(const ZydisDecoder* decoder,
15331534
const ZydisDecoderContext* context, const ZydisDecodedInstruction* instruction,
1534-
ZydisDecodedOperand* operand, const ZydisOperandDefinition* definition)
1535+
ZydisDecodedOperand* operand, const ZydisOperandDetails* definition)
15351536
{
15361537
ZYAN_ASSERT(context);
15371538
ZYAN_ASSERT(instruction);
@@ -1540,10 +1541,10 @@ static void ZydisDecodeOperandImplicitRegister(const ZydisDecoder* decoder,
15401541

15411542
operand->type = ZYDIS_OPERAND_TYPE_REGISTER;
15421543

1543-
switch (definition->op.reg.type)
1544+
switch (definition->reg.type)
15441545
{
15451546
case ZYDIS_IMPLREG_TYPE_STATIC:
1546-
operand->reg.value = definition->op.reg.reg.reg;
1547+
operand->reg.value = definition->reg.reg.reg;
15471548
break;
15481549
case ZYDIS_IMPLREG_TYPE_GPR_OSZ:
15491550
{
@@ -1554,14 +1555,14 @@ static void ZydisDecodeOperandImplicitRegister(const ZydisDecoder* decoder,
15541555
ZYDIS_REGCLASS_GPR64
15551556
};
15561557
operand->reg.value =
1557-
ZydisRegisterEncode(lookup[context->eosz_index], definition->op.reg.reg.id);
1558+
ZydisRegisterEncode(lookup[context->eosz_index], definition->reg.reg.id);
15581559
break;
15591560
}
15601561
case ZYDIS_IMPLREG_TYPE_GPR_ASZ:
15611562
operand->reg.value = ZydisRegisterEncode(
15621563
(instruction->address_width == 16) ? ZYDIS_REGCLASS_GPR16 :
15631564
(instruction->address_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64,
1564-
definition->op.reg.reg.id);
1565+
definition->reg.reg.id);
15651566
break;
15661567
case ZYDIS_IMPLREG_TYPE_IP_ASZ:
15671568
operand->reg.value =
@@ -1573,7 +1574,7 @@ static void ZydisDecodeOperandImplicitRegister(const ZydisDecoder* decoder,
15731574
(decoder->stack_width == ZYDIS_STACK_WIDTH_16) ? ZYDIS_REGCLASS_GPR16 :
15741575
(decoder->stack_width == ZYDIS_STACK_WIDTH_32) ? ZYDIS_REGCLASS_GPR32 :
15751576
ZYDIS_REGCLASS_GPR64,
1576-
definition->op.reg.reg.id);
1577+
definition->reg.reg.id);
15771578
break;
15781579
case ZYDIS_IMPLREG_TYPE_IP_SSZ:
15791580
operand->reg.value =
@@ -1601,11 +1602,11 @@ static void ZydisDecodeOperandImplicitRegister(const ZydisDecoder* decoder,
16011602
* @param context A pointer to the `ZydisDecoderContext` struct.
16021603
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
16031604
* @param operand A pointer to the `ZydisDecodedOperand` struct.
1604-
* @param definition A pointer to the `ZydisOperandDefinition` struct.
1605+
* @param definition A pointer to the `ZydisOperandDetails` struct.
16051606
*/
16061607
static void ZydisDecodeOperandImplicitMemory(const ZydisDecoder* decoder,
16071608
const ZydisDecoderContext* context, const ZydisDecodedInstruction* instruction,
1608-
ZydisDecodedOperand* operand, const ZydisOperandDefinition* definition)
1609+
ZydisDecodedOperand* operand, const ZydisOperandDetails* definition)
16091610
{
16101611
ZYAN_ASSERT(context);
16111612
ZYAN_ASSERT(operand);
@@ -1621,7 +1622,7 @@ static void ZydisDecodeOperandImplicitMemory(const ZydisDecoder* decoder,
16211622
operand->type = ZYDIS_OPERAND_TYPE_MEMORY;
16221623
operand->mem.type = ZYDIS_MEMOP_TYPE_MEM;
16231624

1624-
switch (definition->op.mem.base)
1625+
switch (definition->mem.base)
16251626
{
16261627
case ZYDIS_IMPLMEM_BASE_AGPR_REG:
16271628
operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index],
@@ -1658,10 +1659,10 @@ static void ZydisDecodeOperandImplicitMemory(const ZydisDecoder* decoder,
16581659
ZYAN_UNREACHABLE;
16591660
}
16601661

1661-
if (definition->op.mem.seg)
1662+
if (definition->mem.seg)
16621663
{
16631664
operand->mem.segment =
1664-
ZydisRegisterEncode(ZYDIS_REGCLASS_SEGMENT, definition->op.mem.seg - 1);
1665+
ZydisRegisterEncode(ZYDIS_REGCLASS_SEGMENT, definition->mem.seg - 1);
16651666
ZYAN_ASSERT(operand->mem.segment);
16661667
}
16671668
}
@@ -1687,6 +1688,7 @@ static ZyanStatus ZydisDecodeOperands(const ZydisDecoder* decoder, const ZydisDe
16871688
ZyanU8 imm_id = 0;
16881689
for (ZyanU8 i = 0; i < operand_count; ++i)
16891690
{
1691+
const ZydisOperandDetails *details = ZydisGetOperandDetails(operand);
16901692
ZydisRegisterClass register_class = ZYDIS_REGCLASS_INVALID;
16911693

16921694
operands[i].id = i;
@@ -1705,10 +1707,10 @@ static ZyanStatus ZydisDecodeOperands(const ZydisDecoder* decoder, const ZydisDe
17051707
switch (operand->type)
17061708
{
17071709
case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG:
1708-
ZydisDecodeOperandImplicitRegister(decoder, context, instruction, &operands[i], operand);
1710+
ZydisDecodeOperandImplicitRegister(decoder, context, instruction, &operands[i], details);
17091711
break;
17101712
case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM:
1711-
ZydisDecodeOperandImplicitMemory(decoder, context, instruction, &operands[i], operand);
1713+
ZydisDecodeOperandImplicitMemory(decoder, context, instruction, &operands[i], details);
17121714
break;
17131715
case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1:
17141716
operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
@@ -1725,7 +1727,7 @@ static ZyanStatus ZydisDecodeOperands(const ZydisDecoder* decoder, const ZydisDe
17251727
goto FinalizeOperand;
17261728
}
17271729

1728-
operands[i].encoding = operand->op.encoding;
1730+
operands[i].encoding = details->encoding;
17291731

17301732
// Register operands
17311733
switch (operand->type)
@@ -1807,7 +1809,7 @@ static ZyanStatus ZydisDecodeOperands(const ZydisDecoder* decoder, const ZydisDe
18071809
}
18081810
if (register_class)
18091811
{
1810-
switch (operand->op.encoding)
1812+
switch (details->encoding)
18111813
{
18121814
case ZYDIS_OPERAND_ENCODING_MODRM_REG:
18131815
ZYAN_CHECK(
@@ -1949,8 +1951,8 @@ static ZyanStatus ZydisDecodeOperands(const ZydisDecoder* decoder, const ZydisDe
19491951
case ZYDIS_SEMANTIC_OPTYPE_IMM:
19501952
ZYAN_ASSERT((imm_id == 0) || (imm_id == 1));
19511953
operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
1952-
operands[i].size = operand->size[context->eosz_index] * 8;
1953-
if (operand->op.encoding == ZYDIS_OPERAND_ENCODING_IS4)
1954+
operands[i].size = ZydisGetOperandSizes(operand)[context->eosz_index] * 8;
1955+
if (details->encoding == ZYDIS_OPERAND_ENCODING_IS4)
19541956
{
19551957
// The upper half of the 8-bit immediate is used to encode a register specifier
19561958
ZYAN_ASSERT(instruction->raw.imm[imm_id].size == 8);

0 commit comments

Comments
 (0)