generalize alias support to allow the result of an alias to
add fixed immediate values.  Move the aad and aam aliases to
use this, and document it.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118350 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/docs/CodeGenerator.html b/docs/CodeGenerator.html
index d4e932a..376b91c 100644
--- a/docs/CodeGenerator.html
+++ b/docs/CodeGenerator.html
@@ -1998,7 +1998,15 @@
 <p>This example also shows that tied operands are only listed once.  In the X86
 backend, XOR8rr has two input GR8's and one output GR8 (where an input is tied
 to the output).  InstAliases take a flattened operand list without duplicates
-for tied operands.</p>
+for tied operands.  The result of an instruction alias can also use immediates,
+which are added as simple immediate operands in the result, for example:</p>
+
+<div class="doc_code">
+<pre>
+def : InstAlias&lt;"aad", (AAD8i8 10)&gt;;
+</pre>
+</div>
+
 
 <p>Instruction aliases can also have a Requires clause to make them
 subtarget specific.</p>
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 4ab25cf..9ab6b56 100644
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -752,6 +752,22 @@
   if (getLexer().is(AsmToken::EndOfStatement))
     Parser.Lex(); // Consume the EndOfStatement
 
+  // This is a terrible hack to handle "out[bwl]? %al, (%dx)" ->
+  // "outb %al, %dx".  Out doesn't take a memory form, but this is a widely
+  // documented form in various unofficial manuals, so a lot of code uses it.
+  if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") &&
+      Operands.size() == 3) {
+    X86Operand &Op = *(X86Operand*)Operands.back();
+    if (Op.isMem() && Op.Mem.SegReg == 0 &&
+        isa<MCConstantExpr>(Op.Mem.Disp) &&
+        cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 &&
+        Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
+      SMLoc Loc = Op.getEndLoc();
+      Operands.back() = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
+      delete &Op;
+    }
+  }
+  
   // FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>.  Canonicalize to
   // "shift <op>".
   if ((Name.startswith("shr") || Name.startswith("sar") ||
@@ -781,20 +797,6 @@
                     X86Operand::CreateImm(One, NameLoc, NameLoc));
   }
 
-  // FIXME: Hack to handle "out[bwl]? %al, (%dx)" -> "outb %al, %dx".
-  if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") &&
-      Operands.size() == 3) {
-    X86Operand &Op = *(X86Operand*)Operands.back();
-    if (Op.isMem() && Op.Mem.SegReg == 0 &&
-        isa<MCConstantExpr>(Op.Mem.Disp) &&
-        cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 &&
-        Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
-      SMLoc Loc = Op.getEndLoc();
-      Operands.back() = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
-      delete &Op;
-    }
-  }
-
   // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
   // "f{mul*,add*,sub*,div*} $op"
   if ((Name.startswith("fmul") || Name.startswith("fadd") ||
@@ -839,13 +841,6 @@
                                              NameLoc, NameLoc));
   }
 
-  // FIXME: Hack to handle recognize "aa[dm]" -> "aa[dm] $0xA".
-  if ((Name.startswith("aad") || Name.startswith("aam")) &&
-      Operands.size() == 1) {
-    const MCExpr *A = MCConstantExpr::Create(0xA, getParser().getContext());
-    Operands.push_back(X86Operand::CreateImm(A, NameLoc, NameLoc));
-  }
-
   return false;
 }
 
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index 125da18..7fec014 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -1367,6 +1367,10 @@
 // Assembler Instruction Aliases
 //===----------------------------------------------------------------------===//
 
+// aad/aam default to base 10 if no operand is specified.
+def : InstAlias<"aad", (AAD8i8 10)>;
+def : InstAlias<"aam", (AAM8i8 10)>;
+
 // clr aliases.
 def : InstAlias<"clrb $reg", (XOR8rr  GR8 :$reg, GR8 :$reg)>;
 def : InstAlias<"clrw $reg", (XOR16rr GR16:$reg, GR16:$reg)>;
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 23d370c..4686614 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -270,7 +270,11 @@
       
       /// TiedOperand - This represents a result operand that is a duplicate of
       /// a previous result operand.
-      TiedOperand
+      TiedOperand,
+      
+      /// ImmOperand - This represents an immediate value that is dumped into
+      /// the operand.
+      ImmOperand
     } Kind;
     
     union {
@@ -281,6 +285,9 @@
       /// TiedOperandNum - This is the (earlier) result operand that should be
       /// copied from.
       unsigned TiedOperandNum;
+      
+      /// ImmVal - This is the immediate value added to the instruction.
+      int64_t ImmVal;
     };
     
     /// OpInfo - This is the information about the instruction operand that is
@@ -304,6 +311,15 @@
       X.OpInfo = Op;
       return X;
     }
+    
+    static ResOperand getImmOp(int64_t Val,
+                               const CGIOperandList::OperandInfo *Op) {
+      ResOperand X;
+      X.Kind = ImmOperand;
+      X.ImmVal = Val;
+      X.OpInfo = Op;
+      return X;
+    }
   };
 
   /// TheDef - This is the definition of the instruction or InstAlias that this
@@ -538,16 +554,6 @@
     AsmOperand &Op = AsmOperands[i];
     errs() << "  op[" << i << "] = " << Op.Class->ClassName << " - ";
     errs() << '\"' << Op.Token << "\"\n";
-#if 0
-    if (!Op.OperandInfo) {
-      errs() << "(singleton register)\n";
-      continue;
-    }
-
-    const CGIOperandList::OperandInfo &OI = *Op.OperandInfo;
-    errs() << OI.Name << " " << OI.Rec->getName()
-           << " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n";
-#endif
   }
 }
 
@@ -1174,7 +1180,8 @@
    
   // Set up the operand class.
   for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i)
-    if (CGA.ResultOperands[i].Name == OperandName) {
+    if (CGA.ResultOperands[i].isRecord() &&
+        CGA.ResultOperands[i].getName() == OperandName) {
       // It's safe to go with the first one we find, because CodeGenInstAlias
       // validates that all operands with the same name have the same record.
       unsigned ResultIdx =CGA.getResultInstOperandIndexForResultOperandIndex(i);
@@ -1236,15 +1243,22 @@
     
     // Find out what operand from the asmparser that this MCInst operand comes
     // from.
-    int SrcOperand = FindAsmOperandNamed(CGA.ResultOperands[AliasOpNo++].Name);
-    if (SrcOperand != -1) {
-      ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
-      continue;
+    if (CGA.ResultOperands[AliasOpNo].isRecord()) {
+      StringRef Name = CGA.ResultOperands[AliasOpNo++].getName();
+      int SrcOperand = FindAsmOperandNamed(Name);
+      if (SrcOperand != -1) {
+        ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, &OpInfo));
+        continue;
+      }
+      
+      throw TGError(TheDef->getLoc(), "Instruction '" +
+                    TheDef->getName() + "' has operand '" + OpInfo.Name +
+                    "' that doesn't appear in asm string!");
     }
     
-    throw TGError(TheDef->getLoc(), "Instruction '" +
-                  TheDef->getName() + "' has operand '" + OpInfo.Name +
-                  "' that doesn't appear in asm string!");
+    int64_t ImmVal = CGA.ResultOperands[AliasOpNo++].getImm();
+    ResOperands.push_back(ResOperand::getImmOp(ImmVal, &OpInfo));
+    continue;
   }
 }
 
@@ -1291,7 +1305,6 @@
 
       // Generate code to populate each result operand.
       switch (OpInfo.Kind) {
-      default: assert(0 && "Unknown result operand kind");
       case MatchableInfo::ResOperand::RenderAsmOperand: {
         // This comes from something we parsed.
         MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum];
@@ -1322,6 +1335,12 @@
         Signature += "__Tie" + utostr(TiedOp);
         break;
       }
+      case MatchableInfo::ResOperand::ImmOperand: {
+        int64_t Val = OpInfo.ImmVal;
+        CaseOS << "    Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n";
+        Signature += "__imm" + itostr(Val);
+        break;
+      }
       }
     }
     
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 40d4206..924608c 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -449,6 +449,21 @@
       ++AliasOpNo;
       continue;
     }
+    
+    if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
+      // Integer arguments can't have names.
+      if (!Result->getArgName(AliasOpNo).empty())
+        throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
+                      " must not have a name!");
+      if (ResultInst->Operands[i].MINumOperands != 1 ||
+          !ResultInst->Operands[i].Rec->isSubClassOf("Operand"))
+        throw TGError(R->getLoc(), "invalid argument class " + 
+                      ResultInst->Operands[i].Rec->getName() +
+                      " for integer result operand!");
+      ResultOperands.push_back(ResultOperand(II->getValue()));
+      ++AliasOpNo;
+      continue;
+    }
 
     throw TGError(R->getLoc(), "result of inst alias has unknown operand type");
   }
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index f5b2239..ac593df 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -267,10 +267,26 @@
     
     
     struct ResultOperand {
+    private:
       StringRef Name;
       Record *R;
       
-      ResultOperand(StringRef N, Record *r) : Name(N), R(r) {}
+      int64_t Imm;
+    public:      
+      enum {
+        K_Record,
+        K_Imm
+      } Kind;
+      
+      ResultOperand(StringRef N, Record *r) : Name(N), R(r), Kind(K_Record) {}
+      ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {}
+
+      bool isRecord() const { return Kind == K_Record; }
+      bool isImm() const { return Kind == K_Imm; }
+      
+      StringRef getName() const { assert(isRecord()); return Name; }
+      Record *getRecord() const { assert(isRecord()); return R; }
+      int64_t getImm() const { assert(isImm()); return Imm; }
     };
     
     /// ResultOperands - The decoded operands for the result instruction.