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_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
     49               Register::kNumRegisters);
     50 STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
     51               DoubleRegister::kMaxNumRegisters);
     52 
     53 enum CompilerSelector { CRANKSHAFT, TURBOFAN };
     54 
     55 class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
     56  public:
     57   explicit ArchDefaultRegisterConfiguration(CompilerSelector compiler)
     58       : RegisterConfiguration(
     59             Register::kNumRegisters, DoubleRegister::kMaxNumRegisters,
     60 #if V8_TARGET_ARCH_IA32
     61             kMaxAllocatableGeneralRegisterCount,
     62             kMaxAllocatableDoubleRegisterCount,
     63 #elif V8_TARGET_ARCH_X87
     64             kMaxAllocatableGeneralRegisterCount,
     65             compiler == TURBOFAN ? 1 : kMaxAllocatableDoubleRegisterCount,
     66 #elif V8_TARGET_ARCH_X64
     67             kMaxAllocatableGeneralRegisterCount,
     68             kMaxAllocatableDoubleRegisterCount,
     69 #elif V8_TARGET_ARCH_ARM
     70             FLAG_enable_embedded_constant_pool
     71                 ? (kMaxAllocatableGeneralRegisterCount - 1)
     72                 : kMaxAllocatableGeneralRegisterCount,
     73             CpuFeatures::IsSupported(VFP32DREGS)
     74                 ? kMaxAllocatableDoubleRegisterCount
     75                 : (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT) 0),
     76 #elif V8_TARGET_ARCH_ARM64
     77             kMaxAllocatableGeneralRegisterCount,
     78             kMaxAllocatableDoubleRegisterCount,
     79 #elif V8_TARGET_ARCH_MIPS
     80             kMaxAllocatableGeneralRegisterCount,
     81             kMaxAllocatableDoubleRegisterCount,
     82 #elif V8_TARGET_ARCH_MIPS64
     83             kMaxAllocatableGeneralRegisterCount,
     84             kMaxAllocatableDoubleRegisterCount,
     85 #elif V8_TARGET_ARCH_PPC
     86             kMaxAllocatableGeneralRegisterCount,
     87             kMaxAllocatableDoubleRegisterCount,
     88 #elif V8_TARGET_ARCH_S390
     89             kMaxAllocatableGeneralRegisterCount,
     90             kMaxAllocatableDoubleRegisterCount,
     91 #else
     92 #error Unsupported target architecture.
     93 #endif
     94             kAllocatableGeneralCodes, kAllocatableDoubleCodes,
     95             kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE,
     96             kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames) {
     97   }
     98 };
     99 
    100 template <CompilerSelector compiler>
    101 struct RegisterConfigurationInitializer {
    102   static void Construct(ArchDefaultRegisterConfiguration* config) {
    103     new (config) ArchDefaultRegisterConfiguration(compiler);
    104   }
    105 };
    106 
    107 static base::LazyInstance<ArchDefaultRegisterConfiguration,
    108                           RegisterConfigurationInitializer<CRANKSHAFT>>::type
    109     kDefaultRegisterConfigurationForCrankshaft = LAZY_INSTANCE_INITIALIZER;
    110 
    111 static base::LazyInstance<ArchDefaultRegisterConfiguration,
    112                           RegisterConfigurationInitializer<TURBOFAN>>::type
    113     kDefaultRegisterConfigurationForTurboFan = LAZY_INSTANCE_INITIALIZER;
    114 
    115 }  // namespace
    116 
    117 const RegisterConfiguration* RegisterConfiguration::Crankshaft() {
    118   return &kDefaultRegisterConfigurationForCrankshaft.Get();
    119 }
    120 
    121 const RegisterConfiguration* RegisterConfiguration::Turbofan() {
    122   return &kDefaultRegisterConfigurationForTurboFan.Get();
    123 }
    124 
    125 RegisterConfiguration::RegisterConfiguration(
    126     int num_general_registers, int num_double_registers,
    127     int num_allocatable_general_registers, int num_allocatable_double_registers,
    128     const int* allocatable_general_codes, const int* allocatable_double_codes,
    129     AliasingKind fp_aliasing_kind, const char* const* general_register_names,
    130     const char* const* float_register_names,
    131     const char* const* double_register_names)
    132     : num_general_registers_(num_general_registers),
    133       num_float_registers_(0),
    134       num_double_registers_(num_double_registers),
    135       num_allocatable_general_registers_(num_allocatable_general_registers),
    136       num_allocatable_double_registers_(num_allocatable_double_registers),
    137       num_allocatable_float_registers_(0),
    138       allocatable_general_codes_mask_(0),
    139       allocatable_double_codes_mask_(0),
    140       allocatable_float_codes_mask_(0),
    141       allocatable_general_codes_(allocatable_general_codes),
    142       allocatable_double_codes_(allocatable_double_codes),
    143       fp_aliasing_kind_(fp_aliasing_kind),
    144       general_register_names_(general_register_names),
    145       float_register_names_(float_register_names),
    146       double_register_names_(double_register_names) {
    147   DCHECK(num_general_registers_ <= RegisterConfiguration::kMaxGeneralRegisters);
    148   DCHECK(num_double_registers_ <= RegisterConfiguration::kMaxFPRegisters);
    149   for (int i = 0; i < num_allocatable_general_registers_; ++i) {
    150     allocatable_general_codes_mask_ |= (1 << allocatable_general_codes_[i]);
    151   }
    152   for (int i = 0; i < num_allocatable_double_registers_; ++i) {
    153     allocatable_double_codes_mask_ |= (1 << allocatable_double_codes_[i]);
    154   }
    155 
    156   if (fp_aliasing_kind_ == COMBINE) {
    157     num_float_registers_ = num_double_registers_ * 2 <= kMaxFPRegisters
    158                                ? num_double_registers_ * 2
    159                                : kMaxFPRegisters;
    160     num_allocatable_float_registers_ = 0;
    161     for (int i = 0; i < num_allocatable_double_registers_; i++) {
    162       int base_code = allocatable_double_codes_[i] * 2;
    163       if (base_code >= kMaxFPRegisters) continue;
    164       allocatable_float_codes_[num_allocatable_float_registers_++] = base_code;
    165       allocatable_float_codes_[num_allocatable_float_registers_++] =
    166           base_code + 1;
    167       allocatable_float_codes_mask_ |= (0x3 << base_code);
    168     }
    169   } else {
    170     DCHECK(fp_aliasing_kind_ == OVERLAP);
    171     num_float_registers_ = num_double_registers_;
    172     num_allocatable_float_registers_ = num_allocatable_double_registers_;
    173     for (int i = 0; i < num_allocatable_float_registers_; ++i) {
    174       allocatable_float_codes_[i] = allocatable_double_codes_[i];
    175     }
    176     allocatable_float_codes_mask_ = allocatable_double_codes_mask_;
    177   }
    178 }
    179 
    180 int RegisterConfiguration::GetAliases(MachineRepresentation rep, int index,
    181                                       MachineRepresentation other_rep,
    182                                       int* alias_base_index) const {
    183   DCHECK(fp_aliasing_kind_ == COMBINE);
    184   DCHECK(rep == MachineRepresentation::kFloat32 ||
    185          rep == MachineRepresentation::kFloat64);
    186   DCHECK(other_rep == MachineRepresentation::kFloat32 ||
    187          other_rep == MachineRepresentation::kFloat64);
    188   if (rep == other_rep) {
    189     *alias_base_index = index;
    190     return 1;
    191   }
    192   if (rep == MachineRepresentation::kFloat32) {
    193     DCHECK(other_rep == MachineRepresentation::kFloat64);
    194     DCHECK(index < num_allocatable_float_registers_);
    195     *alias_base_index = index / 2;
    196     return 1;
    197   }
    198   DCHECK(rep == MachineRepresentation::kFloat64);
    199   DCHECK(other_rep == MachineRepresentation::kFloat32);
    200   if (index * 2 >= kMaxFPRegisters) {
    201     // Alias indices are out of float register range.
    202     return 0;
    203   }
    204   *alias_base_index = index * 2;
    205   return 2;
    206 }
    207 
    208 bool RegisterConfiguration::AreAliases(MachineRepresentation rep, int index,
    209                                        MachineRepresentation other_rep,
    210                                        int other_index) const {
    211   DCHECK(fp_aliasing_kind_ == COMBINE);
    212   DCHECK(rep == MachineRepresentation::kFloat32 ||
    213          rep == MachineRepresentation::kFloat64);
    214   DCHECK(other_rep == MachineRepresentation::kFloat32 ||
    215          other_rep == MachineRepresentation::kFloat64);
    216   if (rep == other_rep) {
    217     return index == other_index;
    218   }
    219   if (rep == MachineRepresentation::kFloat32) {
    220     DCHECK(other_rep == MachineRepresentation::kFloat64);
    221     return index / 2 == other_index;
    222   }
    223   DCHECK(rep == MachineRepresentation::kFloat64);
    224   DCHECK(other_rep == MachineRepresentation::kFloat32);
    225   if (index * 2 >= kMaxFPRegisters) {
    226     // Alias indices are out of float register range.
    227     return false;
    228   }
    229   return index == other_index / 2;
    230 }
    231 
    232 #undef REGISTER_COUNT
    233 
    234 }  // namespace internal
    235 }  // namespace v8
    236