aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2005-07-29 00:54:34 +0000
committerChris Lattner <sabre@nondot.org>2005-07-29 00:54:34 +0000
commitf7443dace5b7a08772af64ef748cf557e3f2bee2 (patch)
tree8901e25d868ea50120b023b62fae99d82f6278a7
parent745d5381195f0b1c05687378ec3d5925e59f0223 (diff)
downloadexternal_llvm-f7443dace5b7a08772af64ef748cf557e3f2bee2.zip
external_llvm-f7443dace5b7a08772af64ef748cf557e3f2bee2.tar.gz
external_llvm-f7443dace5b7a08772af64ef748cf557e3f2bee2.tar.bz2
Don't forget to diddle with the control word when performing an FISTP64.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22550 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/X86/X86ISelPattern.cpp44
1 files changed, 36 insertions, 8 deletions
diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp
index 9401d29..86260ae 100644
--- a/lib/Target/X86/X86ISelPattern.cpp
+++ b/lib/Target/X86/X86ISelPattern.cpp
@@ -54,11 +54,12 @@ namespace {
/// address) and two outputs (FP value and token chain).
FILD64m,
- /// FISTP64m - This instruction implements FP_TO_SINT with a
- /// 64-bit destination in memory and a FP reg source. This corresponds to
- /// the X86::FISTP64m instruction. It has two inputs (token chain and
- /// address) and two outputs (FP value and token chain).
- FISTP64m,
+ /// FP_TO_INT*_IN_MEM - This instruction implements FP_TO_SINT with the
+ /// integer destination in memory and a FP reg source. This corresponds
+ /// to the X86::FIST*m instructions and the rounding mode change stuff. It
+ /// has two inputs (token chain and address) and two outputs (FP value and
+ /// token chain).
+ FP_TO_INT64_IN_MEM,
/// CALL/TAILCALL - These operations represent an abstract X86 call
/// instruction, which includes a bunch of information. In particular the
@@ -988,10 +989,10 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
Ops.push_back(DAG.getEntryNode());
Ops.push_back(Op.getOperand(0));
Ops.push_back(StackSlot);
- SDOperand FISTP = DAG.getNode(X86ISD::FISTP64m, MVT::Other, Ops);
+ SDOperand FIST = DAG.getNode(X86ISD::FP_TO_INT64_IN_MEM, MVT::Other, Ops);
// Load the result.
- return DAG.getLoad(MVT::i64, FISTP, StackSlot, DAG.getSrcValue(NULL));
+ return DAG.getLoad(MVT::i64, FIST, StackSlot, DAG.getSrcValue(NULL));
}
}
}
@@ -4356,7 +4357,7 @@ void ISel::Select(SDOperand N) {
SelectExpr(N.getValue(0));
return;
- case X86ISD::FISTP64m: {
+ case X86ISD::FP_TO_INT64_IN_MEM: {
assert(N.getOperand(1).getValueType() == MVT::f64);
X86AddressMode AM;
Select(N.getOperand(0)); // Select the token chain
@@ -4369,7 +4370,34 @@ void ISel::Select(SDOperand N) {
SelectAddress(N.getOperand(2), AM);
ValReg = SelectExpr(N.getOperand(1));
}
+
+ // Change the floating point control register to use "round towards zero"
+ // mode when truncating to an integer value.
+ //
+ MachineFunction *F = BB->getParent();
+ int CWFrameIdx = F->getFrameInfo()->CreateStackObject(2, 2);
+ addFrameReference(BuildMI(BB, X86::FNSTCW16m, 4), CWFrameIdx);
+
+ // Load the old value of the high byte of the control word...
+ unsigned HighPartOfCW = MakeReg(MVT::i8);
+ addFrameReference(BuildMI(BB, X86::MOV8rm, 4, HighPartOfCW),
+ CWFrameIdx, 1);
+
+ // Set the high part to be round to zero...
+ addFrameReference(BuildMI(BB, X86::MOV8mi, 5),
+ CWFrameIdx, 1).addImm(12);
+
+ // Reload the modified control word now...
+ addFrameReference(BuildMI(BB, X86::FLDCW16m, 4), CWFrameIdx);
+
+ // Restore the memory image of control word to original value
+ addFrameReference(BuildMI(BB, X86::MOV8mr, 5),
+ CWFrameIdx, 1).addReg(HighPartOfCW);
+
addFullAddress(BuildMI(BB, X86::FISTP64m, 5), AM).addReg(ValReg);
+
+ // Reload the original control word now.
+ addFrameReference(BuildMI(BB, X86::FLDCW16m, 4), CWFrameIdx);
return;
}