| Index: src/arm/assembler-arm.h
|
| diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
|
| index 27befaa51aa71c4dbc36eedc97659c705dd9313b..97e5eefdd4cc1c78048133173d310bc6231b052f 100644
|
| --- a/src/arm/assembler-arm.h
|
| +++ b/src/arm/assembler-arm.h
|
| @@ -47,6 +47,116 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| +// CpuFeatures keeps track of which features are supported by the target CPU.
|
| +// Supported features must be enabled by a Scope before use.
|
| +class CpuFeatures : public AllStatic {
|
| + public:
|
| + // Detect features of the target CPU. Set safe defaults if the serializer
|
| + // is enabled (snapshots must be portable).
|
| + static void Probe();
|
| +
|
| + // Check whether a feature is supported by the target CPU.
|
| + static bool IsSupported(CpuFeature f) {
|
| + ASSERT(initialized_);
|
| + if (f == VFP3 && !FLAG_enable_vfp3) return false;
|
| + if (f == VFP2 && !FLAG_enable_vfp2) return false;
|
| + if (f == SUDIV && !FLAG_enable_sudiv) return false;
|
| + if (f == UNALIGNED_ACCESSES && !FLAG_enable_unaligned_accesses) {
|
| + return false;
|
| + }
|
| + if (f == VFP32DREGS && !FLAG_enable_32dregs) return false;
|
| + return (supported_ & (1u << f)) != 0;
|
| + }
|
| +
|
| +#ifdef DEBUG
|
| + // Check whether a feature is currently enabled.
|
| + static bool IsEnabled(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;
|
| + }
|
| +#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:
|
| + explicit TryForceFeatureScope(CpuFeature f)
|
| + : old_supported_(CpuFeatures::supported_) {
|
| + if (CanForce()) {
|
| + CpuFeatures::supported_ |= (1u << f);
|
| + }
|
| + }
|
| +
|
| + ~TryForceFeatureScope() {
|
| + if (CanForce()) {
|
| + CpuFeatures::supported_ = old_supported_;
|
| + }
|
| + }
|
| +
|
| + private:
|
| + static bool CanForce() {
|
| + // It's only safe to temporarily force support of CPU features
|
| + // when there's only a single isolate, which is guaranteed when
|
| + // the serializer is enabled.
|
| + return Serializer::enabled();
|
| + }
|
| +
|
| + const unsigned old_supported_;
|
| + };
|
| +
|
| + private:
|
| +#ifdef DEBUG
|
| + static bool initialized_;
|
| +#endif
|
| + static unsigned supported_;
|
| + static unsigned found_by_runtime_probing_;
|
| +
|
| + friend class ExternalReference;
|
| + DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
|
| +};
|
| +
|
| +
|
| // CPU Registers.
|
| //
|
| // 1) We would prefer to use an enum, but enum values are assignment-
|
| @@ -192,7 +302,7 @@ struct SwVfpRegister {
|
|
|
| // Double word VFP register.
|
| struct DwVfpRegister {
|
| - static const int kNumRegisters = 16;
|
| + static const int kNumRegisters = 32;
|
| // A few double registers are reserved: one as a scratch register and one to
|
| // hold 0.0, that does not fit in the immediate field of vmov instructions.
|
| // d14: 0.0
|
| @@ -205,21 +315,19 @@ struct DwVfpRegister {
|
| inline static int NumAllocatableRegisters();
|
| inline static int ToAllocationIndex(DwVfpRegister reg);
|
| static const char* AllocationIndexToString(int index);
|
| -
|
| - static DwVfpRegister FromAllocationIndex(int index) {
|
| - ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
|
| - return from_code(index);
|
| - }
|
| + inline static DwVfpRegister FromAllocationIndex(int index);
|
|
|
| static DwVfpRegister from_code(int code) {
|
| DwVfpRegister r = { code };
|
| return r;
|
| }
|
|
|
| - // Supporting d0 to d15, can be later extended to d31.
|
| - bool is_valid() const { return 0 <= code_ && code_ < 16; }
|
| + bool is_valid() const {
|
| + return 0 <= code_ && code_ < kNumRegisters;
|
| + }
|
| bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
|
| SwVfpRegister low() const {
|
| + ASSERT(code_ < 16);
|
| SwVfpRegister reg;
|
| reg.code_ = code_ * 2;
|
|
|
| @@ -227,6 +335,7 @@ struct DwVfpRegister {
|
| return reg;
|
| }
|
| SwVfpRegister high() const {
|
| + ASSERT(code_ < 16);
|
| SwVfpRegister reg;
|
| reg.code_ = (code_ * 2) + 1;
|
|
|
| @@ -306,6 +415,22 @@ const DwVfpRegister d12 = { 12 };
|
| const DwVfpRegister d13 = { 13 };
|
| const DwVfpRegister d14 = { 14 };
|
| const DwVfpRegister d15 = { 15 };
|
| +const DwVfpRegister d16 = { 16 };
|
| +const DwVfpRegister d17 = { 17 };
|
| +const DwVfpRegister d18 = { 18 };
|
| +const DwVfpRegister d19 = { 19 };
|
| +const DwVfpRegister d20 = { 20 };
|
| +const DwVfpRegister d21 = { 21 };
|
| +const DwVfpRegister d22 = { 22 };
|
| +const DwVfpRegister d23 = { 23 };
|
| +const DwVfpRegister d24 = { 24 };
|
| +const DwVfpRegister d25 = { 25 };
|
| +const DwVfpRegister d26 = { 26 };
|
| +const DwVfpRegister d27 = { 27 };
|
| +const DwVfpRegister d28 = { 28 };
|
| +const DwVfpRegister d29 = { 29 };
|
| +const DwVfpRegister d30 = { 30 };
|
| +const DwVfpRegister d31 = { 31 };
|
|
|
| const Register sfpd_lo = { kRegister_r6_Code };
|
| const Register sfpd_hi = { kRegister_r7_Code };
|
| @@ -485,114 +610,6 @@ class MemOperand BASE_EMBEDDED {
|
| friend class Assembler;
|
| };
|
|
|
| -// CpuFeatures keeps track of which features are supported by the target CPU.
|
| -// Supported features must be enabled by a Scope before use.
|
| -class CpuFeatures : public AllStatic {
|
| - public:
|
| - // Detect features of the target CPU. Set safe defaults if the serializer
|
| - // is enabled (snapshots must be portable).
|
| - static void Probe();
|
| -
|
| - // Check whether a feature is supported by the target CPU.
|
| - static bool IsSupported(CpuFeature f) {
|
| - ASSERT(initialized_);
|
| - if (f == VFP3 && !FLAG_enable_vfp3) return false;
|
| - if (f == VFP2 && !FLAG_enable_vfp2) return false;
|
| - if (f == SUDIV && !FLAG_enable_sudiv) return false;
|
| - if (f == UNALIGNED_ACCESSES && !FLAG_enable_unaligned_accesses) {
|
| - return false;
|
| - }
|
| - return (supported_ & (1u << f)) != 0;
|
| - }
|
| -
|
| -#ifdef DEBUG
|
| - // Check whether a feature is currently enabled.
|
| - static bool IsEnabled(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;
|
| - }
|
| -#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:
|
| - explicit TryForceFeatureScope(CpuFeature f)
|
| - : old_supported_(CpuFeatures::supported_) {
|
| - if (CanForce()) {
|
| - CpuFeatures::supported_ |= (1u << f);
|
| - }
|
| - }
|
| -
|
| - ~TryForceFeatureScope() {
|
| - if (CanForce()) {
|
| - CpuFeatures::supported_ = old_supported_;
|
| - }
|
| - }
|
| -
|
| - private:
|
| - static bool CanForce() {
|
| - // It's only safe to temporarily force support of CPU features
|
| - // when there's only a single isolate, which is guaranteed when
|
| - // the serializer is enabled.
|
| - return Serializer::enabled();
|
| - }
|
| -
|
| - const unsigned old_supported_;
|
| - };
|
| -
|
| - private:
|
| -#ifdef DEBUG
|
| - static bool initialized_;
|
| -#endif
|
| - static unsigned supported_;
|
| - static unsigned found_by_runtime_probing_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
|
| -};
|
| -
|
| -
|
| extern const Instr kMovLrPc;
|
| extern const Instr kLdrPCMask;
|
| extern const Instr kLdrPCPattern;
|
| @@ -981,10 +998,7 @@ class Assembler : public AssemblerBase {
|
| LFlag l = Short); // v5 and above
|
|
|
| // Support for VFP.
|
| - // All these APIs support S0 to S31 and D0 to D15.
|
| - // Currently these APIs do not support extended D registers, i.e, D16 to D31.
|
| - // However, some simple modifications can allow
|
| - // these APIs to support D16 to D31.
|
| + // All these APIs support S0 to S31 and D0 to D31.
|
|
|
| void vldr(const DwVfpRegister dst,
|
| const Register base,
|
| @@ -1053,6 +1067,10 @@ class Assembler : public AssemblerBase {
|
| const DwVfpRegister src,
|
| const Condition cond = al);
|
| void vmov(const DwVfpRegister dst,
|
| + int index,
|
| + const Register src,
|
| + const Condition cond = al);
|
| + void vmov(const DwVfpRegister dst,
|
| const Register src1,
|
| const Register src2,
|
| const Condition cond = al);
|
|
|