__ cvtsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
break;
case kSSEUint32ToFloat64:
- // TODO(turbofan): IA32 SSE LoadUint32() should take an operand.
- __ LoadUint32(i.OutputDoubleRegister(), i.InputRegister(0));
+ __ LoadUint32(i.OutputDoubleRegister(), i.InputOperand(0));
break;
case kIA32Movsxbl:
__ movsx_b(i.OutputRegister(), i.MemoryOperand());
// -----------------------------------------------------------------------------
+// Conversions.
+
+TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) {
+ StreamBuilder m(this, kMachFloat64, kMachUint32);
+ m.Return(m.ChangeUint32ToFloat64(m.Parameter(0)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode());
+}
+
+
+// -----------------------------------------------------------------------------
// Loads and stores
namespace {
void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
IA32OperandGenerator g(this);
- // TODO(turbofan): IA32 SSE LoadUint32() should take an operand.
- Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node),
- g.UseRegister(node->InputAt(0)));
+ Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}
}
break;
case kSSEUint32ToFloat64:
- // TODO(turbofan): X64 SSE cvtqsi2sd should support operands.
- __ cvtqsi2sd(i.OutputDoubleRegister(), i.InputRegister(0));
+ if (instr->InputAt(0)->IsRegister()) {
+ __ cvtqsi2sd(i.OutputDoubleRegister(), i.InputRegister(0));
+ } else {
+ __ cvtqsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
+ }
break;
case kX64Movsxbl:
__ movsxbl(i.OutputRegister(), i.MemoryOperand());
}
+TEST_F(InstructionSelectorTest, ChangeUint32ToFloat64WithParameter) {
+ StreamBuilder m(this, kMachFloat64, kMachUint32);
+ m.Return(m.ChangeUint32ToFloat64(m.Parameter(0)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kSSEUint32ToFloat64, s[0]->arch_opcode());
+}
+
+
TEST_F(InstructionSelectorTest, ChangeUint32ToUint64WithParameter) {
StreamBuilder m(this, kMachUint64, kMachUint32);
m.Return(m.ChangeUint32ToUint64(m.Parameter(0)));
void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
X64OperandGenerator g(this);
- // TODO(turbofan): X64 SSE cvtqsi2sd should support operands.
- Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node),
- g.UseRegister(node->InputAt(0)));
+ Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}
}
-void MacroAssembler::LoadUint32(XMMRegister dst,
- Register src) {
+void MacroAssembler::LoadUint32(XMMRegister dst, const Operand& src) {
Label done;
cmp(src, Immediate(0));
- ExternalReference uint32_bias =
- ExternalReference::address_of_uint32_bias();
+ ExternalReference uint32_bias = ExternalReference::address_of_uint32_bias();
Cvtsi2sd(dst, src);
j(not_sign, &done, Label::kNear);
addsd(dst, Operand::StaticVariable(uint32_bias));
j(not_carry, is_smi);
}
- void LoadUint32(XMMRegister dst, Register src);
+ void LoadUint32(XMMRegister dst, Register src) {
+ LoadUint32(dst, Operand(src));
+ }
+ void LoadUint32(XMMRegister dst, const Operand& src);
// Jump the register contains a smi.
inline void JumpIfSmi(Register value,
}
+void Assembler::cvtqsi2sd(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ emit(0xF2);
+ emit_rex_64(dst, src);
+ emit(0x0F);
+ emit(0x2A);
+ emit_sse_operand(dst, src);
+}
+
+
void Assembler::cvtqsi2sd(XMMRegister dst, Register src) {
EnsureSpace ensure_space(this);
emit(0xF2);
}
+TEST(RunChangeUint32ToFloat64_spilled) {
+ RawMachineAssemblerTester<int32_t> m;
+ const int kNumInputs = 32;
+ int32_t magic = 0x786234;
+ uint32_t input[kNumInputs];
+ double result[kNumInputs];
+ Node* input_node[kNumInputs];
+
+ for (int i = 0; i < kNumInputs; i++) {
+ input_node[i] =
+ m.Load(kMachUint32, m.PointerConstant(&input), m.Int32Constant(i * 4));
+ }
+
+ for (int i = 0; i < kNumInputs; i++) {
+ m.Store(kMachFloat64, m.PointerConstant(&result), m.Int32Constant(i * 8),
+ m.ChangeUint32ToFloat64(input_node[i]));
+ }
+
+ m.Return(m.Int32Constant(magic));
+
+ for (int i = 0; i < kNumInputs; i++) {
+ input[i] = 100 + i;
+ }
+
+ CHECK_EQ(magic, m.Call());
+
+ for (int i = 0; i < kNumInputs; i++) {
+ CHECK_EQ(result[i], static_cast<double>(100 + i));
+ }
+}
+
+
TEST(RunChangeFloat64ToInt32_A) {
RawMachineAssemblerTester<int32_t> m;
int32_t magic = 0x786234;
__ cvttsd2si(rdx, xmm1);
__ cvttsd2siq(rdx, xmm1);
__ cvttsd2siq(rdx, Operand(rbx, rcx, times_4, 10000));
+ __ cvtqsi2sd(xmm1, Operand(rbx, rcx, times_4, 10000));
+ __ cvtqsi2sd(xmm1, rdx);
__ movsd(xmm1, Operand(rbx, rcx, times_4, 10000));
__ movsd(Operand(rbx, rcx, times_4, 10000), xmm1);
// 128 bit move instructions.