summaryrefslogtreecommitdiff
path: root/lib/Target/PowerPC/PPCSubtarget.cpp
blob: 2c1b7839a5fc2a520586627ece6b6d483913cbd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//===- PowerPCSubtarget.cpp - PPC Subtarget Information ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Begeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the PPC specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "PowerPCSubtarget.h"
#include "PowerPC.h"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/SubtargetFeature.h"

using namespace llvm;
PPCTargetEnum llvm::PPCTarget = TargetDefault;

namespace llvm {
  cl::opt<PPCTargetEnum, true>
  PPCTargetArg(cl::desc("Force generation of code for a specific PPC target:"),
               cl::values(
                          clEnumValN(TargetAIX,  "aix", "  Enable AIX codegen"),
                          clEnumValN(TargetDarwin,"darwin","  Enable Darwin codegen"),
                          clEnumValEnd),
               cl::location(PPCTarget), cl::init(TargetDefault));
  cl::opt<bool> EnableGPOPT("enable-gpopt", cl::Hidden,
                             cl::desc("Enable optimizations for GP cpus"));
}

enum PowerPCFeature {
  PowerPCFeature64Bit   = 1 << 0,
  PowerPCFeatureAltivec = 1 << 1,
  PowerPCFeatureFSqrt   = 1 << 2,
  PowerPCFeatureGPUL    = 1 << 3,
};

/// Sorted (by key) array of values for CPU subtype.
static const SubtargetFeatureKV PowerPCSubTypeKV[] = {
  { "601"    , 0 },
  { "602"    , 0 },
  { "603"    , 0 },
  { "603e"   , 0 },
  { "603ev"  , 0 },
  { "604"    , 0 },
  { "604e"   , 0 },
  { "620"    , 0 },
  { "7400"   , PowerPCFeatureAltivec },
  { "7450"   , PowerPCFeatureAltivec },
  { "750"    , 0 },
  { "970"    , PowerPCFeature64Bit | PowerPCFeatureAltivec |
               PowerPCFeatureFSqrt | PowerPCFeatureGPUL },
  { "g3"     , 0 },
  { "g4"     , PowerPCFeatureAltivec },
  { "g4+"    , PowerPCFeatureAltivec },
  { "g5"     , PowerPCFeature64Bit | PowerPCFeatureAltivec |
               PowerPCFeatureFSqrt | PowerPCFeatureGPUL },
  { "generic", 0 }
};
/// Length of PowerPCSubTypeKV.
static const unsigned PowerPCSubTypeKVSize = sizeof(PowerPCSubTypeKV)
                                             / sizeof(SubtargetFeatureKV);

/// Sorted (by key) array of values for CPU features.
static SubtargetFeatureKV PowerPCFeatureKV[] = {
  { "64bit"  , PowerPCFeature64Bit   },
  { "altivec", PowerPCFeatureAltivec },
  { "fsqrt"  , PowerPCFeatureFSqrt },
  { "gpul"   , PowerPCFeatureGPUL    }
 };
/// Length of PowerPCFeatureKV.
static const unsigned PowerPCFeatureKVSize = sizeof(PowerPCFeatureKV)
                                          / sizeof(SubtargetFeatureKV);


#if defined(__APPLE__)
#include <mach/mach.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
#include <mach/machine.h>

/// GetCurrentPowerPCFeatures - Returns the current CPUs features.
static const char *GetCurrentPowerPCCPU() {
  host_basic_info_data_t hostInfo;
  mach_msg_type_number_t infoCount;

  infoCount = HOST_BASIC_INFO_COUNT;
  host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, 
            &infoCount);
            
  if (hostInfo.cpu_type != CPU_TYPE_POWERPC) return "generic";

  switch(hostInfo.cpu_subtype) {
  case CPU_SUBTYPE_POWERPC_601:   return "601";
  case CPU_SUBTYPE_POWERPC_602:   return "602";
  case CPU_SUBTYPE_POWERPC_603:   return "603";
  case CPU_SUBTYPE_POWERPC_603e:  return "603e";
  case CPU_SUBTYPE_POWERPC_603ev: return "603ev";
  case CPU_SUBTYPE_POWERPC_604:   return "604";
  case CPU_SUBTYPE_POWERPC_604e:  return "604e";
  case CPU_SUBTYPE_POWERPC_620:   return "620";
  case CPU_SUBTYPE_POWERPC_750:   return "750";
  case CPU_SUBTYPE_POWERPC_7400:  return "7400";
  case CPU_SUBTYPE_POWERPC_7450:  return "7450";
  case CPU_SUBTYPE_POWERPC_970:   return "970";
  default: ;
  }
  
  return "generic";
}
#endif

PPCSubtarget::PPCSubtarget(const Module &M, const std::string &FS)
  : StackAlignment(16), IsGigaProcessor(false), IsAIX(false), IsDarwin(false) {

  // Determine default and user specified characteristics
  std::string CPU;
#if defined(__APPLE__)
  CPU = GetCurrentPowerPCCPU();
#endif
  uint32_t Bits =
  SubtargetFeatures::Parse(FS, CPU,
                           PowerPCSubTypeKV, PowerPCSubTypeKVSize,
                           PowerPCFeatureKV, PowerPCFeatureKVSize);
  IsGigaProcessor = (Bits & PowerPCFeatureGPUL) != 0;

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  const std::string& TT = M.getTargetTriple();
  if (TT.length() > 5) {
    IsDarwin = TT.find("darwin") != std::string::npos;
  } else if (TT.empty()) {
#if defined(_POWER)
    IsAIX = true;
#elif defined(__APPLE__)
    IsDarwin = true;
#endif
  }
  
  // If GP opts are forced on by the commandline, do so now.
  if (EnableGPOPT) IsGigaProcessor = true;
}