summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBrian Gaeke <gaeke@uiuc.edu>2003-07-11 18:18:35 +0000
committerBrian Gaeke <gaeke@uiuc.edu>2003-07-11 18:18:35 +0000
commit1aa476edf028fed9b5c8ff537fcab42704037094 (patch)
treec5ce479ddc345f6b30f391ae8a71e95c53f13e99 /lib
parent666ff520e6b0a7a3c9f11e7a86d7bf8eebb4e24a (diff)
downloadllvm-1aa476edf028fed9b5c8ff537fcab42704037094.tar.gz
llvm-1aa476edf028fed9b5c8ff537fcab42704037094.tar.bz2
llvm-1aa476edf028fed9b5c8ff537fcab42704037094.tar.xz
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
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/X86/Printer.cpp53
-rw-r--r--lib/Target/X86/X86AsmPrinter.cpp53
-rw-r--r--lib/Target/X86/X86InstrInfo.def48
3 files changed, 126 insertions, 28 deletions
diff --git a/lib/Target/X86/Printer.cpp b/lib/Target/X86/Printer.cpp
index 74820c8690..164ff0d08b 100644
--- a/lib/Target/X86/Printer.cpp
+++ b/lib/Target/X86/Printer.cpp
@@ -665,6 +665,11 @@ void Printer::printMachineInstruction(const MachineInstr *MI, std::ostream &O,
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 @@ void Printer::printMachineInstruction(const MachineInstr *MI, std::ostream &O,
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 @@ void Printer::printMachineInstruction(const MachineInstr *MI, std::ostream &O,
<< 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 @@ void Printer::printMachineInstruction(const MachineInstr *MI, std::ostream &O,
}
}
}
+ // 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);
diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp
index 74820c8690..164ff0d08b 100644
--- a/lib/Target/X86/X86AsmPrinter.cpp
+++ b/lib/Target/X86/X86AsmPrinter.cpp
@@ -665,6 +665,11 @@ void Printer::printMachineInstruction(const MachineInstr *MI, std::ostream &O,
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 @@ void Printer::printMachineInstruction(const MachineInstr *MI, std::ostream &O,
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 @@ void Printer::printMachineInstruction(const MachineInstr *MI, std::ostream &O,
<< 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 @@ void Printer::printMachineInstruction(const MachineInstr *MI, std::ostream &O,
}
}
}
+ // 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);
diff --git a/lib/Target/X86/X86InstrInfo.def b/lib/Target/X86/X86InstrInfo.def
index 242b59d343..bb24074ded 100644
--- a/lib/Target/X86/X86InstrInfo.def
+++ b/lib/Target/X86/X86InstrInfo.def
@@ -318,14 +318,14 @@ I(FSTr64 , "fst", 0xDD, 0, X86II::Void | X86II::Ar
I(FSTPr32 , "fstp", 0xD9, 0, X86II::Void | X86II::ArgF32 | X86II::MRMS3m , NoIR, NoIR) // store float, pop
I(FSTPr64 , "fstp", 0xDD, 0, X86II::Void | X86II::ArgF64 | X86II::MRMS3m , NoIR, NoIR) // store double, pop
I(FSTPr80 , "fstp", 0xDB, 0, X86II::Void | X86II::ArgF80 | X86II::MRMS7m | X86II::OneArgFP , NoIR, NoIR) // store extended, pop
-I(FSTrr , "fst" , 0xD0, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0)
-I(FSTPrr , "fstp" , 0xD8, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0), pop
+I(FSTrr , "fst" , 0xD0, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, NoIR) // ST(i) = ST(0)
+I(FSTPrr , "fstp" , 0xD8, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, NoIR) // ST(i) = ST(0), pop
I(FISTr16 , "fist", 0xDF, 0, X86II::Void | X86II::Arg16 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store signed short
I(FISTr32 , "fist", 0xDB, 0, X86II::Void | X86II::Arg32 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store signed int
I(FISTPr16 , "fistp", 0xDF, 0, X86II::Void | X86II::Arg16 | X86II::MRMS3m , NoIR, NoIR) // store short, pop
I(FISTPr32 , "fistp", 0xDB, 0, X86II::Void | X86II::Arg32 | X86II::MRMS3m , NoIR, NoIR) // store int, pop
-I(FISTPr64 , "fistp", 0xDF, 0, X86II::Void | X86II::Arg64 | X86II::MRMS7m | X86II::OneArgFP , NoIR, NoIR) // store long, pop
+I(FISTPr64 , "fistpll", 0xDF, 0, X86II::Void | X86II::Arg64 | X86II::MRMS7m | X86II::OneArgFP , NoIR, NoIR) // store long, pop
I(FXCH , "fxch" , 0xC8, 0, X86II::D9 | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, O_ST0) // fxch ST(i), ST(0)
@@ -335,34 +335,34 @@ I(FLD0 , "fldz" , 0xEE, 0, X86II::D9 | X86II::
I(FLD1 , "fld1" , 0xE8, 0, X86II::D9 | X86II::ArgF80 | X86II::RawFrm | X86II::ZeroArgFP, NoIR, NoIR) // load +1.0
// Binary arithmetic operations...
-I(FADDST0r , "fadd", 0xC0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) + ST(i)
-I(FADDrST0 , "fadd", 0xC0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) + ST(0)
-I(FADDPrST0 , "faddp", 0xC0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) + ST(0), pop
+I(FADDST0r , "fadd", 0xC0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, O_ST0) // ST(0) = ST(0) + ST(i)
+I(FADDrST0 , "fadd", 0xC0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm | X86II::PrintImplUses, O_ST0, NoIR) // ST(i) = ST(i) + ST(0)
+I(FADDPrST0 , "faddp", 0xC0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, NoIR) // ST(i) = ST(i) + ST(0), pop
-I(FSUBRST0r , "fsubr" , 0xE8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(i) - ST(0)
-I(FSUBrST0 , "fsub" , 0xE8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) - ST(0)
-I(FSUBPrST0 , "fsubp" , 0xE8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) - ST(0), pop
+I(FSUBRST0r , "fsubr" , 0xE8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, O_ST0) // ST(0) = ST(i) - ST(0)
+I(FSUBrST0 , "fsub" , 0xE8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm | X86II::PrintImplUses, O_ST0, NoIR) // ST(i) = ST(i) - ST(0)
+I(FSUBPrST0 , "fsubp" , 0xE8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, NoIR) // ST(i) = ST(i) - ST(0), pop
-I(FSUBST0r , "fsub" , 0xE0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) - ST(i)
-I(FSUBRrST0 , "fsubr" , 0xE0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) - ST(i)
-I(FSUBRPrST0 , "fsubrp", 0xE0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) - ST(i), pop
+I(FSUBST0r , "fsub" , 0xE0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, O_ST0) // ST(0) = ST(0) - ST(i)
+I(FSUBRrST0 , "fsubr" , 0xE0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm | X86II::PrintImplUses, O_ST0, NoIR) // ST(i) = ST(0) - ST(i)
+I(FSUBRPrST0 , "fsubrp", 0xE0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, NoIR) // ST(i) = ST(0) - ST(i), pop
-I(FMULST0r , "fmul", 0xC8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) * ST(i)
-I(FMULrST0 , "fmul", 0xC8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) * ST(0)
-I(FMULPrST0 , "fmulp", 0xC8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) * ST(0), pop
+I(FMULST0r , "fmul", 0xC8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, O_ST0) // ST(0) = ST(0) * ST(i)
+I(FMULrST0 , "fmul", 0xC8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm | X86II::PrintImplUses, O_ST0, NoIR) // ST(i) = ST(i) * ST(0)
+I(FMULPrST0 , "fmulp", 0xC8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, NoIR) // ST(i) = ST(i) * ST(0), pop
-I(FDIVRST0r , "fdivr" , 0xF8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(i) / ST(0)
-I(FDIVrST0 , "fdiv" , 0xF8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) / ST(0)
-I(FDIVPrST0 , "fdivp" , 0xF8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) / ST(0), pop
+I(FDIVRST0r , "fdivr" , 0xF8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, O_ST0) // ST(0) = ST(i) / ST(0)
+I(FDIVrST0 , "fdiv" , 0xF8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm | X86II::PrintImplUses, O_ST0, NoIR) // ST(i) = ST(i) / ST(0)
+I(FDIVPrST0 , "fdivp" , 0xF8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, NoIR) // ST(i) = ST(i) / ST(0), pop
-I(FDIVST0r , "fdiv" , 0xF0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) / ST(i)
-I(FDIVRrST0 , "fdivr" , 0xF0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) / ST(i)
-I(FDIVRPrST0 , "fdivrp", 0xF0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) / ST(i), pop
+I(FDIVST0r , "fdiv" , 0xF0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, O_ST0) // ST(0) = ST(0) / ST(i)
+I(FDIVRrST0 , "fdivr" , 0xF0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm | X86II::PrintImplUses, O_ST0, NoIR) // ST(i) = ST(0) / ST(i)
+I(FDIVRPrST0 , "fdivrp", 0xF0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, NoIR) // ST(i) = ST(0) / ST(i), pop
// Floating point compares
-I(FUCOMr , "fucom" , 0xE0, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // FPSW = compare ST(0) with ST(i)
-I(FUCOMPr , "fucomp" , 0xE8, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // compare, pop
-I(FUCOMPPr , "fucompp" , 0xE9, 0, X86II::DA | X86II::Void | X86II::RawFrm , NoIR, NoIR) // compare ST(0) with ST(1), pop, pop
+I(FUCOMr , "fucom" , 0xE0, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, NoIR) // FPSW = compare ST(0) with ST(i)
+I(FUCOMPr , "fucomp" , 0xE8, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, NoIR) // compare, pop
+I(FUCOMPPr , "fucompp" , 0xE9, 0, X86II::DA | X86II::Void | X86II::RawFrm , O_ST0, NoIR) // compare ST(0) with ST(1), pop, pop
// Floating point flag ops
I(FNSTSWr8 , "fnstsw" , 0xE0, 0, X86II::DF | X86II::Void | X86II::RawFrm , NoIR, O_AX) // AX = fp flags