Home | History | Annotate | Download | only in src
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/register-configuration.h"
      6 #include "src/globals.h"
      7 #include "src/macro-assembler.h"
      8 
      9 namespace v8 {
     10 namespace internal {
     11 
     12 namespace {
     13 
     14 #define REGISTER_COUNT(R) 1 +
     15 static const int kMaxAllocatableGeneralRegisterCount =
     16     ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT)0;
     17 static const int kMaxAllocatableDoubleRegisterCount =
     18     ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_COUNT)0;
     19 
     20 static const int kAllocatableGeneralCodes[] = {
     21 #define REGISTER_CODE(R) Register::kCode_##R,
     22     ALLOCATABLE_GENERAL_REGISTERS(REGISTER_CODE)};
     23 #undef REGISTER_CODE
     24 
     25 static const int kAllocatableDoubleCodes[] = {
     26 #define REGISTER_CODE(R) DoubleRegister::kCode_##R,
     27     ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_CODE)};
     28 #undef REGISTER_CODE
     29 
     30 static const char* const kGeneralRegisterNames[] = {
     31 #define REGISTER_NAME(R) #R,
     32     GENERAL_REGISTERS(REGISTER_NAME)
     33 #undef REGISTER_NAME
     34 };
     35 
     36 static const char* const kFloatRegisterNames[] = {
     37 #define REGISTER_NAME(R) #R,
     38     FLOAT_REGISTERS(REGISTER_NAME)
     39 #undef REGISTER_NAME
     40 };
     41 
     42 static const char* const kDoubleRegisterNames[] = {
     43 #define REGISTER_NAME(R) #R,
     44     DOUBLE_REGISTERS(REGISTER_NAME)
     45 #undef REGISTER_NAME
     46 };
     47 
     48 static const char* const kSimd128RegisterNames[] = {
     49 #define REGISTER_NAME(R) #R,
     50     SIMD128_REGISTERS(REGISTER_NAME)
     51 #undef REGISTER_NAME
     52 };
     53 
     54 STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
     55               Register::kNumRegisters);
     56 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
     57               FloatRegister::kMaxNumRegisters);
     58 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
     59               DoubleRegister::kMaxNumRegisters);
     60 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
     61               Simd128Register::kMaxNumRegisters);
     62 
     63 enum CompilerSelector { CRANKSHAFT, TURBOFAN };
     64 
     65 class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
     66  public:
     67   explicit ArchDefaultRegisterConfiguration(CompilerSelector compiler)
     68       : RegisterConfiguration(
     69             Register::kNumRegisters, DoubleRegister::kMaxNumRegisters,
     70 #if V8_TARGET_ARCH_IA32
     71             kMaxAllocatableGeneralRegisterCount,
     72             kMaxAllocatableDoubleRegisterCount,
     73 #elif V8_TARGET_ARCH_X87
     74             kMaxAllocatableGeneralRegisterCount,
     75             compiler == TURBOFAN ? 1 : kMaxAllocatableDoubleRegisterCount,
     76 #elif V8_TARGET_ARCH_X64
     77             kMaxAllocatableGeneralRegisterCount,
     78             kMaxAllocatableDoubleRegisterCount,
     79 #elif V8_TARGET_ARCH_ARM
     80             FLAG_enable_embedded_constant_pool
     81                 ? (kMaxAllocatableGeneralRegisterCount - 1)
     82                 : kMaxAllocatableGeneralRegisterCount,
     83             CpuFeatures::IsSupported(VFP32DREGS)
     84                 ? kMaxAllocatableDoubleRegisterCount
     85                 : (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT) 0),
     86 #elif V8_TARGET_ARCH_ARM64
     87             kMaxAllocatableGeneralRegisterCount,
     88             kMaxAllocatableDoubleRegisterCount,
     89 #elif V8_TARGET_ARCH_MIPS
     90             kMaxAllocatableGeneralRegisterCount,
     91             kMaxAllocatableDoubleRegisterCount,
     92 #elif V8_TARGET_ARCH_MIPS64
     93             kMaxAllocatableGeneralRegisterCount,
     94             kMaxAllocatableDoubleRegisterCount,
     95 #elif V8_TARGET_ARCH_PPC
     96             kMaxAllocatableGeneralRegisterCount,
     97             kMaxAllocatableDoubleRegisterCount,
     98 #elif V8_TARGET_ARCH_S390
     99             kMaxAllocatableGeneralRegisterCount,
    100             kMaxAllocatableDoubleRegisterCount,
    101 #else
    102 #error Unsupported target architecture.
    103 #endif
    104             kAllocatableGeneralCodes, kAllocatableDoubleCodes,
    105             kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE,
    106             kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames,
    107             kSimd128RegisterNames) {
    108   }
    109 };
    110 
    111 template <CompilerSelector compiler>
    112 struct RegisterConfigurationInitializer {
    113   static void Construct(ArchDefaultRegisterConfiguration* config) {
    114     new (config) ArchDefaultRegisterConfiguration(compiler);
    115   }
    116 };
    117 
    118 static base::LazyInstance<ArchDefaultRegisterConfiguration,
    119                           RegisterConfigurationInitializer<CRANKSHAFT>>::type
    120     kDefaultRegisterConfigurationForCrankshaft = LAZY_INSTANCE_INITIALIZER;
    121 
    122 static base::LazyInstance<ArchDefaultRegisterConfiguration,
    123                           RegisterConfigurationInitializer<TURBOFAN>>::type
    124     kDefaultRegisterConfigurationForTurboFan = LAZY_INSTANCE_INITIALIZER;
    125 
    126 }  // namespace
    127 
    128 const RegisterConfiguration* RegisterConfiguration::Crankshaft() {
    129   return &kDefaultRegisterConfigurationForCrankshaft.Get();
    130 }
    131 
    132 const RegisterConfiguration* RegisterConfiguration::Turbofan() {
    133   return &kDefaultRegisterConfigurationForTurboFan.Get();
    134 }
    135 
    136 RegisterConfiguration::RegisterConfiguration(
    137     int num_general_registers, int num_double_registers,
    138     int num_allocatable_general_registers, int num_allocatable_double_registers,
    139     const int* allocatable_general_codes, const int* allocatable_double_codes,
    140     AliasingKind fp_aliasing_kind, const char* const* general_register_names,
    141     const char* const* float_register_names,
    142     const char* const* double_register_names,
    143     const char* const* simd128_register_names)
    144     : num_general_registers_(num_general_registers),
    145       num_float_registers_(0),
    146       num_double_registers_(num_double_registers),
    147       num_simd128_registers_(0),
    148       num_allocatable_general_registers_(num_allocatable_general_registers),
    149       num_allocatable_float_registers_(0),
    150       num_allocatable_double_registers_(num_allocatable_double_registers),
    151       num_allocatable_simd128_registers_(0),
    152       allocatable_general_codes_mask_(0),
    153       allocatable_float_codes_mask_(0),
    154       allocatable_double_codes_mask_(0),
    155       allocatable_simd128_codes_mask_(0),
    156       allocatable_general_codes_(allocatable_general_codes),
    157       allocatable_double_codes_(allocatable_double_codes),
    158       fp_aliasing_kind_(fp_aliasing_kind),
    159       general_register_names_(general_register_names),
    160       float_register_names_(float_register_names),
    161       double_register_names_(double_register_names),
    162       simd128_register_names_(simd128_register_names) {
    163   DCHECK(num_general_registers_ <= RegisterConfiguration::kMaxGeneralRegisters);
    164   DCHECK(num_double_registers_ <= RegisterConfiguration::kMaxFPRegisters);
    165   for (int i = 0; i < num_allocatable_general_registers_; ++i) {
    166     allocatable_general_codes_mask_ |= (1 << allocatable_general_codes_[i]);
    167   }
    168   for (int i = 0; i < num_allocatable_double_registers_; ++i) {
    169     allocatable_double_codes_mask_ |= (1 << allocatable_double_codes_[i]);
    170   }
    171 
    172   if (fp_aliasing_kind_ == COMBINE) {
    173     num_float_registers_ = num_double_registers_ * 2 <= kMaxFPRegisters
    174                                ? num_double_registers_ * 2
    175                                : kMaxFPRegisters;
    176     num_allocatable_float_registers_ = 0;
    177     for (int i = 0; i < num_allocatable_double_registers_; i++) {
    178       int base_code = allocatable_double_codes_[i] * 2;
    179       if (base_code >= kMaxFPRegisters) continue;
    180       allocatable_float_codes_[num_allocatable_float_registers_++] = base_code;
    181       allocatable_float_codes_[num_allocatable_float_registers_++] =
    182           base_code + 1;
    183       allocatable_float_codes_mask_ |= (0x3 << base_code);
    184     }
    185     num_simd128_registers_ = num_double_registers_ / 2;
    186     num_allocatable_simd128_registers_ = 0;
    187     int last_simd128_code = allocatable_double_codes_[0] / 2;
    188     for (int i = 1; i < num_allocatable_double_registers_; i++) {
    189       int next_simd128_code = allocatable_double_codes_[i] / 2;
    190       // This scheme assumes allocatable_double_codes_ are strictly increasing.
    191       DCHECK_GE(next_simd128_code, last_simd128_code);
    192       if (last_simd128_code == next_simd128_code) {
    193         allocatable_simd128_codes_[num_allocatable_simd128_registers_++] =
    194             next_simd128_code;
    195         allocatable_simd128_codes_mask_ |= (0x1 << next_simd128_code);
    196       }
    197       last_simd128_code = next_simd128_code;
    198     }
    199   } else {
    200     DCHECK(fp_aliasing_kind_ == OVERLAP);
    201     num_float_registers_ = num_simd128_registers_ = num_double_registers_;
    202     num_allocatable_float_registers_ = num_allocatable_simd128_registers_ =
    203         num_allocatable_double_registers_;
    204     for (int i = 0; i < num_allocatable_float_registers_; ++i) {
    205       allocatable_float_codes_[i] = allocatable_simd128_codes_[i] =
    206           allocatable_double_codes_[i];
    207     }
    208     allocatable_float_codes_mask_ = allocatable_simd128_codes_mask_ =
    209         allocatable_double_codes_mask_;
    210   }
    211 }
    212 
    213 // Assert that kFloat32, kFloat64, and kSimd128 are consecutive values.
    214 STATIC_ASSERT(static_cast<int>(MachineRepresentation::kSimd128) ==
    215               static_cast<int>(MachineRepresentation::kFloat64) + 1);
    216 STATIC_ASSERT(static_cast<int>(MachineRepresentation::kFloat64) ==
    217               static_cast<int>(MachineRepresentation::kFloat32) + 1);
    218 
    219 int RegisterConfiguration::GetAliases(MachineRepresentation rep, int index,
    220                                       MachineRepresentation other_rep,
    221                                       int* alias_base_index) const {
    222   DCHECK(fp_aliasing_kind_ == COMBINE);
    223   DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep));
    224   if (rep == other_rep) {
    225     *alias_base_index = index;
    226     return 1;
    227   }
    228   int rep_int = static_cast<int>(rep);
    229   int other_rep_int = static_cast<int>(other_rep);
    230   if (rep_int > other_rep_int) {
    231     int shift = rep_int - other_rep_int;
    232     int base_index = index << shift;
    233     if (base_index >= kMaxFPRegisters) {
    234       // Alias indices would be out of FP register range.
    235       return 0;
    236     }
    237     *alias_base_index = base_index;
    238     return 1 << shift;
    239   }
    240   int shift = other_rep_int - rep_int;
    241   *alias_base_index = index >> shift;
    242   return 1;
    243 }
    244 
    245 bool RegisterConfiguration::AreAliases(MachineRepresentation rep, int index,
    246                                        MachineRepresentation other_rep,
    247                                        int other_index) const {
    248   DCHECK(fp_aliasing_kind_ == COMBINE);
    249   DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep));
    250   if (rep == other_rep) {
    251     return index == other_index;
    252   }
    253   int rep_int = static_cast<int>(rep);
    254   int other_rep_int = static_cast<int>(other_rep);
    255   if (rep_int > other_rep_int) {
    256     int shift = rep_int - other_rep_int;
    257     return index == other_index >> shift;
    258   }
    259   int shift = other_rep_int - rep_int;
    260   return index >> shift == other_index;
    261 }
    262 
    263 #undef REGISTER_COUNT
    264 
    265 }  // namespace internal
    266 }  // namespace v8
    267