1 /* mips internal definitions and helpers
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.
7 #ifndef MIPS_INTERNAL_H
8 #define MIPS_INTERNAL_H
10 #include "fpu/softfloat-helpers.h"
12 /* MMU types, the first four entries have the same layout as the
32 int32_t CP0_Config4_rw_bitmask
;
34 int32_t CP0_Config5_rw_bitmask
;
37 target_ulong CP0_LLAddr_rw_bitmask
;
41 int32_t CP0_Status_rw_bitmask
;
42 int32_t CP0_TCStatus_rw_bitmask
;
45 int32_t CP1_fcr31_rw_bitmask
;
50 int32_t CP0_SRSConf0_rw_bitmask
;
52 int32_t CP0_SRSConf1_rw_bitmask
;
54 int32_t CP0_SRSConf2_rw_bitmask
;
56 int32_t CP0_SRSConf3_rw_bitmask
;
58 int32_t CP0_SRSConf4_rw_bitmask
;
60 int32_t CP0_PageGrain_rw_bitmask
;
61 int32_t CP0_PageGrain
;
62 target_ulong CP0_EBaseWG_rw_bitmask
;
64 enum mips_mmu_types mmu_type
;
68 extern const struct mips_def_t mips_defs
[];
69 extern const int mips_defs_number
;
71 enum CPUMIPSMSADataFormat
{
78 void mips_cpu_do_interrupt(CPUState
*cpu
);
79 bool mips_cpu_exec_interrupt(CPUState
*cpu
, int int_req
);
80 void mips_cpu_dump_state(CPUState
*cpu
, FILE *f
, int flags
);
81 hwaddr
mips_cpu_get_phys_page_debug(CPUState
*cpu
, vaddr addr
);
82 int mips_cpu_gdb_read_register(CPUState
*cpu
, uint8_t *buf
, int reg
);
83 int mips_cpu_gdb_write_register(CPUState
*cpu
, uint8_t *buf
, int reg
);
84 void mips_cpu_do_unaligned_access(CPUState
*cpu
, vaddr addr
,
85 MMUAccessType access_type
,
86 int mmu_idx
, uintptr_t retaddr
);
88 #if !defined(CONFIG_USER_ONLY)
90 typedef struct r4k_tlb_t r4k_tlb_t
;
106 unsigned int EHINV
:1;
110 struct CPUMIPSTLBContext
{
113 int (*map_address
)(struct CPUMIPSState
*env
, hwaddr
*physical
, int *prot
,
114 target_ulong address
, int rw
, int access_type
);
115 void (*helper_tlbwi
)(struct CPUMIPSState
*env
);
116 void (*helper_tlbwr
)(struct CPUMIPSState
*env
);
117 void (*helper_tlbp
)(struct CPUMIPSState
*env
);
118 void (*helper_tlbr
)(struct CPUMIPSState
*env
);
119 void (*helper_tlbinv
)(struct CPUMIPSState
*env
);
120 void (*helper_tlbinvf
)(struct CPUMIPSState
*env
);
123 r4k_tlb_t tlb
[MIPS_TLB_MAX
];
128 int no_mmu_map_address(CPUMIPSState
*env
, hwaddr
*physical
, int *prot
,
129 target_ulong address
, int rw
, int access_type
);
130 int fixed_mmu_map_address(CPUMIPSState
*env
, hwaddr
*physical
, int *prot
,
131 target_ulong address
, int rw
, int access_type
);
132 int r4k_map_address(CPUMIPSState
*env
, hwaddr
*physical
, int *prot
,
133 target_ulong address
, int rw
, int access_type
);
134 void r4k_helper_tlbwi(CPUMIPSState
*env
);
135 void r4k_helper_tlbwr(CPUMIPSState
*env
);
136 void r4k_helper_tlbp(CPUMIPSState
*env
);
137 void r4k_helper_tlbr(CPUMIPSState
*env
);
138 void r4k_helper_tlbinv(CPUMIPSState
*env
);
139 void r4k_helper_tlbinvf(CPUMIPSState
*env
);
140 void r4k_invalidate_tlb(CPUMIPSState
*env
, int idx
, int use_extra
);
142 void mips_cpu_do_transaction_failed(CPUState
*cs
, hwaddr physaddr
,
143 vaddr addr
, unsigned size
,
144 MMUAccessType access_type
,
145 int mmu_idx
, MemTxAttrs attrs
,
146 MemTxResult response
, uintptr_t retaddr
);
147 hwaddr
cpu_mips_translate_address(CPUMIPSState
*env
, target_ulong address
,
151 #define cpu_signal_handler cpu_mips_signal_handler
153 #ifndef CONFIG_USER_ONLY
154 extern const VMStateDescription vmstate_mips_cpu
;
157 static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState
*env
)
159 return (env
->CP0_Status
& (1 << CP0St_IE
)) &&
160 !(env
->CP0_Status
& (1 << CP0St_EXL
)) &&
161 !(env
->CP0_Status
& (1 << CP0St_ERL
)) &&
162 !(env
->hflags
& MIPS_HFLAG_DM
) &&
163 /* Note that the TCStatus IXMT field is initialized to zero,
164 and only MT capable cores can set it to one. So we don't
165 need to check for MT capabilities here. */
166 !(env
->active_tc
.CP0_TCStatus
& (1 << CP0TCSt_IXMT
));
169 /* Check if there is pending and not masked out interrupt */
170 static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState
*env
)
176 pending
= env
->CP0_Cause
& CP0Ca_IP_mask
;
177 status
= env
->CP0_Status
& CP0Ca_IP_mask
;
179 if (env
->CP0_Config3
& (1 << CP0C3_VEIC
)) {
180 /* A MIPS configured with a vectorizing external interrupt controller
181 will feed a vector into the Cause pending lines. The core treats
182 the status lines as a vector level, not as indiviual masks. */
183 r
= pending
> status
;
185 /* A MIPS configured with compatibility or VInt (Vectored Interrupts)
186 treats the pending lines as individual interrupt lines, the status
187 lines are individual masks. */
188 r
= (pending
& status
) != 0;
193 void mips_tcg_init(void);
195 /* TODO QOM'ify CPU reset and remove */
196 void cpu_state_reset(CPUMIPSState
*s
);
197 void cpu_mips_realize_env(CPUMIPSState
*env
);
200 uint32_t cpu_mips_get_random(CPUMIPSState
*env
);
201 uint32_t cpu_mips_get_count(CPUMIPSState
*env
);
202 void cpu_mips_store_count(CPUMIPSState
*env
, uint32_t value
);
203 void cpu_mips_store_compare(CPUMIPSState
*env
, uint32_t value
);
204 void cpu_mips_start_count(CPUMIPSState
*env
);
205 void cpu_mips_stop_count(CPUMIPSState
*env
);
208 bool mips_cpu_tlb_fill(CPUState
*cs
, vaddr address
, int size
,
209 MMUAccessType access_type
, int mmu_idx
,
210 bool probe
, uintptr_t retaddr
);
213 uint32_t float_class_s(uint32_t arg
, float_status
*fst
);
214 uint64_t float_class_d(uint64_t arg
, float_status
*fst
);
216 extern unsigned int ieee_rm
[];
217 int ieee_ex_to_mips(int xcpt
);
218 void update_pagemask(CPUMIPSState
*env
, target_ulong arg1
, int32_t *pagemask
);
220 static inline void restore_rounding_mode(CPUMIPSState
*env
)
222 set_float_rounding_mode(ieee_rm
[env
->active_fpu
.fcr31
& 3],
223 &env
->active_fpu
.fp_status
);
226 static inline void restore_flush_mode(CPUMIPSState
*env
)
228 set_flush_to_zero((env
->active_fpu
.fcr31
& (1 << FCR31_FS
)) != 0,
229 &env
->active_fpu
.fp_status
);
232 static inline void restore_snan_bit_mode(CPUMIPSState
*env
)
234 set_snan_bit_is_one((env
->active_fpu
.fcr31
& (1 << FCR31_NAN2008
)) == 0,
235 &env
->active_fpu
.fp_status
);
238 static inline void restore_fp_status(CPUMIPSState
*env
)
240 restore_rounding_mode(env
);
241 restore_flush_mode(env
);
242 restore_snan_bit_mode(env
);
245 static inline void restore_msa_fp_status(CPUMIPSState
*env
)
247 float_status
*status
= &env
->active_tc
.msa_fp_status
;
248 int rounding_mode
= (env
->active_tc
.msacsr
& MSACSR_RM_MASK
) >> MSACSR_RM
;
249 bool flush_to_zero
= (env
->active_tc
.msacsr
& MSACSR_FS_MASK
) != 0;
251 set_float_rounding_mode(ieee_rm
[rounding_mode
], status
);
252 set_flush_to_zero(flush_to_zero
, status
);
253 set_flush_inputs_to_zero(flush_to_zero
, status
);
256 static inline void restore_pamask(CPUMIPSState
*env
)
258 if (env
->hflags
& MIPS_HFLAG_ELPA
) {
259 env
->PAMask
= (1ULL << env
->PABITS
) - 1;
261 env
->PAMask
= PAMASK_BASE
;
265 static inline int mips_vpe_active(CPUMIPSState
*env
)
269 /* Check that the VPE is enabled. */
270 if (!(env
->mvp
->CP0_MVPControl
& (1 << CP0MVPCo_EVP
))) {
273 /* Check that the VPE is activated. */
274 if (!(env
->CP0_VPEConf0
& (1 << CP0VPEC0_VPA
))) {
278 /* Now verify that there are active thread contexts in the VPE.
280 This assumes the CPU model will internally reschedule threads
281 if the active one goes to sleep. If there are no threads available
282 the active one will be in a sleeping state, and we can turn off
284 if (!(env
->active_tc
.CP0_TCStatus
& (1 << CP0TCSt_A
))) {
285 /* TC is not activated. */
288 if (env
->active_tc
.CP0_TCHalt
& 1) {
289 /* TC is in halt state. */
296 static inline int mips_vp_active(CPUMIPSState
*env
)
298 CPUState
*other_cs
= first_cpu
;
300 /* Check if the VP disabled other VPs (which means the VP is enabled) */
301 if ((env
->CP0_VPControl
>> CP0VPCtl_DIS
) & 1) {
305 /* Check if the virtual processor is disabled due to a DVP */
306 CPU_FOREACH(other_cs
) {
307 MIPSCPU
*other_cpu
= MIPS_CPU(other_cs
);
308 if ((&other_cpu
->env
!= env
) &&
309 ((other_cpu
->env
.CP0_VPControl
>> CP0VPCtl_DIS
) & 1)) {
316 static inline void compute_hflags(CPUMIPSState
*env
)
318 env
->hflags
&= ~(MIPS_HFLAG_COP1X
| MIPS_HFLAG_64
| MIPS_HFLAG_CP0
|
319 MIPS_HFLAG_F64
| MIPS_HFLAG_FPU
| MIPS_HFLAG_KSU
|
320 MIPS_HFLAG_AWRAP
| MIPS_HFLAG_DSP
| MIPS_HFLAG_DSP_R2
|
321 MIPS_HFLAG_DSP_R3
| MIPS_HFLAG_SBRI
| MIPS_HFLAG_MSA
|
322 MIPS_HFLAG_FRE
| MIPS_HFLAG_ELPA
| MIPS_HFLAG_ERL
);
323 if (env
->CP0_Status
& (1 << CP0St_ERL
)) {
324 env
->hflags
|= MIPS_HFLAG_ERL
;
326 if (!(env
->CP0_Status
& (1 << CP0St_EXL
)) &&
327 !(env
->CP0_Status
& (1 << CP0St_ERL
)) &&
328 !(env
->hflags
& MIPS_HFLAG_DM
)) {
329 env
->hflags
|= (env
->CP0_Status
>> CP0St_KSU
) & MIPS_HFLAG_KSU
;
331 #if defined(TARGET_MIPS64)
332 if ((env
->insn_flags
& ISA_MIPS3
) &&
333 (((env
->hflags
& MIPS_HFLAG_KSU
) != MIPS_HFLAG_UM
) ||
334 (env
->CP0_Status
& (1 << CP0St_PX
)) ||
335 (env
->CP0_Status
& (1 << CP0St_UX
)))) {
336 env
->hflags
|= MIPS_HFLAG_64
;
339 if (!(env
->insn_flags
& ISA_MIPS3
)) {
340 env
->hflags
|= MIPS_HFLAG_AWRAP
;
341 } else if (((env
->hflags
& MIPS_HFLAG_KSU
) == MIPS_HFLAG_UM
) &&
342 !(env
->CP0_Status
& (1 << CP0St_UX
))) {
343 env
->hflags
|= MIPS_HFLAG_AWRAP
;
344 } else if (env
->insn_flags
& ISA_MIPS64R6
) {
345 /* Address wrapping for Supervisor and Kernel is specified in R6 */
346 if ((((env
->hflags
& MIPS_HFLAG_KSU
) == MIPS_HFLAG_SM
) &&
347 !(env
->CP0_Status
& (1 << CP0St_SX
))) ||
348 (((env
->hflags
& MIPS_HFLAG_KSU
) == MIPS_HFLAG_KM
) &&
349 !(env
->CP0_Status
& (1 << CP0St_KX
)))) {
350 env
->hflags
|= MIPS_HFLAG_AWRAP
;
354 if (((env
->CP0_Status
& (1 << CP0St_CU0
)) &&
355 !(env
->insn_flags
& ISA_MIPS32R6
)) ||
356 !(env
->hflags
& MIPS_HFLAG_KSU
)) {
357 env
->hflags
|= MIPS_HFLAG_CP0
;
359 if (env
->CP0_Status
& (1 << CP0St_CU1
)) {
360 env
->hflags
|= MIPS_HFLAG_FPU
;
362 if (env
->CP0_Status
& (1 << CP0St_FR
)) {
363 env
->hflags
|= MIPS_HFLAG_F64
;
365 if (((env
->hflags
& MIPS_HFLAG_KSU
) != MIPS_HFLAG_KM
) &&
366 (env
->CP0_Config5
& (1 << CP0C5_SBRI
))) {
367 env
->hflags
|= MIPS_HFLAG_SBRI
;
369 if (env
->insn_flags
& ASE_DSP_R3
) {
371 * Our cpu supports DSP R3 ASE, so enable
372 * access to DSP R3 resources.
374 if (env
->CP0_Status
& (1 << CP0St_MX
)) {
375 env
->hflags
|= MIPS_HFLAG_DSP
| MIPS_HFLAG_DSP_R2
|
378 } else if (env
->insn_flags
& ASE_DSP_R2
) {
380 * Our cpu supports DSP R2 ASE, so enable
381 * access to DSP R2 resources.
383 if (env
->CP0_Status
& (1 << CP0St_MX
)) {
384 env
->hflags
|= MIPS_HFLAG_DSP
| MIPS_HFLAG_DSP_R2
;
387 } else if (env
->insn_flags
& ASE_DSP
) {
389 * Our cpu supports DSP ASE, so enable
390 * access to DSP resources.
392 if (env
->CP0_Status
& (1 << CP0St_MX
)) {
393 env
->hflags
|= MIPS_HFLAG_DSP
;
397 if (env
->insn_flags
& ISA_MIPS32R2
) {
398 if (env
->active_fpu
.fcr0
& (1 << FCR0_F64
)) {
399 env
->hflags
|= MIPS_HFLAG_COP1X
;
401 } else if (env
->insn_flags
& ISA_MIPS32
) {
402 if (env
->hflags
& MIPS_HFLAG_64
) {
403 env
->hflags
|= MIPS_HFLAG_COP1X
;
405 } else if (env
->insn_flags
& ISA_MIPS4
) {
406 /* All supported MIPS IV CPUs use the XX (CU3) to enable
407 and disable the MIPS IV extensions to the MIPS III ISA.
408 Some other MIPS IV CPUs ignore the bit, so the check here
409 would be too restrictive for them. */
410 if (env
->CP0_Status
& (1U << CP0St_CU3
)) {
411 env
->hflags
|= MIPS_HFLAG_COP1X
;
414 if (env
->insn_flags
& ASE_MSA
) {
415 if (env
->CP0_Config5
& (1 << CP0C5_MSAEn
)) {
416 env
->hflags
|= MIPS_HFLAG_MSA
;
419 if (env
->active_fpu
.fcr0
& (1 << FCR0_FREP
)) {
420 if (env
->CP0_Config5
& (1 << CP0C5_FRE
)) {
421 env
->hflags
|= MIPS_HFLAG_FRE
;
424 if (env
->CP0_Config3
& (1 << CP0C3_LPA
)) {
425 if (env
->CP0_PageGrain
& (1 << CP0PG_ELPA
)) {
426 env
->hflags
|= MIPS_HFLAG_ELPA
;
431 void cpu_mips_tlb_flush(CPUMIPSState
*env
);
432 void sync_c0_status(CPUMIPSState
*env
, CPUMIPSState
*cpu
, int tc
);
433 void cpu_mips_store_status(CPUMIPSState
*env
, target_ulong val
);
434 void cpu_mips_store_cause(CPUMIPSState
*env
, target_ulong val
);
436 void QEMU_NORETURN
do_raise_exception_err(CPUMIPSState
*env
, uint32_t exception
,
437 int error_code
, uintptr_t pc
);
439 static inline void QEMU_NORETURN
do_raise_exception(CPUMIPSState
*env
,
443 do_raise_exception_err(env
, exception
, 0, pc
);