mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 19:52:54 +01:00
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. llvm-svn: 7165
This commit is contained in:
parent
cb78ec5ada
commit
efd836df31
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user