1 /* SPDX-License-Identifier: GPL-2.0-or-later */
5 * Copyright (c) 2021 Loongson Technology Corporation Limited
8 #include "qemu/osdep.h"
10 #include "qemu/qemu-print.h"
11 #include "qapi/error.h"
12 #include "qemu/module.h"
13 #include "sysemu/qtest.h"
14 #include "exec/exec-all.h"
15 #include "qapi/qapi-commands-machine-target.h"
17 #include "internals.h"
18 #include "fpu/softfloat-helpers.h"
20 const char * const regnames[32] = {
21 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
22 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
23 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
24 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
27 const char * const fregnames[32] = {
28 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
29 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
30 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
31 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
34 static const char * const excp_names[] = {
35 [EXCCODE_INT] = "Interrupt",
36 [EXCCODE_PIL] = "Page invalid exception for load",
37 [EXCCODE_PIS] = "Page invalid exception for store",
38 [EXCCODE_PIF] = "Page invalid exception for fetch",
39 [EXCCODE_PME] = "Page modified exception",
40 [EXCCODE_PNR] = "Page Not Readable exception",
41 [EXCCODE_PNX] = "Page Not Executable exception",
42 [EXCCODE_PPI] = "Page Privilege error",
43 [EXCCODE_ADEF] = "Address error for instruction fetch",
44 [EXCCODE_ADEM] = "Address error for Memory access",
45 [EXCCODE_SYS] = "Syscall",
46 [EXCCODE_BRK] = "Break",
47 [EXCCODE_INE] = "Instruction Non-Existent",
48 [EXCCODE_IPE] = "Instruction privilege error",
49 [EXCCODE_FPE] = "Floating Point Exception",
50 [EXCCODE_DBP] = "Debug breakpoint",
53 const char *loongarch_exception_name(int32_t exception)
55 assert(excp_names[exception]);
56 return excp_names[exception];
59 void G_NORETURN do_raise_exception(CPULoongArchState *env,
63 CPUState *cs = env_cpu(env);
65 qemu_log_mask(CPU_LOG_INT, "%s: %d (%s)\n",
68 loongarch_exception_name(exception));
69 cs->exception_index = exception;
71 cpu_loop_exit_restore(cs, pc);
74 static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
76 LoongArchCPU *cpu = LOONGARCH_CPU(cs);
77 CPULoongArchState *env = &cpu->env;
83 static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
84 const TranslationBlock *tb)
86 LoongArchCPU *cpu = LOONGARCH_CPU(cs);
87 CPULoongArchState *env = &cpu->env;
91 #endif /* CONFIG_TCG */
93 static void loongarch_la464_initfn(Object *obj)
95 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
96 CPULoongArchState *env = &cpu->env;
99 for (i = 0; i < 21; i++) {
100 env->cpucfg[i] = 0x0;
103 env->cpucfg[0] = 0x14c010; /* PRID */
106 data = FIELD_DP32(data, CPUCFG1, ARCH, 2);
107 data = FIELD_DP32(data, CPUCFG1, PGMMU, 1);
108 data = FIELD_DP32(data, CPUCFG1, IOCSR, 1);
109 data = FIELD_DP32(data, CPUCFG1, PALEN, 0x2f);
110 data = FIELD_DP32(data, CPUCFG1, VALEN, 0x2f);
111 data = FIELD_DP32(data, CPUCFG1, UAL, 1);
112 data = FIELD_DP32(data, CPUCFG1, RI, 1);
113 data = FIELD_DP32(data, CPUCFG1, EP, 1);
114 data = FIELD_DP32(data, CPUCFG1, RPLV, 1);
115 data = FIELD_DP32(data, CPUCFG1, HP, 1);
116 data = FIELD_DP32(data, CPUCFG1, IOCSR_BRD, 1);
117 env->cpucfg[1] = data;
120 data = FIELD_DP32(data, CPUCFG2, FP, 1);
121 data = FIELD_DP32(data, CPUCFG2, FP_SP, 1);
122 data = FIELD_DP32(data, CPUCFG2, FP_DP, 1);
123 data = FIELD_DP32(data, CPUCFG2, FP_VER, 1);
124 data = FIELD_DP32(data, CPUCFG2, LLFTP, 1);
125 data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1);
126 data = FIELD_DP32(data, CPUCFG2, LAM, 1);
127 env->cpucfg[2] = data;
129 env->cpucfg[4] = 100 * 1000 * 1000; /* Crystal frequency */
132 data = FIELD_DP32(data, CPUCFG5, CC_MUL, 1);
133 data = FIELD_DP32(data, CPUCFG5, CC_DIV, 1);
134 env->cpucfg[5] = data;
137 data = FIELD_DP32(data, CPUCFG16, L1_IUPRE, 1);
138 data = FIELD_DP32(data, CPUCFG16, L1_DPRE, 1);
139 data = FIELD_DP32(data, CPUCFG16, L2_IUPRE, 1);
140 data = FIELD_DP32(data, CPUCFG16, L2_IUUNIFY, 1);
141 data = FIELD_DP32(data, CPUCFG16, L2_IUPRIV, 1);
142 data = FIELD_DP32(data, CPUCFG16, L3_IUPRE, 1);
143 data = FIELD_DP32(data, CPUCFG16, L3_IUUNIFY, 1);
144 data = FIELD_DP32(data, CPUCFG16, L3_IUINCL, 1);
145 env->cpucfg[16] = data;
148 data = FIELD_DP32(data, CPUCFG17, L1IU_WAYS, 3);
149 data = FIELD_DP32(data, CPUCFG17, L1IU_SETS, 8);
150 data = FIELD_DP32(data, CPUCFG17, L1IU_SIZE, 6);
151 env->cpucfg[17] = data;
154 data = FIELD_DP32(data, CPUCFG18, L1D_WAYS, 3);
155 data = FIELD_DP32(data, CPUCFG18, L1D_SETS, 8);
156 data = FIELD_DP32(data, CPUCFG18, L1D_SIZE, 6);
157 env->cpucfg[18] = data;
160 data = FIELD_DP32(data, CPUCFG19, L2IU_WAYS, 15);
161 data = FIELD_DP32(data, CPUCFG19, L2IU_SETS, 8);
162 data = FIELD_DP32(data, CPUCFG19, L2IU_SIZE, 6);
163 env->cpucfg[19] = data;
166 data = FIELD_DP32(data, CPUCFG20, L3IU_WAYS, 15);
167 data = FIELD_DP32(data, CPUCFG20, L3IU_SETS, 14);
168 data = FIELD_DP32(data, CPUCFG20, L3IU_SETS, 6);
169 env->cpucfg[20] = data;
172 static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
174 const char *typename = object_class_get_name(OBJECT_CLASS(data));
176 qemu_printf("%s\n", typename);
179 void loongarch_cpu_list(void)
182 list = object_class_get_list_sorted(TYPE_LOONGARCH_CPU, false);
183 g_slist_foreach(list, loongarch_cpu_list_entry, NULL);
187 static void loongarch_cpu_reset(DeviceState *dev)
189 CPUState *cs = CPU(dev);
190 LoongArchCPU *cpu = LOONGARCH_CPU(cs);
191 LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(cpu);
192 CPULoongArchState *env = &cpu->env;
194 lacc->parent_reset(dev);
196 env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
199 cs->exception_index = -1;
202 static void loongarch_cpu_disas_set_info(CPUState *s, disassemble_info *info)
204 info->print_insn = print_insn_loongarch;
207 static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
209 CPUState *cs = CPU(dev);
210 LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev);
211 Error *local_err = NULL;
213 cpu_exec_realizefn(cs, &local_err);
214 if (local_err != NULL) {
215 error_propagate(errp, local_err);
222 lacc->parent_realize(dev, errp);
225 static void loongarch_cpu_init(Object *obj)
227 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
229 cpu_set_cpustate_pointers(cpu);
232 static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
237 typename = g_strdup_printf(LOONGARCH_CPU_TYPE_NAME("%s"), cpu_model);
238 oc = object_class_by_name(typename);
243 void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
245 LoongArchCPU *cpu = LOONGARCH_CPU(cs);
246 CPULoongArchState *env = &cpu->env;
249 qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
250 qemu_fprintf(f, " FCSR0 0x%08x fp_status 0x%02x\n", env->fcsr0,
251 get_float_exception_flags(&env->fp_status));
254 for (i = 0; i < 32; i++) {
256 qemu_fprintf(f, " GPR%02d:", i);
258 qemu_fprintf(f, " %s %016" PRIx64, regnames[i], env->gpr[i]);
260 qemu_fprintf(f, "\n");
265 if (flags & CPU_DUMP_FPU) {
266 for (i = 0; i < 32; i++) {
267 qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], env->fpr[i]);
269 qemu_fprintf(f, "\n");
276 #include "hw/core/tcg-cpu-ops.h"
278 static struct TCGCPUOps loongarch_tcg_ops = {
279 .initialize = loongarch_translate_init,
280 .synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
282 #endif /* CONFIG_TCG */
284 static void loongarch_cpu_class_init(ObjectClass *c, void *data)
286 LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c);
287 CPUClass *cc = CPU_CLASS(c);
288 DeviceClass *dc = DEVICE_CLASS(c);
290 device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
291 &lacc->parent_realize);
292 device_class_set_parent_reset(dc, loongarch_cpu_reset, &lacc->parent_reset);
294 cc->class_by_name = loongarch_cpu_class_by_name;
295 cc->dump_state = loongarch_cpu_dump_state;
296 cc->set_pc = loongarch_cpu_set_pc;
297 cc->disas_set_info = loongarch_cpu_disas_set_info;
299 cc->tcg_ops = &loongarch_tcg_ops;
303 #define DEFINE_LOONGARCH_CPU_TYPE(model, initfn) \
305 .parent = TYPE_LOONGARCH_CPU, \
306 .instance_init = initfn, \
307 .name = LOONGARCH_CPU_TYPE_NAME(model), \
310 static const TypeInfo loongarch_cpu_type_infos[] = {
312 .name = TYPE_LOONGARCH_CPU,
314 .instance_size = sizeof(LoongArchCPU),
315 .instance_init = loongarch_cpu_init,
318 .class_size = sizeof(LoongArchCPUClass),
319 .class_init = loongarch_cpu_class_init,
321 DEFINE_LOONGARCH_CPU_TYPE("la464", loongarch_la464_initfn),
324 DEFINE_TYPES(loongarch_cpu_type_infos)