Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/rs6000/driver-rs6000.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* Subroutines for the gcc driver. | |
2 Copyright (C) 2007, 2008 Free Software Foundation, Inc. | |
3 | |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify | |
7 it under the terms of the GNU General Public License as published by | |
8 the Free Software Foundation; either version 3, or (at your option) | |
9 any later version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 #include "config.h" | |
21 #include "system.h" | |
22 #include "coretypes.h" | |
23 #include "tm.h" | |
24 #include <stdlib.h> | |
25 | |
26 #ifdef _AIX | |
27 # include <sys/systemcfg.h> | |
28 #endif | |
29 | |
30 #ifdef __linux__ | |
31 # include <link.h> | |
32 #endif | |
33 | |
34 #if defined (__APPLE__) || (__FreeBSD__) | |
35 # include <sys/types.h> | |
36 # include <sys/sysctl.h> | |
37 #endif | |
38 | |
39 const char *host_detect_local_cpu (int argc, const char **argv); | |
40 | |
41 #if GCC_VERSION >= 0 | |
42 | |
43 /* Returns parameters that describe L1_ASSOC associative cache of size | |
44 L1_SIZEKB with lines of size L1_LINE, and L2_SIZEKB. */ | |
45 | |
46 static char * | |
47 describe_cache (unsigned l1_sizekb, unsigned l1_line, | |
48 unsigned l1_assoc ATTRIBUTE_UNUSED, unsigned l2_sizekb) | |
49 { | |
50 char l1size[1000], line[1000], l2size[1000]; | |
51 | |
52 /* At the moment, gcc middle-end does not use the information about the | |
53 associativity of the cache. */ | |
54 | |
55 sprintf (l1size, "--param l1-cache-size=%u", l1_sizekb); | |
56 sprintf (line, "--param l1-cache-line-size=%u", l1_line); | |
57 sprintf (l2size, "--param l2-cache-size=%u", l2_sizekb); | |
58 | |
59 return concat (l1size, " ", line, " ", l2size, " ", NULL); | |
60 } | |
61 | |
62 #ifdef __APPLE__ | |
63 | |
64 /* Returns the description of caches on Darwin. */ | |
65 | |
66 static char * | |
67 detect_caches_darwin (void) | |
68 { | |
69 unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb; | |
70 size_t len = 4; | |
71 static int l1_size_name[2] = { CTL_HW, HW_L1DCACHESIZE }; | |
72 static int l1_line_name[2] = { CTL_HW, HW_CACHELINE }; | |
73 static int l2_size_name[2] = { CTL_HW, HW_L2CACHESIZE }; | |
74 | |
75 sysctl (l1_size_name, 2, &l1_sizekb, &len, NULL, 0); | |
76 sysctl (l1_line_name, 2, &l1_line, &len, NULL, 0); | |
77 sysctl (l2_size_name, 2, &l2_sizekb, &len, NULL, 0); | |
78 l1_assoc = 0; | |
79 | |
80 return describe_cache (l1_sizekb / 1024, l1_line, l1_assoc, | |
81 l2_sizekb / 1024); | |
82 } | |
83 | |
84 static const char * | |
85 detect_processor_darwin (void) | |
86 { | |
87 unsigned int proc; | |
88 size_t len = 4; | |
89 | |
90 sysctlbyname ("hw.cpusubtype", &proc, &len, NULL, 0); | |
91 | |
92 if (len > 0) | |
93 switch (proc) | |
94 { | |
95 case 1: | |
96 return "601"; | |
97 case 2: | |
98 return "602"; | |
99 case 3: | |
100 return "603"; | |
101 case 4: | |
102 case 5: | |
103 return "603e"; | |
104 case 6: | |
105 return "604"; | |
106 case 7: | |
107 return "604e"; | |
108 case 8: | |
109 return "620"; | |
110 case 9: | |
111 return "750"; | |
112 case 10: | |
113 return "7400"; | |
114 case 11: | |
115 return "7450"; | |
116 case 100: | |
117 return "970"; | |
118 default: | |
119 return "powerpc"; | |
120 } | |
121 | |
122 return "powerpc"; | |
123 } | |
124 | |
125 #endif /* __APPLE__ */ | |
126 | |
127 #ifdef __FreeBSD__ | |
128 | |
129 /* Returns the description of caches on FreeBSD PPC. */ | |
130 | |
131 static char * | |
132 detect_caches_freebsd (void) | |
133 { | |
134 unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb; | |
135 size_t len = 4; | |
136 | |
137 /* Currently, as of FreeBSD-7.0, there is only the cacheline_size | |
138 available via sysctl. */ | |
139 sysctlbyname ("machdep.cacheline_size", &l1_line, &len, NULL, 0); | |
140 | |
141 l1_sizekb = 32; | |
142 l1_assoc = 0; | |
143 l2_sizekb = 512; | |
144 | |
145 return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb); | |
146 } | |
147 | |
148 /* Currently returns default powerpc. */ | |
149 static const char * | |
150 detect_processor_freebsd (void) | |
151 { | |
152 return "powerpc"; | |
153 } | |
154 | |
155 #endif /* __FreeBSD__ */ | |
156 | |
157 #ifdef __linux__ | |
158 | |
159 /* Returns AT_PLATFORM if present, otherwise generic PowerPC. */ | |
160 | |
161 static const char * | |
162 elf_platform (void) | |
163 { | |
164 int fd; | |
165 | |
166 fd = open ("/proc/self/auxv", O_RDONLY); | |
167 | |
168 if (fd != -1) | |
169 { | |
170 char buf[1024]; | |
171 ElfW(auxv_t) *av; | |
172 ssize_t n; | |
173 | |
174 n = read (fd, buf, sizeof (buf)); | |
175 close (fd); | |
176 | |
177 if (n > 0) | |
178 { | |
179 for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av) | |
180 switch (av->a_type) | |
181 { | |
182 case AT_PLATFORM: | |
183 return (const char *) av->a_un.a_val; | |
184 | |
185 default: | |
186 break; | |
187 } | |
188 } | |
189 } | |
190 return NULL; | |
191 } | |
192 | |
193 /* Returns AT_PLATFORM if present, otherwise generic 32. */ | |
194 | |
195 static int | |
196 elf_dcachebsize (void) | |
197 { | |
198 int fd; | |
199 | |
200 fd = open ("/proc/self/auxv", O_RDONLY); | |
201 | |
202 if (fd != -1) | |
203 { | |
204 char buf[1024]; | |
205 ElfW(auxv_t) *av; | |
206 ssize_t n; | |
207 | |
208 n = read (fd, buf, sizeof (buf)); | |
209 close (fd); | |
210 | |
211 if (n > 0) | |
212 { | |
213 for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av) | |
214 switch (av->a_type) | |
215 { | |
216 case AT_DCACHEBSIZE: | |
217 return av->a_un.a_val; | |
218 | |
219 default: | |
220 break; | |
221 } | |
222 } | |
223 } | |
224 return 32; | |
225 } | |
226 | |
227 /* Returns the description of caches on Linux. */ | |
228 | |
229 static char * | |
230 detect_caches_linux (void) | |
231 { | |
232 unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb; | |
233 const char *platform; | |
234 | |
235 platform = elf_platform (); | |
236 | |
237 if (platform != NULL) | |
238 { | |
239 l1_line = 128; | |
240 | |
241 if (platform[5] == '6') | |
242 /* POWER6 and POWER6x */ | |
243 l1_sizekb = 64; | |
244 else | |
245 l1_sizekb = 32; | |
246 } | |
247 else | |
248 { | |
249 l1_line = elf_dcachebsize (); | |
250 l1_sizekb = 32; | |
251 } | |
252 | |
253 l1_assoc = 0; | |
254 l2_sizekb = 512; | |
255 | |
256 return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb); | |
257 } | |
258 | |
259 static const char * | |
260 detect_processor_linux (void) | |
261 { | |
262 const char *platform; | |
263 | |
264 platform = elf_platform (); | |
265 | |
266 if (platform != NULL) | |
267 return platform; | |
268 else | |
269 return "powerpc"; | |
270 } | |
271 | |
272 #endif /* __linux__ */ | |
273 | |
274 #ifdef _AIX | |
275 /* Returns the description of caches on AIX. */ | |
276 | |
277 static char * | |
278 detect_caches_aix (void) | |
279 { | |
280 unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb; | |
281 | |
282 l1_sizekb = _system_configuration.dcache_size / 1024; | |
283 l1_line = _system_configuration.dcache_line; | |
284 l1_assoc = _system_configuration.dcache_asc; | |
285 l2_sizekb = _system_configuration.L2_cache_size / 1024; | |
286 | |
287 return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb); | |
288 } | |
289 | |
290 | |
291 /* Returns the processor implementation on AIX. */ | |
292 | |
293 static const char * | |
294 detect_processor_aix (void) | |
295 { | |
296 switch (_system_configuration.implementation) | |
297 { | |
298 case 0x0001: | |
299 return "rios1"; | |
300 | |
301 case 0x0002: | |
302 return "rsc"; | |
303 | |
304 case 0x0004: | |
305 return "rios2"; | |
306 | |
307 case 0x0008: | |
308 return "601"; | |
309 | |
310 case 0x0020: | |
311 return "603"; | |
312 | |
313 case 0x0010: | |
314 return "604"; | |
315 | |
316 case 0x0040: | |
317 return "620"; | |
318 | |
319 case 0x0080: | |
320 return "630"; | |
321 | |
322 case 0x0100: | |
323 case 0x0200: | |
324 case 0x0400: | |
325 return "rs64"; | |
326 | |
327 case 0x0800: | |
328 return "power4"; | |
329 | |
330 case 0x2000: | |
331 if (_system_configuration.version == 0x0F0000) | |
332 return "power5"; | |
333 else | |
334 return "power5+"; | |
335 | |
336 case 0x4000: | |
337 return "power6"; | |
338 | |
339 default: | |
340 return "powerpc"; | |
341 } | |
342 } | |
343 #endif /* _AIX */ | |
344 | |
345 | |
346 /* This will be called by the spec parser in gcc.c when it sees | |
347 a %:local_cpu_detect(args) construct. Currently it will be called | |
348 with either "arch" or "tune" as argument depending on if -march=native | |
349 or -mtune=native is to be substituted. | |
350 | |
351 It returns a string containing new command line parameters to be | |
352 put at the place of the above two options, depending on what CPU | |
353 this is executed. | |
354 | |
355 ARGC and ARGV are set depending on the actual arguments given | |
356 in the spec. */ | |
357 const char | |
358 *host_detect_local_cpu (int argc, const char **argv) | |
359 { | |
360 const char *cpu = NULL; | |
361 const char *cache = ""; | |
362 const char *options = ""; | |
363 bool arch; | |
364 | |
365 if (argc < 1) | |
366 return NULL; | |
367 | |
368 arch = strcmp (argv[0], "cpu") == 0; | |
369 if (!arch && strcmp (argv[0], "tune")) | |
370 return NULL; | |
371 | |
372 #if defined (_AIX) | |
373 cache = detect_caches_aix (); | |
374 #elif defined (__APPLE__) | |
375 cache = detect_caches_darwin (); | |
376 #elif defined (__FreeBSD__) | |
377 cache = detect_caches_freebsd (); | |
378 /* FreeBSD PPC does not provide any cache information yet. */ | |
379 cache = ""; | |
380 #elif defined (__linux__) | |
381 cache = detect_caches_linux (); | |
382 /* PPC Linux does not provide any cache information yet. */ | |
383 cache = ""; | |
384 #else | |
385 cache = ""; | |
386 #endif | |
387 | |
388 #if defined (_AIX) | |
389 cpu = detect_processor_aix (); | |
390 #elif defined (__APPLE__) | |
391 cpu = detect_processor_darwin (); | |
392 #elif defined (__FreeBSD__) | |
393 cpu = detect_processor_freebsd (); | |
394 #elif defined (__linux__) | |
395 cpu = detect_processor_linux (); | |
396 #else | |
397 cpu = "powerpc"; | |
398 #endif | |
399 | |
400 return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL); | |
401 } | |
402 | |
403 #else /* GCC_VERSION */ | |
404 | |
405 /* If we aren't compiling with GCC we just provide a minimal | |
406 default value. */ | |
407 const char *host_detect_local_cpu (int argc, const char **argv) | |
408 { | |
409 const char *cpu; | |
410 bool arch; | |
411 | |
412 if (argc < 1) | |
413 return NULL; | |
414 | |
415 arch = strcmp (argv[0], "cpu") == 0; | |
416 if (!arch && strcmp (argv[0], "tune")) | |
417 return NULL; | |
418 | |
419 if (arch) | |
420 cpu = "powerpc"; | |
421 | |
422 return concat ("-m", argv[0], "=", cpu, NULL); | |
423 } | |
424 | |
425 #endif /* GCC_VERSION */ | |
426 |