1/* Subroutines for the gcc driver.
2   Copyright (C) 2011-2020 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#define IN_TARGET_CODE 1
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
26
27static const struct cpu_names {
28  const char *const name;
29  const char *const cpu;
30} cpu_names[] = {
31#if defined __sun__ && defined __svr4__
32  { "TMS390S10",	"supersparc" },	/* Texas Instruments microSPARC I */
33  { "TMS390Z50",	"supersparc" },	/* Texas Instruments SuperSPARC I */
34  { "TMS390Z55",	"supersparc" },	/* Texas Instruments
35					   SuperSPARC I with SuperCache */
36  { "MB86904",		"supersparc" },	/* Fujitsu microSPARC II */
37  { "MB86907",		"supersparc" },	/* Fujitsu TurboSPARC */
38  { "RT623",		"hypersparc" },	/* Ross hyperSPARC */
39  { "RT625",		"hypersparc" },
40  { "RT626",		"hypersparc" },
41  { "UltraSPARC-I",	"ultrasparc" },
42  { "UltraSPARC-II",	"ultrasparc" },
43  { "UltraSPARC-IIe",	"ultrasparc" },
44  { "UltraSPARC-IIi",	"ultrasparc" },
45  { "SPARC64-III",	"ultrasparc" },
46  { "SPARC64-IV",	"ultrasparc" },
47  { "UltraSPARC-III",	"ultrasparc3" },
48  { "UltraSPARC-III+",	"ultrasparc3" },
49  { "UltraSPARC-IIIi",	"ultrasparc3" },
50  { "UltraSPARC-IIIi+",	"ultrasparc3" },
51  { "UltraSPARC-IV",	"ultrasparc3" },
52  { "UltraSPARC-IV+",	"ultrasparc3" },
53  { "SPARC64-V",	"ultrasparc3" },
54  { "SPARC64-VI",	"ultrasparc3" },
55  { "SPARC64-VII",	"ultrasparc3" },
56  { "UltraSPARC-T1",	"niagara" },
57  { "UltraSPARC-T2",	"niagara2" },
58  { "UltraSPARC-T2",	"niagara2" },
59  { "UltraSPARC-T2+",	"niagara2" },
60  { "SPARC-T3",		"niagara3" },
61  { "SPARC-T4",		"niagara4" },
62  { "SPARC-T5",		"niagara4" },
63#else
64  { "SuperSparc",	"supersparc" },
65  { "HyperSparc",	"hypersparc" },
66  { "SpitFire",		"ultrasparc" },
67  { "BlackBird",	"ultrasparc" },
68  { "Sabre",		"ultrasparc" },
69  { "Hummingbird",	"ultrasparc" },
70  { "Cheetah",		"ultrasparc3" },
71  { "Jalapeno",		"ultrasparc3" },
72  { "Jaguar",		"ultrasparc3" },
73  { "Panther",		"ultrasparc3" },
74  { "Serrano",		"ultrasparc3" },
75  { "UltraSparc T1",	"niagara" },
76  { "UltraSparc T2",	"niagara2" },
77  { "UltraSparc T3",	"niagara3" },
78  { "UltraSparc T4",	"niagara4" },
79  { "UltraSparc T5",	"niagara4" },
80  { "LEON",		"leon3" },
81#endif
82  { "SPARC-M7",		"niagara7" },
83  { "SPARC-S7",		"niagara7" },
84  { "SPARC-M8",		"m8" },
85  { NULL,	NULL }
86  };
87
88#if defined __sun__ && defined __svr4__
89#include <kstat.h>
90#endif
91
92/* This will be called by the spec parser in gcc.c when it sees
93   a %:local_cpu_detect(args) construct.  Currently it will be called
94   with either "cpu" or "tune" as argument depending on if -mcpu=native
95   or -mtune=native is to be substituted.
96
97   It returns a string containing new command line parameters to be
98   put at the place of the above two options, depending on what CPU
99   this is executed.  E.g. "-mcpu=ultrasparc3" on an UltraSPARC III for
100   -mcpu=native.  If the routine can't detect a known processor,
101   the -mcpu or -mtune option is discarded.
102
103   ARGC and ARGV are set depending on the actual arguments given
104   in the spec.  */
105const char *
106host_detect_local_cpu (int argc, const char **argv)
107{
108  const char *cpu = NULL;
109#if defined __sun__ && defined __svr4__
110  char *buf = NULL;
111  kstat_ctl_t *kc;
112  kstat_t *ksp;
113  kstat_named_t *brand = NULL;
114#else
115  char buf[128];
116  FILE *f;
117#endif
118  int i;
119
120  if (argc < 1)
121    return NULL;
122
123  if (strcmp (argv[0], "cpu") && strcmp (argv[0], "tune"))
124    return NULL;
125
126#if defined __sun__ && defined __svr4__
127  kc = kstat_open ();
128  if (kc != NULL)
129    {
130      ksp = kstat_lookup (kc, CONST_CAST2 (char *, const char *, "cpu_info"),
131			  -1, NULL);
132      if (ksp != NULL
133	  && kstat_read (kc, ksp, NULL) != -1
134	  && ksp->ks_type == KSTAT_TYPE_NAMED)
135	brand = (kstat_named_t *)
136	  kstat_data_lookup (ksp, CONST_CAST2 (char *, const char *, "brand"));
137      if (brand != NULL && brand->data_type == KSTAT_DATA_STRING)
138	buf = KSTAT_NAMED_STR_PTR (brand);
139    }
140  kstat_close (kc);
141
142  for (i = 0; cpu_names[i].name != NULL; i++)
143    if (strcmp (buf, cpu_names[i].name) == 0)
144      cpu = cpu_names[i].cpu;
145#else
146  f = fopen ("/proc/cpuinfo", "r");
147  if (f == NULL)
148    return NULL;
149
150  while (fgets (buf, sizeof (buf), f) != NULL)
151    if (strncmp (buf, "cpu\t\t:", sizeof ("cpu\t\t:") - 1) == 0)
152      {
153        for (i = 0; cpu_names [i].name; i++)
154          if (strstr (buf, cpu_names [i].name) != NULL)
155	    {
156	      cpu = cpu_names [i].cpu;
157	      break;
158	    }
159	break;
160      }
161
162  fclose (f);
163#endif
164
165  if (cpu == NULL)
166    return NULL;
167
168  return concat ("-m", argv[0], "=", cpu, NULL);
169}
170