/* Subroutines for the gcc driver.
Copyright (C) 2011-2017 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
static const struct cpu_names {
const char *const name;
const char *const cpu;
} cpu_names[] = {
#if defined __sun__ && defined __svr4__
{ "TMS390S10", "supersparc" }, /* Texas Instruments microSPARC I */
{ "TMS390Z50", "supersparc" }, /* Texas Instruments SuperSPARC I */
{ "TMS390Z55", "supersparc" }, /* Texas Instruments
SuperSPARC I with SuperCache */
{ "MB86904", "supersparc" }, /* Fujitsu microSPARC II */
{ "MB86907", "supersparc" }, /* Fujitsu TurboSPARC */
{ "RT623", "hypersparc" }, /* Ross hyperSPARC */
{ "RT625", "hypersparc" },
{ "RT626", "hypersparc" },
{ "UltraSPARC-I", "ultrasparc" },
{ "UltraSPARC-II", "ultrasparc" },
{ "UltraSPARC-IIe", "ultrasparc" },
{ "UltraSPARC-IIi", "ultrasparc" },
{ "SPARC64-III", "ultrasparc" },
{ "SPARC64-IV", "ultrasparc" },
{ "UltraSPARC-III", "ultrasparc3" },
{ "UltraSPARC-III+", "ultrasparc3" },
{ "UltraSPARC-IIIi", "ultrasparc3" },
{ "UltraSPARC-IIIi+", "ultrasparc3" },
{ "UltraSPARC-IV", "ultrasparc3" },
{ "UltraSPARC-IV+", "ultrasparc3" },
{ "SPARC64-V", "ultrasparc3" },
{ "SPARC64-VI", "ultrasparc3" },
{ "SPARC64-VII", "ultrasparc3" },
{ "UltraSPARC-T1", "niagara" },
{ "UltraSPARC-T2", "niagara2" },
{ "UltraSPARC-T2", "niagara2" },
{ "UltraSPARC-T2+", "niagara2" },
{ "SPARC-T3", "niagara3" },
{ "SPARC-T4", "niagara4" },
{ "SPARC-T5", "niagara4" },
#else
{ "SuperSparc", "supersparc" },
{ "HyperSparc", "hypersparc" },
{ "SpitFire", "ultrasparc" },
{ "BlackBird", "ultrasparc" },
{ "Sabre", "ultrasparc" },
{ "Hummingbird", "ultrasparc" },
{ "Cheetah", "ultrasparc3" },
{ "Jalapeno", "ultrasparc3" },
{ "Jaguar", "ultrasparc3" },
{ "Panther", "ultrasparc3" },
{ "Serrano", "ultrasparc3" },
{ "UltraSparc T1", "niagara" },
{ "UltraSparc T2", "niagara2" },
{ "UltraSparc T3", "niagara3" },
{ "UltraSparc T4", "niagara4" },
{ "UltraSparc T5", "niagara4" },
{ "LEON", "leon3" },
#endif
{ "SPARC-M7", "niagara7" },
{ "SPARC-S7", "niagara7" },
{ "SPARC-M8", "m8" },
{ NULL, NULL }
};
#if defined __sun__ && defined __svr4__
#include
#endif
/* This will be called by the spec parser in gcc.c when it sees
a %:local_cpu_detect(args) construct. Currently it will be called
with either "cpu" or "tune" as argument depending on if -mcpu=native
or -mtune=native is to be substituted.
It returns a string containing new command line parameters to be
put at the place of the above two options, depending on what CPU
this is executed. E.g. "-mcpu=ultrasparc3" on an UltraSPARC III for
-mcpu=native. If the routine can't detect a known processor,
the -mcpu or -mtune option is discarded.
ARGC and ARGV are set depending on the actual arguments given
in the spec. */
const char *
host_detect_local_cpu (int argc, const char **argv)
{
const char *cpu = NULL;
#if defined __sun__ && defined __svr4__
char *buf = NULL;
kstat_ctl_t *kc;
kstat_t *ksp;
kstat_named_t *brand = NULL;
#else
char buf[128];
FILE *f;
#endif
int i;
if (argc < 1)
return NULL;
if (strcmp (argv[0], "cpu") && strcmp (argv[0], "tune"))
return NULL;
#if defined __sun__ && defined __svr4__
kc = kstat_open ();
if (kc != NULL)
{
ksp = kstat_lookup (kc, CONST_CAST2 (char *, const char *, "cpu_info"),
-1, NULL);
if (ksp != NULL
&& kstat_read (kc, ksp, NULL) != -1
&& ksp->ks_type == KSTAT_TYPE_NAMED)
brand = (kstat_named_t *)
kstat_data_lookup (ksp, CONST_CAST2 (char *, const char *, "brand"));
/* "brand" was only introduced in Solaris 10. */
if (brand == NULL)
brand = (kstat_named_t *)
kstat_data_lookup (ksp, CONST_CAST2 (char *, const char *,
"implementation"));
/* KSTAT_DATA_STRING was introduced in Solaris 9. */
#ifdef KSTAT_DATA_STRING
if (brand != NULL && brand->data_type == KSTAT_DATA_STRING)
buf = KSTAT_NAMED_STR_PTR (brand);
#else
if (brand != NULL && brand->data_type == KSTAT_DATA_CHAR)
buf = brand->value.c;
#endif
}
kstat_close (kc);
for (i = 0; cpu_names[i].name != NULL; i++)
if (strcmp (buf, cpu_names[i].name) == 0)
cpu = cpu_names[i].cpu;
#else
f = fopen ("/proc/cpuinfo", "r");
if (f == NULL)
return NULL;
while (fgets (buf, sizeof (buf), f) != NULL)
if (strncmp (buf, "cpu\t\t:", sizeof ("cpu\t\t:") - 1) == 0)
{
for (i = 0; cpu_names [i].name; i++)
if (strstr (buf, cpu_names [i].name) != NULL)
{
cpu = cpu_names [i].cpu;
break;
}
break;
}
fclose (f);
#endif
if (cpu == NULL)
return NULL;
return concat ("-m", argv[0], "=", cpu, NULL);
}