diff --git a/lib/Target/X86/X86FloatingPoint.cpp b/lib/Target/X86/X86FloatingPoint.cpp index 58568c31c57..4ac574fb9d0 100644 --- a/lib/Target/X86/X86FloatingPoint.cpp +++ b/lib/Target/X86/X86FloatingPoint.cpp @@ -311,6 +311,63 @@ static int Lookup(const TableEntry *Table, unsigned N, unsigned Opcode) { } #endif +//===----------------------------------------------------------------------===// +// Register File -> Register Stack Mapping Methods +//===----------------------------------------------------------------------===// + +// OpcodeTable - Sorted map of register instructions to their stack version. +// The first element is an register file pseudo instruction, the second is the +// concrete X86 instruction which uses the register stack. +// +static const TableEntry OpcodeTable[] = { + { X86::FpABS , X86::FABS }, + { X86::FpADD32m , X86::FADD32m }, + { X86::FpADD64m , X86::FADD64m }, + { X86::FpCHS , X86::FCHS }, + { X86::FpCMOVA , X86::FCMOVA }, + { X86::FpCMOVAE , X86::FCMOVAE }, + { X86::FpCMOVB , X86::FCMOVB }, + { X86::FpCMOVBE , X86::FCMOVBE }, + { X86::FpCMOVE , X86::FCMOVE }, + { X86::FpCMOVNE , X86::FCMOVNE }, + { X86::FpCMOVNP , X86::FCMOVNP }, + { X86::FpCMOVP , X86::FCMOVP }, + { X86::FpCOS , X86::FCOS }, + { X86::FpDIV32m , X86::FDIV32m }, + { X86::FpDIV64m , X86::FDIV64m }, + { X86::FpDIVR32m, X86::FDIVR32m }, + { X86::FpDIVR64m, X86::FDIVR64m }, + { X86::FpILD16m , X86::FILD16m }, + { X86::FpILD32m , X86::FILD32m }, + { X86::FpILD64m , X86::FILD64m }, + { X86::FpIST16m , X86::FIST16m }, + { X86::FpIST32m , X86::FIST32m }, + { X86::FpIST64m , X86::FISTP64m }, + { X86::FpLD0 , X86::FLD0 }, + { X86::FpLD1 , X86::FLD1 }, + { X86::FpLD32m , X86::FLD32m }, + { X86::FpLD64m , X86::FLD64m }, + { X86::FpMUL32m , X86::FMUL32m }, + { X86::FpMUL64m , X86::FMUL64m }, + { X86::FpSIN , X86::FSIN }, + { X86::FpSQRT , X86::FSQRT }, + { X86::FpST32m , X86::FST32m }, + { X86::FpST64m , X86::FST64m }, + { X86::FpSUB32m , X86::FSUB32m }, + { X86::FpSUB64m , X86::FSUB64m }, + { X86::FpSUBR32m, X86::FSUBR32m }, + { X86::FpSUBR64m, X86::FSUBR64m }, + { X86::FpTST , X86::FTST }, + { X86::FpUCOMIr , X86::FUCOMIr }, + { X86::FpUCOMr , X86::FUCOMr }, +}; + +static unsigned getConcreteOpcode(unsigned Opcode) { + ASSERT_SORTED(OpcodeTable); + int Opc = Lookup(OpcodeTable, ARRAY_SIZE(OpcodeTable), Opcode); + assert(Opc != -1 && "FP Stack instruction not in OpcodeTable!"); + return Opc; +} //===----------------------------------------------------------------------===// // Helper Methods @@ -407,9 +464,12 @@ static unsigned getFPReg(const MachineOperand &MO) { void FPS::handleZeroArgFP(MachineBasicBlock::iterator &I) { MachineInstr *MI = I; unsigned DestReg = getFPReg(MI->getOperand(0)); - MI->RemoveOperand(0); // Remove the explicit ST(0) operand - // Result gets pushed on the stack... + // Change from the pseudo instruction to the concrete instruction. + MI->RemoveOperand(0); // Remove the explicit ST(0) operand + MI->setOpcode(getConcreteOpcode(MI->getOpcode())); + + // Result gets pushed on the stack. pushReg(DestReg); } @@ -424,20 +484,22 @@ void FPS::handleOneArgFP(MachineBasicBlock::iterator &I) { unsigned Reg = getFPReg(MI->getOperand(MI->getNumOperands()-1)); bool KillsSrc = LV->KillsRegister(MI, X86::FP0+Reg); - // FSTP80r and FISTP64r are strange because there are no non-popping versions. + // FISTP64r is strange because there isn't a non-popping versions. // If we have one _and_ we don't want to pop the operand, duplicate the value // on the stack instead of moving it. This ensure that popping the value is // always ok. // - if ((MI->getOpcode() == X86::FSTP80m || - MI->getOpcode() == X86::FISTP64m) && !KillsSrc) { + if (MI->getOpcode() == X86::FpIST64m && !KillsSrc) { duplicateToTop(Reg, 7 /*temp register*/, I); } else { moveToTop(Reg, I); // Move to the top of the stack... } + + // Convert from the pseudo instruction to the concrete instruction. MI->RemoveOperand(MI->getNumOperands()-1); // Remove explicit ST(0) operand + MI->setOpcode(getConcreteOpcode(MI->getOpcode())); - if (MI->getOpcode() == X86::FSTP80m || MI->getOpcode() == X86::FISTP64m) { + if (MI->getOpcode() == X86::FISTP64m) { assert(StackTop > 0 && "Stack empty??"); --StackTop; } else if (KillsSrc) { // Last use of operand? @@ -475,8 +537,10 @@ void FPS::handleOneArgFPRW(MachineBasicBlock::iterator &I) { duplicateToTop(Reg, getFPReg(MI->getOperand(0)), I); } + // Change from the pseudo instruction to the concrete instruction. MI->RemoveOperand(1); // Drop the source operand. MI->RemoveOperand(0); // Drop the destination operand. + MI->setOpcode(getConcreteOpcode(MI->getOpcode())); } @@ -638,8 +702,10 @@ void FPS::handleCompareFP(MachineBasicBlock::iterator &I) { // anywhere. moveToTop(Op0, I); + // Change from the pseudo instruction to the concrete instruction. MI->getOperand(0).setReg(getSTReg(Op1)); MI->RemoveOperand(1); + MI->setOpcode(getConcreteOpcode(MI->getOpcode())); // If any of the operands are killed by this instruction, free them. if (KillsOp0) freeStackSlotAfter(I, Op0); @@ -660,9 +726,12 @@ void FPS::handleCondMovFP(MachineBasicBlock::iterator &I) { moveToTop(Op0, I); // Change the second operand to the stack register that the operand is in. + // Change from the pseudo instruction to the concrete instruction. MI->RemoveOperand(0); MI->getOperand(0).setReg(getSTReg(Op1)); - + MI->setOpcode(getConcreteOpcode(MI->getOpcode())); + + // If we kill the second operand, make sure to pop it from the stack. if (Op0 != Op1 && LV->KillsRegister(MI, X86::FP0+Op1)) { // Get this value off of the register stack. diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp index 9f3bb81d382..9ce406b259d 100644 --- a/lib/Target/X86/X86ISelPattern.cpp +++ b/lib/Target/X86/X86ISelPattern.cpp @@ -757,9 +757,9 @@ void ISel::EmitSelectCC(SDOperand Cond, SDOperand True, SDOperand False, X86::CMOVA32rr, X86::CMOVAE32rr, X86::CMOVP32rr, X86::CMOVNP32rr, }; static const unsigned CMOVTABFP[] = { - X86::FCMOVE , X86::FCMOVNE, /*missing*/0, /*missing*/0, - /*missing*/0, /*missing*/0, X86::FCMOVB , X86::FCMOVBE, - X86::FCMOVA , X86::FCMOVAE, X86::FCMOVP , X86::FCMOVNP + X86::FpCMOVE, X86::FpCMOVNE, /*missing*/0, /*missing*/0, + /*missing*/0, /*missing*/ 0, X86::FpCMOVB, X86::FpCMOVBE, + X86::FpCMOVA, X86::FpCMOVAE, X86::FpCMOVP, X86::FpCMOVNP }; static const int SSE_CMOVTAB[] = { /*CMPEQ*/ 0, /*CMPNEQ*/ 4, /*missing*/ 0, /*missing*/ 0, @@ -944,7 +944,7 @@ void ISel::EmitSelectCC(SDOperand Cond, SDOperand True, SDOperand False, default: assert(0 && "Cannot select this type!"); case MVT::i16: Opc = X86::CMOVE16rr; break; case MVT::i32: Opc = X86::CMOVE32rr; break; - case MVT::f64: Opc = X86::FCMOVE; break; + case MVT::f64: Opc = X86::FpCMOVE; break; } } else { // FIXME: CMP R, 0 -> TEST R, R @@ -990,7 +990,7 @@ void ISel::EmitCMP(SDOperand LHS, SDOperand RHS, bool HasOneUse) { if (!X86ScalarSSE && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0))) { unsigned Reg = SelectExpr(LHS); - BuildMI(BB, X86::FTST, 1).addReg(Reg); + BuildMI(BB, X86::FpTST, 1).addReg(Reg); BuildMI(BB, X86::FNSTSW8r, 0); BuildMI(BB, X86::SAHF, 1); return; @@ -1022,7 +1022,7 @@ void ISel::EmitCMP(SDOperand LHS, SDOperand RHS, bool HasOneUse) { case MVT::i16: Opc = X86::CMP16rr; break; case MVT::i32: Opc = X86::CMP32rr; break; case MVT::f32: Opc = X86::UCOMISSrr; break; - case MVT::f64: Opc = X86ScalarSSE ? X86::UCOMISDrr : X86::FUCOMIr; break; + case MVT::f64: Opc = X86ScalarSSE ? X86::UCOMISDrr : X86::FpUCOMIr; break; } unsigned Tmp1, Tmp2; if (getRegPressure(LHS) > getRegPressure(RHS)) { @@ -1325,14 +1325,14 @@ unsigned ISel::SelectExpr(SDOperand N) { if (cast(N)->isExactlyValue(+0.0) || cast(N)->isExactlyValue(-0.0)) - BuildMI(BB, X86::FLD0, 0, Tmp1); + BuildMI(BB, X86::FpLD0, 0, Tmp1); else if (cast(N)->isExactlyValue(+1.0) || cast(N)->isExactlyValue(-1.0)) - BuildMI(BB, X86::FLD1, 0, Tmp1); + BuildMI(BB, X86::FpLD1, 0, Tmp1); else assert(0 && "Unexpected constant!"); if (Tmp1 != Result) - BuildMI(BB, X86::FCHS, 1, Result).addReg(Tmp1); + BuildMI(BB, X86::FpCHS, 1, Result).addReg(Tmp1); return Result; case ISD::Constant: switch (N.getValueType()) { @@ -1347,7 +1347,7 @@ unsigned ISel::SelectExpr(SDOperand N) { case ISD::UNDEF: if (Node->getValueType(0) == MVT::f64) { // FIXME: SHOULD TEACH STACKIFIER ABOUT UNDEF VALUES! - BuildMI(BB, X86::FLD0, 0, Result); + BuildMI(BB, X86::FpLD0, 0, Result); } else { BuildMI(BB, X86::IMPLICIT_DEF, 0, Result); } @@ -1471,11 +1471,11 @@ unsigned ISel::SelectExpr(SDOperand N) { switch (SrcTy) { case MVT::i32: addFrameReference(BuildMI(BB, X86::MOV32mr, 5), FrameIdx).addReg(Tmp1); - addFrameReference(BuildMI(BB, X86::FILD32m, 5, Result), FrameIdx); + addFrameReference(BuildMI(BB, X86::FpILD32m, 5, Result), FrameIdx); break; case MVT::i16: addFrameReference(BuildMI(BB, X86::MOV16mr, 5), FrameIdx).addReg(Tmp1); - addFrameReference(BuildMI(BB, X86::FILD16m, 5, Result), FrameIdx); + addFrameReference(BuildMI(BB, X86::FpILD16m, 5, Result), FrameIdx); break; default: break; // No promotion required. } @@ -1523,7 +1523,7 @@ unsigned ISel::SelectExpr(SDOperand N) { assert(Op1.getOpcode() == ISD::LOAD && "SSE load not promoted"); Opc = X86::ADDSDrm; } else { - Opc = Op1.getOpcode() == ISD::LOAD ? X86::FADD64m : X86::FADD32m; + Opc = Op1.getOpcode() == ISD::LOAD ? X86::FpADD64m : X86::FpADD32m; } break; } @@ -1616,7 +1616,7 @@ unsigned ISel::SelectExpr(SDOperand N) { Opc = (N.getValueType() == MVT::f32) ? X86::SQRTSSrr : X86::SQRTSDrr; BuildMI(BB, Opc, 1, Result).addReg(Tmp1); } else { - BuildMI(BB, X86::FSQRT, 1, Result).addReg(Tmp1); + BuildMI(BB, X86::FpSQRT, 1, Result).addReg(Tmp1); } return Result; @@ -1631,10 +1631,10 @@ unsigned ISel::SelectExpr(SDOperand N) { Tmp1 = SelectExpr(Node->getOperand(0)); switch (N.getOpcode()) { default: assert(0 && "Unreachable!"); - case ISD::FABS: BuildMI(BB, X86::FABS, 1, Result).addReg(Tmp1); break; - case ISD::FNEG: BuildMI(BB, X86::FCHS, 1, Result).addReg(Tmp1); break; - case ISD::FSIN: BuildMI(BB, X86::FSIN, 1, Result).addReg(Tmp1); break; - case ISD::FCOS: BuildMI(BB, X86::FCOS, 1, Result).addReg(Tmp1); break; + case ISD::FABS: BuildMI(BB, X86::FpABS, 1, Result).addReg(Tmp1); break; + case ISD::FNEG: BuildMI(BB, X86::FpCHS, 1, Result).addReg(Tmp1); break; + case ISD::FSIN: BuildMI(BB, X86::FpSIN, 1, Result).addReg(Tmp1); break; + case ISD::FCOS: BuildMI(BB, X86::FpCOS, 1, Result).addReg(Tmp1); break; } return Result; @@ -1698,7 +1698,7 @@ unsigned ISel::SelectExpr(SDOperand N) { case ISD::XOR: { static const unsigned SUBTab[] = { X86::SUB8ri, X86::SUB16ri, X86::SUB32ri, 0, 0, - X86::SUB8rm, X86::SUB16rm, X86::SUB32rm, X86::FSUB32m, X86::FSUB64m, + X86::SUB8rm, X86::SUB16rm, X86::SUB32rm, X86::FpSUB32m, X86::FpSUB64m, X86::SUB8rr, X86::SUB16rr, X86::SUB32rr, X86::FpSUB , X86::FpSUB, }; static const unsigned SSE_SUBTab[] = { @@ -1708,7 +1708,7 @@ unsigned ISel::SelectExpr(SDOperand N) { }; static const unsigned MULTab[] = { 0, X86::IMUL16rri, X86::IMUL32rri, 0, 0, - 0, X86::IMUL16rm , X86::IMUL32rm, X86::FMUL32m, X86::FMUL64m, + 0, X86::IMUL16rm , X86::IMUL32rm, X86::FpMUL32m, X86::FpMUL64m, 0, X86::IMUL16rr , X86::IMUL32rr, X86::FpMUL , X86::FpMUL, }; static const unsigned SSE_MULTab[] = { @@ -1821,9 +1821,9 @@ unsigned ISel::SelectExpr(SDOperand N) { // For FP, emit 'reverse' subract, with a memory operand. if (N.getValueType() == MVT::f64 && !X86ScalarSSE) { if (Op0.getOpcode() == ISD::EXTLOAD) - Opc = X86::FSUBR32m; + Opc = X86::FpSUBR32m; else - Opc = X86::FSUBR64m; + Opc = X86::FpSUBR64m; X86AddressMode AM; EmitFoldedLoad(Op0, AM); @@ -2015,9 +2015,9 @@ unsigned ISel::SelectExpr(SDOperand N) { // Check for reversed and unreversed DIV. if (isFoldableLoad(N.getOperand(0), N.getOperand(1), true)) { if (N.getOperand(0).getOpcode() == ISD::EXTLOAD) - Opc = X86::FDIVR32m; + Opc = X86::FpDIVR32m; else - Opc = X86::FDIVR64m; + Opc = X86::FpDIVR64m; X86AddressMode AM; EmitFoldedLoad(N.getOperand(0), AM); Tmp1 = SelectExpr(N.getOperand(1)); @@ -2026,9 +2026,9 @@ unsigned ISel::SelectExpr(SDOperand N) { } else if (isFoldableLoad(N.getOperand(1), N.getOperand(0), true) && N.getOperand(1).getOpcode() == ISD::LOAD) { if (N.getOperand(1).getOpcode() == ISD::EXTLOAD) - Opc = X86::FDIV32m; + Opc = X86::FpDIV32m; else - Opc = X86::FDIV64m; + Opc = X86::FpDIV64m; X86AddressMode AM; EmitFoldedLoad(N.getOperand(1), AM); Tmp1 = SelectExpr(N.getOperand(0)); @@ -2230,7 +2230,7 @@ unsigned ISel::SelectExpr(SDOperand N) { if (X86ScalarSSE) { Opc = X86::MOVSDrm; } else { - Opc = X86::FLD64m; + Opc = X86::FpLD64m; ContainsFPCode = true; } break; @@ -2276,7 +2276,7 @@ unsigned ISel::SelectExpr(SDOperand N) { Select(Chain); } - addFullAddress(BuildMI(BB, X86::FILD64m, 4, Result), AM); + addFullAddress(BuildMI(BB, X86::FpILD64m, 4, Result), AM); } return Result; @@ -2295,7 +2295,7 @@ unsigned ISel::SelectExpr(SDOperand N) { unsigned CPIdx = BB->getParent()->getConstantPool()-> getConstantPoolIndex(CP->get()); - addConstantPoolReference(BuildMI(BB, X86::FLD32m, 4, Result), CPIdx); + addConstantPoolReference(BuildMI(BB, X86::FpLD32m, 4, Result), CPIdx); return Result; } @@ -2314,7 +2314,7 @@ unsigned ISel::SelectExpr(SDOperand N) { case MVT::f64: assert(cast(Node->getOperand(3))->getVT() == MVT::f32 && "Bad EXTLOAD!"); - addFullAddress(BuildMI(BB, X86::FLD32m, 5, Result), AM); + addFullAddress(BuildMI(BB, X86::FpLD32m, 5, Result), AM); break; case MVT::i32: switch (cast(Node->getOperand(3))->getVT()) { @@ -2521,7 +2521,7 @@ unsigned ISel::SelectExpr(SDOperand N) { unsigned Size = MVT::getSizeInBits(MVT::f64)/8; MachineFunction *F = BB->getParent(); int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size); - addFrameReference(BuildMI(BB, X86::FST64m, 5), FrameIdx).addReg(X86::FP0); + addFrameReference(BuildMI(BB, X86::FpST64m, 5), FrameIdx).addReg(X86::FP0); addFrameReference(BuildMI(BB, X86::MOVSDrm, 4, Result), FrameIdx); break; } else { @@ -3197,7 +3197,7 @@ void ISel::Select(SDOperand N) { MachineFunction *F = BB->getParent(); int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size); addFrameReference(BuildMI(BB, X86::MOVSSmr, 5), FrameIdx).addReg(Tmp1); - addFrameReference(BuildMI(BB, X86::FLD32m, 4, X86::FP0), FrameIdx); + addFrameReference(BuildMI(BB, X86::FpLD32m, 4, X86::FP0), FrameIdx); BuildMI(BB, X86::FpSETRESULT, 1).addReg(X86::FP0); ContainsFPCode = true; } else { @@ -3212,7 +3212,7 @@ void ISel::Select(SDOperand N) { MachineFunction *F = BB->getParent(); int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size); addFrameReference(BuildMI(BB, X86::MOVSDmr, 5), FrameIdx).addReg(Tmp1); - addFrameReference(BuildMI(BB, X86::FLD64m, 4, X86::FP0), FrameIdx); + addFrameReference(BuildMI(BB, X86::FpLD64m, 4, X86::FP0), FrameIdx); BuildMI(BB, X86::FpSETRESULT, 1).addReg(X86::FP0); ContainsFPCode = true; } else { @@ -3342,9 +3342,9 @@ void ISel::Select(SDOperand N) { // Get the X86 opcode to use. switch (N.getOpcode()) { - case X86ISD::FP_TO_INT16_IN_MEM: Tmp1 = X86::FIST16m; break; - case X86ISD::FP_TO_INT32_IN_MEM: Tmp1 = X86::FIST32m; break; - case X86ISD::FP_TO_INT64_IN_MEM: Tmp1 = X86::FISTP64m; break; + case X86ISD::FP_TO_INT16_IN_MEM: Tmp1 = X86::FpIST16m; break; + case X86ISD::FP_TO_INT32_IN_MEM: Tmp1 = X86::FpIST32m; break; + case X86ISD::FP_TO_INT64_IN_MEM: Tmp1 = X86::FpIST64m; break; } addFullAddress(BuildMI(BB, Tmp1, 5), AM).addReg(ValReg); @@ -3393,7 +3393,7 @@ void ISel::Select(SDOperand N) { case MVT::i1: Opc = X86::MOV8mr; break; case MVT::f32: assert(!X86ScalarSSE && "Cannot truncstore scalar SSE regs"); - Opc = X86::FST32m; break; + Opc = X86::FpST32m; break; } std::vector > RP; @@ -3474,7 +3474,7 @@ void ISel::Select(SDOperand N) { case MVT::i16: Opc = X86::MOV16mr; break; case MVT::i32: Opc = X86::MOV32mr; break; case MVT::f32: Opc = X86::MOVSSmr; break; - case MVT::f64: Opc = X86ScalarSSE ? X86::MOVSDmr : X86::FST64m; break; + case MVT::f64: Opc = X86ScalarSSE ? X86::MOVSDmr : X86::FpST64m; break; } std::vector > RP; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 79db00183c8..c5e77dc7246 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -2203,334 +2203,256 @@ def RDTSC : I<0x31, RawFrm, (ops), "rdtsc", []>, TB, Imp<[],[EAX,EDX]>; // Stack-based Floating point support //===----------------------------------------------------------------------===// -// FIXME: These need to indicate mod/ref sets for FP regs... & FP 'TOP' +// Floating point support. All FP Stack operations are represented with two +// instructions here. The first instruction, generated by the instruction +// selector, uses "RFP" registers: a traditional register file to reference +// floating point values. These instructions are all psuedo instructions and +// use the "Fp" prefix. The second instruction is defined with FPI, which is +// the actual instruction emitted by the assembler. The FP stackifier pass +// converts one to the other after register allocation occurs. +// +// Note that the FpI instruction should have instruction selection info (e.g. +// a pattern) and the FPI instruction should have emission info (e.g. opcode +// encoding and asm printing info). -// Floating point instruction template -class FPI o, Format F, FPFormat fp, dag ops, string asm, - list pattern> - : X86Inst { +// FPI - Floating Point Instruction template. +class FPI o, Format F, dag ops, string asm> : I {} + +// FpI - Floating Point Psuedo Instruction template. +class FpI pattern> + : X86Inst<0, Pseudo, NoImm, ops, ""> { let FPForm = fp; let FPFormBits = FPForm.Value; let Pattern = pattern; } -// Pseudo instructions for floating point. We use these pseudo instructions -// because they can be expanded by the fp spackifier into one of many different -// forms of instructions for doing these operations. Until the stackifier runs, -// we prefer to be abstract. -def FpMOV : FPI<0, Pseudo, SpecialFP, - (ops RFP:$dst, RFP:$src), "", []>; // f1 = fmov f2 -def FpADD : FPI<0, Pseudo, TwoArgFP , - (ops RFP:$dst, RFP:$src1, RFP:$src2), "", - []>; // f1 = fadd f2, f3 -def FpSUB : FPI<0, Pseudo, TwoArgFP , - (ops RFP:$dst, RFP:$src1, RFP:$src2), "", - []>; // f1 = fsub f2, f3 -def FpMUL : FPI<0, Pseudo, TwoArgFP , - (ops RFP:$dst, RFP:$src1, RFP:$src2), "", - []>; // f1 = fmul f2, f3 -def FpDIV : FPI<0, Pseudo, TwoArgFP , - (ops RFP:$dst, RFP:$src1, RFP:$src2), "", - []>; // f1 = fdiv f2, f3 +// Random Pseudo Instructions. +def FpGETRESULT : FpI<(ops RFP:$dst), SpecialFP, // FPR = ST(0) + []>; +def FpSETRESULT : FpI<(ops RFP:$src), SpecialFP, + [(X86fpset RFP:$src)]>, Imp<[], [ST0]>; // ST(0) = FPR +def FpMOV : FpI<(ops RFP:$dst, RFP:$src), SpecialFP, + []>; // f1 = fmov f2 -def FpLD32m : FPI<0xD9, MRM0m, ZeroArgFP, - (ops RFP:$dst, f32mem:$src), - "fld{s} $src", +// Binary Ops with a memory source. +def FpADD32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = ST(0) + [mem32] +def FpADD64m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = ST(0) + [mem32] +def FpMUL32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = ST(0) * [mem32] +def FpMUL64m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = ST(0) * [mem32] +def FpSUB32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = ST(0) - [mem32] +def FpSUB64m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = ST(0) - [mem32] +def FpSUBR32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = [mem32] - ST(0) +def FpSUBR64m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = [mem32] - ST(0) +def FpDIV32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = ST(0) / [mem32] +def FpDIV64m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = ST(0) / [mem32] +def FpDIVR32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = [mem32] / ST(0) +def FpDIVR64m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, + []>; // ST(0) = [mem32] / ST(0) + + +def FADD32m : FPI<0xD8, MRM0m, (ops f32mem:$src), "fadd{s} $src">; +def FADD64m : FPI<0xDC, MRM0m, (ops f64mem:$src), "fadd{l} $src">; +def FMUL32m : FPI<0xD8, MRM1m, (ops f32mem:$src), "fmul{s} $src">; +def FMUL64m : FPI<0xDC, MRM1m, (ops f64mem:$src), "fmul{l} $src">; +def FSUB32m : FPI<0xD8, MRM4m, (ops f32mem:$src), "fsub{s} $src">; +def FSUB64m : FPI<0xDC, MRM4m, (ops f64mem:$src), "fsub{l} $src">; +def FSUBR32m : FPI<0xD8, MRM5m, (ops f32mem:$src), "fsubr{s} $src">; +def FSUBR64m : FPI<0xDC, MRM5m, (ops f64mem:$src), "fsubr{l} $src">; +def FDIV32m : FPI<0xD8, MRM6m, (ops f32mem:$src), "fdiv{s} $src">; +def FDIV64m : FPI<0xDC, MRM6m, (ops f64mem:$src), "fdiv{l} $src">; +def FDIVR32m : FPI<0xD8, MRM7m, (ops f32mem:$src), "fdivr{s} $src">; +def FDIVR64m : FPI<0xDC, MRM7m, (ops f64mem:$src), "fdivr{l} $src">; + +// FIXME: Implement these when we have a dag-dag isel! +//def FIADD16m : FPI<0xDE, MRM0m>; // ST(0) = ST(0) + [mem16int] +//def FIADD32m : FPI<0xDA, MRM0m>; // ST(0) = ST(0) + [mem32int] +//def FIMUL16m : FPI<0xDE, MRM1m>; // ST(0) = ST(0) * [mem16] +//def FIMUL32m : FPI<0xDA, MRM1m>; // ST(0) = ST(0) * [mem32] +//def FISUB16m : FPI<0xDE, MRM4m>; // ST(0) = ST(0) - [mem16int] +//def FISUB32m : FPI<0xDA, MRM4m>; // ST(0) = ST(0) - [mem32int] +//def FISUBR16m : FPI<0xDE, MRM5m>; // ST(0) = [mem16int] - ST(0) +//def FISUBR32m : FPI<0xDA, MRM5m>; // ST(0) = [mem32int] - ST(0) +//def FIDIV16m : FPI<0xDE, MRM6m>; // ST(0) = ST(0) / [mem16int] +//def FIDIV32m : FPI<0xDA, MRM6m>; // ST(0) = ST(0) / [mem32int] +//def FIDIVR16m : FPI<0xDE, MRM7m>; // ST(0) = [mem16int] / ST(0) +//def FIDIVR32m : FPI<0xDA, MRM7m>; // ST(0) = [mem32int] / ST(0) + + +// Floating point cmovs. +let isTwoAddress = 1 in { + def FpCMOVB : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; + def FpCMOVBE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; + def FpCMOVE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; + def FpCMOVP : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; + def FpCMOVAE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; + def FpCMOVA : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; + def FpCMOVNE : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; + def FpCMOVNP : FpI<(ops RST:$dst, RFP:$src1, RFP:$src2), CondMovFP, []>; +} + +def FCMOVB : FPI<0xC0, AddRegFrm, (ops RST:$op), + "fcmovb {$op, %ST(0)|%ST(0), $op}">, DA; +def FCMOVBE : FPI<0xD0, AddRegFrm, (ops RST:$op), + "fcmovbe {$op, %ST(0)|%ST(0), $op}">, DA; +def FCMOVE : FPI<0xC8, AddRegFrm, (ops RST:$op), + "fcmove {$op, %ST(0)|%ST(0), $op}">, DA; +def FCMOVP : FPI<0xD8, AddRegFrm, (ops RST:$op), + "fcmovu {$op, %ST(0)|%ST(0), $op}">, DA; +def FCMOVAE : FPI<0xC0, AddRegFrm, (ops RST:$op), + "fcmovae {$op, %ST(0)|%ST(0), $op}">, DB; +def FCMOVA : FPI<0xD0, AddRegFrm, (ops RST:$op), + "fcmova {$op, %ST(0)|%ST(0), $op}">, DB; +def FCMOVNE : FPI<0xC8, AddRegFrm, (ops RST:$op), + "fcmovne {$op, %ST(0)|%ST(0), $op}">, DB; +def FCMOVNP : FPI<0xD8, AddRegFrm, (ops RST:$op), + "fcmovnu {$op, %ST(0)|%ST(0), $op}">, DB; + +// Floating point loads & stores. +def FpLD32m : FpI<(ops RFP:$dst, f32mem:$src), ZeroArgFP, [(set RFP:$dst, (X86fld addr:$src, f32))]>; - -def FpLD64m : FPI<0xDD, MRM0m, ZeroArgFP, - (ops RFP:$dst, f64mem:$src), - "fld{l} $src", +def FpLD64m : FpI<(ops RFP:$dst, f64mem:$src), ZeroArgFP, [(set RFP:$dst, (X86fld addr:$src, f64))]>; +def FpILD16m : FpI<(ops RFP:$dst, i16mem:$src), ZeroArgFP, + []>; +def FpILD32m : FpI<(ops RFP:$dst, i32mem:$src), ZeroArgFP, + []>; +def FpILD64m : FpI<(ops RFP:$dst, i64mem:$src), ZeroArgFP, + []>; -def FpGETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$dst), "", []>, - Imp<[ST0], []>; // FPR = ST(0) +def FpST32m : FpI<(ops f32mem:$op, RFP:$src), OneArgFP, []>; +def FpST64m : FpI<(ops f64mem:$op, RFP:$src), OneArgFP, []>; +def FpSTP32m : FpI<(ops f32mem:$op, RFP:$src), OneArgFP, []>; +def FpSTP64m : FpI<(ops f64mem:$op, RFP:$src), OneArgFP, []>; +def FpIST16m : FpI<(ops i16mem:$op, RFP:$src), OneArgFP, []>; +def FpIST32m : FpI<(ops i32mem:$op, RFP:$src), OneArgFP, []>; +def FpIST64m : FpI<(ops i64mem:$op, RFP:$src), OneArgFP, []>; -def FpSETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$src), "", - [(X86fpset RFP:$src)]>, - Imp<[], [ST0]>; // ST(0) = FPR +def FLD32m : FPI<0xD9, MRM0m, (ops f32mem:$src), "fld{s} $src">; +def FLD64m : FPI<0xDD, MRM0m, (ops f64mem:$src), "fld{l} $src">; +def FILD16m : FPI<0xDF, MRM0m, (ops i16mem:$src), "fild{s} $src">; +def FILD32m : FPI<0xDB, MRM0m, (ops i32mem:$src), "fild{l} $src">; +def FILD64m : FPI<0xDF, MRM5m, (ops i64mem:$src), "fild{ll} $src">; +def FST32m : FPI<0xD9, MRM2m, (ops f32mem:$dst), "fst{s} $dst">; +def FST64m : FPI<0xDD, MRM2m, (ops f64mem:$dst), "fst{l} $dst">; +def FSTP32m : FPI<0xD9, MRM3m, (ops f32mem:$dst), "fstp{s} $dst">; +def FSTP64m : FPI<0xDD, MRM3m, (ops f64mem:$dst), "fstp{l} $dst">; +def FIST16m : FPI<0xDF, MRM2m, (ops i16mem:$dst), "fist{s} $dst">; +def FIST32m : FPI<0xDB, MRM2m, (ops i32mem:$dst), "fist{l} $dst">; +def FISTP16m : FPI<0xDF, MRM3m, (ops i16mem:$dst), "fistp{s} $dst">; +def FISTP32m : FPI<0xDB, MRM3m, (ops i32mem:$dst), "fistp{l} $dst">; +def FISTP64m : FPI<0xDF, MRM7m, (ops i64mem:$dst), "fistp{ll} $dst">; -// FADD reg, mem: Before stackification, these are represented by: -// R1 = FADD* R2, [mem] -def FADD32m : FPI<0xD8, MRM0m, OneArgFPRW, // ST(0) = ST(0) + [mem32real] - (ops f32mem:$src, variable_ops), - "fadd{s} $src", []>; -def FADD64m : FPI<0xDC, MRM0m, OneArgFPRW, // ST(0) = ST(0) + [mem64real] - (ops f64mem:$src, variable_ops), - "fadd{l} $src", []>; -//def FIADD16m : FPI<0xDE, MRM0m, OneArgFPRW>; // ST(0) = ST(0) + [mem16int] -//def FIADD32m : FPI<0xDA, MRM0m, OneArgFPRW>; // ST(0) = ST(0) + [mem32int] +// FP Stack manipulation instructions. +def FLDrr : FPI<0xC0, AddRegFrm, (ops RST:$op), "fld $op">, D9; +def FSTrr : FPI<0xD0, AddRegFrm, (ops RST:$op), "fst $op">, DD; +def FSTPrr : FPI<0xD8, AddRegFrm, (ops RST:$op), "fstp $op">, DD; +def FXCH : FPI<0xC8, AddRegFrm, (ops RST:$op), "fxch $op">, D9; -// FMUL reg, mem: Before stackification, these are represented by: -// R1 = FMUL* R2, [mem] -def FMUL32m : FPI<0xD8, MRM1m, OneArgFPRW, // ST(0) = ST(0) * [mem32real] - (ops f32mem:$src, variable_ops), - "fmul{s} $src", []>; -def FMUL64m : FPI<0xDC, MRM1m, OneArgFPRW, // ST(0) = ST(0) * [mem64real] - (ops f64mem:$src, variable_ops), - "fmul{l} $src", []>; -// ST(0) = ST(0) * [mem16int] -//def FIMUL16m : FPI16m<"fimul", 0xDE, MRM1m, OneArgFPRW>; -// ST(0) = ST(0) * [mem32int] -//def FIMUL32m : FPI32m<"fimul", 0xDA, MRM1m, OneArgFPRW>; +// Floating point constant loads. +def FpLD0 : FpI<(ops RFP:$dst), ZeroArgFP, []>; +def FpLD1 : FpI<(ops RFP:$dst), ZeroArgFP, []>; -// FSUB reg, mem: Before stackification, these are represented by: -// R1 = FSUB* R2, [mem] -def FSUB32m : FPI<0xD8, MRM4m, OneArgFPRW, // ST(0) = ST(0) - [mem32real] - (ops f32mem:$src, variable_ops), - "fsub{s} $src", []>; -def FSUB64m : FPI<0xDC, MRM4m, OneArgFPRW, // ST(0) = ST(0) - [mem64real] - (ops f64mem:$src, variable_ops), - "fsub{l} $src", []>; -// ST(0) = ST(0) - [mem16int] -//def FISUB16m : FPI16m<"fisub", 0xDE, MRM4m, OneArgFPRW>; -// ST(0) = ST(0) - [mem32int] -//def FISUB32m : FPI32m<"fisub", 0xDA, MRM4m, OneArgFPRW>; - -// FSUBR reg, mem: Before stackification, these are represented by: -// R1 = FSUBR* R2, [mem] - -// Note that the order of operands does not reflect the operation being -// performed. -def FSUBR32m : FPI<0xD8, MRM5m, OneArgFPRW, // ST(0) = [mem32real] - ST(0) - (ops f32mem:$src, variable_ops), - "fsubr{s} $src", []>; -def FSUBR64m : FPI<0xDC, MRM5m, OneArgFPRW, // ST(0) = [mem64real] - ST(0) - (ops f64mem:$src, variable_ops), - "fsubr{l} $src", []>; -// ST(0) = [mem16int] - ST(0) -//def FISUBR16m : FPI16m<"fisubr", 0xDE, MRM5m, OneArgFPRW>; -// ST(0) = [mem32int] - ST(0) -//def FISUBR32m : FPI32m<"fisubr", 0xDA, MRM5m, OneArgFPRW>; - -// FDIV reg, mem: Before stackification, these are represented by: -// R1 = FDIV* R2, [mem] -def FDIV32m : FPI<0xD8, MRM6m, OneArgFPRW, // ST(0) = ST(0) / [mem32real] - (ops f32mem:$src, variable_ops), - "fdiv{s} $src", []>; -def FDIV64m : FPI<0xDC, MRM6m, OneArgFPRW, // ST(0) = ST(0) / [mem64real] - (ops f64mem:$src, variable_ops), - "fdiv{l} $src", []>; -// ST(0) = ST(0) / [mem16int] -//def FIDIV16m : FPI16m<"fidiv", 0xDE, MRM6m, OneArgFPRW>; -// ST(0) = ST(0) / [mem32int] -//def FIDIV32m : FPI32m<"fidiv", 0xDA, MRM6m, OneArgFPRW>; - -// FDIVR reg, mem: Before stackification, these are represented by: -// R1 = FDIVR* R2, [mem] -// Note that the order of operands does not reflect the operation being -// performed. -def FDIVR32m : FPI<0xD8, MRM7m, OneArgFPRW, // ST(0) = [mem32real] / ST(0) - (ops f32mem:$src, variable_ops), - "fdivr{s} $src", []>; -def FDIVR64m : FPI<0xDC, MRM7m, OneArgFPRW, // ST(0) = [mem64real] / ST(0) - (ops f64mem:$src, variable_ops), - "fdivr{l} $src", []>; -// ST(0) = [mem16int] / ST(0) -//def FIDIVR16m : FPI16m<"fidivr", 0xDE, MRM7m, OneArgFPRW>; -// ST(0) = [mem32int] / ST(0) -//def FIDIVR32m : FPI32m<"fidivr", 0xDA, MRM7m, OneArgFPRW>; +def FLD0 : FPI<0xEE, RawFrm, (ops), "fldz">, D9; +def FLD1 : FPI<0xE8, RawFrm, (ops), "fld1">, D9; -// Floating point cmovs... -let isTwoAddress = 1, Uses = [ST0], Defs = [ST0] in { - def FCMOVB : FPI<0xC0, AddRegFrm, CondMovFP, - (ops RST:$op, variable_ops), - "fcmovb {$op, %ST(0)|%ST(0), $op}", []>, DA; - def FCMOVBE : FPI<0xD0, AddRegFrm, CondMovFP, - (ops RST:$op, variable_ops), - "fcmovbe {$op, %ST(0)|%ST(0), $op}", []>, DA; - def FCMOVE : FPI<0xC8, AddRegFrm, CondMovFP, - (ops RST:$op, variable_ops), - "fcmove {$op, %ST(0)|%ST(0), $op}", []>, DA; - def FCMOVP : FPI<0xD8, AddRegFrm, CondMovFP, - (ops RST:$op, variable_ops), - "fcmovu {$op, %ST(0)|%ST(0), $op}", []>, DA; - def FCMOVAE : FPI<0xC0, AddRegFrm, CondMovFP, - (ops RST:$op, variable_ops), - "fcmovae {$op, %ST(0)|%ST(0), $op}", []>, DB; - def FCMOVA : FPI<0xD0, AddRegFrm, CondMovFP, - (ops RST:$op, variable_ops), - "fcmova {$op, %ST(0)|%ST(0), $op}", []>, DB; - def FCMOVNE : FPI<0xC8, AddRegFrm, CondMovFP, - (ops RST:$op, variable_ops), - "fcmovne {$op, %ST(0)|%ST(0), $op}", []>, DB; - def FCMOVNP : FPI<0xD8, AddRegFrm, CondMovFP, - (ops RST:$op, variable_ops), - "fcmovnu {$op, %ST(0)|%ST(0), $op}", []>, DB; -} +// Unary operations. +def FpCHS : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW, + [(set RFP:$dst, (fneg RFP:$src))]>; +def FpABS : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW, + [(set RFP:$dst, (fabs RFP:$src))]>; +def FpSQRT : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW, + [(set RFP:$dst, (fsqrt RFP:$src))]>; +def FpSIN : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW, + [(set RFP:$dst, (fsin RFP:$src))]>; +def FpCOS : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW, + [(set RFP:$dst, (fcos RFP:$src))]>; +def FpTST : FpI<(ops RFP:$src), OneArgFP, + []>; -// Floating point loads & stores... -// FIXME: these are all marked variable_ops because they have an implicit -// destination. Instructions like FILD* that are generated by the instruction -// selector (not the fp stackifier) need more accurate operand accounting. -def FLDrr : FPI<0xC0, AddRegFrm, NotFP, - (ops RST:$src, variable_ops), - "fld $src", []>, D9; -def FLD32m : FPI<0xD9, MRM0m, ZeroArgFP, - (ops f32mem:$src, variable_ops), - "fld{s} $src", []>; -def FLD64m : FPI<0xDD, MRM0m, ZeroArgFP, - (ops f64mem:$src, variable_ops), - "fld{l} $src", []>; -def FLD80m : FPI<0xDB, MRM5m, ZeroArgFP, - (ops f80mem:$src, variable_ops), - "fld{t} $src", []>; -def FILD16m : FPI<0xDF, MRM0m, ZeroArgFP, - (ops i16mem:$src, variable_ops), - "fild{s} $src", []>; -def FILD32m : FPI<0xDB, MRM0m, ZeroArgFP, - (ops i32mem:$src, variable_ops), - "fild{l} $src", []>; -def FILD64m : FPI<0xDF, MRM5m, ZeroArgFP, - (ops i64mem:$src, variable_ops), - "fild{ll} $src", []>; - -def FSTrr : FPI<0xD0, AddRegFrm, NotFP, - (ops RST:$op, variable_ops), - "fst $op", []>, DD; -def FSTPrr : FPI<0xD8, AddRegFrm, NotFP, - (ops RST:$op, variable_ops), - "fstp $op", []>, DD; -def FST32m : FPI<0xD9, MRM2m, OneArgFP, - (ops f32mem:$op, variable_ops), - "fst{s} $op", []>; -def FST64m : FPI<0xDD, MRM2m, OneArgFP, - (ops f64mem:$op, variable_ops), - "fst{l} $op", []>; -def FSTP32m : FPI<0xD9, MRM3m, OneArgFP, - (ops f32mem:$op, variable_ops), - "fstp{s} $op", []>; -def FSTP64m : FPI<0xDD, MRM3m, OneArgFP, - (ops f64mem:$op, variable_ops), - "fstp{l} $op", []>; -def FSTP80m : FPI<0xDB, MRM7m, OneArgFP, - (ops f80mem:$op, variable_ops), - "fstp{t} $op", []>; - -def FIST16m : FPI<0xDF, MRM2m , OneArgFP, - (ops i16mem:$op, variable_ops), - "fist{s} $op", []>; -def FIST32m : FPI<0xDB, MRM2m , OneArgFP, - (ops i32mem:$op, variable_ops), - "fist{l} $op", []>; -def FISTP16m : FPI<0xDF, MRM3m , NotFP , - (ops i16mem:$op, variable_ops), - "fistp{s} $op", []>; -def FISTP32m : FPI<0xDB, MRM3m , NotFP , - (ops i32mem:$op, variable_ops), - "fistp{l} $op", []>; -def FISTP64m : FPI<0xDF, MRM7m , OneArgFP, - (ops i64mem:$op, variable_ops), - "fistp{ll} $op", []>; - -def FXCH : FPI<0xC8, AddRegFrm, NotFP, - (ops RST:$op), "fxch $op", []>, D9; // fxch ST(i), ST(0) - -// Floating point constant loads... -def FLD0 : FPI<0xEE, RawFrm, ZeroArgFP, (ops variable_ops), "fldz", []>, D9; -def FLD1 : FPI<0xE8, RawFrm, ZeroArgFP, (ops variable_ops), "fld1", []>, D9; +def FCHS : FPI<0xE0, RawFrm, (ops), "fchs">, D9; +def FABS : FPI<0xE1, RawFrm, (ops), "fabs">, D9; +def FSQRT : FPI<0xFA, RawFrm, (ops), "fsqrt">, D9; +def FSIN : FPI<0xFE, RawFrm, (ops), "fsin">, D9; +def FCOS : FPI<0xFF, RawFrm, (ops), "fcos">, D9; +def FTST : FPI<0xE4, RawFrm, (ops), "ftst">, D9; -// Unary operations... -def FCHS : FPI<0xE0, RawFrm, OneArgFPRW, // f1 = fchs f2 - (ops variable_ops), - "fchs", []>, D9; -def FABS : FPI<0xE1, RawFrm, OneArgFPRW, // f1 = fabs f2 - (ops variable_ops), - "fabs", []>, D9; -def FSQRT : FPI<0xFA, RawFrm, OneArgFPRW, // fsqrt ST(0) - (ops variable_ops), - "fsqrt", []>, D9; -def FSIN : FPI<0xFE, RawFrm, OneArgFPRW, // fsin ST(0) - (ops variable_ops), - "fsin", []>, D9; -def FCOS : FPI<0xFF, RawFrm, OneArgFPRW, // fcos ST(0) - (ops variable_ops), - "fcos", []>, D9; -def FTST : FPI<0xE4, RawFrm, OneArgFP , // ftst ST(0) - (ops variable_ops), - "ftst", []>, D9; -// Binary arithmetic operations... -class FPST0rInst o, dag ops, string asm> - : I, D8 { - list Uses = [ST0]; - list Defs = [ST0]; -} -class FPrST0Inst o, dag ops, string asm> - : I, DC { - list Uses = [ST0]; -} -class FPrST0PInst o, dag ops, string asm> - : I, DE { - list Uses = [ST0]; -} +// Add, Sub, Mul, Div. +def FpADD : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP, + [(set RFP:$dst, (fadd RFP:$src1, RFP:$src2))]>; +def FpSUB : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP, + [(set RFP:$dst, (fsub RFP:$src1, RFP:$src2))]>; +def FpMUL : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP, + [(set RFP:$dst, (fmul RFP:$src1, RFP:$src2))]>; +def FpDIV : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP, + [(set RFP:$dst, (fdiv RFP:$src1, RFP:$src2))]>; -def FADDST0r : FPST0rInst <0xC0, (ops RST:$op), - "fadd $op">; -def FADDrST0 : FPrST0Inst <0xC0, (ops RST:$op), - "fadd {%ST(0), $op|$op, %ST(0)}">; -def FADDPrST0 : FPrST0PInst<0xC0, (ops RST:$op), - "faddp $op">; +class FPST0rInst o, string asm> + : FPI, D8; +class FPrST0Inst o, string asm> + : FPI, DC; +class FPrST0PInst o, string asm> + : FPI, DE; // NOTE: GAS and apparently all other AT&T style assemblers have a broken notion // of some of the 'reverse' forms of the fsub and fdiv instructions. As such, // we have to put some 'r's in and take them out of weird places. -def FSUBRST0r : FPST0rInst <0xE8, (ops RST:$op), - "fsubr $op">; -def FSUBrST0 : FPrST0Inst <0xE8, (ops RST:$op), - "fsub{r} {%ST(0), $op|$op, %ST(0)}">; -def FSUBPrST0 : FPrST0PInst<0xE8, (ops RST:$op), - "fsub{r}p $op">; +def FADDST0r : FPST0rInst <0xC0, "fadd $op">; +def FADDrST0 : FPrST0Inst <0xC0, "fadd {%ST(0), $op|$op, %ST(0)}">; +def FADDPrST0 : FPrST0PInst<0xC0, "faddp $op">; +def FSUBRST0r : FPST0rInst <0xE8, "fsubr $op">; +def FSUBrST0 : FPrST0Inst <0xE8, "fsub{r} {%ST(0), $op|$op, %ST(0)}">; +def FSUBPrST0 : FPrST0PInst<0xE8, "fsub{r}p $op">; +def FSUBST0r : FPST0rInst <0xE0, "fsub $op">; +def FSUBRrST0 : FPrST0Inst <0xE0, "fsub{|r} {%ST(0), $op|$op, %ST(0)}">; +def FSUBRPrST0 : FPrST0PInst<0xE0, "fsub{|r}p $op">; +def FMULST0r : FPST0rInst <0xC8, "fmul $op">; +def FMULrST0 : FPrST0Inst <0xC8, "fmul {%ST(0), $op|$op, %ST(0)}">; +def FMULPrST0 : FPrST0PInst<0xC8, "fmulp $op">; +def FDIVRST0r : FPST0rInst <0xF8, "fdivr $op">; +def FDIVrST0 : FPrST0Inst <0xF8, "fdiv{r} {%ST(0), $op|$op, %ST(0)}">; +def FDIVPrST0 : FPrST0PInst<0xF8, "fdiv{r}p $op">; +def FDIVST0r : FPST0rInst <0xF0, "fdiv $op">; +def FDIVRrST0 : FPrST0Inst <0xF0, "fdiv{|r} {%ST(0), $op|$op, %ST(0)}">; +def FDIVRPrST0 : FPrST0PInst<0xF0, "fdiv{|r}p $op">; -def FSUBST0r : FPST0rInst <0xE0, (ops RST:$op), - "fsub $op">; -def FSUBRrST0 : FPrST0Inst <0xE0, (ops RST:$op), - "fsub{|r} {%ST(0), $op|$op, %ST(0)}">; -def FSUBRPrST0 : FPrST0PInst<0xE0, (ops RST:$op), - "fsub{|r}p $op">; +// Floating point compares. +def FpUCOMr : FpI<(ops RST:$lhs, RST:$rhs), CompareFP, + []>; // FPSW = cmp ST(0) with ST(i) +def FpUCOMIr : FpI<(ops RST:$lhs, RST:$rhs), CompareFP, + []>; // CC = cmp ST(0) with ST(i) -def FMULST0r : FPST0rInst <0xC8, (ops RST:$op), - "fmul $op">; -def FMULrST0 : FPrST0Inst <0xC8, (ops RST:$op), - "fmul {%ST(0), $op|$op, %ST(0)}">; -def FMULPrST0 : FPrST0PInst<0xC8, (ops RST:$op), - "fmulp $op">; +def FUCOMr : FPI<0xE0, AddRegFrm, // FPSW = cmp ST(0) with ST(i) + (ops RST:$reg), + "fucom $reg">, DD, Imp<[ST0],[]>; +def FUCOMPr : FPI<0xE8, AddRegFrm, // FPSW = cmp ST(0) with ST(i), pop + (ops RST:$reg), + "fucomp $reg">, DD, Imp<[ST0],[]>; +def FUCOMPPr : FPI<0xE9, RawFrm, // cmp ST(0) with ST(1), pop, pop + (ops), + "fucompp">, DA, Imp<[ST0],[]>; -def FDIVRST0r : FPST0rInst <0xF8, (ops RST:$op), - "fdivr $op">; -def FDIVrST0 : FPrST0Inst <0xF8, (ops RST:$op), - "fdiv{r} {%ST(0), $op|$op, %ST(0)}">; -def FDIVPrST0 : FPrST0PInst<0xF8, (ops RST:$op), - "fdiv{r}p $op">; - -def FDIVST0r : FPST0rInst <0xF0, (ops RST:$op), // ST(0) = ST(0) / ST(i) - "fdiv $op">; -def FDIVRrST0 : FPrST0Inst <0xF0, (ops RST:$op), // ST(i) = ST(0) / ST(i) - "fdiv{|r} {%ST(0), $op|$op, %ST(0)}">; -def FDIVRPrST0 : FPrST0PInst<0xF0, (ops RST:$op), // ST(i) = ST(0) / ST(i), pop - "fdiv{|r}p $op">; - -// Floating point compares -def FUCOMr : FPI<0xE0, AddRegFrm, CompareFP, // FPSW = cmp ST(0) with ST(i) - (ops RST:$reg, variable_ops), - "fucom $reg", []>, DD, Imp<[ST0],[]>; -def FUCOMPr : I<0xE8, AddRegFrm, // FPSW = cmp ST(0) with ST(i), pop - (ops RST:$reg, variable_ops), - "fucomp $reg", []>, DD, Imp<[ST0],[]>; -def FUCOMPPr : I<0xE9, RawFrm, // cmp ST(0) with ST(1), pop, pop - (ops variable_ops), - "fucompp", []>, DA, Imp<[ST0],[]>; - -def FUCOMIr : FPI<0xE8, AddRegFrm, CompareFP, // CC = cmp ST(0) with ST(i) - (ops RST:$reg, variable_ops), - "fucomi {$reg, %ST(0)|%ST(0), $reg}", []>, DB, Imp<[ST0],[]>; -def FUCOMIPr : I<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i), pop - (ops RST:$reg, variable_ops), - "fucomip {$reg, %ST(0)|%ST(0), $reg}", []>, DF, Imp<[ST0],[]>; +def FUCOMIr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i) + (ops RST:$reg), + "fucomi {$reg, %ST(0)|%ST(0), $reg}">, DB, Imp<[ST0],[]>; +def FUCOMIPr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i), pop + (ops RST:$reg), + "fucomip {$reg, %ST(0)|%ST(0), $reg}">, DF, Imp<[ST0],[]>; -// Floating point flag ops +// Floating point flag ops. def FNSTSW8r : I<0xE0, RawFrm, // AX = fp flags (ops), "fnstsw", []>, DF, Imp<[],[AX]>; diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index a0e0aca16c2..765b657d065 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -56,7 +56,7 @@ void X86RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB, } else if (RC == &X86::R16RegClass) { Opc = X86::MOV16mr; } else if (RC == &X86::RFPRegClass || RC == &X86::RSTRegClass) { - Opc = X86::FST64m; + Opc = X86::FpST64m; } else if (RC == &X86::V4F4RegClass) { Opc = X86::MOVSSmr; } else if (RC == &X86::V2F8RegClass) { @@ -80,7 +80,7 @@ void X86RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, } else if (RC == &X86::R16RegClass) { Opc = X86::MOV16rm; } else if (RC == &X86::RFPRegClass || RC == &X86::RSTRegClass) { - Opc = X86::FLD64m; + Opc = X86::FpLD64m; } else if (RC == &X86::V4F4RegClass) { Opc = X86::MOVSSrm; } else if (RC == &X86::V2F8RegClass) { @@ -123,8 +123,7 @@ unsigned X86RegisterInfo::isLoadFromStackSlot(MachineInstr *MI, case X86::MOV8rm: case X86::MOV16rm: case X86::MOV32rm: - case X86::FLD64m: - case X86::FLD80m: + case X86::FpLD64m: case X86::MOVSSrm: case X86::MOVSDrm: if (MI->getOperand(1).isFrameIndex() && MI->getOperand(2).isImmediate() &&