| Index: src/arm/assembler-arm.cc
|
| diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
|
| index 78ffe25390592406cf51c78f21f5ab466b2c99fb..7a9af3928650ee85d2056b2e8dd1d334277211ae 100644
|
| --- a/src/arm/assembler-arm.cc
|
| +++ b/src/arm/assembler-arm.cc
|
| @@ -46,84 +46,201 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -// Get the CPU features enabled by the build. For cross compilation the
|
| -// preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS
|
| -// can be defined to enable ARMv7 and VFPv3 instructions when building the
|
| -// snapshot.
|
| -static unsigned CpuFeaturesImpliedByCompiler() {
|
| - unsigned answer = 0;
|
| -#ifdef CAN_USE_ARMV8_INSTRUCTIONS
|
| - if (FLAG_enable_armv8) {
|
| - answer |= 1u << ARMv8;
|
| - // ARMv8 always features VFP and NEON.
|
| - answer |= 1u << ARMv7 | 1u << VFP3 | 1u << NEON | 1u << VFP32DREGS;
|
| - answer |= 1u << SUDIV;
|
| +static const unsigned kArmv6 = 0u;
|
| +static const unsigned kArmv7 = kArmv6 | (1u << ARMv7);
|
| +static const unsigned kArmv7WithSudiv = kArmv7 | (1u << ARMv7_SUDIV);
|
| +static const unsigned kArmv8 = kArmv7WithSudiv | (1u << ARMv8);
|
| +
|
| +static unsigned CpuFeaturesFromCommandLine() {
|
| + unsigned result;
|
| + if (strcmp(FLAG_arm_arch, "armv8") == 0) {
|
| + result = kArmv8;
|
| + } else if (strcmp(FLAG_arm_arch, "armv7+sudiv") == 0) {
|
| + result = kArmv7WithSudiv;
|
| + } else if (strcmp(FLAG_arm_arch, "armv7") == 0) {
|
| + result = kArmv7;
|
| + } else if (strcmp(FLAG_arm_arch, "armv6") == 0) {
|
| + result = kArmv6;
|
| + } else {
|
| + fprintf(stderr, "Error: unrecognised value for --arm-arch ('%s').\n",
|
| + FLAG_arm_arch);
|
| + fprintf(stderr,
|
| + "Supported values are: armv8\n"
|
| + " armv7+sudiv\n"
|
| + " armv7\n"
|
| + " armv6\n");
|
| + CHECK(false);
|
| + }
|
| +
|
| + // If any of the old (deprecated) flags are specified, print a warning, but
|
| + // otherwise try to respect them for now.
|
| + // TODO(jbramley): When all the old bots have been updated, remove this.
|
| + if (FLAG_enable_armv7.has_value || FLAG_enable_vfp3.has_value ||
|
| + FLAG_enable_32dregs.has_value || FLAG_enable_neon.has_value ||
|
| + FLAG_enable_sudiv.has_value || FLAG_enable_armv8.has_value) {
|
| + // As an approximation of the old behaviour, set the default values from the
|
| + // arm_arch setting, then apply the flags over the top.
|
| + bool enable_armv7 = (result & (1u << ARMv7)) != 0;
|
| + bool enable_vfp3 = (result & (1u << ARMv7)) != 0;
|
| + bool enable_32dregs = (result & (1u << ARMv7)) != 0;
|
| + bool enable_neon = (result & (1u << ARMv7)) != 0;
|
| + bool enable_sudiv = (result & (1u << ARMv7_SUDIV)) != 0;
|
| + bool enable_armv8 = (result & (1u << ARMv8)) != 0;
|
| + if (FLAG_enable_armv7.has_value) {
|
| + fprintf(stderr,
|
| + "Warning: --enable_armv7 is deprecated. "
|
| + "Use --arm_arch instead.\n");
|
| + enable_armv7 = FLAG_enable_armv7.value;
|
| + }
|
| + if (FLAG_enable_vfp3.has_value) {
|
| + fprintf(stderr,
|
| + "Warning: --enable_vfp3 is deprecated. "
|
| + "Use --arm_arch instead.\n");
|
| + enable_vfp3 = FLAG_enable_vfp3.value;
|
| + }
|
| + if (FLAG_enable_32dregs.has_value) {
|
| + fprintf(stderr,
|
| + "Warning: --enable_32dregs is deprecated. "
|
| + "Use --arm_arch instead.\n");
|
| + enable_32dregs = FLAG_enable_32dregs.value;
|
| + }
|
| + if (FLAG_enable_neon.has_value) {
|
| + fprintf(stderr,
|
| + "Warning: --enable_neon is deprecated. "
|
| + "Use --arm_arch instead.\n");
|
| + enable_neon = FLAG_enable_neon.value;
|
| + }
|
| + if (FLAG_enable_sudiv.has_value) {
|
| + fprintf(stderr,
|
| + "Warning: --enable_sudiv is deprecated. "
|
| + "Use --arm_arch instead.\n");
|
| + enable_sudiv = FLAG_enable_sudiv.value;
|
| + }
|
| + if (FLAG_enable_armv8.has_value) {
|
| + fprintf(stderr,
|
| + "Warning: --enable_armv8 is deprecated. "
|
| + "Use --arm_arch instead.\n");
|
| + enable_armv8 = FLAG_enable_armv8.value;
|
| + }
|
| + // Emulate the old implications.
|
| + if (enable_armv8) {
|
| + enable_vfp3 = true;
|
| + enable_neon = true;
|
| + enable_32dregs = true;
|
| + enable_sudiv = true;
|
| + }
|
| + // Select the best available configuration.
|
| + if (enable_armv7 && enable_vfp3 && enable_32dregs && enable_neon) {
|
| + if (enable_sudiv) {
|
| + if (enable_armv8) {
|
| + result = kArmv8;
|
| + } else {
|
| + result = kArmv7WithSudiv;
|
| + }
|
| + } else {
|
| + result = kArmv7;
|
| + }
|
| + } else {
|
| + result = kArmv6;
|
| + }
|
| }
|
| -#endif // CAN_USE_ARMV8_INSTRUCTIONS
|
| -#ifdef CAN_USE_ARMV7_INSTRUCTIONS
|
| - if (FLAG_enable_armv7) answer |= 1u << ARMv7;
|
| -#endif // CAN_USE_ARMV7_INSTRUCTIONS
|
| -#ifdef CAN_USE_VFP3_INSTRUCTIONS
|
| - if (FLAG_enable_vfp3) answer |= 1u << VFP3 | 1u << ARMv7;
|
| -#endif // CAN_USE_VFP3_INSTRUCTIONS
|
| -#ifdef CAN_USE_VFP32DREGS
|
| - if (FLAG_enable_32dregs) answer |= 1u << VFP32DREGS;
|
| -#endif // CAN_USE_VFP32DREGS
|
| -#ifdef CAN_USE_NEON
|
| - if (FLAG_enable_neon) answer |= 1u << NEON;
|
| -#endif // CAN_USE_VFP32DREGS
|
| + return result;
|
| +}
|
| +
|
| +// Get the CPU features enabled by the build.
|
| +// For cross compilation the preprocessor symbols such as
|
| +// CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS can be used to
|
| +// enable ARMv7 and VFPv3 instructions when building the snapshot. However,
|
| +// these flags should be consistent with a supported ARM configuration:
|
| +// "armv6": ARMv6 + VFPv2
|
| +// "armv7": ARMv7 + VFPv3-D32 + NEON
|
| +// "armv7+sudiv": ARMv7 + VFPv4-D32 + NEON + SUDIV
|
| +// "armv8": ARMv8 (+ all of the above)
|
| +static constexpr unsigned CpuFeaturesFromCompiler() {
|
| +// TODO(jbramley): Once the build flags are simplified, these tests should
|
| +// also be simplified.
|
| +
|
| +// Check *architectural* implications.
|
| +#if defined(CAN_USE_ARMV8_INSTRUCTIONS) && !defined(CAN_USE_ARMV7_INSTRUCTIONS)
|
| +#error "CAN_USE_ARMV8_INSTRUCTIONS should imply CAN_USE_ARMV7_INSTRUCTIONS"
|
| +#endif
|
| +#if defined(CAN_USE_ARMV8_INSTRUCTIONS) && !defined(CAN_USE_SUDIV)
|
| +#error "CAN_USE_ARMV8_INSTRUCTIONS should imply CAN_USE_SUDIV"
|
| +#endif
|
| +#if defined(CAN_USE_ARMV7_INSTRUCTIONS) != defined(CAN_USE_VFP3_INSTRUCTIONS)
|
| +// V8 requires VFP, and all ARMv7 devices with VFP have VFPv3. Similarly,
|
| +// VFPv3 isn't available before ARMv7.
|
| +#error "CAN_USE_ARMV7_INSTRUCTIONS should match CAN_USE_VFP3_INSTRUCTIONS"
|
| +#endif
|
| +#if defined(CAN_USE_NEON) && !defined(CAN_USE_ARMV7_INSTRUCTIONS)
|
| +#error "CAN_USE_NEON should imply CAN_USE_ARMV7_INSTRUCTIONS"
|
| +#endif
|
|
|
| - return answer;
|
| +// Find compiler-implied features.
|
| +#if defined(CAN_USE_ARMV8_INSTRUCTIONS) && \
|
| + defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_SUDIV) && \
|
| + defined(CAN_USE_NEON) && defined(CAN_USE_VFP3_INSTRUCTIONS)
|
| + return kArmv8;
|
| +#elif defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_SUDIV) && \
|
| + defined(CAN_USE_NEON) && defined(CAN_USE_VFP3_INSTRUCTIONS)
|
| + return kArmv7WithSudiv;
|
| +#elif defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_NEON) && \
|
| + defined(CAN_USE_VFP3_INSTRUCTIONS)
|
| + return kArmv7;
|
| +#else
|
| + return kArmv6;
|
| +#endif
|
| }
|
|
|
|
|
| void CpuFeatures::ProbeImpl(bool cross_compile) {
|
| - supported_ |= CpuFeaturesImpliedByCompiler();
|
| dcache_line_size_ = 64;
|
|
|
| + unsigned command_line = CpuFeaturesFromCommandLine();
|
| // Only use statically determined features for cross compile (snapshot).
|
| - if (cross_compile) return;
|
| + if (cross_compile) {
|
| + supported_ |= command_line & CpuFeaturesFromCompiler();
|
| + return;
|
| + }
|
|
|
| #ifndef __arm__
|
| // For the simulator build, use whatever the flags specify.
|
| - if (FLAG_enable_armv8) {
|
| - supported_ |= 1u << ARMv8;
|
| - // ARMv8 always features VFP and NEON.
|
| - supported_ |= 1u << ARMv7 | 1u << VFP3 | 1u << NEON | 1u << VFP32DREGS;
|
| - supported_ |= 1u << SUDIV;
|
| - if (FLAG_enable_movw_movt) supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
|
| - }
|
| - if (FLAG_enable_armv7) {
|
| - supported_ |= 1u << ARMv7;
|
| - if (FLAG_enable_vfp3) supported_ |= 1u << VFP3;
|
| - if (FLAG_enable_neon) supported_ |= 1u << NEON | 1u << VFP32DREGS;
|
| - if (FLAG_enable_sudiv) supported_ |= 1u << SUDIV;
|
| - if (FLAG_enable_movw_movt) supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
|
| - if (FLAG_enable_32dregs) supported_ |= 1u << VFP32DREGS;
|
| + supported_ |= command_line;
|
| +
|
| + if (FLAG_enable_movw_movt && ((supported_ & kArmv7) == kArmv7)) {
|
| + supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
|
| }
|
|
|
| #else // __arm__
|
| // Probe for additional features at runtime.
|
| base::CPU cpu;
|
| - if (FLAG_enable_vfp3 && cpu.has_vfp3()) {
|
| - // This implementation also sets the VFP flags if runtime
|
| - // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI
|
| - // 0406B, page A1-6.
|
| - supported_ |= 1u << VFP3 | 1u << ARMv7;
|
| + // Runtime detection is slightly fuzzy, and some inferences are necessary.
|
| + unsigned runtime = kArmv6;
|
| + // NEON and VFPv3 imply at least ARMv7-A.
|
| + if (cpu.has_neon() && cpu.has_vfp3_d32()) {
|
| + DCHECK(cpu.has_vfp3());
|
| + runtime |= kArmv7;
|
| + if (cpu.has_idiva()) {
|
| + runtime |= kArmv7WithSudiv;
|
| + if (cpu.architecture() >= 8) {
|
| + runtime |= kArmv8;
|
| + }
|
| + }
|
| }
|
|
|
| - if (FLAG_enable_neon && cpu.has_neon()) supported_ |= 1u << NEON;
|
| - if (FLAG_enable_sudiv && cpu.has_idiva()) supported_ |= 1u << SUDIV;
|
| + // Use the best of the features found by CPU detection and those inferred from
|
| + // the build system. In both cases, restrict available features using the
|
| + // command-line. Note that the command-line flags are very permissive (kArmv8)
|
| + // by default.
|
| + supported_ |= command_line & CpuFeaturesFromCompiler();
|
| + supported_ |= command_line & runtime;
|
|
|
| - if (cpu.architecture() >= 7) {
|
| - if (FLAG_enable_armv7) supported_ |= 1u << ARMv7;
|
| - if (FLAG_enable_armv8 && cpu.architecture() >= 8) {
|
| - supported_ |= 1u << ARMv8;
|
| - }
|
| - // Use movw/movt for QUALCOMM ARMv7 cores.
|
| - if (FLAG_enable_movw_movt && cpu.implementer() == base::CPU::QUALCOMM) {
|
| - supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
|
| - }
|
| + // Additional tuning options.
|
| +
|
| + // Prefer to use movw/movt for QUALCOMM ARMv7 cores.
|
| + if (FLAG_enable_movw_movt && ((supported_ & kArmv7) == kArmv7) &&
|
| + (cpu.implementer() == base::CPU::QUALCOMM)) {
|
| + supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
|
| }
|
|
|
| // ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines.
|
| @@ -132,11 +249,11 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
|
| cpu.part() == base::CPU::ARM_CORTEX_A9)) {
|
| dcache_line_size_ = 32;
|
| }
|
| -
|
| - if (FLAG_enable_32dregs && cpu.has_vfp3_d32()) supported_ |= 1u << VFP32DREGS;
|
| #endif
|
|
|
| - DCHECK(!IsSupported(VFP3) || IsSupported(ARMv7));
|
| + DCHECK_IMPLIES(IsSupported(ARMv7_SUDIV), IsSupported(ARMv7));
|
| + DCHECK_IMPLIES(IsSupported(ARMv8), IsSupported(ARMv7_SUDIV));
|
| + DCHECK_IMPLIES(IsSupported(MOVW_MOVT_IMMEDIATE_LOADS), IsSupported(ARMv7));
|
| }
|
|
|
|
|
| @@ -209,7 +326,7 @@ void CpuFeatures::PrintFeatures() {
|
| #else
|
| bool eabi_hardfloat = false;
|
| #endif
|
| - printf(" USE_EABI_HARDFLOAT=%d\n", eabi_hardfloat);
|
| + printf(" USE_EABI_HARDFLOAT=%d\n", eabi_hardfloat);
|
| }
|
|
|
|
|
|
|