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:
parent
ca8298273a
commit
0dee9a7942
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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(¬_string);
|
__ bind(¬_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|.
|
||||||
|
|
||||||
|
@ -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, ®op, &rm);
|
get_modrm(*current, &mod, ®op, &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, ®op, &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, ®op, &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.
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user