OLD | NEW |
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions | 5 // modification, are permitted provided that the following conditions |
6 // are met: | 6 // are met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 28 matching lines...) Expand all Loading... |
39 #if V8_TARGET_ARCH_ARM | 39 #if V8_TARGET_ARCH_ARM |
40 | 40 |
41 #include "src/arm/assembler-arm-inl.h" | 41 #include "src/arm/assembler-arm-inl.h" |
42 #include "src/base/bits.h" | 42 #include "src/base/bits.h" |
43 #include "src/base/cpu.h" | 43 #include "src/base/cpu.h" |
44 #include "src/macro-assembler.h" | 44 #include "src/macro-assembler.h" |
45 | 45 |
46 namespace v8 { | 46 namespace v8 { |
47 namespace internal { | 47 namespace internal { |
48 | 48 |
49 // Get the CPU features enabled by the build. For cross compilation the | 49 static const unsigned kArmv6 = 0u; |
50 // preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS | 50 static const unsigned kArmv7 = kArmv6 | (1u << ARMv7); |
51 // can be defined to enable ARMv7 and VFPv3 instructions when building the | 51 static const unsigned kArmv7WithSudiv = kArmv7 | (1u << ARMv7_SUDIV); |
52 // snapshot. | 52 static const unsigned kArmv8 = kArmv7WithSudiv | (1u << ARMv8); |
53 static unsigned CpuFeaturesImpliedByCompiler() { | 53 |
54 unsigned answer = 0; | 54 static unsigned CpuFeaturesFromCommandLine() { |
55 #ifdef CAN_USE_ARMV8_INSTRUCTIONS | 55 unsigned result; |
56 if (FLAG_enable_armv8) { | 56 if (strcmp(FLAG_arm_arch, "armv8") == 0) { |
57 answer |= 1u << ARMv8; | 57 result = kArmv8; |
58 // ARMv8 always features VFP and NEON. | 58 } else if (strcmp(FLAG_arm_arch, "armv7+sudiv") == 0) { |
59 answer |= 1u << ARMv7 | 1u << VFP3 | 1u << NEON | 1u << VFP32DREGS; | 59 result = kArmv7WithSudiv; |
60 answer |= 1u << SUDIV; | 60 } else if (strcmp(FLAG_arm_arch, "armv7") == 0) { |
61 } | 61 result = kArmv7; |
62 #endif // CAN_USE_ARMV8_INSTRUCTIONS | 62 } else if (strcmp(FLAG_arm_arch, "armv6") == 0) { |
63 #ifdef CAN_USE_ARMV7_INSTRUCTIONS | 63 result = kArmv6; |
64 if (FLAG_enable_armv7) answer |= 1u << ARMv7; | 64 } else { |
65 #endif // CAN_USE_ARMV7_INSTRUCTIONS | 65 fprintf(stderr, "Error: unrecognised value for --arm-arch ('%s').\n", |
66 #ifdef CAN_USE_VFP3_INSTRUCTIONS | 66 FLAG_arm_arch); |
67 if (FLAG_enable_vfp3) answer |= 1u << VFP3 | 1u << ARMv7; | 67 fprintf(stderr, |
68 #endif // CAN_USE_VFP3_INSTRUCTIONS | 68 "Supported values are: armv8\n" |
69 #ifdef CAN_USE_VFP32DREGS | 69 " armv7+sudiv\n" |
70 if (FLAG_enable_32dregs) answer |= 1u << VFP32DREGS; | 70 " armv7\n" |
71 #endif // CAN_USE_VFP32DREGS | 71 " armv6\n"); |
72 #ifdef CAN_USE_NEON | 72 CHECK(false); |
73 if (FLAG_enable_neon) answer |= 1u << NEON; | 73 } |
74 #endif // CAN_USE_VFP32DREGS | 74 |
75 | 75 // If any of the old (deprecated) flags are specified, print a warning, but |
76 return answer; | 76 // otherwise try to respect them for now. |
| 77 // TODO(jbramley): When all the old bots have been updated, remove this. |
| 78 if (FLAG_enable_armv7.has_value || FLAG_enable_vfp3.has_value || |
| 79 FLAG_enable_32dregs.has_value || FLAG_enable_neon.has_value || |
| 80 FLAG_enable_sudiv.has_value || FLAG_enable_armv8.has_value) { |
| 81 // As an approximation of the old behaviour, set the default values from the |
| 82 // arm_arch setting, then apply the flags over the top. |
| 83 bool enable_armv7 = (result & (1u << ARMv7)) != 0; |
| 84 bool enable_vfp3 = (result & (1u << ARMv7)) != 0; |
| 85 bool enable_32dregs = (result & (1u << ARMv7)) != 0; |
| 86 bool enable_neon = (result & (1u << ARMv7)) != 0; |
| 87 bool enable_sudiv = (result & (1u << ARMv7_SUDIV)) != 0; |
| 88 bool enable_armv8 = (result & (1u << ARMv8)) != 0; |
| 89 if (FLAG_enable_armv7.has_value) { |
| 90 fprintf(stderr, |
| 91 "Warning: --enable_armv7 is deprecated. " |
| 92 "Use --arm_arch instead.\n"); |
| 93 enable_armv7 = FLAG_enable_armv7.value; |
| 94 } |
| 95 if (FLAG_enable_vfp3.has_value) { |
| 96 fprintf(stderr, |
| 97 "Warning: --enable_vfp3 is deprecated. " |
| 98 "Use --arm_arch instead.\n"); |
| 99 enable_vfp3 = FLAG_enable_vfp3.value; |
| 100 } |
| 101 if (FLAG_enable_32dregs.has_value) { |
| 102 fprintf(stderr, |
| 103 "Warning: --enable_32dregs is deprecated. " |
| 104 "Use --arm_arch instead.\n"); |
| 105 enable_32dregs = FLAG_enable_32dregs.value; |
| 106 } |
| 107 if (FLAG_enable_neon.has_value) { |
| 108 fprintf(stderr, |
| 109 "Warning: --enable_neon is deprecated. " |
| 110 "Use --arm_arch instead.\n"); |
| 111 enable_neon = FLAG_enable_neon.value; |
| 112 } |
| 113 if (FLAG_enable_sudiv.has_value) { |
| 114 fprintf(stderr, |
| 115 "Warning: --enable_sudiv is deprecated. " |
| 116 "Use --arm_arch instead.\n"); |
| 117 enable_sudiv = FLAG_enable_sudiv.value; |
| 118 } |
| 119 if (FLAG_enable_armv8.has_value) { |
| 120 fprintf(stderr, |
| 121 "Warning: --enable_armv8 is deprecated. " |
| 122 "Use --arm_arch instead.\n"); |
| 123 enable_armv8 = FLAG_enable_armv8.value; |
| 124 } |
| 125 // Emulate the old implications. |
| 126 if (enable_armv8) { |
| 127 enable_vfp3 = true; |
| 128 enable_neon = true; |
| 129 enable_32dregs = true; |
| 130 enable_sudiv = true; |
| 131 } |
| 132 // Select the best available configuration. |
| 133 if (enable_armv7 && enable_vfp3 && enable_32dregs && enable_neon) { |
| 134 if (enable_sudiv) { |
| 135 if (enable_armv8) { |
| 136 result = kArmv8; |
| 137 } else { |
| 138 result = kArmv7WithSudiv; |
| 139 } |
| 140 } else { |
| 141 result = kArmv7; |
| 142 } |
| 143 } else { |
| 144 result = kArmv6; |
| 145 } |
| 146 } |
| 147 return result; |
77 } | 148 } |
78 | 149 |
| 150 // Get the CPU features enabled by the build. |
| 151 // For cross compilation the preprocessor symbols such as |
| 152 // CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS can be used to |
| 153 // enable ARMv7 and VFPv3 instructions when building the snapshot. However, |
| 154 // these flags should be consistent with a supported ARM configuration: |
| 155 // "armv6": ARMv6 + VFPv2 |
| 156 // "armv7": ARMv7 + VFPv3-D32 + NEON |
| 157 // "armv7+sudiv": ARMv7 + VFPv4-D32 + NEON + SUDIV |
| 158 // "armv8": ARMv8 (+ all of the above) |
| 159 static constexpr unsigned CpuFeaturesFromCompiler() { |
| 160 // TODO(jbramley): Once the build flags are simplified, these tests should |
| 161 // also be simplified. |
| 162 |
| 163 // Check *architectural* implications. |
| 164 #if defined(CAN_USE_ARMV8_INSTRUCTIONS) && !defined(CAN_USE_ARMV7_INSTRUCTIONS) |
| 165 #error "CAN_USE_ARMV8_INSTRUCTIONS should imply CAN_USE_ARMV7_INSTRUCTIONS" |
| 166 #endif |
| 167 #if defined(CAN_USE_ARMV8_INSTRUCTIONS) && !defined(CAN_USE_SUDIV) |
| 168 #error "CAN_USE_ARMV8_INSTRUCTIONS should imply CAN_USE_SUDIV" |
| 169 #endif |
| 170 #if defined(CAN_USE_ARMV7_INSTRUCTIONS) != defined(CAN_USE_VFP3_INSTRUCTIONS) |
| 171 // V8 requires VFP, and all ARMv7 devices with VFP have VFPv3. Similarly, |
| 172 // VFPv3 isn't available before ARMv7. |
| 173 #error "CAN_USE_ARMV7_INSTRUCTIONS should match CAN_USE_VFP3_INSTRUCTIONS" |
| 174 #endif |
| 175 #if defined(CAN_USE_NEON) && !defined(CAN_USE_ARMV7_INSTRUCTIONS) |
| 176 #error "CAN_USE_NEON should imply CAN_USE_ARMV7_INSTRUCTIONS" |
| 177 #endif |
| 178 |
| 179 // Find compiler-implied features. |
| 180 #if defined(CAN_USE_ARMV8_INSTRUCTIONS) && \ |
| 181 defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_SUDIV) && \ |
| 182 defined(CAN_USE_NEON) && defined(CAN_USE_VFP3_INSTRUCTIONS) |
| 183 return kArmv8; |
| 184 #elif defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_SUDIV) && \ |
| 185 defined(CAN_USE_NEON) && defined(CAN_USE_VFP3_INSTRUCTIONS) |
| 186 return kArmv7WithSudiv; |
| 187 #elif defined(CAN_USE_ARMV7_INSTRUCTIONS) && defined(CAN_USE_NEON) && \ |
| 188 defined(CAN_USE_VFP3_INSTRUCTIONS) |
| 189 return kArmv7; |
| 190 #else |
| 191 return kArmv6; |
| 192 #endif |
| 193 } |
| 194 |
79 | 195 |
80 void CpuFeatures::ProbeImpl(bool cross_compile) { | 196 void CpuFeatures::ProbeImpl(bool cross_compile) { |
81 supported_ |= CpuFeaturesImpliedByCompiler(); | |
82 dcache_line_size_ = 64; | 197 dcache_line_size_ = 64; |
83 | 198 |
| 199 unsigned command_line = CpuFeaturesFromCommandLine(); |
84 // Only use statically determined features for cross compile (snapshot). | 200 // Only use statically determined features for cross compile (snapshot). |
85 if (cross_compile) return; | 201 if (cross_compile) { |
| 202 supported_ |= command_line & CpuFeaturesFromCompiler(); |
| 203 return; |
| 204 } |
86 | 205 |
87 #ifndef __arm__ | 206 #ifndef __arm__ |
88 // For the simulator build, use whatever the flags specify. | 207 // For the simulator build, use whatever the flags specify. |
89 if (FLAG_enable_armv8) { | 208 supported_ |= command_line; |
90 supported_ |= 1u << ARMv8; | 209 |
91 // ARMv8 always features VFP and NEON. | 210 if (FLAG_enable_movw_movt && ((supported_ & kArmv7) == kArmv7)) { |
92 supported_ |= 1u << ARMv7 | 1u << VFP3 | 1u << NEON | 1u << VFP32DREGS; | 211 supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; |
93 supported_ |= 1u << SUDIV; | |
94 if (FLAG_enable_movw_movt) supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; | |
95 } | |
96 if (FLAG_enable_armv7) { | |
97 supported_ |= 1u << ARMv7; | |
98 if (FLAG_enable_vfp3) supported_ |= 1u << VFP3; | |
99 if (FLAG_enable_neon) supported_ |= 1u << NEON | 1u << VFP32DREGS; | |
100 if (FLAG_enable_sudiv) supported_ |= 1u << SUDIV; | |
101 if (FLAG_enable_movw_movt) supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; | |
102 if (FLAG_enable_32dregs) supported_ |= 1u << VFP32DREGS; | |
103 } | 212 } |
104 | 213 |
105 #else // __arm__ | 214 #else // __arm__ |
106 // Probe for additional features at runtime. | 215 // Probe for additional features at runtime. |
107 base::CPU cpu; | 216 base::CPU cpu; |
108 if (FLAG_enable_vfp3 && cpu.has_vfp3()) { | 217 // Runtime detection is slightly fuzzy, and some inferences are necessary. |
109 // This implementation also sets the VFP flags if runtime | 218 unsigned runtime = kArmv6; |
110 // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI | 219 // NEON and VFPv3 imply at least ARMv7-A. |
111 // 0406B, page A1-6. | 220 if (cpu.has_neon() && cpu.has_vfp3_d32()) { |
112 supported_ |= 1u << VFP3 | 1u << ARMv7; | 221 DCHECK(cpu.has_vfp3()); |
113 } | 222 runtime |= kArmv7; |
114 | 223 if (cpu.has_idiva()) { |
115 if (FLAG_enable_neon && cpu.has_neon()) supported_ |= 1u << NEON; | 224 runtime |= kArmv7WithSudiv; |
116 if (FLAG_enable_sudiv && cpu.has_idiva()) supported_ |= 1u << SUDIV; | 225 if (cpu.architecture() >= 8) { |
117 | 226 runtime |= kArmv8; |
118 if (cpu.architecture() >= 7) { | 227 } |
119 if (FLAG_enable_armv7) supported_ |= 1u << ARMv7; | 228 } |
120 if (FLAG_enable_armv8 && cpu.architecture() >= 8) { | 229 } |
121 supported_ |= 1u << ARMv8; | 230 |
122 } | 231 // Use the best of the features found by CPU detection and those inferred from |
123 // Use movw/movt for QUALCOMM ARMv7 cores. | 232 // the build system. In both cases, restrict available features using the |
124 if (FLAG_enable_movw_movt && cpu.implementer() == base::CPU::QUALCOMM) { | 233 // command-line. Note that the command-line flags are very permissive (kArmv8) |
125 supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; | 234 // by default. |
126 } | 235 supported_ |= command_line & CpuFeaturesFromCompiler(); |
| 236 supported_ |= command_line & runtime; |
| 237 |
| 238 // Additional tuning options. |
| 239 |
| 240 // Prefer to use movw/movt for QUALCOMM ARMv7 cores. |
| 241 if (FLAG_enable_movw_movt && ((supported_ & kArmv7) == kArmv7) && |
| 242 (cpu.implementer() == base::CPU::QUALCOMM)) { |
| 243 supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; |
127 } | 244 } |
128 | 245 |
129 // ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines. | 246 // ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines. |
130 if (cpu.implementer() == base::CPU::ARM && | 247 if (cpu.implementer() == base::CPU::ARM && |
131 (cpu.part() == base::CPU::ARM_CORTEX_A5 || | 248 (cpu.part() == base::CPU::ARM_CORTEX_A5 || |
132 cpu.part() == base::CPU::ARM_CORTEX_A9)) { | 249 cpu.part() == base::CPU::ARM_CORTEX_A9)) { |
133 dcache_line_size_ = 32; | 250 dcache_line_size_ = 32; |
134 } | 251 } |
135 | |
136 if (FLAG_enable_32dregs && cpu.has_vfp3_d32()) supported_ |= 1u << VFP32DREGS; | |
137 #endif | 252 #endif |
138 | 253 |
139 DCHECK(!IsSupported(VFP3) || IsSupported(ARMv7)); | 254 DCHECK_IMPLIES(IsSupported(ARMv7_SUDIV), IsSupported(ARMv7)); |
| 255 DCHECK_IMPLIES(IsSupported(ARMv8), IsSupported(ARMv7_SUDIV)); |
| 256 DCHECK_IMPLIES(IsSupported(MOVW_MOVT_IMMEDIATE_LOADS), IsSupported(ARMv7)); |
140 } | 257 } |
141 | 258 |
142 | 259 |
143 void CpuFeatures::PrintTarget() { | 260 void CpuFeatures::PrintTarget() { |
144 const char* arm_arch = NULL; | 261 const char* arm_arch = NULL; |
145 const char* arm_target_type = ""; | 262 const char* arm_target_type = ""; |
146 const char* arm_no_probe = ""; | 263 const char* arm_no_probe = ""; |
147 const char* arm_fpu = ""; | 264 const char* arm_fpu = ""; |
148 const char* arm_thumb = ""; | 265 const char* arm_thumb = ""; |
149 const char* arm_float_abi = NULL; | 266 const char* arm_float_abi = NULL; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 CpuFeatures::IsSupported(VFP3), CpuFeatures::IsSupported(VFP32DREGS), | 319 CpuFeatures::IsSupported(VFP3), CpuFeatures::IsSupported(VFP32DREGS), |
203 CpuFeatures::IsSupported(NEON), CpuFeatures::IsSupported(SUDIV), | 320 CpuFeatures::IsSupported(NEON), CpuFeatures::IsSupported(SUDIV), |
204 CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS)); | 321 CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS)); |
205 #ifdef __arm__ | 322 #ifdef __arm__ |
206 bool eabi_hardfloat = base::OS::ArmUsingHardFloat(); | 323 bool eabi_hardfloat = base::OS::ArmUsingHardFloat(); |
207 #elif USE_EABI_HARDFLOAT | 324 #elif USE_EABI_HARDFLOAT |
208 bool eabi_hardfloat = true; | 325 bool eabi_hardfloat = true; |
209 #else | 326 #else |
210 bool eabi_hardfloat = false; | 327 bool eabi_hardfloat = false; |
211 #endif | 328 #endif |
212 printf(" USE_EABI_HARDFLOAT=%d\n", eabi_hardfloat); | 329 printf(" USE_EABI_HARDFLOAT=%d\n", eabi_hardfloat); |
213 } | 330 } |
214 | 331 |
215 | 332 |
216 // ----------------------------------------------------------------------------- | 333 // ----------------------------------------------------------------------------- |
217 // Implementation of RelocInfo | 334 // Implementation of RelocInfo |
218 | 335 |
219 // static | 336 // static |
220 const int RelocInfo::kApplyMask = 0; | 337 const int RelocInfo::kApplyMask = 0; |
221 | 338 |
222 | 339 |
(...skipping 4026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4249 DCHECK(is_uint12(offset)); | 4366 DCHECK(is_uint12(offset)); |
4250 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); | 4367 instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset)); |
4251 } | 4368 } |
4252 } | 4369 } |
4253 | 4370 |
4254 | 4371 |
4255 } // namespace internal | 4372 } // namespace internal |
4256 } // namespace v8 | 4373 } // namespace v8 |
4257 | 4374 |
4258 #endif // V8_TARGET_ARCH_ARM | 4375 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |