Commit 73fcafd6 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Bring back the fisttp instruction on machines with SSE3, but check the

input so we don't have to check the exception flags afterwards.
Review URL: http://codereview.chromium.org/509001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3504 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e1b13fc3
......@@ -1675,6 +1675,15 @@ void Assembler::fisttp_s(const Operand& adr) {
}
void Assembler::fisttp_d(const Operand& adr) {
ASSERT(CpuFeatures::IsEnabled(SSE3));
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0xDD);
emit_operand(ecx, adr);
}
void Assembler::fist_s(const Operand& adr) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
......
......@@ -693,6 +693,7 @@ class Assembler : public Malloced {
void fistp_d(const Operand& adr);
void fisttp_s(const Operand& adr);
void fisttp_d(const Operand& adr);
void fabs();
void fchs();
......
......@@ -764,6 +764,7 @@ class FloatingPointHelper : public AllStatic {
// Takes the operands in edx and eax and loads them as integers in eax
// and ecx.
static void LoadAsIntegers(MacroAssembler* masm,
bool use_sse3,
Label* operand_conversion_failure);
// Test if operands are numbers (smi or HeapNumber objects), and load
// them into xmm0 and xmm1 if they are. Jump to label not_numbers if
......@@ -7268,6 +7269,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
Label operand_conversion_failure;
FloatingPointHelper::LoadAsIntegers(
masm,
use_sse3_,
&operand_conversion_failure);
switch (op_) {
case Token::BIT_OR: __ or_(eax, Operand(ecx)); break;
......@@ -7450,6 +7452,7 @@ void GenericBinaryOpStub::GenerateReturn(MacroAssembler* masm) {
// trashed registers.
void IntegerConvert(MacroAssembler* masm,
Register source,
bool use_sse3,
Label* conversion_failure) {
Label done, right_exponent, normal_exponent;
Register scratch = ebx;
......@@ -7459,6 +7462,22 @@ void IntegerConvert(MacroAssembler* masm,
// Get exponent alone in scratch2.
__ mov(scratch2, scratch);
__ and_(scratch2, HeapNumber::kExponentMask);
if (use_sse3) {
CpuFeatures::Scope scope(SSE3);
// Check whether the exponent is too big for a 64 bit signed integer.
const uint32_t too_big_exponent =
(HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
__ cmp(Operand(scratch2), Immediate(too_big_exponent));
__ j(greater_equal, conversion_failure);
// Load x87 register with heap number.
__ fld_d(FieldOperand(source, HeapNumber::kValueOffset));
// Reserve space for 64 bit answer.
__ sub(Operand(esp), Immediate(sizeof(uint64_t))); // Nolint.
// Do conversion, which cannot fail because we checked the exponent.
__ fisttp_d(Operand(esp, 0));
__ mov(ecx, Operand(esp, 0)); // Load low word of answer into ecx.
__ add(Operand(esp), Immediate(sizeof(uint64_t))); // Nolint.
} else {
// Load ecx with zero. We use this either for the final shift or
// for the answer.
__ xor_(ecx, Operand(ecx));
......@@ -7469,15 +7488,16 @@ void IntegerConvert(MacroAssembler* masm,
const uint32_t non_smi_exponent =
(HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift;
__ cmp(Operand(scratch2), Immediate(non_smi_exponent));
// If we have a match of the int32-but-not-Smi exponent then skip some logic.
// If we have a match of the int32-but-not-Smi exponent then skip some
// logic.
__ j(equal, &right_exponent);
// If the exponent is higher than that then go to slow case. This catches
// numbers that don't fit in a signed int32, infinities and NaNs.
__ j(less, &normal_exponent);
{
// Handle a big exponent. The only reason we have this code is that the >>>
// operator has a tendency to generate numbers with an exponent of 31.
// Handle a big exponent. The only reason we have this code is that the
// >>> operator has a tendency to generate numbers with an exponent of 31.
const uint32_t big_non_smi_exponent =
(HeapNumber::kExponentBias + 31) << HeapNumber::kExponentShift;
__ cmp(Operand(scratch2), Immediate(big_non_smi_exponent));
......@@ -7539,8 +7559,8 @@ void IntegerConvert(MacroAssembler* masm,
// actually need this because the bits get shifted out again, but
// it's probably slower to test than just to do it.
__ mov(scratch2, FieldOperand(source, HeapNumber::kMantissaOffset));
// Shift down 22 bits to get the most significant 10 bits or the low mantissa
// word.
// Shift down 22 bits to get the most significant 10 bits or the low
// mantissa word.
__ shr(scratch2, 32 - shift_distance);
__ or_(scratch2, Operand(scratch));
// Move down according to the exponent.
......@@ -7556,12 +7576,14 @@ void IntegerConvert(MacroAssembler* masm,
__ bind(&negative);
__ sub(ecx, Operand(scratch2));
__ bind(&done);
}
}
// Input: edx, eax are the left and right objects of a bit op.
// Output: eax, ecx are left and right integers for a bit op.
void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
bool use_sse3,
Label* conversion_failure) {
// Check float operands.
Label arg1_is_object, arg2_is_object, load_arg2;
......@@ -7577,7 +7599,7 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
__ cmp(ebx, Factory::heap_number_map());
__ j(not_equal, conversion_failure);
// Get the untagged integer version of the edx heap number in ecx.
IntegerConvert(masm, edx, conversion_failure);
IntegerConvert(masm, edx, use_sse3, conversion_failure);
__ mov(edx, ecx);
// Here edx has the untagged integer, eax has a Smi or a heap number.
......@@ -7594,7 +7616,7 @@ void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
__ cmp(ebx, Factory::heap_number_map());
__ j(not_equal, conversion_failure);
// Get the untagged integer version of the eax heap number in ecx.
IntegerConvert(masm, eax, conversion_failure);
IntegerConvert(masm, eax, use_sse3, conversion_failure);
__ bind(&done);
__ mov(eax, edx);
}
......
......@@ -638,6 +638,31 @@ function testShiftNonSmis() {
testShiftNonSmis();
function intConversion() {
function foo(x) {
assertEquals(x, (x * 1.0000000001) | 0, "foo more " + x);
assertEquals(x, x | 0, "foo " + x);
if (x > 0) {
assertEquals(x - 1, (x * 0.9999999999) | 0, "foo less " + x);
} else {
assertEquals(x + 1, (x * 0.9999999999) | 0, "foo less " + x);
}
}
for (var i = 1; i < 0x80000000; i *= 2) {
foo(i);
foo(-i);
}
for (var i = 1; i < 1/0; i *= 2) {
assertEquals(i | 0, (i * 1.0000000000000001) | 0, "b" + i);
assertEquals(-i | 0, (i * -1.0000000000000001) | 0, "c" + i);
}
for (var i = 0.5; i > 0; i /= 2) {
assertEquals(0, i | 0, "d" + i);
assertEquals(0, -i | 0, "e" + i);
}
}
intConversion();
// Verify that we handle the (optimized) corner case of shifting by
// zero even for non-smis.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment