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:
if (!valid)
return -1;
break;
- case ENCODING_RM:
+ CASE_ENCODING_RM:
if (insn->eaBase >= insn->eaRegBase) {
insn->eaBase = (EABase)fixupRMValue(insn,
(OperandType)op->type,
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:
};
#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)") \
# 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
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");
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,
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);
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"
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.