}
-// The Probe method needs executable memory, so it uses Heap::CreateCode.
-// Allocation failure is silent and leads to safe default.
void CpuFeatures::Probe() {
ASSERT(!initialized_);
ASSERT(supported_ == 0);
}
-void Assembler::andps(XMMRegister dst, XMMRegister src) {
+void Assembler::andps(XMMRegister dst, const Operand& src) {
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x0F);
EMIT(0x54);
}
-void Assembler::orps(XMMRegister dst, XMMRegister src) {
+void Assembler::orps(XMMRegister dst, const Operand& src) {
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x0F);
EMIT(0x56);
}
-void Assembler::xorps(XMMRegister dst, XMMRegister src) {
+void Assembler::xorps(XMMRegister dst, const Operand& src) {
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x0F);
EMIT(0x57);
}
-void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
+void Assembler::addps(XMMRegister dst, const Operand& src) {
ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
- EMIT(0xF2);
EMIT(0x0F);
- EMIT(0x51);
+ EMIT(0x58);
emit_sse_operand(dst, src);
}
-void Assembler::andpd(XMMRegister dst, XMMRegister src) {
+void Assembler::subps(XMMRegister dst, const Operand& src) {
ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
- EMIT(0x66);
EMIT(0x0F);
- EMIT(0x54);
+ EMIT(0x5C);
emit_sse_operand(dst, src);
}
-void Assembler::orpd(XMMRegister dst, XMMRegister src) {
+void Assembler::mulps(XMMRegister dst, const Operand& src) {
+ ASSERT(IsEnabled(SSE2));
+ EnsureSpace ensure_space(this);
+ EMIT(0x0F);
+ EMIT(0x59);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::divps(XMMRegister dst, const Operand& src) {
+ ASSERT(IsEnabled(SSE2));
+ EnsureSpace ensure_space(this);
+ EMIT(0x0F);
+ EMIT(0x5E);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::sqrtsd(XMMRegister dst, XMMRegister src) {
+ ASSERT(IsEnabled(SSE2));
+ EnsureSpace ensure_space(this);
+ EMIT(0xF2);
+ EMIT(0x0F);
+ EMIT(0x51);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::andpd(XMMRegister dst, XMMRegister src) {
ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
- EMIT(0x56);
+ EMIT(0x54);
emit_sse_operand(dst, src);
}
-void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
+void Assembler::orpd(XMMRegister dst, XMMRegister src) {
ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
- EMIT(0x2E);
+ EMIT(0x56);
emit_sse_operand(dst, src);
}
}
+void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) {
+ ASSERT(IsEnabled(SSE2));
+ ASSERT(is_uint8(imm8));
+ EnsureSpace ensure_space(this);
+ EMIT(0x0F);
+ EMIT(0xC6);
+ emit_sse_operand(dst, src);
+ EMIT(imm8);
+}
+
+
void Assembler::movdqa(const Operand& dst, XMMRegister src) {
ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
}
-void Assembler::movsd(XMMRegister dst, XMMRegister src) {
- ASSERT(IsEnabled(SSE2));
- EnsureSpace ensure_space(this);
- EMIT(0xF2);
- EMIT(0x0F);
- EMIT(0x10);
- emit_sse_operand(dst, src);
-}
-
-
void Assembler::movss(const Operand& dst, XMMRegister src ) {
ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
}
-void Assembler::movss(XMMRegister dst, XMMRegister src) {
- ASSERT(IsEnabled(SSE2));
- EnsureSpace ensure_space(this);
- EMIT(0xF3);
- EMIT(0x0F);
- EMIT(0x10);
- emit_sse_operand(dst, src);
-}
-
-
void Assembler::movd(XMMRegister dst, const Operand& src) {
ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
void cpuid();
// SSE instructions
- void andps(XMMRegister dst, XMMRegister src);
- void xorps(XMMRegister dst, XMMRegister src);
- void orps(XMMRegister dst, XMMRegister src);
+ void movaps(XMMRegister dst, XMMRegister src);
+ void shufps(XMMRegister dst, XMMRegister src, byte imm8);
+
+ void andps(XMMRegister dst, const Operand& src);
+ void andps(XMMRegister dst, XMMRegister src) { andps(dst, Operand(src)); }
+ void xorps(XMMRegister dst, const Operand& src);
+ void xorps(XMMRegister dst, XMMRegister src) { xorps(dst, Operand(src)); }
+ void orps(XMMRegister dst, const Operand& src);
+ void orps(XMMRegister dst, XMMRegister src) { orps(dst, Operand(src)); }
+
+ void addps(XMMRegister dst, const Operand& src);
+ void addps(XMMRegister dst, XMMRegister src) { addps(dst, Operand(src)); }
+ void subps(XMMRegister dst, const Operand& src);
+ void subps(XMMRegister dst, XMMRegister src) { subps(dst, Operand(src)); }
+ void mulps(XMMRegister dst, const Operand& src);
+ void mulps(XMMRegister dst, XMMRegister src) { mulps(dst, Operand(src)); }
+ void divps(XMMRegister dst, const Operand& src);
+ void divps(XMMRegister dst, XMMRegister src) { divps(dst, Operand(src)); }
// SSE2 instructions
void cvttss2si(Register dst, const Operand& src);
+ void cvttss2si(Register dst, XMMRegister src) {
+ cvttss2si(dst, Operand(src));
+ }
void cvttsd2si(Register dst, const Operand& src);
void cvtsd2si(Register dst, XMMRegister src);
void andpd(XMMRegister dst, XMMRegister src);
void orpd(XMMRegister dst, XMMRegister src);
- void ucomisd(XMMRegister dst, XMMRegister src);
+ void ucomisd(XMMRegister dst, XMMRegister src) { ucomisd(dst, Operand(src)); }
void ucomisd(XMMRegister dst, const Operand& src);
enum RoundingMode {
void cmpltsd(XMMRegister dst, XMMRegister src);
void pcmpeqd(XMMRegister dst, XMMRegister src);
- void movaps(XMMRegister dst, XMMRegister src);
-
void movdqa(XMMRegister dst, const Operand& src);
void movdqa(const Operand& dst, XMMRegister src);
void movdqu(XMMRegister dst, const Operand& src);
void movd(XMMRegister dst, const Operand& src);
void movd(Register dst, XMMRegister src) { movd(Operand(dst), src); }
void movd(const Operand& dst, XMMRegister src);
- void movsd(XMMRegister dst, XMMRegister src);
+ void movsd(XMMRegister dst, XMMRegister src) { movsd(dst, Operand(src)); }
void movsd(XMMRegister dst, const Operand& src);
void movsd(const Operand& dst, XMMRegister src);
void movss(XMMRegister dst, const Operand& src);
void movss(const Operand& dst, XMMRegister src);
- void movss(XMMRegister dst, XMMRegister src);
+ void movss(XMMRegister dst, XMMRegister src) { movss(dst, Operand(src)); }
void extractps(Register dst, XMMRegister src, byte imm8);
void pand(XMMRegister dst, XMMRegister src);
NameOfXMMRegister(regop),
NameOfXMMRegister(rm));
data++;
- } else if (f0byte == 0x54) {
+ } else if (f0byte >= 0x53 && f0byte <= 0x5F) {
+ const char* const pseudo_op[] = {
+ "rcpps",
+ "andps",
+ "andnps",
+ "orps",
+ "xorps",
+ "addps",
+ "mulps",
+ "cvtps2pd",
+ "cvtdq2ps",
+ "subps",
+ "minps",
+ "divps",
+ "maxps",
+ };
+
data += 2;
int mod, regop, rm;
get_modrm(*data, &mod, ®op, &rm);
- AppendToBuffer("andps %s,%s",
- NameOfXMMRegister(regop),
- NameOfXMMRegister(rm));
- data++;
- } else if (f0byte == 0x56) {
+ AppendToBuffer("%s %s,",
+ pseudo_op[f0byte - 0x53],
+ NameOfXMMRegister(regop));
+ data += PrintRightXMMOperand(data);
+ } else if (f0byte == 0x50) {
data += 2;
int mod, regop, rm;
get_modrm(*data, &mod, ®op, &rm);
- AppendToBuffer("orps %s,%s",
- NameOfXMMRegister(regop),
+ AppendToBuffer("movmskps %s,%s",
+ NameOfCPURegister(regop),
NameOfXMMRegister(rm));
data++;
- } else if (f0byte == 0x57) {
+ } else if (f0byte== 0xC6) {
+ // shufps xmm, xmm/m128, imm8
data += 2;
int mod, regop, rm;
get_modrm(*data, &mod, ®op, &rm);
- AppendToBuffer("xorps %s,%s",
- NameOfXMMRegister(regop),
- NameOfXMMRegister(rm));
- data++;
- } else if (f0byte == 0x50) {
+ int8_t imm8 = static_cast<int8_t>(data[1]);
+ AppendToBuffer("shufps %s,%s,%d",
+ NameOfXMMRegister(rm),
+ NameOfXMMRegister(regop),
+ static_cast<int>(imm8));
data += 2;
- int mod, regop, rm;
- get_modrm(*data, &mod, ®op, &rm);
- AppendToBuffer("movmskps %s,%s",
- NameOfCPURegister(regop),
- NameOfXMMRegister(rm));
- data++;
} else if ((f0byte & 0xF0) == 0x80) {
data += JumpConditional(data, branch_hint);
} else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
ASSERT(cpu.has_sse2());
probed_features |= static_cast<uint64_t>(1) << SSE2;
- // CMOD must be available on every x64 CPU.
+ // CMOV must be available on every x64 CPU.
ASSERT(cpu.has_cmov());
probed_features |= static_cast<uint64_t>(1) << CMOV;
}
+void Assembler::andps(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0x54);
+ emit_sse_operand(dst, src);
+}
+
+
void Assembler::orps(XMMRegister dst, XMMRegister src) {
EnsureSpace ensure_space(this);
emit_optional_rex_32(dst, src);
}
+void Assembler::orps(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0x56);
+ emit_sse_operand(dst, src);
+}
+
+
void Assembler::xorps(XMMRegister dst, XMMRegister src) {
EnsureSpace ensure_space(this);
emit_optional_rex_32(dst, src);
}
+void Assembler::xorps(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0x57);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::addps(XMMRegister dst, XMMRegister src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0x58);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::addps(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0x58);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::subps(XMMRegister dst, XMMRegister src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0x5C);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::subps(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0x5C);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::mulps(XMMRegister dst, XMMRegister src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0x59);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::mulps(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0x59);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::divps(XMMRegister dst, XMMRegister src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0x5E);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::divps(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0x5E);
+ emit_sse_operand(dst, src);
+}
+
+
// SSE 2 operations.
void Assembler::movd(XMMRegister dst, Register src) {
}
+void Assembler::shufps(XMMRegister dst, XMMRegister src, byte imm8) {
+ ASSERT(is_uint8(imm8));
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(src, dst);
+ emit(0x0F);
+ emit(0xC6);
+ emit_sse_operand(dst, src);
+ emit(imm8);
+}
+
+
void Assembler::movapd(XMMRegister dst, XMMRegister src) {
EnsureSpace ensure_space(this);
if (src.low_bits() == 4) {
void movaps(XMMRegister dst, XMMRegister src);
void movss(XMMRegister dst, const Operand& src);
void movss(const Operand& dst, XMMRegister src);
+ void shufps(XMMRegister dst, XMMRegister src, byte imm8);
void cvttss2si(Register dst, const Operand& src);
void cvttss2si(Register dst, XMMRegister src);
void cvtlsi2ss(XMMRegister dst, Register src);
void andps(XMMRegister dst, XMMRegister src);
+ void andps(XMMRegister dst, const Operand& src);
void orps(XMMRegister dst, XMMRegister src);
+ void orps(XMMRegister dst, const Operand& src);
void xorps(XMMRegister dst, XMMRegister src);
+ void xorps(XMMRegister dst, const Operand& src);
+
+ void addps(XMMRegister dst, XMMRegister src);
+ void addps(XMMRegister dst, const Operand& src);
+ void subps(XMMRegister dst, XMMRegister src);
+ void subps(XMMRegister dst, const Operand& src);
+ void mulps(XMMRegister dst, XMMRegister src);
+ void mulps(XMMRegister dst, const Operand& src);
+ void divps(XMMRegister dst, XMMRegister src);
+ void divps(XMMRegister dst, const Operand& src);
void movmskps(Register dst, XMMRegister src);
byte_size_operand_ = idesc.byte_size_operation;
current += PrintOperands(idesc.mnem, idesc.op_order_, current);
- } else if (opcode == 0x54) {
- // andps xmm, xmm/m128
+ } else if (opcode >= 0x53 && opcode <= 0x5F) {
+ const char* const pseudo_op[] = {
+ "rcpps",
+ "andps",
+ "andnps",
+ "orps",
+ "xorps",
+ "addps",
+ "mulps",
+ "cvtps2pd",
+ "cvtdq2ps",
+ "subps",
+ "minps",
+ "divps",
+ "maxps",
+ };
int mod, regop, rm;
get_modrm(*current, &mod, ®op, &rm);
- AppendToBuffer("andps %s,", NameOfXMMRegister(regop));
+ AppendToBuffer("%s %s,",
+ pseudo_op[opcode - 0x53],
+ NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
- } else if (opcode == 0x56) {
- // orps xmm, xmm/m128
+ } else if (opcode == 0xC6) {
+ // shufps xmm, xmm/m128, imm8
int mod, regop, rm;
get_modrm(*current, &mod, ®op, &rm);
- AppendToBuffer("orps %s,", NameOfXMMRegister(regop));
- current += PrintRightXMMOperand(current);
-
- } else if (opcode == 0x57) {
- // xorps xmm, xmm/m128
- int mod, regop, rm;
- get_modrm(*current, &mod, ®op, &rm);
- AppendToBuffer("xorps %s,", NameOfXMMRegister(regop));
+ AppendToBuffer("shufps %s, ", NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
+ AppendToBuffer(", %d", (*current) & 3);
+ current += 1;
} else if (opcode == 0x50) {
// movmskps reg, xmm
}
+typedef int (*F8)(float x, float y);
+TEST(AssemblerIa32SSE) {
+ CcTest::InitializeVM();
+ if (!CpuFeatures::IsSupported(SSE2)) return;
+
+ Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
+ HandleScope scope(isolate);
+ v8::internal::byte buffer[256];
+ MacroAssembler assm(isolate, buffer, sizeof buffer);
+ {
+ CpuFeatureScope fscope(&assm, SSE2);
+ __ movss(xmm0, Operand(esp, kPointerSize));
+ __ movss(xmm1, Operand(esp, 2 * kPointerSize));
+ __ shufps(xmm0, xmm0, 0x0);
+ __ shufps(xmm1, xmm1, 0x0);
+ __ movaps(xmm2, xmm1);
+ __ addps(xmm2, xmm0);
+ __ mulps(xmm2, xmm1);
+ __ subps(xmm2, xmm0);
+ __ divps(xmm2, xmm1);
+ __ cvttss2si(eax, xmm2);
+ __ ret(0);
+ }
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Code* code = Code::cast(isolate->heap()->CreateCode(
+ desc,
+ Code::ComputeFlags(Code::STUB),
+ Handle<Code>())->ToObjectChecked());
+ CHECK(code->IsCode());
+#ifdef OBJECT_PRINT
+ Code::cast(code)->Print();
+#endif
+
+ F8 f = FUNCTION_CAST<F8>(Code::cast(code)->entry());
+ CHECK_EQ(2, f(1.0, 2.0));
+}
+
+
#undef __
}
+typedef int (*F6)(float x, float y);
+TEST(AssemblerX64SSE) {
+ CcTest::InitializeVM();
+
+ Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
+ HandleScope scope(isolate);
+ v8::internal::byte buffer[256];
+ MacroAssembler assm(isolate, buffer, sizeof buffer);
+ {
+ __ shufps(xmm0, xmm0, 0x0); // brocast first argument
+ __ shufps(xmm1, xmm1, 0x0); // brocast second argument
+ __ movaps(xmm2, xmm1);
+ __ addps(xmm2, xmm0);
+ __ mulps(xmm2, xmm1);
+ __ subps(xmm2, xmm0);
+ __ divps(xmm2, xmm1);
+ __ cvttss2si(rax, xmm2);
+ __ ret(0);
+ }
+
+ CodeDesc desc;
+ assm.GetCode(&desc);
+ Code* code = Code::cast(isolate->heap()->CreateCode(
+ desc,
+ Code::ComputeFlags(Code::STUB),
+ Handle<Code>())->ToObjectChecked());
+ CHECK(code->IsCode());
+#ifdef OBJECT_PRINT
+ Code::cast(code)->Print();
+#endif
+
+ F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
+ CHECK_EQ(2, f(1.0, 2.0));
+}
#undef __
__ fcompp();
__ fwait();
__ nop();
+
+ // SSE instruction
+ {
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatureScope fscope(&assm, SSE2);
+ // Move operation
+ __ movaps(xmm0, xmm1);
+ __ shufps(xmm0, xmm0, 0x0);
+
+ // logic operation
+ __ andps(xmm0, xmm1);
+ __ andps(xmm0, Operand(ebx, ecx, times_4, 10000));
+ __ orps(xmm0, xmm1);
+ __ orps(xmm0, Operand(ebx, ecx, times_4, 10000));
+ __ xorps(xmm0, xmm1);
+ __ xorps(xmm0, Operand(ebx, ecx, times_4, 10000));
+
+ // Arithmetic operation
+ __ addps(xmm1, xmm0);
+ __ addps(xmm1, Operand(ebx, ecx, times_4, 10000));
+ __ subps(xmm1, xmm0);
+ __ subps(xmm1, Operand(ebx, ecx, times_4, 10000));
+ __ mulps(xmm1, xmm0);
+ __ mulps(xmm1, Operand(ebx, ecx, times_4, 10000));
+ __ divps(xmm1, xmm0);
+ __ divps(xmm1, Operand(ebx, ecx, times_4, 10000));
+ }
+ }
{
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope fscope(&assm, SSE2);
__ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000));
__ movsd(xmm1, Operand(ebx, ecx, times_4, 10000));
__ movsd(Operand(ebx, ecx, times_4, 10000), xmm1);
- __ movaps(xmm0, xmm1);
// 128 bit move instructions.
__ movdqa(xmm0, Operand(ebx, ecx, times_4, 10000));
__ movdqa(Operand(ebx, ecx, times_4, 10000), xmm0);
__ ucomisd(xmm0, xmm1);
__ cmpltsd(xmm0, xmm1);
- __ andps(xmm0, xmm1);
- __ orps(xmm0, xmm1);
__ andpd(xmm0, xmm1);
__ psllq(xmm0, 17);
__ psllq(xmm0, xmm1);
__ or_(rdx, Immediate(3));
__ xor_(rdx, Immediate(3));
__ nop();
- {
- CHECK(CpuFeatures::IsSupported(CPUID));
- CpuFeatures::Scope fscope(CPUID);
- __ cpuid();
- }
+ __ cpuid();
__ movsxbq(rdx, Operand(rcx, 0));
__ movsxwq(rdx, Operand(rcx, 0));
__ movzxbl(rdx, Operand(rcx, 0));
// SSE instruction
{
+ // Move operation
__ cvttss2si(rdx, Operand(rbx, rcx, times_4, 10000));
__ cvttss2si(rdx, xmm1);
__ movaps(xmm0, xmm1);
+ // logic operation
__ andps(xmm0, xmm1);
+ __ andps(xmm0, Operand(rbx, rcx, times_4, 10000));
__ orps(xmm0, xmm1);
+ __ ordps(xmm0, Operand(rbx, rcx, times_4, 10000));
__ xorps(xmm0, xmm1);
+ __ xordps(xmm0, Operand(rbx, rcx, times_4, 10000));
+
+ // Arithmetic operation
+ __ addps(xmm1, xmm0);
+ __ addps(xmm1, Operand(rbx, rcx, times_4, 10000));
+ __ subps(xmm1, xmm0);
+ __ subps(xmm1, Operand(rbx, rcx, times_4, 10000));
+ __ mulps(xmm1, xmm0);
+ __ mulps(xmm1, Operand(rbx, ecx, times_4, 10000));
+ __ divps(xmm1, xmm0);
+ __ divps(xmm1, Operand(rbx, rcx, times_4, 10000));
}
// SSE 2 instructions
{