diff --git a/include/Zydis/DecoderTypes.h b/include/Zydis/DecoderTypes.h index 644fd03..8b93c40 100644 --- a/include/Zydis/DecoderTypes.h +++ b/include/Zydis/DecoderTypes.h @@ -856,7 +856,7 @@ typedef struct ZydisDecodedInstruction_ */ ZydisVectorLength vectorLength; /** - * @brief Info about the embedded writemask-register. + * @brief Info about the embedded writemask-register (`EVEX` and `MVEX` only). */ struct { @@ -901,22 +901,22 @@ typedef struct ZydisDecodedInstruction_ ZydisRoundingMode mode; } rounding; /** - * @brief Contains info about the AVX register-swizzle (MVEX only). + * @brief Contains info about the AVX register-swizzle (`MVEX` only). */ struct { /** - * @brief The AVX register-swizzle mode (MVEX only). + * @brief The AVX register-swizzle mode (`MVEX` only). */ ZydisSwizzleMode mode; } swizzle; /** - * @brief Contains info about the AVX data-conversion (MVEX only). + * @brief Contains info about the AVX data-conversion (`MVEX` only). */ struct { /** - * @brief The AVX data-conversion mode (MVEX only). + * @brief The AVX data-conversion mode (`MVEX` only). */ ZydisConversionMode mode; } conversion; @@ -925,9 +925,10 @@ typedef struct ZydisDecodedInstruction_ */ 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; + // TODO: publish EVEX tuple-type and MVEX functionality } avx; /** * @brief Meta info. @@ -1265,6 +1266,7 @@ typedef struct ZydisDecodedInstruction_ * @brief The physical displacement size, in bits. */ ZydisU8 size; + // TODO: publish cd8 scale /** * @brief The offset of the displacement data, relative to the beginning of the * instruction, in bytes. diff --git a/include/Zydis/Internal/SharedData.h b/include/Zydis/Internal/SharedData.h index 907a929..5d6a52f 100644 --- a/include/Zydis/Internal/SharedData.h +++ b/include/Zydis/Internal/SharedData.h @@ -222,7 +222,9 @@ enum ZydisInternalElementSizes ZYDIS_IELEMENT_SIZE_16, ZYDIS_IELEMENT_SIZE_32, 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_16, 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_4_TO_8, 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 }; /* ---------------------------------------------------------------------------------------------- */ diff --git a/include/Zydis/SharedTypes.h b/include/Zydis/SharedTypes.h index ee86779..a457857 100644 --- a/include/Zydis/SharedTypes.h +++ b/include/Zydis/SharedTypes.h @@ -114,7 +114,7 @@ typedef ZydisU8 ZydisAddressWidth; */ 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_32 = 32, ZYDIS_ADDRESS_WIDTH_64 = 64, diff --git a/src/Decoder.c b/src/Decoder.c index ac48f27..025c53c 100644 --- a/src/Decoder.c +++ b/src/Decoder.c @@ -139,7 +139,7 @@ typedef struct ZydisDecoderContext_ /* ---------------------------------------------------------------------------------------------- */ /** - * @brief Defines the @c ZydisRegisterEncoding struct. + * @brief Defines the @c ZydisRegisterEncoding datatype. */ typedef ZydisU8 ZydisRegisterEncoding; @@ -2341,29 +2341,17 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context, if (def->broadcast) { 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: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_2; - break; - case ZYDIS_VEX_STATIC_BROADCAST_1_TO_4: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_4; - break; - case ZYDIS_VEX_STATIC_BROADCAST_1_TO_8: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8; - break; - 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; - } + ZYDIS_BROADCAST_MODE_INVALID, + ZYDIS_BROADCAST_MODE_1_TO_2, + ZYDIS_BROADCAST_MODE_1_TO_4, + ZYDIS_BROADCAST_MODE_1_TO_8, + ZYDIS_BROADCAST_MODE_1_TO_16, + ZYDIS_BROADCAST_MODE_1_TO_32, + ZYDIS_BROADCAST_MODE_2_TO_4 + }; + instruction->avx.broadcast.mode = broadcasts[def->broadcast]; } break; } @@ -2395,154 +2383,109 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context, ZYDIS_ASSERT(def->elementSize); // Element size - switch (def->elementSize) + static const ZydisU8 elementSizes[ZYDIS_IELEMENT_SIZE_MAX_VALUE + 1] = { - case ZYDIS_IELEMENT_SIZE_8: - context->evex.elementSize = 8; - break; - case ZYDIS_IELEMENT_SIZE_16: - 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; - } + 0, 8, 16, 32, 64, 128 + }; + ZYDIS_ASSERT(def->elementSize < ZYDIS_ARRAY_SIZE(elementSizes)); + context->evex.elementSize = elementSizes[def->elementSize]; // Compressed disp8 scale and broadcast-factor switch (def->tupleType) { case ZYDIS_TUPLETYPE_FV: - switch (instruction->raw.evex.b) + { + const ZydisU8 evex_b = instruction->raw.evex.b; + 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 0: - switch (instruction->avx.vectorLength) - { - case 128: - context->cd8scale = 16; - break; - case 256: - 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: - ZYDIS_ASSERT(context->evex.elementSize == 32); - context->cd8scale = 4; - switch (instruction->avx.vectorLength) + /*B0*/ { /*W0*/ { 16, 32, 64 }, /*W1*/ { 16, 32, 64 } }, + /*B1*/ { /*W0*/ { 4, 4, 4 }, /*W1*/ { 8, 8, 8 } } + }; + static const ZydisBroadcastMode broadcasts[2][2][3] = + { + /*B0*/ + { + /*W0*/ { - case 128: - 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) + ZYDIS_BROADCAST_MODE_INVALID, + ZYDIS_BROADCAST_MODE_INVALID, + ZYDIS_BROADCAST_MODE_INVALID + }, + /*W1*/ + { + ZYDIS_BROADCAST_MODE_INVALID, + ZYDIS_BROADCAST_MODE_INVALID, + ZYDIS_BROADCAST_MODE_INVALID + } + }, + /*B1*/ + { + /*W0*/ { - case 128: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_2; - break; - case 256: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_4; - break; - case 512: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8; - break; - default: - ZYDIS_UNREACHABLE; - } - break; - default: - ZYDIS_UNREACHABLE; + 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; + } 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); - switch (instruction->raw.evex.b) + ZYDIS_ASSERT(!evex_b || def->functionality == ZYDIS_EVEX_FUNC_BC); + + static const ZydisU8 scales[2][3] = { - case 0: - switch (instruction->avx.vectorLength) - { - case 128: - context->cd8scale = 8; - break; - case 256: - context->cd8scale = 16; - break; - case 512: - context->cd8scale = 32; - break; - default: - ZYDIS_UNREACHABLE; + /*B0*/ { 8, 16, 32 }, + /*B1*/ { 4, 4, 4 } + }; + static const ZydisBroadcastMode broadcasts[2][3] = + { + /*B0*/ + { + ZYDIS_BROADCAST_MODE_INVALID, + ZYDIS_BROADCAST_MODE_INVALID, + ZYDIS_BROADCAST_MODE_INVALID + }, + /*B1*/ + { + ZYDIS_BROADCAST_MODE_1_TO_2, + ZYDIS_BROADCAST_MODE_1_TO_4, + ZYDIS_BROADCAST_MODE_1_TO_8 } - break; - case 1: - context->cd8scale = 4; - switch (instruction->avx.vectorLength) - { - case 128: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_2; - break; - case 256: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_4; - break; - case 512: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8; - break; - default: - ZYDIS_UNREACHABLE; - } - break; - default: - ZYDIS_UNREACHABLE; - } + }; + context->cd8scale = scales[evex_b][vectorLength]; + instruction->avx.broadcast.mode = broadcasts[evex_b][vectorLength]; break; + } case ZYDIS_TUPLETYPE_FVM: - switch (instruction->avx.vectorLength) + { + static const ZydisU8 scales[3] = { - case 128: - context->cd8scale = 16; - break; - case 256: - context->cd8scale = 32; - break; - case 512: - context->cd8scale = 64; - break; - default: - ZYDIS_UNREACHABLE; - } + 16, 32, 64 + }; + context->cd8scale = scales[vectorLength]; break; + } case ZYDIS_TUPLETYPE_GSCAT: switch (context->cache.W) { @@ -2556,8 +2499,20 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context, ZYDIS_UNREACHABLE; } 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; + }; case ZYDIS_TUPLETYPE_T1F: switch (context->evex.elementSize) { @@ -2618,72 +2573,44 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context, context->cd8scale = 32; break; case ZYDIS_TUPLETYPE_HVM: - switch (instruction->avx.vectorLength) + { + static const ZydisU8 scales[3] = { - case 128: - context->cd8scale = 8; - break; - case 256: - context->cd8scale = 16; - break; - case 512: - context->cd8scale = 32; - break; - default: - ZYDIS_UNREACHABLE; - } + 8, 16, 32 + }; + context->cd8scale = scales[vectorLength]; break; + } case ZYDIS_TUPLETYPE_QVM: - switch (instruction->avx.vectorLength) + { + static const ZydisU8 scales[3] = { - case 128: - context->cd8scale = 4; - break; - case 256: - context->cd8scale = 8; - break; - case 512: - context->cd8scale = 16; - break; - default: - ZYDIS_UNREACHABLE; - } + 4, 8, 16 + }; + context->cd8scale = scales[vectorLength]; break; + } case ZYDIS_TUPLETYPE_OVM: - switch (instruction->avx.vectorLength) + { + static const ZydisU8 scales[3] = { - case 128: - context->cd8scale = 2; - break; - case 256: - context->cd8scale = 4; - break; - case 512: - context->cd8scale = 8; - break; - default: - ZYDIS_UNREACHABLE; - } + 2, 4, 8 + }; + context->cd8scale = scales[vectorLength]; break; + } case ZYDIS_TUPLETYPE_M128: context->cd8scale = 16; break; case ZYDIS_TUPLETYPE_DUP: - switch (instruction->avx.vectorLength) + { + static const ZydisU8 scales[3] = { - case 128: - context->cd8scale = 8; - break; - case 256: - context->cd8scale = 32; - break; - case 512: - context->cd8scale = 64; - break; - default: - ZYDIS_UNREACHABLE; - } + 8, 32, 64 + }; + context->cd8scale = scales[vectorLength]; break; + } default: ZYDIS_UNREACHABLE; } @@ -2697,47 +2624,24 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context, { ZYDIS_ASSERT(!instruction->avx.broadcast.mode); 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: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_2; - break; - case ZYDIS_EVEX_STATIC_BROADCAST_1_TO_4: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_4; - break; - case ZYDIS_EVEX_STATIC_BROADCAST_1_TO_8: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8; - break; - case ZYDIS_EVEX_STATIC_BROADCAST_1_TO_16: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16; - break; - case ZYDIS_EVEX_STATIC_BROADCAST_1_TO_32: - instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_32; - break; - case ZYDIS_EVEX_STATIC_BROADCAST_1_TO_64: - 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; - } + ZYDIS_BROADCAST_MODE_INVALID, + ZYDIS_BROADCAST_MODE_1_TO_2, + ZYDIS_BROADCAST_MODE_1_TO_4, + ZYDIS_BROADCAST_MODE_1_TO_8, + ZYDIS_BROADCAST_MODE_1_TO_16, + ZYDIS_BROADCAST_MODE_1_TO_32, + ZYDIS_BROADCAST_MODE_1_TO_64, + ZYDIS_BROADCAST_MODE_2_TO_4, + ZYDIS_BROADCAST_MODE_2_TO_8, + ZYDIS_BROADCAST_MODE_2_TO_16, + ZYDIS_BROADCAST_MODE_4_TO_8, + ZYDIS_BROADCAST_MODE_4_TO_16, + ZYDIS_BROADCAST_MODE_8_TO_16 + }; + ZYDIS_ASSERT(def->broadcast < ZYDIS_ARRAY_SIZE(broadcasts)); + instruction->avx.broadcast.mode = broadcasts[def->broadcast]; } // Rounding mode and SAE @@ -4094,7 +3998,7 @@ static ZydisStatus ZydisNodeHandlerMvexE(ZydisDecodedInstruction* instruction, Z * * @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, ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition)