forked from OSchip/llvm-project
AVX-512: decoder for AVX-512, made by Alexey Bader.
llvm-svn: 198013
This commit is contained in:
parent
5746c07629
commit
371e363833
|
@ -2067,6 +2067,7 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
|
|||
return true;
|
||||
}
|
||||
}
|
||||
// TODO: add parsing of broadcasts {1to8}, {1to16}
|
||||
// Parse "zeroing non-masked" semantic {z}
|
||||
if (getLexer().is(AsmToken::LCurly)) {
|
||||
Operands.push_back(X86Operand::CreateToken("{z}", consumeToken()));
|
||||
|
|
|
@ -418,13 +418,22 @@ static bool translateRMMemory(MCInst &mcInst, InternalInstruction &insn,
|
|||
bool IndexIs256 = (Opcode == X86::VGATHERQPDYrm ||
|
||||
Opcode == X86::VGATHERDPSYrm ||
|
||||
Opcode == X86::VGATHERQPSYrm ||
|
||||
Opcode == X86::VGATHERDPDZrm ||
|
||||
Opcode == X86::VPGATHERDQZrm ||
|
||||
Opcode == X86::VPGATHERQQYrm ||
|
||||
Opcode == X86::VPGATHERDDYrm ||
|
||||
Opcode == X86::VPGATHERQDYrm);
|
||||
if (IndexIs128 || IndexIs256) {
|
||||
bool IndexIs512 = (Opcode == X86::VGATHERQPDZrm ||
|
||||
Opcode == X86::VGATHERDPSZrm ||
|
||||
Opcode == X86::VGATHERQPSZrm ||
|
||||
Opcode == X86::VPGATHERQQZrm ||
|
||||
Opcode == X86::VPGATHERDDZrm ||
|
||||
Opcode == X86::VPGATHERQDZrm);
|
||||
if (IndexIs128 || IndexIs256 || IndexIs512) {
|
||||
unsigned IndexOffset = insn.sibIndex -
|
||||
(insn.addressSize == 8 ? SIB_INDEX_RAX:SIB_INDEX_EAX);
|
||||
SIBIndex IndexBase = IndexIs256 ? SIB_INDEX_YMM0 : SIB_INDEX_XMM0;
|
||||
SIBIndex IndexBase = IndexIs512 ? SIB_INDEX_ZMM0 :
|
||||
IndexIs256 ? SIB_INDEX_YMM0 : SIB_INDEX_XMM0;
|
||||
insn.sibIndex = (SIBIndex)(IndexBase +
|
||||
(insn.sibIndex == SIB_INDEX_NONE ? 4 : IndexOffset));
|
||||
}
|
||||
|
@ -565,6 +574,9 @@ static bool translateRM(MCInst &mcInst, const OperandSpecifier &operand,
|
|||
case TYPE_XMM128:
|
||||
case TYPE_XMM256:
|
||||
case TYPE_XMM512:
|
||||
case TYPE_VK1:
|
||||
case TYPE_VK8:
|
||||
case TYPE_VK16:
|
||||
case TYPE_DEBUGREG:
|
||||
case TYPE_CONTROLREG:
|
||||
return translateRMRegister(mcInst, insn);
|
||||
|
@ -596,7 +608,7 @@ static bool translateRM(MCInst &mcInst, const OperandSpecifier &operand,
|
|||
///
|
||||
/// @param mcInst - The MCInst to append to.
|
||||
/// @param stackPos - The stack position to translate.
|
||||
/// @return - 0 on success; nonzero otherwise.
|
||||
/// @return - false on success; true otherwise.
|
||||
static bool translateFPRegister(MCInst &mcInst,
|
||||
uint8_t stackPos) {
|
||||
if (stackPos >= 8) {
|
||||
|
@ -609,6 +621,23 @@ static bool translateFPRegister(MCInst &mcInst,
|
|||
return false;
|
||||
}
|
||||
|
||||
/// translateMaskRegister - Translates a 3-bit mask register number to
|
||||
/// LLVM form, and appends it to an MCInst.
|
||||
///
|
||||
/// @param mcInst - The MCInst to append to.
|
||||
/// @param maskRegNum - Number of mask register from 0 to 7.
|
||||
/// @return - false on success; true otherwise.
|
||||
static bool translateMaskRegister(MCInst &mcInst,
|
||||
uint8_t maskRegNum) {
|
||||
if (maskRegNum >= 8) {
|
||||
debug("Invalid mask register number");
|
||||
return true;
|
||||
}
|
||||
|
||||
mcInst.addOperand(MCOperand::CreateReg(X86::K0 + maskRegNum));
|
||||
return false;
|
||||
}
|
||||
|
||||
/// translateOperand - Translates an operand stored in an internal instruction
|
||||
/// to LLVM's format and appends it to an MCInst.
|
||||
///
|
||||
|
@ -626,6 +655,8 @@ static bool translateOperand(MCInst &mcInst, const OperandSpecifier &operand,
|
|||
case ENCODING_REG:
|
||||
translateRegister(mcInst, insn.reg);
|
||||
return false;
|
||||
case ENCODING_WRITEMASK:
|
||||
return translateMaskRegister(mcInst, insn.writemask);
|
||||
case ENCODING_RM:
|
||||
return translateRM(mcInst, operand, insn, Dis);
|
||||
case ENCODING_CB:
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
* @return - The InstructionContext to use when looking up an
|
||||
* an instruction with these attributes.
|
||||
*/
|
||||
static InstructionContext contextForAttrs(uint8_t attrMask) {
|
||||
static InstructionContext contextForAttrs(uint16_t attrMask) {
|
||||
return CONTEXTS_SYM[attrMask];
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ static InstructionContext contextForAttrs(uint8_t attrMask) {
|
|||
*/
|
||||
static int modRMRequired(OpcodeType type,
|
||||
InstructionContext insnContext,
|
||||
uint8_t opcode) {
|
||||
uint16_t opcode) {
|
||||
const struct ContextDecision* decision = 0;
|
||||
|
||||
switch (type) {
|
||||
|
@ -444,9 +444,60 @@ static int readPrefixes(struct InternalInstruction* insn) {
|
|||
dbgprintf(insn, "Found prefix 0x%hhx", byte);
|
||||
}
|
||||
|
||||
insn->vexXopType = TYPE_NO_VEX_XOP;
|
||||
insn->vectorExtensionType = TYPE_NO_VEX_XOP;
|
||||
|
||||
if (byte == 0xc4) {
|
||||
if (byte == 0x62) {
|
||||
uint8_t byte1, byte2;
|
||||
|
||||
if (consumeByte(insn, &byte1)) {
|
||||
dbgprintf(insn, "Couldn't read second byte of EVEX prefix");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lookAtByte(insn, &byte2)) {
|
||||
dbgprintf(insn, "Couldn't read third byte of EVEX prefix");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0) &&
|
||||
((~byte1 & 0xc) == 0xc) && ((byte2 & 0x4) == 0x4)) {
|
||||
insn->vectorExtensionType = TYPE_EVEX;
|
||||
}
|
||||
else {
|
||||
unconsumeByte(insn); /* unconsume byte1 */
|
||||
unconsumeByte(insn); /* unconsume byte */
|
||||
insn->necessaryPrefixLocation = insn->readerCursor - 2;
|
||||
}
|
||||
|
||||
if (insn->vectorExtensionType == TYPE_EVEX) {
|
||||
insn->vectorExtensionPrefix[0] = byte;
|
||||
insn->vectorExtensionPrefix[1] = byte1;
|
||||
if (consumeByte(insn, &insn->vectorExtensionPrefix[2])) {
|
||||
dbgprintf(insn, "Couldn't read third byte of EVEX prefix");
|
||||
return -1;
|
||||
}
|
||||
if (consumeByte(insn, &insn->vectorExtensionPrefix[3])) {
|
||||
dbgprintf(insn, "Couldn't read fourth byte of EVEX prefix");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We simulate the REX prefix for simplicity's sake */
|
||||
if (insn->mode == MODE_64BIT) {
|
||||
insn->rexPrefix = 0x40
|
||||
| (wFromEVEX3of4(insn->vectorExtensionPrefix[2]) << 3)
|
||||
| (rFromEVEX2of4(insn->vectorExtensionPrefix[1]) << 2)
|
||||
| (xFromEVEX2of4(insn->vectorExtensionPrefix[1]) << 1)
|
||||
| (bFromEVEX2of4(insn->vectorExtensionPrefix[1]) << 0);
|
||||
}
|
||||
|
||||
hasOpSize = (VEX_PREFIX_66 == ppFromEVEX3of4(insn->vectorExtensionPrefix[2]));
|
||||
|
||||
dbgprintf(insn, "Found EVEX prefix 0x%hhx 0x%hhx 0x%hhx 0x%hhx",
|
||||
insn->vectorExtensionPrefix[0], insn->vectorExtensionPrefix[1],
|
||||
insn->vectorExtensionPrefix[2], insn->vectorExtensionPrefix[3]);
|
||||
}
|
||||
}
|
||||
else if (byte == 0xc4) {
|
||||
uint8_t byte1;
|
||||
|
||||
if (lookAtByte(insn, &byte1)) {
|
||||
|
@ -455,7 +506,7 @@ static int readPrefixes(struct InternalInstruction* insn) {
|
|||
}
|
||||
|
||||
if (insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0) {
|
||||
insn->vexXopType = TYPE_VEX_3B;
|
||||
insn->vectorExtensionType = TYPE_VEX_3B;
|
||||
insn->necessaryPrefixLocation = insn->readerCursor - 1;
|
||||
}
|
||||
else {
|
||||
|
@ -463,22 +514,22 @@ static int readPrefixes(struct InternalInstruction* insn) {
|
|||
insn->necessaryPrefixLocation = insn->readerCursor - 1;
|
||||
}
|
||||
|
||||
if (insn->vexXopType == TYPE_VEX_3B) {
|
||||
insn->vexXopPrefix[0] = byte;
|
||||
consumeByte(insn, &insn->vexXopPrefix[1]);
|
||||
consumeByte(insn, &insn->vexXopPrefix[2]);
|
||||
if (insn->vectorExtensionType == TYPE_VEX_3B) {
|
||||
insn->vectorExtensionPrefix[0] = byte;
|
||||
consumeByte(insn, &insn->vectorExtensionPrefix[1]);
|
||||
consumeByte(insn, &insn->vectorExtensionPrefix[2]);
|
||||
|
||||
/* We simulate the REX prefix for simplicity's sake */
|
||||
|
||||
if (insn->mode == MODE_64BIT) {
|
||||
insn->rexPrefix = 0x40
|
||||
| (wFromVEX3of3(insn->vexXopPrefix[2]) << 3)
|
||||
| (rFromVEX2of3(insn->vexXopPrefix[1]) << 2)
|
||||
| (xFromVEX2of3(insn->vexXopPrefix[1]) << 1)
|
||||
| (bFromVEX2of3(insn->vexXopPrefix[1]) << 0);
|
||||
| (wFromVEX3of3(insn->vectorExtensionPrefix[2]) << 3)
|
||||
| (rFromVEX2of3(insn->vectorExtensionPrefix[1]) << 2)
|
||||
| (xFromVEX2of3(insn->vectorExtensionPrefix[1]) << 1)
|
||||
| (bFromVEX2of3(insn->vectorExtensionPrefix[1]) << 0);
|
||||
}
|
||||
|
||||
switch (ppFromVEX3of3(insn->vexXopPrefix[2]))
|
||||
switch (ppFromVEX3of3(insn->vectorExtensionPrefix[2]))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
@ -488,8 +539,8 @@ static int readPrefixes(struct InternalInstruction* insn) {
|
|||
}
|
||||
|
||||
dbgprintf(insn, "Found VEX prefix 0x%hhx 0x%hhx 0x%hhx",
|
||||
insn->vexXopPrefix[0], insn->vexXopPrefix[1],
|
||||
insn->vexXopPrefix[2]);
|
||||
insn->vectorExtensionPrefix[0], insn->vectorExtensionPrefix[1],
|
||||
insn->vectorExtensionPrefix[2]);
|
||||
}
|
||||
}
|
||||
else if (byte == 0xc5) {
|
||||
|
@ -501,22 +552,22 @@ static int readPrefixes(struct InternalInstruction* insn) {
|
|||
}
|
||||
|
||||
if (insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0) {
|
||||
insn->vexXopType = TYPE_VEX_2B;
|
||||
insn->vectorExtensionType = TYPE_VEX_2B;
|
||||
}
|
||||
else {
|
||||
unconsumeByte(insn);
|
||||
}
|
||||
|
||||
if (insn->vexXopType == TYPE_VEX_2B) {
|
||||
insn->vexXopPrefix[0] = byte;
|
||||
consumeByte(insn, &insn->vexXopPrefix[1]);
|
||||
if (insn->vectorExtensionType == TYPE_VEX_2B) {
|
||||
insn->vectorExtensionPrefix[0] = byte;
|
||||
consumeByte(insn, &insn->vectorExtensionPrefix[1]);
|
||||
|
||||
if (insn->mode == MODE_64BIT) {
|
||||
insn->rexPrefix = 0x40
|
||||
| (rFromVEX2of2(insn->vexXopPrefix[1]) << 2);
|
||||
| (rFromVEX2of2(insn->vectorExtensionPrefix[1]) << 2);
|
||||
}
|
||||
|
||||
switch (ppFromVEX2of2(insn->vexXopPrefix[1]))
|
||||
switch (ppFromVEX2of2(insn->vectorExtensionPrefix[1]))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
@ -525,7 +576,9 @@ static int readPrefixes(struct InternalInstruction* insn) {
|
|||
break;
|
||||
}
|
||||
|
||||
dbgprintf(insn, "Found VEX prefix 0x%hhx 0x%hhx", insn->vexXopPrefix[0], insn->vexXopPrefix[1]);
|
||||
dbgprintf(insn, "Found VEX prefix 0x%hhx 0x%hhx",
|
||||
insn->vectorExtensionPrefix[0],
|
||||
insn->vectorExtensionPrefix[1]);
|
||||
}
|
||||
}
|
||||
else if (byte == 0x8f) {
|
||||
|
@ -537,7 +590,7 @@ static int readPrefixes(struct InternalInstruction* insn) {
|
|||
}
|
||||
|
||||
if ((byte1 & 0x38) != 0x0) { /* 0 in these 3 bits is a POP instruction. */
|
||||
insn->vexXopType = TYPE_XOP;
|
||||
insn->vectorExtensionType = TYPE_XOP;
|
||||
insn->necessaryPrefixLocation = insn->readerCursor - 1;
|
||||
}
|
||||
else {
|
||||
|
@ -545,22 +598,22 @@ static int readPrefixes(struct InternalInstruction* insn) {
|
|||
insn->necessaryPrefixLocation = insn->readerCursor - 1;
|
||||
}
|
||||
|
||||
if (insn->vexXopType == TYPE_XOP) {
|
||||
insn->vexXopPrefix[0] = byte;
|
||||
consumeByte(insn, &insn->vexXopPrefix[1]);
|
||||
consumeByte(insn, &insn->vexXopPrefix[2]);
|
||||
if (insn->vectorExtensionType == TYPE_XOP) {
|
||||
insn->vectorExtensionPrefix[0] = byte;
|
||||
consumeByte(insn, &insn->vectorExtensionPrefix[1]);
|
||||
consumeByte(insn, &insn->vectorExtensionPrefix[2]);
|
||||
|
||||
/* We simulate the REX prefix for simplicity's sake */
|
||||
|
||||
if (insn->mode == MODE_64BIT) {
|
||||
insn->rexPrefix = 0x40
|
||||
| (wFromXOP3of3(insn->vexXopPrefix[2]) << 3)
|
||||
| (rFromXOP2of3(insn->vexXopPrefix[1]) << 2)
|
||||
| (xFromXOP2of3(insn->vexXopPrefix[1]) << 1)
|
||||
| (bFromXOP2of3(insn->vexXopPrefix[1]) << 0);
|
||||
| (wFromXOP3of3(insn->vectorExtensionPrefix[2]) << 3)
|
||||
| (rFromXOP2of3(insn->vectorExtensionPrefix[1]) << 2)
|
||||
| (xFromXOP2of3(insn->vectorExtensionPrefix[1]) << 1)
|
||||
| (bFromXOP2of3(insn->vectorExtensionPrefix[1]) << 0);
|
||||
}
|
||||
|
||||
switch (ppFromXOP3of3(insn->vexXopPrefix[2]))
|
||||
switch (ppFromXOP3of3(insn->vectorExtensionPrefix[2]))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
@ -570,8 +623,8 @@ static int readPrefixes(struct InternalInstruction* insn) {
|
|||
}
|
||||
|
||||
dbgprintf(insn, "Found XOP prefix 0x%hhx 0x%hhx 0x%hhx",
|
||||
insn->vexXopPrefix[0], insn->vexXopPrefix[1],
|
||||
insn->vexXopPrefix[2]);
|
||||
insn->vectorExtensionPrefix[0], insn->vectorExtensionPrefix[1],
|
||||
insn->vectorExtensionPrefix[2]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -646,13 +699,12 @@ static int readOpcode(struct InternalInstruction* insn) {
|
|||
|
||||
insn->opcodeType = ONEBYTE;
|
||||
|
||||
if (insn->vexXopType == TYPE_VEX_3B)
|
||||
{
|
||||
switch (mmmmmFromVEX2of3(insn->vexXopPrefix[1]))
|
||||
if (insn->vectorExtensionType == TYPE_EVEX)
|
||||
{
|
||||
switch (mmFromEVEX2of4(insn->vectorExtensionPrefix[1])) {
|
||||
default:
|
||||
dbgprintf(insn, "Unhandled m-mmmm field for instruction (0x%hhx)",
|
||||
mmmmmFromVEX2of3(insn->vexXopPrefix[1]));
|
||||
dbgprintf(insn, "Unhandled mm field for instruction (0x%hhx)",
|
||||
mmFromEVEX2of4(insn->vectorExtensionPrefix[1]));
|
||||
return -1;
|
||||
case VEX_LOB_0F:
|
||||
insn->opcodeType = TWOBYTE;
|
||||
|
@ -665,18 +717,32 @@ static int readOpcode(struct InternalInstruction* insn) {
|
|||
return consumeByte(insn, &insn->opcode);
|
||||
}
|
||||
}
|
||||
else if (insn->vexXopType == TYPE_VEX_2B)
|
||||
{
|
||||
else if (insn->vectorExtensionType == TYPE_VEX_3B) {
|
||||
switch (mmmmmFromVEX2of3(insn->vectorExtensionPrefix[1])) {
|
||||
default:
|
||||
dbgprintf(insn, "Unhandled m-mmmm field for instruction (0x%hhx)",
|
||||
mmmmmFromVEX2of3(insn->vectorExtensionPrefix[1]));
|
||||
return -1;
|
||||
case VEX_LOB_0F:
|
||||
insn->opcodeType = TWOBYTE;
|
||||
return consumeByte(insn, &insn->opcode);
|
||||
case VEX_LOB_0F38:
|
||||
insn->opcodeType = THREEBYTE_38;
|
||||
return consumeByte(insn, &insn->opcode);
|
||||
case VEX_LOB_0F3A:
|
||||
insn->opcodeType = THREEBYTE_3A;
|
||||
return consumeByte(insn, &insn->opcode);
|
||||
}
|
||||
}
|
||||
else if (insn->vectorExtensionType == TYPE_VEX_2B) {
|
||||
insn->opcodeType = TWOBYTE;
|
||||
return consumeByte(insn, &insn->opcode);
|
||||
}
|
||||
else if (insn->vexXopType == TYPE_XOP)
|
||||
{
|
||||
switch (mmmmmFromXOP2of3(insn->vexXopPrefix[1]))
|
||||
{
|
||||
else if (insn->vectorExtensionType == TYPE_XOP) {
|
||||
switch (mmmmmFromXOP2of3(insn->vectorExtensionPrefix[1])) {
|
||||
default:
|
||||
dbgprintf(insn, "Unhandled m-mmmm field for instruction (0x%hhx)",
|
||||
mmmmmFromVEX2of3(insn->vexXopPrefix[1]));
|
||||
mmmmmFromVEX2of3(insn->vectorExtensionPrefix[1]));
|
||||
return -1;
|
||||
case XOP_MAP_SELECT_8:
|
||||
insn->opcodeType = XOP8_MAP;
|
||||
|
@ -760,10 +826,10 @@ static int readModRM(struct InternalInstruction* insn);
|
|||
*/
|
||||
static int getIDWithAttrMask(uint16_t* instructionID,
|
||||
struct InternalInstruction* insn,
|
||||
uint8_t attrMask) {
|
||||
uint16_t attrMask) {
|
||||
BOOL hasModRMExtension;
|
||||
|
||||
uint8_t instructionClass;
|
||||
uint16_t instructionClass;
|
||||
|
||||
instructionClass = contextForAttrs(attrMask);
|
||||
|
||||
|
@ -826,7 +892,7 @@ static BOOL is16BitEquivalent(const char* orig, const char* equiv) {
|
|||
* nonzero otherwise.
|
||||
*/
|
||||
static int getID(struct InternalInstruction* insn, const void *miiArg) {
|
||||
uint8_t attrMask;
|
||||
uint16_t attrMask;
|
||||
uint16_t instructionID;
|
||||
|
||||
dbgprintf(insn, "getID()");
|
||||
|
@ -836,11 +902,11 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
|
|||
if (insn->mode == MODE_64BIT)
|
||||
attrMask |= ATTR_64BIT;
|
||||
|
||||
if (insn->vexXopType != TYPE_NO_VEX_XOP) {
|
||||
attrMask |= ATTR_VEX;
|
||||
if (insn->vectorExtensionType != TYPE_NO_VEX_XOP) {
|
||||
attrMask |= (insn->vectorExtensionType == TYPE_EVEX) ? ATTR_EVEX : ATTR_VEX;
|
||||
|
||||
if (insn->vexXopType == TYPE_VEX_3B) {
|
||||
switch (ppFromVEX3of3(insn->vexXopPrefix[2])) {
|
||||
if (insn->vectorExtensionType == TYPE_EVEX) {
|
||||
switch (ppFromEVEX3of4(insn->vectorExtensionPrefix[2])) {
|
||||
case VEX_PREFIX_66:
|
||||
attrMask |= ATTR_OPSIZE;
|
||||
break;
|
||||
|
@ -852,11 +918,35 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (lFromVEX3of3(insn->vexXopPrefix[2]))
|
||||
if (zFromEVEX4of4(insn->vectorExtensionPrefix[3]))
|
||||
attrMask |= ATTR_EVEXKZ;
|
||||
if (bFromEVEX4of4(insn->vectorExtensionPrefix[3]))
|
||||
attrMask |= ATTR_EVEXB;
|
||||
if (aaaFromEVEX4of4(insn->vectorExtensionPrefix[3]))
|
||||
attrMask |= ATTR_EVEXK;
|
||||
if (lFromEVEX4of4(insn->vectorExtensionPrefix[3]))
|
||||
attrMask |= ATTR_EVEXL;
|
||||
if (l2FromEVEX4of4(insn->vectorExtensionPrefix[3]))
|
||||
attrMask |= ATTR_EVEXL2;
|
||||
}
|
||||
else if (insn->vectorExtensionType == TYPE_VEX_3B) {
|
||||
switch (ppFromVEX3of3(insn->vectorExtensionPrefix[2])) {
|
||||
case VEX_PREFIX_66:
|
||||
attrMask |= ATTR_OPSIZE;
|
||||
break;
|
||||
case VEX_PREFIX_F3:
|
||||
attrMask |= ATTR_XS;
|
||||
break;
|
||||
case VEX_PREFIX_F2:
|
||||
attrMask |= ATTR_XD;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lFromVEX3of3(insn->vectorExtensionPrefix[2]))
|
||||
attrMask |= ATTR_VEXL;
|
||||
}
|
||||
else if (insn->vexXopType == TYPE_VEX_2B) {
|
||||
switch (ppFromVEX2of2(insn->vexXopPrefix[1])) {
|
||||
else if (insn->vectorExtensionType == TYPE_VEX_2B) {
|
||||
switch (ppFromVEX2of2(insn->vectorExtensionPrefix[1])) {
|
||||
case VEX_PREFIX_66:
|
||||
attrMask |= ATTR_OPSIZE;
|
||||
break;
|
||||
|
@ -868,11 +958,11 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (lFromVEX2of2(insn->vexXopPrefix[1]))
|
||||
if (lFromVEX2of2(insn->vectorExtensionPrefix[1]))
|
||||
attrMask |= ATTR_VEXL;
|
||||
}
|
||||
else if (insn->vexXopType == TYPE_XOP) {
|
||||
switch (ppFromXOP3of3(insn->vexXopPrefix[2])) {
|
||||
else if (insn->vectorExtensionType == TYPE_XOP) {
|
||||
switch (ppFromXOP3of3(insn->vectorExtensionPrefix[2])) {
|
||||
case VEX_PREFIX_66:
|
||||
attrMask |= ATTR_OPSIZE;
|
||||
break;
|
||||
|
@ -884,7 +974,7 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (lFromXOP3of3(insn->vexXopPrefix[2]))
|
||||
if (lFromXOP3of3(insn->vectorExtensionPrefix[2]))
|
||||
attrMask |= ATTR_VEXL;
|
||||
}
|
||||
else {
|
||||
|
@ -1033,6 +1123,8 @@ static int readSIB(struct InternalInstruction* insn) {
|
|||
return -1;
|
||||
|
||||
index = indexFromSIB(insn->sib) | (xFromREX(insn->rexPrefix) << 3);
|
||||
if (insn->vectorExtensionType == TYPE_EVEX)
|
||||
index |= v2FromEVEX4of4(insn->vectorExtensionPrefix[3]) << 4;
|
||||
|
||||
switch (index) {
|
||||
case 0x4:
|
||||
|
@ -1183,6 +1275,10 @@ static int readModRM(struct InternalInstruction* insn) {
|
|||
|
||||
reg |= rFromREX(insn->rexPrefix) << 3;
|
||||
rm |= bFromREX(insn->rexPrefix) << 3;
|
||||
if (insn->vectorExtensionType == TYPE_EVEX) {
|
||||
reg |= r2FromEVEX2of4(insn->vectorExtensionPrefix[1]) << 4;
|
||||
rm |= xFromEVEX2of4(insn->vectorExtensionPrefix[1]) << 4;
|
||||
}
|
||||
|
||||
insn->reg = (Reg)(insn->regBase + reg);
|
||||
|
||||
|
@ -1229,6 +1325,7 @@ static int readModRM(struct InternalInstruction* insn) {
|
|||
case 0x0:
|
||||
insn->eaDisplacement = EA_DISP_NONE; /* readSIB may override this */
|
||||
switch (rm) {
|
||||
case 0x14:
|
||||
case 0x4:
|
||||
case 0xc: /* in case REXW.b is set */
|
||||
insn->eaBase = (insn->addressSize == 4 ?
|
||||
|
@ -1252,6 +1349,7 @@ static int readModRM(struct InternalInstruction* insn) {
|
|||
case 0x2:
|
||||
insn->eaDisplacement = (mod == 0x1 ? EA_DISP_8 : EA_DISP_32);
|
||||
switch (rm) {
|
||||
case 0x14:
|
||||
case 0x4:
|
||||
case 0xc: /* in case REXW.b is set */
|
||||
insn->eaBase = EA_BASE_sib;
|
||||
|
@ -1312,6 +1410,10 @@ static int readModRM(struct InternalInstruction* insn) {
|
|||
case TYPE_XMM32: \
|
||||
case TYPE_XMM: \
|
||||
return prefix##_XMM0 + index; \
|
||||
case TYPE_VK1: \
|
||||
case TYPE_VK8: \
|
||||
case TYPE_VK16: \
|
||||
return prefix##_K0 + index; \
|
||||
case TYPE_MM64: \
|
||||
case TYPE_MM32: \
|
||||
case TYPE_MM: \
|
||||
|
@ -1550,12 +1652,14 @@ static int readImmediate(struct InternalInstruction* insn, uint8_t size) {
|
|||
static int readVVVV(struct InternalInstruction* insn) {
|
||||
dbgprintf(insn, "readVVVV()");
|
||||
|
||||
if (insn->vexXopType == TYPE_VEX_3B)
|
||||
insn->vvvv = vvvvFromVEX3of3(insn->vexXopPrefix[2]);
|
||||
else if (insn->vexXopType == TYPE_VEX_2B)
|
||||
insn->vvvv = vvvvFromVEX2of2(insn->vexXopPrefix[1]);
|
||||
else if (insn->vexXopType == TYPE_XOP)
|
||||
insn->vvvv = vvvvFromXOP3of3(insn->vexXopPrefix[2]);
|
||||
if (insn->vectorExtensionType == TYPE_EVEX)
|
||||
insn->vvvv = vvvvFromEVEX3of4(insn->vectorExtensionPrefix[2]);
|
||||
else if (insn->vectorExtensionType == TYPE_VEX_3B)
|
||||
insn->vvvv = vvvvFromVEX3of3(insn->vectorExtensionPrefix[2]);
|
||||
else if (insn->vectorExtensionType == TYPE_VEX_2B)
|
||||
insn->vvvv = vvvvFromVEX2of2(insn->vectorExtensionPrefix[1]);
|
||||
else if (insn->vectorExtensionType == TYPE_XOP)
|
||||
insn->vvvv = vvvvFromXOP3of3(insn->vectorExtensionPrefix[2]);
|
||||
else
|
||||
return -1;
|
||||
|
||||
|
@ -1565,6 +1669,23 @@ static int readVVVV(struct InternalInstruction* insn) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* readMaskRegister - Reads an mask register from the opcode field of an
|
||||
* instruction.
|
||||
*
|
||||
* @param insn - The instruction whose opcode field is to be read.
|
||||
* @return - 0 on success; nonzero otherwise.
|
||||
*/
|
||||
static int readMaskRegister(struct InternalInstruction* insn) {
|
||||
dbgprintf(insn, "readMaskRegister()");
|
||||
|
||||
if (insn->vectorExtensionType != TYPE_EVEX)
|
||||
return -1;
|
||||
|
||||
insn->writemask = aaaFromEVEX4of4(insn->vectorExtensionPrefix[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* readOperands - Consults the specifier for an instruction and consumes all
|
||||
* operands for that instruction, interpreting them as it goes.
|
||||
|
@ -1675,6 +1796,10 @@ static int readOperands(struct InternalInstruction* insn) {
|
|||
if (fixupReg(insn, &x86OperandSets[insn->spec->operands][index]))
|
||||
return -1;
|
||||
break;
|
||||
case ENCODING_WRITEMASK:
|
||||
if (readMaskRegister(insn))
|
||||
return -1;
|
||||
break;
|
||||
case ENCODING_DUP:
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -45,6 +45,21 @@ extern "C" {
|
|||
#define xFromREX(rex) (((rex) & 0x2) >> 1)
|
||||
#define bFromREX(rex) ((rex) & 0x1)
|
||||
|
||||
#define rFromEVEX2of4(evex) (((~(evex)) & 0x80) >> 7)
|
||||
#define xFromEVEX2of4(evex) (((~(evex)) & 0x40) >> 6)
|
||||
#define bFromEVEX2of4(evex) (((~(evex)) & 0x20) >> 5)
|
||||
#define r2FromEVEX2of4(evex) (((~(evex)) & 0x10) >> 4)
|
||||
#define mmFromEVEX2of4(evex) ((evex) & 0x3)
|
||||
#define wFromEVEX3of4(evex) (((evex) & 0x80) >> 7)
|
||||
#define vvvvFromEVEX3of4(evex) (((~(evex)) & 0x78) >> 3)
|
||||
#define ppFromEVEX3of4(evex) ((evex) & 0x3)
|
||||
#define zFromEVEX4of4(evex) (((evex) & 0x80) >> 7)
|
||||
#define l2FromEVEX4of4(evex) (((evex) & 0x40) >> 6)
|
||||
#define lFromEVEX4of4(evex) (((evex) & 0x20) >> 5)
|
||||
#define bFromEVEX4of4(evex) (((evex) & 0x10) >> 4)
|
||||
#define v2FromEVEX4of4(evex) (((~evex) & 0x8) >> 3)
|
||||
#define aaaFromEVEX4of4(evex) ((evex) & 0x7)
|
||||
|
||||
#define rFromVEX2of3(vex) (((~(vex)) & 0x80) >> 7)
|
||||
#define xFromVEX2of3(vex) (((~(vex)) & 0x40) >> 6)
|
||||
#define bFromVEX2of3(vex) (((~(vex)) & 0x20) >> 5)
|
||||
|
@ -314,6 +329,16 @@ extern "C" {
|
|||
ENTRY(ZMM30) \
|
||||
ENTRY(ZMM31)
|
||||
|
||||
#define REGS_MASKS \
|
||||
ENTRY(K0) \
|
||||
ENTRY(K1) \
|
||||
ENTRY(K2) \
|
||||
ENTRY(K3) \
|
||||
ENTRY(K4) \
|
||||
ENTRY(K5) \
|
||||
ENTRY(K6) \
|
||||
ENTRY(K7)
|
||||
|
||||
#define REGS_SEGMENT \
|
||||
ENTRY(ES) \
|
||||
ENTRY(CS) \
|
||||
|
@ -361,6 +386,7 @@ extern "C" {
|
|||
REGS_XMM \
|
||||
REGS_YMM \
|
||||
REGS_ZMM \
|
||||
REGS_MASKS \
|
||||
REGS_SEGMENT \
|
||||
REGS_DEBUG \
|
||||
REGS_CONTROL \
|
||||
|
@ -463,7 +489,7 @@ typedef enum {
|
|||
} XOPMapSelect;
|
||||
|
||||
/*
|
||||
* VEXPrefixCode - Possible values for the VEX.pp field
|
||||
* VEXPrefixCode - Possible values for the VEX.pp/EVEX.pp field
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
|
@ -477,8 +503,9 @@ typedef enum {
|
|||
TYPE_NO_VEX_XOP = 0x0,
|
||||
TYPE_VEX_2B = 0x1,
|
||||
TYPE_VEX_3B = 0x2,
|
||||
TYPE_XOP = 0x3
|
||||
} VEXXOPType;
|
||||
TYPE_EVEX = 0x3,
|
||||
TYPE_XOP = 0x4
|
||||
} VectorExtensionType;
|
||||
|
||||
typedef uint8_t BOOL;
|
||||
|
||||
|
@ -536,10 +563,10 @@ struct InternalInstruction {
|
|||
uint8_t prefixPresent[0x100];
|
||||
/* contains the location (for use with the reader) of the prefix byte */
|
||||
uint64_t prefixLocations[0x100];
|
||||
/* The value of the VEX/XOP prefix, if present */
|
||||
uint8_t vexXopPrefix[3];
|
||||
/* The length of the VEX prefix (0 if not present) */
|
||||
VEXXOPType vexXopType;
|
||||
/* The value of the vector extention prefix(EVEX/VEX/XOP), if present */
|
||||
uint8_t vectorExtensionPrefix[4];
|
||||
/* The type of the vector extension prefix */
|
||||
VectorExtensionType vectorExtensionType;
|
||||
/* The value of the REX prefix, if present */
|
||||
uint8_t rexPrefix;
|
||||
/* The location where a mandatory prefix would have to be (i.e., right before
|
||||
|
@ -585,6 +612,9 @@ struct InternalInstruction {
|
|||
instructions */
|
||||
Reg vvvv;
|
||||
|
||||
/* The writemask for AVX-512 instructions which is contained in EVEX.aaa */
|
||||
Reg writemask;
|
||||
|
||||
/* The ModR/M byte, which contains most register operands and some portion of
|
||||
all memory operands */
|
||||
BOOL consumedModRM;
|
||||
|
|
|
@ -55,14 +55,20 @@
|
|||
*/
|
||||
#define ATTRIBUTE_BITS \
|
||||
ENUM_ENTRY(ATTR_NONE, 0x00) \
|
||||
ENUM_ENTRY(ATTR_64BIT, 0x01) \
|
||||
ENUM_ENTRY(ATTR_XS, 0x02) \
|
||||
ENUM_ENTRY(ATTR_XD, 0x04) \
|
||||
ENUM_ENTRY(ATTR_REXW, 0x08) \
|
||||
ENUM_ENTRY(ATTR_OPSIZE, 0x10) \
|
||||
ENUM_ENTRY(ATTR_ADSIZE, 0x20) \
|
||||
ENUM_ENTRY(ATTR_VEX, 0x40) \
|
||||
ENUM_ENTRY(ATTR_VEXL, 0x80)
|
||||
ENUM_ENTRY(ATTR_64BIT, (0x1 << 0)) \
|
||||
ENUM_ENTRY(ATTR_XS, (0x1 << 1)) \
|
||||
ENUM_ENTRY(ATTR_XD, (0x1 << 2)) \
|
||||
ENUM_ENTRY(ATTR_REXW, (0x1 << 3)) \
|
||||
ENUM_ENTRY(ATTR_OPSIZE, (0x1 << 4)) \
|
||||
ENUM_ENTRY(ATTR_ADSIZE, (0x1 << 5)) \
|
||||
ENUM_ENTRY(ATTR_VEX, (0x1 << 6)) \
|
||||
ENUM_ENTRY(ATTR_VEXL, (0x1 << 7)) \
|
||||
ENUM_ENTRY(ATTR_EVEX, (0x1 << 8)) \
|
||||
ENUM_ENTRY(ATTR_EVEXL, (0x1 << 9)) \
|
||||
ENUM_ENTRY(ATTR_EVEXL2, (0x1 << 10)) \
|
||||
ENUM_ENTRY(ATTR_EVEXK, (0x1 << 11)) \
|
||||
ENUM_ENTRY(ATTR_EVEXKZ, (0x1 << 12)) \
|
||||
ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13))
|
||||
|
||||
#define ENUM_ENTRY(n, v) n = v,
|
||||
enum attributeBits {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
# RUN: llvm-mc --disassemble %s -triple=x86_64-apple-darwin9 -mcpu=knl | FileCheck %s
|
||||
|
||||
# CHECK: vpbroadcastd %xmm18, %zmm28 {%k7} {z}
|
||||
0x62 0x22 0x7d 0xcf 0x58 0xe2
|
||||
|
||||
# CHECK: vbroadcastss (%rsp), %zmm28
|
||||
0x62 0x62 0x7d 0x48 0x18 0x24 0x24
|
||||
|
||||
# CHECK: vblendmpd (%rsi), %zmm2, %zmm8 {%k7}
|
||||
0x62 0x72 0xed 0x4f 0x65 0x06
|
||||
|
||||
# CHECK: vpermpd (%rsi,%r10,4), %zmm2, %zmm8
|
||||
0x62 0x32 0xed 0x48 0x16 0x04 0x96
|
||||
|
||||
# CHECK: vpbroadcastmw2d %k2, %zmm8
|
||||
0x62 0xd2 0x7e 0x48 0x3a 0xd0
|
||||
|
||||
# CHECK: vpbroadcastq (%r9,%rax), %zmm28
|
||||
0x62 0x42 0xfd 0x48 0x59 0x24 0x01
|
||||
|
||||
# CHECK: vbroadcastss %xmm0, %zmm1
|
||||
0x62 0xf2 0x7d 0x48 0x18 0xc8
|
||||
|
||||
# CHECK: vextracti32x4 $4, %zmm0, (%r10)
|
||||
0x62 0xd3 0x7d 0x48 0x39 0x02 0x04
|
||||
|
||||
# CHECK: vextracti32x4 $4, %zmm0, %xmm1
|
||||
0x62 0xf3 0x7d 0x48 0x39 0xc1 0x04
|
||||
|
||||
# CHECK: vinserti32x4 $1, %xmm21, %zmm5, %zmm17
|
||||
0x62 0xa3 0x55 0x48 0x38 0xcd 0x01
|
||||
|
||||
# CHECK: vmovaps %zmm21, %zmm5 {%k3}
|
||||
0x62 0xb1 0x7c 0x4b 0x28 0xed
|
||||
|
||||
# CHECK: vgatherdps (%rsi,%zmm0,4), %zmm1 {%k2}
|
||||
0x62 0xf2 0x7d 0x4a 0x92 0x0c 0x86
|
||||
|
||||
# CHECK: vgatherdpd (%rsi,%ymm0,4), %zmm1 {%k2}
|
||||
0x62 0xf2 0xfd 0x4a 0x92 0x0c 0x86
|
||||
|
||||
#####################################################
|
||||
# MASK INSTRUCTIONS #
|
||||
#####################################################
|
||||
|
||||
# CHECK: kshiftlw $3, %k1, %k2
|
||||
0xc4 0xe3 0xf9 0x32 0xd1 0x03
|
||||
|
||||
# CHECK: kmovw (%rdi), %k1
|
||||
0xc5 0xf8 0x90 0x0f
|
||||
|
||||
# CHECK: kmovw %k1, %eax
|
||||
0xc5 0xf8 0x93 0xc1
|
||||
|
||||
# CHECK: kandw %k1, %k2, %k3
|
||||
0xc5 0xec 0x41 0xd9
|
||||
|
||||
# CHECK: kmovw %k5, %k1
|
||||
0xc5 0xf8 0x90 0xcd
|
|
@ -636,14 +636,36 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
|
|||
}
|
||||
|
||||
void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
|
||||
const unsigned int tableSize = 16384;
|
||||
o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR
|
||||
"[256] = {\n";
|
||||
"[" << tableSize << "] = {\n";
|
||||
i++;
|
||||
|
||||
for (unsigned index = 0; index < 256; ++index) {
|
||||
for (unsigned index = 0; index < tableSize; ++index) {
|
||||
o.indent(i * 2);
|
||||
|
||||
if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
|
||||
if (index & ATTR_EVEX) {
|
||||
o << "IC_EVEX";
|
||||
if (index & ATTR_EVEXL2)
|
||||
o << "_L2";
|
||||
else if (index & ATTR_EVEXL)
|
||||
o << "_L";
|
||||
if (index & ATTR_REXW)
|
||||
o << "_W";
|
||||
if (index & ATTR_OPSIZE)
|
||||
o << "_OPSIZE";
|
||||
else if (index & ATTR_XD)
|
||||
o << "_XD";
|
||||
else if (index & ATTR_XS)
|
||||
o << "_XS";
|
||||
if (index & ATTR_EVEXKZ)
|
||||
o << "_KZ";
|
||||
else if (index & ATTR_EVEXK)
|
||||
o << "_K";
|
||||
if (index & ATTR_EVEXB)
|
||||
o << "_B";
|
||||
}
|
||||
else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
|
||||
o << "IC_VEX_L_W_OPSIZE";
|
||||
else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XD))
|
||||
o << "IC_VEX_L_W_XD";
|
||||
|
@ -713,7 +735,7 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
|
|||
else
|
||||
o << "IC";
|
||||
|
||||
if (index < 255)
|
||||
if (index < tableSize - 1)
|
||||
o << ",";
|
||||
else
|
||||
o << " ";
|
||||
|
|
Loading…
Reference in New Issue