text: // Copyright 2014 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "base/cpu.h"
  #include "base/logging.h"
  #include "base/strings/string_util.h"
  #include "build/build_config.h"
  #if defined(OS_WIN)
  #include "base/win/windows_version.h"
  #endif
  
  namespace nacl {
  
  const char* GetSandboxArch() {
  #if defined(ARCH_CPU_ARM_FAMILY)
    return "arm";
  #elif defined(ARCH_CPU_MIPS_FAMILY)
    return "mips32";
  #elif defined(ARCH_CPU_X86_FAMILY)
  
  #if defined(OS_WIN)
    // We have to check the host architecture on Windows.
    // See sandbox_isa.h for an explanation why.
    if (base::win::OSInfo::GetInstance()->architecture() ==
        base::win::OSInfo::X64_ARCHITECTURE)
      return "x86-64";
    else
      return "x86-32";
  #elif ARCH_CPU_64_BITS
    return "x86-64";
  #else
    return "x86-32";
  #endif  // defined(OS_WIN)
  
  #else
  #error Architecture not supported.
  #endif
  }
  
  std::string GetCpuFeatures() {
    // PNaCl's translator from pexe to nexe can be told exactly what
    // capabilities the user's machine has because the pexe to nexe
    // translation is specific to the machine, and CPU information goes
    // into the translation cache. This allows the translator to generate
    // faster code.
    //
    // Care must be taken to avoid instructions which aren't supported by
    // the NaCl sandbox. Ideally the translator would do this, but there's
    // no point in not doing the whitelist here.
    //
    // TODO(jfb) Some features are missing, either because the NaCl
    //           sandbox doesn't support them, because base::CPU doesn't
    //           detect them, or because they don't help vector shuffles
    //           (and we omit them because it simplifies testing). Add the
    //           other features.
    //
    // TODO(jfb) The following is x86-specific. The base::CPU class
    //           doesn't handle other architectures very well, and we
    //           should at least detect the presence of ARM's integer
    //           divide.
    std::vector<std::string> features;
    base::CPU cpu;
  
    // On x86, SSE features are ordered: the most recent one implies the
    // others. Care is taken here to only specify the latest SSE version,
    // whereas non-SSE features don't follow this model: POPCNT is
    // effectively always implied by SSE4.2 but has to be specified
    // separately.
    //
    // TODO: AVX2, AVX, SSE 4.2.
    if (cpu.has_sse41()) features.push_back("+sse4.1");
    // TODO: SSE 4A, SSE 4.
    else if (cpu.has_ssse3()) features.push_back("+ssse3");
    // TODO: SSE 3
    else if (cpu.has_sse2()) features.push_back("+sse2");
  
    if (cpu.has_popcnt()) features.push_back("+popcnt");
  
    // TODO: AES, LZCNT, ...
    return base::JoinString(features, ",");
  }
  
  }  // namespace nacl
  