]> git.proxmox.com Git - mirror_qemu.git/blame - target/mips/internal.h
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
[mirror_qemu.git] / target / mips / internal.h
CommitLineData
26aa3d9a
PMD
1/* mips internal definitions and helpers
2 *
3 * This work is licensed under the terms of the GNU GPL, version 2 or later.
4 * See the COPYING file in the top-level directory.
5 */
6
7#ifndef MIPS_INTERNAL_H
8#define MIPS_INTERNAL_H
9
41da212c
IM
10
11/* MMU types, the first four entries have the same layout as the
12 CP0C0_MT field. */
13enum mips_mmu_types {
14 MMU_TYPE_NONE,
15 MMU_TYPE_R4000,
16 MMU_TYPE_RESERVED,
17 MMU_TYPE_FMT,
18 MMU_TYPE_R3000,
19 MMU_TYPE_R6000,
20 MMU_TYPE_R8000
21};
22
23struct mips_def_t {
24 const char *name;
25 int32_t CP0_PRid;
26 int32_t CP0_Config0;
27 int32_t CP0_Config1;
28 int32_t CP0_Config2;
29 int32_t CP0_Config3;
30 int32_t CP0_Config4;
31 int32_t CP0_Config4_rw_bitmask;
32 int32_t CP0_Config5;
33 int32_t CP0_Config5_rw_bitmask;
34 int32_t CP0_Config6;
35 int32_t CP0_Config7;
36 target_ulong CP0_LLAddr_rw_bitmask;
37 int CP0_LLAddr_shift;
38 int32_t SYNCI_Step;
39 int32_t CCRes;
40 int32_t CP0_Status_rw_bitmask;
41 int32_t CP0_TCStatus_rw_bitmask;
42 int32_t CP0_SRSCtl;
43 int32_t CP1_fcr0;
44 int32_t CP1_fcr31_rw_bitmask;
45 int32_t CP1_fcr31;
46 int32_t MSAIR;
47 int32_t SEGBITS;
48 int32_t PABITS;
49 int32_t CP0_SRSConf0_rw_bitmask;
50 int32_t CP0_SRSConf0;
51 int32_t CP0_SRSConf1_rw_bitmask;
52 int32_t CP0_SRSConf1;
53 int32_t CP0_SRSConf2_rw_bitmask;
54 int32_t CP0_SRSConf2;
55 int32_t CP0_SRSConf3_rw_bitmask;
56 int32_t CP0_SRSConf3;
57 int32_t CP0_SRSConf4_rw_bitmask;
58 int32_t CP0_SRSConf4;
59 int32_t CP0_PageGrain_rw_bitmask;
60 int32_t CP0_PageGrain;
61 target_ulong CP0_EBaseWG_rw_bitmask;
f9c9cd63 62 uint64_t insn_flags;
41da212c 63 enum mips_mmu_types mmu_type;
5fb2dcd1 64 int32_t SAARP;
41da212c
IM
65};
66
67extern const struct mips_def_t mips_defs[];
68extern const int mips_defs_number;
69
26aa3d9a
PMD
70enum CPUMIPSMSADataFormat {
71 DF_BYTE = 0,
72 DF_HALF,
73 DF_WORD,
74 DF_DOUBLE
75};
76
77void mips_cpu_do_interrupt(CPUState *cpu);
78bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
90c84c56 79void mips_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
26aa3d9a
PMD
80hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
81int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
82int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
83void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
84 MMUAccessType access_type,
85 int mmu_idx, uintptr_t retaddr);
86
87#if !defined(CONFIG_USER_ONLY)
88
89typedef struct r4k_tlb_t r4k_tlb_t;
90struct r4k_tlb_t {
91 target_ulong VPN;
92 uint32_t PageMask;
93 uint16_t ASID;
94 unsigned int G:1;
95 unsigned int C0:3;
96 unsigned int C1:3;
97 unsigned int V0:1;
98 unsigned int V1:1;
99 unsigned int D0:1;
100 unsigned int D1:1;
101 unsigned int XI0:1;
102 unsigned int XI1:1;
103 unsigned int RI0:1;
104 unsigned int RI1:1;
105 unsigned int EHINV:1;
106 uint64_t PFN[2];
107};
108
109struct CPUMIPSTLBContext {
110 uint32_t nb_tlb;
111 uint32_t tlb_in_use;
112 int (*map_address)(struct CPUMIPSState *env, hwaddr *physical, int *prot,
113 target_ulong address, int rw, int access_type);
114 void (*helper_tlbwi)(struct CPUMIPSState *env);
115 void (*helper_tlbwr)(struct CPUMIPSState *env);
116 void (*helper_tlbp)(struct CPUMIPSState *env);
117 void (*helper_tlbr)(struct CPUMIPSState *env);
118 void (*helper_tlbinv)(struct CPUMIPSState *env);
119 void (*helper_tlbinvf)(struct CPUMIPSState *env);
120 union {
121 struct {
122 r4k_tlb_t tlb[MIPS_TLB_MAX];
123 } r4k;
124 } mmu;
125};
126
127int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
128 target_ulong address, int rw, int access_type);
129int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
130 target_ulong address, int rw, int access_type);
131int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
132 target_ulong address, int rw, int access_type);
133void r4k_helper_tlbwi(CPUMIPSState *env);
134void r4k_helper_tlbwr(CPUMIPSState *env);
135void r4k_helper_tlbp(CPUMIPSState *env);
136void r4k_helper_tlbr(CPUMIPSState *env);
137void r4k_helper_tlbinv(CPUMIPSState *env);
138void r4k_helper_tlbinvf(CPUMIPSState *env);
139void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra);
140
141void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
142 bool is_write, bool is_exec, int unused,
143 unsigned size);
144hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address,
145 int rw);
146#endif
147
148#define cpu_signal_handler cpu_mips_signal_handler
149
150#ifndef CONFIG_USER_ONLY
151extern const struct VMStateDescription vmstate_mips_cpu;
152#endif
153
154static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env)
155{
156 return (env->CP0_Status & (1 << CP0St_IE)) &&
157 !(env->CP0_Status & (1 << CP0St_EXL)) &&
158 !(env->CP0_Status & (1 << CP0St_ERL)) &&
159 !(env->hflags & MIPS_HFLAG_DM) &&
160 /* Note that the TCStatus IXMT field is initialized to zero,
161 and only MT capable cores can set it to one. So we don't
162 need to check for MT capabilities here. */
163 !(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT));
164}
165
166/* Check if there is pending and not masked out interrupt */
167static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
168{
169 int32_t pending;
170 int32_t status;
171 bool r;
172
173 pending = env->CP0_Cause & CP0Ca_IP_mask;
174 status = env->CP0_Status & CP0Ca_IP_mask;
175
176 if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
177 /* A MIPS configured with a vectorizing external interrupt controller
178 will feed a vector into the Cause pending lines. The core treats
179 the status lines as a vector level, not as indiviual masks. */
180 r = pending > status;
181 } else {
182 /* A MIPS configured with compatibility or VInt (Vectored Interrupts)
183 treats the pending lines as individual interrupt lines, the status
184 lines are individual masks. */
185 r = (pending & status) != 0;
186 }
187 return r;
188}
189
190void mips_tcg_init(void);
191
192/* TODO QOM'ify CPU reset and remove */
193void cpu_state_reset(CPUMIPSState *s);
27e38392 194void cpu_mips_realize_env(CPUMIPSState *env);
26aa3d9a
PMD
195
196/* cp0_timer.c */
197uint32_t cpu_mips_get_random(CPUMIPSState *env);
198uint32_t cpu_mips_get_count(CPUMIPSState *env);
199void cpu_mips_store_count(CPUMIPSState *env, uint32_t value);
200void cpu_mips_store_compare(CPUMIPSState *env, uint32_t value);
201void cpu_mips_start_count(CPUMIPSState *env);
202void cpu_mips_stop_count(CPUMIPSState *env);
203
204/* helper.c */
931d019f
RH
205bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
206 MMUAccessType access_type, int mmu_idx,
207 bool probe, uintptr_t retaddr);
26aa3d9a
PMD
208
209/* op_helper.c */
210uint32_t float_class_s(uint32_t arg, float_status *fst);
211uint64_t float_class_d(uint64_t arg, float_status *fst);
212
213extern unsigned int ieee_rm[];
214int ieee_ex_to_mips(int xcpt);
074cfcb4 215void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask);
26aa3d9a
PMD
216
217static inline void restore_rounding_mode(CPUMIPSState *env)
218{
219 set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3],
220 &env->active_fpu.fp_status);
221}
222
223static inline void restore_flush_mode(CPUMIPSState *env)
224{
225 set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0,
226 &env->active_fpu.fp_status);
227}
228
229static inline void restore_fp_status(CPUMIPSState *env)
230{
231 restore_rounding_mode(env);
232 restore_flush_mode(env);
233 restore_snan_bit_mode(env);
234}
235
236static inline void restore_msa_fp_status(CPUMIPSState *env)
237{
238 float_status *status = &env->active_tc.msa_fp_status;
239 int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM;
240 bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0;
241
242 set_float_rounding_mode(ieee_rm[rounding_mode], status);
243 set_flush_to_zero(flush_to_zero, status);
244 set_flush_inputs_to_zero(flush_to_zero, status);
245}
246
247static inline void restore_pamask(CPUMIPSState *env)
248{
249 if (env->hflags & MIPS_HFLAG_ELPA) {
250 env->PAMask = (1ULL << env->PABITS) - 1;
251 } else {
252 env->PAMask = PAMASK_BASE;
253 }
254}
255
256static inline int mips_vpe_active(CPUMIPSState *env)
257{
258 int active = 1;
259
260 /* Check that the VPE is enabled. */
261 if (!(env->mvp->CP0_MVPControl & (1 << CP0MVPCo_EVP))) {
262 active = 0;
263 }
264 /* Check that the VPE is activated. */
265 if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))) {
266 active = 0;
267 }
268
269 /* Now verify that there are active thread contexts in the VPE.
270
271 This assumes the CPU model will internally reschedule threads
272 if the active one goes to sleep. If there are no threads available
273 the active one will be in a sleeping state, and we can turn off
274 the entire VPE. */
275 if (!(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_A))) {
276 /* TC is not activated. */
277 active = 0;
278 }
279 if (env->active_tc.CP0_TCHalt & 1) {
280 /* TC is in halt state. */
281 active = 0;
282 }
283
284 return active;
285}
286
287static inline int mips_vp_active(CPUMIPSState *env)
288{
289 CPUState *other_cs = first_cpu;
290
291 /* Check if the VP disabled other VPs (which means the VP is enabled) */
292 if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) {
293 return 1;
294 }
295
296 /* Check if the virtual processor is disabled due to a DVP */
297 CPU_FOREACH(other_cs) {
298 MIPSCPU *other_cpu = MIPS_CPU(other_cs);
299 if ((&other_cpu->env != env) &&
300 ((other_cpu->env.CP0_VPControl >> CP0VPCtl_DIS) & 1)) {
301 return 0;
302 }
303 }
304 return 1;
305}
306
307static inline void compute_hflags(CPUMIPSState *env)
308{
309 env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
310 MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
908f6be1
SM
311 MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2 |
312 MIPS_HFLAG_DSP_R3 | MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA |
59e781fb 313 MIPS_HFLAG_FRE | MIPS_HFLAG_ELPA | MIPS_HFLAG_ERL);
26aa3d9a
PMD
314 if (env->CP0_Status & (1 << CP0St_ERL)) {
315 env->hflags |= MIPS_HFLAG_ERL;
316 }
317 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
318 !(env->CP0_Status & (1 << CP0St_ERL)) &&
319 !(env->hflags & MIPS_HFLAG_DM)) {
320 env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
321 }
322#if defined(TARGET_MIPS64)
323 if ((env->insn_flags & ISA_MIPS3) &&
324 (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
325 (env->CP0_Status & (1 << CP0St_PX)) ||
326 (env->CP0_Status & (1 << CP0St_UX)))) {
327 env->hflags |= MIPS_HFLAG_64;
328 }
329
330 if (!(env->insn_flags & ISA_MIPS3)) {
331 env->hflags |= MIPS_HFLAG_AWRAP;
332 } else if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
333 !(env->CP0_Status & (1 << CP0St_UX))) {
334 env->hflags |= MIPS_HFLAG_AWRAP;
335 } else if (env->insn_flags & ISA_MIPS64R6) {
336 /* Address wrapping for Supervisor and Kernel is specified in R6 */
337 if ((((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_SM) &&
338 !(env->CP0_Status & (1 << CP0St_SX))) ||
339 (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_KM) &&
340 !(env->CP0_Status & (1 << CP0St_KX)))) {
341 env->hflags |= MIPS_HFLAG_AWRAP;
342 }
343 }
344#endif
345 if (((env->CP0_Status & (1 << CP0St_CU0)) &&
346 !(env->insn_flags & ISA_MIPS32R6)) ||
347 !(env->hflags & MIPS_HFLAG_KSU)) {
348 env->hflags |= MIPS_HFLAG_CP0;
349 }
350 if (env->CP0_Status & (1 << CP0St_CU1)) {
351 env->hflags |= MIPS_HFLAG_FPU;
352 }
353 if (env->CP0_Status & (1 << CP0St_FR)) {
354 env->hflags |= MIPS_HFLAG_F64;
355 }
356 if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_KM) &&
357 (env->CP0_Config5 & (1 << CP0C5_SBRI))) {
358 env->hflags |= MIPS_HFLAG_SBRI;
359 }
908f6be1
SM
360 if (env->insn_flags & ASE_DSP_R3) {
361 /*
362 * Our cpu supports DSP R3 ASE, so enable
363 * access to DSP R3 resources.
364 */
59e781fb 365 if (env->CP0_Status & (1 << CP0St_MX)) {
908f6be1
SM
366 env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2 |
367 MIPS_HFLAG_DSP_R3;
59e781fb 368 }
908f6be1
SM
369 } else if (env->insn_flags & ASE_DSP_R2) {
370 /*
371 * Our cpu supports DSP R2 ASE, so enable
372 * access to DSP R2 resources.
373 */
26aa3d9a 374 if (env->CP0_Status & (1 << CP0St_MX)) {
908f6be1 375 env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2;
26aa3d9a
PMD
376 }
377
378 } else if (env->insn_flags & ASE_DSP) {
908f6be1
SM
379 /*
380 * Our cpu supports DSP ASE, so enable
381 * access to DSP resources.
382 */
26aa3d9a
PMD
383 if (env->CP0_Status & (1 << CP0St_MX)) {
384 env->hflags |= MIPS_HFLAG_DSP;
385 }
386
387 }
388 if (env->insn_flags & ISA_MIPS32R2) {
389 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
390 env->hflags |= MIPS_HFLAG_COP1X;
391 }
392 } else if (env->insn_flags & ISA_MIPS32) {
393 if (env->hflags & MIPS_HFLAG_64) {
394 env->hflags |= MIPS_HFLAG_COP1X;
395 }
396 } else if (env->insn_flags & ISA_MIPS4) {
397 /* All supported MIPS IV CPUs use the XX (CU3) to enable
398 and disable the MIPS IV extensions to the MIPS III ISA.
399 Some other MIPS IV CPUs ignore the bit, so the check here
400 would be too restrictive for them. */
401 if (env->CP0_Status & (1U << CP0St_CU3)) {
402 env->hflags |= MIPS_HFLAG_COP1X;
403 }
404 }
405 if (env->insn_flags & ASE_MSA) {
406 if (env->CP0_Config5 & (1 << CP0C5_MSAEn)) {
407 env->hflags |= MIPS_HFLAG_MSA;
408 }
409 }
410 if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
411 if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
412 env->hflags |= MIPS_HFLAG_FRE;
413 }
414 }
415 if (env->CP0_Config3 & (1 << CP0C3_LPA)) {
416 if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) {
417 env->hflags |= MIPS_HFLAG_ELPA;
418 }
419 }
420}
421
422void cpu_mips_tlb_flush(CPUMIPSState *env);
423void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc);
424void cpu_mips_store_status(CPUMIPSState *env, target_ulong val);
425void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val);
426
427void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
428 int error_code, uintptr_t pc);
429
430static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env,
431 uint32_t exception,
432 uintptr_t pc)
433{
434 do_raise_exception_err(env, exception, 0, pc);
435}
436
437#endif