Revision: 4930
Author: [email protected]
Date: Wed Jun 23 07:05:18 2010
Log: X64: Change some fpu operations to use XMM registers.
Review URL: http://codereview.chromium.org/2827022
http://code.google.com/p/v8/source/detail?r=4930
Modified:
/branches/bleeding_edge/src/x64/assembler-x64.cc
/branches/bleeding_edge/src/x64/assembler-x64.h
/branches/bleeding_edge/src/x64/codegen-x64.cc
/branches/bleeding_edge/src/x64/disasm-x64.cc
/branches/bleeding_edge/src/x64/ic-x64.cc
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.cc Wed Jun 23 04:48:30
2010
+++ /branches/bleeding_edge/src/x64/assembler-x64.cc Wed Jun 23 07:05:18
2010
@@ -2604,6 +2604,28 @@
emit(0x10); // load
emit_sse_operand(dst, 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) {
@@ -2659,6 +2681,17 @@
emit(0x2A);
emit_sse_operand(dst, 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) {
@@ -2681,6 +2714,28 @@
emit(0x5A);
emit_sse_operand(dst, 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) {
@@ -2760,6 +2815,18 @@
}
+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) {
Register ireg = { reg.code() };
emit_operand(ireg, adr);
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.h Wed Jun 23 04:48:30 2010
+++ /branches/bleeding_edge/src/x64/assembler-x64.h Wed Jun 23 07:05:18 2010
@@ -1110,6 +1110,9 @@
void movsd(XMMRegister dst, XMMRegister 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 cvttsd2si(Register dst, const Operand& src);
void cvttsd2siq(Register dst, XMMRegister src);
@@ -1119,7 +1122,11 @@
void cvtqsi2sd(XMMRegister dst, const Operand& src);
void cvtqsi2sd(XMMRegister dst, Register src);
+ void cvtlsi2ss(XMMRegister dst, Register 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 subsd(XMMRegister dst, XMMRegister src);
@@ -1130,6 +1137,7 @@
void sqrtsd(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.
void emit_sse_operand(XMMRegister dst, XMMRegister src);
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Wed Jun 23 02:21:32 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Wed Jun 23 07:05:18 2010
@@ -5336,9 +5336,8 @@
dest->false_target()->Branch(equal);
Condition is_smi = masm_->CheckSmi(value.reg());
dest->true_target()->Branch(is_smi);
- __ fldz();
- __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset));
- __ FCmp();
+ __ xorpd(xmm0, xmm0);
+ __ ucomisd(xmm0, FieldOperand(value.reg(), HeapNumber::kValueOffset));
value.Unuse();
dest->Split(not_zero);
} else {
@@ -8000,14 +7999,12 @@
__ jmp(&true_result);
__ 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);
__ j(not_equal, &true_result);
- __ fldz(); // Load zero onto fp stack
- // Load heap-number double value onto fp stack
- __ fld_d(FieldOperand(rax, HeapNumber::kValueOffset));
- __ FCmp();
+ // HeapNumber => false iff +0, -0, or NaN.
+ // These three cases set the zero flag when compared to zero using
ucomisd.
+ __ xorpd(xmm0, xmm0);
+ __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
__ j(zero, &false_result);
// Fall through to |true_result|.
=======================================
--- /branches/bleeding_edge/src/x64/disasm-x64.cc Wed Jun 23 04:48:30 2010
+++ /branches/bleeding_edge/src/x64/disasm-x64.cc Wed Jun 23 07:05:18 2010
@@ -1057,7 +1057,7 @@
// CVTSI2SD: integer to XMM double conversion.
int mod, regop, rm;
get_modrm(*current, &mod, ®op, &rm);
- AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
+ AppendToBuffer("%sd %s,", mnemonic, NameOfXMMRegister(regop));
current += PrintRightOperand(current);
} else if ((opcode & 0xF8) == 0x58 || opcode == 0x51) {
// XMM arithmetic. Mnemonic was retrieved at the start of this
function.
@@ -1070,7 +1070,25 @@
}
} else if (group_1_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.
// Assert that mod is not 3, so source is memory, not an XMM
register.
ASSERT_NE(0xC0, *current & 0xC0);
@@ -1146,8 +1164,8 @@
switch (opcode) {
case 0x1F:
return "nop";
- case 0x2A: // F2 prefix.
- return "cvtsi2sd";
+ case 0x2A: // F2/F3 prefix.
+ return "cvtsi2s";
case 0x31:
return "rdtsc";
case 0x51: // F2 prefix.
=======================================
--- /branches/bleeding_edge/src/x64/ic-x64.cc Wed Jun 23 02:10:21 2010
+++ /branches/bleeding_edge/src/x64/ic-x64.cc Wed Jun 23 07:05:18 2010
@@ -702,7 +702,7 @@
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
- Label slow, failed_allocation;
+ Label slow;
// Check that the object isn't a smi.
__ JumpIfSmi(rdx, &slow);
@@ -761,7 +761,7 @@
__ movl(rcx, Operand(rbx, rcx, times_4, 0));
break;
case kExternalFloatArray:
- __ fld_s(Operand(rbx, rcx, times_4, 0));
+ __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
break;
default:
UNREACHABLE();
@@ -773,20 +773,16 @@
// For integer array types:
// rcx: value
// For floating-point array type:
- // FP(0): value
-
- if (array_type == kExternalIntArray ||
- array_type == kExternalUnsignedIntArray) {
- // For the Int and UnsignedInt array types, we need to see whether
+ // xmm0: value as double.
+
+ ASSERT(kSmiValueSize == 32);
+ if (array_type == kExternalUnsignedIntArray) {
+ // For the UnsignedInt array type, we need to see whether
// the value can be represented in a Smi. If not, we need to convert
// it to a HeapNumber.
Label box_int;
- if (array_type == kExternalIntArray) {
- __ JumpIfNotValidSmiValue(rcx, &box_int);
- } else {
- ASSERT_EQ(array_type, kExternalUnsignedIntArray);
- __ JumpIfUIntNotValidSmiValue(rcx, &box_int);
- }
+
+ __ JumpIfUIntNotValidSmiValue(rcx, &box_int);
__ Integer32ToSmi(rax, rcx);
__ ret(0);
@@ -795,41 +791,28 @@
// Allocate a HeapNumber for the int and perform int-to-double
// conversion.
- __ push(rcx);
- if (array_type == kExternalIntArray) {
- __ fild_s(Operand(rsp, 0));
- } else {
- ASSERT(array_type == kExternalUnsignedIntArray);
- // The value is zero-extended on the stack, because all pushes are
- // 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);
+ ASSERT(array_type == kExternalUnsignedIntArray);
+ // The value is zero-extended since we loaded the value from memory
+ // with movl.
+ __ cvtqsi2sd(xmm0, rcx);
+
+ __ AllocateHeapNumber(rcx, rbx, &slow);
// Set the value.
+ __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
__ movq(rax, rcx);
- __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
__ ret(0);
} else if (array_type == kExternalFloatArray) {
// For the floating-point array type, we need to always allocate a
// HeapNumber.
- __ AllocateHeapNumber(rcx, rbx, &failed_allocation);
+ __ AllocateHeapNumber(rcx, rbx, &slow);
// Set the value.
+ __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
__ movq(rax, rcx);
- __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
__ ret(0);
} else {
__ Integer32ToSmi(rax, rcx);
__ 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.
__ bind(&slow);
@@ -1116,10 +1099,8 @@
break;
case kExternalFloatArray:
// Need to perform int-to-float conversion.
- __ push(rdx);
- __ fild_s(Operand(rsp, 0));
- __ pop(rdx);
- __ fstp_s(Operand(rbx, rdi, times_4, 0));
+ __ cvtlsi2ss(xmm0, rdx);
+ __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
break;
default:
UNREACHABLE();
@@ -1156,6 +1137,8 @@
__ j(parity_even, &is_nan);
__ 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));
__ pop(rdx);
// rdx: value (converted to an untagged integer)
@@ -1201,7 +1184,7 @@
// rbx: base pointer of external storage
__ ffree();
__ fincstp();
- __ movq(rdx, Immediate(0));
+ __ Set(rdx, 0);
switch (array_type) {
case kExternalByteArray:
case kExternalUnsignedByteArray:
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev