Fix some serious floating-point bugs (fixes test cases such as Oscar,
Fhourstones, McCat-vor, and many others...)

Printer.cpp: Print implicit uses for AddRegFrm instructions.  Break gas
bug workarounds up into separate stanzas of code for each bug.  Add new
workarounds for fild and fistp.

X86InstrInfo.def: Add O_ST0 implicit uses for more FP instrs where they
obviously apply. Also add PrintImplUses flags for FP instrs where they
are necessary for gas to understand the output.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7165 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp
index 74820c8..164ff0d 100644
--- a/lib/Target/X86/X86AsmPrinter.cpp
+++ b/lib/Target/X86/X86AsmPrinter.cpp
@@ -665,6 +665,11 @@
       O << ", ";
       printOp(O, MI->getOperand(1), RI);
     }
+    if (Desc.TSFlags & X86II::PrintImplUses) {
+      for (const unsigned *p = Desc.ImplicitUses; *p; ++p) {
+	O << ", " << RI.get(*p).Name;
+      }
+    }
     O << "\n";
     return;
   }
@@ -819,7 +824,10 @@
            isMem(MI, 0) && "Bad MRMSxM format!");
     assert((MI->getNumOperands() != 5 || MI->getOperand(4).isImmediate()) &&
            "Bad MRMSxM format!");
-    // Work around GNU assembler bugs in FSTP and FLD.
+    // Bug: The 80-bit FP store-pop instruction "fstp XWORD PTR [...]"
+    // is misassembled by gas in intel_syntax mode as its 32-bit
+    // equivalent "fstp DWORD PTR [...]". Workaround: Output the raw
+    // opcode bytes instead of the instruction.
     if (MI->getOpCode() == X86::FSTPr80) {
       if ((MI->getOperand(0).getReg() == X86::ESP)
 	  && (MI->getOperand(1).getImmedValue() == 1)) {
@@ -834,7 +842,12 @@
             << std::dec << "\t# ";
 	}
       }
-    } else if (MI->getOpCode() == X86::FLDr80) {
+    }
+    // Bug: The 80-bit FP load instruction "fld XWORD PTR [...]" is
+    // misassembled by gas in intel_syntax mode as its 32-bit
+    // equivalent "fld DWORD PTR [...]". Workaround: Output the raw
+    // opcode bytes instead of the instruction.
+    if (MI->getOpCode() == X86::FLDr80) {
       if ((MI->getOperand(0).getReg() == X86::ESP)
           && (MI->getOperand(1).getImmedValue() == 1)) {
 	int DispVal = MI->getOperand(3).getImmedValue();
@@ -849,6 +862,42 @@
 	}
       }
     }
+    // Bug: gas intel_syntax mode treats "fild QWORD PTR [...]" as an
+    // invalid opcode, saying "64 bit operations are only supported in
+    // 64 bit modes." libopcodes disassembles it as "fild DWORD PTR
+    // [...]", which is wrong. Workaround: Output the raw opcode bytes
+    // instead of the instruction.
+    if (MI->getOpCode() == X86::FILDr64) {
+      if ((MI->getOperand(0).getReg() == X86::ESP)
+          && (MI->getOperand(1).getImmedValue() == 1)) {
+	int DispVal = MI->getOperand(3).getImmedValue();
+	if ((DispVal < -128) || (DispVal > 127)) { // 4 byte disp.
+          unsigned int val = (unsigned int) DispVal;
+          O << ".byte 0xdf, 0xac, 0x24\n\t";
+          O << ".long 0x" << std::hex << (unsigned) val << std::dec << "\t# ";
+	} else { // 1 byte disp.
+          unsigned char val = (unsigned char) DispVal;
+          O << ".byte 0xdf, 0x6c, 0x24, 0x" << std::hex << (unsigned) val
+            << std::dec << "\t# ";
+	}
+      }
+    }
+    // Bug: gas intel_syntax mode treats "fistp QWORD PTR [...]" as
+    // an invalid opcode, saying "64 bit operations are only
+    // supported in 64 bit modes." libopcodes disassembles it as
+    // "fistpll DWORD PTR [...]", which is wrong. Workaround: Output
+    // "fistpll DWORD PTR " instead, which is what libopcodes is
+    // expecting to see.
+    if (MI->getOpCode() == X86::FISTPr64) {
+      O << "fistpll DWORD PTR ";
+      printMemReference(O, MI, 0, RI);
+      if (MI->getNumOperands() == 5) {
+	O << ", ";
+	printOp(O, MI->getOperand(4), RI);
+      }
+      O << "\t# ";
+    }
+    
     O << TII.getName(MI->getOpCode()) << " ";
     O << sizePtr(Desc) << " ";
     printMemReference(O, MI, 0, RI);