Internal refactorings and performance optimizations

This commit is contained in:
flobernd 2018-01-10 17:02:11 +01:00
parent 585fa7035a
commit fb519fe933
No known key found for this signature in database
GPG Key ID: 9C3AE0ED4A969F10
4 changed files with 168 additions and 256 deletions

View File

@ -856,7 +856,7 @@ typedef struct ZydisDecodedInstruction_
*/ */
ZydisVectorLength vectorLength; ZydisVectorLength vectorLength;
/** /**
* @brief Info about the embedded writemask-register. * @brief Info about the embedded writemask-register (`EVEX` and `MVEX` only).
*/ */
struct struct
{ {
@ -901,22 +901,22 @@ typedef struct ZydisDecodedInstruction_
ZydisRoundingMode mode; ZydisRoundingMode mode;
} rounding; } rounding;
/** /**
* @brief Contains info about the AVX register-swizzle (MVEX only). * @brief Contains info about the AVX register-swizzle (`MVEX` only).
*/ */
struct struct
{ {
/** /**
* @brief The AVX register-swizzle mode (MVEX only). * @brief The AVX register-swizzle mode (`MVEX` only).
*/ */
ZydisSwizzleMode mode; ZydisSwizzleMode mode;
} swizzle; } swizzle;
/** /**
* @brief Contains info about the AVX data-conversion (MVEX only). * @brief Contains info about the AVX data-conversion (`MVEX` only).
*/ */
struct struct
{ {
/** /**
* @brief The AVX data-conversion mode (MVEX only). * @brief The AVX data-conversion mode (`MVEX` only).
*/ */
ZydisConversionMode mode; ZydisConversionMode mode;
} conversion; } conversion;
@ -925,9 +925,10 @@ typedef struct ZydisDecodedInstruction_
*/ */
ZydisBool hasSAE; ZydisBool hasSAE;
/** /**
* @brief Signals, if the instruction has a memory eviction-hint (MVEX only). * @brief Signals, if the instruction has a memory eviction-hint (`MVEX` only).
*/ */
ZydisBool hasEvictionHint; ZydisBool hasEvictionHint;
// TODO: publish EVEX tuple-type and MVEX functionality
} avx; } avx;
/** /**
* @brief Meta info. * @brief Meta info.
@ -1265,6 +1266,7 @@ typedef struct ZydisDecodedInstruction_
* @brief The physical displacement size, in bits. * @brief The physical displacement size, in bits.
*/ */
ZydisU8 size; ZydisU8 size;
// TODO: publish cd8 scale
/** /**
* @brief The offset of the displacement data, relative to the beginning of the * @brief The offset of the displacement data, relative to the beginning of the
* instruction, in bytes. * instruction, in bytes.

View File

@ -222,7 +222,9 @@ enum ZydisInternalElementSizes
ZYDIS_IELEMENT_SIZE_16, ZYDIS_IELEMENT_SIZE_16,
ZYDIS_IELEMENT_SIZE_32, ZYDIS_IELEMENT_SIZE_32,
ZYDIS_IELEMENT_SIZE_64, ZYDIS_IELEMENT_SIZE_64,
ZYDIS_IELEMENT_SIZE_128 ZYDIS_IELEMENT_SIZE_128,
ZYDIS_IELEMENT_SIZE_MAX_VALUE = ZYDIS_IELEMENT_SIZE_128
}; };
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
@ -463,7 +465,9 @@ enum ZydisVEXStaticBroadcasts
ZYDIS_VEX_STATIC_BROADCAST_1_TO_8, ZYDIS_VEX_STATIC_BROADCAST_1_TO_8,
ZYDIS_VEX_STATIC_BROADCAST_1_TO_16, ZYDIS_VEX_STATIC_BROADCAST_1_TO_16,
ZYDIS_VEX_STATIC_BROADCAST_1_TO_32, ZYDIS_VEX_STATIC_BROADCAST_1_TO_32,
ZYDIS_VEX_STATIC_BROADCAST_2_TO_4 ZYDIS_VEX_STATIC_BROADCAST_2_TO_4,
ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_VEX_STATIC_BROADCAST_2_TO_4
}; };
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
@ -490,7 +494,9 @@ enum ZydisEVEXStaticBroadcasts
ZYDIS_EVEX_STATIC_BROADCAST_2_TO_16, ZYDIS_EVEX_STATIC_BROADCAST_2_TO_16,
ZYDIS_EVEX_STATIC_BROADCAST_4_TO_8, ZYDIS_EVEX_STATIC_BROADCAST_4_TO_8,
ZYDIS_EVEX_STATIC_BROADCAST_4_TO_16, ZYDIS_EVEX_STATIC_BROADCAST_4_TO_16,
ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16 ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16,
ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16
}; };
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */

View File

@ -114,7 +114,7 @@ typedef ZydisU8 ZydisAddressWidth;
*/ */
enum ZydisAddressWidths enum ZydisAddressWidths
{ {
ZYDIS_ADDRESS_WIDTH_INVALID = 0, ZYDIS_ADDRESS_WIDTH_INVALID = 0, // TODO: Don't manually initialize values
ZYDIS_ADDRESS_WIDTH_16 = 16, ZYDIS_ADDRESS_WIDTH_16 = 16,
ZYDIS_ADDRESS_WIDTH_32 = 32, ZYDIS_ADDRESS_WIDTH_32 = 32,
ZYDIS_ADDRESS_WIDTH_64 = 64, ZYDIS_ADDRESS_WIDTH_64 = 64,

View File

@ -139,7 +139,7 @@ typedef struct ZydisDecoderContext_
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Defines the @c ZydisRegisterEncoding struct. * @brief Defines the @c ZydisRegisterEncoding datatype.
*/ */
typedef ZydisU8 ZydisRegisterEncoding; typedef ZydisU8 ZydisRegisterEncoding;
@ -2341,29 +2341,17 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
if (def->broadcast) if (def->broadcast)
{ {
instruction->avx.broadcast.isStatic = ZYDIS_TRUE; instruction->avx.broadcast.isStatic = ZYDIS_TRUE;
switch (def->broadcast) static ZydisBroadcastMode broadcasts[ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE + 1] =
{ {
case ZYDIS_VEX_STATIC_BROADCAST_1_TO_2: ZYDIS_BROADCAST_MODE_INVALID,
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_2; ZYDIS_BROADCAST_MODE_1_TO_2,
break; ZYDIS_BROADCAST_MODE_1_TO_4,
case ZYDIS_VEX_STATIC_BROADCAST_1_TO_4: ZYDIS_BROADCAST_MODE_1_TO_8,
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_4; ZYDIS_BROADCAST_MODE_1_TO_16,
break; ZYDIS_BROADCAST_MODE_1_TO_32,
case ZYDIS_VEX_STATIC_BROADCAST_1_TO_8: ZYDIS_BROADCAST_MODE_2_TO_4
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8; };
break; instruction->avx.broadcast.mode = broadcasts[def->broadcast];
case ZYDIS_VEX_STATIC_BROADCAST_1_TO_16:
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16;
break;
case ZYDIS_VEX_STATIC_BROADCAST_1_TO_32:
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_32;
break;
case ZYDIS_VEX_STATIC_BROADCAST_2_TO_4:
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_2_TO_4;
break;
default:
ZYDIS_UNREACHABLE;
}
} }
break; break;
} }
@ -2395,154 +2383,109 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
ZYDIS_ASSERT(def->elementSize); ZYDIS_ASSERT(def->elementSize);
// Element size // Element size
switch (def->elementSize) static const ZydisU8 elementSizes[ZYDIS_IELEMENT_SIZE_MAX_VALUE + 1] =
{ {
case ZYDIS_IELEMENT_SIZE_8: 0, 8, 16, 32, 64, 128
context->evex.elementSize = 8; };
break; ZYDIS_ASSERT(def->elementSize < ZYDIS_ARRAY_SIZE(elementSizes));
case ZYDIS_IELEMENT_SIZE_16: context->evex.elementSize = elementSizes[def->elementSize];
context->evex.elementSize = 16;
break;
case ZYDIS_IELEMENT_SIZE_32:
context->evex.elementSize = 32;
break;
case ZYDIS_IELEMENT_SIZE_64:
context->evex.elementSize = 64;
break;
case ZYDIS_IELEMENT_SIZE_128:
context->evex.elementSize = 128;
break;
default:
ZYDIS_UNREACHABLE;
}
// Compressed disp8 scale and broadcast-factor // Compressed disp8 scale and broadcast-factor
switch (def->tupleType) switch (def->tupleType)
{ {
case ZYDIS_TUPLETYPE_FV: case ZYDIS_TUPLETYPE_FV:
switch (instruction->raw.evex.b)
{ {
case 0: const ZydisU8 evex_b = instruction->raw.evex.b;
switch (instruction->avx.vectorLength) const ZydisU8 evex_w = context->cache.W;
ZYDIS_ASSERT(evex_b < 2);
ZYDIS_ASSERT(evex_w < 2);
ZYDIS_ASSERT(!evex_b || ((!evex_w && context->evex.elementSize == 32) ||
( evex_w && context->evex.elementSize == 64)));
ZYDIS_ASSERT(!evex_b || def->functionality == ZYDIS_EVEX_FUNC_BC);
static const ZydisU8 scales[2][2][3] =
{ {
case 128: /*B0*/ { /*W0*/ { 16, 32, 64 }, /*W1*/ { 16, 32, 64 } },
context->cd8scale = 16; /*B1*/ { /*W0*/ { 4, 4, 4 }, /*W1*/ { 8, 8, 8 } }
break; };
case 256: static const ZydisBroadcastMode broadcasts[2][2][3] =
context->cd8scale = 32;
break;
case 512:
context->cd8scale = 64;
break;
default:
ZYDIS_UNREACHABLE;
}
break;
case 1:
ZYDIS_ASSERT(def->functionality == ZYDIS_EVEX_FUNC_BC);
switch (context->cache.W)
{ {
case 0: /*B0*/
ZYDIS_ASSERT(context->evex.elementSize == 32);
context->cd8scale = 4;
switch (instruction->avx.vectorLength)
{ {
case 128: /*W0*/
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_4;
break;
case 256:
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8;
break;
case 512:
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16;
break;
default:
ZYDIS_UNREACHABLE;
}
break;
case 1:
ZYDIS_ASSERT(context->evex.elementSize == 64);
context->cd8scale = 8;
switch (instruction->avx.vectorLength)
{ {
case 128: ZYDIS_BROADCAST_MODE_INVALID,
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_2; ZYDIS_BROADCAST_MODE_INVALID,
break; ZYDIS_BROADCAST_MODE_INVALID
case 256: },
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_4; /*W1*/
break; {
case 512: ZYDIS_BROADCAST_MODE_INVALID,
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8; ZYDIS_BROADCAST_MODE_INVALID,
break; ZYDIS_BROADCAST_MODE_INVALID
default:
ZYDIS_UNREACHABLE;
} }
break; },
default: /*B1*/
ZYDIS_UNREACHABLE; {
/*W0*/
{
ZYDIS_BROADCAST_MODE_1_TO_4,
ZYDIS_BROADCAST_MODE_1_TO_8,
ZYDIS_BROADCAST_MODE_1_TO_16
},
/*W1*/
{
ZYDIS_BROADCAST_MODE_1_TO_2,
ZYDIS_BROADCAST_MODE_1_TO_4,
ZYDIS_BROADCAST_MODE_1_TO_8
} }
break;
default:
ZYDIS_UNREACHABLE;
} }
};
context->cd8scale = scales[evex_b][evex_w][vectorLength];
instruction->avx.broadcast.mode = broadcasts[evex_b][evex_w][vectorLength];
break; break;
}
case ZYDIS_TUPLETYPE_HV: case ZYDIS_TUPLETYPE_HV:
{
const ZydisU8 evex_b = instruction->raw.evex.b;
ZYDIS_ASSERT(evex_b < 2);
ZYDIS_ASSERT(!context->cache.W);
ZYDIS_ASSERT(context->evex.elementSize == 32); ZYDIS_ASSERT(context->evex.elementSize == 32);
switch (instruction->raw.evex.b) ZYDIS_ASSERT(!evex_b || def->functionality == ZYDIS_EVEX_FUNC_BC);
static const ZydisU8 scales[2][3] =
{ {
case 0: /*B0*/ { 8, 16, 32 },
switch (instruction->avx.vectorLength) /*B1*/ { 4, 4, 4 }
};
static const ZydisBroadcastMode broadcasts[2][3] =
{ {
case 128: /*B0*/
context->cd8scale = 8;
break;
case 256:
context->cd8scale = 16;
break;
case 512:
context->cd8scale = 32;
break;
default:
ZYDIS_UNREACHABLE;
}
break;
case 1:
context->cd8scale = 4;
switch (instruction->avx.vectorLength)
{ {
case 128: ZYDIS_BROADCAST_MODE_INVALID,
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_2; ZYDIS_BROADCAST_MODE_INVALID,
break; ZYDIS_BROADCAST_MODE_INVALID
case 256: },
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_4; /*B1*/
break; {
case 512: ZYDIS_BROADCAST_MODE_1_TO_2,
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8; ZYDIS_BROADCAST_MODE_1_TO_4,
break; ZYDIS_BROADCAST_MODE_1_TO_8
default:
ZYDIS_UNREACHABLE;
} }
};
context->cd8scale = scales[evex_b][vectorLength];
instruction->avx.broadcast.mode = broadcasts[evex_b][vectorLength];
break; break;
default:
ZYDIS_UNREACHABLE;
} }
break;
case ZYDIS_TUPLETYPE_FVM: case ZYDIS_TUPLETYPE_FVM:
switch (instruction->avx.vectorLength)
{ {
case 128: static const ZydisU8 scales[3] =
context->cd8scale = 16; {
16, 32, 64
};
context->cd8scale = scales[vectorLength];
break; break;
case 256:
context->cd8scale = 32;
break;
case 512:
context->cd8scale = 64;
break;
default:
ZYDIS_UNREACHABLE;
} }
break;
case ZYDIS_TUPLETYPE_GSCAT: case ZYDIS_TUPLETYPE_GSCAT:
switch (context->cache.W) switch (context->cache.W)
{ {
@ -2556,8 +2499,20 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
} }
case ZYDIS_TUPLETYPE_T1S: case ZYDIS_TUPLETYPE_T1S:
context->cd8scale = context->evex.elementSize / 8; {
static const ZydisU8 scales[6] =
{
/* */ 0,
/* 8*/ 1,
/* 16*/ 2,
/* 32*/ 4,
/* 64*/ 8,
/*128*/ 16,
};
ZYDIS_ASSERT(def->elementSize < ZYDIS_ARRAY_SIZE(scales));
context->cd8scale = scales[def->elementSize];
break; break;
};
case ZYDIS_TUPLETYPE_T1F: case ZYDIS_TUPLETYPE_T1F:
switch (context->evex.elementSize) switch (context->evex.elementSize)
{ {
@ -2618,72 +2573,44 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
context->cd8scale = 32; context->cd8scale = 32;
break; break;
case ZYDIS_TUPLETYPE_HVM: case ZYDIS_TUPLETYPE_HVM:
switch (instruction->avx.vectorLength)
{ {
case 128: static const ZydisU8 scales[3] =
context->cd8scale = 8; {
8, 16, 32
};
context->cd8scale = scales[vectorLength];
break; break;
case 256:
context->cd8scale = 16;
break;
case 512:
context->cd8scale = 32;
break;
default:
ZYDIS_UNREACHABLE;
} }
break;
case ZYDIS_TUPLETYPE_QVM: case ZYDIS_TUPLETYPE_QVM:
switch (instruction->avx.vectorLength)
{ {
case 128: static const ZydisU8 scales[3] =
context->cd8scale = 4; {
4, 8, 16
};
context->cd8scale = scales[vectorLength];
break; break;
case 256:
context->cd8scale = 8;
break;
case 512:
context->cd8scale = 16;
break;
default:
ZYDIS_UNREACHABLE;
} }
break;
case ZYDIS_TUPLETYPE_OVM: case ZYDIS_TUPLETYPE_OVM:
switch (instruction->avx.vectorLength)
{ {
case 128: static const ZydisU8 scales[3] =
context->cd8scale = 2; {
2, 4, 8
};
context->cd8scale = scales[vectorLength];
break; break;
case 256:
context->cd8scale = 4;
break;
case 512:
context->cd8scale = 8;
break;
default:
ZYDIS_UNREACHABLE;
} }
break;
case ZYDIS_TUPLETYPE_M128: case ZYDIS_TUPLETYPE_M128:
context->cd8scale = 16; context->cd8scale = 16;
break; break;
case ZYDIS_TUPLETYPE_DUP: case ZYDIS_TUPLETYPE_DUP:
switch (instruction->avx.vectorLength)
{ {
case 128: static const ZydisU8 scales[3] =
context->cd8scale = 8; {
8, 32, 64
};
context->cd8scale = scales[vectorLength];
break; break;
case 256:
context->cd8scale = 32;
break;
case 512:
context->cd8scale = 64;
break;
default:
ZYDIS_UNREACHABLE;
} }
break;
default: default:
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
} }
@ -2697,47 +2624,24 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
{ {
ZYDIS_ASSERT(!instruction->avx.broadcast.mode); ZYDIS_ASSERT(!instruction->avx.broadcast.mode);
instruction->avx.broadcast.isStatic = ZYDIS_TRUE; instruction->avx.broadcast.isStatic = ZYDIS_TRUE;
switch (def->broadcast) static const ZydisBroadcastMode broadcasts[ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE + 1] =
{ {
case ZYDIS_EVEX_STATIC_BROADCAST_1_TO_2: ZYDIS_BROADCAST_MODE_INVALID,
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_2; ZYDIS_BROADCAST_MODE_1_TO_2,
break; ZYDIS_BROADCAST_MODE_1_TO_4,
case ZYDIS_EVEX_STATIC_BROADCAST_1_TO_4: ZYDIS_BROADCAST_MODE_1_TO_8,
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_4; ZYDIS_BROADCAST_MODE_1_TO_16,
break; ZYDIS_BROADCAST_MODE_1_TO_32,
case ZYDIS_EVEX_STATIC_BROADCAST_1_TO_8: ZYDIS_BROADCAST_MODE_1_TO_64,
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8; ZYDIS_BROADCAST_MODE_2_TO_4,
break; ZYDIS_BROADCAST_MODE_2_TO_8,
case ZYDIS_EVEX_STATIC_BROADCAST_1_TO_16: ZYDIS_BROADCAST_MODE_2_TO_16,
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16; ZYDIS_BROADCAST_MODE_4_TO_8,
break; ZYDIS_BROADCAST_MODE_4_TO_16,
case ZYDIS_EVEX_STATIC_BROADCAST_1_TO_32: ZYDIS_BROADCAST_MODE_8_TO_16
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_32; };
break; ZYDIS_ASSERT(def->broadcast < ZYDIS_ARRAY_SIZE(broadcasts));
case ZYDIS_EVEX_STATIC_BROADCAST_1_TO_64: instruction->avx.broadcast.mode = broadcasts[def->broadcast];
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_64;
break;
case ZYDIS_EVEX_STATIC_BROADCAST_2_TO_4:
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_2_TO_4;
break;
case ZYDIS_EVEX_STATIC_BROADCAST_2_TO_8:
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_2_TO_8;
break;
case ZYDIS_EVEX_STATIC_BROADCAST_2_TO_16:
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_2_TO_16;
break;
case ZYDIS_EVEX_STATIC_BROADCAST_4_TO_8:
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_8;
break;
case ZYDIS_EVEX_STATIC_BROADCAST_4_TO_16:
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_16;
break;
case ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16:
instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_8_TO_16;
break;
default:
ZYDIS_UNREACHABLE;
}
} }
// Rounding mode and SAE // Rounding mode and SAE
@ -4094,7 +3998,7 @@ static ZydisStatus ZydisNodeHandlerMvexE(ZydisDecodedInstruction* instruction, Z
* *
* @return A zydis status code. * @return A zydis status code.
* *
* This function is called directly after a valid instruction-definition was found. * This function is called immediately after a valid instruction-definition was found.
*/ */
static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context, static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition) ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition)