[X86] AVX512: Add disassembler support for compressed displacement

There are two parts here.  First is to modify tablegen to adjust the encoding
type ENCODING_RM with the scaling factor.

The second is to use the new encoding types to compute the correct
displacement in the decoder.

Fixes <rdar://problem/17608489>

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213281 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Adam Nemet 2014-07-17 17:04:56 +00:00
parent f166cc13e2
commit 6ae2941874
6 changed files with 80 additions and 5 deletions

View File

@ -717,7 +717,7 @@ static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand,
return false;
case ENCODING_WRITEMASK:
return translateMaskRegister(mcInst, insn.writemask);
case ENCODING_RM:
CASE_ENCODING_RM:
return translateRM(mcInst, operand, insn, Dis);
case ENCODING_CB:
case ENCODING_CW:

View File

@ -1488,7 +1488,7 @@ static int fixupReg(struct InternalInstruction *insn,
if (!valid)
return -1;
break;
case ENCODING_RM:
CASE_ENCODING_RM:
if (insn->eaBase >= insn->eaRegBase) {
insn->eaBase = (EABase)fixupRMValue(insn,
(OperandType)op->type,
@ -1681,11 +1681,14 @@ static int readOperands(struct InternalInstruction* insn) {
case ENCODING_DI:
break;
case ENCODING_REG:
case ENCODING_RM:
CASE_ENCODING_RM:
if (readModRM(insn))
return -1;
if (fixupReg(insn, &Op))
return -1;
// Apply the AVX512 compressed displacement scaling factor.
if (Op.encoding != ENCODING_REG && insn->eaDisplacement == EA_DISP_8)
insn->displacement *= 1 << (Op.encoding - ENCODING_RM);
break;
case ENCODING_CB:
case ENCODING_CW:

View File

@ -325,11 +325,26 @@ enum ModRMDecisionType {
};
#undef ENUM_ENTRY
#define CASE_ENCODING_RM \
case ENCODING_RM: \
case ENCODING_RM_CD2: \
case ENCODING_RM_CD4: \
case ENCODING_RM_CD8: \
case ENCODING_RM_CD16: \
case ENCODING_RM_CD32: \
case ENCODING_RM_CD64
// Physical encodings of instruction operands.
#define ENCODINGS \
ENUM_ENTRY(ENCODING_NONE, "") \
ENUM_ENTRY(ENCODING_REG, "Register operand in ModR/M byte.") \
ENUM_ENTRY(ENCODING_RM, "R/M operand in ModR/M byte.") \
ENUM_ENTRY(ENCODING_RM_CD2, "R/M operand with CDisp scaling of 2") \
ENUM_ENTRY(ENCODING_RM_CD4, "R/M operand with CDisp scaling of 4") \
ENUM_ENTRY(ENCODING_RM_CD8, "R/M operand with CDisp scaling of 8") \
ENUM_ENTRY(ENCODING_RM_CD16,"R/M operand with CDisp scaling of 16") \
ENUM_ENTRY(ENCODING_RM_CD32,"R/M operand with CDisp scaling of 32") \
ENUM_ENTRY(ENCODING_RM_CD64,"R/M operand with CDisp scaling of 64") \
ENUM_ENTRY(ENCODING_VVVV, "Register operand in VEX.vvvv byte.") \
ENUM_ENTRY(ENCODING_WRITEMASK, "Register operand in EVEX.aaa byte.") \
ENUM_ENTRY(ENCODING_CB, "1-byte code offset (possible new CS value)") \

View File

@ -63,3 +63,42 @@
# CHECK: kmovw %k5, %k1
0xc5 0xf8 0x90 0xcd
#####################################################
# COMPRESSED DISPLACEMENT #
#####################################################
# TupleType = FVM
# CHECK: vmovdqu32 %zmm0, -448(%rcx)
0x62 0xf1 0x7e 0x48 0x7f 0x41 0xf9
# TupleType = T1S, 64-bit eltsize
# CHECK: vaddsd 256(%rdx), %xmm0, %xmm16
0x62 0xe1 0xff 0x08 0x58 0x42 0x20
# TupleType = T1S, 32-bit eltsize
# CHECK: vaddss 256(%rdx), %xmm0, %xmm16
0x62 0xe1 0x7e 0x08 0x58 0x42 0x40
# TupleType = FV
# CHECK: vaddpd 256(%rdx), %zmm0, %zmm16
0x62 0xe1 0xfd 0x48 0x58 0x42 0x04
# TupleType = FV, broadcast, 64-bit eltsize
# CHECK: vaddpd 256(%rdx){1to8}, %zmm0, %zmm16
0x62 0xe1 0xfd 0x58 0x58 0x42 0x20
# TupleType = FV, broadcast, 32-bit eltsize
# CHECK: vaddps 256(%rdx){1to16}, %zmm0, %zmm16
0x62 0xe1 0x7c 0x58 0x58 0x42 0x40
# TupleType = T4
# CHECK: vbroadcasti32x4 256(%rdx), %zmm16
0x62 0xe2 0x7d 0x48 0x5a 0x42 0x10
# Cases where we can't use cdisp8
# CHECK: vaddss 255(%rdx), %xmm0, %xmm16
0x62 0xe1 0x7e 0x08 0x58 0x82 0xff 0x00 0x00 0x00
# CHECK: vaddss 1024(%rdx), %xmm0, %xmm16
0x62 0xe1 0x7e 0x08 0x58 0x82 0x00 0x04 0x00 0x00

View File

@ -205,6 +205,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
HasEVEX_B = Rec->getValueAsBit("hasEVEX_B");
IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
CD8_Scale = byteFromRec(Rec, "CD8_Scale");
Name = Rec->getName();
AsmString = Rec->getValueAsString("AsmString");
@ -441,6 +442,16 @@ InstructionContext RecognizableInstr::insnContext() const {
return insnContext;
}
void RecognizableInstr::adjustOperandEncoding(OperandEncoding &encoding) {
// The scaling factor for AVX512 compressed displacement encoding is an
// instruction attribute. Adjust the ModRM encoding type to include the
// scale for compressed displacement.
if (encoding != ENCODING_RM || CD8_Scale == 0)
return;
encoding = (OperandEncoding)(encoding + Log2_32(CD8_Scale));
assert(encoding <= ENCODING_RM_CD64 && "Invalid CDisp scaling");
}
void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
unsigned &physicalOperandIndex,
unsigned &numPhysicalOperands,
@ -464,8 +475,10 @@ void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
const std::string &typeName = (*Operands)[operandIndex].Rec->getName();
Spec->operands[operandIndex].encoding = encodingFromString(typeName,
OpSize);
OperandEncoding encoding = encodingFromString(typeName, OpSize);
// Adjust the encoding type for an operand based on the instruction.
adjustOperandEncoding(encoding);
Spec->operands[operandIndex].encoding = encoding;
Spec->operands[operandIndex].type = typeFromString(typeName,
HasREX_WPrefix, OpSize);

View File

@ -78,6 +78,8 @@ private:
bool IsCodeGenOnly;
/// The ForceDisassemble field from the record
bool ForceDisassemble;
// The CD8_Scale field from the record
uint8_t CD8_Scale;
// Whether the instruction has the predicate "In64BitMode"
bool Is64Bit;
// Whether the instruction has the predicate "In32BitMode"
@ -153,6 +155,9 @@ private:
static OperandEncoding writemaskRegisterEncodingFromString(const std::string &s,
uint8_t OpSize);
/// \brief Adjust the encoding type for an operand based on the instruction.
void adjustOperandEncoding(OperandEncoding &encoding);
/// handleOperand - Converts a single operand from the LLVM table format to
/// the emitted table format, handling any duplicate operands it encounters
/// and then one non-duplicate.