mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
Implement (and document!) support for MnemonicAlias's to have Requires
directives, allowing things like this: def : MnemonicAlias<"pop", "popl">, Requires<[In32BitMode]>; def : MnemonicAlias<"pop", "popq">, Requires<[In64BitMode]>; Move the rest of the X86 MnemonicAliases over to the .td file. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117830 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8cc0a6b788
commit
693173feef
@ -1896,7 +1896,7 @@ compiler.</p>
|
|||||||
The MatchInstructionImpl function performs alias processing and then does
|
The MatchInstructionImpl function performs alias processing and then does
|
||||||
actual matching.</p>
|
actual matching.</p>
|
||||||
|
|
||||||
<p>Alias processing if the phase that canonicalizes different lexical forms of
|
<p>Alias processing is the phase that canonicalizes different lexical forms of
|
||||||
the same instructions down to one representation. There are several different
|
the same instructions down to one representation. There are several different
|
||||||
kinds of alias that are possible to implement and they are listed below in the
|
kinds of alias that are possible to implement and they are listed below in the
|
||||||
order that they are processed (which is in order from simplest/weakest to most
|
order that they are processed (which is in order from simplest/weakest to most
|
||||||
@ -1911,7 +1911,7 @@ description.</p>
|
|||||||
|
|
||||||
<p>The first phase of alias processing is simple instruction mneomonic
|
<p>The first phase of alias processing is simple instruction mneomonic
|
||||||
remapping for classes of instructions which are allowed with two different
|
remapping for classes of instructions which are allowed with two different
|
||||||
mneomonics. This phase is a simple and unconditionally remapping from one input
|
mnemonics. This phase is a simple and unconditionally remapping from one input
|
||||||
mnemonic to one output mnemonic. It isn't possible for this form of alias to
|
mnemonic to one output mnemonic. It isn't possible for this form of alias to
|
||||||
look at the operands at all, so the remapping must apply for all forms of a
|
look at the operands at all, so the remapping must apply for all forms of a
|
||||||
given mnemonic. Mnemonic aliases are defined simply, for example X86 has:
|
given mnemonic. Mnemonic aliases are defined simply, for example X86 has:
|
||||||
@ -1928,7 +1928,19 @@ def : MnemonicAlias<"ud2a", "ud2">;
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>... and many others. With a MnemonicAlias definition, the mnemonic is
|
<p>... and many others. With a MnemonicAlias definition, the mnemonic is
|
||||||
remapped simply and directly.</p>
|
remapped simply and directly. Though MnemonicAlias's can't look at any aspect
|
||||||
|
of the instruction (such as the operands) they can depend on global modes (the
|
||||||
|
same ones supported by the matcher), through a Requires clause:</p>
|
||||||
|
|
||||||
|
<div class="doc_code">
|
||||||
|
<pre>
|
||||||
|
def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>;
|
||||||
|
def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>;
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>In this example, the mnemonic gets mapped into different a new one depending
|
||||||
|
on the current instruction set.</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -541,11 +541,18 @@ def DefaultAsmParser : AsmParser;
|
|||||||
/// actually has one for each suffix as well):
|
/// actually has one for each suffix as well):
|
||||||
/// def : MnemonicAlias<"sal", "shl">;
|
/// def : MnemonicAlias<"sal", "shl">;
|
||||||
///
|
///
|
||||||
/// Mnemonic aliases are mapped before any other translation in the match phase.
|
/// Mnemonic aliases are mapped before any other translation in the match phase,
|
||||||
|
/// and do allow Requires predicates, e.g.:
|
||||||
|
///
|
||||||
|
/// def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>;
|
||||||
|
/// def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>;
|
||||||
///
|
///
|
||||||
class MnemonicAlias<string From, string To> {
|
class MnemonicAlias<string From, string To> {
|
||||||
string FromMnemonic = From;
|
string FromMnemonic = From;
|
||||||
string ToMnemonic = To;
|
string ToMnemonic = To;
|
||||||
|
|
||||||
|
// Predicates - Predicates that must be true for this remapping to happen.
|
||||||
|
list<Predicate> Predicates = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -620,16 +620,10 @@ X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
|
|||||||
bool X86ATTAsmParser::
|
bool X86ATTAsmParser::
|
||||||
ParseInstruction(StringRef Name, SMLoc NameLoc,
|
ParseInstruction(StringRef Name, SMLoc NameLoc,
|
||||||
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
|
||||||
// FIXME: Hack to recognize some aliases.
|
// FIXME: This is not correct at all.
|
||||||
StringRef PatchedName = StringSwitch<StringRef>(Name)
|
if (Name == "movzx") Name = "movzb";
|
||||||
.Case("push", Is64Bit ? "pushq" : "pushl")
|
|
||||||
.Case("pop", Is64Bit ? "popq" : "popl")
|
StringRef PatchedName = Name;
|
||||||
.Case("pushf", Is64Bit ? "pushfq" : "pushfl")
|
|
||||||
.Case("popf", Is64Bit ? "popfq" : "popfl")
|
|
||||||
.Case("retl", Is64Bit ? "retl" : "ret")
|
|
||||||
.Case("retq", Is64Bit ? "ret" : "retq")
|
|
||||||
.Case("movzx", "movzb") // FIXME: Not correct.
|
|
||||||
.Default(Name);
|
|
||||||
|
|
||||||
// FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
|
// FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
|
||||||
const MCExpr *ExtraImmOp = 0;
|
const MCExpr *ExtraImmOp = 0;
|
||||||
@ -714,9 +708,9 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
|
|||||||
|
|
||||||
// Determine whether this is an instruction prefix.
|
// Determine whether this is an instruction prefix.
|
||||||
bool isPrefix =
|
bool isPrefix =
|
||||||
PatchedName == "lock" || PatchedName == "rep" ||
|
Name == "lock" || Name == "rep" ||
|
||||||
PatchedName == "repe" || PatchedName == "repz" ||
|
Name == "repe" || Name == "repz" ||
|
||||||
PatchedName == "repne" || PatchedName == "repnz";
|
Name == "repne" || Name == "repnz";
|
||||||
|
|
||||||
|
|
||||||
// This does the actual operand parsing. Don't parse any more if we have a
|
// This does the actual operand parsing. Don't parse any more if we have a
|
||||||
|
@ -1266,13 +1266,25 @@ def : MnemonicAlias<"cdq", "cltd">;
|
|||||||
def : MnemonicAlias<"cwde", "cwtl">;
|
def : MnemonicAlias<"cwde", "cwtl">;
|
||||||
def : MnemonicAlias<"cdqe", "cltq">;
|
def : MnemonicAlias<"cdqe", "cltq">;
|
||||||
|
|
||||||
def : MnemonicAlias<"pushfd", "pushfl">;
|
def : MnemonicAlias<"pop", "popl">, Requires<[In32BitMode]>;
|
||||||
|
def : MnemonicAlias<"pop", "popq">, Requires<[In64BitMode]>;
|
||||||
|
def : MnemonicAlias<"popf", "popfl">, Requires<[In32BitMode]>;
|
||||||
|
def : MnemonicAlias<"popf", "popfq">, Requires<[In64BitMode]>;
|
||||||
def : MnemonicAlias<"popfd", "popfl">;
|
def : MnemonicAlias<"popfd", "popfl">;
|
||||||
|
|
||||||
|
def : MnemonicAlias<"push", "pushl">, Requires<[In32BitMode]>;
|
||||||
|
def : MnemonicAlias<"push", "pushq">, Requires<[In64BitMode]>;
|
||||||
|
def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>;
|
||||||
|
def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>;
|
||||||
|
def : MnemonicAlias<"pushfd", "pushfl">;
|
||||||
|
|
||||||
def : MnemonicAlias<"repe", "rep">;
|
def : MnemonicAlias<"repe", "rep">;
|
||||||
def : MnemonicAlias<"repz", "rep">;
|
def : MnemonicAlias<"repz", "rep">;
|
||||||
def : MnemonicAlias<"repnz", "repne">;
|
def : MnemonicAlias<"repnz", "repne">;
|
||||||
|
|
||||||
|
def : MnemonicAlias<"retl", "ret">, Requires<[In32BitMode]>;
|
||||||
|
def : MnemonicAlias<"retq", "ret">, Requires<[In64BitMode]>;
|
||||||
|
|
||||||
def : MnemonicAlias<"salb", "shlb">;
|
def : MnemonicAlias<"salb", "shlb">;
|
||||||
def : MnemonicAlias<"salw", "shlw">;
|
def : MnemonicAlias<"salw", "shlw">;
|
||||||
def : MnemonicAlias<"sall", "shll">;
|
def : MnemonicAlias<"sall", "shll">;
|
||||||
|
@ -587,7 +587,7 @@ private:
|
|||||||
|
|
||||||
SubtargetFeatureInfo *&Entry = SubtargetFeatures[Def];
|
SubtargetFeatureInfo *&Entry = SubtargetFeatures[Def];
|
||||||
if (!Entry) {
|
if (!Entry) {
|
||||||
Entry = new SubtargetFeatureInfo;
|
Entry = new SubtargetFeatureInfo();
|
||||||
Entry->TheDef = Def;
|
Entry->TheDef = Def;
|
||||||
Entry->Index = SubtargetFeatures.size() - 1;
|
Entry->Index = SubtargetFeatures.size() - 1;
|
||||||
Entry->EnumName = "Feature_" + Def->getName();
|
Entry->EnumName = "Feature_" + Def->getName();
|
||||||
@ -1514,6 +1514,35 @@ static void EmitComputeAvailableFeatures(CodeGenTarget &Target,
|
|||||||
OS << "}\n\n";
|
OS << "}\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string GetAliasRequiredFeatures(Record *R) {
|
||||||
|
// FIXME: This is a total hack.
|
||||||
|
std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates");
|
||||||
|
|
||||||
|
std::string Result;
|
||||||
|
unsigned NumFeatures = 0;
|
||||||
|
for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) {
|
||||||
|
Record *Pred = ReqFeatures[i];
|
||||||
|
|
||||||
|
// FIXME: Total hack; for now, we just limit ourselves to In32BitMode
|
||||||
|
// and In64BitMode, because we aren't going to have the right feature
|
||||||
|
// masks for SSE and friends. We need to decide what we are going to do
|
||||||
|
// about CPU subtypes to implement this the right way.
|
||||||
|
if (Pred->getName() != "In32BitMode" &&
|
||||||
|
Pred->getName() != "In64BitMode")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (NumFeatures)
|
||||||
|
Result += '|';
|
||||||
|
|
||||||
|
Result += "Feature_" + Pred->getName();
|
||||||
|
++NumFeatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NumFeatures > 1)
|
||||||
|
Result = '(' + Result + ')';
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
/// EmitMnemonicAliases - If the target has any MnemonicAlias<> definitions,
|
/// EmitMnemonicAliases - If the target has any MnemonicAlias<> definitions,
|
||||||
/// emit a function for them and return true, otherwise return false.
|
/// emit a function for them and return true, otherwise return false.
|
||||||
static bool EmitMnemonicAliases(raw_ostream &OS) {
|
static bool EmitMnemonicAliases(raw_ostream &OS) {
|
||||||
@ -1539,22 +1568,45 @@ static bool EmitMnemonicAliases(raw_ostream &OS) {
|
|||||||
for (std::map<std::string, std::vector<Record*> >::iterator
|
for (std::map<std::string, std::vector<Record*> >::iterator
|
||||||
I = AliasesFromMnemonic.begin(), E = AliasesFromMnemonic.end();
|
I = AliasesFromMnemonic.begin(), E = AliasesFromMnemonic.end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
const std::string &From = I->first;
|
|
||||||
const std::vector<Record*> &ToVec = I->second;
|
const std::vector<Record*> &ToVec = I->second;
|
||||||
|
|
||||||
// If there is only one destination mnemonic, generate simple code.
|
// Loop through each alias and emit code that handles each case. If there
|
||||||
if (ToVec.size() == 1) {
|
// are two instructions without predicates, emit an error. If there is one,
|
||||||
Cases.push_back(std::make_pair(From, "Mnemonic = \"" +
|
// emit it last.
|
||||||
ToVec[0]->getValueAsString("ToMnemonic") +
|
std::string MatchCode;
|
||||||
"\"; return;"));
|
int AliasWithNoPredicate = -1;
|
||||||
continue;
|
|
||||||
|
for (unsigned i = 0, e = ToVec.size(); i != e; ++i) {
|
||||||
|
Record *R = ToVec[i];
|
||||||
|
std::string FeatureMask = GetAliasRequiredFeatures(R);
|
||||||
|
|
||||||
|
// If this unconditionally matches, remember it for later and diagnose
|
||||||
|
// duplicates.
|
||||||
|
if (FeatureMask.empty()) {
|
||||||
|
if (AliasWithNoPredicate != -1) {
|
||||||
|
// We can't have two aliases from the same mnemonic with no predicate.
|
||||||
|
PrintError(ToVec[AliasWithNoPredicate]->getLoc(),
|
||||||
|
"two MnemonicAliases with the same 'from' mnemonic!");
|
||||||
|
PrintError(R->getLoc(), "this is the other MnemonicAliases.");
|
||||||
|
throw std::string("ERROR: Invalid MnemonicAliases definitions!");
|
||||||
|
}
|
||||||
|
|
||||||
|
AliasWithNoPredicate = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MatchCode += "if ((Features & " + FeatureMask + ") == "+FeatureMask+")\n";
|
||||||
|
MatchCode += " Mnemonic = \"" +R->getValueAsString("ToMnemonic")+"\";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, diagnose an error, can't have two aliases from the same
|
if (AliasWithNoPredicate != -1) {
|
||||||
// mnemonic.
|
Record *R = ToVec[AliasWithNoPredicate];
|
||||||
PrintError(ToVec[0]->getLoc(), "two MnemonicAliases with the same 'from' mnemonic!");
|
MatchCode += "Mnemonic = \"" + R->getValueAsString("ToMnemonic") + "\";";
|
||||||
PrintError(ToVec[1]->getLoc(), "this is the other MnemonicAliases.");
|
}
|
||||||
throw std::string("ERROR: Invalid MnemonicAliases definitions!");
|
|
||||||
|
MatchCode += "return;";
|
||||||
|
|
||||||
|
Cases.push_back(std::make_pair(I->first, MatchCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user