xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/arm/driver-arm.c (revision 33881f779a77dce6440bdc44610d94de75bebefe)
1 /* Subroutines for the gcc driver.
2    Copyright (C) 2011-2017 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 "configargs.h"
25 
26 struct vendor_cpu {
27   const char *part_no;
28   const char *arch_name;
29   const char *cpu_name;
30 };
31 
32 static struct vendor_cpu arm_cpu_table[] = {
33     {"0x926", "armv5te", "arm926ej-s"},
34     {"0xa26", "armv5te", "arm1026ej-s"},
35     {"0xb02", "armv6k", "mpcore"},
36     {"0xb36", "armv6j", "arm1136j-s"},
37     {"0xb56", "armv6t2", "arm1156t2-s"},
38     /* armv6kz is the correct spelling for ARMv6KZ but may not be supported in
39        the version of binutils used.  The incorrect spelling is supported in
40        legacy and current binutils so that is used instead.  */
41     {"0xb76", "armv6zk", "arm1176jz-s"},
42     {"0xc05", "armv7-a", "cortex-a5"},
43     {"0xc07", "armv7ve", "cortex-a7"},
44     {"0xc08", "armv7-a", "cortex-a8"},
45     {"0xc09", "armv7-a", "cortex-a9"},
46     {"0xc0d", "armv7ve", "cortex-a12"},
47     {"0xc0e", "armv7ve", "cortex-a17"},
48     {"0xc0f", "armv7ve", "cortex-a15"},
49     {"0xd01", "armv8-a+crc", "cortex-a32"},
50     {"0xd04", "armv8-a+crc", "cortex-a35"},
51     {"0xd03", "armv8-a+crc", "cortex-a53"},
52     {"0xd07", "armv8-a+crc", "cortex-a57"},
53     {"0xd08", "armv8-a+crc", "cortex-a72"},
54     {"0xd09", "armv8-a+crc", "cortex-a73"},
55     {"0xc14", "armv7-r", "cortex-r4"},
56     {"0xc15", "armv7-r", "cortex-r5"},
57     {"0xc20", "armv6-m", "cortex-m0"},
58     {"0xc21", "armv6-m", "cortex-m1"},
59     {"0xc23", "armv7-m", "cortex-m3"},
60     {"0xc24", "armv7e-m", "cortex-m4"},
61     {NULL, NULL, NULL}
62 };
63 
64 static struct {
65   const char *vendor_no;
66   const struct vendor_cpu *vendor_parts;
67 } vendors[] = {
68     {"0x41", arm_cpu_table},
69     {NULL, NULL}
70 };
71 
72 /* This will be called by the spec parser in gcc.c when it sees
73    a %:local_cpu_detect(args) construct.  Currently it will be called
74    with either "arch", "cpu" or "tune" as argument depending on if
75    -march=native, -mcpu=native or -mtune=native is to be substituted.
76 
77    It returns a string containing new command line parameters to be
78    put at the place of the above two options, depending on what CPU
79    this is executed.  E.g. "-march=armv7-a" on a Cortex-A8 for
80    -march=native.  If the routine can't detect a known processor,
81    the -march or -mtune option is discarded.
82 
83    ARGC and ARGV are set depending on the actual arguments given
84    in the spec.  */
85 const char *
86 host_detect_local_cpu (int argc, const char **argv)
87 {
88   const char *val = NULL;
89   char buf[128];
90   FILE *f = NULL;
91   bool arch;
92   const struct vendor_cpu *cpu_table = NULL;
93 
94   if (argc < 1)
95     goto not_found;
96 
97   arch = strcmp (argv[0], "arch") == 0;
98   if (!arch && strcmp (argv[0], "cpu") != 0 && strcmp (argv[0], "tune"))
99     goto not_found;
100 
101   f = fopen ("/proc/cpuinfo", "r");
102   if (f == NULL)
103     goto not_found;
104 
105   while (fgets (buf, sizeof (buf), f) != NULL)
106     {
107       /* Ensure that CPU implementer is ARM (0x41).  */
108       if (strncmp (buf, "CPU implementer", sizeof ("CPU implementer") - 1) == 0)
109 	{
110 	  int i;
111 	  for (i = 0; vendors[i].vendor_no != NULL; i++)
112 	    if (strstr (buf, vendors[i].vendor_no) != NULL)
113 	      {
114 		cpu_table = vendors[i].vendor_parts;
115 		break;
116 	      }
117 	}
118 
119       /* Detect arch/cpu.  */
120       if (strncmp (buf, "CPU part", sizeof ("CPU part") - 1) == 0)
121 	{
122 	  int i;
123 
124 	  if (cpu_table == NULL)
125 	    goto not_found;
126 
127 	  for (i = 0; cpu_table[i].part_no != NULL; i++)
128 	    if (strstr (buf, cpu_table[i].part_no) != NULL)
129 	      {
130 		val = arch ? cpu_table[i].arch_name : cpu_table[i].cpu_name;
131 		break;
132 	      }
133 	  break;
134 	}
135     }
136 
137   if (val)
138     {
139       fclose (f);
140       return concat ("-m", argv[0], "=", val, NULL);
141      }
142 
143 not_found:
144   {
145     unsigned int i;
146     unsigned int opt;
147     const char *search[] = {NULL, "arch"};
148 
149     if (f)
150       fclose (f);
151 
152     search[0] = argv[0];
153     for (opt = 0; opt < ARRAY_SIZE (search); opt++)
154       for (i = 0; i < ARRAY_SIZE (configure_default_options); i++)
155 	if (strcmp (configure_default_options[i].name, search[opt]) == 0)
156 	  return concat ("-m", search[opt], "=",
157 			 configure_default_options[i].value, NULL);
158     return NULL;
159   }
160 }
161