X64: Change some fpu operations to use XMM registers.

Review URL: http://codereview.chromium.org/2827022

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4930 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
lrn@chromium.org 2010-06-23 14:05:18 +00:00
parent ca8298273a
commit 0dee9a7942
5 changed files with 125 additions and 52 deletions

View File

@ -2606,6 +2606,28 @@ void Assembler::movsd(XMMRegister dst, const Operand& src) {
} }
void Assembler::movss(XMMRegister dst, const Operand& src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0xF3); // single
emit_optional_rex_32(dst, src);
emit(0x0F);
emit(0x10); // load
emit_sse_operand(dst, src);
}
void Assembler::movss(const Operand& src, XMMRegister dst) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0xF3); // single
emit_optional_rex_32(dst, src);
emit(0x0F);
emit(0x11); // store
emit_sse_operand(dst, src);
}
void Assembler::cvttss2si(Register dst, const Operand& src) { void Assembler::cvttss2si(Register dst, const Operand& src) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
@ -2661,6 +2683,17 @@ void Assembler::cvtlsi2sd(XMMRegister dst, Register src) {
} }
void Assembler::cvtlsi2ss(XMMRegister dst, Register src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0xF3);
emit_optional_rex_32(dst, src);
emit(0x0F);
emit(0x2A);
emit_sse_operand(dst, src);
}
void Assembler::cvtqsi2sd(XMMRegister dst, Register src) { void Assembler::cvtqsi2sd(XMMRegister dst, Register src) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
@ -2683,6 +2716,28 @@ void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
} }
void Assembler::cvtss2sd(XMMRegister dst, const Operand& src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0xF3);
emit_optional_rex_32(dst, src);
emit(0x0F);
emit(0x5A);
emit_sse_operand(dst, src);
}
void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0xF2);
emit_optional_rex_32(dst, src);
emit(0x0F);
emit(0x5A);
emit_sse_operand(dst, src);
}
void Assembler::addsd(XMMRegister dst, XMMRegister src) { void Assembler::addsd(XMMRegister dst, XMMRegister src) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
@ -2760,6 +2815,18 @@ void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
} }
void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0x66);
emit_optional_rex_32(dst, src);
emit(0x0f);
emit(0x2e);
emit_sse_operand(dst, src);
}
void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) { void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
Register ireg = { reg.code() }; Register ireg = { reg.code() };
emit_operand(ireg, adr); emit_operand(ireg, adr);

View File

@ -1110,6 +1110,9 @@ class Assembler : public Malloced {
void movsd(XMMRegister dst, XMMRegister src); void movsd(XMMRegister dst, XMMRegister src);
void movsd(XMMRegister dst, const Operand& src); void movsd(XMMRegister dst, const Operand& src);
void movss(XMMRegister dst, const Operand& src);
void movss(const Operand& dst, XMMRegister src);
void cvttss2si(Register dst, const Operand& src); void cvttss2si(Register dst, const Operand& src);
void cvttsd2si(Register dst, const Operand& src); void cvttsd2si(Register dst, const Operand& src);
void cvttsd2siq(Register dst, XMMRegister src); void cvttsd2siq(Register dst, XMMRegister src);
@ -1119,7 +1122,11 @@ class Assembler : public Malloced {
void cvtqsi2sd(XMMRegister dst, const Operand& src); void cvtqsi2sd(XMMRegister dst, const Operand& src);
void cvtqsi2sd(XMMRegister dst, Register src); void cvtqsi2sd(XMMRegister dst, Register src);
void cvtlsi2ss(XMMRegister dst, Register src);
void cvtss2sd(XMMRegister dst, XMMRegister src); void cvtss2sd(XMMRegister dst, XMMRegister src);
void cvtss2sd(XMMRegister dst, const Operand& src);
void cvtsd2ss(XMMRegister dst, XMMRegister src);
void addsd(XMMRegister dst, XMMRegister src); void addsd(XMMRegister dst, XMMRegister src);
void subsd(XMMRegister dst, XMMRegister src); void subsd(XMMRegister dst, XMMRegister src);
@ -1130,6 +1137,7 @@ class Assembler : public Malloced {
void sqrtsd(XMMRegister dst, XMMRegister src); void sqrtsd(XMMRegister dst, XMMRegister src);
void ucomisd(XMMRegister dst, XMMRegister src); void ucomisd(XMMRegister dst, XMMRegister src);
void ucomisd(XMMRegister dst, const Operand& src);
// The first argument is the reg field, the second argument is the r/m field. // The first argument is the reg field, the second argument is the r/m field.
void emit_sse_operand(XMMRegister dst, XMMRegister src); void emit_sse_operand(XMMRegister dst, XMMRegister src);

View File

@ -5336,9 +5336,8 @@ void CodeGenerator::ToBoolean(ControlDestination* dest) {
dest->false_target()->Branch(equal); dest->false_target()->Branch(equal);
Condition is_smi = masm_->CheckSmi(value.reg()); Condition is_smi = masm_->CheckSmi(value.reg());
dest->true_target()->Branch(is_smi); dest->true_target()->Branch(is_smi);
__ fldz(); __ xorpd(xmm0, xmm0);
__ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset)); __ ucomisd(xmm0, FieldOperand(value.reg(), HeapNumber::kValueOffset));
__ FCmp();
value.Unuse(); value.Unuse();
dest->Split(not_zero); dest->Split(not_zero);
} else { } else {
@ -8000,14 +7999,12 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
__ jmp(&true_result); __ jmp(&true_result);
__ bind(&not_string); __ bind(&not_string);
// HeapNumber => false iff +0, -0, or NaN.
// These three cases set C3 when compared to zero in the FPU.
__ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex);
__ j(not_equal, &true_result); __ j(not_equal, &true_result);
__ fldz(); // Load zero onto fp stack // HeapNumber => false iff +0, -0, or NaN.
// Load heap-number double value onto fp stack // These three cases set the zero flag when compared to zero using ucomisd.
__ fld_d(FieldOperand(rax, HeapNumber::kValueOffset)); __ xorpd(xmm0, xmm0);
__ FCmp(); __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
__ j(zero, &false_result); __ j(zero, &false_result);
// Fall through to |true_result|. // Fall through to |true_result|.

View File

@ -1057,7 +1057,7 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
// CVTSI2SD: integer to XMM double conversion. // CVTSI2SD: integer to XMM double conversion.
int mod, regop, rm; int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm); get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop)); AppendToBuffer("%sd %s,", mnemonic, NameOfXMMRegister(regop));
current += PrintRightOperand(current); current += PrintRightOperand(current);
} else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) { } else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
// XMM arithmetic. Mnemonic was retrieved at the start of this function. // XMM arithmetic. Mnemonic was retrieved at the start of this function.
@ -1070,7 +1070,25 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
} }
} else if (group_1_prefix_ == 0xF3) { } else if (group_1_prefix_ == 0xF3) {
// Instructions with prefix 0xF3. // Instructions with prefix 0xF3.
if (opcode == 0x2C) { if (opcode == 0x11 || opcode == 0x10) {
// MOVSS: Move scalar double-precision fp to/from/between XMM registers.
AppendToBuffer("movss ");
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
if (opcode == 0x11) {
current += PrintRightOperand(current);
AppendToBuffer(",%s", NameOfXMMRegister(regop));
} else {
AppendToBuffer("%s,", NameOfXMMRegister(regop));
current += PrintRightOperand(current);
}
} else if (opcode == 0x2A) {
// CVTSI2SS: integer to XMM single conversion.
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("%ss %s,", mnemonic, NameOfXMMRegister(regop));
current += PrintRightOperand(current);
} else if (opcode == 0x2C) {
// CVTTSS2SI: Convert scalar single-precision FP to dword integer. // CVTTSS2SI: Convert scalar single-precision FP to dword integer.
// Assert that mod is not 3, so source is memory, not an XMM register. // Assert that mod is not 3, so source is memory, not an XMM register.
ASSERT_NE(0xC0, *current & 0xC0); ASSERT_NE(0xC0, *current & 0xC0);
@ -1146,8 +1164,8 @@ const char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
switch (opcode) { switch (opcode) {
case 0x1F: case 0x1F:
return "nop"; return "nop";
case 0x2A: // F2 prefix. case 0x2A: // F2/F3 prefix.
return "cvtsi2sd"; return "cvtsi2s";
case 0x31: case 0x31:
return "rdtsc"; return "rdtsc";
case 0x51: // F2 prefix. case 0x51: // F2 prefix.

View File

@ -702,7 +702,7 @@ void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
// -- rdx : receiver // -- rdx : receiver
// -- rsp[0] : return address // -- rsp[0] : return address
// ----------------------------------- // -----------------------------------
Label slow, failed_allocation; Label slow;
// Check that the object isn't a smi. // Check that the object isn't a smi.
__ JumpIfSmi(rdx, &slow); __ JumpIfSmi(rdx, &slow);
@ -761,7 +761,7 @@ void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
__ movl(rcx, Operand(rbx, rcx, times_4, 0)); __ movl(rcx, Operand(rbx, rcx, times_4, 0));
break; break;
case kExternalFloatArray: case kExternalFloatArray:
__ fld_s(Operand(rbx, rcx, times_4, 0)); __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
@ -773,20 +773,16 @@ void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
// For integer array types: // For integer array types:
// rcx: value // rcx: value
// For floating-point array type: // For floating-point array type:
// FP(0): value // xmm0: value as double.
if (array_type == kExternalIntArray || ASSERT(kSmiValueSize == 32);
array_type == kExternalUnsignedIntArray) { if (array_type == kExternalUnsignedIntArray) {
// For the Int and UnsignedInt array types, we need to see whether // For the UnsignedInt array type, we need to see whether
// the value can be represented in a Smi. If not, we need to convert // the value can be represented in a Smi. If not, we need to convert
// it to a HeapNumber. // it to a HeapNumber.
Label box_int; Label box_int;
if (array_type == kExternalIntArray) {
__ JumpIfNotValidSmiValue(rcx, &box_int); __ JumpIfUIntNotValidSmiValue(rcx, &box_int);
} else {
ASSERT_EQ(array_type, kExternalUnsignedIntArray);
__ JumpIfUIntNotValidSmiValue(rcx, &box_int);
}
__ Integer32ToSmi(rax, rcx); __ Integer32ToSmi(rax, rcx);
__ ret(0); __ ret(0);
@ -795,42 +791,29 @@ void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
// Allocate a HeapNumber for the int and perform int-to-double // Allocate a HeapNumber for the int and perform int-to-double
// conversion. // conversion.
__ push(rcx); ASSERT(array_type == kExternalUnsignedIntArray);
if (array_type == kExternalIntArray) { // The value is zero-extended since we loaded the value from memory
__ fild_s(Operand(rsp, 0)); // with movl.
} else { __ cvtqsi2sd(xmm0, rcx);
ASSERT(array_type == kExternalUnsignedIntArray);
// The value is zero-extended on the stack, because all pushes are __ AllocateHeapNumber(rcx, rbx, &slow);
// 64-bit and we loaded the value from memory with movl.
__ fild_d(Operand(rsp, 0));
}
__ pop(rcx);
// FP(0): value
__ AllocateHeapNumber(rcx, rbx, &failed_allocation);
// Set the value. // Set the value.
__ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
__ movq(rax, rcx); __ movq(rax, rcx);
__ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
__ ret(0); __ ret(0);
} else if (array_type == kExternalFloatArray) { } else if (array_type == kExternalFloatArray) {
// For the floating-point array type, we need to always allocate a // For the floating-point array type, we need to always allocate a
// HeapNumber. // HeapNumber.
__ AllocateHeapNumber(rcx, rbx, &failed_allocation); __ AllocateHeapNumber(rcx, rbx, &slow);
// Set the value. // Set the value.
__ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
__ movq(rax, rcx); __ movq(rax, rcx);
__ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
__ ret(0); __ ret(0);
} else { } else {
__ Integer32ToSmi(rax, rcx); __ Integer32ToSmi(rax, rcx);
__ ret(0); __ ret(0);
} }
// If we fail allocation of the HeapNumber, we still have a value on
// top of the FPU stack. Remove it.
__ bind(&failed_allocation);
__ ffree();
__ fincstp();
// Fall through to slow case.
// Slow case: Jump to runtime. // Slow case: Jump to runtime.
__ bind(&slow); __ bind(&slow);
__ IncrementCounter(&Counters::keyed_load_external_array_slow, 1); __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
@ -1116,10 +1099,8 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
break; break;
case kExternalFloatArray: case kExternalFloatArray:
// Need to perform int-to-float conversion. // Need to perform int-to-float conversion.
__ push(rdx); __ cvtlsi2ss(xmm0, rdx);
__ fild_s(Operand(rsp, 0)); __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
__ pop(rdx);
__ fstp_s(Operand(rbx, rdi, times_4, 0));
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
@ -1156,6 +1137,8 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
__ j(parity_even, &is_nan); __ j(parity_even, &is_nan);
__ push(rdx); // Make room on the stack. Receiver is no longer needed. __ push(rdx); // Make room on the stack. Receiver is no longer needed.
// TODO(lrn): If the rounding of this conversion is not deliberate, maybe
// switch to xmm registers.
__ fistp_d(Operand(rsp, 0)); __ fistp_d(Operand(rsp, 0));
__ pop(rdx); __ pop(rdx);
// rdx: value (converted to an untagged integer) // rdx: value (converted to an untagged integer)
@ -1201,7 +1184,7 @@ void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
// rbx: base pointer of external storage // rbx: base pointer of external storage
__ ffree(); __ ffree();
__ fincstp(); __ fincstp();
__ movq(rdx, Immediate(0)); __ Set(rdx, 0);
switch (array_type) { switch (array_type) {
case kExternalByteArray: case kExternalByteArray:
case kExternalUnsignedByteArray: case kExternalUnsignedByteArray: