bool CpuFeatures::initialized_ = false;
#endif
unsigned CpuFeatures::supported_ = 0;
-unsigned CpuFeatures::found_by_runtime_probing_ = 0;
+unsigned CpuFeatures::found_by_runtime_probing_only_ = 0;
ExternalReference ExternalReference::cpu_features() {
void CpuFeatures::Probe() {
- unsigned standard_features = static_cast<unsigned>(
+ uint64_t standard_features = static_cast<unsigned>(
OS::CpuFeaturesImpliedByPlatform()) | CpuFeaturesImpliedByCompiler();
ASSERT(supported_ == 0 || supported_ == standard_features);
#ifdef DEBUG
// For the simulator=arm build, use VFP when FLAG_enable_vfp3 is
// enabled. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6.
if (FLAG_enable_vfp3) {
- supported_ |= 1u << VFP3 | 1u << ARMv7 | 1u << VFP2;
+ supported_ |=
+ static_cast<uint64_t>(1) << VFP3 |
+ static_cast<uint64_t>(1) << ARMv7 |
+ static_cast<uint64_t>(1) << VFP2;
}
// For the simulator=arm build, use ARMv7 when FLAG_enable_armv7 is enabled
if (FLAG_enable_armv7) {
- supported_ |= 1u << ARMv7;
+ supported_ |= static_cast<uint64_t>(1) << ARMv7;
}
if (FLAG_enable_sudiv) {
- supported_ |= 1u << SUDIV;
+ supported_ |= static_cast<uint64_t>(1) << SUDIV;
}
if (FLAG_enable_movw_movt) {
- supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
+ supported_ |= static_cast<uint64_t>(1) << MOVW_MOVT_IMMEDIATE_LOADS;
}
if (FLAG_enable_32dregs) {
- supported_ |= 1u << VFP32DREGS;
+ supported_ |= static_cast<uint64_t>(1) << VFP32DREGS;
}
#else // __arm__
// This implementation also sets the VFP flags if runtime
// detection of VFP returns true. VFPv3 implies ARMv7 and VFP2, see ARM DDI
// 0406B, page A1-6.
- found_by_runtime_probing_ |= 1u << VFP3 | 1u << ARMv7 | 1u << VFP2;
+ found_by_runtime_probing_only_ |=
+ static_cast<uint64_t>(1) << VFP3 |
+ static_cast<uint64_t>(1) << ARMv7 |
+ static_cast<uint64_t>(1) << VFP2;
} else if (!IsSupported(VFP2) && OS::ArmCpuHasFeature(VFP2)) {
- found_by_runtime_probing_ |= 1u << VFP2;
+ found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << VFP2;
}
if (!IsSupported(ARMv7) && OS::ArmCpuHasFeature(ARMv7)) {
- found_by_runtime_probing_ |= 1u << ARMv7;
+ found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << ARMv7;
}
if (!IsSupported(SUDIV) && OS::ArmCpuHasFeature(SUDIV)) {
- found_by_runtime_probing_ |= 1u << SUDIV;
+ found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << SUDIV;
}
if (!IsSupported(UNALIGNED_ACCESSES) && OS::ArmCpuHasFeature(ARMv7)) {
- found_by_runtime_probing_ |= 1u << UNALIGNED_ACCESSES;
+ found_by_runtime_probing_only_ |=
+ static_cast<uint64_t>(1) << UNALIGNED_ACCESSES;
}
if (OS::GetCpuImplementer() == QUALCOMM_IMPLEMENTER &&
OS::ArmCpuHasFeature(ARMv7)) {
- found_by_runtime_probing_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
+ found_by_runtime_probing_only_ |=
+ static_cast<uint64_t>(1) << MOVW_MOVT_IMMEDIATE_LOADS;
}
if (!IsSupported(VFP32DREGS) && OS::ArmCpuHasFeature(VFP32DREGS)) {
- found_by_runtime_probing_ |= 1u << VFP32DREGS;
+ found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << VFP32DREGS;
}
- supported_ |= found_by_runtime_probing_;
+ supported_ |= found_by_runtime_probing_only_;
#endif
// Assert that VFP3 implies VFP2 and ARMv7.
void Assembler::ldrd(Register dst1, Register dst2,
const MemOperand& src, Condition cond) {
- ASSERT(CpuFeatures::IsEnabled(ARMv7));
+ ASSERT(IsEnabled(ARMv7));
ASSERT(src.rm().is(no_reg));
ASSERT(!dst1.is(lr)); // r14.
ASSERT_EQ(0, dst1.code() % 2);
ASSERT(!src1.is(lr)); // r14.
ASSERT_EQ(0, src1.code() % 2);
ASSERT_EQ(src1.code() + 1, src2.code());
- ASSERT(CpuFeatures::IsEnabled(ARMv7));
+ ASSERT(IsEnabled(ARMv7));
addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
}
// Instruction details available in ARM DDI 0406C.b, A8-924.
// cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) |
// Vd(15-12) | 1011(11-8) | offset
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int u = 1;
if (offset < 0) {
offset = -offset;
// Instruction details available in ARM DDI 0406A, A8-628.
// cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
// Vdst(15-12) | 1010(11-8) | offset
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int u = 1;
if (offset < 0) {
offset = -offset;
// Instruction details available in ARM DDI 0406C.b, A8-1082.
// cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) |
// Vd(15-12) | 1011(11-8) | (offset/4)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int u = 1;
if (offset < 0) {
offset = -offset;
// Instruction details available in ARM DDI 0406A, A8-786.
// cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
// Vdst(15-12) | 1010(11-8) | (offset/4)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int u = 1;
if (offset < 0) {
offset = -offset;
// Instruction details available in ARM DDI 0406C.b, A8-922.
// cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
// first(15-12) | 1011(11-8) | (count * 2)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
ASSERT_LE(first.code(), last.code());
ASSERT(am == ia || am == ia_w || am == db_w);
ASSERT(!base.is(pc));
// Instruction details available in ARM DDI 0406C.b, A8-1080.
// cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
// first(15-12) | 1011(11-8) | (count * 2)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
ASSERT_LE(first.code(), last.code());
ASSERT(am == ia || am == ia_w || am == db_w);
ASSERT(!base.is(pc));
// Instruction details available in ARM DDI 0406A, A8-626.
// cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
// first(15-12) | 1010(11-8) | (count/2)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
ASSERT_LE(first.code(), last.code());
ASSERT(am == ia || am == ia_w || am == db_w);
ASSERT(!base.is(pc));
// Instruction details available in ARM DDI 0406A, A8-784.
// cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
// first(15-12) | 1011(11-8) | (count/2)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
ASSERT_LE(first.code(), last.code());
ASSERT(am == ia || am == ia_w || am == db_w);
ASSERT(!base.is(pc));
void Assembler::vmov(const DwVfpRegister dst,
double imm,
const Register scratch) {
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
uint32_t enc;
if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) {
const Condition cond) {
// Sd = Sm
// Instruction details available in ARM DDI 0406B, A8-642.
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int sd, d, sm, m;
dst.split_code(&sd, &d);
src.split_code(&sm, &m);
// Instruction details available in ARM DDI 0406C.b, A8-938.
// cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
// 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int vd, d;
dst.split_code(&vd, &d);
int vm, m;
// Instruction details available in ARM DDI 0406C.b, A8-940.
// cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) |
// Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
ASSERT(index.index == 0 || index.index == 1);
int vd, d;
dst.split_code(&vd, &d);
// Instruction details available in ARM DDI 0406C.b, A8-948.
// cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
// Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
ASSERT(!src1.is(pc) && !src2.is(pc));
int vm, m;
dst.split_code(&vm, &m);
// Instruction details available in ARM DDI 0406C.b, A8-948.
// cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
// Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
ASSERT(!dst1.is(pc) && !dst2.is(pc));
int vm, m;
src.split_code(&vm, &m);
// Instruction details available in ARM DDI 0406A, A8-642.
// cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
// Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
ASSERT(!src.is(pc));
int sn, n;
dst.split_code(&sn, &n);
// Instruction details available in ARM DDI 0406A, A8-642.
// cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
// Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
ASSERT(!dst.is(pc));
int sn, n;
src.split_code(&sn, &n);
const SwVfpRegister src,
VFPConversionMode mode,
const Condition cond) {
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
}
const SwVfpRegister src,
VFPConversionMode mode,
const Condition cond) {
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
}
const SwVfpRegister src,
VFPConversionMode mode,
const Condition cond) {
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
}
const DwVfpRegister src,
VFPConversionMode mode,
const Condition cond) {
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
}
const DwVfpRegister src,
VFPConversionMode mode,
const Condition cond) {
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
}
const SwVfpRegister src,
VFPConversionMode mode,
const Condition cond) {
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
}
const DwVfpRegister src,
VFPConversionMode mode,
const Condition cond) {
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
}
// Instruction details available in ARM DDI 0406C.b, A8-968.
// cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
// 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int vd, d;
dst.split_code(&vd, &d);
int vm, m;
// Instruction details available in ARM DDI 0406C.b, A8-524.
// cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
// 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int vd, d;
dst.split_code(&vd, &d);
int vm, m;
// Instruction details available in ARM DDI 0406C.b, A8-830.
// cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
// Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int vd, d;
dst.split_code(&vd, &d);
int vn, n;
// Instruction details available in ARM DDI 0406C.b, A8-1086.
// cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
// Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int vd, d;
dst.split_code(&vd, &d);
int vn, n;
// Instruction details available in ARM DDI 0406C.b, A8-960.
// cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
// Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int vd, d;
dst.split_code(&vd, &d);
int vn, n;
// Instruction details available in ARM DDI 0406C.b, A8-882.
// cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
// Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int vd, d;
dst.split_code(&vd, &d);
int vn, n;
// Instruction details available in ARM DDI 0406C.b, A8-864.
// cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
// Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int vd, d;
src1.split_code(&vd, &d);
int vm, m;
// Instruction details available in ARM DDI 0406C.b, A8-864.
// cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
// Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
ASSERT(src2 == 0.0);
int vd, d;
src1.split_code(&vd, &d);
// Instruction details available in ARM DDI 0406A, A8-652.
// cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
// Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
emit(cond | 0xE*B24 | 0xE*B20 | B16 |
dst.code()*B12 | 0xA*B8 | B4);
}
// Instruction details available in ARM DDI 0406A, A8-652.
// cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
// Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
emit(cond | 0xE*B24 | 0xF*B20 | B16 |
dst.code()*B12 | 0xA*B8 | B4);
}
// Instruction details available in ARM DDI 0406C.b, A8-1058.
// cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
// Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
int vd, d;
dst.split_code(&vd, &d);
int vm, m;
namespace internal {
// CpuFeatures keeps track of which features are supported by the target CPU.
-// Supported features must be enabled by a Scope before use.
+// Supported features must be enabled by a CpuFeatureScope before use.
class CpuFeatures : public AllStatic {
public:
// Detect features of the target CPU. Set safe defaults if the serializer
return (supported_ & (1u << f)) != 0;
}
-#ifdef DEBUG
- // Check whether a feature is currently enabled.
- static bool IsEnabled(CpuFeature f) {
+ static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
ASSERT(initialized_);
- Isolate* isolate = Isolate::UncheckedCurrent();
- if (isolate == NULL) {
- // When no isolate is available, work as if we're running in
- // release mode.
- return IsSupported(f);
- }
- unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
- return (enabled & (1u << f)) != 0;
+ return (found_by_runtime_probing_only_ &
+ (static_cast<uint64_t>(1) << f)) != 0;
}
-#endif
-
- // Enable a specified feature within a scope.
- class Scope BASE_EMBEDDED {
-#ifdef DEBUG
-
- public:
- explicit Scope(CpuFeature f) {
- unsigned mask = 1u << f;
- // VFP2 and ARMv7 are implied by VFP3.
- if (f == VFP3) mask |= 1u << VFP2 | 1u << ARMv7;
- ASSERT(CpuFeatures::IsSupported(f));
- ASSERT(!Serializer::enabled() ||
- (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
- isolate_ = Isolate::UncheckedCurrent();
- old_enabled_ = 0;
- if (isolate_ != NULL) {
- old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
- isolate_->set_enabled_cpu_features(old_enabled_ | mask);
- }
- }
- ~Scope() {
- ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
- if (isolate_ != NULL) {
- isolate_->set_enabled_cpu_features(old_enabled_);
- }
- }
-
- private:
- Isolate* isolate_;
- unsigned old_enabled_;
-#else
-
- public:
- explicit Scope(CpuFeature f) {}
-#endif
- };
class TryForceFeatureScope BASE_EMBEDDED {
public:
static bool initialized_;
#endif
static unsigned supported_;
- static unsigned found_by_runtime_probing_;
+ static unsigned found_by_runtime_probing_only_;
friend class ExternalReference;
DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
Register scratch1,
Register scratch2) {
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ mov(scratch1, Operand(r0, ASR, kSmiTagSize));
__ vmov(d7.high(), scratch1);
__ vcvt_f64_s32(d7, d7.high());
// Handle loading a double from a heap number.
if (CpuFeatures::IsSupported(VFP2) &&
destination == kVFPRegisters) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
// Load the double from tagged HeapNumber to double register.
__ sub(scratch1, object, Operand(kHeapObjectTag));
__ vldr(dst, scratch1, HeapNumber::kValueOffset);
// Handle loading a double from a smi.
__ bind(&is_smi);
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
// Convert smi to double using VFP instructions.
__ vmov(dst.high(), scratch1);
__ vcvt_f64_s32(dst, dst.high());
Label done;
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ vmov(single_scratch, int_scratch);
__ vcvt_f64_s32(double_dst, single_scratch);
if (destination == kCoreRegisters) {
// Load the number.
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
// Load the double value.
__ sub(scratch1, object, Operand(kHeapObjectTag));
__ vldr(double_dst, scratch1, HeapNumber::kValueOffset);
// Object is a heap number.
// Convert the floating point value to a 32-bit integer.
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
// Load the double value.
__ sub(scratch1, object, Operand(kHeapObjectTag));
__ push(lr);
__ PrepareCallCFunction(0, 2, scratch);
if (masm->use_eabi_hardfloat()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ vmov(d0, r0, r1);
__ vmov(d1, r2, r3);
}
// Store answer in the overwritable heap number. Double returned in
// registers r0 and r1 or in d0.
if (masm->use_eabi_hardfloat()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ vstr(d0,
FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
} else {
// Lhs is a smi, rhs is a number.
if (CpuFeatures::IsSupported(VFP2)) {
// Convert lhs to a double in d7.
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ SmiToDoubleVFPRegister(lhs, d7, r7, s15);
// Load the double from rhs, tagged HeapNumber r0, to d6.
__ sub(r7, rhs, Operand(kHeapObjectTag));
// Rhs is a smi, lhs is a heap number.
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
// Load the double from lhs, tagged HeapNumber r1, to d7.
__ sub(r7, lhs, Operand(kHeapObjectTag));
__ vldr(d7, r7, HeapNumber::kValueOffset);
__ push(lr);
__ PrepareCallCFunction(0, 2, r5);
if (masm->use_eabi_hardfloat()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ vmov(d0, r0, r1);
__ vmov(d1, r2, r3);
}
// Both are heap numbers. Load them up then jump to the code we have
// for that.
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ sub(r7, rhs, Operand(kHeapObjectTag));
__ vldr(d6, r7, HeapNumber::kValueOffset);
__ sub(r7, lhs, Operand(kHeapObjectTag));
if (!object_is_smi) {
__ JumpIfSmi(object, &is_smi);
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ CheckMap(object,
scratch1,
Heap::kHeapNumberMapRootIndex,
Isolate* isolate = masm->isolate();
if (CpuFeatures::IsSupported(VFP2)) {
__ bind(&lhs_not_nan);
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
Label no_nan;
// ARMv7 VFP3 instructions to implement double precision comparison.
__ VFPCompareAndSetFlags(d7, d6);
__ b(ne, ¬_heap_number);
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset));
__ VFPCompareAndSetFlags(d1, 0.0);
const Register scratch = r1;
if (save_doubles_ == kSaveFPRegs) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
// Check CPU flags for number of registers, setting the Z condition flag.
__ CheckFor32DRegs(scratch);
ExternalReference::store_buffer_overflow_function(masm->isolate()),
argument_count);
if (save_doubles_ == kSaveFPRegs) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
// Check CPU flags for number of registers, setting the Z condition flag.
__ CheckFor32DRegs(scratch);
if (CpuFeatures::IsSupported(VFP2)) {
// Convert the int32 in r1 to the heap number in r0. r2 is corrupted.
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ vmov(s0, r1);
__ vcvt_f64_s32(d0, s0);
__ sub(r2, r0, Operand(kHeapObjectTag));
// Using VFP registers:
// d6: Left value
// d7: Right value
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
switch (op) {
case Token::ADD:
__ vadd(d5, d6, d7);
if (CpuFeatures::IsSupported(VFP2)) {
// Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As
// mentioned above SHR needs to always produce a positive result.
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ vmov(s0, r2);
if (op == Token::SHR) {
__ vcvt_f64_u32(d0, s0);
&transition);
if (destination == FloatingPointHelper::kVFPRegisters) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
Label return_heap_number;
switch (op_) {
case Token::ADD:
mode_);
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
if (op_ != Token::SHR) {
// Convert the result to a floating point value.
__ vmov(double_scratch.low(), r2);
const bool tagged = (argument_type_ == TAGGED);
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
if (tagged) {
// Argument is a number and is on stack and in r0.
// Load argument and check if it is a smi.
__ TailCallExternalReference(runtime_function, 1, 1);
} else {
ASSERT(CpuFeatures::IsSupported(VFP2));
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
Label no_update;
Label skip_cache;
void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm,
Register scratch) {
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(masm->IsEnabled(VFP2));
Isolate* isolate = masm->isolate();
__ push(lr);
void MathPowStub::Generate(MacroAssembler* masm) {
- CpuFeatures::Scope vfp2_scope(VFP2);
+ CpuFeatureScope vfp2_scope(masm, VFP2);
const Register base = r1;
const Register exponent = r2;
const Register heapnumbermap = r5;
// These stubs might already be in the snapshot, detect that and don't
// regenerate, which would lead to code stub initialization state being messed
// up.
- Code* save_doubles_code = NULL;
- Code* store_buffer_overflow_code = NULL;
- if (!save_doubles.FindCodeInCache(&save_doubles_code, ISOLATE)) {
- if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope2(VFP2);
- save_doubles_code = *save_doubles.GetCode(isolate);
- store_buffer_overflow_code = *stub.GetCode(isolate);
- } else {
- save_doubles_code = *save_doubles.GetCode(isolate);
- store_buffer_overflow_code = *stub.GetCode(isolate);
- }
+ Code* save_doubles_code;
+ if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) {
+ save_doubles_code = *save_doubles.GetCode(isolate);
save_doubles_code->set_is_pregenerated(true);
+
+ Code* store_buffer_overflow_code = *stub.GetCode(isolate);
store_buffer_overflow_code->set_is_pregenerated(true);
}
- ISOLATE->set_fp_stubs_generated(true);
+ isolate->set_fp_stubs_generated(true);
}
__ stm(db_w, sp, kCalleeSaved | lr.bit());
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
// Save callee-saved vfp registers.
__ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
// Set up the reserved register for 0.0.
#endif
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
// Restore callee-saved vfp registers.
__ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
}
// Inlining the double comparison and falling back to the general compare
// stub if NaN is involved or VFP2 is unsupported.
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
// Load left and right operand.
Label done, left, left_smi, right_smi;
if (mode == kSaveFPRegs) {
// Number of d-regs not known at snapshot time.
ASSERT(!Serializer::enabled());
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
masm->sub(sp,
sp,
Operand(kDoubleSize * (DwVfpRegister::NumRegisters() - 1)));
if (mode == kSaveFPRegs) {
// Number of d-regs not known at snapshot time.
ASSERT(!Serializer::enabled());
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
// Restore all VFP registers except d0.
// TODO(hans): We should probably restore d0 too. And maybe use vldm.
for (int i = DwVfpRegister::NumRegisters() - 1; i > 0; i--) {
MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
{
- CpuFeatures::Scope use_vfp(VFP2);
+ CpuFeatureScope use_vfp(&masm, VFP2);
DwVfpRegister input = d0;
DwVfpRegister result = d1;
DwVfpRegister double_scratch1 = d2;
// Normal smi, convert to double and store.
if (vfp2_supported) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ vmov(s0, r9);
__ vcvt_f64_s32(d0, s0);
__ vstr(d0, r7, 0);
kDoubleSize * DwVfpRegister::kMaxNumAllocatableRegisters;
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
// Save all allocatable VFP registers before messing with them.
ASSERT(kDoubleRegZero.code() == 14);
ASSERT(kScratchDoubleReg.code() == 15);
}
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
// Copy VFP registers to
// double_registers_[DoubleRegister::kMaxNumAllocatableRegisters]
int double_regs_offset = FrameDescription::double_registers_offset();
__ b(lt, &outer_push_loop);
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
// Check CPU flags for number of registers, setting the Z condition flag.
__ CheckFor32DRegs(ip);
__ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset));
__ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
// 0x41300000 is the top half of 1.0 x 2^20 as a double.
// Create this constant using mov/orr to avoid PC relative load.
__ mov(r1, Operand(0x41000000));
}
if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
Comment(";;; Save clobbered callee double registers");
int count = 0;
BitVector* doubles = chunk()->allocated_double_registers();
Label done;
if (CpuFeatures::IsSupported(SUDIV)) {
- CpuFeatures::Scope scope(SUDIV);
+ CpuFeatureScope scope(masm(), SUDIV);
// Check for x % 0.
if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
__ cmp(right, Operand::Zero());
Label vfp_modulo, both_positive, right_negative;
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
// Check for x % 0.
if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
__ teq(remainder, Operand(divisor), ne);
__ sub(result, result, Operand(1), LeaveCC, mi);
} else {
- CpuFeatures::Scope scope(SUDIV);
+ CpuFeatureScope scope(masm(), SUDIV);
const Register right = ToRegister(instr->right());
// Check for x / 0.
LOperand* left_argument,
LOperand* right_argument,
Token::Value op) {
- CpuFeatures::Scope vfp_scope(VFP2);
+ CpuFeatureScope vfp_scope(masm(), VFP2);
Register left = ToRegister(left_argument);
Register right = ToRegister(right_argument);
void LCodeGen::DoConstantD(LConstantD* instr) {
ASSERT(instr->result()->IsDoubleRegister());
DwVfpRegister result = ToDoubleRegister(instr->result());
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
double v = instr->value();
__ Vmov(result, v, scratch0());
}
__ mov(result_reg, right_op, LeaveCC, NegateCondition(condition));
} else {
ASSERT(instr->hydrogen()->representation().IsDouble());
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
DwVfpRegister left_reg = ToDoubleRegister(left);
DwVfpRegister right_reg = ToDoubleRegister(right);
DwVfpRegister result_reg = ToDoubleRegister(instr->result());
void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
DwVfpRegister left = ToDoubleRegister(instr->left());
DwVfpRegister right = ToDoubleRegister(instr->right());
DwVfpRegister result = ToDoubleRegister(instr->result());
__ cmp(reg, Operand::Zero());
EmitBranch(true_block, false_block, ne);
} else if (r.IsDouble()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
DwVfpRegister reg = ToDoubleRegister(instr->value());
Register scratch = scratch0();
}
if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
// heap number -> false iff +0, -0, or NaN.
DwVfpRegister dbl_scratch = double_scratch0();
Label not_heap_number;
EmitGoto(next_block);
} else {
if (instr->is_double()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
// Compare left and right operands as doubles and load the
// resulting flags into the normal status register.
__ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right));
__ CallRuntime(Runtime::kTraceExit, 1);
}
if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
ASSERT(NeedsEagerFrame());
BitVector* doubles = chunk()->allocated_double_registers();
BitVector::Iterator save_iterator(doubles);
: Operand(key, LSL, shift_size);
__ add(scratch0(), external_pointer, operand);
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
__ vldr(kScratchDoubleReg.low(), scratch0(), additional_offset);
__ vcvt_f64_f32(result, kScratchDoubleReg.low());
__ add(elements, elements, Operand(key, LSL, shift_size));
}
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
__ add(elements, elements, Operand(base_offset));
__ vldr(result, elements, 0);
if (instr->hydrogen()->RequiresHoleCheck()) {
void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
// Class for deferred case.
class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
public:
void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
DwVfpRegister input = ToDoubleRegister(instr->value());
Register result = ToRegister(instr->result());
Register scratch = scratch0();
void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
DwVfpRegister input = ToDoubleRegister(instr->value());
Register result = ToRegister(instr->result());
DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp());
void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
DwVfpRegister input = ToDoubleRegister(instr->value());
DwVfpRegister result = ToDoubleRegister(instr->result());
__ vsqrt(result, input);
void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
DwVfpRegister input = ToDoubleRegister(instr->value());
DwVfpRegister result = ToDoubleRegister(instr->result());
DwVfpRegister temp = ToDoubleRegister(instr->temp());
void LCodeGen::DoPower(LPower* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
Representation exponent_type = instr->hydrogen()->right()->representation();
// Having marked this as a call, we can use any registers.
// Just make sure that the input/output registers are the expected ones.
void LCodeGen::DoRandom(LRandom* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
class DeferredDoRandom: public LDeferredCode {
public:
DeferredDoRandom(LCodeGen* codegen, LRandom* instr)
void LCodeGen::DoMathExp(LMathExp* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
DwVfpRegister input = ToDoubleRegister(instr->value());
DwVfpRegister result = ToDoubleRegister(instr->result());
DwVfpRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
Register external_pointer = ToRegister(instr->elements());
Register key = no_reg;
ElementsKind elements_kind = instr->elements_kind();
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
- CpuFeatures::Scope scope(VFP3);
+ CpuFeatureScope scope(masm(), VFP3);
DwVfpRegister value(ToDoubleRegister(instr->value()));
Operand operand(key_is_constant
? Operand(constant_key << element_size_shift)
void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
DwVfpRegister value = ToDoubleRegister(instr->value());
Register elements = ToRegister(instr->elements());
Register key = no_reg;
void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
LOperand* input = instr->value();
ASSERT(input->IsRegister() || input->IsStackSlot());
LOperand* output = instr->result();
void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
LOperand* input = instr->value();
LOperand* output = instr->result();
__ eor(src, src, Operand(0x80000000));
}
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
__ vmov(flt_scratch, src);
__ vcvt_f64_s32(dbl_scratch, flt_scratch);
} else {
}
} else {
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
__ vmov(flt_scratch, src);
__ vcvt_f64_u32(dbl_scratch, flt_scratch);
} else {
// number.
__ bind(&done);
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
__ vstr(dbl_scratch, dst, HeapNumber::kValueOffset);
} else {
__ str(sfpd_lo, MemOperand(dst, HeapNumber::kMantissaOffset));
Label done;
if (convert_hole) {
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
DwVfpRegister input_reg = ToDoubleRegister(instr->value());
__ VFPCompareAndSetFlags(input_reg, input_reg);
__ b(vc, &no_special_nan_handling);
}
__ bind(deferred->exit());
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
__ vstr(input_reg, reg, HeapNumber::kValueOffset);
} else {
__ str(sfpd_lo, MemOperand(reg, HeapNumber::kValueOffset));
Register scratch = scratch0();
SwVfpRegister flt_scratch = double_scratch0().low();
ASSERT(!result_reg.is(double_scratch0()));
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
Label load_smi, heap_number, done;
__ cmp(scratch1, Operand(ip));
if (instr->truncating()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
Register scratch3 = ToRegister(instr->temp2());
ASSERT(!scratch3.is(input_reg) &&
!scratch3.is(scratch1) &&
scratch3);
} else {
- CpuFeatures::Scope scope(VFP3);
+ CpuFeatureScope scope(masm(), VFP3);
// Deoptimize if we don't have a heap number.
DeoptimizeIf(ne, instr->environment());
void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
- CpuFeatures::Scope vfp_scope(VFP2);
+ CpuFeatureScope vfp_scope(masm(), VFP2);
DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped());
Register result_reg = ToRegister(instr->result());
DwVfpRegister temp_reg = ToDoubleRegister(instr->temp());
void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
Register unclamped_reg = ToRegister(instr->unclamped());
Register result_reg = ToRegister(instr->result());
__ ClampUint8(result_reg, unclamped_reg);
void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm(), VFP2);
Register scratch = scratch0();
Register input_reg = ToRegister(instr->unclamped());
Register result_reg = ToRegister(instr->result());
} else if (source->IsStackSlot()) {
__ ldr(kSavedValueRegister, cgen_->ToMemOperand(source));
} else if (source->IsDoubleRegister()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(cgen_->masm(), VFP2);
__ vmov(kScratchDoubleReg, cgen_->ToDoubleRegister(source));
} else if (source->IsDoubleStackSlot()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(cgen_->masm(), VFP2);
__ vldr(kScratchDoubleReg, cgen_->ToMemOperand(source));
} else {
UNREACHABLE();
} else if (saved_destination_->IsStackSlot()) {
__ str(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_));
} else if (saved_destination_->IsDoubleRegister()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(cgen_->masm(), VFP2);
__ vmov(cgen_->ToDoubleRegister(saved_destination_), kScratchDoubleReg);
} else if (saved_destination_->IsDoubleStackSlot()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(cgen_->masm(), VFP2);
__ vstr(kScratchDoubleReg, cgen_->ToMemOperand(saved_destination_));
} else {
UNREACHABLE();
MemOperand destination_operand = cgen_->ToMemOperand(destination);
if (in_cycle_) {
if (!destination_operand.OffsetIsUint12Encodable()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(cgen_->masm(), VFP2);
// ip is overwritten while saving the value to the destination.
// Therefore we can't use ip. It is OK if the read from the source
// destroys ip, since that happens before the value is read.
}
} else if (source->IsDoubleRegister()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(cgen_->masm(), VFP2);
DwVfpRegister source_register = cgen_->ToDoubleRegister(source);
if (destination->IsDoubleRegister()) {
__ vmov(cgen_->ToDoubleRegister(destination), source_register);
}
} else if (source->IsDoubleStackSlot()) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(cgen_->masm(), VFP2);
MemOperand source_operand = cgen_->ToMemOperand(source);
if (destination->IsDoubleRegister()) {
__ vldr(cgen_->ToDoubleRegister(destination), source_operand);
void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src) {
ASSERT(CpuFeatures::IsSupported(VFP2));
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(this, VFP2);
if (!dst.is(src)) {
vmov(dst, src);
}
// Generate two ldr instructions if ldrd is not available.
if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size()) {
- CpuFeatures::Scope scope(ARMv7);
+ CpuFeatureScope scope(this, ARMv7);
ldrd(dst1, dst2, src, cond);
} else {
if ((src.am() == Offset) || (src.am() == NegOffset)) {
// Generate two str instructions if strd is not available.
if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size()) {
- CpuFeatures::Scope scope(ARMv7);
+ CpuFeatureScope scope(this, ARMv7);
strd(src1, src2, dst, cond);
} else {
MemOperand dst2(dst);
void MacroAssembler::Vmov(const DwVfpRegister dst,
const double imm,
const Register scratch) {
- ASSERT(CpuFeatures::IsEnabled(VFP2));
+ ASSERT(IsEnabled(VFP2));
static const DoubleRepresentation minus_zero(-0.0);
static const DoubleRepresentation zero(0.0);
DoubleRepresentation value(imm);
// Optionally save all double registers.
if (save_doubles) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(this, VFP2);
// Check CPU flags for number of registers, setting the Z condition flag.
CheckFor32DRegs(ip);
Register argument_count) {
// Optionally restore all double registers.
if (save_doubles) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(this, VFP2);
// Calculate the stack location of the saved doubles and restore them.
const int offset = 2 * kPointerSize;
sub(r3, fp,
scratch4,
s2);
if (destination == FloatingPointHelper::kVFPRegisters) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(this, VFP2);
vstr(d0, scratch1, 0);
} else {
str(mantissa_reg, MemOperand(scratch1, 0));
DwVfpRegister double_scratch,
Label *not_int32) {
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(this, VFP2);
sub(scratch, source, Operand(kHeapObjectTag));
vldr(double_scratch, scratch, HeapNumber::kValueOffset);
vcvt_s32_f64(double_scratch.low(), double_scratch);
ASSERT(!double_input.is(double_scratch));
ASSERT(CpuFeatures::IsSupported(VFP2));
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(this, VFP2);
Register prev_fpscr = result;
Label done;
Register scratch,
Register input_high,
Register input_low) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(this, VFP2);
ASSERT(!input_high.is(result));
ASSERT(!input_low.is(result));
ASSERT(!input_low.is(input_high));
Register scratch1,
Register scratch2) {
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ vmov(s0, ival);
__ add(scratch1, dst, Operand(wordoffset, LSL, 2));
__ vcvt_f32_s32(s0, s0);
return Handle<Code>::null();
}
- CpuFeatures::Scope scope_vfp2(VFP2);
+ CpuFeatureScope scope_vfp2(masm(), VFP2);
const int argc = arguments().immediate();
// If the object is not a JSObject or we got an unexpected number of
// arguments, bail out to the regular call.
DwVfpRegister double_scratch1,
Label* fail) {
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
Label key_ok;
// Check for smi or a smi inside a heap number. We convert the heap
// number and check if the conversion is exact and fits into the smi
d0, r6, r7, // These are: double_dst, dst_mantissa, dst_exponent.
r4, s2); // These are: scratch2, single_scratch.
if (destination == FloatingPointHelper::kVFPRegisters) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
__ vstr(d0, r3, 0);
} else {
__ str(r6, MemOperand(r3, 0));
// +/-Infinity into integer arrays basically undefined. For more
// reproducible behavior, convert these to zero.
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(masm, VFP2);
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
// vldr requires offset to be a multiple of 4 so we can not
AssemblerBase::AssemblerBase(Isolate* isolate, void* buffer, int buffer_size)
: isolate_(isolate),
jit_cookie_(0),
+ enabled_cpu_features_(0),
emit_debug_code_(FLAG_debug_code),
predictable_code_size_(false) {
if (FLAG_mask_constants_with_cookie && isolate != NULL) {
// -----------------------------------------------------------------------------
+// Implementation of CpuFeatureScope
+
+#ifdef DEBUG
+CpuFeatureScope::CpuFeatureScope(AssemblerBase* assembler, CpuFeature f)
+ : assembler_(assembler) {
+ ASSERT(CpuFeatures::IsSupported(f));
+ ASSERT(!Serializer::enabled() ||
+ !CpuFeatures::IsFoundByRuntimeProbingOnly(f));
+ old_enabled_ = assembler_->enabled_cpu_features();
+ uint64_t mask = static_cast<uint64_t>(1) << f;
+ // TODO(svenpanne) This special case below doesn't belong here!
+#if V8_TARGET_ARCH_ARM
+ // VFP2 and ARMv7 are implied by VFP3.
+ if (f == VFP3) {
+ mask |=
+ static_cast<uint64_t>(1) << VFP2 |
+ static_cast<uint64_t>(1) << ARMv7;
+ }
+#endif
+ assembler_->set_enabled_cpu_features(old_enabled_ | mask);
+}
+
+
+CpuFeatureScope::~CpuFeatureScope() {
+ assembler_->set_enabled_cpu_features(old_enabled_);
+}
+#endif
+
+
+// -----------------------------------------------------------------------------
// Implementation of Label
int Label::pos() const {
bool predictable_code_size() const { return predictable_code_size_; }
void set_predictable_code_size(bool value) { predictable_code_size_ = value; }
+ uint64_t enabled_cpu_features() const { return enabled_cpu_features_; }
+ void set_enabled_cpu_features(uint64_t features) {
+ enabled_cpu_features_ = features;
+ }
+ bool IsEnabled(CpuFeature f) {
+ return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0;
+ }
+
// Overwrite a host NaN with a quiet target NaN. Used by mksnapshot for
// cross-snapshotting.
static void QuietNaN(HeapObject* nan) { }
private:
Isolate* isolate_;
int jit_cookie_;
+ uint64_t enabled_cpu_features_;
bool emit_debug_code_;
bool predictable_code_size_;
};
};
+// Enable a specified feature within a scope.
+class CpuFeatureScope BASE_EMBEDDED {
+ public:
+#ifdef DEBUG
+ CpuFeatureScope(AssemblerBase* assembler, CpuFeature f);
+ ~CpuFeatureScope();
+
+ private:
+ AssemblerBase* assembler_;
+ uint64_t old_enabled_;
+#else
+ CpuFeatureScope(AssemblerBase* assembler, CpuFeature f) {}
+#endif
+};
+
+
// -----------------------------------------------------------------------------
// Labels represent pc locations; they are typically jump or call targets.
// After declaration, a label can be freely used to denote known or (yet)
bool CpuFeatures::initialized_ = false;
#endif
uint64_t CpuFeatures::supported_ = 0;
-uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
+uint64_t CpuFeatures::found_by_runtime_probing_only_ = 0;
ExternalReference ExternalReference::cpu_features() {
__ bind(&cpuid);
__ mov(eax, 1);
supported_ = (1 << CPUID);
- { Scope fscope(CPUID);
+ { CpuFeatureScope fscope(&assm, CPUID);
__ cpuid();
}
supported_ = 0;
typedef uint64_t (*F0)();
F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
- supported_ = probe();
- found_by_runtime_probing_ = supported_;
- uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
- supported_ |= os_guarantees;
- found_by_runtime_probing_ &= ~os_guarantees;
+ uint64_t probed_features = probe();
+ uint64_t platform_features = OS::CpuFeaturesImpliedByPlatform();
+ supported_ = probed_features | platform_features;
+ found_by_runtime_probing_only_ = probed_features & ~platform_features;
delete memory;
}
void Assembler::cpuid() {
- ASSERT(CpuFeatures::IsEnabled(CPUID));
+ ASSERT(IsEnabled(CPUID));
EnsureSpace ensure_space(this);
EMIT(0x0F);
EMIT(0xA2);
void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(CMOV));
+ ASSERT(IsEnabled(CMOV));
EnsureSpace ensure_space(this);
// Opcode: 0f 40 + cc /r.
EMIT(0x0F);
void Assembler::rdtsc() {
- ASSERT(CpuFeatures::IsEnabled(RDTSC));
+ ASSERT(IsEnabled(RDTSC));
EnsureSpace ensure_space(this);
EMIT(0x0F);
EMIT(0x31);
void Assembler::fisttp_s(const Operand& adr) {
- ASSERT(CpuFeatures::IsEnabled(SSE3));
+ ASSERT(IsEnabled(SSE3));
EnsureSpace ensure_space(this);
EMIT(0xDB);
emit_operand(ecx, adr);
void Assembler::fisttp_d(const Operand& adr) {
- ASSERT(CpuFeatures::IsEnabled(SSE3));
+ ASSERT(IsEnabled(SSE3));
EnsureSpace ensure_space(this);
EMIT(0xDD);
emit_operand(ecx, adr);
void Assembler::cvttss2si(Register dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF3);
EMIT(0x0F);
void Assembler::cvttsd2si(Register dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::cvtsd2si(Register dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF3);
EMIT(0x0F);
void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::addsd(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::addsd(XMMRegister dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::mulsd(XMMRegister dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::subsd(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::divsd(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
- ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+ ASSERT(IsEnabled(SSE4_1));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
}
void Assembler::movmskpd(Register dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::movmskps(Register dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x0F);
EMIT(0x50);
void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::movaps(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x0F);
EMIT(0x28);
void Assembler::movdqa(const Operand& dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::movdqa(XMMRegister dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF3);
EMIT(0x0F);
void Assembler::movdqu(XMMRegister dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF3);
EMIT(0x0F);
void Assembler::movntdqa(XMMRegister dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+ ASSERT(IsEnabled(SSE4_1));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::movntdq(const Operand& dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::movsd(const Operand& dst, XMMRegister src ) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2); // double
EMIT(0x0F);
void Assembler::movsd(XMMRegister dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2); // double
EMIT(0x0F);
void Assembler::movsd(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF2);
EMIT(0x0F);
void Assembler::movss(const Operand& dst, XMMRegister src ) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF3); // float
EMIT(0x0F);
void Assembler::movss(XMMRegister dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF3); // float
EMIT(0x0F);
void Assembler::movss(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0xF3);
EMIT(0x0F);
void Assembler::movd(XMMRegister dst, const Operand& src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::movd(const Operand& dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::pand(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::pxor(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::por(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::ptest(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+ ASSERT(IsEnabled(SSE4_1));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::psllq(XMMRegister reg, int8_t shift) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::psllq(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::psrlq(XMMRegister reg, int8_t shift) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::psrlq(XMMRegister dst, XMMRegister src) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
- ASSERT(CpuFeatures::IsEnabled(SSE2));
+ ASSERT(IsEnabled(SSE2));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) {
- ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+ ASSERT(IsEnabled(SSE4_1));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) {
- ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+ ASSERT(IsEnabled(SSE4_1));
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
// CpuFeatures keeps track of which features are supported by the target CPU.
-// Supported features must be enabled by a Scope before use.
+// Supported features must be enabled by a CpuFeatureScope before use.
// Example:
-// if (CpuFeatures::IsSupported(SSE2)) {
-// CpuFeatures::Scope fscope(SSE2);
+// if (assembler->IsSupported(SSE2)) {
+// CpuFeatureScope fscope(assembler, SSE2);
// // Generate SSE2 floating point code.
// } else {
// // Generate standard x87 floating point code.
return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
}
-#ifdef DEBUG
- // Check whether a feature is currently enabled.
- static bool IsEnabled(CpuFeature f) {
+ static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
ASSERT(initialized_);
- Isolate* isolate = Isolate::UncheckedCurrent();
- if (isolate == NULL) {
- // When no isolate is available, work as if we're running in
- // release mode.
- return IsSupported(f);
- }
- uint64_t enabled = isolate->enabled_cpu_features();
- return (enabled & (static_cast<uint64_t>(1) << f)) != 0;
+ return (found_by_runtime_probing_only_ &
+ (static_cast<uint64_t>(1) << f)) != 0;
}
-#endif
-
- // Enable a specified feature within a scope.
- class Scope BASE_EMBEDDED {
-#ifdef DEBUG
-
- public:
- explicit Scope(CpuFeature f) {
- uint64_t mask = static_cast<uint64_t>(1) << f;
- ASSERT(CpuFeatures::IsSupported(f));
- ASSERT(!Serializer::enabled() ||
- (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
- isolate_ = Isolate::UncheckedCurrent();
- old_enabled_ = 0;
- if (isolate_ != NULL) {
- old_enabled_ = isolate_->enabled_cpu_features();
- isolate_->set_enabled_cpu_features(old_enabled_ | mask);
- }
- }
- ~Scope() {
- ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
- if (isolate_ != NULL) {
- isolate_->set_enabled_cpu_features(old_enabled_);
- }
- }
-
- private:
- Isolate* isolate_;
- uint64_t old_enabled_;
-#else
-
- public:
- explicit Scope(CpuFeature f) {}
-#endif
- };
class TryForceFeatureScope BASE_EMBEDDED {
public:
static bool initialized_;
#endif
static uint64_t supported_;
- static uint64_t found_by_runtime_probing_;
+ static uint64_t found_by_runtime_probing_only_;
friend class ExternalReference;
DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
// restore them.
__ pushad();
if (save_doubles_ == kSaveFPRegs) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm, SSE2);
__ sub(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters));
for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
XMMRegister reg = XMMRegister::from_code(i);
ExternalReference::store_buffer_overflow_function(masm->isolate()),
argument_count);
if (save_doubles_ == kSaveFPRegs) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm, SSE2);
for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
XMMRegister reg = XMMRegister::from_code(i);
__ movdbl(reg, Operand(esp, i * kDoubleSize));
__ cmp(scratch2, Immediate(kResultIsZeroExponent));
__ j(above, &done);
if (use_sse3) {
- CpuFeatures::Scope scope(SSE3);
+ CpuFeatureScope scope(masm, SSE3);
// Check whether the exponent is too big for a 64 bit signed integer.
static const uint32_t kTooBigExponent = 63;
__ cmp(scratch2, Immediate(kTooBigExponent));
__ bind(&heapnumber_allocated);
}
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
__ cvtsi2sd(xmm0, ecx);
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
} else {
} else {
ASSERT_EQ(Token::SHL, op);
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
__ cvtsi2sd(xmm0, left);
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
} else {
}
__ AllocateHeapNumber(ecx, ebx, no_reg, slow);
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
FloatingPointHelper::LoadSSE2Smis(masm, ebx);
switch (op) {
case Token::ADD: __ addsd(xmm0, xmm1); break;
Label not_floats;
Label not_int32;
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
// It could be that only SMIs have been seen at either the left
// or the right operand. For precise type feedback, patch the IC
// again if this changes.
}
// Store the result in the HeapNumber and return.
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
__ cvtsi2sd(xmm0, ebx);
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
} else {
case Token::DIV: {
Label not_floats;
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
// It could be that only SMIs have been seen at either the left
// or the right operand. For precise type feedback, patch the IC
}
// Store the result in the HeapNumber and return.
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
__ cvtsi2sd(xmm0, ebx);
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
} else {
case Token::DIV: {
Label not_floats;
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats);
switch (op_) {
}
// Store the result in the HeapNumber and return.
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
__ cvtsi2sd(xmm0, ebx);
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
} else {
__ bind(&loaded);
} else { // UNTAGGED.
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm, SSE2);
if (CpuFeatures::IsSupported(SSE4_1)) {
- CpuFeatures::Scope sse4_scope(SSE4_1);
+ CpuFeatureScope sse4_scope(masm, SSE4_1);
__ pextrd(edx, xmm1, 0x1); // copy xmm1[63..32] to edx.
} else {
__ pshufd(xmm0, xmm1, 0x1);
__ fstp(0);
__ ret(kPointerSize);
} else { // UNTAGGED.
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm, SSE2);
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
}
if (tagged) {
__ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack);
} else { // UNTAGGED.
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm, SSE2);
__ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
__ sub(esp, Immediate(kDoubleSize));
__ movdbl(Operand(esp, 0), xmm1);
if (tagged) {
__ ret(kPointerSize);
} else { // UNTAGGED.
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm, SSE2);
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
ExternalReference(RuntimeFunction(), masm->isolate());
__ TailCallExternalReference(runtime, 1, 1);
} else { // UNTAGGED.
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm, SSE2);
__ bind(&runtime_call_clear_stack);
__ bind(&runtime_call);
__ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
// Get the untagged integer version of the edx heap number in ecx.
if (left_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
ConvertHeapNumberToInt32(masm, edx, conversion_failure);
} else {
IntegerConvert(masm, edx, use_sse3, conversion_failure);
// Get the untagged integer version of the eax heap number in ecx.
if (right_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
ConvertHeapNumberToInt32(masm, eax, conversion_failure);
} else {
IntegerConvert(masm, eax, use_sse3, conversion_failure);
void MathPowStub::Generate(MacroAssembler* masm) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
Factory* factory = masm->isolate()->factory();
const Register exponent = eax;
const Register base = edx;
FixedArray::kHeaderSize));
__ JumpIfSmi(probe, not_found);
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope fscope(SSE2);
+ CpuFeatureScope fscope(masm, SSE2);
__ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
__ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
__ ucomisd(xmm0, xmm1);
Label non_number_comparison;
Label unordered;
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
- CpuFeatures::Scope use_cmov(CMOV);
+ CpuFeatureScope use_sse2(masm, SSE2);
+ CpuFeatureScope use_cmov(masm, CMOV);
FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison);
__ ucomisd(xmm0, xmm1);
// Inlining the double comparison and falling back to the general compare
// stub if NaN is involved or SSE2 or CMOV is unsupported.
if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) {
- CpuFeatures::Scope scope1(SSE2);
- CpuFeatures::Scope scope2(CMOV);
+ CpuFeatureScope scope1(masm, SSE2);
+ CpuFeatureScope scope2(masm, CMOV);
// Load left and right operand.
Label done, left, left_smi, right_smi;
if (!scratch0_.is(eax) && !scratch1_.is(eax)) masm->push(eax);
if (!scratch0_.is(edx) && !scratch1_.is(edx)) masm->push(edx);
if (mode == kSaveFPRegs) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm, SSE2);
masm->sub(esp,
Immediate(kDoubleSize * (XMMRegister::kNumRegisters - 1)));
// Save all XMM registers except XMM0.
inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
SaveFPRegsMode mode) {
if (mode == kSaveFPRegs) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm, SSE2);
// Restore all XMM registers except XMM0.
for (int i = XMMRegister::kNumRegisters - 1; i > 0; i--) {
XMMRegister reg = XMMRegister::from_code(i);
// esp[1 * kPointerSize]: raw double input
// esp[0 * kPointerSize]: return address
{
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(&masm, SSE2);
XMMRegister input = xmm1;
XMMRegister result = xmm2;
__ movdbl(input, Operand(esp, 1 * kPointerSize));
// esp[0 * kPointerSize]: return address
// Move double input into registers.
{
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(&masm, SSE2);
__ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
__ sqrtsd(xmm0, xmm0);
__ movdbl(Operand(esp, 1 * kPointerSize), xmm0);
__ bind(&ok);
}
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope enable(SSE2);
+ CpuFeatureScope enable(&masm, SSE2);
__ push(edi);
__ push(esi);
stack_offset += 2 * kPointerSize;
ExternalReference::address_of_the_hole_nan();
XMMRegister the_hole_nan = xmm1;
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
__ movdbl(the_hole_nan,
Operand::StaticVariable(canonical_the_hole_nan_reference));
}
// Normal smi, convert it to double and store.
__ SmiUntag(ebx);
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope fscope(SSE2);
+ CpuFeatureScope fscope(masm, SSE2);
__ cvtsi2sd(xmm0, ebx);
__ movdbl(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize),
xmm0);
}
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
__ movdbl(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize),
the_hole_nan);
} else {
__ AllocateHeapNumber(edx, esi, no_reg, &gc_required);
// edx: new heap number
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope fscope(SSE2);
+ CpuFeatureScope fscope(masm, SSE2);
__ movdbl(xmm0,
FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize));
__ movdbl(FieldOperand(edx, HeapNumber::kValueOffset), xmm0);
XMMRegister::kNumAllocatableRegisters;
__ sub(esp, Immediate(kDoubleRegsSize));
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
int offset = i * kDoubleSize;
int double_regs_offset = FrameDescription::double_registers_offset();
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
// Fill in the double input registers.
for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
int dst_offset = i * kDoubleSize + double_regs_offset;
// In case of OSR or a failed STUB, we have to restore the XMM registers.
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
int src_offset = i * kDoubleSize + double_regs_offset;
// ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
// This is implemented on both SSE2 and FPU.
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope fscope(SSE2);
+ CpuFeatureScope fscope(masm(), SSE2);
__ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
__ movd(xmm1, ebx);
__ movd(xmm0, eax);
if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) {
Comment(";;; Save clobbered callee double registers");
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
int count = 0;
BitVector* doubles = chunk()->allocated_double_registers();
BitVector::Iterator save_iterator(doubles);
int32_t lower = static_cast<int32_t>(int_val);
int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
if (CpuFeatures::IsSupported(SSE4_1)) {
- CpuFeatures::Scope scope1(SSE2);
- CpuFeatures::Scope scope2(SSE4_1);
+ CpuFeatureScope scope1(masm(), SSE2);
+ CpuFeatureScope scope2(masm(), SSE4_1);
if (lower != 0) {
__ Set(temp, Immediate(lower));
__ movd(res, Operand(temp));
__ pinsrd(res, Operand(temp), 1);
}
} else {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
__ Set(temp, Immediate(upper));
__ movd(res, Operand(temp));
__ psllq(res, 32);
void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
LOperand* left = instr->left();
LOperand* right = instr->right();
ASSERT(left->Equals(instr->result()));
void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister left = ToDoubleRegister(instr->left());
XMMRegister right = ToDoubleRegister(instr->right());
XMMRegister result = ToDoubleRegister(instr->result());
void LCodeGen::DoBranch(LBranch* instr) {
int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id());
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
Representation r = instr->hydrogen()->value()->representation();
if (r.IsInteger32()) {
EmitGoto(next_block);
} else {
if (instr->is_double()) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
// Don't base result on EFLAGS when a NaN is involved. Instead
// jump to the false block.
__ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
}
if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) {
ASSERT(NeedsEagerFrame());
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
BitVector* doubles = chunk()->allocated_double_registers();
BitVector::Iterator save_iterator(doubles);
int count = 0;
instr->additional_index()));
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister result(ToDoubleRegister(instr->result()));
__ movss(result, operand);
__ cvtss2sd(result, result);
}
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
__ movdbl(ToDoubleRegister(instr->result()), operand);
} else {
__ fld_d(operand);
FixedDoubleArray::kHeaderSize - kHeapObjectTag,
instr->additional_index());
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister result = ToDoubleRegister(instr->result());
__ movdbl(result, double_load_operand);
} else {
ASSERT(instr->value()->Equals(instr->result()));
Representation r = instr->hydrogen()->value()->representation();
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
if (r.IsDouble()) {
XMMRegister scratch = xmm0;
XMMRegister input_reg = ToDoubleRegister(instr->value());
void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister xmm_scratch = xmm0;
Register output_reg = ToRegister(instr->result());
XMMRegister input_reg = ToDoubleRegister(instr->value());
if (CpuFeatures::IsSupported(SSE4_1)) {
- CpuFeatures::Scope scope(SSE4_1);
+ CpuFeatureScope scope(masm(), SSE4_1);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// Deoptimize on negative zero.
Label non_zero;
}
void LCodeGen::DoMathRound(LMathRound* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
Register output_reg = ToRegister(instr->result());
XMMRegister input_reg = ToDoubleRegister(instr->value());
XMMRegister xmm_scratch = xmm0;
void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister input_reg = ToDoubleRegister(instr->value());
ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
__ sqrtsd(input_reg, input_reg);
void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister xmm_scratch = xmm0;
XMMRegister input_reg = ToDoubleRegister(instr->value());
Register scratch = ToRegister(instr->temp());
DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr);
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
// Having marked this instruction as a call we can use any
// registers.
ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
ASSERT(instr->value()->Equals(instr->result()));
XMMRegister input_reg = ToDoubleRegister(instr->value());
Label positive, done, zero;
void LCodeGen::DoMathExp(LMathExp* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister input = ToDoubleRegister(instr->value());
XMMRegister result = ToDoubleRegister(instr->result());
Register temp1 = ToRegister(instr->temp1());
0,
instr->additional_index()));
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
__ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
__ movss(operand, xmm0);
} else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
__ movdbl(operand, ToDoubleRegister(instr->value()));
} else {
Register value = ToRegister(instr->value());
void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister value = ToDoubleRegister(instr->value());
if (instr->NeedsCanonicalization()) {
void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
LOperand* input = instr->value();
ASSERT(input->IsRegister() || input->IsStackSlot());
LOperand* output = instr->result();
void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
LOperand* input = instr->value();
LOperand* output = instr->result();
LOperand* temp = instr->temp();
__ SmiUntag(reg);
__ xor_(reg, 0x80000000);
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope feature_scope(SSE2);
+ CpuFeatureScope feature_scope(masm(), SSE2);
__ cvtsi2sd(xmm0, Operand(reg));
} else {
__ push(reg);
}
} else {
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope feature_scope(SSE2);
+ CpuFeatureScope feature_scope(masm(), SSE2);
__ LoadUint32(xmm0, reg, xmm1);
} else {
// There's no fild variant for unsigned values, so zero-extend to a 64-bit
// number.
__ bind(&done);
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope feature_scope(SSE2);
+ CpuFeatureScope feature_scope(masm(), SSE2);
__ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0);
} else {
__ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
if (convert_hole) {
bool use_sse2 = CpuFeatures::IsSupported(SSE2);
if (use_sse2) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister input_reg = ToDoubleRegister(instr->value());
__ ucomisd(input_reg, input_reg);
} else {
__ j(parity_odd, &no_special_nan_handling);
__ sub(esp, Immediate(kDoubleSize));
if (use_sse2) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister input_reg = ToDoubleRegister(instr->value());
__ movdbl(MemOperand(esp, 0), input_reg);
} else {
ExternalReference nan =
ExternalReference::address_of_canonical_non_hole_nan();
if (use_sse2) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister input_reg = ToDoubleRegister(instr->value());
__ movdbl(input_reg, Operand::StaticVariable(nan));
} else {
}
__ bind(deferred->exit());
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister input_reg = ToDoubleRegister(instr->value());
__ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg);
} else {
__ bind(&heap_number);
if (CpuFeatures::IsSupported(SSE3)) {
- CpuFeatures::Scope scope(SSE3);
+ CpuFeatureScope scope(masm(), SSE3);
Label convert;
// Use more powerful conversion when sse3 is available.
// Load x87 register with heap number.
__ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result.
__ add(Operand(esp), Immediate(kDoubleSize));
} else {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister xmm_temp = ToDoubleRegister(instr->temp());
__ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
__ cvttsd2si(input_reg, Operand(xmm0));
DeoptimizeIf(parity_even, instr->environment()); // NaN.
}
} else if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
// Deoptimize if we don't have a heap number.
__ RecordComment("Deferred TaggedToI: not a heap number");
DeoptimizeIf(not_equal, instr->environment());
ASSERT(result->IsDoubleRegister());
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
Register input_reg = ToRegister(input);
XMMRegister result_reg = ToDoubleRegister(result);
ASSERT(input->IsDoubleRegister());
LOperand* result = instr->result();
ASSERT(result->IsRegister());
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister input_reg = ToDoubleRegister(input);
Register result_reg = ToRegister(result);
__ cmp(result_reg, 0x80000000u);
if (CpuFeatures::IsSupported(SSE3)) {
// This will deoptimize if the exponent of the input in out of range.
- CpuFeatures::Scope scope(SSE3);
+ CpuFeatureScope scope(masm(), SSE3);
Label convert, done;
__ j(not_equal, &done, Label::kNear);
__ sub(Operand(esp), Immediate(kDoubleSize));
void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
XMMRegister value_reg = ToDoubleRegister(instr->unclamped());
Register result_reg = ToRegister(instr->result());
__ ClampDoubleToUint8(value_reg, xmm0, result_reg);
void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm(), SSE2);
ASSERT(instr->unclamped()->Equals(instr->result()));
Register input_reg = ToRegister(instr->unclamped());
}
} else if (source->IsDoubleRegister()) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(cgen_->masm(), SSE2);
XMMRegister src = cgen_->ToDoubleRegister(source);
if (destination->IsDoubleRegister()) {
XMMRegister dst = cgen_->ToDoubleRegister(destination);
__ movdbl(dst, src);
}
} else if (source->IsDoubleStackSlot()) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(cgen_->masm(), SSE2);
ASSERT(destination->IsDoubleRegister() ||
destination->IsDoubleStackSlot());
Operand src = cgen_->ToOperand(source);
__ mov(src, tmp0);
}
} else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(cgen_->masm(), SSE2);
// XMM register-register swap. We rely on having xmm0
// available as a fixed scratch register.
XMMRegister src = cgen_->ToDoubleRegister(source);
__ movaps(dst, xmm0);
} else if (source->IsDoubleRegister() || destination->IsDoubleRegister()) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(cgen_->masm(), SSE2);
// XMM register-memory swap. We rely on having xmm0
// available as a fixed scratch register.
ASSERT(source->IsDoubleStackSlot() || destination->IsDoubleStackSlot());
__ movdbl(reg, Operand(xmm0));
} else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(cgen_->masm(), SSE2);
// Double-width memory-to-memory. Spill on demand to use a general
// purpose temporary register and also rely on having xmm0 available as
// a fixed scratch register.
ExternalReference canonical_nan_reference =
ExternalReference::address_of_canonical_non_hole_nan();
if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(this, SSE2);
movdbl(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset));
bind(&have_double_value);
movdbl(FieldOperand(elements, key, times_4,
j(zero, ¬_nan);
bind(&is_nan);
if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(this, SSE2);
movdbl(scratch2, Operand::StaticVariable(canonical_nan_reference));
} else {
fld_d(Operand::StaticVariable(canonical_nan_reference));
mov(scratch1, maybe_number);
SmiUntag(scratch1);
if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
- CpuFeatures::Scope fscope(SSE2);
+ CpuFeatureScope fscope(this, SSE2);
cvtsi2sd(scratch2, scratch1);
movdbl(FieldOperand(elements, key, times_4,
FixedDoubleArray::kHeaderSize - elements_offset),
void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
// Optionally save all XMM registers.
if (save_doubles) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(this, SSE2);
int space = XMMRegister::kNumRegisters * kDoubleSize + argc * kPointerSize;
sub(esp, Immediate(space));
const int offset = -2 * kPointerSize;
void MacroAssembler::LeaveExitFrame(bool save_doubles) {
// Optionally restore all XMM registers.
if (save_doubles) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(this, SSE2);
const int offset = -2 * kPointerSize;
for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
XMMRegister reg = XMMRegister::from_code(i);
return Handle<Code>::null();
}
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm(), SSE2);
const int argc = arguments().immediate();
__ mov(ebx, edi);
__ cmp(eax, arg_number);
if (CpuFeatures::IsSupported(CMOV)) {
- CpuFeatures::Scope use_cmov(CMOV);
+ CpuFeatureScope use_cmov(masm(), CMOV);
__ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize));
} else {
Label not_passed;
// Check that key is a smi and if SSE2 is available a heap number
// containing a smi and branch if the check fails.
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
+ CpuFeatureScope use_sse2(masm, SSE2);
Label key_ok;
__ JumpIfSmi(key, &key_ok);
__ cmp(FieldOperand(key, HeapObject::kMapOffset),
if ((elements_kind == EXTERNAL_INT_ELEMENTS ||
elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) &&
CpuFeatures::IsSupported(SSE3)) {
- CpuFeatures::Scope scope(SSE3);
+ CpuFeatureScope scope(masm, SSE3);
// fisttp stores values as signed integers. To represent the
// entire range of int and unsigned int arrays, store as a
// 64-bit int and discard the high 32 bits.
__ mov(Operand(edi, ecx, times_2, 0), ebx);
} else {
ASSERT(CpuFeatures::IsSupported(SSE2));
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(masm, SSE2);
__ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset));
__ cmp(ebx, 0x80000000u);
__ j(equal, &slow);
V(unsigned, ast_node_count, 0) \
/* SafeStackFrameIterator activations count. */ \
V(int, safe_stack_iterator_counter, 0) \
- V(uint64_t, enabled_cpu_features, 0) \
V(CpuProfiler*, cpu_profiler, NULL) \
V(HeapProfiler*, heap_profiler, NULL) \
V(bool, observer_delivery_pending, false) \
bool CpuFeatures::initialized_ = false;
#endif
unsigned CpuFeatures::supported_ = 0;
-unsigned CpuFeatures::found_by_runtime_probing_ = 0;
+unsigned CpuFeatures::found_by_runtime_probing_only_ = 0;
ExternalReference ExternalReference::cpu_features() {
static uint64_t CpuFeaturesImpliedByCompiler() {
uint64_t answer = 0;
#ifdef CAN_USE_FPU_INSTRUCTIONS
- answer |= 1u << FPU;
+ answer |= static_cast<uint64_t>(1) << FPU;
#endif // def CAN_USE_FPU_INSTRUCTIONS
#ifdef __mips__
// generation even when generating snapshots. This won't work for cross
// compilation.
#if(defined(__mips_hard_float) && __mips_hard_float != 0)
- answer |= 1u << FPU;
+ answer |= static_cast<uint64_t>(1) << FPU;
#endif // defined(__mips_hard_float) && __mips_hard_float != 0
#endif // def __mips__
#if !defined(__mips__)
// For the simulator=mips build, use FPU when FLAG_enable_fpu is enabled.
if (FLAG_enable_fpu) {
- supported_ |= 1u << FPU;
+ supported_ |= static_cast<uint64_t>(1) << FPU;
}
#else
// Probe for additional features not already known to be available.
if (OS::MipsCpuHasFeature(FPU)) {
// This implementation also sets the FPU flags if
// runtime detection of FPU returns true.
- supported_ |= 1u << FPU;
- found_by_runtime_probing_ |= 1u << FPU;
+ supported_ |= static_cast<uint64_t>(1) << FPU;
+ found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << FPU;
}
#endif
}
FPURegister fd,
SecondaryField func) {
ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid());
- ASSERT(CpuFeatures::IsEnabled(FPU));
+ ASSERT(IsEnabled(FPU));
Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
| (fd.code() << kFdShift) | func;
emit(instr);
FPURegister fd,
SecondaryField func) {
ASSERT(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid());
- ASSERT(CpuFeatures::IsEnabled(FPU));
+ ASSERT(IsEnabled(FPU));
Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift)
| (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
emit(instr);
FPURegister fd,
SecondaryField func) {
ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid());
- ASSERT(CpuFeatures::IsEnabled(FPU));
+ ASSERT(IsEnabled(FPU));
Instr instr = opcode | fmt | (rt.code() << kRtShift)
| (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
emit(instr);
FPUControlRegister fs,
SecondaryField func) {
ASSERT(fs.is_valid() && rt.is_valid());
- ASSERT(CpuFeatures::IsEnabled(FPU));
+ ASSERT(IsEnabled(FPU));
Instr instr =
opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
emit(instr);
FPURegister ft,
int32_t j) {
ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
- ASSERT(CpuFeatures::IsEnabled(FPU));
+ ASSERT(IsEnabled(FPU));
Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
| (j & kImm16Mask);
emit(instr);
// Conditions.
void Assembler::c(FPUCondition cond, SecondaryField fmt,
FPURegister fs, FPURegister ft, uint16_t cc) {
- ASSERT(CpuFeatures::IsEnabled(FPU));
+ ASSERT(IsEnabled(FPU));
ASSERT(is_uint3(cc));
ASSERT((fmt & ~(31 << kRsShift)) == 0);
Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
void Assembler::fcmp(FPURegister src1, const double src2,
FPUCondition cond) {
- ASSERT(CpuFeatures::IsEnabled(FPU));
+ ASSERT(IsEnabled(FPU));
ASSERT(src2 == 0.0);
mtc1(zero_reg, f14);
cvt_d_w(f14, f14);
void Assembler::bc1f(int16_t offset, uint16_t cc) {
- ASSERT(CpuFeatures::IsEnabled(FPU));
+ ASSERT(IsEnabled(FPU));
ASSERT(is_uint3(cc));
Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
emit(instr);
void Assembler::bc1t(int16_t offset, uint16_t cc) {
- ASSERT(CpuFeatures::IsEnabled(FPU));
+ ASSERT(IsEnabled(FPU));
ASSERT(is_uint3(cc));
Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
emit(instr);
// CpuFeatures keeps track of which features are supported by the target CPU.
-// Supported features must be enabled by a Scope before use.
+// Supported features must be enabled by a CpuFeatureScope before use.
class CpuFeatures : public AllStatic {
public:
// Detect features of the target CPU. Set safe defaults if the serializer
return (supported_ & (1u << f)) != 0;
}
-
-#ifdef DEBUG
- // Check whether a feature is currently enabled.
- static bool IsEnabled(CpuFeature f) {
+ static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
ASSERT(initialized_);
- Isolate* isolate = Isolate::UncheckedCurrent();
- if (isolate == NULL) {
- // When no isolate is available, work as if we're running in
- // release mode.
- return IsSupported(f);
- }
- unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
- return (enabled & (1u << f)) != 0;
+ return (found_by_runtime_probing_only_ &
+ (static_cast<uint64_t>(1) << f)) != 0;
}
-#endif
-
- // Enable a specified feature within a scope.
- class Scope BASE_EMBEDDED {
-#ifdef DEBUG
-
- public:
- explicit Scope(CpuFeature f) {
- unsigned mask = 1u << f;
- ASSERT(CpuFeatures::IsSupported(f));
- ASSERT(!Serializer::enabled() ||
- (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
- isolate_ = Isolate::UncheckedCurrent();
- old_enabled_ = 0;
- if (isolate_ != NULL) {
- old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
- isolate_->set_enabled_cpu_features(old_enabled_ | mask);
- }
- }
- ~Scope() {
- ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
- if (isolate_ != NULL) {
- isolate_->set_enabled_cpu_features(old_enabled_);
- }
- }
-
- private:
- Isolate* isolate_;
- unsigned old_enabled_;
-#else
-
- public:
- explicit Scope(CpuFeature f) {}
-#endif
- };
class TryForceFeatureScope BASE_EMBEDDED {
public:
static bool initialized_;
#endif
static unsigned supported_;
- static unsigned found_by_runtime_probing_;
+ static unsigned found_by_runtime_probing_only_;
friend class ExternalReference;
DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
Register scratch1,
Register scratch2) {
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ sra(scratch1, a0, kSmiTagSize);
__ mtc1(scratch1, f14);
__ cvt_d_w(f14, f14);
// Handle loading a double from a heap number.
if (CpuFeatures::IsSupported(FPU) &&
destination == kFPURegisters) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
// Load the double from tagged HeapNumber to double register.
// ARM uses a workaround here because of the unaligned HeapNumber
// Handle loading a double from a smi.
__ bind(&is_smi);
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
// Convert smi to double using FPU instructions.
__ mtc1(scratch1, dst);
__ cvt_d_w(dst, dst);
Label done;
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ mtc1(int_scratch, single_scratch);
__ cvt_d_w(double_dst, single_scratch);
if (destination == kCoreRegisters) {
// Load the number.
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
// Load the double value.
__ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset));
// Object is a heap number.
// Convert the floating point value to a 32-bit integer.
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
// Load the double value.
__ ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset));
__ push(ra);
__ PrepareCallCFunction(4, scratch); // Two doubles are 4 arguments.
if (!IsMipsSoftFloatABI) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
// We are not using MIPS FPU instructions, and parameters for the runtime
// function call are prepaired in a0-a3 registers, but function we are
// calling is compiled with hard-float flag and expecting hard float ABI
}
// Store answer in the overwritable heap number.
if (!IsMipsSoftFloatABI) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
// Double returned in register f0.
__ sdc1(f0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
} else {
// Rhs is a smi, lhs is a number.
// Convert smi rhs to double.
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ sra(at, rhs, kSmiTagSize);
__ mtc1(at, f14);
__ cvt_d_w(f14, f14);
// Lhs is a smi, rhs is a number.
// Convert smi lhs to double.
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ sra(at, lhs, kSmiTagSize);
__ mtc1(at, f12);
__ cvt_d_w(f12, f12);
void EmitNanCheck(MacroAssembler* masm, Condition cc) {
bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
// Lhs and rhs are already loaded to f12 and f14 register pairs.
__ Move(t0, t1, f14);
__ Move(t2, t3, f12);
// Exception: 0 and -0.
bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
// Lhs and rhs are already loaded to f12 and f14 register pairs.
__ Move(t0, t1, f14);
__ Move(t2, t3, f12);
__ pop(ra); // Because this function returns int, result is in v0.
__ Ret();
} else {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
Label equal, less_than;
__ BranchF(&equal, NULL, eq, f12, f14);
__ BranchF(&less_than, NULL, lt, f12, f14);
// Both are heap numbers. Load them up then jump to the code we have
// for that.
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset));
__ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset));
} else {
if (!object_is_smi) {
__ JumpIfSmi(object, &is_smi);
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ CheckMap(object,
scratch1,
Heap::kHeapNumberMapRootIndex,
Isolate* isolate = masm->isolate();
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
Label nan;
__ li(t0, Operand(LESS));
__ li(t1, Operand(GREATER));
// it, too: zero for false, and a non-zero value for true.
void ToBooleanStub::Generate(MacroAssembler* masm) {
// This stub uses FPU instructions.
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
Label patch;
const Register map = t5.is(tos_) ? t3 : t5;
// restore them.
__ MultiPush(kJSCallerSaved | ra.bit());
if (save_doubles_ == kSaveFPRegs) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ MultiPushFPU(kCallerSavedFPU);
}
const int argument_count = 1;
ExternalReference::store_buffer_overflow_function(masm->isolate()),
argument_count);
if (save_doubles_ == kSaveFPRegs) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ MultiPopFPU(kCallerSavedFPU);
}
if (CpuFeatures::IsSupported(FPU)) {
// Convert the int32 in a1 to the heap number in v0. a2 is corrupted.
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ mtc1(a1, f0);
__ cvt_d_w(f0, f0);
__ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset));
// Using FPU registers:
// f12: Left value.
// f14: Right value.
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
switch (op) {
case Token::ADD:
__ add_d(f10, f12, f14);
if (CpuFeatures::IsSupported(FPU)) {
// Convert the int32 in a2 to the heap number in a0. As
// mentioned above SHR needs to always produce a positive result.
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ mtc1(a2, f0);
if (op == Token::SHR) {
__ Cvt_d_uw(f0, f0, f22);
&transition);
if (destination == FloatingPointHelper::kFPURegisters) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
Label return_heap_number;
switch (op_) {
case Token::ADD:
mode_);
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
if (op_ != Token::SHR) {
// Convert the result to a floating point value.
const bool tagged = (argument_type_ == TAGGED);
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
if (tagged) {
// Argument is a number and is on stack and in a0.
1);
} else {
ASSERT(CpuFeatures::IsSupported(FPU));
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
Label no_update;
Label skip_cache;
void MathPowStub::Generate(MacroAssembler* masm) {
- CpuFeatures::Scope fpu_scope(FPU);
+ CpuFeatureScope fpu_scope(masm, FPU);
const Register base = a1;
const Register exponent = a2;
const Register heapnumbermap = t1;
// These stubs might already be in the snapshot, detect that and don't
// regenerate, which would lead to code stub initialization state being messed
// up.
- Code* save_doubles_code = NULL;
- Code* store_buffer_overflow_code = NULL;
- if (!save_doubles.FindCodeInCache(&save_doubles_code, ISOLATE)) {
- if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope2(FPU);
- save_doubles_code = *save_doubles.GetCode(isolate);
- store_buffer_overflow_code = *stub.GetCode(isolate);
- } else {
- save_doubles_code = *save_doubles.GetCode(isolate);
- store_buffer_overflow_code = *stub.GetCode(isolate);
- }
+ Code* save_doubles_code;
+ if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) {
+ save_doubles_code = *save_doubles.GetCode(isolate);
save_doubles_code->set_is_pregenerated(true);
+
+ Code* store_buffer_overflow_code = *stub.GetCode(isolate);
store_buffer_overflow_code->set_is_pregenerated(true);
}
- ISOLATE->set_fp_stubs_generated(true);
+ isolate->set_fp_stubs_generated(true);
}
__ MultiPush(kCalleeSaved | ra.bit());
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
// Save callee-saved FPU registers.
__ MultiPushFPU(kCalleeSavedFPU);
// Set up the reserved register for 0.0.
__ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset);
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
// Restore callee-saved fpu registers.
__ MultiPopFPU(kCalleeSavedFPU);
}
// Inlining the double comparison and falling back to the general compare
// stub if NaN is involved or FPU is unsupported.
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
// Load left and right operand.
Label done, left, left_smi, right_smi;
void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
masm->MultiPush((kJSCallerSaved | ra.bit()) & ~scratch1_.bit());
if (mode == kSaveFPRegs) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
masm->MultiPushFPU(kCallerSavedFPU);
}
}
inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
SaveFPRegsMode mode) {
if (mode == kSaveFPRegs) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
masm->MultiPopFPU(kCallerSavedFPU);
}
masm->MultiPop((kJSCallerSaved | ra.bit()) & ~scratch1_.bit());
MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
{
- CpuFeatures::Scope use_fpu(FPU);
+ CpuFeatureScope use_fpu(&masm, FPU);
DoubleRegister input = f12;
DoubleRegister result = f0;
DoubleRegister double_scratch1 = f4;
// Normal smi, convert to double and store.
if (fpu_supported) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ mtc1(t5, f0);
__ cvt_d_w(f0, f0);
__ sdc1(f0, MemOperand(t3));
kDoubleSize * FPURegister::kMaxNumAllocatableRegisters;
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
// Save all FPU registers before messing with them.
__ Subu(sp, sp, Operand(kDoubleRegsSize));
for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
int double_regs_offset = FrameDescription::double_registers_offset();
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
// Copy FPU registers to
// double_registers_[DoubleRegister::kNumAllocatableRegisters]
for (int i = 0; i < FPURegister::NumAllocatableRegisters(); ++i) {
__ Branch(&outer_push_loop, lt, t0, Operand(a1));
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
__ lw(a1, MemOperand(a0, Deoptimizer::input_offset()));
for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
__ lw(a0, FieldMemOperand(a0, GlobalObject::kNativeContextOffset));
__ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
// 0x41300000 is the top half of 1.0 x 2^20 as a double.
__ li(a1, Operand(0x41300000));
// Move 0x41300000xxxxxxxx (x = random bits in v0) to FPU.
HPhase phase("Z_Code generation", chunk());
ASSERT(is_unused());
status_ = GENERATING;
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
// Open a frame scope to indicate that there is a frame on the stack. The
// NONE indicates that the scope shouldn't actually generate code to set up
}
if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
Comment(";;; Save clobbered callee double registers");
int count = 0;
BitVector* doubles = chunk()->allocated_double_registers();
void LCodeGen::DoConstantD(LConstantD* instr) {
ASSERT(instr->result()->IsDoubleRegister());
DoubleRegister result = ToDoubleRegister(instr->result());
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
double v = instr->value();
__ Move(result, v);
}
__ bind(&done);
} else {
ASSERT(instr->hydrogen()->representation().IsDouble());
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
FPURegister left_reg = ToDoubleRegister(left);
FPURegister right_reg = ToDoubleRegister(right);
FPURegister result_reg = ToDoubleRegister(instr->result());
void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
DoubleRegister left = ToDoubleRegister(instr->left());
DoubleRegister right = ToDoubleRegister(instr->right());
DoubleRegister result = ToDoubleRegister(instr->result());
Register reg = ToRegister(instr->value());
EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg));
} else if (r.IsDouble()) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
DoubleRegister reg = ToDoubleRegister(instr->value());
// Test the double value. Zero and NaN are false.
EmitBranchF(true_block, false_block, ne, reg, kDoubleRegZero);
}
if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
// heap number -> false iff +0, -0, or NaN.
DoubleRegister dbl_scratch = double_scratch0();
Label not_heap_number;
EmitGoto(next_block);
} else {
if (instr->is_double()) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
// Compare left and right as doubles and load the
// resulting flags into the normal status register.
FPURegister left_reg = ToDoubleRegister(left);
__ CallRuntime(Runtime::kTraceExit, 1);
}
if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
ASSERT(NeedsEagerFrame());
BitVector* doubles = chunk()->allocated_double_registers();
BitVector::Iterator save_iterator(doubles);
__ Addu(scratch0(), scratch0(), external_pointer);
}
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
__ lwc1(result, MemOperand(scratch0(), additional_offset));
__ cvt_d_s(result, result);
__ Addu(elements, elements, scratch);
}
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
__ Addu(elements, elements, Operand(base_offset));
__ ldc1(result, MemOperand(elements));
if (instr->hydrogen()->RequiresHoleCheck()) {
void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
// Class for deferred case.
class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
public:
void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
DoubleRegister input = ToDoubleRegister(instr->value());
Register result = ToRegister(instr->result());
Register scratch1 = scratch0();
void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
DoubleRegister input = ToDoubleRegister(instr->value());
Register result = ToRegister(instr->result());
DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp());
void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
DoubleRegister input = ToDoubleRegister(instr->value());
DoubleRegister result = ToDoubleRegister(instr->result());
__ sqrt_d(result, input);
void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
DoubleRegister input = ToDoubleRegister(instr->value());
DoubleRegister result = ToDoubleRegister(instr->result());
DoubleRegister temp = ToDoubleRegister(instr->temp());
void LCodeGen::DoPower(LPower* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
Representation exponent_type = instr->hydrogen()->right()->representation();
// Having marked this as a call, we can use any registers.
// Just make sure that the input/output registers are the expected ones.
void LCodeGen::DoRandom(LRandom* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
class DeferredDoRandom: public LDeferredCode {
public:
DeferredDoRandom(LCodeGen* codegen, LRandom* instr)
void LCodeGen::DoMathExp(LMathExp* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
DoubleRegister input = ToDoubleRegister(instr->value());
DoubleRegister result = ToDoubleRegister(instr->result());
DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
Register external_pointer = ToRegister(instr->elements());
Register key = no_reg;
ElementsKind elements_kind = instr->elements_kind();
void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
DoubleRegister value = ToDoubleRegister(instr->value());
Register elements = ToRegister(instr->elements());
Register key = no_reg;
void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
LOperand* input = instr->value();
ASSERT(input->IsRegister() || input->IsStackSlot());
LOperand* output = instr->result();
void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
LOperand* input = instr->value();
LOperand* output = instr->result();
__ Xor(src, src, Operand(0x80000000));
}
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
__ mtc1(src, dbl_scratch);
__ cvt_d_w(dbl_scratch, dbl_scratch);
} else {
}
} else {
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
__ mtc1(src, dbl_scratch);
__ Cvt_d_uw(dbl_scratch, dbl_scratch, f22);
} else {
// number.
__ bind(&done);
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
__ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset));
} else {
__ sw(sfpd_lo, MemOperand(dst, HeapNumber::kMantissaOffset));
Label done;
if (convert_hole) {
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
DoubleRegister input_reg = ToDoubleRegister(instr->value());
__ BranchF(&no_special_nan_handling, NULL, eq, input_reg, input_reg);
__ Move(reg, scratch0(), input_reg);
}
__ bind(deferred->exit());
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
__ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset));
} else {
__ sw(sfpd_lo, MemOperand(reg, HeapNumber::kValueOffset));
LEnvironment* env,
NumberUntagDMode mode) {
Register scratch = scratch0();
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
Label load_smi, heap_number, done;
// of the if.
if (instr->truncating()) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
Register scratch3 = ToRegister(instr->temp2());
FPURegister single_scratch = double_scratch.low();
ASSERT(!scratch3.is(input_reg) &&
void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
- CpuFeatures::Scope vfp_scope(FPU);
+ CpuFeatureScope vfp_scope(masm(), FPU);
DoubleRegister value_reg = ToDoubleRegister(instr->unclamped());
Register result_reg = ToRegister(instr->result());
DoubleRegister temp_reg = ToDoubleRegister(instr->temp());
void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
- CpuFeatures::Scope vfp_scope(FPU);
+ CpuFeatureScope vfp_scope(masm(), FPU);
Register unclamped_reg = ToRegister(instr->unclamped());
Register result_reg = ToRegister(instr->result());
__ ClampUint8(result_reg, unclamped_reg);
void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
- CpuFeatures::Scope vfp_scope(FPU);
+ CpuFeatureScope vfp_scope(masm(), FPU);
Register scratch = scratch0();
Register input_reg = ToRegister(instr->unclamped());
Register result_reg = ToRegister(instr->result());
} else if (source->IsStackSlot()) {
__ lw(kLithiumScratchReg, cgen_->ToMemOperand(source));
} else if (source->IsDoubleRegister()) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(cgen_->masm(), FPU);
__ mov_d(kLithiumScratchDouble, cgen_->ToDoubleRegister(source));
} else if (source->IsDoubleStackSlot()) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(cgen_->masm(), FPU);
__ ldc1(kLithiumScratchDouble, cgen_->ToMemOperand(source));
} else {
UNREACHABLE();
} else if (saved_destination_->IsStackSlot()) {
__ sw(kLithiumScratchReg, cgen_->ToMemOperand(saved_destination_));
} else if (saved_destination_->IsDoubleRegister()) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(cgen_->masm(), FPU);
__ mov_d(cgen_->ToDoubleRegister(saved_destination_),
kLithiumScratchDouble);
} else if (saved_destination_->IsDoubleStackSlot()) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(cgen_->masm(), FPU);
__ sdc1(kLithiumScratchDouble,
cgen_->ToMemOperand(saved_destination_));
} else {
MemOperand destination_operand = cgen_->ToMemOperand(destination);
if (in_cycle_) {
if (!destination_operand.OffsetIsInt16Encodable()) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(cgen_->masm(), FPU);
// 'at' is overwritten while saving the value to the destination.
// Therefore we can't use 'at'. It is OK if the read from the source
// destroys 'at', since that happens before the value is read.
}
} else if (source->IsDoubleRegister()) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(cgen_->masm(), FPU);
DoubleRegister source_register = cgen_->ToDoubleRegister(source);
if (destination->IsDoubleRegister()) {
__ mov_d(cgen_->ToDoubleRegister(destination), source_register);
}
} else if (source->IsDoubleStackSlot()) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(cgen_->masm(), FPU);
MemOperand source_operand = cgen_->ToMemOperand(source);
if (destination->IsDoubleRegister()) {
__ ldc1(cgen_->ToDoubleRegister(destination), source_operand);
void MacroAssembler::MultiPushFPU(RegList regs) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
int16_t num_to_push = NumberOfBitsSet(regs);
int16_t stack_offset = num_to_push * kDoubleSize;
void MacroAssembler::MultiPushReversedFPU(RegList regs) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
int16_t num_to_push = NumberOfBitsSet(regs);
int16_t stack_offset = num_to_push * kDoubleSize;
void MacroAssembler::MultiPopFPU(RegList regs) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
int16_t stack_offset = 0;
for (int16_t i = 0; i < kNumRegisters; i++) {
void MacroAssembler::MultiPopReversedFPU(RegList regs) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
int16_t stack_offset = 0;
for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
void MacroAssembler::Move(FPURegister dst, double imm) {
- ASSERT(CpuFeatures::IsEnabled(FPU));
+ ASSERT(IsEnabled(FPU));
static const DoubleRepresentation minus_zero(-0.0);
static const DoubleRepresentation zero(0.0);
DoubleRepresentation value(imm);
}
bind(&right_exponent);
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
// MIPS FPU instructions implementing double precision to integer
// conversion using round to zero. Since the FP value was qualified
// above, the resulting integer should be a legal int32.
ASSERT(!except_flag.is(scratch));
ASSERT(CpuFeatures::IsSupported(FPU));
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
Label done;
// Clear the except flag (0 = no exception)
Register scratch,
Register scratch2,
Register scratch3) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
ASSERT(!scratch2.is(result));
ASSERT(!scratch3.is(result));
ASSERT(!scratch3.is(scratch2));
scratch4,
f2);
if (destination == FloatingPointHelper::kFPURegisters) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
sdc1(f0, MemOperand(scratch1, 0));
} else {
sw(mantissa_reg, MemOperand(scratch1, 0));
void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
if (IsMipsSoftFloatABI) {
Move(dst, v0, v1);
} else {
void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
if (!IsMipsSoftFloatABI) {
Move(f12, dreg);
} else {
void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg1,
DoubleRegister dreg2) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
if (!IsMipsSoftFloatABI) {
if (dreg2.is(f12)) {
ASSERT(!dreg1.is(f14));
void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg,
Register reg) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
if (!IsMipsSoftFloatABI) {
Move(f12, dreg);
Move(a2, reg);
const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
if (save_doubles) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
// The stack must be allign to 0 modulo 8 for stores with sdc1.
ASSERT(kDoubleSize == frame_alignment);
if (frame_alignment > 0) {
bool do_return) {
// Optionally restore all double registers.
if (save_doubles) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(this, FPU);
// Remember: we only need to restore every 2nd double FPU value.
lw(t8, MemOperand(fp, ExitFrameConstants::kSPOffset));
for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
Register scratch1,
Register scratch2) {
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ mtc1(ival, f0);
__ cvt_s_w(f0, f0);
__ sll(scratch1, wordoffset, 2);
return Handle<Code>::null();
}
- CpuFeatures::Scope scope_fpu(FPU);
+ CpuFeatureScope scope_fpu(masm(), FPU);
const int argc = arguments().immediate();
// If the object is not a JSObject or we got an unexpected number of
// arguments, bail out to the regular call.
FPURegister double_scratch1,
Label* fail) {
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
Label key_ok;
// Check for smi or a smi inside a heap number. We convert the heap
// number and check if the conversion is exact and fits into the smi
f0, t2, t3, // These are: double_dst, dst_mantissa, dst_exponent.
t0, f2); // These are: scratch2, single_scratch.
if (destination == FloatingPointHelper::kFPURegisters) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm(), FPU);
__ sdc1(f0, MemOperand(a3, 0));
} else {
__ sw(t2, MemOperand(a3, 0));
// reproducible behavior, convert these to zero.
if (CpuFeatures::IsSupported(FPU)) {
- CpuFeatures::Scope scope(FPU);
+ CpuFeatureScope scope(masm, FPU);
__ ldc1(f0, FieldMemOperand(a0, HeapNumber::kValueOffset));
bool CpuFeatures::initialized_ = false;
#endif
uint64_t CpuFeatures::supported_ = CpuFeatures::kDefaultCpuFeatures;
-uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
+uint64_t CpuFeatures::found_by_runtime_probing_only_ = 0;
ExternalReference ExternalReference::cpu_features() {
__ bind(&cpuid);
__ movl(rax, Immediate(1));
supported_ = kDefaultCpuFeatures | (1 << CPUID);
- { Scope fscope(CPUID);
+ { CpuFeatureScope fscope(&assm, CPUID);
__ cpuid();
// Move the result from ecx:edx to rdi.
__ movl(rdi, rdx); // Zero-extended to 64 bits.
typedef uint64_t (*F0)();
F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
- supported_ = probe();
- found_by_runtime_probing_ = supported_;
- found_by_runtime_probing_ &= ~kDefaultCpuFeatures;
- uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
- supported_ |= os_guarantees;
- found_by_runtime_probing_ &= ~os_guarantees;
+
+ uint64_t probed_features = probe();
+ uint64_t platform_features = OS::CpuFeaturesImpliedByPlatform();
+ supported_ = probed_features | platform_features;
+ found_by_runtime_probing_only_
+ = probed_features & ~kDefaultCpuFeatures & ~platform_features;
+
// SSE2 and CMOV must be available on an X64 CPU.
ASSERT(IsSupported(CPUID));
ASSERT(IsSupported(SSE2));
void Assembler::cpuid() {
- ASSERT(CpuFeatures::IsEnabled(CPUID));
+ ASSERT(IsEnabled(CPUID));
EnsureSpace ensure_space(this);
emit(0x0F);
emit(0xA2);
void Assembler::fisttp_s(const Operand& adr) {
- ASSERT(CpuFeatures::IsEnabled(SSE3));
+ ASSERT(IsEnabled(SSE3));
EnsureSpace ensure_space(this);
emit_optional_rex_32(adr);
emit(0xDB);
void Assembler::fisttp_d(const Operand& adr) {
- ASSERT(CpuFeatures::IsEnabled(SSE3));
+ ASSERT(IsEnabled(SSE3));
EnsureSpace ensure_space(this);
emit_optional_rex_32(adr);
emit(0xDD);
void Assembler::roundsd(XMMRegister dst, XMMRegister src,
Assembler::RoundingMode mode) {
- ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+ ASSERT(IsEnabled(SSE4_1));
EnsureSpace ensure_space(this);
emit(0x66);
emit_optional_rex_32(dst, src);
// CpuFeatures keeps track of which features are supported by the target CPU.
-// Supported features must be enabled by a Scope before use.
+// Supported features must be enabled by a CpuFeatureScope before use.
// Example:
-// if (CpuFeatures::IsSupported(SSE3)) {
-// CpuFeatures::Scope fscope(SSE3);
+// if (assembler->IsSupported(SSE3)) {
+// CpuFeatureScope fscope(assembler, SSE3);
// // Generate SSE3 floating point code.
// } else {
// // Generate standard x87 or SSE2 floating point code.
if (f == CMOV && !FLAG_enable_cmov) return false;
if (f == RDTSC && !FLAG_enable_rdtsc) return false;
if (f == SAHF && !FLAG_enable_sahf) return false;
- return (supported_ & (V8_UINT64_C(1) << f)) != 0;
+ return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
}
-#ifdef DEBUG
- // Check whether a feature is currently enabled.
- static bool IsEnabled(CpuFeature f) {
+ static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
ASSERT(initialized_);
- Isolate* isolate = Isolate::UncheckedCurrent();
- if (isolate == NULL) {
- // When no isolate is available, work as if we're running in
- // release mode.
- return IsSupported(f);
- }
- uint64_t enabled = isolate->enabled_cpu_features();
- return (enabled & (V8_UINT64_C(1) << f)) != 0;
+ return (found_by_runtime_probing_only_ &
+ (static_cast<uint64_t>(1) << f)) != 0;
}
-#endif
-
- // Enable a specified feature within a scope.
- class Scope BASE_EMBEDDED {
-#ifdef DEBUG
-
- public:
- explicit Scope(CpuFeature f) {
- uint64_t mask = V8_UINT64_C(1) << f;
- ASSERT(CpuFeatures::IsSupported(f));
- ASSERT(!Serializer::enabled() ||
- (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
- isolate_ = Isolate::UncheckedCurrent();
- old_enabled_ = 0;
- if (isolate_ != NULL) {
- old_enabled_ = isolate_->enabled_cpu_features();
- isolate_->set_enabled_cpu_features(old_enabled_ | mask);
- }
- }
- ~Scope() {
- ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
- if (isolate_ != NULL) {
- isolate_->set_enabled_cpu_features(old_enabled_);
- }
- }
-
- private:
- Isolate* isolate_;
- uint64_t old_enabled_;
-#else
-
- public:
- explicit Scope(CpuFeature f) {}
-#endif
- };
private:
// Safe defaults include SSE2 and CMOV for X64. It is always available, if
static bool initialized_;
#endif
static uint64_t supported_;
- static uint64_t found_by_runtime_probing_;
+ static uint64_t found_by_runtime_probing_only_;
friend class ExternalReference;
DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
XMMRegister input_reg = ToDoubleRegister(instr->value());
if (CpuFeatures::IsSupported(SSE4_1)) {
- CpuFeatures::Scope scope(SSE4_1);
+ CpuFeatureScope scope(masm(), SSE4_1);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// Deoptimize if minus zero.
__ movq(output_reg, input_reg);
}
// R12 to r15 are callee save on all platforms.
if (fp_mode == kSaveFPRegs) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(this, SSE2);
subq(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters));
for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
XMMRegister reg = XMMRegister::from_code(i);
Register exclusion2,
Register exclusion3) {
if (fp_mode == kSaveFPRegs) {
- CpuFeatures::Scope scope(SSE2);
+ CpuFeatureScope scope(this, SSE2);
for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
XMMRegister reg = XMMRegister::from_code(i);
movsd(reg, Operand(rsp, i * kDoubleSize));
if (CpuFeatures::IsSupported(VFP3)) {
- CpuFeatures::Scope scope(VFP3);
+ CpuFeatureScope scope(&assm, VFP3);
__ mov(ip, Operand(sp));
__ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
Assembler assm(isolate, NULL, 0);
if (CpuFeatures::IsSupported(ARMv7)) {
- CpuFeatures::Scope scope(ARMv7);
+ CpuFeatureScope scope(&assm, ARMv7);
// On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
__ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555
__ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11
Assembler assm(isolate, NULL, 0);
if (CpuFeatures::IsSupported(ARMv7)) {
- CpuFeatures::Scope scope(ARMv7);
+ CpuFeatureScope scope(&assm, ARMv7);
__ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF.
__ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
__ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0.
Assembler assm(isolate, NULL, 0);
if (CpuFeatures::IsSupported(VFP3)) {
- CpuFeatures::Scope scope(VFP3);
+ CpuFeatureScope scope(&assm, VFP3);
Label wrong_exception;
Assembler assm(isolate, NULL, 0);
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(&assm, VFP2);
__ mov(ip, Operand(sp));
__ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
Assembler assm(isolate, NULL, 0);
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(&assm, VFP2);
__ mov(ip, Operand(sp));
__ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
Assembler assm(isolate, NULL, 0);
if (CpuFeatures::IsSupported(VFP2)) {
- CpuFeatures::Scope scope(VFP2);
+ CpuFeatureScope scope(&assm, VFP2);
__ mov(ip, Operand(sp));
__ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
if (CpuFeatures::IsSupported(VFP3)) {
- CpuFeatures::Scope scope(VFP3);
+ CpuFeatureScope scope(&assm, VFP3);
__ stm(db_w, sp, r4.bit() | lr.bit());
Assembler assm(isolate, buffer, sizeof buffer);
CHECK(CpuFeatures::IsSupported(SSE2));
- { CpuFeatures::Scope fscope(SSE2);
+ { CpuFeatureScope fscope(&assm, SSE2);
__ cvttss2si(eax, Operand(esp, 4));
__ ret(0);
}
Assembler assm(isolate, buffer, sizeof buffer);
CHECK(CpuFeatures::IsSupported(SSE2));
- CpuFeatures::Scope fscope(SSE2);
+ CpuFeatureScope fscope(&assm, SSE2);
__ cvttsd2si(eax, Operand(esp, 4));
__ ret(0);
if (!CpuFeatures::IsSupported(SSE2)) return;
v8::HandleScope scope;
- CHECK(CpuFeatures::IsSupported(SSE2));
- CpuFeatures::Scope fscope(SSE2);
v8::internal::byte buffer[256];
Isolate* isolate = Isolate::Current();
Assembler assm(isolate, buffer, sizeof buffer);
+ CpuFeatureScope fscope(&assm, SSE2);
__ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
__ movdbl(xmm1, Operand(esp, 3 * kPointerSize));
__ addsd(xmm0, xmm1);
if (!CpuFeatures::IsSupported(SSE2)) return;
v8::HandleScope scope;
- CHECK(CpuFeatures::IsSupported(SSE2));
- CpuFeatures::Scope fscope(SSE2);
v8::internal::byte buffer[256];
Isolate* isolate = Isolate::Current();
Assembler assm(isolate, buffer, sizeof buffer);
+ CpuFeatureScope fscope(&assm, SSE2);
__ mov(eax, Operand(esp, 4));
__ cvtsi2sd(xmm0, eax);
// Copy xmm0 to st(0) using eight bytes of stack.
SET_UP();
if (CpuFeatures::IsSupported(VFP3)) {
- CpuFeatures::Scope scope(VFP3);
+ CpuFeatureScope scope(&assm, VFP3);
COMPARE(vmov(d0, r2, r3),
"ec432b10 vmov d0, r2, r3");
COMPARE(vmov(r2, r3, d0),
"e7210002 str r0, [r1, -r2]!");
if (CpuFeatures::IsSupported(ARMv7)) {
- CpuFeatures::Scope scope(ARMv7);
+ CpuFeatureScope scope(&assm, ARMv7);
COMPARE(ldrd(r0, r1, MemOperand(r1)),
"e1c100d0 ldrd r0, [r1, #+0]");
COMPARE(ldrd(r2, r3, MemOperand(r3, 127)),
__ nop();
{
CHECK(CpuFeatures::IsSupported(CPUID));
- CpuFeatures::Scope fscope(CPUID);
+ CpuFeatureScope fscope(&assm, CPUID);
__ cpuid();
}
{
CHECK(CpuFeatures::IsSupported(RDTSC));
- CpuFeatures::Scope fscope(RDTSC);
+ CpuFeatureScope fscope(&assm, RDTSC);
__ rdtsc();
}
__ movsx_b(edx, ecx);
__ nop();
{
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope fscope(SSE2);
+ CpuFeatureScope fscope(&assm, SSE2);
__ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000));
__ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000));
__ addsd(xmm1, xmm0);
// cmov.
{
if (CpuFeatures::IsSupported(CMOV)) {
- CpuFeatures::Scope use_cmov(CMOV);
+ CpuFeatureScope use_cmov(&assm, CMOV);
__ cmov(overflow, eax, Operand(eax, 0));
__ cmov(no_overflow, eax, Operand(eax, 1));
__ cmov(below, eax, Operand(eax, 2));
// andpd, cmpltsd, movaps, psllq, psrlq, por.
{
if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope fscope(SSE2);
+ CpuFeatureScope fscope(&assm, SSE2);
__ andpd(xmm0, xmm1);
__ andpd(xmm1, xmm2);
{
if (CpuFeatures::IsSupported(SSE2) &&
CpuFeatures::IsSupported(SSE4_1)) {
- CpuFeatures::Scope scope(SSE4_1);
+ CpuFeatureScope scope(&assm, SSE4_1);
__ pextrd(eax, xmm0, 1);
__ pinsrd(xmm1, eax, 0);
}