Various bugfixes

- Fixed operand-size and element-count of AGEN operands
- Fixed decoding of 8-bit modrm.rm register-operands
- Fixed vector-length for EVEX instructions with rounding-semantics
This commit is contained in:
flobernd 2017-06-19 20:19:21 +02:00
parent 2d2e1acf27
commit 4bceac86c9
4 changed files with 2907 additions and 2833 deletions

View File

@ -750,6 +750,10 @@ enum ZydisTupleTypes
* @brief Tuple1 Fixed * @brief Tuple1 Fixed
*/ */
ZYDIS_TUPLETYPE_T1F, ZYDIS_TUPLETYPE_T1F,
/**
* @brief Tuple1 4x32
*/
ZYDIS_TUPLETYPE_T1_4X,
/** /**
* @brief Gather / Scatter * @brief Gather / Scatter
*/ */
@ -785,11 +789,7 @@ enum ZydisTupleTypes
/** /**
* @brief MOVDDUP * @brief MOVDDUP
*/ */
ZYDIS_TUPLETYPE_DUP, ZYDIS_TUPLETYPE_DUP
/**
* @brief Tuple1 4x32
*/
ZYDIS_TUPLETYPE_T1_4X
}; };
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */

File diff suppressed because it is too large Load Diff

View File

@ -290,6 +290,43 @@ enum ZydisImplicitMemBase
/* Instruction definition */ /* Instruction definition */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisInternalVectorLength datatype.
*/
typedef uint8_t ZydisInternalVectorLength;
/**
* @brief Values that represent internal vector-lengths.
*/
enum ZydisInternalVectorLengths
{
ZYDIS_IVECTOR_LENGTH_DEFAULT,
ZYDIS_IVECTOR_LENGTH_FIXED_128,
ZYDIS_IVECTOR_LENGTH_FIXED_256,
ZYDIS_IVECTOR_LENGTH_FIXED_512
};
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisInternalElementSize datatype.
*/
typedef uint8_t ZydisInternalElementSize;
/**
* @brief Values that represent internal element-sizes.
*/
enum ZydisInternalElementSizes
{
ZYDIS_IELEMENT_SIZE_INVALID,
ZYDIS_IELEMENT_SIZE_8,
ZYDIS_IELEMENT_SIZE_16,
ZYDIS_IELEMENT_SIZE_32,
ZYDIS_IELEMENT_SIZE_64
};
/* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Defines the @c ZydisEVEXFunctionality datatype. * @brief Defines the @c ZydisEVEXFunctionality datatype.
*/ */
@ -392,8 +429,9 @@ typedef struct ZydisInstructionDefinitionVEX_
typedef struct ZydisInstructionDefinitionEVEX_ typedef struct ZydisInstructionDefinitionEVEX_
{ {
ZYDIS_INSTRUCTION_DEFINITION_BASE; ZYDIS_INSTRUCTION_DEFINITION_BASE;
ZydisInternalVectorLength vectorLength: 2;
ZydisTupleType tupleType : 4; ZydisTupleType tupleType : 4;
uint8_t elementSize : 7; ZydisInternalElementSize elementSize : 4;
ZydisEVEXFunctionality functionality : 2; ZydisEVEXFunctionality functionality : 2;
ZydisMaskPolicy maskPolicy : 2; ZydisMaskPolicy maskPolicy : 2;
} ZydisInstructionDefinitionEVEX; } ZydisInstructionDefinitionEVEX;

View File

@ -940,7 +940,16 @@ static void ZydisSetOperandSizeAndElementInfo(ZydisDecoderContext* context,
case ZYDIS_INSTRUCTION_ENCODING_3DNOW: case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
case ZYDIS_INSTRUCTION_ENCODING_XOP: case ZYDIS_INSTRUCTION_ENCODING_XOP:
case ZYDIS_INSTRUCTION_ENCODING_VEX: case ZYDIS_INSTRUCTION_ENCODING_VEX:
operand->size = definition->size[context->eoszIndex] * 8; if (operand->mem.isAddressGenOnly)
{
ZYDIS_ASSERT(definition->size[context->eoszIndex] == 0);
operand->size = info->addressWidth;
operand->elementCount = 1;
} else
{
ZYDIS_ASSERT(definition->size[context->eoszIndex]);
operand->size = definition->size[context->eoszIndex] * 8;
}
break; break;
case ZYDIS_INSTRUCTION_ENCODING_EVEX: case ZYDIS_INSTRUCTION_ENCODING_EVEX:
if (definition->size[context->eoszIndex]) if (definition->size[context->eoszIndex])
@ -977,6 +986,7 @@ static void ZydisSetOperandSizeAndElementInfo(ZydisDecoderContext* context,
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
} }
} }
ZYDIS_ASSERT(operand->size);
break; break;
case ZYDIS_INSTRUCTION_ENCODING_MVEX: case ZYDIS_INSTRUCTION_ENCODING_MVEX:
// TODO: // TODO:
@ -993,7 +1003,6 @@ static void ZydisSetOperandSizeAndElementInfo(ZydisDecoderContext* context,
break; break;
case ZYDIS_OPERAND_TYPE_IMMEDIATE: case ZYDIS_OPERAND_TYPE_IMMEDIATE:
operand->size = definition->size[context->eoszIndex] * 8; operand->size = definition->size[context->eoszIndex] * 8;
ZYDIS_ASSERT(operand->size);
break; break;
default: default:
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
@ -1523,10 +1532,18 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
break; break;
case ZYDIS_OPERAND_ENCODING_MODRM_RM: case ZYDIS_OPERAND_ENCODING_MODRM_RM:
ZYDIS_ASSERT(info->details.modrm.isDecoded); ZYDIS_ASSERT(info->details.modrm.isDecoded);
ZYDIS_CHECK( if (info->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX)
{
ZYDIS_CHECK(
ZydisDecodeOperandRegister(info, &info->operands[i], registerClass,
(context->cache.X << 4) |
(context->cache.B << 3) | info->details.modrm.rm));
} else
{
ZYDIS_CHECK(
ZydisDecodeOperandRegister(info, &info->operands[i], registerClass, ZydisDecodeOperandRegister(info, &info->operands[i], registerClass,
(context->cache.X << 4) |
(context->cache.B << 3) | info->details.modrm.rm)); (context->cache.B << 3) | info->details.modrm.rm));
}
break; break;
case ZYDIS_OPERAND_ENCODING_OPCODE: case ZYDIS_OPERAND_ENCODING_OPCODE:
{ {
@ -2086,35 +2103,57 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
ZYDIS_ASSERT(context); ZYDIS_ASSERT(context);
ZYDIS_ASSERT(info); ZYDIS_ASSERT(info);
ZYDIS_ASSERT(definition); ZYDIS_ASSERT(definition);
// Vector length
switch (context->cache.LL)
{
case 0:
info->avx.vectorLength = ZYDIS_VECTOR_LENGTH_128;
break;
case 1:
info->avx.vectorLength = ZYDIS_VECTOR_LENGTH_256;
break;
case 2:
info->avx.vectorLength = ZYDIS_VECTOR_LENGTH_512;
break;
default:
ZYDIS_UNREACHABLE;
}
if (info->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) if (info->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX)
{ {
const ZydisInstructionDefinitionEVEX* def = const ZydisInstructionDefinitionEVEX* def =
(const ZydisInstructionDefinitionEVEX*)definition; (const ZydisInstructionDefinitionEVEX*)definition;
uint8_t vectorLength = vectorLength = context->cache.LL;;
if (def->vectorLength)
{
vectorLength = def->vectorLength - 1;
}
// Vector length
switch (vectorLength)
{
case 0:
info->avx.vectorLength = ZYDIS_VECTOR_LENGTH_128;
break;
case 1:
info->avx.vectorLength = ZYDIS_VECTOR_LENGTH_256;
break;
case 2:
info->avx.vectorLength = ZYDIS_VECTOR_LENGTH_512;
break;
default:
ZYDIS_UNREACHABLE;
}
info->avx.tupleType = def->tupleType; info->avx.tupleType = def->tupleType;
if (info->avx.tupleType) if (info->avx.tupleType)
{ {
ZYDIS_ASSERT(info->details.modrm.mod != 3); ZYDIS_ASSERT(info->details.modrm.mod != 3);
ZYDIS_ASSERT((def->elementSize == 8) || (def->elementSize == 16) || ZYDIS_ASSERT(def->elementSize);
(def->elementSize == 32) || (def->elementSize == 64));
info->avx.elementSize = def->elementSize; // Element size
switch (def->elementSize)
{
case ZYDIS_IELEMENT_SIZE_8:
info->avx.elementSize = 8;
break;
case ZYDIS_IELEMENT_SIZE_16:
info->avx.elementSize = 16;
break;
case ZYDIS_IELEMENT_SIZE_32:
info->avx.elementSize = 32;
break;
case ZYDIS_IELEMENT_SIZE_64:
info->avx.elementSize = 64;
break;
default:
ZYDIS_UNREACHABLE;
}
// Compressed disp8 scale and broadcast-factor // Compressed disp8 scale and broadcast-factor
switch (info->avx.tupleType) switch (info->avx.tupleType)
@ -2243,6 +2282,18 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
} }
break; break;
case ZYDIS_TUPLETYPE_GSCAT:
switch (context->cache.W)
{
case 0:
ZYDIS_ASSERT(info->avx.elementSize == 32);
break;
case 1:
ZYDIS_ASSERT(info->avx.elementSize == 64);
break;
default:
ZYDIS_UNREACHABLE;
}
case ZYDIS_TUPLETYPE_T1S: case ZYDIS_TUPLETYPE_T1S:
info->avx.compressedDisp8Scale = info->avx.elementSize / 8; info->avx.compressedDisp8Scale = info->avx.elementSize / 8;
break; break;
@ -2259,20 +2310,10 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
} }
break; break;
case ZYDIS_TUPLETYPE_GSCAT: case ZYDIS_TUPLETYPE_T1_4X:
switch (context->cache.W) ZYDIS_ASSERT(info->avx.elementSize == 32);
{ ZYDIS_ASSERT(context->cache.W == 0);
case 0: info->avx.compressedDisp8Scale = 16;
ZYDIS_ASSERT(info->avx.elementSize == 32);
info->avx.compressedDisp8Scale = 4;
break;
case 1:
ZYDIS_ASSERT(info->avx.elementSize == 64);
info->avx.compressedDisp8Scale = 8;
break;
default:
ZYDIS_UNREACHABLE;
}
break; break;
case ZYDIS_TUPLETYPE_T2: case ZYDIS_TUPLETYPE_T2:
switch (context->cache.W) switch (context->cache.W)
@ -2382,11 +2423,6 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
} }
break; break;
case ZYDIS_TUPLETYPE_T1_4X:
ZYDIS_ASSERT(info->avx.elementSize == 32);
ZYDIS_ASSERT(context->cache.W == 0);
info->avx.compressedDisp8Scale = 16;
break;
default: default:
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
} }