Fix x86 type conversions. test-art-host-oat passes.
- test-art-host-oat enabled in test builds.
- Created inline versions of float-to-int and double-to-int.
- Fixed calls to helper functions for long-to-float/double and
float/double-to-long.
- Removed storePair and replaced its use with storeBaseDispWide (fixes
iput-wide and aput-wide with doubles).
- Renamed helper functions to have art_ prefix.
- Fixed move-exception to store the result back.
- Fixed floating point comparison when the destination reg is the same as
a source. The typing would get confused since the source is floating
point, but the result is int, and a clobber is needed to overwrite the
expected result type. A similar thing happens in float/double-to-int.
Change-Id: I0a876072254411aa42d6acadb8723be030727219
diff --git a/src/compiler/codegen/x86/FP/X86FP.cc b/src/compiler/codegen/x86/FP/X86FP.cc
index 7c27eae..24cd7d3 100644
--- a/src/compiler/codegen/x86/FP/X86FP.cc
+++ b/src/compiler/codegen/x86/FP/X86FP.cc
@@ -124,7 +124,9 @@
RegLocation rlDest;
X86OpCode op = kX86Nop;
int srcReg;
+ int tempReg;
RegLocation rlResult;
+ LIR* branch = NULL;
switch (opcode) {
case Instruction::INT_TO_FLOAT:
longSrc = false;
@@ -151,14 +153,45 @@
op = kX86Cvtsi2sdRR;
break;
case Instruction::FLOAT_TO_INT:
+ rlSrc = oatGetSrc(cUnit, mir, 0);
+ rlSrc = loadValue(cUnit, rlSrc, kFPReg);
+ srcReg = rlSrc.lowReg;
+ rlDest = oatGetDest(cUnit, mir, 0);
+ oatClobberSReg(cUnit, rlDest.sRegLow);
+ rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ tempReg = oatAllocTempFloat(cUnit);
+
+ loadConstant(cUnit, rlResult.lowReg, 0x7fffffff);
+ newLIR2(cUnit, kX86Cvtsi2ssRR, tempReg, rlResult.lowReg);
+ newLIR2(cUnit, kX86ComissRR, srcReg, tempReg);
+ branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondA);
+ newLIR2(cUnit, kX86Cvtss2siRR, rlResult.lowReg, srcReg);
+ branch->target = newLIR0(cUnit, kPseudoTargetLabel);
+ storeValue(cUnit, rlDest, rlResult);
+ return false;
case Instruction::DOUBLE_TO_INT:
- // These are easy to implement inline except when the src is > MAX_INT/LONG the result
- // needs to be changed from 0x80000000 to 0x7FFFFFF (requires an in memory float/double
- // literal constant to compare against).
- UNIMPLEMENTED(WARNING) << "inline [df]2i " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
+ rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
+ rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
+ srcReg = rlSrc.lowReg;
+ rlDest = oatGetDest(cUnit, mir, 0);
+ oatClobberSReg(cUnit, rlDest.sRegLow);
+ rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ tempReg = oatAllocTempDouble(cUnit);
+
+ loadConstant(cUnit, rlResult.lowReg, 0x7fffffff);
+ newLIR2(cUnit, kX86Cvtsi2sdRR, tempReg, rlResult.lowReg);
+ newLIR2(cUnit, kX86ComisdRR, srcReg, tempReg);
+ branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondA);
+ newLIR2(cUnit, kX86Cvtsd2siRR, rlResult.lowReg, srcReg);
+ branch->target = newLIR0(cUnit, kPseudoTargetLabel);
+ storeValue(cUnit, rlDest, rlResult);
+ return false;
case Instruction::LONG_TO_DOUBLE:
- case Instruction::FLOAT_TO_LONG:
case Instruction::LONG_TO_FLOAT:
+ // These can be implemented inline by using memory as a 64-bit source.
+ // However, this can't be done easily if the register has been promoted.
+ UNIMPLEMENTED(WARNING) << "inline l2[df] " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
+ case Instruction::FLOAT_TO_LONG:
case Instruction::DOUBLE_TO_LONG:
return genConversionPortable(cUnit, mir);
default:
@@ -205,6 +238,7 @@
rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
srcReg2 = S2D(rlSrc2.lowReg, rlSrc2.highReg);
}
+ oatClobberSReg(cUnit, rlDest.sRegLow);
RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
loadConstantNoClobber(cUnit, rlResult.lowReg, unorderedGt ? 1 : 0);
if (single) {