]> Git Repo - qemu.git/blame - target/mips/cpu.c
target/mips: Move Special opcodes to tcg/sysemu/special_helper.c
[qemu.git] / target / mips / cpu.c
CommitLineData
0f71a709
AF
1/*
2 * QEMU MIPS CPU
3 *
4 * Copyright (c) 2012 SUSE LINUX Products GmbH
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see
18 * <http://www.gnu.org/licenses/lgpl-2.1.html>
19 */
20
c684822a 21#include "qemu/osdep.h"
8a6359f9 22#include "qemu/cutils.h"
c20cf02b 23#include "qemu/qemu-print.h"
da34e65c 24#include "qapi/error.h"
0f71a709 25#include "cpu.h"
26aa3d9a 26#include "internal.h"
14c03ab9 27#include "kvm_mips.h"
0b8fa32f 28#include "qemu/module.h"
14c03ab9 29#include "sysemu/kvm.h"
8a6359f9 30#include "sysemu/qtest.h"
63c91552 31#include "exec/exec-all.h"
d0bec217 32#include "hw/qdev-properties.h"
a0713e85 33#include "hw/qdev-clock.h"
6b5fe137 34#include "semihosting/semihost.h"
a10b453a 35#include "qapi/qapi-commands-machine-target.h"
03e4d95c 36#include "fpu_helper.h"
0f71a709 37
830b87ea 38const char regnames[32][4] = {
adbf1be3
PMD
39 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
40 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
41 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
42 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
43};
44
e9927723
PMD
45#if !defined(CONFIG_USER_ONLY)
46
47/* Called for updates to CP0_Status. */
48void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc)
49{
50 int32_t tcstatus, *tcst;
51 uint32_t v = cpu->CP0_Status;
52 uint32_t cu, mx, asid, ksu;
53 uint32_t mask = ((1 << CP0TCSt_TCU3)
54 | (1 << CP0TCSt_TCU2)
55 | (1 << CP0TCSt_TCU1)
56 | (1 << CP0TCSt_TCU0)
57 | (1 << CP0TCSt_TMX)
58 | (3 << CP0TCSt_TKSU)
59 | (0xff << CP0TCSt_TASID));
60
61 cu = (v >> CP0St_CU0) & 0xf;
62 mx = (v >> CP0St_MX) & 0x1;
63 ksu = (v >> CP0St_KSU) & 0x3;
64 asid = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
65
66 tcstatus = cu << CP0TCSt_TCU0;
67 tcstatus |= mx << CP0TCSt_TMX;
68 tcstatus |= ksu << CP0TCSt_TKSU;
69 tcstatus |= asid;
70
71 if (tc == cpu->current_tc) {
72 tcst = &cpu->active_tc.CP0_TCStatus;
73 } else {
74 tcst = &cpu->tcs[tc].CP0_TCStatus;
75 }
76
77 *tcst &= ~mask;
78 *tcst |= tcstatus;
79 compute_hflags(cpu);
80}
81
82void cpu_mips_store_status(CPUMIPSState *env, target_ulong val)
83{
84 uint32_t mask = env->CP0_Status_rw_bitmask;
85 target_ulong old = env->CP0_Status;
86
87 if (env->insn_flags & ISA_MIPS_R6) {
88 bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3;
89#if defined(TARGET_MIPS64)
90 uint32_t ksux = (1 << CP0St_KX) & val;
91 ksux |= (ksux >> 1) & val; /* KX = 0 forces SX to be 0 */
92 ksux |= (ksux >> 1) & val; /* SX = 0 forces UX to be 0 */
93 val = (val & ~(7 << CP0St_UX)) | ksux;
94#endif
95 if (has_supervisor && extract32(val, CP0St_KSU, 2) == 0x3) {
96 mask &= ~(3 << CP0St_KSU);
97 }
98 mask &= ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & val);
99 }
100
101 env->CP0_Status = (old & ~mask) | (val & mask);
102#if defined(TARGET_MIPS64)
103 if ((env->CP0_Status ^ old) & (old & (7 << CP0St_UX))) {
104 /* Access to at least one of the 64-bit segments has been disabled */
105 tlb_flush(env_cpu(env));
106 }
107#endif
108 if (ase_mt_available(env)) {
109 sync_c0_status(env, env, env->current_tc);
110 } else {
111 compute_hflags(env);
112 }
113}
114
115void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val)
116{
117 uint32_t mask = 0x00C00300;
118 uint32_t old = env->CP0_Cause;
119 int i;
120
121 if (env->insn_flags & ISA_MIPS_R2) {
122 mask |= 1 << CP0Ca_DC;
123 }
124 if (env->insn_flags & ISA_MIPS_R6) {
125 mask &= ~((1 << CP0Ca_WP) & val);
126 }
127
128 env->CP0_Cause = (env->CP0_Cause & ~mask) | (val & mask);
129
130 if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
131 if (env->CP0_Cause & (1 << CP0Ca_DC)) {
132 cpu_mips_stop_count(env);
133 } else {
134 cpu_mips_start_count(env);
135 }
136 }
137
138 /* Set/reset software interrupts */
139 for (i = 0 ; i < 2 ; i++) {
140 if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) {
141 cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i)));
142 }
143 }
144}
145
146#endif /* !CONFIG_USER_ONLY */
147
4d169b9c
PMD
148static void fpu_dump_fpr(fpr_t *fpr, FILE *f, bool is_fpu64)
149{
150 if (is_fpu64) {
151 qemu_fprintf(f, "w:%08x d:%016" PRIx64 " fd:%13g fs:%13g psu: %13g\n",
152 fpr->w[FP_ENDIAN_IDX], fpr->d,
153 (double)fpr->fd,
154 (double)fpr->fs[FP_ENDIAN_IDX],
155 (double)fpr->fs[!FP_ENDIAN_IDX]);
156 } else {
157 fpr_t tmp;
158
159 tmp.w[FP_ENDIAN_IDX] = fpr->w[FP_ENDIAN_IDX];
160 tmp.w[!FP_ENDIAN_IDX] = (fpr + 1)->w[FP_ENDIAN_IDX];
161 qemu_fprintf(f, "w:%08x d:%016" PRIx64 " fd:%13g fs:%13g psu:%13g\n",
162 tmp.w[FP_ENDIAN_IDX], tmp.d,
163 (double)tmp.fd,
164 (double)tmp.fs[FP_ENDIAN_IDX],
165 (double)tmp.fs[!FP_ENDIAN_IDX]);
166 }
167}
168
4f14ce4b
PMD
169static void fpu_dump_state(CPUMIPSState *env, FILE *f, int flags)
170{
171 int i;
4d169b9c 172 bool is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
4f14ce4b
PMD
173
174 qemu_fprintf(f,
175 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
176 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
177 get_float_exception_flags(&env->active_fpu.fp_status));
178 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
179 qemu_fprintf(f, "%3s: ", fregnames[i]);
4d169b9c 180 fpu_dump_fpr(&env->active_fpu.fpr[i], f, is_fpu64);
4f14ce4b 181 }
4f14ce4b
PMD
182}
183
184static void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
185{
186 MIPSCPU *cpu = MIPS_CPU(cs);
187 CPUMIPSState *env = &cpu->env;
188 int i;
189
190 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
191 " LO=0x" TARGET_FMT_lx " ds %04x "
192 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
193 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
194 env->hflags, env->btarget, env->bcond);
195 for (i = 0; i < 32; i++) {
196 if ((i & 3) == 0) {
197 qemu_fprintf(f, "GPR%02d:", i);
198 }
199 qemu_fprintf(f, " %s " TARGET_FMT_lx,
200 regnames[i], env->active_tc.gpr[i]);
201 if ((i & 3) == 3) {
202 qemu_fprintf(f, "\n");
203 }
204 }
205
206 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
207 TARGET_FMT_lx "\n",
208 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
209 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
210 PRIx64 "\n",
211 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
212 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
213 env->CP0_Config2, env->CP0_Config3);
214 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
215 env->CP0_Config4, env->CP0_Config5);
216 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
217 fpu_dump_state(env, f, flags);
218 }
219}
220
e9927723
PMD
221static const char * const excp_names[EXCP_LAST + 1] = {
222 [EXCP_RESET] = "reset",
223 [EXCP_SRESET] = "soft reset",
224 [EXCP_DSS] = "debug single step",
225 [EXCP_DINT] = "debug interrupt",
226 [EXCP_NMI] = "non-maskable interrupt",
227 [EXCP_MCHECK] = "machine check",
228 [EXCP_EXT_INTERRUPT] = "interrupt",
229 [EXCP_DFWATCH] = "deferred watchpoint",
230 [EXCP_DIB] = "debug instruction breakpoint",
231 [EXCP_IWATCH] = "instruction fetch watchpoint",
232 [EXCP_AdEL] = "address error load",
233 [EXCP_AdES] = "address error store",
234 [EXCP_TLBF] = "TLB refill",
235 [EXCP_IBE] = "instruction bus error",
236 [EXCP_DBp] = "debug breakpoint",
237 [EXCP_SYSCALL] = "syscall",
238 [EXCP_BREAK] = "break",
239 [EXCP_CpU] = "coprocessor unusable",
240 [EXCP_RI] = "reserved instruction",
241 [EXCP_OVERFLOW] = "arithmetic overflow",
242 [EXCP_TRAP] = "trap",
243 [EXCP_FPE] = "floating point",
244 [EXCP_DDBS] = "debug data break store",
245 [EXCP_DWATCH] = "data watchpoint",
246 [EXCP_LTLBL] = "TLB modify",
247 [EXCP_TLBL] = "TLB load",
248 [EXCP_TLBS] = "TLB store",
249 [EXCP_DBE] = "data bus error",
250 [EXCP_DDBL] = "debug data break load",
251 [EXCP_THREAD] = "thread",
252 [EXCP_MDMX] = "MDMX",
253 [EXCP_C2E] = "precise coprocessor 2",
254 [EXCP_CACHE] = "cache error",
255 [EXCP_TLBXI] = "TLB execute-inhibit",
256 [EXCP_TLBRI] = "TLB read-inhibit",
257 [EXCP_MSADIS] = "MSA disabled",
258 [EXCP_MSAFPE] = "MSA floating point",
259};
260
261const char *mips_exception_name(int32_t exception)
262{
263 if (exception < 0 || exception > EXCP_LAST) {
264 return "unknown";
265 }
266 return excp_names[exception];
267}
268
269void cpu_set_exception_base(int vp_index, target_ulong address)
270{
271 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
272 vp->env.exception_base = address;
273}
274
275target_ulong exception_resume_pc(CPUMIPSState *env)
276{
277 target_ulong bad_pc;
278 target_ulong isa_mode;
279
280 isa_mode = !!(env->hflags & MIPS_HFLAG_M16);
281 bad_pc = env->active_tc.PC | isa_mode;
282 if (env->hflags & MIPS_HFLAG_BMASK) {
283 /*
284 * If the exception was raised from a delay slot, come back to
285 * the jump.
286 */
287 bad_pc -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4);
288 }
289
290 return bad_pc;
291}
292
293bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
294{
295 if (interrupt_request & CPU_INTERRUPT_HARD) {
296 MIPSCPU *cpu = MIPS_CPU(cs);
297 CPUMIPSState *env = &cpu->env;
298
299 if (cpu_mips_hw_interrupts_enabled(env) &&
300 cpu_mips_hw_interrupts_pending(env)) {
301 /* Raise it */
302 cs->exception_index = EXCP_EXT_INTERRUPT;
303 env->error_code = 0;
304 mips_cpu_do_interrupt(cs);
305 return true;
306 }
307 }
308 return false;
309}
310
311void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env,
312 uint32_t exception,
313 int error_code,
314 uintptr_t pc)
315{
316 CPUState *cs = env_cpu(env);
317
318 qemu_log_mask(CPU_LOG_INT, "%s: %d (%s) %d\n",
319 __func__, exception, mips_exception_name(exception),
320 error_code);
321 cs->exception_index = exception;
322 env->error_code = error_code;
323
324 cpu_loop_exit_restore(cs, pc);
325}
326
f45748f1
AF
327static void mips_cpu_set_pc(CPUState *cs, vaddr value)
328{
329 MIPSCPU *cpu = MIPS_CPU(cs);
f45748f1 330
533fc64f 331 mips_env_set_pc(&cpu->env, value);
f45748f1
AF
332}
333
ec62595b 334#ifdef CONFIG_TCG
04a37d4c
RH
335static void mips_cpu_synchronize_from_tb(CPUState *cs,
336 const TranslationBlock *tb)
bdf7ae5b
AF
337{
338 MIPSCPU *cpu = MIPS_CPU(cs);
339 CPUMIPSState *env = &cpu->env;
340
341 env->active_tc.PC = tb->pc;
342 env->hflags &= ~MIPS_HFLAG_BMASK;
343 env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
344}
ec62595b 345#endif /* CONFIG_TCG */
bdf7ae5b 346
8c2e1b00
AF
347static bool mips_cpu_has_work(CPUState *cs)
348{
349 MIPSCPU *cpu = MIPS_CPU(cs);
350 CPUMIPSState *env = &cpu->env;
351 bool has_work = false;
352
cf02a116
AM
353 /*
354 * Prior to MIPS Release 6 it is implementation dependent if non-enabled
355 * interrupts wake-up the CPU, however most of the implementations only
356 * check for interrupts that can be taken.
357 */
8c2e1b00
AF
358 if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
359 cpu_mips_hw_interrupts_pending(env)) {
7540a43a 360 if (cpu_mips_hw_interrupts_enabled(env) ||
2e211e0a 361 (env->insn_flags & ISA_MIPS_R6)) {
71ca034a
LA
362 has_work = true;
363 }
8c2e1b00
AF
364 }
365
366 /* MIPS-MT has the ability to halt the CPU. */
17c2c320 367 if (ase_mt_available(env)) {
cf02a116
AM
368 /*
369 * The QEMU model will issue an _WAKE request whenever the CPUs
370 * should be woken up.
371 */
8c2e1b00
AF
372 if (cs->interrupt_request & CPU_INTERRUPT_WAKE) {
373 has_work = true;
374 }
375
376 if (!mips_vpe_active(env)) {
377 has_work = false;
378 }
379 }
01bc435b
YK
380 /* MIPS Release 6 has the ability to halt the CPU. */
381 if (env->CP0_Config5 & (1 << CP0C5_VP)) {
382 if (cs->interrupt_request & CPU_INTERRUPT_WAKE) {
383 has_work = true;
384 }
385 if (!mips_vp_active(env)) {
386 has_work = false;
387 }
388 }
8c2e1b00
AF
389 return has_work;
390}
391
0dc351ca 392#include "cpu-defs.c.inc"
c20cf02b 393
9bcd41d4 394static void mips_cpu_reset(DeviceState *dev)
c20cf02b 395{
9bcd41d4
PMD
396 CPUState *cs = CPU(dev);
397 MIPSCPU *cpu = MIPS_CPU(cs);
398 MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
399 CPUMIPSState *env = &cpu->env;
400
401 mcc->parent_reset(dev);
402
403 memset(env, 0, offsetof(CPUMIPSState, end_reset_fields));
c20cf02b
PMD
404
405 /* Reset registers to their default values */
406 env->CP0_PRid = env->cpu_model->CP0_PRid;
407 env->CP0_Config0 = env->cpu_model->CP0_Config0;
408#ifdef TARGET_WORDS_BIGENDIAN
409 env->CP0_Config0 |= (1 << CP0C0_BE);
410#endif
411 env->CP0_Config1 = env->cpu_model->CP0_Config1;
412 env->CP0_Config2 = env->cpu_model->CP0_Config2;
413 env->CP0_Config3 = env->cpu_model->CP0_Config3;
414 env->CP0_Config4 = env->cpu_model->CP0_Config4;
415 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
416 env->CP0_Config5 = env->cpu_model->CP0_Config5;
417 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
418 env->CP0_Config6 = env->cpu_model->CP0_Config6;
419 env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask;
420 env->CP0_Config7 = env->cpu_model->CP0_Config7;
421 env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask;
422 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
423 << env->cpu_model->CP0_LLAddr_shift;
424 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
425 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
426 env->CCRes = env->cpu_model->CCRes;
427 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
428 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
429 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
430 env->current_tc = 0;
431 env->SEGBITS = env->cpu_model->SEGBITS;
432 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
433#if defined(TARGET_MIPS64)
434 if (env->cpu_model->insn_flags & ISA_MIPS3) {
435 env->SEGMask |= 3ULL << 62;
436 }
437#endif
438 env->PABITS = env->cpu_model->PABITS;
439 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
440 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
441 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
442 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
443 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
444 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
445 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
446 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
447 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
448 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
449 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
450 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
451 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
452 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
453 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
454 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
455 env->msair = env->cpu_model->MSAIR;
456 env->insn_flags = env->cpu_model->insn_flags;
457
458#if defined(CONFIG_USER_ONLY)
459 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
460# ifdef TARGET_MIPS64
461 /* Enable 64-bit register mode. */
462 env->CP0_Status |= (1 << CP0St_PX);
463# endif
464# ifdef TARGET_ABI_MIPSN64
465 /* Enable 64-bit address mode. */
466 env->CP0_Status |= (1 << CP0St_UX);
467# endif
468 /*
469 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
470 * hardware registers.
471 */
472 env->CP0_HWREna |= 0x0000000F;
473 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
474 env->CP0_Status |= (1 << CP0St_CU1);
475 }
476 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
477 env->CP0_Status |= (1 << CP0St_MX);
478 }
479# if defined(TARGET_MIPS64)
480 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
481 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
482 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
483 env->CP0_Status |= (1 << CP0St_FR);
484 }
485# endif
486#else /* !CONFIG_USER_ONLY */
487 if (env->hflags & MIPS_HFLAG_BMASK) {
488 /*
489 * If the exception was raised from a delay slot,
490 * come back to the jump.
491 */
492 env->CP0_ErrorEPC = (env->active_tc.PC
493 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
494 } else {
495 env->CP0_ErrorEPC = env->active_tc.PC;
496 }
497 env->active_tc.PC = env->exception_base;
498 env->CP0_Random = env->tlb->nb_tlb - 1;
499 env->tlb->tlb_in_use = env->tlb->nb_tlb;
500 env->CP0_Wired = 0;
501 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
502 env->CP0_EBase = (cs->cpu_index & 0x3FF);
503 if (mips_um_ksegs_enabled()) {
504 env->CP0_EBase |= 0x40000000;
505 } else {
506 env->CP0_EBase |= (int32_t)0x80000000;
507 }
508 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
509 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
510 }
511 env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
512 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
513 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
514 /*
515 * Vectored interrupts not implemented, timer on int 7,
516 * no performance counters.
517 */
518 env->CP0_IntCtl = 0xe0000000;
519 {
520 int i;
521
522 for (i = 0; i < 7; i++) {
523 env->CP0_WatchLo[i] = 0;
524 env->CP0_WatchHi[i] = 0x80000000;
525 }
526 env->CP0_WatchLo[7] = 0;
527 env->CP0_WatchHi[7] = 0;
528 }
529 /* Count register increments in debug mode, EJTAG version 1 */
530 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
531
532 cpu_mips_store_count(env, 1);
533
534 if (ase_mt_available(env)) {
535 int i;
536
537 /* Only TC0 on VPE 0 starts as active. */
538 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
539 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
540 env->tcs[i].CP0_TCHalt = 1;
541 }
542 env->active_tc.CP0_TCHalt = 1;
543 cs->halted = 1;
544
545 if (cs->cpu_index == 0) {
546 /* VPE0 starts up enabled. */
547 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
548 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
549
550 /* TC0 starts up unhalted. */
551 cs->halted = 0;
552 env->active_tc.CP0_TCHalt = 0;
553 env->tcs[0].CP0_TCHalt = 0;
554 /* With thread 0 active. */
555 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
556 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
557 }
558 }
559
560 /*
561 * Configure default legacy segmentation control. We use this regardless of
562 * whether segmentation control is presented to the guest.
563 */
564 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
565 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
566 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
567 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
568 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
569 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
570 (2 << CP0SC_C);
571 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
572 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
573 (3 << CP0SC_C)) << 16;
574 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
575 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
576 (1 << CP0SC_EU) | (2 << CP0SC_C);
577 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
578 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
579 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
580 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
581 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
582#endif /* !CONFIG_USER_ONLY */
2e211e0a 583 if ((env->insn_flags & ISA_MIPS_R6) &&
c20cf02b
PMD
584 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
585 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
586 env->CP0_Status |= (1 << CP0St_FR);
587 }
588
2e211e0a 589 if (env->insn_flags & ISA_MIPS_R6) {
c20cf02b
PMD
590 /* PTW = 1 */
591 env->CP0_PWSize = 0x40;
592 /* GDI = 12 */
593 /* UDI = 12 */
594 /* MDI = 12 */
595 /* PRI = 12 */
596 /* PTEI = 2 */
597 env->CP0_PWField = 0x0C30C302;
598 } else {
599 /* GDI = 0 */
600 /* UDI = 0 */
601 /* MDI = 0 */
602 /* PRI = 0 */
603 /* PTEI = 2 */
604 env->CP0_PWField = 0x02;
605 }
606
607 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
608 /* microMIPS on reset when Config3.ISA is 3 */
609 env->hflags |= MIPS_HFLAG_M16;
610 }
611
72f31f60 612 msa_reset(env);
c20cf02b
PMD
613
614 compute_hflags(env);
615 restore_fp_status(env);
616 restore_pamask(env);
617 cs->exception_index = EXCP_NONE;
618
619 if (semihosting_get_argc()) {
620 /* UHI interface can be used to obtain argc and argv */
621 env->active_tc.gpr[4] = -1;
622 }
14c03ab9
JH
623
624#ifndef CONFIG_USER_ONLY
625 if (kvm_enabled()) {
626 kvm_mips_reset_vcpu(cpu);
627 }
628#endif
0f71a709
AF
629}
630
cf02a116
AM
631static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info)
632{
89a955e8
AM
633 MIPSCPU *cpu = MIPS_CPU(s);
634 CPUMIPSState *env = &cpu->env;
635
636 if (!(env->insn_flags & ISA_NANOMIPS32)) {
63a946c7 637#ifdef TARGET_WORDS_BIGENDIAN
89a955e8 638 info->print_insn = print_insn_big_mips;
63a946c7 639#else
89a955e8 640 info->print_insn = print_insn_little_mips;
63a946c7 641#endif
89a955e8
AM
642 } else {
643#if defined(CONFIG_NANOMIPS_DIS)
644 info->print_insn = print_insn_nanomips;
645#endif
646 }
63a946c7
PC
647}
648
d225b512 649/*
d0bec217 650 * Since commit 6af0bf9c7c3 this model assumes a CPU clocked at 200MHz.
d225b512
PMD
651 */
652#define CPU_FREQ_HZ_DEFAULT 200000000
653#define CP0_COUNT_RATE_DEFAULT 2
d225b512
PMD
654
655static void mips_cp0_period_set(MIPSCPU *cpu)
656{
657 CPUMIPSState *env = &cpu->env;
658
0ac1fb25
PM
659 env->cp0_count_ns = clock_ticks_to_ns(MIPS_CPU(cpu)->clock,
660 cpu->cp0_count_rate);
a0713e85 661 assert(env->cp0_count_ns);
d225b512
PMD
662}
663
c1caf1d9
AF
664static void mips_cpu_realizefn(DeviceState *dev, Error **errp)
665{
14a10fc3 666 CPUState *cs = CPU(dev);
df4dc102 667 MIPSCPU *cpu = MIPS_CPU(dev);
7b884bf5 668 CPUMIPSState *env = &cpu->env;
c1caf1d9 669 MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev);
ce5b1bbf
LV
670 Error *local_err = NULL;
671
a0713e85 672 if (!clock_get(cpu->clock)) {
8a6359f9
PMD
673#ifndef CONFIG_USER_ONLY
674 if (!qtest_enabled()) {
675 g_autofree char *cpu_freq_str = freq_to_str(CPU_FREQ_HZ_DEFAULT);
676
677 warn_report("CPU input clock is not connected to any output clock, "
678 "using default frequency of %s.", cpu_freq_str);
679 }
680#endif
a0713e85
PMD
681 /* Initialize the frequency in case the clock remains unconnected. */
682 clock_set_hz(cpu->clock, CPU_FREQ_HZ_DEFAULT);
683 }
d225b512
PMD
684 mips_cp0_period_set(cpu);
685
ce5b1bbf
LV
686 cpu_exec_realizefn(cs, &local_err);
687 if (local_err != NULL) {
688 error_propagate(errp, local_err);
689 return;
690 }
c1caf1d9 691
7b884bf5
PMD
692 env->exception_base = (int32_t)0xBFC00000;
693
c2842017 694#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
7b884bf5
PMD
695 mmu_init(env, env->cpu_model);
696#endif
697 fpu_init(env, env->cpu_model);
698 mvp_init(env);
df4dc102 699
14a10fc3
AF
700 cpu_reset(cs);
701 qemu_init_vcpu(cs);
c1caf1d9
AF
702
703 mcc->parent_realize(dev, errp);
704}
705
5b0c40f7
AF
706static void mips_cpu_initfn(Object *obj)
707{
708 MIPSCPU *cpu = MIPS_CPU(obj);
709 CPUMIPSState *env = &cpu->env;
41da212c 710 MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(obj);
5b0c40f7 711
7506ed90 712 cpu_set_cpustate_pointers(cpu);
5ee0abed 713 cpu->clock = qdev_init_clock_in(DEVICE(obj), "clk-in", NULL, cpu, 0);
41da212c 714 env->cpu_model = mcc->cpu_def;
5b0c40f7
AF
715}
716
41da212c
IM
717static char *mips_cpu_type_name(const char *cpu_model)
718{
a7519f2b 719 return g_strdup_printf(MIPS_CPU_TYPE_NAME("%s"), cpu_model);
41da212c
IM
720}
721
722static ObjectClass *mips_cpu_class_by_name(const char *cpu_model)
723{
724 ObjectClass *oc;
725 char *typename;
726
41da212c
IM
727 typename = mips_cpu_type_name(cpu_model);
728 oc = object_class_by_name(typename);
729 g_free(typename);
730 return oc;
731}
732
d0bec217
PMD
733static Property mips_cpu_properties[] = {
734 /* CP0 timer running at half the clock of the CPU */
735 DEFINE_PROP_UINT32("cp0-count-rate", MIPSCPU, cp0_count_rate,
736 CP0_COUNT_RATE_DEFAULT),
737 DEFINE_PROP_END_OF_LIST()
738};
739
78271684
CF
740#ifdef CONFIG_TCG
741#include "hw/core/tcg-cpu-ops.h"
742/*
743 * NB: cannot be const, as some elements are changed for specific
744 * mips hardware (see hw/mips/jazz.c).
745 */
746static struct TCGCPUOps mips_tcg_ops = {
747 .initialize = mips_tcg_init,
748 .synchronize_from_tb = mips_cpu_synchronize_from_tb,
749 .cpu_exec_interrupt = mips_cpu_exec_interrupt,
750 .tlb_fill = mips_cpu_tlb_fill,
751
752#if !defined(CONFIG_USER_ONLY)
753 .do_interrupt = mips_cpu_do_interrupt,
754 .do_transaction_failed = mips_cpu_do_transaction_failed,
755 .do_unaligned_access = mips_cpu_do_unaligned_access,
95ab7c22 756 .io_recompile_replay_branch = mips_io_recompile_replay_branch,
78271684
CF
757#endif /* !CONFIG_USER_ONLY */
758};
759#endif /* CONFIG_TCG */
760
0f71a709
AF
761static void mips_cpu_class_init(ObjectClass *c, void *data)
762{
763 MIPSCPUClass *mcc = MIPS_CPU_CLASS(c);
764 CPUClass *cc = CPU_CLASS(c);
c1caf1d9
AF
765 DeviceClass *dc = DEVICE_CLASS(c);
766
bf853881
PMD
767 device_class_set_parent_realize(dc, mips_cpu_realizefn,
768 &mcc->parent_realize);
781c67ca 769 device_class_set_parent_reset(dc, mips_cpu_reset, &mcc->parent_reset);
d0bec217 770 device_class_set_props(dc, mips_cpu_properties);
97a8ea5a 771
41da212c 772 cc->class_by_name = mips_cpu_class_by_name;
8c2e1b00 773 cc->has_work = mips_cpu_has_work;
878096ee 774 cc->dump_state = mips_cpu_dump_state;
f45748f1 775 cc->set_pc = mips_cpu_set_pc;
5b50e790
AF
776 cc->gdb_read_register = mips_cpu_gdb_read_register;
777 cc->gdb_write_register = mips_cpu_gdb_write_register;
931d019f 778#ifndef CONFIG_USER_ONLY
00b941e5 779 cc->get_phys_page_debug = mips_cpu_get_phys_page_debug;
04cd7962 780 cc->vmsd = &vmstate_mips_cpu;
00b941e5 781#endif
63a946c7 782 cc->disas_set_info = mips_cpu_disas_set_info;
a0e372f0 783 cc->gdb_num_core_regs = 73;
2472b6c0 784 cc->gdb_stop_before_watchpoint = true;
78271684
CF
785#ifdef CONFIG_TCG
786 cc->tcg_ops = &mips_tcg_ops;
787#endif /* CONFIG_TCG */
0f71a709
AF
788}
789
790static const TypeInfo mips_cpu_type_info = {
791 .name = TYPE_MIPS_CPU,
792 .parent = TYPE_CPU,
793 .instance_size = sizeof(MIPSCPU),
5b0c40f7 794 .instance_init = mips_cpu_initfn,
41da212c 795 .abstract = true,
0f71a709
AF
796 .class_size = sizeof(MIPSCPUClass),
797 .class_init = mips_cpu_class_init,
798};
799
41da212c
IM
800static void mips_cpu_cpudef_class_init(ObjectClass *oc, void *data)
801{
802 MIPSCPUClass *mcc = MIPS_CPU_CLASS(oc);
803 mcc->cpu_def = data;
804}
805
806static void mips_register_cpudef_type(const struct mips_def_t *def)
807{
808 char *typename = mips_cpu_type_name(def->name);
809 TypeInfo ti = {
810 .name = typename,
811 .parent = TYPE_MIPS_CPU,
812 .class_init = mips_cpu_cpudef_class_init,
813 .class_data = (void *)def,
814 };
815
816 type_register(&ti);
817 g_free(typename);
818}
819
0f71a709
AF
820static void mips_cpu_register_types(void)
821{
41da212c
IM
822 int i;
823
0f71a709 824 type_register_static(&mips_cpu_type_info);
41da212c
IM
825 for (i = 0; i < mips_defs_number; i++) {
826 mips_register_cpudef_type(&mips_defs[i]);
827 }
0f71a709
AF
828}
829
830type_init(mips_cpu_register_types)
7aaab96a 831
a10b453a
PMD
832static void mips_cpu_add_definition(gpointer data, gpointer user_data)
833{
834 ObjectClass *oc = data;
835 CpuDefinitionInfoList **cpu_list = user_data;
a10b453a
PMD
836 CpuDefinitionInfo *info;
837 const char *typename;
838
839 typename = object_class_get_name(oc);
840 info = g_malloc0(sizeof(*info));
841 info->name = g_strndup(typename,
842 strlen(typename) - strlen("-" TYPE_MIPS_CPU));
843 info->q_typename = g_strdup(typename);
844
54aa3de7 845 QAPI_LIST_PREPEND(*cpu_list, info);
a10b453a
PMD
846}
847
848CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
849{
850 CpuDefinitionInfoList *cpu_list = NULL;
851 GSList *list;
852
853 list = object_class_get_list(TYPE_MIPS_CPU, false);
854 g_slist_foreach(list, mips_cpu_add_definition, &cpu_list);
855 g_slist_free(list);
856
857 return cpu_list;
858}
859
7aaab96a
PMD
860/* Could be used by generic CPU object */
861MIPSCPU *mips_cpu_create_with_clock(const char *cpu_type, Clock *cpu_refclk)
862{
863 DeviceState *cpu;
864
865 cpu = DEVICE(object_new(cpu_type));
866 qdev_connect_clock_in(cpu, "clk-in", cpu_refclk);
867 qdev_realize(cpu, NULL, &error_abort);
868
869 return MIPS_CPU(cpu);
870}
df6adb68
PMD
871
872bool cpu_supports_isa(const CPUMIPSState *env, uint64_t isa_mask)
873{
874 return (env->cpu_model->insn_flags & isa_mask) != 0;
875}
ffa657ee
PMD
876
877bool cpu_type_supports_isa(const char *cpu_type, uint64_t isa)
878{
879 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
880 return (mcc->cpu_def->insn_flags & isa) != 0;
881}
882
883bool cpu_type_supports_cps_smp(const char *cpu_type)
884{
885 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
886 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
887}
This page took 0.625654 seconds and 4 git commands to generate.