1/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "bcc/Support/Properties.h"
18#include "bcc/Support/TargetCompilerConfigs.h"
19
20#include "llvm/ADT/StringMap.h"
21#include "llvm/Support/Host.h"
22
23// Get ARM version number (i.e., __ARM_ARCH__)
24#ifdef __arm__
25#include <machine/cpu-features.h>
26#endif
27
28using namespace bcc;
29
30//===----------------------------------------------------------------------===//
31// ARM
32//===----------------------------------------------------------------------===//
33#if defined(PROVIDE_ARM_CODEGEN)
34
35bool ARMBaseCompilerConfig::HasThumb2() {
36#if !defined(TARGET_BUILD)
37  // Cross-compiler can always generate Thumb-2 instructions.
38  return true;
39#else // defined(TARGET_BUILD)
40#  if (__ARM_ARCH__ >= 7) || defined(__ARM_ARCH_6T2__)
41  return true;
42#  else
43  // ARM prior to V6T2 doesn't support Thumb-2.
44  return false;
45#  endif
46#endif
47}
48
49void
50ARMBaseCompilerConfig::GetFeatureVector(std::vector<std::string> &pAttributes,
51                                        bool pInThumbMode, bool pEnableNEON) {
52  llvm::StringMap<bool> Features;
53  llvm::sys::getHostCPUFeatures(Features);
54
55#if defined(ARCH_ARM_HAVE_VFP)
56  pAttributes.push_back("+vfp3");
57#  if !defined(ARCH_ARM_HAVE_VFP_D32)
58  pAttributes.push_back("+d16");
59#  endif
60#endif
61
62  if (pInThumbMode) {
63    if (HasThumb2()) {
64      pAttributes.push_back("+thumb2");
65    } else {
66      pAttributes.push_back("-thumb2");
67    }
68  }
69
70  if (pEnableNEON && Features.count("neon") && Features["neon"]) {
71    pAttributes.push_back("+neon");
72  } else {
73    pAttributes.push_back("-neon");
74    pAttributes.push_back("-neonfp");
75  }
76
77  if (!getProperty("debug.rs.arm-no-hwdiv")) {
78    if (Features.count("hwdiv-arm") && Features["hwdiv-arm"])
79      pAttributes.push_back("+hwdiv-arm");
80
81    if (Features.count("hwdiv") && Features["hwdiv"])
82      pAttributes.push_back("+hwdiv");
83  }
84
85  return;
86}
87
88ARMBaseCompilerConfig::ARMBaseCompilerConfig(const std::string &pTriple,
89                                             bool pInThumbMode)
90  : CompilerConfig(pTriple), mInThumbMode(pInThumbMode) {
91
92  // Enable NEON by default.
93  mEnableNEON = true;
94
95  if (!getProperty("debug.rs.arm-no-tune-for-cpu"))
96    setCPU(llvm::sys::getHostCPUName());
97
98  std::vector<std::string> attributes;
99  GetFeatureVector(attributes, mInThumbMode, mEnableNEON);
100  setFeatureString(attributes);
101
102  return;
103}
104
105bool ARMBaseCompilerConfig::enableNEON(bool pEnable) {
106#if defined(ARCH_ARM_HAVE_NEON)
107  if (mEnableNEON != pEnable) {
108    std::vector<std::string> attributes;
109    GetFeatureVector(attributes, mInThumbMode, pEnable);
110    setFeatureString(attributes);
111    mEnableNEON = pEnable;
112    return true;
113  }
114  // Fall-through
115#endif
116  return false;
117}
118#endif // defined(PROVIDE_ARM_CODEGEN)
119