]>
Commit | Line | Data |
---|---|---|
228021f0 SG |
1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
2 | /* | |
3 | * QEMU LoongArch CPU | |
4 | * | |
5 | * Copyright (c) 2021 Loongson Technology Corporation Limited | |
6 | */ | |
7 | ||
8 | #ifndef LOONGARCH_CPU_H | |
9 | #define LOONGARCH_CPU_H | |
10 | ||
16f5396c | 11 | #include "qemu/int128.h" |
228021f0 SG |
12 | #include "exec/cpu-defs.h" |
13 | #include "fpu/softfloat-types.h" | |
14 | #include "hw/registerfields.h" | |
dd615fa4 | 15 | #include "qemu/timer.h" |
8f15d617 | 16 | #ifndef CONFIG_USER_ONLY |
f84a2aac | 17 | #include "exec/memory.h" |
8f15d617 | 18 | #endif |
b4bda200 | 19 | #include "cpu-csr.h" |
f84a2aac XY |
20 | |
21 | #define IOCSRF_TEMP 0 | |
22 | #define IOCSRF_NODECNT 1 | |
23 | #define IOCSRF_MSI 2 | |
24 | #define IOCSRF_EXTIOI 3 | |
25 | #define IOCSRF_CSRIPI 4 | |
26 | #define IOCSRF_FREQCSR 5 | |
27 | #define IOCSRF_FREQSCALE 6 | |
28 | #define IOCSRF_DVFSV1 7 | |
29 | #define IOCSRF_GMOD 9 | |
30 | #define IOCSRF_VM 11 | |
31 | ||
c77432d0 | 32 | #define VERSION_REG 0x0 |
f84a2aac XY |
33 | #define FEATURE_REG 0x8 |
34 | #define VENDOR_REG 0x10 | |
35 | #define CPUNAME_REG 0x20 | |
36 | #define MISC_FUNC_REG 0x420 | |
37 | #define IOCSRM_EXTIOI_EN 48 | |
38 | ||
39 | #define IOCSR_MEM_SIZE 0x428 | |
228021f0 SG |
40 | |
41 | #define TCG_GUEST_DEFAULT_MO (0) | |
42 | ||
43 | #define FCSR0_M1 0x1f /* FCSR1 mask, Enables */ | |
44 | #define FCSR0_M2 0x1f1f0000 /* FCSR2 mask, Cause and Flags */ | |
45 | #define FCSR0_M3 0x300 /* FCSR3 mask, Round Mode */ | |
46 | #define FCSR0_RM 8 /* Round Mode bit num on fcsr0 */ | |
47 | ||
48 | FIELD(FCSR0, ENABLES, 0, 5) | |
49 | FIELD(FCSR0, RM, 8, 2) | |
50 | FIELD(FCSR0, FLAGS, 16, 5) | |
51 | FIELD(FCSR0, CAUSE, 24, 5) | |
52 | ||
53 | #define GET_FP_CAUSE(REG) FIELD_EX32(REG, FCSR0, CAUSE) | |
00952d93 QH |
54 | #define SET_FP_CAUSE(REG, V) \ |
55 | do { \ | |
56 | (REG) = FIELD_DP32(REG, FCSR0, CAUSE, V); \ | |
57 | } while (0) | |
aca67472 SG |
58 | #define UPDATE_FP_CAUSE(REG, V) \ |
59 | do { \ | |
60 | (REG) |= FIELD_DP32(0, FCSR0, CAUSE, V); \ | |
61 | } while (0) | |
00952d93 | 62 | |
228021f0 | 63 | #define GET_FP_ENABLES(REG) FIELD_EX32(REG, FCSR0, ENABLES) |
00952d93 QH |
64 | #define SET_FP_ENABLES(REG, V) \ |
65 | do { \ | |
66 | (REG) = FIELD_DP32(REG, FCSR0, ENABLES, V); \ | |
67 | } while (0) | |
68 | ||
228021f0 | 69 | #define GET_FP_FLAGS(REG) FIELD_EX32(REG, FCSR0, FLAGS) |
00952d93 QH |
70 | #define SET_FP_FLAGS(REG, V) \ |
71 | do { \ | |
72 | (REG) = FIELD_DP32(REG, FCSR0, FLAGS, V); \ | |
73 | } while (0) | |
74 | ||
228021f0 SG |
75 | #define UPDATE_FP_FLAGS(REG, V) \ |
76 | do { \ | |
77 | (REG) |= FIELD_DP32(0, FCSR0, FLAGS, V); \ | |
78 | } while (0) | |
79 | ||
80 | #define FP_INEXACT 1 | |
81 | #define FP_UNDERFLOW 2 | |
82 | #define FP_OVERFLOW 4 | |
83 | #define FP_DIV0 8 | |
84 | #define FP_INVALID 16 | |
85 | ||
a6b129c8 SG |
86 | #define EXCODE(code, subcode) ( ((subcode) << 6) | (code) ) |
87 | #define EXCODE_MCODE(code) ( (code) & 0x3f ) | |
88 | #define EXCODE_SUBCODE(code) ( (code) >> 6 ) | |
89 | ||
90 | #define EXCCODE_EXTERNAL_INT 64 /* plus external interrupt number */ | |
91 | #define EXCCODE_INT EXCODE(0, 0) | |
92 | #define EXCCODE_PIL EXCODE(1, 0) | |
93 | #define EXCCODE_PIS EXCODE(2, 0) | |
94 | #define EXCCODE_PIF EXCODE(3, 0) | |
95 | #define EXCCODE_PME EXCODE(4, 0) | |
96 | #define EXCCODE_PNR EXCODE(5, 0) | |
97 | #define EXCCODE_PNX EXCODE(6, 0) | |
98 | #define EXCCODE_PPI EXCODE(7, 0) | |
99 | #define EXCCODE_ADEF EXCODE(8, 0) /* Different exception subcode */ | |
100 | #define EXCCODE_ADEM EXCODE(8, 1) | |
101 | #define EXCCODE_ALE EXCODE(9, 0) | |
102 | #define EXCCODE_BCE EXCODE(10, 0) | |
103 | #define EXCCODE_SYS EXCODE(11, 0) | |
104 | #define EXCCODE_BRK EXCODE(12, 0) | |
105 | #define EXCCODE_INE EXCODE(13, 0) | |
106 | #define EXCCODE_IPE EXCODE(14, 0) | |
107 | #define EXCCODE_FPD EXCODE(15, 0) | |
108 | #define EXCCODE_SXD EXCODE(16, 0) | |
109 | #define EXCCODE_ASXD EXCODE(17, 0) | |
110 | #define EXCCODE_FPE EXCODE(18, 0) /* Different exception subcode */ | |
111 | #define EXCCODE_VFPE EXCODE(18, 1) | |
112 | #define EXCCODE_WPEF EXCODE(19, 0) /* Different exception subcode */ | |
113 | #define EXCCODE_WPEM EXCODE(19, 1) | |
114 | #define EXCCODE_BTD EXCODE(20, 0) | |
115 | #define EXCCODE_BTE EXCODE(21, 0) | |
116 | #define EXCCODE_DBP EXCODE(26, 0) /* Reserved subcode used for debug */ | |
228021f0 SG |
117 | |
118 | /* cpucfg[0] bits */ | |
119 | FIELD(CPUCFG0, PRID, 0, 32) | |
120 | ||
121 | /* cpucfg[1] bits */ | |
122 | FIELD(CPUCFG1, ARCH, 0, 2) | |
123 | FIELD(CPUCFG1, PGMMU, 2, 1) | |
124 | FIELD(CPUCFG1, IOCSR, 3, 1) | |
125 | FIELD(CPUCFG1, PALEN, 4, 8) | |
126 | FIELD(CPUCFG1, VALEN, 12, 8) | |
127 | FIELD(CPUCFG1, UAL, 20, 1) | |
128 | FIELD(CPUCFG1, RI, 21, 1) | |
129 | FIELD(CPUCFG1, EP, 22, 1) | |
130 | FIELD(CPUCFG1, RPLV, 23, 1) | |
131 | FIELD(CPUCFG1, HP, 24, 1) | |
132 | FIELD(CPUCFG1, IOCSR_BRD, 25, 1) | |
133 | FIELD(CPUCFG1, MSG_INT, 26, 1) | |
134 | ||
19f82a4a JC |
135 | /* cpucfg[1].arch */ |
136 | #define CPUCFG1_ARCH_LA32R 0 | |
137 | #define CPUCFG1_ARCH_LA32 1 | |
138 | #define CPUCFG1_ARCH_LA64 2 | |
139 | ||
228021f0 SG |
140 | /* cpucfg[2] bits */ |
141 | FIELD(CPUCFG2, FP, 0, 1) | |
142 | FIELD(CPUCFG2, FP_SP, 1, 1) | |
143 | FIELD(CPUCFG2, FP_DP, 2, 1) | |
144 | FIELD(CPUCFG2, FP_VER, 3, 3) | |
145 | FIELD(CPUCFG2, LSX, 6, 1) | |
146 | FIELD(CPUCFG2, LASX, 7, 1) | |
147 | FIELD(CPUCFG2, COMPLEX, 8, 1) | |
148 | FIELD(CPUCFG2, CRYPTO, 9, 1) | |
149 | FIELD(CPUCFG2, LVZ, 10, 1) | |
150 | FIELD(CPUCFG2, LVZ_VER, 11, 3) | |
151 | FIELD(CPUCFG2, LLFTP, 14, 1) | |
152 | FIELD(CPUCFG2, LLFTP_VER, 15, 3) | |
153 | FIELD(CPUCFG2, LBT_X86, 18, 1) | |
154 | FIELD(CPUCFG2, LBT_ARM, 19, 1) | |
155 | FIELD(CPUCFG2, LBT_MIPS, 20, 1) | |
156 | FIELD(CPUCFG2, LSPW, 21, 1) | |
157 | FIELD(CPUCFG2, LAM, 22, 1) | |
158 | ||
159 | /* cpucfg[3] bits */ | |
160 | FIELD(CPUCFG3, CCDMA, 0, 1) | |
161 | FIELD(CPUCFG3, SFB, 1, 1) | |
162 | FIELD(CPUCFG3, UCACC, 2, 1) | |
163 | FIELD(CPUCFG3, LLEXC, 3, 1) | |
164 | FIELD(CPUCFG3, SCDLY, 4, 1) | |
165 | FIELD(CPUCFG3, LLDBAR, 5, 1) | |
166 | FIELD(CPUCFG3, ITLBHMC, 6, 1) | |
167 | FIELD(CPUCFG3, ICHMC, 7, 1) | |
168 | FIELD(CPUCFG3, SPW_LVL, 8, 3) | |
169 | FIELD(CPUCFG3, SPW_HP_HF, 11, 1) | |
170 | FIELD(CPUCFG3, RVA, 12, 1) | |
171 | FIELD(CPUCFG3, RVAMAX, 13, 4) | |
172 | ||
173 | /* cpucfg[4] bits */ | |
174 | FIELD(CPUCFG4, CC_FREQ, 0, 32) | |
175 | ||
176 | /* cpucfg[5] bits */ | |
177 | FIELD(CPUCFG5, CC_MUL, 0, 16) | |
178 | FIELD(CPUCFG5, CC_DIV, 16, 16) | |
179 | ||
180 | /* cpucfg[6] bits */ | |
181 | FIELD(CPUCFG6, PMP, 0, 1) | |
182 | FIELD(CPUCFG6, PMVER, 1, 3) | |
183 | FIELD(CPUCFG6, PMNUM, 4, 4) | |
184 | FIELD(CPUCFG6, PMBITS, 8, 6) | |
185 | FIELD(CPUCFG6, UPM, 14, 1) | |
186 | ||
187 | /* cpucfg[16] bits */ | |
188 | FIELD(CPUCFG16, L1_IUPRE, 0, 1) | |
189 | FIELD(CPUCFG16, L1_IUUNIFY, 1, 1) | |
190 | FIELD(CPUCFG16, L1_DPRE, 2, 1) | |
191 | FIELD(CPUCFG16, L2_IUPRE, 3, 1) | |
192 | FIELD(CPUCFG16, L2_IUUNIFY, 4, 1) | |
193 | FIELD(CPUCFG16, L2_IUPRIV, 5, 1) | |
194 | FIELD(CPUCFG16, L2_IUINCL, 6, 1) | |
195 | FIELD(CPUCFG16, L2_DPRE, 7, 1) | |
196 | FIELD(CPUCFG16, L2_DPRIV, 8, 1) | |
197 | FIELD(CPUCFG16, L2_DINCL, 9, 1) | |
198 | FIELD(CPUCFG16, L3_IUPRE, 10, 1) | |
199 | FIELD(CPUCFG16, L3_IUUNIFY, 11, 1) | |
200 | FIELD(CPUCFG16, L3_IUPRIV, 12, 1) | |
201 | FIELD(CPUCFG16, L3_IUINCL, 13, 1) | |
202 | FIELD(CPUCFG16, L3_DPRE, 14, 1) | |
203 | FIELD(CPUCFG16, L3_DPRIV, 15, 1) | |
204 | FIELD(CPUCFG16, L3_DINCL, 16, 1) | |
205 | ||
206 | /* cpucfg[17] bits */ | |
207 | FIELD(CPUCFG17, L1IU_WAYS, 0, 16) | |
208 | FIELD(CPUCFG17, L1IU_SETS, 16, 8) | |
209 | FIELD(CPUCFG17, L1IU_SIZE, 24, 7) | |
210 | ||
211 | /* cpucfg[18] bits */ | |
212 | FIELD(CPUCFG18, L1D_WAYS, 0, 16) | |
213 | FIELD(CPUCFG18, L1D_SETS, 16, 8) | |
214 | FIELD(CPUCFG18, L1D_SIZE, 24, 7) | |
215 | ||
216 | /* cpucfg[19] bits */ | |
217 | FIELD(CPUCFG19, L2IU_WAYS, 0, 16) | |
218 | FIELD(CPUCFG19, L2IU_SETS, 16, 8) | |
219 | FIELD(CPUCFG19, L2IU_SIZE, 24, 7) | |
220 | ||
221 | /* cpucfg[20] bits */ | |
222 | FIELD(CPUCFG20, L3IU_WAYS, 0, 16) | |
223 | FIELD(CPUCFG20, L3IU_SETS, 16, 8) | |
224 | FIELD(CPUCFG20, L3IU_SIZE, 24, 7) | |
225 | ||
398cecb9 XY |
226 | /*CSR_CRMD */ |
227 | FIELD(CSR_CRMD, PLV, 0, 2) | |
228 | FIELD(CSR_CRMD, IE, 2, 1) | |
229 | FIELD(CSR_CRMD, DA, 3, 1) | |
230 | FIELD(CSR_CRMD, PG, 4, 1) | |
231 | FIELD(CSR_CRMD, DATF, 5, 2) | |
232 | FIELD(CSR_CRMD, DATM, 7, 2) | |
233 | FIELD(CSR_CRMD, WE, 9, 1) | |
234 | ||
228021f0 SG |
235 | extern const char * const regnames[32]; |
236 | extern const char * const fregnames[32]; | |
237 | ||
f757a2cd | 238 | #define N_IRQS 13 |
dd615fa4 XY |
239 | #define IRQ_TIMER 11 |
240 | #define IRQ_IPI 12 | |
f757a2cd | 241 | |
7e1c521e XY |
242 | #define LOONGARCH_STLB 2048 /* 2048 STLB */ |
243 | #define LOONGARCH_MTLB 64 /* 64 MTLB */ | |
244 | #define LOONGARCH_TLB_MAX (LOONGARCH_STLB + LOONGARCH_MTLB) | |
245 | ||
246 | /* | |
247 | * define the ASID PS E VPPN field of TLB | |
248 | */ | |
249 | FIELD(TLB_MISC, E, 0, 1) | |
250 | FIELD(TLB_MISC, ASID, 1, 10) | |
251 | FIELD(TLB_MISC, VPPN, 13, 35) | |
252 | FIELD(TLB_MISC, PS, 48, 6) | |
253 | ||
008a3b16 SG |
254 | #define LSX_LEN (128) |
255 | #define LASX_LEN (256) | |
256 | ||
16f5396c | 257 | typedef union VReg { |
008a3b16 SG |
258 | int8_t B[LASX_LEN / 8]; |
259 | int16_t H[LASX_LEN / 16]; | |
260 | int32_t W[LASX_LEN / 32]; | |
261 | int64_t D[LASX_LEN / 64]; | |
262 | uint8_t UB[LASX_LEN / 8]; | |
263 | uint16_t UH[LASX_LEN / 16]; | |
264 | uint32_t UW[LASX_LEN / 32]; | |
265 | uint64_t UD[LASX_LEN / 64]; | |
266 | Int128 Q[LASX_LEN / 128]; | |
267 | } VReg; | |
16f5396c SG |
268 | |
269 | typedef union fpr_t fpr_t; | |
270 | union fpr_t { | |
271 | VReg vreg; | |
272 | }; | |
273 | ||
7e1c521e XY |
274 | struct LoongArchTLB { |
275 | uint64_t tlb_misc; | |
276 | /* Fields corresponding to CSR_TLBELO0/1 */ | |
277 | uint64_t tlb_entry0; | |
278 | uint64_t tlb_entry1; | |
279 | }; | |
280 | typedef struct LoongArchTLB LoongArchTLB; | |
281 | ||
228021f0 SG |
282 | typedef struct CPUArchState { |
283 | uint64_t gpr[32]; | |
284 | uint64_t pc; | |
285 | ||
16f5396c | 286 | fpr_t fpr[32]; |
228021f0 SG |
287 | float_status fp_status; |
288 | bool cf[8]; | |
289 | ||
290 | uint32_t fcsr0; | |
291 | uint32_t fcsr0_mask; | |
292 | ||
293 | uint32_t cpucfg[21]; | |
294 | ||
295 | uint64_t lladdr; /* LL virtual address compared against SC */ | |
296 | uint64_t llval; | |
297 | ||
398cecb9 XY |
298 | /* LoongArch CSRs */ |
299 | uint64_t CSR_CRMD; | |
300 | uint64_t CSR_PRMD; | |
301 | uint64_t CSR_EUEN; | |
302 | uint64_t CSR_MISC; | |
303 | uint64_t CSR_ECFG; | |
304 | uint64_t CSR_ESTAT; | |
305 | uint64_t CSR_ERA; | |
306 | uint64_t CSR_BADV; | |
307 | uint64_t CSR_BADI; | |
308 | uint64_t CSR_EENTRY; | |
309 | uint64_t CSR_TLBIDX; | |
310 | uint64_t CSR_TLBEHI; | |
311 | uint64_t CSR_TLBELO0; | |
312 | uint64_t CSR_TLBELO1; | |
313 | uint64_t CSR_ASID; | |
314 | uint64_t CSR_PGDL; | |
315 | uint64_t CSR_PGDH; | |
316 | uint64_t CSR_PGD; | |
317 | uint64_t CSR_PWCL; | |
318 | uint64_t CSR_PWCH; | |
319 | uint64_t CSR_STLBPS; | |
320 | uint64_t CSR_RVACFG; | |
321 | uint64_t CSR_PRCFG1; | |
322 | uint64_t CSR_PRCFG2; | |
323 | uint64_t CSR_PRCFG3; | |
324 | uint64_t CSR_SAVE[16]; | |
325 | uint64_t CSR_TID; | |
326 | uint64_t CSR_TCFG; | |
327 | uint64_t CSR_TVAL; | |
328 | uint64_t CSR_CNTC; | |
329 | uint64_t CSR_TICLR; | |
330 | uint64_t CSR_LLBCTL; | |
331 | uint64_t CSR_IMPCTL1; | |
332 | uint64_t CSR_IMPCTL2; | |
333 | uint64_t CSR_TLBRENTRY; | |
334 | uint64_t CSR_TLBRBADV; | |
335 | uint64_t CSR_TLBRERA; | |
336 | uint64_t CSR_TLBRSAVE; | |
337 | uint64_t CSR_TLBRELO0; | |
338 | uint64_t CSR_TLBRELO1; | |
339 | uint64_t CSR_TLBREHI; | |
340 | uint64_t CSR_TLBRPRMD; | |
341 | uint64_t CSR_MERRCTL; | |
342 | uint64_t CSR_MERRINFO1; | |
343 | uint64_t CSR_MERRINFO2; | |
344 | uint64_t CSR_MERRENTRY; | |
345 | uint64_t CSR_MERRERA; | |
346 | uint64_t CSR_MERRSAVE; | |
347 | uint64_t CSR_CTAG; | |
348 | uint64_t CSR_DMW[4]; | |
349 | uint64_t CSR_DBG; | |
350 | uint64_t CSR_DERA; | |
351 | uint64_t CSR_DSAVE; | |
c34ad459 | 352 | uint64_t CSR_CPUID; |
7e1c521e | 353 | |
0093b9a5 | 354 | #ifndef CONFIG_USER_ONLY |
7e1c521e | 355 | LoongArchTLB tlb[LOONGARCH_TLB_MAX]; |
f84a2aac XY |
356 | |
357 | AddressSpace address_space_iocsr; | |
358 | MemoryRegion system_iocsr; | |
359 | MemoryRegion iocsr_mem; | |
6a6f26f4 XY |
360 | bool load_elf; |
361 | uint64_t elf_address; | |
758a7475 TZ |
362 | /* Store ipistate to access from this struct */ |
363 | DeviceState *ipistate; | |
0093b9a5 | 364 | #endif |
228021f0 SG |
365 | } CPULoongArchState; |
366 | ||
367 | /** | |
368 | * LoongArchCPU: | |
369 | * @env: #CPULoongArchState | |
370 | * | |
371 | * A LoongArch CPU. | |
372 | */ | |
373 | struct ArchCPU { | |
374 | /*< private >*/ | |
375 | CPUState parent_obj; | |
376 | /*< public >*/ | |
377 | ||
228021f0 | 378 | CPULoongArchState env; |
dd615fa4 | 379 | QEMUTimer timer; |
14f21f67 | 380 | uint32_t phy_id; |
fda3f15b XY |
381 | |
382 | /* 'compatible' string for this CPU for Linux device trees */ | |
383 | const char *dtb_compatible; | |
228021f0 SG |
384 | }; |
385 | ||
386 | #define TYPE_LOONGARCH_CPU "loongarch-cpu" | |
6cbba3e9 | 387 | #define TYPE_LOONGARCH32_CPU "loongarch32-cpu" |
146f2354 | 388 | #define TYPE_LOONGARCH64_CPU "loongarch64-cpu" |
228021f0 SG |
389 | |
390 | OBJECT_DECLARE_CPU_TYPE(LoongArchCPU, LoongArchCPUClass, | |
391 | LOONGARCH_CPU) | |
392 | ||
393 | /** | |
394 | * LoongArchCPUClass: | |
395 | * @parent_realize: The parent class' realize handler. | |
f78b49ae | 396 | * @parent_phases: The parent class' reset phase handlers. |
228021f0 SG |
397 | * |
398 | * A LoongArch CPU model. | |
399 | */ | |
400 | struct LoongArchCPUClass { | |
401 | /*< private >*/ | |
402 | CPUClass parent_class; | |
403 | /*< public >*/ | |
404 | ||
405 | DeviceRealize parent_realize; | |
f78b49ae | 406 | ResettablePhases parent_phases; |
228021f0 SG |
407 | }; |
408 | ||
7e1c521e XY |
409 | /* |
410 | * LoongArch CPUs has 4 privilege levels. | |
411 | * 0 for kernel mode, 3 for user mode. | |
412 | * Define an extra index for DA(direct addressing) mode. | |
413 | */ | |
c8885b88 RW |
414 | #define MMU_PLV_KERNEL 0 |
415 | #define MMU_PLV_USER 3 | |
416 | #define MMU_IDX_KERNEL MMU_PLV_KERNEL | |
417 | #define MMU_IDX_USER MMU_PLV_USER | |
418 | #define MMU_IDX_DA 4 | |
7e1c521e XY |
419 | |
420 | static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch) | |
421 | { | |
0093b9a5 | 422 | #ifdef CONFIG_USER_ONLY |
c8885b88 | 423 | return MMU_IDX_USER; |
0093b9a5 | 424 | #else |
c8885b88 RW |
425 | if (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG)) { |
426 | return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); | |
7e1c521e | 427 | } |
c8885b88 | 428 | return MMU_IDX_DA; |
0093b9a5 | 429 | #endif |
7e1c521e XY |
430 | } |
431 | ||
19f82a4a JC |
432 | static inline bool is_la64(CPULoongArchState *env) |
433 | { | |
434 | return FIELD_EX32(env->cpucfg[1], CPUCFG1, ARCH) == CPUCFG1_ARCH_LA64; | |
435 | } | |
436 | ||
39665820 JC |
437 | static inline bool is_va32(CPULoongArchState *env) |
438 | { | |
439 | /* VA32 if !LA64 or VA32L[1-3] */ | |
440 | bool va32 = !is_la64(env); | |
441 | uint64_t plv = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV); | |
442 | if (plv >= 1 && (FIELD_EX64(env->CSR_MISC, CSR_MISC, VA32) & (1 << plv))) { | |
443 | va32 = true; | |
444 | } | |
445 | return va32; | |
446 | } | |
447 | ||
2f6478ff JC |
448 | static inline void set_pc(CPULoongArchState *env, uint64_t value) |
449 | { | |
7033c0e6 JC |
450 | if (is_va32(env)) { |
451 | env->pc = (uint32_t)value; | |
452 | } else { | |
453 | env->pc = value; | |
454 | } | |
2f6478ff JC |
455 | } |
456 | ||
b4bda200 RW |
457 | /* |
458 | * LoongArch CPUs hardware flags. | |
459 | */ | |
460 | #define HW_FLAGS_PLV_MASK R_CSR_CRMD_PLV_MASK /* 0x03 */ | |
461 | #define HW_FLAGS_CRMD_PG R_CSR_CRMD_PG_MASK /* 0x10 */ | |
2419978c | 462 | #define HW_FLAGS_EUEN_FPE 0x04 |
a3f3db5c | 463 | #define HW_FLAGS_EUEN_SXE 0x08 |
b8f1bdf3 | 464 | #define HW_FLAGS_EUEN_ASXE 0x10 |
39665820 | 465 | #define HW_FLAGS_VA32 0x20 |
b4bda200 | 466 | |
bb5de525 AJ |
467 | static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, vaddr *pc, |
468 | uint64_t *cs_base, uint32_t *flags) | |
7e1c521e XY |
469 | { |
470 | *pc = env->pc; | |
471 | *cs_base = 0; | |
b4bda200 | 472 | *flags = env->CSR_CRMD & (R_CSR_CRMD_PLV_MASK | R_CSR_CRMD_PG_MASK); |
2419978c | 473 | *flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, FPE) * HW_FLAGS_EUEN_FPE; |
a3f3db5c | 474 | *flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE) * HW_FLAGS_EUEN_SXE; |
b8f1bdf3 | 475 | *flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE) * HW_FLAGS_EUEN_ASXE; |
39665820 | 476 | *flags |= is_va32(env) * HW_FLAGS_VA32; |
7e1c521e XY |
477 | } |
478 | ||
228021f0 SG |
479 | void loongarch_cpu_list(void); |
480 | ||
481 | #define cpu_list loongarch_cpu_list | |
482 | ||
483 | #include "exec/cpu-all.h" | |
484 | ||
485 | #define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU | |
486 | #define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX | |
487 | #define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU | |
488 | ||
489 | #endif /* LOONGARCH_CPU_H */ |