diff options
author | Elena Demikhovsky <elena.demikhovsky@intel.com> | 2013-12-25 11:40:51 +0000 |
---|---|---|
committer | Elena Demikhovsky <elena.demikhovsky@intel.com> | 2013-12-25 11:40:51 +0000 |
commit | 371e3638337096968a63c9eb1e76302975916cf9 (patch) | |
tree | d343cec1310da28c3a48a2bd5bbcc5cf2a3c886d /llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c | |
parent | 5746c076294babd11ddba633043f946c18ac8d87 (diff) | |
download | bcm5719-llvm-371e3638337096968a63c9eb1e76302975916cf9.tar.gz bcm5719-llvm-371e3638337096968a63c9eb1e76302975916cf9.zip |
AVX-512: decoder for AVX-512, made by Alexey Bader.
llvm-svn: 198013
Diffstat (limited to 'llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c')
-rw-r--r-- | llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c | 257 |
1 files changed, 191 insertions, 66 deletions
diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c index c81a85755f8..4b97678d0c7 100644 --- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c +++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.c @@ -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,29 @@ static int readOpcode(struct InternalInstruction* insn) { insn->opcodeType = ONEBYTE; - if (insn->vexXopType == TYPE_VEX_3B) + if (insn->vectorExtensionType == TYPE_EVEX) { - switch (mmmmmFromVEX2of3(insn->vexXopPrefix[1])) - { + switch (mmFromEVEX2of4(insn->vectorExtensionPrefix[1])) { + default: + dbgprintf(insn, "Unhandled mm field for instruction (0x%hhx)", + mmFromEVEX2of4(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_3B) { + switch (mmmmmFromVEX2of3(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 VEX_LOB_0F: insn->opcodeType = TWOBYTE; @@ -665,18 +734,15 @@ static int readOpcode(struct InternalInstruction* insn) { return consumeByte(insn, &insn->opcode); } } - else if (insn->vexXopType == TYPE_VEX_2B) - { + 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,35 @@ 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->vectorExtensionType == TYPE_EVEX) { + switch (ppFromEVEX3of4(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 (insn->vexXopType == TYPE_VEX_3B) { - switch (ppFromVEX3of3(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; @@ -852,11 +942,11 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) { break; } - if (lFromVEX3of3(insn->vexXopPrefix[2])) + 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; @@ -1566,6 +1670,23 @@ static int readVVVV(struct InternalInstruction* insn) { } /* + * 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: |