aboutsummaryrefslogtreecommitdiff
blob: 358ae87a743adf1183118103fdb210e1464e8cf7 (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
147
148
149
150
151
152
153
https://bugs.gentoo.org/802930

From 5bf03bd8c8a97fb30bc7e146216396bbe9f6a36d Mon Sep 17 00:00:00 2001
From: Luke McHale <luke.mchale@protonmail.com>
Date: Fri, 7 Aug 2020 16:46:16 +0000
Subject: [PATCH] powerpcspe arch is missing AT_PLATFORM translation table
 present in the regular powerpc (rs6000) arch. Fixes -mcpu=native when run on
 e500v2 to correctly drop the ppc from AT_PLATFORM ppc8548 to GCC's canonical
 8548.

---
 gcc/config/powerpcspe/driver-powerpcspe.c | 97 +++++++++++++++++++++--
 1 file changed, 89 insertions(+), 8 deletions(-)

--- a/gcc/config/powerpcspe/driver-powerpcspe.c
+++ b/gcc/config/powerpcspe/driver-powerpcspe.c
@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "diagnostic.h"
+#include "opts.h"
 #include <stdlib.h>
 
 #ifdef _AIX
@@ -38,6 +40,44 @@ along with GCC; see the file COPYING3.  If not see
 # include <sys/sysctl.h>
 #endif
 
+#ifdef __linux__
+/* Canonical GCC cpu name table.  */
+static const char *rs6000_supported_cpu_names[] =
+{
+#define RS6000_CPU(NAME, CPU, FLAGS) NAME,
+#include "powerpcspe-cpus.def"
+#undef RS6000_CPU
+};
+
+/* This table holds a list of cpus where their Linux AT_PLATFORM name differs
+   from their GCC canonical name.  The first column in a row contains the GCC
+   canonical cpu name and the other columns in that row contain AT_PLATFORM
+   names that should be mapped to the canonical name.  */
+
+static const char *linux_cpu_translation_table[][4] = {
+  { "403", "ppc403", NULL },
+  { "405", "ppc405", NULL },
+  { "440", "ppc440", "ppc440gp", NULL },
+  { "476", "ppc470", NULL },
+  { "601", "ppc601", NULL },
+  { "603", "ppc603", NULL },
+  { "604", "ppc604", NULL },
+  { "7400", "ppc7400", NULL },
+  { "7450", "ppc7450", NULL },
+  { "750", "ppc750", NULL },
+  { "823", "ppc823", NULL },
+  { "8540", "ppc8540", NULL },
+  { "8548", "ppc8548", NULL },
+  { "970", "ppc970", NULL },
+  { "cell", "ppc-cell-be", NULL },
+  { "e500mc", "ppce500mc", NULL },
+  { "e5500", "ppce5500", NULL },
+  { "e6500", "ppce6500", NULL },
+  { "power7", "power7+", NULL },
+  { NULL } /* End of table sentinel.  */
+};
+#endif
+
 const char *host_detect_local_cpu (int argc, const char **argv);
 
 #if GCC_VERSION >= 0
@@ -158,14 +198,19 @@ detect_processor_freebsd (void)
 
 #ifdef __linux__
 
-/* Returns AT_PLATFORM if present, otherwise generic PowerPC.  */
+/* Returns the canonical AT_PLATFORM if present, otherwise NULL.  */
 
 static const char *
 elf_platform (void)
 {
-  int fd;
+  /* Used to cache the result we determine below.  */
+  static const char *cpu = NULL;
 
-  fd = open ("/proc/self/auxv", O_RDONLY);
+  /* Use the cached AT_PLATFORM cpu name if we've already determined it.  */
+  if (cpu != NULL)
+    return cpu;
+
+  int fd = open ("/proc/self/auxv", O_RDONLY);
 
   if (fd != -1)
     {
@@ -179,15 +224,51 @@ elf_platform (void)
       if (n > 0)
 	{
 	  for (av = (ElfW(auxv_t) *) buf; av->a_type != AT_NULL; ++av)
-	    switch (av->a_type)
+	    if (av->a_type == AT_PLATFORM)
 	      {
-	      case AT_PLATFORM:
-		return (const char *) av->a_un.a_val;
-
-	      default:
+		/* Cache the result.  */
+		cpu = (const char *) av->a_un.a_val;
 		break;
 	      }
 	}
+
+      /* Verify that CPU is either a valid -mcpu=<cpu> option name, or is a
+	 valid alternative name.  If it is a valid alternative name, then use
+	 the canonical name.  */
+      if (cpu != NULL)
+	{
+	  size_t i, j;
+	  char *s;
+
+	  /* Check if AT_PLATFORM is a GCC canonical cpu name.  */
+	  for (i = 0; i < ARRAY_SIZE (rs6000_supported_cpu_names); i++)
+	    if (!strcmp (cpu, rs6000_supported_cpu_names[i]))
+	      return cpu;
+
+	  /* Check if AT_PLATFORM can be translated to a canonical cpu name.  */
+	  for (i = 0; linux_cpu_translation_table[i][0] != NULL; i++)
+	    {
+	      const char *canonical = linux_cpu_translation_table[i][0];
+	      for (j = 1; linux_cpu_translation_table[i][j] != NULL; j++)
+		if (!strcmp (cpu, linux_cpu_translation_table[i][j]))
+		  {
+		    /* Cache the result.  */
+		    cpu = canonical;
+		    return cpu;
+		  }
+	    }
+
+	  /* The kernel returned an AT_PLATFORM name we do not support.  */
+	  auto_vec <const char *> candidates;
+	  for (i = 0; i < ARRAY_SIZE (rs6000_supported_cpu_names); i++)
+	    candidates.safe_push (rs6000_supported_cpu_names[i]);
+	  candidates_list_and_hint (cpu, s, candidates);
+	  fatal_error (
+	    input_location,
+	    "Unsupported cpu name returned from kernel for -mcpu=native: %s\n"
+	    "Please use an explicit cpu name.  Valid cpu names are: %s",
+	    cpu, s);
+	}
     }
   return NULL;
 }
-- 
2.27.0