xref: /netbsd-src/external/gpl3/gcc/dist/gcc/config/loongarch/loongarch-cpu.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /* Definitions for LoongArch CPU properties.
2    Copyright (C) 2021-2022 Free Software Foundation, Inc.
3    Contributed by Loongson Ltd.
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11 
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #define IN_TARGET_CODE 1
22 
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "diagnostic-core.h"
28 
29 #include "loongarch-opts.h"
30 #include "loongarch-cpu.h"
31 #include "loongarch-str.h"
32 
33 /* Native CPU detection with "cpucfg" */
34 #define N_CPUCFG_WORDS 0x15
35 static uint32_t cpucfg_cache[N_CPUCFG_WORDS] = { 0 };
36 static const int cpucfg_useful_idx[] = {0, 1, 2, 16, 17, 18, 19};
37 
38 static uint32_t
read_cpucfg_word(int wordno)39 read_cpucfg_word (int wordno)
40 {
41   /* To make cross-compiler shut up.  */
42   (void) wordno;
43   uint32_t ret = 0;
44 
45   #ifdef __loongarch__
46   __asm__ __volatile__ ("cpucfg %0,%1\n\t"
47 			:"=r"(ret)
48 			:"r"(wordno)
49 			:);
50   #endif
51 
52   return ret;
53 }
54 
55 void
cache_cpucfg(void)56 cache_cpucfg (void)
57 {
58   for (unsigned int i = 0; i < sizeof (cpucfg_useful_idx) / sizeof (int); i++)
59     {
60       cpucfg_cache[cpucfg_useful_idx[i]]
61 	= read_cpucfg_word (cpucfg_useful_idx[i]);
62     }
63 }
64 
65 uint32_t
get_native_prid(void)66 get_native_prid (void)
67 {
68   /* Fill loongarch_cpu_default_config[CPU_NATIVE] with cpucfg data,
69      see "Loongson Architecture Reference Manual"
70      (Volume 1, Section 2.2.10.5) */
71   return cpucfg_cache[0];
72 }
73 
74 const char*
get_native_prid_str(void)75 get_native_prid_str (void)
76 {
77   static char prid_str[9];
78   sprintf (prid_str, "%08x", cpucfg_cache[0]);
79   return (const char*) prid_str;
80 }
81 
82 /* Fill property tables for CPU_NATIVE.  */
83 unsigned int
fill_native_cpu_config(int p_arch_native,int p_tune_native)84 fill_native_cpu_config (int p_arch_native, int p_tune_native)
85 {
86   int ret_cpu_type;
87 
88   /* Nothing needs to be done unless "-march/tune=native"
89      is given or implied.  */
90   if (!(p_arch_native || p_tune_native))
91     return CPU_NATIVE;
92 
93   /* Fill cpucfg_cache with the "cpucfg" instruction.  */
94   cache_cpucfg ();
95 
96 
97   /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].base
98      With: base architecture (ARCH)
99      At:   cpucfg_words[1][1:0] */
100 
101   #define NATIVE_BASE_ISA (loongarch_cpu_default_isa[CPU_NATIVE].base)
102   switch (cpucfg_cache[1] & 0x3)
103     {
104       case 0x02:
105 	NATIVE_BASE_ISA = ISA_BASE_LA64V100;
106 	break;
107 
108       default:
109 	if (p_arch_native)
110 	  fatal_error (UNKNOWN_LOCATION,
111 		       "unknown base architecture %<0x%x%>, %qs failed",
112 		       (unsigned int) (cpucfg_cache[1] & 0x3),
113 		       "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
114     }
115 
116   /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].fpu
117      With: FPU type (FP, FP_SP, FP_DP)
118      At:   cpucfg_words[2][2:0] */
119 
120   #define NATIVE_FPU (loongarch_cpu_default_isa[CPU_NATIVE].fpu)
121   switch (cpucfg_cache[2] & 0x7)
122     {
123       case 0x07:
124 	NATIVE_FPU = ISA_EXT_FPU64;
125 	break;
126 
127       case 0x03:
128 	NATIVE_FPU = ISA_EXT_FPU32;
129 	break;
130 
131       case 0x00:
132 	NATIVE_FPU = ISA_EXT_NOFPU;
133 	break;
134 
135       default:
136 	if (p_arch_native)
137 	  fatal_error (UNKNOWN_LOCATION,
138 		       "unknown FPU type %<0x%x%>, %qs failed",
139 		       (unsigned int) (cpucfg_cache[2] & 0x7),
140 		       "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
141     }
142 
143   /* Fill: loongarch_cpu_cache[CPU_NATIVE]
144      With: cache size info
145      At:   cpucfg_words[16:20][31:0] */
146 
147   int l1d_present = 0, l1u_present = 0;
148   int l2d_present = 0;
149   uint32_t l1_szword, l2_szword;
150 
151   l1u_present |= cpucfg_cache[16] & 3;	      /* bit[1:0]: unified l1 cache */
152   l1d_present |= cpucfg_cache[16] & 4;	      /* bit[2:2]: l1 dcache */
153   l1_szword = l1d_present ? 18 : (l1u_present ? 17 : 0);
154   l1_szword = l1_szword ? cpucfg_cache[l1_szword]: 0;
155 
156   l2d_present |= cpucfg_cache[16] & 24;	      /* bit[4:3]: unified l2 cache */
157   l2d_present |= cpucfg_cache[16] & 128;      /* bit[7:7]: l2 dcache */
158   l2_szword = l2d_present ? cpucfg_cache[19]: 0;
159 
160   loongarch_cpu_cache[CPU_NATIVE].l1d_line_size
161     = 1 << ((l1_szword & 0x7f000000) >> 24);  /* bit[30:24]: log2(linesize) */
162 
163   loongarch_cpu_cache[CPU_NATIVE].l1d_size
164     = (1 << ((l1_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
165     * ((l1_szword & 0x0000ffff) + 1)	      /* bit[15:0]:  sets - 1 */
166     * (1 << ((l1_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */
167     >> 10;				      /* in kilobytes */
168 
169   loongarch_cpu_cache[CPU_NATIVE].l2d_size
170     = (1 << ((l2_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
171     * ((l2_szword & 0x0000ffff) + 1)	      /* bit[15:0]:  sets - 1 */
172     * (1 << ((l2_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */
173     >> 10;				      /* in kilobytes */
174 
175   /* Fill: ret_cpu_type
176      With: processor ID (PRID)
177      At:   cpucfg_words[0][31:0] */
178 
179   switch (cpucfg_cache[0] & 0x00ffff00)
180   {
181     case 0x0014c000:   /* LA464 */
182       ret_cpu_type = CPU_LA464;
183       break;
184 
185     default:
186       /* Unknown PRID.  This is generally harmless as long as
187 	 the properties above can be obtained via "cpucfg".  */
188       if (p_tune_native)
189 	inform (UNKNOWN_LOCATION, "unknown processor ID %<0x%x%>, "
190 		"some tuning parameters will fall back to default",
191 		cpucfg_cache[0]);
192       break;
193   }
194 
195   /* Properties that cannot be looked up directly using cpucfg.  */
196   loongarch_cpu_issue_rate[CPU_NATIVE]
197     = loongarch_cpu_issue_rate[ret_cpu_type];
198 
199   loongarch_cpu_multipass_dfa_lookahead[CPU_NATIVE]
200     = loongarch_cpu_multipass_dfa_lookahead[ret_cpu_type];
201 
202   loongarch_cpu_rtx_cost_data[CPU_NATIVE]
203     = loongarch_cpu_rtx_cost_data[ret_cpu_type];
204 
205   return ret_cpu_type;
206 }
207