mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-26 05:00:26 +00:00
implement (and document!) the first kind of MC assembler alias, which
just remaps one mnemonic to another. Convert a few of the X86 aliases from .cpp to .td code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117815 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
905b8f7614
commit
674c1dcca2
@ -1878,15 +1878,64 @@ We've tried hard to automate the generation of the assembler from the .td files
|
||||
part of the manual and repetitive data entry can be factored and shared with the
|
||||
compiler.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection" id="na_instparsing">Instruction Parsing</div>
|
||||
|
||||
<div class="doc_text"><p>To Be Written</p></div>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection" id="na_instaliases">
|
||||
Instruction Alias Processing
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
<p>Once the instruction is parsed, it enters the MatchInstructionImpl function.
|
||||
The MatchInstructionImpl function performs alias processing and then does
|
||||
actual matching.</p>
|
||||
|
||||
<p>Alias processing if the phase that canonicalizes different lexical forms of
|
||||
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
|
||||
order that they are processed (which is in order from simplest/weakest to most
|
||||
complex/powerful). Generally you want to use the first alias mechanism that
|
||||
meets the needs of your instruction, because it will allow a more concise
|
||||
description.</p>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">Mnemonic Aliases</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>The first phase of alias processing is simple instruction mneomonic
|
||||
remapping for classes of instructions which are allowed with two different
|
||||
mneomonics. 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
|
||||
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:
|
||||
</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
def : MnemonicAlias<"cbw", "cbtw">;
|
||||
def : MnemonicAlias<"smovq", "movsq">;
|
||||
def : MnemonicAlias<"fldcww", "fldcw">;
|
||||
def : MnemonicAlias<"fucompi", "fucomip">;
|
||||
def : MnemonicAlias<"ud2a", "ud2">;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>... and many others. With a MnemonicAlias definition, the mnemonic is
|
||||
remapped simply and directly.</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<a name="proepicode">Prolog/Epilog Code Insertion</a>
|
||||
</div>
|
||||
<div class="doc_subsection" id="na_matching">Instruction Matching</div>
|
||||
|
||||
<div class="doc_text"><p>To Be Written</p></div>
|
||||
|
||||
|
||||
|
@ -530,6 +530,25 @@ class AsmParser {
|
||||
def DefaultAsmParser : AsmParser;
|
||||
|
||||
|
||||
/// MnemonicAlias - This class allows targets to define assembler mnemonic
|
||||
/// aliases. This should be used when all forms of one mnemonic are accepted
|
||||
/// with a different mnemonic. For example, X86 allows:
|
||||
/// sal %al, 1 -> shl %al, 1
|
||||
/// sal %ax, %cl -> shl %ax, %cl
|
||||
/// sal %eax, %cl -> shl %eax, %cl
|
||||
/// etc. Though "sal" is accepted with many forms, all of them are directly
|
||||
/// translated to a shl, so it can be handled with (in the case of X86, it
|
||||
/// actually has one for each suffix as well):
|
||||
/// def : MnemonicAlias<"sal", "shl">;
|
||||
///
|
||||
/// Mnemonic aliases are mapped before any other translation in the match phase.
|
||||
///
|
||||
class MnemonicAlias<string From, string To> {
|
||||
string FromMnemonic = From;
|
||||
string ToMnemonic = To;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AsmWriter - This class can be implemented by targets that need to customize
|
||||
// the format of the .s file writer.
|
||||
|
@ -632,17 +632,6 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
|
||||
.Case("repe", "rep")
|
||||
.Case("repz", "rep")
|
||||
.Case("repnz", "repne")
|
||||
.Case("iret", "iretl")
|
||||
.Case("sysret", "sysretl")
|
||||
.Case("cbw", "cbtw")
|
||||
.Case("cwd", "cwtd")
|
||||
.Case("cdq", "cltd")
|
||||
.Case("cwde", "cwtl")
|
||||
.Case("cdqe", "cltq")
|
||||
.Case("smovb", "movsb")
|
||||
.Case("smovw", "movsw")
|
||||
.Case("smovl", "movsl")
|
||||
.Case("smovq", "movsq")
|
||||
.Case("push", Is64Bit ? "pushq" : "pushl")
|
||||
.Case("pop", Is64Bit ? "popq" : "popl")
|
||||
.Case("pushf", Is64Bit ? "pushfq" : "pushfl")
|
||||
@ -704,14 +693,10 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
|
||||
.Case("movzx", "movzb") // FIXME: Not correct.
|
||||
.Case("fildq", "fildll")
|
||||
.Case("fcompi", "fcomip")
|
||||
.Case("fucompi", "fucomip")
|
||||
.Case("fldcww", "fldcw")
|
||||
.Case("fnstcww", "fnstcw")
|
||||
.Case("fstcww", "fstcw")
|
||||
.Case("fnstsww", "fnstsw")
|
||||
.Case("fstsww", "fstsw")
|
||||
.Case("verrw", "verr")
|
||||
.Case("ud2a", "ud2")
|
||||
.Default(Name);
|
||||
|
||||
// FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
|
||||
|
@ -1254,3 +1254,26 @@ include "X86InstrSystem.td"
|
||||
// Compiler Pseudo Instructions and Pat Patterns
|
||||
include "X86InstrCompiler.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Assembler Aliases
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def : MnemonicAlias<"iret", "iretl">;
|
||||
def : MnemonicAlias<"sysret", "sysretl">;
|
||||
def : MnemonicAlias<"cbw", "cbtw">;
|
||||
def : MnemonicAlias<"cwd", "cwtd">;
|
||||
def : MnemonicAlias<"cdq", "cltd">;
|
||||
def : MnemonicAlias<"cwde", "cwtl">;
|
||||
def : MnemonicAlias<"cdqe", "cltq">;
|
||||
def : MnemonicAlias<"smovb", "movsb">;
|
||||
def : MnemonicAlias<"smovw", "movsw">;
|
||||
def : MnemonicAlias<"smovl", "movsl">;
|
||||
def : MnemonicAlias<"smovq", "movsq">;
|
||||
|
||||
def : MnemonicAlias<"fldcww", "fldcw">;
|
||||
def : MnemonicAlias<"fucompi", "fucomip">;
|
||||
def : MnemonicAlias<"ud2a", "ud2">;
|
||||
def : MnemonicAlias<"verrw", "verr">;
|
||||
|
||||
|
||||
|
||||
|
@ -1514,6 +1514,26 @@ static void EmitComputeAvailableFeatures(CodeGenTarget &Target,
|
||||
OS << "}\n\n";
|
||||
}
|
||||
|
||||
/// EmitMnemonicAliases - If the target has any MnemonicAlias<> definitions,
|
||||
/// emit them.
|
||||
static void EmitMnemonicAliases(raw_ostream &OS) {
|
||||
std::vector<Record*> Aliases =
|
||||
Records.getAllDerivedDefinitions("MnemonicAlias");
|
||||
if (Aliases.empty()) return;
|
||||
|
||||
OS << " // Process all MnemonicAliases to remap the mnemonic.\n";
|
||||
std::vector<StringMatcher::StringPair> Cases;
|
||||
for (unsigned i = 0, e = Aliases.size(); i != e; ++i) {
|
||||
Record *R = Aliases[i];
|
||||
Cases.push_back(std::make_pair(R->getValueAsString("FromMnemonic"),
|
||||
"Mnemonic = \"" +
|
||||
R->getValueAsString("ToMnemonic") +
|
||||
"\"; break;"));
|
||||
}
|
||||
|
||||
StringMatcher("Mnemonic", Cases, OS).Emit();
|
||||
}
|
||||
|
||||
void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
CodeGenTarget Target;
|
||||
Record *AsmParser = Target.getAsmParser();
|
||||
@ -1701,6 +1721,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
OS << " // Get the current feature set.\n";
|
||||
OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n";
|
||||
|
||||
OS << " // Get the instruction mnemonic, which is the first token.\n";
|
||||
OS << " StringRef Mnemonic = ((" << Target.getName()
|
||||
<< "Operand*)Operands[0])->getToken();\n\n";
|
||||
|
||||
EmitMnemonicAliases(OS);
|
||||
|
||||
// Emit code to compute the class list for this operand vector.
|
||||
OS << " // Eliminate obvious mismatches.\n";
|
||||
OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n";
|
||||
@ -1725,10 +1751,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
|
||||
<< "i != e; ++i)\n";
|
||||
OS << " Classes[i] = InvalidMatchClass;\n\n";
|
||||
|
||||
OS << " // Get the instruction mnemonic, which is the first token.\n";
|
||||
OS << " StringRef Mnemonic = ((" << Target.getName()
|
||||
<< "Operand*)Operands[0])->getToken();\n\n";
|
||||
|
||||
OS << " // Some state to try to produce better error messages.\n";
|
||||
OS << " bool HadMatchOtherThanFeatures = false;\n\n";
|
||||
OS << " // Set ErrorInfo to the operand that mismatches if it is \n";
|
||||
|
Loading…
Reference in New Issue
Block a user