aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/loongarch/loongarch-cpu.cc
blob: 34905f3de30e1ec6cbb4587f186a6530f201827f (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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/* Definitions for LoongArch CPU properties.
   Copyright (C) 2021-2023 Free Software Foundation, Inc.
   Contributed by Loongson Ltd.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#define IN_TARGET_CODE 1

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "diagnostic-core.h"

#include "loongarch-opts.h"
#include "loongarch-cpu.h"
#include "loongarch-str.h"

/* Native CPU detection with "cpucfg" */
#define N_CPUCFG_WORDS 0x15
static uint32_t cpucfg_cache[N_CPUCFG_WORDS] = { 0 };
static const int cpucfg_useful_idx[] = {0, 1, 2, 16, 17, 18, 19};

static uint32_t
read_cpucfg_word (int wordno)
{
  /* To make cross-compiler shut up.  */
  (void) wordno;
  uint32_t ret = 0;

  #ifdef __loongarch__
  __asm__ __volatile__ ("cpucfg %0,%1\n\t"
			:"=r"(ret)
			:"r"(wordno)
			:);
  #endif

  return ret;
}

void
cache_cpucfg (void)
{
  for (unsigned int i = 0; i < sizeof (cpucfg_useful_idx) / sizeof (int); i++)
    {
      cpucfg_cache[cpucfg_useful_idx[i]]
	= read_cpucfg_word (cpucfg_useful_idx[i]);
    }
}

uint32_t
get_native_prid (void)
{
  /* Fill loongarch_cpu_default_config[CPU_NATIVE] with cpucfg data,
     see "Loongson Architecture Reference Manual"
     (Volume 1, Section 2.2.10.5) */
  return cpucfg_cache[0];
}

const char*
get_native_prid_str (void)
{
  static char prid_str[9];
  sprintf (prid_str, "%08x", cpucfg_cache[0]);
  return (const char*) prid_str;
}

/* Fill property tables for CPU_NATIVE.  */
unsigned int
fill_native_cpu_config (int p_arch_native, int p_tune_native)
{
  int ret_cpu_type;

  /* Nothing needs to be done unless "-march/tune=native"
     is given or implied.  */
  if (!(p_arch_native || p_tune_native))
    return CPU_NATIVE;

  /* Fill cpucfg_cache with the "cpucfg" instruction.  */
  cache_cpucfg ();


  /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].base
     With: base architecture (ARCH)
     At:   cpucfg_words[1][1:0] */

  #define NATIVE_BASE_ISA (loongarch_cpu_default_isa[CPU_NATIVE].base)
  switch (cpucfg_cache[1] & 0x3)
    {
      case 0x02:
	NATIVE_BASE_ISA = ISA_BASE_LA64V100;
	break;

      default:
	if (p_arch_native)
	  fatal_error (UNKNOWN_LOCATION,
		       "unknown base architecture %<0x%x%>, %qs failed",
		       (unsigned int) (cpucfg_cache[1] & 0x3),
		       "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
    }

  /* Fill: loongarch_cpu_default_isa[CPU_NATIVE].fpu
     With: FPU type (FP, FP_SP, FP_DP)
     At:   cpucfg_words[2][2:0] */

  #define NATIVE_FPU (loongarch_cpu_default_isa[CPU_NATIVE].fpu)
  switch (cpucfg_cache[2] & 0x7)
    {
      case 0x07:
	NATIVE_FPU = ISA_EXT_FPU64;
	break;

      case 0x03:
	NATIVE_FPU = ISA_EXT_FPU32;
	break;

      case 0x00:
	NATIVE_FPU = ISA_EXT_NOFPU;
	break;

      default:
	if (p_arch_native)
	  fatal_error (UNKNOWN_LOCATION,
		       "unknown FPU type %<0x%x%>, %qs failed",
		       (unsigned int) (cpucfg_cache[2] & 0x7),
		       "-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
    }

  /* Fill: loongarch_cpu_cache[CPU_NATIVE]
     With: cache size info
     At:   cpucfg_words[16:20][31:0] */

  int l1d_present = 0, l1u_present = 0;
  int l2d_present = 0;
  uint32_t l1_szword, l2_szword;

  l1u_present |= cpucfg_cache[16] & 3;	      /* bit[1:0]: unified l1 cache */
  l1d_present |= cpucfg_cache[16] & 4;	      /* bit[2:2]: l1 dcache */
  l1_szword = l1d_present ? 18 : (l1u_present ? 17 : 0);
  l1_szword = l1_szword ? cpucfg_cache[l1_szword]: 0;

  l2d_present |= cpucfg_cache[16] & 24;	      /* bit[4:3]: unified l2 cache */
  l2d_present |= cpucfg_cache[16] & 128;      /* bit[7:7]: l2 dcache */
  l2_szword = l2d_present ? cpucfg_cache[19]: 0;

  loongarch_cpu_cache[CPU_NATIVE].l1d_line_size
    = 1 << ((l1_szword & 0x7f000000) >> 24);  /* bit[30:24]: log2(linesize) */

  loongarch_cpu_cache[CPU_NATIVE].l1d_size
    = (1 << ((l1_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
    * ((l1_szword & 0x0000ffff) + 1)	      /* bit[15:0]:  sets - 1 */
    * (1 << ((l1_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */
    >> 10;				      /* in kilobytes */

  loongarch_cpu_cache[CPU_NATIVE].l2d_size
    = (1 << ((l2_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
    * ((l2_szword & 0x0000ffff) + 1)	      /* bit[15:0]:  sets - 1 */
    * (1 << ((l2_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */
    >> 10;				      /* in kilobytes */

  /* Fill: ret_cpu_type
     With: processor ID (PRID)
     At:   cpucfg_words[0][31:0] */

  switch (cpucfg_cache[0] & 0x00ffff00)
  {
    case 0x0014c000:   /* LA464 */
      ret_cpu_type = CPU_LA464;
      break;

    default:
      /* Unknown PRID.  This is generally harmless as long as
	 the properties above can be obtained via "cpucfg".  */
      if (p_tune_native)
	inform (UNKNOWN_LOCATION, "unknown processor ID %<0x%x%>, "
		"some tuning parameters will fall back to default",
		cpucfg_cache[0]);
      break;
  }

  /* Properties that cannot be looked up directly using cpucfg.  */
  loongarch_cpu_issue_rate[CPU_NATIVE]
    = loongarch_cpu_issue_rate[ret_cpu_type];

  loongarch_cpu_multipass_dfa_lookahead[CPU_NATIVE]
    = loongarch_cpu_multipass_dfa_lookahead[ret_cpu_type];

  loongarch_cpu_rtx_cost_data[CPU_NATIVE]
    = loongarch_cpu_rtx_cost_data[ret_cpu_type];

  return ret_cpu_type;
}