1 /* Definitions for LoongArch CPU properties.
2 Copyright (C) 2021-2024 Free Software Foundation, Inc.
3 Contributed by Loongson Ltd.
5 This file is part of GCC.
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)
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.
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/>. */
21 #define IN_TARGET_CODE 1
25 #include "coretypes.h"
26 #include "diagnostic-core.h"
28 #include "loongarch-def.h"
29 #include "loongarch-opts.h"
30 #include "loongarch-cpu.h"
31 #include "loongarch-str.h"
32 #include "loongarch-evolution.h"
35 /* Native CPU detection with "cpucfg" */
36 static uint32_t cpucfg_cache
[N_CPUCFG_WORDS
] = { 0 };
39 read_cpucfg_word (int wordno
)
41 /* To make cross-compiler shut up. */
46 __asm__
__volatile__ ("cpucfg %0,%1\n\t"
58 for (int idx
: cpucfg_useful_idx
)
59 cpucfg_cache
[idx
] = read_cpucfg_word (idx
);
63 get_native_prid (void)
65 /* Fill loongarch_cpu_default_config[ARCH_NATIVE] with cpucfg data,
66 see "Loongson Architecture Reference Manual"
67 (Volume 1, Section 2.2.10.5) */
68 return cpucfg_cache
[0];
72 get_native_prid_str (void)
74 static char prid_str
[9];
75 sprintf (prid_str
, "%08x", cpucfg_cache
[0]);
76 return (const char*) prid_str
;
79 /* Fill property tables for ARCH_NATIVE / TUNE_NATIVE. */
81 fill_native_cpu_config (struct loongarch_target
*tgt
)
83 int arch_native_p
= tgt
->cpu_arch
== ARCH_NATIVE
;
84 int tune_native_p
= tgt
->cpu_tune
== TUNE_NATIVE
;
85 int native_cpu_arch
= ARCH_NATIVE
;
86 int native_cpu_tune
= TUNE_NATIVE
;
88 /* Nothing needs to be done unless "-march/tune=native"
89 is given or implied. */
90 if (!arch_native_p
&& !tune_native_p
)
93 /* Fill cpucfg_cache with the "cpucfg" instruction. */
96 /* Fill: tgt->cpu_arch | tgt->cpu_tune
97 With: processor ID (PRID)
98 At: cpucfg_words[0][31:0] */
100 switch (cpucfg_cache
[0] & 0x00ffff00)
102 case 0x0014c000: /* LA464 */
103 native_cpu_arch
= ARCH_LA464
;
104 native_cpu_tune
= TUNE_LA464
;
107 case 0x0014d000: /* LA664 */
108 native_cpu_arch
= ARCH_LA664
;
109 native_cpu_tune
= TUNE_LA664
;
115 inform (UNKNOWN_LOCATION
, "unknown processor ID %<0x%x%>, "
116 "some tuning parameters will fall back to default",
121 /* if -march=native */
125 tgt
->cpu_arch
= native_cpu_arch
;
127 auto &preset
= loongarch_cpu_default_isa
[tgt
->cpu_arch
];
129 /* Fill: loongarch_cpu_default_isa[tgt->cpu_arch].base
130 With: base architecture (ARCH)
131 At: cpucfg_words[1][1:0] */
133 if (native_cpu_arch
!= ARCH_NATIVE
)
134 tmp
= loongarch_cpu_default_isa
[native_cpu_arch
].base
;
136 switch (cpucfg_cache
[1] & 0x3)
143 fatal_error (UNKNOWN_LOCATION
,
144 "unknown native base architecture %<0x%x%>, "
146 (unsigned int) (cpucfg_cache
[1] & 0x3),
147 "-m" OPTSTR_ARCH
"=" STR_CPU_NATIVE
);
150 /* Use the native value anyways. */
153 /* Fill: loongarch_cpu_default_isa[tgt->cpu_arch].fpu
154 With: FPU type (FP, FP_SP, FP_DP)
155 At: cpucfg_words[2][2:0] */
157 switch (cpucfg_cache
[2] & 0x7)
172 fatal_error (UNKNOWN_LOCATION
,
173 "unknown native FPU type %<0x%x%>, %qs failed",
174 (unsigned int) (cpucfg_cache
[2] & 0x7),
175 "-m" OPTSTR_ARCH
"=" STR_CPU_NATIVE
);
178 /* Check consistency with PRID presets. */
179 if (native_cpu_arch
!= ARCH_NATIVE
&& tmp
!= preset
.fpu
)
180 warning (0, "floating-point unit %qs differs from PRID preset %qs",
181 loongarch_isa_ext_strings
[tmp
],
182 loongarch_isa_ext_strings
[preset
.fpu
]);
184 /* Use the native value anyways. */
188 /* Fill: loongarch_cpu_default_isa[ARCH_NATIVE].simd
189 With: SIMD extension type (LSX, LASX)
190 At: cpucfg_words[2][7:6] */
192 switch (cpucfg_cache
[2] & 0xc0)
195 tmp
= ISA_EXT_SIMD_LASX
;
199 tmp
= ISA_EXT_SIMD_LSX
;
204 warning (0, "unknown SIMD extension "
205 "(%qs disabled while %qs is enabled), disabling SIMD",
206 loongarch_isa_ext_strings
[ISA_EXT_SIMD_LSX
],
207 loongarch_isa_ext_strings
[ISA_EXT_SIMD_LASX
]);
215 /* Check consistency with PRID presets. */
218 if (native_cpu_arch != ARCH_NATIVE && tmp != preset.simd)
219 warning (0, "SIMD extension %qs differs from PRID preset %qs",
220 loongarch_isa_ext_strings[tmp],
221 loongarch_isa_ext_strings[preset.simd]);
224 /* Use the native value anyways. */
228 int64_t hw_isa_evolution
= 0;
230 /* Features added during ISA evolution. */
231 for (const auto &entry
: cpucfg_map
)
232 if (cpucfg_cache
[entry
.cpucfg_word
] & entry
.cpucfg_bit
)
233 hw_isa_evolution
|= entry
.isa_evolution_bit
;
235 if (native_cpu_arch
!= ARCH_NATIVE
)
237 /* Check if the local CPU really supports the features of the base
238 ISA of probed native_cpu_arch. If any feature is not detected,
239 either GCC or the hardware is buggy. */
240 if ((preset
.evolution
& hw_isa_evolution
) != hw_isa_evolution
)
242 "detected base architecture %qs, but some of its "
243 "features are not detected; the detected base "
244 "architecture may be unreliable, only detected "
245 "features will be enabled",
246 loongarch_isa_base_strings
[preset
.base
]);
248 preset
.evolution
= hw_isa_evolution
;
253 tgt
->cpu_tune
= native_cpu_tune
;
255 /* Fill: loongarch_cpu_cache[tgt->cpu_tune]
256 With: cache size info
257 At: cpucfg_words[16:20][31:0] */
259 auto &preset_cache
= loongarch_cpu_cache
[tgt
->cpu_tune
];
260 struct loongarch_cache native_cache
;
261 int l1d_present
= 0, l1u_present
= 0;
263 uint32_t l1_szword
, l2_szword
;
265 l1u_present
|= cpucfg_cache
[16] & 3; /* bit[1:0]: unified l1 */
266 l1d_present
|= cpucfg_cache
[16] & 4; /* bit[2:2]: l1d */
267 l1_szword
= l1d_present
? 18 : (l1u_present
? 17 : 0);
268 l1_szword
= l1_szword
? cpucfg_cache
[l1_szword
]: 0;
270 l2d_present
|= cpucfg_cache
[16] & 24; /* bit[4:3]: unified l2 */
271 l2d_present
|= cpucfg_cache
[16] & 128; /* bit[7:7]: l2d */
272 l2_szword
= l2d_present
? cpucfg_cache
[19]: 0;
274 native_cache
.l1d_line_size
275 = 1 << ((l1_szword
& 0x7f000000) >> 24); /* bit[30:24]: log2(line) */
277 native_cache
.l1d_size
278 = (1 << ((l1_szword
& 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
279 * ((l1_szword
& 0x0000ffff) + 1) /* bit[15:0]: sets - 1 */
280 * (1 << ((l1_szword
& 0x7f000000) >> 24)) /* bit[30:24]: log2(line) */
281 >> 10; /* in kibibytes */
283 native_cache
.l2d_size
284 = (1 << ((l2_szword
& 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
285 * ((l2_szword
& 0x0000ffff) + 1) /* bit[15:0]: sets - 1 */
286 * (1 << ((l2_szword
& 0x7f000000) >> 24)) /* bit[30:24]: log2(linesz) */
287 >> 10; /* in kibibytes */
289 /* Use the native value anyways. */
290 preset_cache
.l1d_line_size
= native_cache
.l1d_line_size
;
291 preset_cache
.l1d_size
= native_cache
.l1d_size
;
292 preset_cache
.l2d_size
= native_cache
.l2d_size
;