2009-12-19 03:59:52 +01:00
|
|
|
//===- X86RecognizableInstr.cpp - Disassembler instruction spec --*- C++ -*-===//
|
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2009-12-19 03:59:52 +01:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file is part of the X86 Disassembler Emitter.
|
|
|
|
// It contains the implementation of a single recognizable instruction.
|
|
|
|
// Documentation for the disassembler emitter in general can be found in
|
2017-07-04 15:09:29 +02:00
|
|
|
// X86DisassemblerEmitter.h.
|
2009-12-19 03:59:52 +01:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "X86RecognizableInstr.h"
|
2012-12-04 11:37:14 +01:00
|
|
|
#include "X86DisassemblerShared.h"
|
2009-12-19 03:59:52 +01:00
|
|
|
#include "X86ModRMFilters.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace X86Disassembler;
|
|
|
|
|
|
|
|
/// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit.
|
|
|
|
/// Useful for switch statements and the like.
|
|
|
|
///
|
|
|
|
/// @param init - A reference to the BitsInit to be decoded.
|
|
|
|
/// @return - The field, with the first bit in the BitsInit as the lowest
|
|
|
|
/// order bit.
|
2011-07-30 00:43:06 +02:00
|
|
|
static uint8_t byteFromBitsInit(BitsInit &init) {
|
2009-12-19 03:59:52 +01:00
|
|
|
int width = init.getNumBits();
|
|
|
|
|
|
|
|
assert(width <= 8 && "Field is too large for uint8_t!");
|
|
|
|
|
|
|
|
int index;
|
|
|
|
uint8_t mask = 0x01;
|
|
|
|
|
|
|
|
uint8_t ret = 0;
|
|
|
|
|
|
|
|
for (index = 0; index < width; index++) {
|
2018-04-03 07:10:12 +02:00
|
|
|
if (cast<BitInit>(init.getBit(index))->getValue())
|
2009-12-19 03:59:52 +01:00
|
|
|
ret |= mask;
|
|
|
|
|
|
|
|
mask <<= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// byteFromRec - Extract a value at most 8 bits in with from a Record given the
|
|
|
|
/// name of the field.
|
|
|
|
///
|
|
|
|
/// @param rec - The record from which to extract the value.
|
|
|
|
/// @param name - The name of the field in the record.
|
|
|
|
/// @return - The field, as translated by byteFromBitsInit().
|
2020-12-18 17:00:27 +01:00
|
|
|
static uint8_t byteFromRec(const Record* rec, StringRef name) {
|
2011-07-30 00:43:06 +02:00
|
|
|
BitsInit* bits = rec->getValueAsBitsInit(name);
|
2009-12-19 03:59:52 +01:00
|
|
|
return byteFromBitsInit(*bits);
|
|
|
|
}
|
|
|
|
|
|
|
|
RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
|
|
|
|
const CodeGenInstruction &insn,
|
|
|
|
InstrUID uid) {
|
|
|
|
UID = uid;
|
|
|
|
|
|
|
|
Rec = insn.TheDef;
|
2020-01-28 20:23:46 +01:00
|
|
|
Name = std::string(Rec->getName());
|
2009-12-19 03:59:52 +01:00
|
|
|
Spec = &tables.specForUID(UID);
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
if (!Rec->isSubClassOf("X86Inst")) {
|
|
|
|
ShouldBeEmitted = false;
|
|
|
|
return;
|
|
|
|
}
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2014-02-26 07:01:21 +01:00
|
|
|
OpPrefix = byteFromRec(Rec, "OpPrefixBits");
|
|
|
|
OpMap = byteFromRec(Rec, "OpMapBits");
|
2009-12-19 03:59:52 +01:00
|
|
|
Opcode = byteFromRec(Rec, "Opcode");
|
|
|
|
Form = byteFromRec(Rec, "FormBits");
|
2014-02-26 07:01:21 +01:00
|
|
|
Encoding = byteFromRec(Rec, "OpEncBits");
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2018-02-15 22:20:31 +01:00
|
|
|
OpSize = byteFromRec(Rec, "OpSizeBits");
|
|
|
|
AdSize = byteFromRec(Rec, "AdSizeBits");
|
|
|
|
HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
|
|
|
|
HasVEX_4V = Rec->getValueAsBit("hasVEX_4V");
|
2019-04-09 09:40:06 +02:00
|
|
|
HasVEX_W = Rec->getValueAsBit("HasVEX_W");
|
|
|
|
IgnoresVEX_W = Rec->getValueAsBit("IgnoresVEX_W");
|
2018-02-15 22:20:31 +01:00
|
|
|
IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
|
|
|
|
HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2");
|
|
|
|
HasEVEX_K = Rec->getValueAsBit("hasEVEX_K");
|
|
|
|
HasEVEX_KZ = Rec->getValueAsBit("hasEVEX_Z");
|
|
|
|
HasEVEX_B = Rec->getValueAsBit("hasEVEX_B");
|
|
|
|
IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
|
|
|
|
ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
|
|
|
|
CD8_Scale = byteFromRec(Rec, "CD8_Scale");
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2020-01-28 20:23:46 +01:00
|
|
|
Name = std::string(Rec->getName());
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2010-11-01 05:03:32 +01:00
|
|
|
Operands = &insn.Operands.OperandList;
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2012-09-19 08:37:45 +02:00
|
|
|
HasVEX_LPrefix = Rec->getValueAsBit("hasVEX_L");
|
2011-10-16 05:51:13 +02:00
|
|
|
|
2017-10-23 04:26:24 +02:00
|
|
|
EncodeRC = HasEVEX_B &&
|
|
|
|
(Form == X86Local::MRMDestReg || Form == X86Local::MRMSrcReg);
|
|
|
|
|
2011-07-16 04:41:28 +02:00
|
|
|
// Check for 64-bit inst which does not require REX
|
2011-09-23 08:57:25 +02:00
|
|
|
Is32Bit = false;
|
2011-07-16 04:41:28 +02:00
|
|
|
Is64Bit = false;
|
|
|
|
// FIXME: Is there some better way to check for In64BitMode?
|
|
|
|
std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates");
|
|
|
|
for (unsigned i = 0, e = Predicates.size(); i != e; ++i) {
|
2013-12-20 03:04:49 +01:00
|
|
|
if (Predicates[i]->getName().find("Not64Bit") != Name.npos ||
|
2019-03-31 16:49:00 +02:00
|
|
|
Predicates[i]->getName().find("In32Bit") != Name.npos) {
|
2011-09-23 08:57:25 +02:00
|
|
|
Is32Bit = true;
|
|
|
|
break;
|
|
|
|
}
|
2013-12-20 03:04:49 +01:00
|
|
|
if (Predicates[i]->getName().find("In64Bit") != Name.npos) {
|
2011-07-16 04:41:28 +02:00
|
|
|
Is64Bit = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-13 08:07:16 +01:00
|
|
|
if (Form == X86Local::Pseudo || (IsCodeGenOnly && !ForceDisassemble)) {
|
|
|
|
ShouldBeEmitted = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Special case since there is no attribute class for 64-bit and VEX
|
|
|
|
if (Name == "VMASKMOVDQU64") {
|
|
|
|
ShouldBeEmitted = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
ShouldBeEmitted = true;
|
|
|
|
}
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
void RecognizableInstr::processInstr(DisassemblerTables &tables,
|
2012-07-12 08:52:41 +02:00
|
|
|
const CodeGenInstruction &insn,
|
|
|
|
InstrUID uid)
|
2009-12-19 03:59:52 +01:00
|
|
|
{
|
2010-05-20 22:20:32 +02:00
|
|
|
// Ignore "asm parser only" instructions.
|
|
|
|
if (insn.TheDef->getValueAsBit("isAsmParserOnly"))
|
|
|
|
return;
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
RecognizableInstr recogInstr(tables, insn, uid);
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2014-02-13 08:07:16 +01:00
|
|
|
if (recogInstr.shouldBeEmitted()) {
|
|
|
|
recogInstr.emitInstructionSpecifier();
|
2009-12-19 03:59:52 +01:00
|
|
|
recogInstr.emitDecodePath(tables);
|
2014-02-13 08:07:16 +01:00
|
|
|
}
|
2009-12-19 03:59:52 +01:00
|
|
|
}
|
|
|
|
|
2013-11-03 14:46:31 +01:00
|
|
|
#define EVEX_KB(n) (HasEVEX_KZ && HasEVEX_B ? n##_KZ_B : \
|
|
|
|
(HasEVEX_K && HasEVEX_B ? n##_K_B : \
|
|
|
|
(HasEVEX_KZ ? n##_KZ : \
|
|
|
|
(HasEVEX_K? n##_K : (HasEVEX_B ? n##_B : n)))))
|
2013-07-28 10:28:38 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
InstructionContext RecognizableInstr::insnContext() const {
|
|
|
|
InstructionContext insnContext;
|
|
|
|
|
2014-02-02 08:08:01 +01:00
|
|
|
if (Encoding == X86Local::EVEX) {
|
2013-07-28 10:28:38 +02:00
|
|
|
if (HasVEX_LPrefix && HasEVEX_L2Prefix) {
|
2013-07-28 23:28:02 +02:00
|
|
|
errs() << "Don't support VEX.L if EVEX_L2 is enabled: " << Name << "\n";
|
|
|
|
llvm_unreachable("Don't support VEX.L if EVEX_L2 is enabled");
|
2013-07-28 10:28:38 +02:00
|
|
|
}
|
|
|
|
// VEX_L & VEX_W
|
2019-04-09 09:40:06 +02:00
|
|
|
if (!EncodeRC && HasVEX_LPrefix && HasVEX_W) {
|
2014-02-02 08:46:05 +01:00
|
|
|
if (OpPrefix == X86Local::PD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L_W_OPSIZE);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L_W_XS);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L_W_XD);
|
2014-02-18 01:21:49 +01:00
|
|
|
else if (OpPrefix == X86Local::PS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L_W);
|
2014-02-18 01:21:49 +01:00
|
|
|
else {
|
|
|
|
errs() << "Instruction does not use a prefix: " << Name << "\n";
|
|
|
|
llvm_unreachable("Invalid prefix");
|
|
|
|
}
|
2017-10-23 04:26:24 +02:00
|
|
|
} else if (!EncodeRC && HasVEX_LPrefix) {
|
2013-07-28 10:28:38 +02:00
|
|
|
// VEX_L
|
2014-02-02 08:46:05 +01:00
|
|
|
if (OpPrefix == X86Local::PD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L_OPSIZE);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L_XS);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L_XD);
|
2014-02-18 01:21:49 +01:00
|
|
|
else if (OpPrefix == X86Local::PS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L);
|
2014-02-18 01:21:49 +01:00
|
|
|
else {
|
|
|
|
errs() << "Instruction does not use a prefix: " << Name << "\n";
|
|
|
|
llvm_unreachable("Invalid prefix");
|
|
|
|
}
|
2019-04-09 09:40:06 +02:00
|
|
|
} else if (!EncodeRC && HasEVEX_L2Prefix && HasVEX_W) {
|
2013-07-28 10:28:38 +02:00
|
|
|
// EVEX_L2 & VEX_W
|
2014-02-02 08:46:05 +01:00
|
|
|
if (OpPrefix == X86Local::PD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L2_W_OPSIZE);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L2_W_XS);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L2_W_XD);
|
2014-02-18 01:21:49 +01:00
|
|
|
else if (OpPrefix == X86Local::PS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L2_W);
|
2014-02-18 01:21:49 +01:00
|
|
|
else {
|
|
|
|
errs() << "Instruction does not use a prefix: " << Name << "\n";
|
|
|
|
llvm_unreachable("Invalid prefix");
|
|
|
|
}
|
2017-10-23 04:26:24 +02:00
|
|
|
} else if (!EncodeRC && HasEVEX_L2Prefix) {
|
2013-07-28 10:28:38 +02:00
|
|
|
// EVEX_L2
|
2014-02-02 08:46:05 +01:00
|
|
|
if (OpPrefix == X86Local::PD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L2_OPSIZE);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L2_XD);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L2_XS);
|
2014-02-18 01:21:49 +01:00
|
|
|
else if (OpPrefix == X86Local::PS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_L2);
|
2014-02-18 01:21:49 +01:00
|
|
|
else {
|
|
|
|
errs() << "Instruction does not use a prefix: " << Name << "\n";
|
|
|
|
llvm_unreachable("Invalid prefix");
|
|
|
|
}
|
2013-07-28 10:28:38 +02:00
|
|
|
}
|
2019-04-09 09:40:06 +02:00
|
|
|
else if (HasVEX_W) {
|
2013-07-28 10:28:38 +02:00
|
|
|
// VEX_W
|
2014-02-02 08:46:05 +01:00
|
|
|
if (OpPrefix == X86Local::PD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_W_OPSIZE);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_W_XS);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_W_XD);
|
2014-02-18 01:21:49 +01:00
|
|
|
else if (OpPrefix == X86Local::PS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_W);
|
2014-02-18 01:21:49 +01:00
|
|
|
else {
|
|
|
|
errs() << "Instruction does not use a prefix: " << Name << "\n";
|
|
|
|
llvm_unreachable("Invalid prefix");
|
|
|
|
}
|
2013-07-28 10:28:38 +02:00
|
|
|
}
|
|
|
|
// No L, no W
|
2014-02-02 08:46:05 +01:00
|
|
|
else if (OpPrefix == X86Local::PD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_OPSIZE);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_XD);
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX_XS);
|
2018-04-03 08:37:01 +02:00
|
|
|
else if (OpPrefix == X86Local::PS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = EVEX_KB(IC_EVEX);
|
2018-04-03 08:37:01 +02:00
|
|
|
else {
|
|
|
|
errs() << "Instruction does not use a prefix: " << Name << "\n";
|
|
|
|
llvm_unreachable("Invalid prefix");
|
|
|
|
}
|
2013-07-28 10:28:38 +02:00
|
|
|
/// eof EVEX
|
2014-02-02 08:08:01 +01:00
|
|
|
} else if (Encoding == X86Local::VEX || Encoding == X86Local::XOP) {
|
2019-04-09 09:40:06 +02:00
|
|
|
if (HasVEX_LPrefix && HasVEX_W) {
|
2014-02-02 08:46:05 +01:00
|
|
|
if (OpPrefix == X86Local::PD)
|
2011-11-07 00:04:08 +01:00
|
|
|
insnContext = IC_VEX_L_W_OPSIZE;
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = IC_VEX_L_W_XS;
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XD)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = IC_VEX_L_W_XD;
|
2014-02-18 01:21:49 +01:00
|
|
|
else if (OpPrefix == X86Local::PS)
|
2013-07-28 10:28:38 +02:00
|
|
|
insnContext = IC_VEX_L_W;
|
2014-02-18 01:21:49 +01:00
|
|
|
else {
|
|
|
|
errs() << "Instruction does not use a prefix: " << Name << "\n";
|
|
|
|
llvm_unreachable("Invalid prefix");
|
|
|
|
}
|
2014-02-02 08:46:05 +01:00
|
|
|
} else if (OpPrefix == X86Local::PD && HasVEX_LPrefix)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX_L_OPSIZE;
|
2019-04-09 09:40:06 +02:00
|
|
|
else if (OpPrefix == X86Local::PD && HasVEX_W)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX_W_OPSIZE;
|
2014-02-02 08:46:05 +01:00
|
|
|
else if (OpPrefix == X86Local::PD)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX_OPSIZE;
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (HasVEX_LPrefix && OpPrefix == X86Local::XS)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX_L_XS;
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (HasVEX_LPrefix && OpPrefix == X86Local::XD)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX_L_XD;
|
2019-04-09 09:40:06 +02:00
|
|
|
else if (HasVEX_W && OpPrefix == X86Local::XS)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX_W_XS;
|
2019-04-09 09:40:06 +02:00
|
|
|
else if (HasVEX_W && OpPrefix == X86Local::XD)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX_W_XD;
|
2019-04-09 09:40:06 +02:00
|
|
|
else if (HasVEX_W && OpPrefix == X86Local::PS)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX_W;
|
2014-02-18 01:21:49 +01:00
|
|
|
else if (HasVEX_LPrefix && OpPrefix == X86Local::PS)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX_L;
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XD)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX_XD;
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XS)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX_XS;
|
2014-02-18 01:21:49 +01:00
|
|
|
else if (OpPrefix == X86Local::PS)
|
2011-03-15 02:23:15 +01:00
|
|
|
insnContext = IC_VEX;
|
2014-02-18 01:21:49 +01:00
|
|
|
else {
|
|
|
|
errs() << "Instruction does not use a prefix: " << Name << "\n";
|
|
|
|
llvm_unreachable("Invalid prefix");
|
|
|
|
}
|
2015-01-02 08:02:25 +01:00
|
|
|
} else if (Is64Bit || HasREX_WPrefix || AdSize == X86Local::AdSize64) {
|
2014-02-02 10:25:09 +01:00
|
|
|
if (HasREX_WPrefix && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD))
|
2009-12-19 03:59:52 +01:00
|
|
|
insnContext = IC_64BIT_REXW_OPSIZE;
|
2015-01-03 01:00:20 +01:00
|
|
|
else if (HasREX_WPrefix && AdSize == X86Local::AdSize32)
|
|
|
|
insnContext = IC_64BIT_REXW_ADSIZE;
|
2014-02-02 10:25:09 +01:00
|
|
|
else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD)
|
2011-10-01 21:54:56 +02:00
|
|
|
insnContext = IC_64BIT_XD_OPSIZE;
|
2014-02-02 10:25:09 +01:00
|
|
|
else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS)
|
2011-10-11 06:34:23 +02:00
|
|
|
insnContext = IC_64BIT_XS_OPSIZE;
|
2018-05-01 12:01:16 +02:00
|
|
|
else if (AdSize == X86Local::AdSize32 && OpPrefix == X86Local::PD)
|
|
|
|
insnContext = IC_64BIT_OPSIZE_ADSIZE;
|
2014-12-31 08:07:31 +01:00
|
|
|
else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize32)
|
|
|
|
insnContext = IC_64BIT_OPSIZE_ADSIZE;
|
2014-02-02 10:25:09 +01:00
|
|
|
else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)
|
2009-12-19 03:59:52 +01:00
|
|
|
insnContext = IC_64BIT_OPSIZE;
|
2014-12-24 07:05:22 +01:00
|
|
|
else if (AdSize == X86Local::AdSize32)
|
2012-02-27 02:54:29 +01:00
|
|
|
insnContext = IC_64BIT_ADSIZE;
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (HasREX_WPrefix && OpPrefix == X86Local::XS)
|
2009-12-19 03:59:52 +01:00
|
|
|
insnContext = IC_64BIT_REXW_XS;
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (HasREX_WPrefix && OpPrefix == X86Local::XD)
|
2009-12-19 03:59:52 +01:00
|
|
|
insnContext = IC_64BIT_REXW_XD;
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XD)
|
2009-12-19 03:59:52 +01:00
|
|
|
insnContext = IC_64BIT_XD;
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XS)
|
2009-12-19 03:59:52 +01:00
|
|
|
insnContext = IC_64BIT_XS;
|
|
|
|
else if (HasREX_WPrefix)
|
|
|
|
insnContext = IC_64BIT_REXW;
|
|
|
|
else
|
|
|
|
insnContext = IC_64BIT;
|
|
|
|
} else {
|
2014-02-02 10:25:09 +01:00
|
|
|
if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD)
|
2011-10-01 21:54:56 +02:00
|
|
|
insnContext = IC_XD_OPSIZE;
|
2014-02-02 10:25:09 +01:00
|
|
|
else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS)
|
2011-10-11 06:34:23 +02:00
|
|
|
insnContext = IC_XS_OPSIZE;
|
2018-04-05 20:20:14 +02:00
|
|
|
else if (AdSize == X86Local::AdSize16 && OpPrefix == X86Local::XD)
|
|
|
|
insnContext = IC_XD_ADSIZE;
|
|
|
|
else if (AdSize == X86Local::AdSize16 && OpPrefix == X86Local::XS)
|
|
|
|
insnContext = IC_XS_ADSIZE;
|
2018-05-01 12:01:16 +02:00
|
|
|
else if (AdSize == X86Local::AdSize16 && OpPrefix == X86Local::PD)
|
|
|
|
insnContext = IC_OPSIZE_ADSIZE;
|
2014-12-31 08:07:31 +01:00
|
|
|
else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize16)
|
|
|
|
insnContext = IC_OPSIZE_ADSIZE;
|
2014-02-02 10:25:09 +01:00
|
|
|
else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)
|
2009-12-19 03:59:52 +01:00
|
|
|
insnContext = IC_OPSIZE;
|
2014-12-24 07:05:22 +01:00
|
|
|
else if (AdSize == X86Local::AdSize16)
|
2012-02-27 02:54:29 +01:00
|
|
|
insnContext = IC_ADSIZE;
|
2014-01-31 09:47:06 +01:00
|
|
|
else if (OpPrefix == X86Local::XD)
|
2009-12-19 03:59:52 +01:00
|
|
|
insnContext = IC_XD;
|
2014-02-20 08:59:43 +01:00
|
|
|
else if (OpPrefix == X86Local::XS)
|
2009-12-19 03:59:52 +01:00
|
|
|
insnContext = IC_XS;
|
|
|
|
else
|
|
|
|
insnContext = IC;
|
|
|
|
}
|
|
|
|
|
|
|
|
return insnContext;
|
|
|
|
}
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2014-07-17 19:04:56 +02:00
|
|
|
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.
|
2020-07-02 02:36:45 +02:00
|
|
|
if ((encoding != ENCODING_RM &&
|
|
|
|
encoding != ENCODING_VSIB &&
|
|
|
|
encoding != ENCODING_SIB) ||CD8_Scale == 0)
|
2014-07-17 19:04:56 +02:00
|
|
|
return;
|
|
|
|
encoding = (OperandEncoding)(encoding + Log2_32(CD8_Scale));
|
2017-01-16 06:44:25 +01:00
|
|
|
assert(((encoding >= ENCODING_RM && encoding <= ENCODING_RM_CD64) ||
|
2020-07-02 02:36:45 +02:00
|
|
|
(encoding == ENCODING_SIB) ||
|
2017-01-16 06:44:25 +01:00
|
|
|
(encoding >= ENCODING_VSIB && encoding <= ENCODING_VSIB_CD64)) &&
|
|
|
|
"Invalid CDisp scaling");
|
2014-07-17 19:04:56 +02:00
|
|
|
}
|
|
|
|
|
2012-07-12 08:52:41 +02:00
|
|
|
void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
|
|
|
|
unsigned &physicalOperandIndex,
|
2016-02-16 05:24:56 +01:00
|
|
|
unsigned numPhysicalOperands,
|
2012-07-12 08:52:41 +02:00
|
|
|
const unsigned *operandMapping,
|
|
|
|
OperandEncoding (*encodingFromString)
|
|
|
|
(const std::string&,
|
2014-02-02 10:25:09 +01:00
|
|
|
uint8_t OpSize)) {
|
2009-12-19 03:59:52 +01:00
|
|
|
if (optional) {
|
|
|
|
if (physicalOperandIndex >= numPhysicalOperands)
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
assert(physicalOperandIndex < numPhysicalOperands);
|
|
|
|
}
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
while (operandMapping[operandIndex] != operandIndex) {
|
|
|
|
Spec->operands[operandIndex].encoding = ENCODING_DUP;
|
|
|
|
Spec->operands[operandIndex].type =
|
|
|
|
(OperandType)(TYPE_DUP0 + operandMapping[operandIndex]);
|
|
|
|
++operandIndex;
|
|
|
|
}
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2017-07-05 22:14:54 +02:00
|
|
|
StringRef typeName = (*Operands)[operandIndex].Rec->getName();
|
2011-03-15 02:23:15 +01:00
|
|
|
|
2020-01-28 20:23:46 +01:00
|
|
|
OperandEncoding encoding = encodingFromString(std::string(typeName), OpSize);
|
2014-07-17 19:04:56 +02:00
|
|
|
// Adjust the encoding type for an operand based on the instruction.
|
|
|
|
adjustOperandEncoding(encoding);
|
|
|
|
Spec->operands[operandIndex].encoding = encoding;
|
2020-01-28 20:23:46 +01:00
|
|
|
Spec->operands[operandIndex].type =
|
|
|
|
typeFromString(std::string(typeName), HasREX_WPrefix, OpSize);
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
++operandIndex;
|
|
|
|
++physicalOperandIndex;
|
|
|
|
}
|
|
|
|
|
2014-01-02 04:58:45 +01:00
|
|
|
void RecognizableInstr::emitInstructionSpecifier() {
|
2009-12-19 03:59:52 +01:00
|
|
|
Spec->name = Name;
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
Spec->insnContext = insnContext();
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2010-11-01 05:03:32 +01:00
|
|
|
const std::vector<CGIOperandList::OperandInfo> &OperandList = *Operands;
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
unsigned numOperands = OperandList.size();
|
|
|
|
unsigned numPhysicalOperands = 0;
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
// operandMapping maps from operands in OperandList to their originals.
|
|
|
|
// If operandMapping[i] != i, then the entry is a duplicate.
|
|
|
|
unsigned operandMapping[X86_MAX_OPERANDS];
|
2011-12-30 07:23:39 +01:00
|
|
|
assert(numOperands <= X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough");
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2012-07-12 08:52:41 +02:00
|
|
|
for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
|
2015-01-15 12:41:30 +01:00
|
|
|
if (!OperandList[operandIndex].Constraints.empty()) {
|
2010-11-01 05:03:32 +01:00
|
|
|
const CGIOperandList::ConstraintInfo &Constraint =
|
2010-02-10 02:45:28 +01:00
|
|
|
OperandList[operandIndex].Constraints[0];
|
|
|
|
if (Constraint.isTied()) {
|
2012-07-12 08:52:41 +02:00
|
|
|
operandMapping[operandIndex] = operandIndex;
|
|
|
|
operandMapping[Constraint.getTiedOperand()] = operandIndex;
|
2009-12-19 03:59:52 +01:00
|
|
|
} else {
|
|
|
|
++numPhysicalOperands;
|
|
|
|
operandMapping[operandIndex] = operandIndex;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
++numPhysicalOperands;
|
|
|
|
operandMapping[operandIndex] = operandIndex;
|
|
|
|
}
|
|
|
|
}
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
#define HANDLE_OPERAND(class) \
|
|
|
|
handleOperand(false, \
|
|
|
|
operandIndex, \
|
|
|
|
physicalOperandIndex, \
|
|
|
|
numPhysicalOperands, \
|
|
|
|
operandMapping, \
|
|
|
|
class##EncodingFromString);
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
#define HANDLE_OPTIONAL(class) \
|
|
|
|
handleOperand(true, \
|
|
|
|
operandIndex, \
|
|
|
|
physicalOperandIndex, \
|
|
|
|
numPhysicalOperands, \
|
|
|
|
operandMapping, \
|
|
|
|
class##EncodingFromString);
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
// operandIndex should always be < numOperands
|
2012-07-12 08:52:41 +02:00
|
|
|
unsigned operandIndex = 0;
|
2009-12-19 03:59:52 +01:00
|
|
|
// physicalOperandIndex should always be < numPhysicalOperands
|
|
|
|
unsigned physicalOperandIndex = 0;
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2016-02-18 05:54:32 +01:00
|
|
|
#ifndef NDEBUG
|
2014-10-01 21:28:11 +02:00
|
|
|
// Given the set of prefix bits, how many additional operands does the
|
|
|
|
// instruction have?
|
|
|
|
unsigned additionalOperands = 0;
|
2016-08-22 09:38:50 +02:00
|
|
|
if (HasVEX_4V)
|
2014-10-01 21:28:11 +02:00
|
|
|
++additionalOperands;
|
|
|
|
if (HasEVEX_K)
|
|
|
|
++additionalOperands;
|
2016-02-18 05:54:32 +01:00
|
|
|
#endif
|
2014-10-01 21:28:11 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
switch (Form) {
|
2014-01-16 08:36:58 +01:00
|
|
|
default: llvm_unreachable("Unhandled form");
|
2020-02-21 21:30:27 +01:00
|
|
|
case X86Local::PrefixByte:
|
|
|
|
return;
|
2014-01-22 16:08:08 +01:00
|
|
|
case X86Local::RawFrmSrc:
|
|
|
|
HANDLE_OPERAND(relocation);
|
|
|
|
return;
|
2014-01-22 16:08:21 +01:00
|
|
|
case X86Local::RawFrmDst:
|
|
|
|
HANDLE_OPERAND(relocation);
|
|
|
|
return;
|
2014-01-22 16:08:36 +01:00
|
|
|
case X86Local::RawFrmDstSrc:
|
|
|
|
HANDLE_OPERAND(relocation);
|
|
|
|
HANDLE_OPERAND(relocation);
|
|
|
|
return;
|
2009-12-19 03:59:52 +01:00
|
|
|
case X86Local::RawFrm:
|
|
|
|
// Operand 1 (optional) is an address or immediate.
|
2016-02-18 05:54:29 +01:00
|
|
|
assert(numPhysicalOperands <= 1 &&
|
2009-12-19 03:59:52 +01:00
|
|
|
"Unexpected number of operands for RawFrm");
|
|
|
|
HANDLE_OPTIONAL(relocation)
|
|
|
|
break;
|
2014-01-16 08:36:58 +01:00
|
|
|
case X86Local::RawFrmMemOffs:
|
|
|
|
// Operand 1 is an address.
|
|
|
|
HANDLE_OPERAND(relocation);
|
|
|
|
break;
|
2009-12-19 03:59:52 +01:00
|
|
|
case X86Local::AddRegFrm:
|
|
|
|
// Operand 1 is added to the opcode.
|
|
|
|
// Operand 2 (optional) is an address.
|
|
|
|
assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 &&
|
|
|
|
"Unexpected number of operands for AddRegFrm");
|
|
|
|
HANDLE_OPERAND(opcodeModifier)
|
|
|
|
HANDLE_OPTIONAL(relocation)
|
|
|
|
break;
|
[X86] Merge the different Jcc instructions for each condition code into single instructions that store the condition code as an operand.
Summary:
This avoids needing an isel pattern for each condition code. And it removes translation switches for converting between Jcc instructions and condition codes.
Now the printer, encoder and disassembler take care of converting the immediate. We use InstAliases to handle the assembly matching. But we print using the asm string in the instruction definition. The instruction itself is marked IsCodeGenOnly=1 to hide it from the assembly parser.
Reviewers: spatel, lebedev.ri, courbet, gchatelet, RKSimon
Reviewed By: RKSimon
Subscribers: MatzeB, qcolombet, eraman, hiraditya, arphaman, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60228
llvm-svn: 357802
2019-04-05 21:28:09 +02:00
|
|
|
case X86Local::AddCCFrm:
|
|
|
|
// Operand 1 (optional) is an address or immediate.
|
|
|
|
assert(numPhysicalOperands == 2 &&
|
|
|
|
"Unexpected number of operands for AddCCFrm");
|
|
|
|
HANDLE_OPERAND(relocation)
|
|
|
|
HANDLE_OPERAND(opcodeModifier)
|
|
|
|
break;
|
2009-12-19 03:59:52 +01:00
|
|
|
case X86Local::MRMDestReg:
|
|
|
|
// Operand 1 is a register operand in the R/M field.
|
2014-10-01 21:28:11 +02:00
|
|
|
// - In AVX512 there may be a mask operand here -
|
2009-12-19 03:59:52 +01:00
|
|
|
// Operand 2 is a register operand in the Reg/Opcode field.
|
2011-08-30 09:09:35 +02:00
|
|
|
// - In AVX, there is a register operand in the VEX.vvvv field here -
|
2009-12-19 03:59:52 +01:00
|
|
|
// Operand 3 (optional) is an immediate.
|
2014-10-01 21:28:11 +02:00
|
|
|
assert(numPhysicalOperands >= 2 + additionalOperands &&
|
|
|
|
numPhysicalOperands <= 3 + additionalOperands &&
|
|
|
|
"Unexpected number of operands for MRMDestRegFrm");
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
HANDLE_OPERAND(rmRegister)
|
2014-10-09 01:25:29 +02:00
|
|
|
if (HasEVEX_K)
|
|
|
|
HANDLE_OPERAND(writemaskRegister)
|
2011-08-30 09:09:35 +02:00
|
|
|
|
2014-02-02 08:08:01 +01:00
|
|
|
if (HasVEX_4V)
|
2011-08-30 09:09:35 +02:00
|
|
|
// FIXME: In AVX, the register below becomes the one encoded
|
|
|
|
// in ModRMVEX and the one above the one in the VEX.VVVV field
|
|
|
|
HANDLE_OPERAND(vvvvRegister)
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
HANDLE_OPERAND(roRegister)
|
|
|
|
HANDLE_OPTIONAL(immediate)
|
|
|
|
break;
|
|
|
|
case X86Local::MRMDestMem:
|
2020-07-02 02:36:45 +02:00
|
|
|
case X86Local::MRMDestMemFSIB:
|
2009-12-19 03:59:52 +01:00
|
|
|
// Operand 1 is a memory operand (possibly SIB-extended)
|
|
|
|
// Operand 2 is a register operand in the Reg/Opcode field.
|
2011-08-30 09:09:35 +02:00
|
|
|
// - In AVX, there is a register operand in the VEX.vvvv field here -
|
2009-12-19 03:59:52 +01:00
|
|
|
// Operand 3 (optional) is an immediate.
|
2014-10-01 21:28:11 +02:00
|
|
|
assert(numPhysicalOperands >= 2 + additionalOperands &&
|
|
|
|
numPhysicalOperands <= 3 + additionalOperands &&
|
|
|
|
"Unexpected number of operands for MRMDestMemFrm with VEX_4V");
|
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
HANDLE_OPERAND(memory)
|
2011-08-30 09:09:35 +02:00
|
|
|
|
2013-07-28 10:28:38 +02:00
|
|
|
if (HasEVEX_K)
|
|
|
|
HANDLE_OPERAND(writemaskRegister)
|
|
|
|
|
2014-02-02 08:08:01 +01:00
|
|
|
if (HasVEX_4V)
|
2011-08-30 09:09:35 +02:00
|
|
|
// FIXME: In AVX, the register below becomes the one encoded
|
|
|
|
// in ModRMVEX and the one above the one in the VEX.VVVV field
|
|
|
|
HANDLE_OPERAND(vvvvRegister)
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
HANDLE_OPERAND(roRegister)
|
|
|
|
HANDLE_OPTIONAL(immediate)
|
|
|
|
break;
|
|
|
|
case X86Local::MRMSrcReg:
|
|
|
|
// Operand 1 is a register operand in the Reg/Opcode field.
|
|
|
|
// Operand 2 is a register operand in the R/M field.
|
2011-03-15 02:23:15 +01:00
|
|
|
// - In AVX, there is a register operand in the VEX.vvvv field here -
|
2009-12-19 03:59:52 +01:00
|
|
|
// Operand 3 (optional) is an immediate.
|
2012-05-29 21:05:25 +02:00
|
|
|
// Operand 4 (optional) is an immediate.
|
2010-06-09 00:51:23 +02:00
|
|
|
|
2014-10-01 21:28:11 +02:00
|
|
|
assert(numPhysicalOperands >= 2 + additionalOperands &&
|
|
|
|
numPhysicalOperands <= 4 + additionalOperands &&
|
|
|
|
"Unexpected number of operands for MRMSrcRegFrm");
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2011-03-15 02:23:15 +01:00
|
|
|
HANDLE_OPERAND(roRegister)
|
2011-10-16 05:51:13 +02:00
|
|
|
|
2013-07-28 10:28:38 +02:00
|
|
|
if (HasEVEX_K)
|
|
|
|
HANDLE_OPERAND(writemaskRegister)
|
|
|
|
|
2014-02-02 08:08:01 +01:00
|
|
|
if (HasVEX_4V)
|
2010-06-12 01:50:47 +02:00
|
|
|
// FIXME: In AVX, the register below becomes the one encoded
|
|
|
|
// in ModRMVEX and the one above the one in the VEX.VVVV field
|
2011-03-15 02:23:15 +01:00
|
|
|
HANDLE_OPERAND(vvvvRegister)
|
2011-10-16 05:51:13 +02:00
|
|
|
|
2011-03-15 02:23:15 +01:00
|
|
|
HANDLE_OPERAND(rmRegister)
|
2016-08-22 09:38:45 +02:00
|
|
|
HANDLE_OPTIONAL(immediate)
|
2011-12-30 07:23:39 +01:00
|
|
|
HANDLE_OPTIONAL(immediate) // above might be a register in 7:4
|
2009-12-19 03:59:52 +01:00
|
|
|
break;
|
2016-08-22 09:38:50 +02:00
|
|
|
case X86Local::MRMSrcReg4VOp3:
|
|
|
|
assert(numPhysicalOperands == 3 &&
|
2017-04-27 16:25:04 +02:00
|
|
|
"Unexpected number of operands for MRMSrcReg4VOp3Frm");
|
2016-08-22 09:38:50 +02:00
|
|
|
HANDLE_OPERAND(roRegister)
|
|
|
|
HANDLE_OPERAND(rmRegister)
|
|
|
|
HANDLE_OPERAND(vvvvRegister)
|
|
|
|
break;
|
2016-08-22 09:38:45 +02:00
|
|
|
case X86Local::MRMSrcRegOp4:
|
|
|
|
assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 &&
|
|
|
|
"Unexpected number of operands for MRMSrcRegOp4Frm");
|
|
|
|
HANDLE_OPERAND(roRegister)
|
|
|
|
HANDLE_OPERAND(vvvvRegister)
|
|
|
|
HANDLE_OPERAND(immediate) // Register in imm[7:4]
|
|
|
|
HANDLE_OPERAND(rmRegister)
|
|
|
|
HANDLE_OPTIONAL(immediate)
|
|
|
|
break;
|
[X86] Merge the different CMOV instructions for each condition code into single instructions that store the condition code as an immediate.
Summary:
Reorder the condition code enum to match their encodings. Move it to MC layer so it can be used by the scheduler models.
This avoids needing an isel pattern for each condition code. And it removes
translation switches for converting between CMOV instructions and condition
codes.
Now the printer, encoder and disassembler take care of converting the immediate.
We use InstAliases to handle the assembly matching. But we print using the
asm string in the instruction definition. The instruction itself is marked
IsCodeGenOnly=1 to hide it from the assembly parser.
This does complicate the scheduler models a little since we can't assign the
A and BE instructions to a separate class now.
I plan to make similar changes for SETcc and Jcc.
Reviewers: RKSimon, spatel, lebedev.ri, andreadb, courbet
Reviewed By: RKSimon
Subscribers: gchatelet, hiraditya, kristina, lebedev.ri, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60041
llvm-svn: 357800
2019-04-05 21:27:41 +02:00
|
|
|
case X86Local::MRMSrcRegCC:
|
|
|
|
assert(numPhysicalOperands == 3 &&
|
|
|
|
"Unexpected number of operands for MRMSrcRegCC");
|
|
|
|
HANDLE_OPERAND(roRegister)
|
|
|
|
HANDLE_OPERAND(rmRegister)
|
|
|
|
HANDLE_OPERAND(opcodeModifier)
|
|
|
|
break;
|
2009-12-19 03:59:52 +01:00
|
|
|
case X86Local::MRMSrcMem:
|
2020-07-02 02:36:45 +02:00
|
|
|
case X86Local::MRMSrcMemFSIB:
|
2009-12-19 03:59:52 +01:00
|
|
|
// Operand 1 is a register operand in the Reg/Opcode field.
|
|
|
|
// Operand 2 is a memory operand (possibly SIB-extended)
|
2011-03-15 02:23:15 +01:00
|
|
|
// - In AVX, there is a register operand in the VEX.vvvv field here -
|
2009-12-19 03:59:52 +01:00
|
|
|
// Operand 3 (optional) is an immediate.
|
2011-10-16 09:55:05 +02:00
|
|
|
|
2014-10-01 21:28:11 +02:00
|
|
|
assert(numPhysicalOperands >= 2 + additionalOperands &&
|
|
|
|
numPhysicalOperands <= 4 + additionalOperands &&
|
|
|
|
"Unexpected number of operands for MRMSrcMemFrm");
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
HANDLE_OPERAND(roRegister)
|
2010-06-12 01:50:47 +02:00
|
|
|
|
2013-07-28 10:28:38 +02:00
|
|
|
if (HasEVEX_K)
|
|
|
|
HANDLE_OPERAND(writemaskRegister)
|
|
|
|
|
2014-02-02 08:08:01 +01:00
|
|
|
if (HasVEX_4V)
|
2010-06-12 01:50:47 +02:00
|
|
|
// FIXME: In AVX, the register below becomes the one encoded
|
|
|
|
// in ModRMVEX and the one above the one in the VEX.VVVV field
|
2011-03-15 02:23:15 +01:00
|
|
|
HANDLE_OPERAND(vvvvRegister)
|
2010-06-12 01:50:47 +02:00
|
|
|
|
2009-12-19 03:59:52 +01:00
|
|
|
HANDLE_OPERAND(memory)
|
2016-08-22 09:38:45 +02:00
|
|
|
HANDLE_OPTIONAL(immediate)
|
2011-12-30 07:23:39 +01:00
|
|
|
HANDLE_OPTIONAL(immediate) // above might be a register in 7:4
|
2009-12-19 03:59:52 +01:00
|
|
|
break;
|
2016-08-22 09:38:50 +02:00
|
|
|
case X86Local::MRMSrcMem4VOp3:
|
|
|
|
assert(numPhysicalOperands == 3 &&
|
2017-04-27 16:25:04 +02:00
|
|
|
"Unexpected number of operands for MRMSrcMem4VOp3Frm");
|
2016-08-22 09:38:50 +02:00
|
|
|
HANDLE_OPERAND(roRegister)
|
|
|
|
HANDLE_OPERAND(memory)
|
|
|
|
HANDLE_OPERAND(vvvvRegister)
|
|
|
|
break;
|
2016-08-22 09:38:45 +02:00
|
|
|
case X86Local::MRMSrcMemOp4:
|
|
|
|
assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 &&
|
|
|
|
"Unexpected number of operands for MRMSrcMemOp4Frm");
|
|
|
|
HANDLE_OPERAND(roRegister)
|
|
|
|
HANDLE_OPERAND(vvvvRegister)
|
|
|
|
HANDLE_OPERAND(immediate) // Register in imm[7:4]
|
|
|
|
HANDLE_OPERAND(memory)
|
|
|
|
HANDLE_OPTIONAL(immediate)
|
|
|
|
break;
|
[X86] Merge the different CMOV instructions for each condition code into single instructions that store the condition code as an immediate.
Summary:
Reorder the condition code enum to match their encodings. Move it to MC layer so it can be used by the scheduler models.
This avoids needing an isel pattern for each condition code. And it removes
translation switches for converting between CMOV instructions and condition
codes.
Now the printer, encoder and disassembler take care of converting the immediate.
We use InstAliases to handle the assembly matching. But we print using the
asm string in the instruction definition. The instruction itself is marked
IsCodeGenOnly=1 to hide it from the assembly parser.
This does complicate the scheduler models a little since we can't assign the
A and BE instructions to a separate class now.
I plan to make similar changes for SETcc and Jcc.
Reviewers: RKSimon, spatel, lebedev.ri, andreadb, courbet
Reviewed By: RKSimon
Subscribers: gchatelet, hiraditya, kristina, lebedev.ri, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60041
llvm-svn: 357800
2019-04-05 21:27:41 +02:00
|
|
|
case X86Local::MRMSrcMemCC:
|
|
|
|
assert(numPhysicalOperands == 3 &&
|
|
|
|
"Unexpected number of operands for MRMSrcMemCC");
|
|
|
|
HANDLE_OPERAND(roRegister)
|
|
|
|
HANDLE_OPERAND(memory)
|
|
|
|
HANDLE_OPERAND(opcodeModifier)
|
|
|
|
break;
|
2019-04-05 21:27:49 +02:00
|
|
|
case X86Local::MRMXrCC:
|
|
|
|
assert(numPhysicalOperands == 2 &&
|
|
|
|
"Unexpected number of operands for MRMXrCC");
|
|
|
|
HANDLE_OPERAND(rmRegister)
|
|
|
|
HANDLE_OPERAND(opcodeModifier)
|
|
|
|
break;
|
2020-07-02 02:36:45 +02:00
|
|
|
case X86Local::MRMr0:
|
|
|
|
// Operand 1 is a register operand in the R/M field.
|
|
|
|
HANDLE_OPERAND(roRegister)
|
|
|
|
break;
|
2014-02-10 07:55:41 +01:00
|
|
|
case X86Local::MRMXr:
|
2009-12-19 03:59:52 +01:00
|
|
|
case X86Local::MRM0r:
|
|
|
|
case X86Local::MRM1r:
|
|
|
|
case X86Local::MRM2r:
|
|
|
|
case X86Local::MRM3r:
|
|
|
|
case X86Local::MRM4r:
|
|
|
|
case X86Local::MRM5r:
|
|
|
|
case X86Local::MRM6r:
|
|
|
|
case X86Local::MRM7r:
|
2014-10-01 21:28:11 +02:00
|
|
|
// Operand 1 is a register operand in the R/M field.
|
|
|
|
// Operand 2 (optional) is an immediate or relocation.
|
|
|
|
// Operand 3 (optional) is an immediate.
|
|
|
|
assert(numPhysicalOperands >= 0 + additionalOperands &&
|
|
|
|
numPhysicalOperands <= 3 + additionalOperands &&
|
|
|
|
"Unexpected number of operands for MRMnr");
|
|
|
|
|
2014-02-02 08:08:01 +01:00
|
|
|
if (HasVEX_4V)
|
2011-10-15 22:46:47 +02:00
|
|
|
HANDLE_OPERAND(vvvvRegister)
|
2013-08-22 14:18:28 +02:00
|
|
|
|
|
|
|
if (HasEVEX_K)
|
|
|
|
HANDLE_OPERAND(writemaskRegister)
|
2009-12-19 03:59:52 +01:00
|
|
|
HANDLE_OPTIONAL(rmRegister)
|
|
|
|
HANDLE_OPTIONAL(relocation)
|
2012-05-29 21:05:25 +02:00
|
|
|
HANDLE_OPTIONAL(immediate)
|
2009-12-19 03:59:52 +01:00
|
|
|
break;
|
2019-04-05 21:27:49 +02:00
|
|
|
case X86Local::MRMXmCC:
|
|
|
|
assert(numPhysicalOperands == 2 &&
|
|
|
|
"Unexpected number of operands for MRMXm");
|
|
|
|
HANDLE_OPERAND(memory)
|
|
|
|
HANDLE_OPERAND(opcodeModifier)
|
|
|
|
break;
|
2014-02-10 07:55:41 +01:00
|
|
|
case X86Local::MRMXm:
|
2009-12-19 03:59:52 +01:00
|
|
|
case X86Local::MRM0m:
|
|
|
|
case X86Local::MRM1m:
|
|
|
|
case X86Local::MRM2m:
|
|
|
|
case X86Local::MRM3m:
|
|
|
|
case X86Local::MRM4m:
|
|
|
|
case X86Local::MRM5m:
|
|
|
|
case X86Local::MRM6m:
|
|
|
|
case X86Local::MRM7m:
|
2014-10-01 21:28:11 +02:00
|
|
|
// Operand 1 is a memory operand (possibly SIB-extended)
|
|
|
|
// Operand 2 (optional) is an immediate or relocation.
|
|
|
|
assert(numPhysicalOperands >= 1 + additionalOperands &&
|
|
|
|
numPhysicalOperands <= 2 + additionalOperands &&
|
|
|
|
"Unexpected number of operands for MRMnm");
|
|
|
|
|
2014-02-02 08:08:01 +01:00
|
|
|
if (HasVEX_4V)
|
2011-10-15 22:46:47 +02:00
|
|
|
HANDLE_OPERAND(vvvvRegister)
|
2013-08-22 14:18:28 +02:00
|
|
|
if (HasEVEX_K)
|
|
|
|
HANDLE_OPERAND(writemaskRegister)
|
2009-12-19 03:59:52 +01:00
|
|
|
HANDLE_OPERAND(memory)
|
|
|
|
HANDLE_OPTIONAL(relocation)
|
|
|
|
break;
|
2010-10-05 00:45:51 +02:00
|
|
|
case X86Local::RawFrmImm8:
|
|
|
|
// operand 1 is a 16-bit immediate
|
|
|
|
// operand 2 is an 8-bit immediate
|
|
|
|
assert(numPhysicalOperands == 2 &&
|
|
|
|
"Unexpected number of operands for X86Local::RawFrmImm8");
|
|
|
|
HANDLE_OPERAND(immediate)
|
|
|
|
HANDLE_OPERAND(immediate)
|
|
|
|
break;
|
|
|
|
case X86Local::RawFrmImm16:
|
|
|
|
// operand 1 is a 16-bit immediate
|
|
|
|
// operand 2 is a 16-bit immediate
|
|
|
|
HANDLE_OPERAND(immediate)
|
|
|
|
HANDLE_OPERAND(immediate)
|
|
|
|
break;
|
2020-06-20 07:18:53 +02:00
|
|
|
case X86Local::MRM0X:
|
|
|
|
case X86Local::MRM1X:
|
|
|
|
case X86Local::MRM2X:
|
|
|
|
case X86Local::MRM3X:
|
|
|
|
case X86Local::MRM4X:
|
|
|
|
case X86Local::MRM5X:
|
|
|
|
case X86Local::MRM6X:
|
|
|
|
case X86Local::MRM7X:
|
2018-03-24 08:15:46 +01:00
|
|
|
#define MAP(from, to) case X86Local::MRM_##from:
|
|
|
|
X86_INSTR_MRM_MAPPING
|
|
|
|
#undef MAP
|
2018-03-12 18:24:50 +01:00
|
|
|
HANDLE_OPTIONAL(relocation)
|
2009-12-19 03:59:52 +01:00
|
|
|
break;
|
|
|
|
}
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2018-03-24 08:15:46 +01:00
|
|
|
#undef HANDLE_OPERAND
|
|
|
|
#undef HANDLE_OPTIONAL
|
2009-12-19 03:59:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
|
|
|
|
// Special cases where the LLVM tables are not complete
|
|
|
|
|
2010-02-13 00:39:46 +01:00
|
|
|
#define MAP(from, to) \
|
2015-02-15 05:16:44 +01:00
|
|
|
case X86Local::MRM_##from:
|
2009-12-19 03:59:52 +01:00
|
|
|
|
2017-12-08 23:32:35 +01:00
|
|
|
llvm::Optional<OpcodeType> opcodeType;
|
2014-01-31 09:47:06 +01:00
|
|
|
switch (OpMap) {
|
|
|
|
default: llvm_unreachable("Invalid map!");
|
2018-03-24 08:48:54 +01:00
|
|
|
case X86Local::OB: opcodeType = ONEBYTE; break;
|
|
|
|
case X86Local::TB: opcodeType = TWOBYTE; break;
|
|
|
|
case X86Local::T8: opcodeType = THREEBYTE_38; break;
|
|
|
|
case X86Local::TA: opcodeType = THREEBYTE_3A; break;
|
|
|
|
case X86Local::XOP8: opcodeType = XOP8_MAP; break;
|
|
|
|
case X86Local::XOP9: opcodeType = XOP9_MAP; break;
|
|
|
|
case X86Local::XOPA: opcodeType = XOPA_MAP; break;
|
|
|
|
case X86Local::ThreeDNow: opcodeType = THREEDNOW_MAP; break;
|
2018-03-24 08:15:45 +01:00
|
|
|
}
|
2014-02-10 07:55:41 +01:00
|
|
|
|
2018-03-24 08:15:47 +01:00
|
|
|
std::unique_ptr<ModRMFilter> filter;
|
2018-03-24 08:15:45 +01:00
|
|
|
switch (Form) {
|
|
|
|
default: llvm_unreachable("Invalid form!");
|
|
|
|
case X86Local::Pseudo: llvm_unreachable("Pseudo should not be emitted!");
|
|
|
|
case X86Local::RawFrm:
|
|
|
|
case X86Local::AddRegFrm:
|
|
|
|
case X86Local::RawFrmMemOffs:
|
|
|
|
case X86Local::RawFrmSrc:
|
|
|
|
case X86Local::RawFrmDst:
|
|
|
|
case X86Local::RawFrmDstSrc:
|
|
|
|
case X86Local::RawFrmImm8:
|
|
|
|
case X86Local::RawFrmImm16:
|
[X86] Merge the different Jcc instructions for each condition code into single instructions that store the condition code as an operand.
Summary:
This avoids needing an isel pattern for each condition code. And it removes translation switches for converting between Jcc instructions and condition codes.
Now the printer, encoder and disassembler take care of converting the immediate. We use InstAliases to handle the assembly matching. But we print using the asm string in the instruction definition. The instruction itself is marked IsCodeGenOnly=1 to hide it from the assembly parser.
Reviewers: spatel, lebedev.ri, courbet, gchatelet, RKSimon
Reviewed By: RKSimon
Subscribers: MatzeB, qcolombet, eraman, hiraditya, arphaman, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60228
llvm-svn: 357802
2019-04-05 21:28:09 +02:00
|
|
|
case X86Local::AddCCFrm:
|
2020-02-21 21:30:27 +01:00
|
|
|
case X86Local::PrefixByte:
|
2019-08-15 17:54:37 +02:00
|
|
|
filter = std::make_unique<DumbFilter>();
|
2018-03-24 08:15:45 +01:00
|
|
|
break;
|
|
|
|
case X86Local::MRMDestReg:
|
|
|
|
case X86Local::MRMSrcReg:
|
|
|
|
case X86Local::MRMSrcReg4VOp3:
|
|
|
|
case X86Local::MRMSrcRegOp4:
|
[X86] Merge the different CMOV instructions for each condition code into single instructions that store the condition code as an immediate.
Summary:
Reorder the condition code enum to match their encodings. Move it to MC layer so it can be used by the scheduler models.
This avoids needing an isel pattern for each condition code. And it removes
translation switches for converting between CMOV instructions and condition
codes.
Now the printer, encoder and disassembler take care of converting the immediate.
We use InstAliases to handle the assembly matching. But we print using the
asm string in the instruction definition. The instruction itself is marked
IsCodeGenOnly=1 to hide it from the assembly parser.
This does complicate the scheduler models a little since we can't assign the
A and BE instructions to a separate class now.
I plan to make similar changes for SETcc and Jcc.
Reviewers: RKSimon, spatel, lebedev.ri, andreadb, courbet
Reviewed By: RKSimon
Subscribers: gchatelet, hiraditya, kristina, lebedev.ri, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60041
llvm-svn: 357800
2019-04-05 21:27:41 +02:00
|
|
|
case X86Local::MRMSrcRegCC:
|
2019-04-05 21:27:49 +02:00
|
|
|
case X86Local::MRMXrCC:
|
2018-03-24 08:15:45 +01:00
|
|
|
case X86Local::MRMXr:
|
2019-08-15 17:54:37 +02:00
|
|
|
filter = std::make_unique<ModFilter>(true);
|
2018-03-24 08:15:45 +01:00
|
|
|
break;
|
|
|
|
case X86Local::MRMDestMem:
|
2020-07-02 02:36:45 +02:00
|
|
|
case X86Local::MRMDestMemFSIB:
|
2018-03-24 08:15:45 +01:00
|
|
|
case X86Local::MRMSrcMem:
|
2020-07-02 02:36:45 +02:00
|
|
|
case X86Local::MRMSrcMemFSIB:
|
2018-03-24 08:15:45 +01:00
|
|
|
case X86Local::MRMSrcMem4VOp3:
|
|
|
|
case X86Local::MRMSrcMemOp4:
|
[X86] Merge the different CMOV instructions for each condition code into single instructions that store the condition code as an immediate.
Summary:
Reorder the condition code enum to match their encodings. Move it to MC layer so it can be used by the scheduler models.
This avoids needing an isel pattern for each condition code. And it removes
translation switches for converting between CMOV instructions and condition
codes.
Now the printer, encoder and disassembler take care of converting the immediate.
We use InstAliases to handle the assembly matching. But we print using the
asm string in the instruction definition. The instruction itself is marked
IsCodeGenOnly=1 to hide it from the assembly parser.
This does complicate the scheduler models a little since we can't assign the
A and BE instructions to a separate class now.
I plan to make similar changes for SETcc and Jcc.
Reviewers: RKSimon, spatel, lebedev.ri, andreadb, courbet
Reviewed By: RKSimon
Subscribers: gchatelet, hiraditya, kristina, lebedev.ri, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60041
llvm-svn: 357800
2019-04-05 21:27:41 +02:00
|
|
|
case X86Local::MRMSrcMemCC:
|
2019-04-05 21:27:49 +02:00
|
|
|
case X86Local::MRMXmCC:
|
2018-03-24 08:15:45 +01:00
|
|
|
case X86Local::MRMXm:
|
2019-08-15 17:54:37 +02:00
|
|
|
filter = std::make_unique<ModFilter>(false);
|
2013-10-03 07:17:48 +02:00
|
|
|
break;
|
2018-03-24 08:15:45 +01:00
|
|
|
case X86Local::MRM0r: case X86Local::MRM1r:
|
|
|
|
case X86Local::MRM2r: case X86Local::MRM3r:
|
|
|
|
case X86Local::MRM4r: case X86Local::MRM5r:
|
|
|
|
case X86Local::MRM6r: case X86Local::MRM7r:
|
2019-08-15 17:54:37 +02:00
|
|
|
filter = std::make_unique<ExtendedFilter>(true, Form - X86Local::MRM0r);
|
2018-03-24 08:15:45 +01:00
|
|
|
break;
|
2020-06-20 07:18:53 +02:00
|
|
|
case X86Local::MRM0X: case X86Local::MRM1X:
|
|
|
|
case X86Local::MRM2X: case X86Local::MRM3X:
|
|
|
|
case X86Local::MRM4X: case X86Local::MRM5X:
|
|
|
|
case X86Local::MRM6X: case X86Local::MRM7X:
|
|
|
|
filter = std::make_unique<ExtendedFilter>(true, Form - X86Local::MRM0X);
|
|
|
|
break;
|
2020-07-02 02:36:45 +02:00
|
|
|
case X86Local::MRMr0:
|
|
|
|
filter = std::make_unique<ExtendedRMFilter>(true, Form - X86Local::MRMr0);
|
|
|
|
break;
|
2018-03-24 08:15:45 +01:00
|
|
|
case X86Local::MRM0m: case X86Local::MRM1m:
|
|
|
|
case X86Local::MRM2m: case X86Local::MRM3m:
|
|
|
|
case X86Local::MRM4m: case X86Local::MRM5m:
|
|
|
|
case X86Local::MRM6m: case X86Local::MRM7m:
|
2019-08-15 17:54:37 +02:00
|
|
|
filter = std::make_unique<ExtendedFilter>(false, Form - X86Local::MRM0m);
|
2018-03-24 08:15:45 +01:00
|
|
|
break;
|
|
|
|
X86_INSTR_MRM_MAPPING
|
2019-08-15 17:54:37 +02:00
|
|
|
filter = std::make_unique<ExactFilter>(0xC0 + Form - X86Local::MRM_C0);
|
2018-03-24 08:15:45 +01:00
|
|
|
break;
|
|
|
|
} // switch (Form)
|
|
|
|
|
|
|
|
uint8_t opcodeToSet = Opcode;
|
2009-12-19 03:59:52 +01:00
|
|
|
|
2015-01-02 08:02:25 +01:00
|
|
|
unsigned AddressSize = 0;
|
|
|
|
switch (AdSize) {
|
|
|
|
case X86Local::AdSize16: AddressSize = 16; break;
|
|
|
|
case X86Local::AdSize32: AddressSize = 32; break;
|
|
|
|
case X86Local::AdSize64: AddressSize = 64; break;
|
|
|
|
}
|
|
|
|
|
2017-12-08 23:32:35 +01:00
|
|
|
assert(opcodeType && "Opcode type not set");
|
2009-12-19 03:59:52 +01:00
|
|
|
assert(filter && "Filter not set");
|
|
|
|
|
[X86] Merge the different CMOV instructions for each condition code into single instructions that store the condition code as an immediate.
Summary:
Reorder the condition code enum to match their encodings. Move it to MC layer so it can be used by the scheduler models.
This avoids needing an isel pattern for each condition code. And it removes
translation switches for converting between CMOV instructions and condition
codes.
Now the printer, encoder and disassembler take care of converting the immediate.
We use InstAliases to handle the assembly matching. But we print using the
asm string in the instruction definition. The instruction itself is marked
IsCodeGenOnly=1 to hide it from the assembly parser.
This does complicate the scheduler models a little since we can't assign the
A and BE instructions to a separate class now.
I plan to make similar changes for SETcc and Jcc.
Reviewers: RKSimon, spatel, lebedev.ri, andreadb, courbet
Reviewed By: RKSimon
Subscribers: gchatelet, hiraditya, kristina, lebedev.ri, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60041
llvm-svn: 357800
2019-04-05 21:27:41 +02:00
|
|
|
if (Form == X86Local::AddRegFrm || Form == X86Local::MRMSrcRegCC ||
|
2019-04-05 21:27:49 +02:00
|
|
|
Form == X86Local::MRMSrcMemCC || Form == X86Local::MRMXrCC ||
|
[X86] Merge the different Jcc instructions for each condition code into single instructions that store the condition code as an operand.
Summary:
This avoids needing an isel pattern for each condition code. And it removes translation switches for converting between Jcc instructions and condition codes.
Now the printer, encoder and disassembler take care of converting the immediate. We use InstAliases to handle the assembly matching. But we print using the asm string in the instruction definition. The instruction itself is marked IsCodeGenOnly=1 to hide it from the assembly parser.
Reviewers: spatel, lebedev.ri, courbet, gchatelet, RKSimon
Reviewed By: RKSimon
Subscribers: MatzeB, qcolombet, eraman, hiraditya, arphaman, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60228
llvm-svn: 357802
2019-04-05 21:28:09 +02:00
|
|
|
Form == X86Local::MRMXmCC || Form == X86Local::AddCCFrm) {
|
[X86] Merge the different CMOV instructions for each condition code into single instructions that store the condition code as an immediate.
Summary:
Reorder the condition code enum to match their encodings. Move it to MC layer so it can be used by the scheduler models.
This avoids needing an isel pattern for each condition code. And it removes
translation switches for converting between CMOV instructions and condition
codes.
Now the printer, encoder and disassembler take care of converting the immediate.
We use InstAliases to handle the assembly matching. But we print using the
asm string in the instruction definition. The instruction itself is marked
IsCodeGenOnly=1 to hide it from the assembly parser.
This does complicate the scheduler models a little since we can't assign the
A and BE instructions to a separate class now.
I plan to make similar changes for SETcc and Jcc.
Reviewers: RKSimon, spatel, lebedev.ri, andreadb, courbet
Reviewed By: RKSimon
Subscribers: gchatelet, hiraditya, kristina, lebedev.ri, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60041
llvm-svn: 357800
2019-04-05 21:27:41 +02:00
|
|
|
unsigned Count = Form == X86Local::AddRegFrm ? 8 : 16;
|
|
|
|
assert(((opcodeToSet % Count) == 0) && "ADDREG_FRM opcode not aligned");
|
2014-01-01 15:22:37 +01:00
|
|
|
|
|
|
|
uint8_t currentOpcode;
|
|
|
|
|
[X86] Merge the different CMOV instructions for each condition code into single instructions that store the condition code as an immediate.
Summary:
Reorder the condition code enum to match their encodings. Move it to MC layer so it can be used by the scheduler models.
This avoids needing an isel pattern for each condition code. And it removes
translation switches for converting between CMOV instructions and condition
codes.
Now the printer, encoder and disassembler take care of converting the immediate.
We use InstAliases to handle the assembly matching. But we print using the
asm string in the instruction definition. The instruction itself is marked
IsCodeGenOnly=1 to hide it from the assembly parser.
This does complicate the scheduler models a little since we can't assign the
A and BE instructions to a separate class now.
I plan to make similar changes for SETcc and Jcc.
Reviewers: RKSimon, spatel, lebedev.ri, andreadb, courbet
Reviewed By: RKSimon
Subscribers: gchatelet, hiraditya, kristina, lebedev.ri, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60041
llvm-svn: 357800
2019-04-05 21:27:41 +02:00
|
|
|
for (currentOpcode = opcodeToSet; currentOpcode < opcodeToSet + Count;
|
2014-01-01 15:22:37 +01:00
|
|
|
++currentOpcode)
|
2017-12-08 23:32:35 +01:00
|
|
|
tables.setTableFields(*opcodeType, insnContext(), currentOpcode, *filter,
|
2017-10-23 18:49:26 +02:00
|
|
|
UID, Is32Bit, OpPrefix == 0,
|
|
|
|
IgnoresVEX_L || EncodeRC,
|
2019-04-09 09:40:06 +02:00
|
|
|
IgnoresVEX_W, AddressSize);
|
2009-12-19 03:59:52 +01:00
|
|
|
} else {
|
2017-12-08 23:32:35 +01:00
|
|
|
tables.setTableFields(*opcodeType, insnContext(), opcodeToSet, *filter, UID,
|
2017-10-23 18:49:26 +02:00
|
|
|
Is32Bit, OpPrefix == 0, IgnoresVEX_L || EncodeRC,
|
2019-04-09 09:40:06 +02:00
|
|
|
IgnoresVEX_W, AddressSize);
|
2009-12-19 03:59:52 +01:00
|
|
|
}
|
2012-07-30 06:48:12 +02:00
|
|
|
|
2010-02-13 00:39:46 +01:00
|
|
|
#undef MAP
|
2009-12-19 03:59:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#define TYPE(str, type) if (s == str) return type;
|
|
|
|
OperandType RecognizableInstr::typeFromString(const std::string &s,
|
|
|
|
bool hasREX_WPrefix,
|
2014-02-02 10:25:09 +01:00
|
|
|
uint8_t OpSize) {
|
2009-12-19 03:59:52 +01:00
|
|
|
if(hasREX_WPrefix) {
|
|
|
|
// For instructions with a REX_W prefix, a declared 32-bit register encoding
|
|
|
|
// is special.
|
|
|
|
TYPE("GR32", TYPE_R32)
|
|
|
|
}
|
2014-02-02 10:25:09 +01:00
|
|
|
if(OpSize == X86Local::OpSize16) {
|
|
|
|
// For OpSize16 instructions, a declared 16-bit register or
|
2014-01-15 06:02:02 +01:00
|
|
|
// immediate encoding is special.
|
|
|
|
TYPE("GR16", TYPE_Rv)
|
2014-02-02 10:25:09 +01:00
|
|
|
} else if(OpSize == X86Local::OpSize32) {
|
|
|
|
// For OpSize32 instructions, a declared 32-bit register or
|
2009-12-19 03:59:52 +01:00
|
|
|
// immediate encoding is special.
|
2014-01-15 06:02:02 +01:00
|
|
|
TYPE("GR32", TYPE_Rv)
|
2009-12-19 03:59:52 +01:00
|
|
|
}
|
2017-01-16 07:49:03 +01:00
|
|
|
TYPE("i16mem", TYPE_M)
|
|
|
|
TYPE("i16imm", TYPE_IMM)
|
|
|
|
TYPE("i16i8imm", TYPE_IMM)
|
2014-01-15 06:02:02 +01:00
|
|
|
TYPE("GR16", TYPE_R16)
|
2020-07-16 08:50:29 +02:00
|
|
|
TYPE("GR16orGR32orGR64", TYPE_R16)
|
2017-01-16 07:49:03 +01:00
|
|
|
TYPE("i32mem", TYPE_M)
|
|
|
|
TYPE("i32imm", TYPE_IMM)
|
|
|
|
TYPE("i32i8imm", TYPE_IMM)
|
2014-01-15 06:02:02 +01:00
|
|
|
TYPE("GR32", TYPE_R32)
|
2013-10-14 06:55:01 +02:00
|
|
|
TYPE("GR32orGR64", TYPE_R32)
|
2017-01-16 07:49:03 +01:00
|
|
|
TYPE("i64mem", TYPE_M)
|
|
|
|
TYPE("i64i32imm", TYPE_IMM)
|
|
|
|
TYPE("i64i8imm", TYPE_IMM)
|
2009-12-19 03:59:52 +01:00
|
|
|
TYPE("GR64", TYPE_R64)
|
2017-01-16 07:49:03 +01:00
|
|
|
TYPE("i8mem", TYPE_M)
|
|
|
|
TYPE("i8imm", TYPE_IMM)
|
2019-08-07 07:34:27 +02:00
|
|
|
TYPE("u4imm", TYPE_UIMM8)
|
2015-01-21 09:15:54 +01:00
|
|
|
TYPE("u8imm", TYPE_UIMM8)
|
2019-03-18 22:33:59 +01:00
|
|
|
TYPE("i16u8imm", TYPE_UIMM8)
|
2015-01-25 03:21:16 +01:00
|
|
|
TYPE("i32u8imm", TYPE_UIMM8)
|
2019-03-18 22:33:59 +01:00
|
|
|
TYPE("i64u8imm", TYPE_UIMM8)
|
2009-12-19 03:59:52 +01:00
|
|
|
TYPE("GR8", TYPE_R8)
|
2017-01-16 07:49:03 +01:00
|
|
|
TYPE("VR128", TYPE_XMM)
|
|
|
|
TYPE("VR128X", TYPE_XMM)
|
|
|
|
TYPE("f128mem", TYPE_M)
|
|
|
|
TYPE("f256mem", TYPE_M)
|
|
|
|
TYPE("f512mem", TYPE_M)
|
|
|
|
TYPE("FR128", TYPE_XMM)
|
|
|
|
TYPE("FR64", TYPE_XMM)
|
|
|
|
TYPE("FR64X", TYPE_XMM)
|
|
|
|
TYPE("f64mem", TYPE_M)
|
|
|
|
TYPE("sdmem", TYPE_M)
|
|
|
|
TYPE("FR32", TYPE_XMM)
|
|
|
|
TYPE("FR32X", TYPE_XMM)
|
|
|
|
TYPE("f32mem", TYPE_M)
|
|
|
|
TYPE("ssmem", TYPE_M)
|
2009-12-19 03:59:52 +01:00
|
|
|
TYPE("RST", TYPE_ST)
|
2019-02-04 05:15:10 +01:00
|
|
|
TYPE("RSTi", TYPE_ST)
|
2017-01-16 07:49:03 +01:00
|
|
|
TYPE("i128mem", TYPE_M)
|
|
|
|
TYPE("i256mem", TYPE_M)
|
|
|
|
TYPE("i512mem", TYPE_M)
|
2020-01-09 20:01:55 +01:00
|
|
|
TYPE("i64i32imm_brtarget", TYPE_REL)
|
|
|
|
TYPE("i16imm_brtarget", TYPE_REL)
|
|
|
|
TYPE("i32imm_brtarget", TYPE_REL)
|
[X86] Merge the different CMOV instructions for each condition code into single instructions that store the condition code as an immediate.
Summary:
Reorder the condition code enum to match their encodings. Move it to MC layer so it can be used by the scheduler models.
This avoids needing an isel pattern for each condition code. And it removes
translation switches for converting between CMOV instructions and condition
codes.
Now the printer, encoder and disassembler take care of converting the immediate.
We use InstAliases to handle the assembly matching. But we print using the
asm string in the instruction definition. The instruction itself is marked
IsCodeGenOnly=1 to hide it from the assembly parser.
This does complicate the scheduler models a little since we can't assign the
A and BE instructions to a separate class now.
I plan to make similar changes for SETcc and Jcc.
Reviewers: RKSimon, spatel, lebedev.ri, andreadb, courbet
Reviewed By: RKSimon
Subscribers: gchatelet, hiraditya, kristina, lebedev.ri, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60041
llvm-svn: 357800
2019-04-05 21:27:41 +02:00
|
|
|
TYPE("ccode", TYPE_IMM)
|
2017-01-16 07:49:03 +01:00
|
|
|
TYPE("AVX512RC", TYPE_IMM)
|
2017-01-16 07:49:09 +01:00
|
|
|
TYPE("brtarget32", TYPE_REL)
|
|
|
|
TYPE("brtarget16", TYPE_REL)
|
|
|
|
TYPE("brtarget8", TYPE_REL)
|
2017-01-16 07:49:03 +01:00
|
|
|
TYPE("f80mem", TYPE_M)
|
|
|
|
TYPE("lea64_32mem", TYPE_M)
|
|
|
|
TYPE("lea64mem", TYPE_M)
|
2009-12-19 03:59:52 +01:00
|
|
|
TYPE("VR64", TYPE_MM64)
|
2017-01-16 07:49:03 +01:00
|
|
|
TYPE("i64imm", TYPE_IMM)
|
2015-01-08 08:41:30 +01:00
|
|
|
TYPE("anymem", TYPE_M)
|
2018-05-01 06:42:00 +02:00
|
|
|
TYPE("opaquemem", TYPE_M)
|
2020-07-02 02:36:45 +02:00
|
|
|
TYPE("sibmem", TYPE_MSIB)
|
2009-12-19 03:59:52 +01:00
|
|
|
TYPE("SEGMENT_REG", TYPE_SEGMENTREG)
|
|
|
|
TYPE("DEBUG_REG", TYPE_DEBUGREG)
|
2010-05-06 22:59:00 +02:00
|
|
|
TYPE("CONTROL_REG", TYPE_CONTROLREG)
|
2017-01-16 07:49:03 +01:00
|
|
|
TYPE("srcidx8", TYPE_SRCIDX)
|
|
|
|
TYPE("srcidx16", TYPE_SRCIDX)
|
|
|
|
TYPE("srcidx32", TYPE_SRCIDX)
|
|
|
|
TYPE("srcidx64", TYPE_SRCIDX)
|
|
|
|
TYPE("dstidx8", TYPE_DSTIDX)
|
|
|
|
TYPE("dstidx16", TYPE_DSTIDX)
|
|
|
|
TYPE("dstidx32", TYPE_DSTIDX)
|
|
|
|
TYPE("dstidx64", TYPE_DSTIDX)
|
|
|
|
TYPE("offset16_8", TYPE_MOFFS)
|
|
|
|
TYPE("offset16_16", TYPE_MOFFS)
|
|
|
|
TYPE("offset16_32", TYPE_MOFFS)
|
|
|
|
TYPE("offset32_8", TYPE_MOFFS)
|
|
|
|
TYPE("offset32_16", TYPE_MOFFS)
|
|
|
|
TYPE("offset32_32", TYPE_MOFFS)
|
|
|
|
TYPE("offset32_64", TYPE_MOFFS)
|
|
|
|
TYPE("offset64_8", TYPE_MOFFS)
|
|
|
|
TYPE("offset64_16", TYPE_MOFFS)
|
|
|
|
TYPE("offset64_32", TYPE_MOFFS)
|
|
|
|
TYPE("offset64_64", TYPE_MOFFS)
|
|
|
|
TYPE("VR256", TYPE_YMM)
|
|
|
|
TYPE("VR256X", TYPE_YMM)
|
|
|
|
TYPE("VR512", TYPE_ZMM)
|
|
|
|
TYPE("VK1", TYPE_VK)
|
|
|
|
TYPE("VK1WM", TYPE_VK)
|
|
|
|
TYPE("VK2", TYPE_VK)
|
|
|
|
TYPE("VK2WM", TYPE_VK)
|
|
|
|
TYPE("VK4", TYPE_VK)
|
|
|
|
TYPE("VK4WM", TYPE_VK)
|
|
|
|
TYPE("VK8", TYPE_VK)
|
|
|
|
TYPE("VK8WM", TYPE_VK)
|
|
|
|
TYPE("VK16", TYPE_VK)
|
|
|
|
TYPE("VK16WM", TYPE_VK)
|
|
|
|
TYPE("VK32", TYPE_VK)
|
|
|
|
TYPE("VK32WM", TYPE_VK)
|
|
|
|
TYPE("VK64", TYPE_VK)
|
|
|
|
TYPE("VK64WM", TYPE_VK)
|
2019-05-31 04:50:41 +02:00
|
|
|
TYPE("VK1Pair", TYPE_VK_PAIR)
|
|
|
|
TYPE("VK2Pair", TYPE_VK_PAIR)
|
|
|
|
TYPE("VK4Pair", TYPE_VK_PAIR)
|
|
|
|
TYPE("VK8Pair", TYPE_VK_PAIR)
|
|
|
|
TYPE("VK16Pair", TYPE_VK_PAIR)
|
2017-10-21 22:03:20 +02:00
|
|
|
TYPE("vx64mem", TYPE_MVSIBX)
|
|
|
|
TYPE("vx128mem", TYPE_MVSIBX)
|
|
|
|
TYPE("vx256mem", TYPE_MVSIBX)
|
|
|
|
TYPE("vy128mem", TYPE_MVSIBY)
|
|
|
|
TYPE("vy256mem", TYPE_MVSIBY)
|
|
|
|
TYPE("vx64xmem", TYPE_MVSIBX)
|
|
|
|
TYPE("vx128xmem", TYPE_MVSIBX)
|
|
|
|
TYPE("vx256xmem", TYPE_MVSIBX)
|
|
|
|
TYPE("vy128xmem", TYPE_MVSIBY)
|
|
|
|
TYPE("vy256xmem", TYPE_MVSIBY)
|
2018-06-06 21:15:12 +02:00
|
|
|
TYPE("vy512xmem", TYPE_MVSIBY)
|
|
|
|
TYPE("vz256mem", TYPE_MVSIBZ)
|
2017-10-21 22:03:20 +02:00
|
|
|
TYPE("vz512mem", TYPE_MVSIBZ)
|
2015-06-09 15:02:10 +02:00
|
|
|
TYPE("BNDR", TYPE_BNDR)
|
2020-07-02 02:36:45 +02:00
|
|
|
TYPE("TILE", TYPE_TMM)
|
2009-12-19 03:59:52 +01:00
|
|
|
errs() << "Unhandled type string " << s << "\n";
|
|
|
|
llvm_unreachable("Unhandled type string");
|
|
|
|
}
|
|
|
|
#undef TYPE
|
|
|
|
|
|
|
|
#define ENCODING(str, encoding) if (s == str) return encoding;
|
2014-02-02 10:25:09 +01:00
|
|
|
OperandEncoding
|
|
|
|
RecognizableInstr::immediateEncodingFromString(const std::string &s,
|
|
|
|
uint8_t OpSize) {
|
|
|
|
if(OpSize != X86Local::OpSize16) {
|
2009-12-19 03:59:52 +01:00
|
|
|
// For instructions without an OpSize prefix, a declared 16-bit register or
|
|
|
|
// immediate encoding is special.
|
|
|
|
ENCODING("i16imm", ENCODING_IW)
|
|
|
|
}
|
|
|
|
ENCODING("i32i8imm", ENCODING_IB)
|
2017-10-23 04:26:24 +02:00
|
|
|
ENCODING("AVX512RC", ENCODING_IRC)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("i16imm", ENCODING_Iv)
|
|
|
|
ENCODING("i16i8imm", ENCODING_IB)
|
|
|
|
ENCODING("i32imm", ENCODING_Iv)
|
|
|
|
ENCODING("i64i32imm", ENCODING_ID)
|
|
|
|
ENCODING("i64i8imm", ENCODING_IB)
|
|
|
|
ENCODING("i8imm", ENCODING_IB)
|
2019-08-07 07:34:27 +02:00
|
|
|
ENCODING("u4imm", ENCODING_IB)
|
2015-01-21 09:15:54 +01:00
|
|
|
ENCODING("u8imm", ENCODING_IB)
|
2019-03-18 22:33:59 +01:00
|
|
|
ENCODING("i16u8imm", ENCODING_IB)
|
2015-01-25 03:21:16 +01:00
|
|
|
ENCODING("i32u8imm", ENCODING_IB)
|
2019-03-18 22:33:59 +01:00
|
|
|
ENCODING("i64u8imm", ENCODING_IB)
|
2011-03-15 02:23:15 +01:00
|
|
|
// This is not a typo. Instructions like BLENDVPD put
|
|
|
|
// register IDs in 8-bit immediates nowadays.
|
2012-08-31 17:40:30 +02:00
|
|
|
ENCODING("FR32", ENCODING_IB)
|
|
|
|
ENCODING("FR64", ENCODING_IB)
|
2015-12-14 23:08:36 +01:00
|
|
|
ENCODING("FR128", ENCODING_IB)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("VR128", ENCODING_IB)
|
|
|
|
ENCODING("VR256", ENCODING_IB)
|
|
|
|
ENCODING("FR32X", ENCODING_IB)
|
|
|
|
ENCODING("FR64X", ENCODING_IB)
|
|
|
|
ENCODING("VR128X", ENCODING_IB)
|
|
|
|
ENCODING("VR256X", ENCODING_IB)
|
|
|
|
ENCODING("VR512", ENCODING_IB)
|
2020-07-02 02:36:45 +02:00
|
|
|
ENCODING("TILE", ENCODING_IB)
|
2009-12-19 03:59:52 +01:00
|
|
|
errs() << "Unhandled immediate encoding " << s << "\n";
|
|
|
|
llvm_unreachable("Unhandled immediate encoding");
|
|
|
|
}
|
|
|
|
|
2014-02-02 10:25:09 +01:00
|
|
|
OperandEncoding
|
|
|
|
RecognizableInstr::rmRegisterEncodingFromString(const std::string &s,
|
|
|
|
uint8_t OpSize) {
|
2014-01-01 15:22:37 +01:00
|
|
|
ENCODING("RST", ENCODING_FP)
|
2019-02-04 05:15:10 +01:00
|
|
|
ENCODING("RSTi", ENCODING_FP)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("GR16", ENCODING_RM)
|
2020-07-16 08:50:29 +02:00
|
|
|
ENCODING("GR16orGR32orGR64",ENCODING_RM)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("GR32", ENCODING_RM)
|
2013-10-14 06:55:01 +02:00
|
|
|
ENCODING("GR32orGR64", ENCODING_RM)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("GR64", ENCODING_RM)
|
|
|
|
ENCODING("GR8", ENCODING_RM)
|
|
|
|
ENCODING("VR128", ENCODING_RM)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("VR128X", ENCODING_RM)
|
2015-12-14 23:08:36 +01:00
|
|
|
ENCODING("FR128", ENCODING_RM)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("FR64", ENCODING_RM)
|
|
|
|
ENCODING("FR32", ENCODING_RM)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("FR64X", ENCODING_RM)
|
|
|
|
ENCODING("FR32X", ENCODING_RM)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("VR64", ENCODING_RM)
|
2011-03-15 02:23:15 +01:00
|
|
|
ENCODING("VR256", ENCODING_RM)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("VR256X", ENCODING_RM)
|
|
|
|
ENCODING("VR512", ENCODING_RM)
|
2013-12-16 14:52:35 +01:00
|
|
|
ENCODING("VK1", ENCODING_RM)
|
2015-04-21 16:38:31 +02:00
|
|
|
ENCODING("VK2", ENCODING_RM)
|
|
|
|
ENCODING("VK4", ENCODING_RM)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("VK8", ENCODING_RM)
|
|
|
|
ENCODING("VK16", ENCODING_RM)
|
2014-07-23 16:49:42 +02:00
|
|
|
ENCODING("VK32", ENCODING_RM)
|
|
|
|
ENCODING("VK64", ENCODING_RM)
|
2019-05-31 04:50:41 +02:00
|
|
|
ENCODING("VK1PAIR", ENCODING_RM)
|
|
|
|
ENCODING("VK2PAIR", ENCODING_RM)
|
|
|
|
ENCODING("VK4PAIR", ENCODING_RM)
|
|
|
|
ENCODING("VK8PAIR", ENCODING_RM)
|
|
|
|
ENCODING("VK16PAIR", ENCODING_RM)
|
2015-06-09 15:02:10 +02:00
|
|
|
ENCODING("BNDR", ENCODING_RM)
|
2020-07-02 02:36:45 +02:00
|
|
|
ENCODING("TILE", ENCODING_RM)
|
2009-12-19 03:59:52 +01:00
|
|
|
errs() << "Unhandled R/M register encoding " << s << "\n";
|
|
|
|
llvm_unreachable("Unhandled R/M register encoding");
|
|
|
|
}
|
|
|
|
|
2014-02-02 10:25:09 +01:00
|
|
|
OperandEncoding
|
|
|
|
RecognizableInstr::roRegisterEncodingFromString(const std::string &s,
|
|
|
|
uint8_t OpSize) {
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("GR16", ENCODING_REG)
|
2020-07-16 08:50:29 +02:00
|
|
|
ENCODING("GR16orGR32orGR64",ENCODING_REG)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("GR32", ENCODING_REG)
|
2013-10-14 06:55:01 +02:00
|
|
|
ENCODING("GR32orGR64", ENCODING_REG)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("GR64", ENCODING_REG)
|
|
|
|
ENCODING("GR8", ENCODING_REG)
|
|
|
|
ENCODING("VR128", ENCODING_REG)
|
2015-12-14 23:08:36 +01:00
|
|
|
ENCODING("FR128", ENCODING_REG)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("FR64", ENCODING_REG)
|
|
|
|
ENCODING("FR32", ENCODING_REG)
|
|
|
|
ENCODING("VR64", ENCODING_REG)
|
|
|
|
ENCODING("SEGMENT_REG", ENCODING_REG)
|
|
|
|
ENCODING("DEBUG_REG", ENCODING_REG)
|
2010-05-06 22:59:00 +02:00
|
|
|
ENCODING("CONTROL_REG", ENCODING_REG)
|
2011-03-15 02:23:15 +01:00
|
|
|
ENCODING("VR256", ENCODING_REG)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("VR256X", ENCODING_REG)
|
|
|
|
ENCODING("VR128X", ENCODING_REG)
|
|
|
|
ENCODING("FR64X", ENCODING_REG)
|
|
|
|
ENCODING("FR32X", ENCODING_REG)
|
|
|
|
ENCODING("VR512", ENCODING_REG)
|
2013-12-16 14:52:35 +01:00
|
|
|
ENCODING("VK1", ENCODING_REG)
|
2014-08-25 16:49:34 +02:00
|
|
|
ENCODING("VK2", ENCODING_REG)
|
|
|
|
ENCODING("VK4", ENCODING_REG)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("VK8", ENCODING_REG)
|
|
|
|
ENCODING("VK16", ENCODING_REG)
|
2014-07-23 16:49:42 +02:00
|
|
|
ENCODING("VK32", ENCODING_REG)
|
|
|
|
ENCODING("VK64", ENCODING_REG)
|
2019-05-31 04:50:41 +02:00
|
|
|
ENCODING("VK1Pair", ENCODING_REG)
|
|
|
|
ENCODING("VK2Pair", ENCODING_REG)
|
|
|
|
ENCODING("VK4Pair", ENCODING_REG)
|
|
|
|
ENCODING("VK8Pair", ENCODING_REG)
|
|
|
|
ENCODING("VK16Pair", ENCODING_REG)
|
2013-12-16 14:52:35 +01:00
|
|
|
ENCODING("VK1WM", ENCODING_REG)
|
2015-04-21 16:38:31 +02:00
|
|
|
ENCODING("VK2WM", ENCODING_REG)
|
|
|
|
ENCODING("VK4WM", ENCODING_REG)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("VK8WM", ENCODING_REG)
|
|
|
|
ENCODING("VK16WM", ENCODING_REG)
|
2015-04-21 16:38:31 +02:00
|
|
|
ENCODING("VK32WM", ENCODING_REG)
|
|
|
|
ENCODING("VK64WM", ENCODING_REG)
|
2015-06-09 15:02:10 +02:00
|
|
|
ENCODING("BNDR", ENCODING_REG)
|
2020-07-02 02:36:45 +02:00
|
|
|
ENCODING("TILE", ENCODING_REG)
|
2009-12-19 03:59:52 +01:00
|
|
|
errs() << "Unhandled reg/opcode register encoding " << s << "\n";
|
|
|
|
llvm_unreachable("Unhandled reg/opcode register encoding");
|
|
|
|
}
|
|
|
|
|
2014-02-02 10:25:09 +01:00
|
|
|
OperandEncoding
|
|
|
|
RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s,
|
|
|
|
uint8_t OpSize) {
|
2011-10-14 09:06:56 +02:00
|
|
|
ENCODING("GR32", ENCODING_VVVV)
|
|
|
|
ENCODING("GR64", ENCODING_VVVV)
|
2011-03-15 02:23:15 +01:00
|
|
|
ENCODING("FR32", ENCODING_VVVV)
|
2015-12-14 23:08:36 +01:00
|
|
|
ENCODING("FR128", ENCODING_VVVV)
|
2011-03-15 02:23:15 +01:00
|
|
|
ENCODING("FR64", ENCODING_VVVV)
|
|
|
|
ENCODING("VR128", ENCODING_VVVV)
|
|
|
|
ENCODING("VR256", ENCODING_VVVV)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("FR32X", ENCODING_VVVV)
|
|
|
|
ENCODING("FR64X", ENCODING_VVVV)
|
|
|
|
ENCODING("VR128X", ENCODING_VVVV)
|
|
|
|
ENCODING("VR256X", ENCODING_VVVV)
|
|
|
|
ENCODING("VR512", ENCODING_VVVV)
|
2013-12-16 14:52:35 +01:00
|
|
|
ENCODING("VK1", ENCODING_VVVV)
|
2014-07-21 16:54:21 +02:00
|
|
|
ENCODING("VK2", ENCODING_VVVV)
|
|
|
|
ENCODING("VK4", ENCODING_VVVV)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("VK8", ENCODING_VVVV)
|
|
|
|
ENCODING("VK16", ENCODING_VVVV)
|
2014-07-28 15:46:45 +02:00
|
|
|
ENCODING("VK32", ENCODING_VVVV)
|
|
|
|
ENCODING("VK64", ENCODING_VVVV)
|
2019-05-31 04:50:41 +02:00
|
|
|
ENCODING("VK1PAIR", ENCODING_VVVV)
|
|
|
|
ENCODING("VK2PAIR", ENCODING_VVVV)
|
|
|
|
ENCODING("VK4PAIR", ENCODING_VVVV)
|
|
|
|
ENCODING("VK8PAIR", ENCODING_VVVV)
|
|
|
|
ENCODING("VK16PAIR", ENCODING_VVVV)
|
2020-07-02 02:36:45 +02:00
|
|
|
ENCODING("TILE", ENCODING_VVVV)
|
2011-03-15 02:23:15 +01:00
|
|
|
errs() << "Unhandled VEX.vvvv register encoding " << s << "\n";
|
|
|
|
llvm_unreachable("Unhandled VEX.vvvv register encoding");
|
|
|
|
}
|
|
|
|
|
2014-02-02 10:25:09 +01:00
|
|
|
OperandEncoding
|
|
|
|
RecognizableInstr::writemaskRegisterEncodingFromString(const std::string &s,
|
|
|
|
uint8_t OpSize) {
|
2013-12-16 14:52:35 +01:00
|
|
|
ENCODING("VK1WM", ENCODING_WRITEMASK)
|
2014-07-21 16:54:21 +02:00
|
|
|
ENCODING("VK2WM", ENCODING_WRITEMASK)
|
|
|
|
ENCODING("VK4WM", ENCODING_WRITEMASK)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("VK8WM", ENCODING_WRITEMASK)
|
|
|
|
ENCODING("VK16WM", ENCODING_WRITEMASK)
|
2014-07-21 16:54:21 +02:00
|
|
|
ENCODING("VK32WM", ENCODING_WRITEMASK)
|
|
|
|
ENCODING("VK64WM", ENCODING_WRITEMASK)
|
2013-07-28 10:28:38 +02:00
|
|
|
errs() << "Unhandled mask register encoding " << s << "\n";
|
|
|
|
llvm_unreachable("Unhandled mask register encoding");
|
|
|
|
}
|
|
|
|
|
2014-02-02 10:25:09 +01:00
|
|
|
OperandEncoding
|
|
|
|
RecognizableInstr::memoryEncodingFromString(const std::string &s,
|
|
|
|
uint8_t OpSize) {
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("i16mem", ENCODING_RM)
|
|
|
|
ENCODING("i32mem", ENCODING_RM)
|
|
|
|
ENCODING("i64mem", ENCODING_RM)
|
|
|
|
ENCODING("i8mem", ENCODING_RM)
|
2010-09-29 04:57:56 +02:00
|
|
|
ENCODING("ssmem", ENCODING_RM)
|
|
|
|
ENCODING("sdmem", ENCODING_RM)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("f128mem", ENCODING_RM)
|
2010-09-29 04:57:56 +02:00
|
|
|
ENCODING("f256mem", ENCODING_RM)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("f512mem", ENCODING_RM)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("f64mem", ENCODING_RM)
|
|
|
|
ENCODING("f32mem", ENCODING_RM)
|
|
|
|
ENCODING("i128mem", ENCODING_RM)
|
2011-03-15 02:23:15 +01:00
|
|
|
ENCODING("i256mem", ENCODING_RM)
|
2013-07-28 10:28:38 +02:00
|
|
|
ENCODING("i512mem", ENCODING_RM)
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("f80mem", ENCODING_RM)
|
|
|
|
ENCODING("lea64_32mem", ENCODING_RM)
|
|
|
|
ENCODING("lea64mem", ENCODING_RM)
|
2015-01-08 08:41:30 +01:00
|
|
|
ENCODING("anymem", ENCODING_RM)
|
2018-05-01 06:42:00 +02:00
|
|
|
ENCODING("opaquemem", ENCODING_RM)
|
2020-07-02 02:36:45 +02:00
|
|
|
ENCODING("sibmem", ENCODING_SIB)
|
2017-01-16 06:44:25 +01:00
|
|
|
ENCODING("vx64mem", ENCODING_VSIB)
|
|
|
|
ENCODING("vx128mem", ENCODING_VSIB)
|
|
|
|
ENCODING("vx256mem", ENCODING_VSIB)
|
|
|
|
ENCODING("vy128mem", ENCODING_VSIB)
|
|
|
|
ENCODING("vy256mem", ENCODING_VSIB)
|
|
|
|
ENCODING("vx64xmem", ENCODING_VSIB)
|
|
|
|
ENCODING("vx128xmem", ENCODING_VSIB)
|
|
|
|
ENCODING("vx256xmem", ENCODING_VSIB)
|
|
|
|
ENCODING("vy128xmem", ENCODING_VSIB)
|
|
|
|
ENCODING("vy256xmem", ENCODING_VSIB)
|
2018-06-06 21:15:12 +02:00
|
|
|
ENCODING("vy512xmem", ENCODING_VSIB)
|
|
|
|
ENCODING("vz256mem", ENCODING_VSIB)
|
2017-01-16 06:44:25 +01:00
|
|
|
ENCODING("vz512mem", ENCODING_VSIB)
|
2009-12-19 03:59:52 +01:00
|
|
|
errs() << "Unhandled memory encoding " << s << "\n";
|
|
|
|
llvm_unreachable("Unhandled memory encoding");
|
|
|
|
}
|
|
|
|
|
2014-02-02 10:25:09 +01:00
|
|
|
OperandEncoding
|
|
|
|
RecognizableInstr::relocationEncodingFromString(const std::string &s,
|
|
|
|
uint8_t OpSize) {
|
|
|
|
if(OpSize != X86Local::OpSize16) {
|
2009-12-19 03:59:52 +01:00
|
|
|
// For instructions without an OpSize prefix, a declared 16-bit register or
|
|
|
|
// immediate encoding is special.
|
2020-01-09 20:01:55 +01:00
|
|
|
ENCODING("i16imm", ENCODING_IW)
|
2009-12-19 03:59:52 +01:00
|
|
|
}
|
2020-01-09 20:01:55 +01:00
|
|
|
ENCODING("i16imm", ENCODING_Iv)
|
|
|
|
ENCODING("i16i8imm", ENCODING_IB)
|
|
|
|
ENCODING("i32imm", ENCODING_Iv)
|
|
|
|
ENCODING("i32i8imm", ENCODING_IB)
|
|
|
|
ENCODING("i64i32imm", ENCODING_ID)
|
|
|
|
ENCODING("i64i8imm", ENCODING_IB)
|
|
|
|
ENCODING("i8imm", ENCODING_IB)
|
|
|
|
ENCODING("u8imm", ENCODING_IB)
|
|
|
|
ENCODING("i16u8imm", ENCODING_IB)
|
|
|
|
ENCODING("i32u8imm", ENCODING_IB)
|
|
|
|
ENCODING("i64u8imm", ENCODING_IB)
|
|
|
|
ENCODING("i64i32imm_brtarget", ENCODING_ID)
|
|
|
|
ENCODING("i16imm_brtarget", ENCODING_IW)
|
|
|
|
ENCODING("i32imm_brtarget", ENCODING_ID)
|
|
|
|
ENCODING("brtarget32", ENCODING_ID)
|
|
|
|
ENCODING("brtarget16", ENCODING_IW)
|
|
|
|
ENCODING("brtarget8", ENCODING_IB)
|
|
|
|
ENCODING("i64imm", ENCODING_IO)
|
|
|
|
ENCODING("offset16_8", ENCODING_Ia)
|
|
|
|
ENCODING("offset16_16", ENCODING_Ia)
|
|
|
|
ENCODING("offset16_32", ENCODING_Ia)
|
|
|
|
ENCODING("offset32_8", ENCODING_Ia)
|
|
|
|
ENCODING("offset32_16", ENCODING_Ia)
|
|
|
|
ENCODING("offset32_32", ENCODING_Ia)
|
|
|
|
ENCODING("offset32_64", ENCODING_Ia)
|
|
|
|
ENCODING("offset64_8", ENCODING_Ia)
|
|
|
|
ENCODING("offset64_16", ENCODING_Ia)
|
|
|
|
ENCODING("offset64_32", ENCODING_Ia)
|
|
|
|
ENCODING("offset64_64", ENCODING_Ia)
|
|
|
|
ENCODING("srcidx8", ENCODING_SI)
|
|
|
|
ENCODING("srcidx16", ENCODING_SI)
|
|
|
|
ENCODING("srcidx32", ENCODING_SI)
|
|
|
|
ENCODING("srcidx64", ENCODING_SI)
|
|
|
|
ENCODING("dstidx8", ENCODING_DI)
|
|
|
|
ENCODING("dstidx16", ENCODING_DI)
|
|
|
|
ENCODING("dstidx32", ENCODING_DI)
|
|
|
|
ENCODING("dstidx64", ENCODING_DI)
|
2009-12-19 03:59:52 +01:00
|
|
|
errs() << "Unhandled relocation encoding " << s << "\n";
|
|
|
|
llvm_unreachable("Unhandled relocation encoding");
|
|
|
|
}
|
|
|
|
|
2014-02-02 10:25:09 +01:00
|
|
|
OperandEncoding
|
|
|
|
RecognizableInstr::opcodeModifierEncodingFromString(const std::string &s,
|
|
|
|
uint8_t OpSize) {
|
2009-12-19 03:59:52 +01:00
|
|
|
ENCODING("GR32", ENCODING_Rv)
|
|
|
|
ENCODING("GR64", ENCODING_RO)
|
|
|
|
ENCODING("GR16", ENCODING_Rv)
|
|
|
|
ENCODING("GR8", ENCODING_RB)
|
[X86] Merge the different CMOV instructions for each condition code into single instructions that store the condition code as an immediate.
Summary:
Reorder the condition code enum to match their encodings. Move it to MC layer so it can be used by the scheduler models.
This avoids needing an isel pattern for each condition code. And it removes
translation switches for converting between CMOV instructions and condition
codes.
Now the printer, encoder and disassembler take care of converting the immediate.
We use InstAliases to handle the assembly matching. But we print using the
asm string in the instruction definition. The instruction itself is marked
IsCodeGenOnly=1 to hide it from the assembly parser.
This does complicate the scheduler models a little since we can't assign the
A and BE instructions to a separate class now.
I plan to make similar changes for SETcc and Jcc.
Reviewers: RKSimon, spatel, lebedev.ri, andreadb, courbet
Reviewed By: RKSimon
Subscribers: gchatelet, hiraditya, kristina, lebedev.ri, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60041
llvm-svn: 357800
2019-04-05 21:27:41 +02:00
|
|
|
ENCODING("ccode", ENCODING_CC)
|
2009-12-19 03:59:52 +01:00
|
|
|
errs() << "Unhandled opcode modifier encoding " << s << "\n";
|
|
|
|
llvm_unreachable("Unhandled opcode modifier encoding");
|
|
|
|
}
|
2009-12-19 05:16:48 +01:00
|
|
|
#undef ENCODING
|