1#if !defined (__MIPS_CPU_H__)
2#define __MIPS_CPU_H__
3
4
5
6#define ALIGNED_ONLY
7
8#define CPUArchState struct CPUMIPSState
9
10#include "config.h"
11#include "qemu-common.h"
12#include "mips-defs.h"
13#include "exec/cpu-defs.h"
14#include "fpu/softfloat.h"
15
16struct CPUMIPSState;
17
18typedef struct r4k_tlb_t r4k_tlb_t;
19struct r4k_tlb_t {
20 target_ulong VPN;
21 uint32_t PageMask;
22 uint_fast8_t ASID;
23 uint_fast16_t G:1;
24 uint_fast16_t C0:3;
25 uint_fast16_t C1:3;
26 uint_fast16_t V0:1;
27 uint_fast16_t V1:1;
28 uint_fast16_t D0:1;
29 uint_fast16_t D1:1;
30 uint_fast16_t XI0:1;
31 uint_fast16_t XI1:1;
32 uint_fast16_t RI0:1;
33 uint_fast16_t RI1:1;
34 uint_fast16_t EHINV:1;
35 uint64_t PFN[2];
36};
37
38#if !defined(CONFIG_USER_ONLY)
39typedef struct CPUMIPSTLBContext CPUMIPSTLBContext;
40struct CPUMIPSTLBContext {
41 uint32_t nb_tlb;
42 uint32_t tlb_in_use;
43 int (*map_address) (struct CPUMIPSState *env, hwaddr *physical, int *prot, target_ulong address, int rw, int access_type);
44 void (*helper_tlbwi)(struct CPUMIPSState *env);
45 void (*helper_tlbwr)(struct CPUMIPSState *env);
46 void (*helper_tlbp)(struct CPUMIPSState *env);
47 void (*helper_tlbr)(struct CPUMIPSState *env);
48 void (*helper_tlbinv)(struct CPUMIPSState *env);
49 void (*helper_tlbinvf)(struct CPUMIPSState *env);
50 union {
51 struct {
52 r4k_tlb_t tlb[MIPS_TLB_MAX];
53 } r4k;
54 } mmu;
55};
56#endif
57
58
59#define MSA_WRLEN (128)
60
61enum CPUMIPSMSADataFormat {
62 DF_BYTE = 0,
63 DF_HALF,
64 DF_WORD,
65 DF_DOUBLE
66};
67
68typedef union wr_t wr_t;
69union wr_t {
70 int8_t b[MSA_WRLEN/8];
71 int16_t h[MSA_WRLEN/16];
72 int32_t w[MSA_WRLEN/32];
73 int64_t d[MSA_WRLEN/64];
74};
75
76typedef union fpr_t fpr_t;
77union fpr_t {
78 float64 fd;
79 float32 fs[2];
80 uint64_t d;
81 uint32_t w[2];
82
83 wr_t wr;
84};
85
86
87
88#if defined(HOST_WORDS_BIGENDIAN)
89# define FP_ENDIAN_IDX 1
90#else
91# define FP_ENDIAN_IDX 0
92#endif
93
94typedef struct CPUMIPSFPUContext CPUMIPSFPUContext;
95struct CPUMIPSFPUContext {
96
97 fpr_t fpr[32];
98 float_status fp_status;
99
100 uint32_t fcr0;
101#define FCR0_FREP 29
102#define FCR0_UFRP 28
103#define FCR0_F64 22
104#define FCR0_L 21
105#define FCR0_W 20
106#define FCR0_3D 19
107#define FCR0_PS 18
108#define FCR0_D 17
109#define FCR0_S 16
110#define FCR0_PRID 8
111#define FCR0_REV 0
112
113 uint32_t fcr31;
114#define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
115#define CLEAR_FP_COND(num,env) do { ((env).fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
116#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1))
117#define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f)
118#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
119#define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f)
120#define SET_FP_CAUSE(reg,v) do { (reg) = ((reg) & ~(0x3f << 12)) | ((v & 0x3f) << 12); } while(0)
121#define SET_FP_ENABLE(reg,v) do { (reg) = ((reg) & ~(0x1f << 7)) | ((v & 0x1f) << 7); } while(0)
122#define SET_FP_FLAGS(reg,v) do { (reg) = ((reg) & ~(0x1f << 2)) | ((v & 0x1f) << 2); } while(0)
123#define UPDATE_FP_FLAGS(reg,v) do { (reg) |= ((v & 0x1f) << 2); } while(0)
124#define FP_INEXACT 1
125#define FP_UNDERFLOW 2
126#define FP_OVERFLOW 4
127#define FP_DIV0 8
128#define FP_INVALID 16
129#define FP_UNIMPLEMENTED 32
130};
131
132#define NB_MMU_MODES 3
133#define TARGET_INSN_START_EXTRA_WORDS 2
134
135typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
136struct CPUMIPSMVPContext {
137 int32_t CP0_MVPControl;
138#define CP0MVPCo_CPA 3
139#define CP0MVPCo_STLB 2
140#define CP0MVPCo_VPC 1
141#define CP0MVPCo_EVP 0
142 int32_t CP0_MVPConf0;
143#define CP0MVPC0_M 31
144#define CP0MVPC0_TLBS 29
145#define CP0MVPC0_GS 28
146#define CP0MVPC0_PCP 27
147#define CP0MVPC0_PTLBE 16
148#define CP0MVPC0_TCA 15
149#define CP0MVPC0_PVPE 10
150#define CP0MVPC0_PTC 0
151 int32_t CP0_MVPConf1;
152#define CP0MVPC1_CIM 31
153#define CP0MVPC1_CIF 30
154#define CP0MVPC1_PCX 20
155#define CP0MVPC1_PCP2 10
156#define CP0MVPC1_PCP1 0
157};
158
159typedef struct mips_def_t mips_def_t;
160
161#define MIPS_SHADOW_SET_MAX 16
162#define MIPS_TC_MAX 5
163#define MIPS_FPU_MAX 1
164#define MIPS_DSP_ACC 4
165#define MIPS_KSCRATCH_NUM 6
166
167typedef struct TCState TCState;
168struct TCState {
169 target_ulong gpr[32];
170 target_ulong PC;
171 target_ulong HI[MIPS_DSP_ACC];
172 target_ulong LO[MIPS_DSP_ACC];
173 target_ulong ACX[MIPS_DSP_ACC];
174 target_ulong DSPControl;
175 int32_t CP0_TCStatus;
176#define CP0TCSt_TCU3 31
177#define CP0TCSt_TCU2 30
178#define CP0TCSt_TCU1 29
179#define CP0TCSt_TCU0 28
180#define CP0TCSt_TMX 27
181#define CP0TCSt_RNST 23
182#define CP0TCSt_TDS 21
183#define CP0TCSt_DT 20
184#define CP0TCSt_DA 15
185#define CP0TCSt_A 13
186#define CP0TCSt_TKSU 11
187#define CP0TCSt_IXMT 10
188#define CP0TCSt_TASID 0
189 int32_t CP0_TCBind;
190#define CP0TCBd_CurTC 21
191#define CP0TCBd_TBE 17
192#define CP0TCBd_CurVPE 0
193 target_ulong CP0_TCHalt;
194 target_ulong CP0_TCContext;
195 target_ulong CP0_TCSchedule;
196 target_ulong CP0_TCScheFBack;
197 int32_t CP0_Debug_tcstatus;
198 target_ulong CP0_UserLocal;
199
200 int32_t msacsr;
201
202#define MSACSR_FS 24
203#define MSACSR_FS_MASK (1 << MSACSR_FS)
204#define MSACSR_NX 18
205#define MSACSR_NX_MASK (1 << MSACSR_NX)
206#define MSACSR_CEF 2
207#define MSACSR_CEF_MASK (0xffff << MSACSR_CEF)
208#define MSACSR_RM 0
209#define MSACSR_RM_MASK (0x3 << MSACSR_RM)
210#define MSACSR_MASK (MSACSR_RM_MASK | MSACSR_CEF_MASK | MSACSR_NX_MASK | \
211 MSACSR_FS_MASK)
212
213 float_status msa_fp_status;
214};
215
216typedef struct CPUMIPSState CPUMIPSState;
217struct CPUMIPSState {
218 TCState active_tc;
219 CPUMIPSFPUContext active_fpu;
220
221 uint32_t current_tc;
222 uint32_t current_fpu;
223
224 uint32_t SEGBITS;
225 uint32_t PABITS;
226#if defined(TARGET_MIPS64)
227# define PABITS_BASE 36
228#else
229# define PABITS_BASE 32
230#endif
231 target_ulong SEGMask;
232 uint64_t PAMask;
233#define PAMASK_BASE ((1ULL << PABITS_BASE) - 1)
234
235 int32_t msair;
236#define MSAIR_ProcID 8
237#define MSAIR_Rev 0
238
239 int32_t CP0_Index;
240
241 int32_t CP0_Random;
242 int32_t CP0_VPEControl;
243#define CP0VPECo_YSI 21
244#define CP0VPECo_GSI 20
245#define CP0VPECo_EXCPT 16
246#define CP0VPECo_TE 15
247#define CP0VPECo_TargTC 0
248 int32_t CP0_VPEConf0;
249#define CP0VPEC0_M 31
250#define CP0VPEC0_XTC 21
251#define CP0VPEC0_TCS 19
252#define CP0VPEC0_SCS 18
253#define CP0VPEC0_DSC 17
254#define CP0VPEC0_ICS 16
255#define CP0VPEC0_MVP 1
256#define CP0VPEC0_VPA 0
257 int32_t CP0_VPEConf1;
258#define CP0VPEC1_NCX 20
259#define CP0VPEC1_NCP2 10
260#define CP0VPEC1_NCP1 0
261 target_ulong CP0_YQMask;
262 target_ulong CP0_VPESchedule;
263 target_ulong CP0_VPEScheFBack;
264 int32_t CP0_VPEOpt;
265#define CP0VPEOpt_IWX7 15
266#define CP0VPEOpt_IWX6 14
267#define CP0VPEOpt_IWX5 13
268#define CP0VPEOpt_IWX4 12
269#define CP0VPEOpt_IWX3 11
270#define CP0VPEOpt_IWX2 10
271#define CP0VPEOpt_IWX1 9
272#define CP0VPEOpt_IWX0 8
273#define CP0VPEOpt_DWX7 7
274#define CP0VPEOpt_DWX6 6
275#define CP0VPEOpt_DWX5 5
276#define CP0VPEOpt_DWX4 4
277#define CP0VPEOpt_DWX3 3
278#define CP0VPEOpt_DWX2 2
279#define CP0VPEOpt_DWX1 1
280#define CP0VPEOpt_DWX0 0
281 uint64_t CP0_EntryLo0;
282 uint64_t CP0_EntryLo1;
283#if defined(TARGET_MIPS64)
284# define CP0EnLo_RI 63
285# define CP0EnLo_XI 62
286#else
287# define CP0EnLo_RI 31
288# define CP0EnLo_XI 30
289#endif
290 target_ulong CP0_Context;
291 target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM];
292 int32_t CP0_PageMask;
293 int32_t CP0_PageGrain_rw_bitmask;
294 int32_t CP0_PageGrain;
295#define CP0PG_RIE 31
296#define CP0PG_XIE 30
297#define CP0PG_ELPA 29
298#define CP0PG_IEC 27
299 int32_t CP0_Wired;
300 int32_t CP0_SRSConf0_rw_bitmask;
301 int32_t CP0_SRSConf0;
302#define CP0SRSC0_M 31
303#define CP0SRSC0_SRS3 20
304#define CP0SRSC0_SRS2 10
305#define CP0SRSC0_SRS1 0
306 int32_t CP0_SRSConf1_rw_bitmask;
307 int32_t CP0_SRSConf1;
308#define CP0SRSC1_M 31
309#define CP0SRSC1_SRS6 20
310#define CP0SRSC1_SRS5 10
311#define CP0SRSC1_SRS4 0
312 int32_t CP0_SRSConf2_rw_bitmask;
313 int32_t CP0_SRSConf2;
314#define CP0SRSC2_M 31
315#define CP0SRSC2_SRS9 20
316#define CP0SRSC2_SRS8 10
317#define CP0SRSC2_SRS7 0
318 int32_t CP0_SRSConf3_rw_bitmask;
319 int32_t CP0_SRSConf3;
320#define CP0SRSC3_M 31
321#define CP0SRSC3_SRS12 20
322#define CP0SRSC3_SRS11 10
323#define CP0SRSC3_SRS10 0
324 int32_t CP0_SRSConf4_rw_bitmask;
325 int32_t CP0_SRSConf4;
326#define CP0SRSC4_SRS15 20
327#define CP0SRSC4_SRS14 10
328#define CP0SRSC4_SRS13 0
329 int32_t CP0_HWREna;
330 target_ulong CP0_BadVAddr;
331 uint32_t CP0_BadInstr;
332 uint32_t CP0_BadInstrP;
333 int32_t CP0_Count;
334 target_ulong CP0_EntryHi;
335#define CP0EnHi_EHINV 10
336 int32_t CP0_Compare;
337 int32_t CP0_Status;
338#define CP0St_CU3 31
339#define CP0St_CU2 30
340#define CP0St_CU1 29
341#define CP0St_CU0 28
342#define CP0St_RP 27
343#define CP0St_FR 26
344#define CP0St_RE 25
345#define CP0St_MX 24
346#define CP0St_PX 23
347#define CP0St_BEV 22
348#define CP0St_TS 21
349#define CP0St_SR 20
350#define CP0St_NMI 19
351#define CP0St_IM 8
352#define CP0St_KX 7
353#define CP0St_SX 6
354#define CP0St_UX 5
355#define CP0St_KSU 3
356#define CP0St_ERL 2
357#define CP0St_EXL 1
358#define CP0St_IE 0
359 int32_t CP0_IntCtl;
360#define CP0IntCtl_IPTI 29
361#define CP0IntCtl_IPPC1 26
362#define CP0IntCtl_VS 5
363 int32_t CP0_SRSCtl;
364#define CP0SRSCtl_HSS 26
365#define CP0SRSCtl_EICSS 18
366#define CP0SRSCtl_ESS 12
367#define CP0SRSCtl_PSS 6
368#define CP0SRSCtl_CSS 0
369 int32_t CP0_SRSMap;
370#define CP0SRSMap_SSV7 28
371#define CP0SRSMap_SSV6 24
372#define CP0SRSMap_SSV5 20
373#define CP0SRSMap_SSV4 16
374#define CP0SRSMap_SSV3 12
375#define CP0SRSMap_SSV2 8
376#define CP0SRSMap_SSV1 4
377#define CP0SRSMap_SSV0 0
378 int32_t CP0_Cause;
379#define CP0Ca_BD 31
380#define CP0Ca_TI 30
381#define CP0Ca_CE 28
382#define CP0Ca_DC 27
383#define CP0Ca_PCI 26
384#define CP0Ca_IV 23
385#define CP0Ca_WP 22
386#define CP0Ca_IP 8
387#define CP0Ca_IP_mask 0x0000FF00
388#define CP0Ca_EC 2
389 target_ulong CP0_EPC;
390 int32_t CP0_PRid;
391 int32_t CP0_EBase;
392 int32_t CP0_Config0;
393#define CP0C0_M 31
394#define CP0C0_K23 28
395#define CP0C0_KU 25
396#define CP0C0_MDU 20
397#define CP0C0_MM 18
398#define CP0C0_BM 16
399#define CP0C0_BE 15
400#define CP0C0_AT 13
401#define CP0C0_AR 10
402#define CP0C0_MT 7
403#define CP0C0_VI 3
404#define CP0C0_K0 0
405 int32_t CP0_Config1;
406#define CP0C1_M 31
407#define CP0C1_MMU 25
408#define CP0C1_IS 22
409#define CP0C1_IL 19
410#define CP0C1_IA 16
411#define CP0C1_DS 13
412#define CP0C1_DL 10
413#define CP0C1_DA 7
414#define CP0C1_C2 6
415#define CP0C1_MD 5
416#define CP0C1_PC 4
417#define CP0C1_WR 3
418#define CP0C1_CA 2
419#define CP0C1_EP 1
420#define CP0C1_FP 0
421 int32_t CP0_Config2;
422#define CP0C2_M 31
423#define CP0C2_TU 28
424#define CP0C2_TS 24
425#define CP0C2_TL 20
426#define CP0C2_TA 16
427#define CP0C2_SU 12
428#define CP0C2_SS 8
429#define CP0C2_SL 4
430#define CP0C2_SA 0
431 int32_t CP0_Config3;
432#define CP0C3_M 31
433#define CP0C3_BPG 30
434#define CP0C3_CMCGR 29
435#define CP0C3_MSAP 28
436#define CP0C3_BP 27
437#define CP0C3_BI 26
438#define CP0C3_IPLW 21
439#define CP0C3_MMAR 18
440#define CP0C3_MCU 17
441#define CP0C3_ISA_ON_EXC 16
442#define CP0C3_ISA 14
443#define CP0C3_ULRI 13
444#define CP0C3_RXI 12
445#define CP0C3_DSP2P 11
446#define CP0C3_DSPP 10
447#define CP0C3_LPA 7
448#define CP0C3_VEIC 6
449#define CP0C3_VInt 5
450#define CP0C3_SP 4
451#define CP0C3_CDMM 3
452#define CP0C3_MT 2
453#define CP0C3_SM 1
454#define CP0C3_TL 0
455 int32_t CP0_Config4;
456 int32_t CP0_Config4_rw_bitmask;
457#define CP0C4_M 31
458#define CP0C4_IE 29
459#define CP0C4_KScrExist 16
460#define CP0C4_MMUExtDef 14
461#define CP0C4_FTLBPageSize 8
462#define CP0C4_FTLBWays 4
463#define CP0C4_FTLBSets 0
464#define CP0C4_MMUSizeExt 0
465 int32_t CP0_Config5;
466 int32_t CP0_Config5_rw_bitmask;
467#define CP0C5_M 31
468#define CP0C5_K 30
469#define CP0C5_CV 29
470#define CP0C5_EVA 28
471#define CP0C5_MSAEn 27
472#define CP0C5_XNP 13
473#define CP0C5_UFE 9
474#define CP0C5_FRE 8
475#define CP0C5_SBRI 6
476#define CP0C5_MVH 5
477#define CP0C5_LLB 4
478#define CP0C5_UFR 2
479#define CP0C5_NFExists 0
480 int32_t CP0_Config6;
481 int32_t CP0_Config7;
482
483 uint64_t lladdr;
484 target_ulong llval;
485 target_ulong llnewval;
486 target_ulong llreg;
487 uint64_t CP0_LLAddr_rw_bitmask;
488 int CP0_LLAddr_shift;
489 target_ulong CP0_WatchLo[8];
490 int32_t CP0_WatchHi[8];
491 target_ulong CP0_XContext;
492 int32_t CP0_Framemask;
493 int32_t CP0_Debug;
494#define CP0DB_DBD 31
495#define CP0DB_DM 30
496#define CP0DB_LSNM 28
497#define CP0DB_Doze 27
498#define CP0DB_Halt 26
499#define CP0DB_CNT 25
500#define CP0DB_IBEP 24
501#define CP0DB_DBEP 21
502#define CP0DB_IEXI 20
503#define CP0DB_VER 15
504#define CP0DB_DEC 10
505#define CP0DB_SSt 8
506#define CP0DB_DINT 5
507#define CP0DB_DIB 4
508#define CP0DB_DDBS 3
509#define CP0DB_DDBL 2
510#define CP0DB_DBp 1
511#define CP0DB_DSS 0
512 target_ulong CP0_DEPC;
513 int32_t CP0_Performance0;
514 uint64_t CP0_TagLo;
515 int32_t CP0_DataLo;
516 int32_t CP0_TagHi;
517 int32_t CP0_DataHi;
518 target_ulong CP0_ErrorEPC;
519 int32_t CP0_DESAVE;
520
521 TCState tcs[MIPS_SHADOW_SET_MAX];
522 CPUMIPSFPUContext fpus[MIPS_FPU_MAX];
523
524 int error_code;
525#define EXCP_TLB_NOMATCH 0x1
526#define EXCP_INST_NOTAVAIL 0x2
527 uint32_t hflags;
528
529#define MIPS_HFLAG_TMASK 0x75807FF
530#define MIPS_HFLAG_MODE 0x00007
531
532
533
534#define MIPS_HFLAG_KSU 0x00003
535#define MIPS_HFLAG_UM 0x00002
536#define MIPS_HFLAG_SM 0x00001
537#define MIPS_HFLAG_KM 0x00000
538#define MIPS_HFLAG_DM 0x00004
539#define MIPS_HFLAG_64 0x00008
540#define MIPS_HFLAG_CP0 0x00010
541#define MIPS_HFLAG_FPU 0x00020
542#define MIPS_HFLAG_F64 0x00040
543
544
545
546#define MIPS_HFLAG_COP1X 0x00080
547#define MIPS_HFLAG_RE 0x00100
548#define MIPS_HFLAG_AWRAP 0x00200
549#define MIPS_HFLAG_M16 0x00400
550#define MIPS_HFLAG_M16_SHIFT 10
551
552
553
554
555#define MIPS_HFLAG_BMASK_BASE 0x803800
556#define MIPS_HFLAG_B 0x00800
557#define MIPS_HFLAG_BC 0x01000
558#define MIPS_HFLAG_BL 0x01800
559#define MIPS_HFLAG_BR 0x02000
560
561#define MIPS_HFLAG_BMASK_EXT 0x7C000
562#define MIPS_HFLAG_B16 0x04000
563#define MIPS_HFLAG_BDS16 0x08000
564#define MIPS_HFLAG_BDS32 0x10000
565#define MIPS_HFLAG_BDS_STRICT 0x20000
566#define MIPS_HFLAG_BX 0x40000
567#define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT)
568
569#define MIPS_HFLAG_DSP 0x080000
570#define MIPS_HFLAG_DSPR2 0x100000
571
572#define MIPS_HFLAG_HWRENA_ULR 0x200000
573#define MIPS_HFLAG_SBRI 0x400000
574#define MIPS_HFLAG_FBNSLOT 0x800000
575#define MIPS_HFLAG_MSA 0x1000000
576#define MIPS_HFLAG_FRE 0x2000000
577#define MIPS_HFLAG_ELPA 0x4000000
578 target_ulong btarget;
579 target_ulong bcond;
580
581 int SYNCI_Step;
582 int CCRes;
583 uint32_t CP0_Status_rw_bitmask;
584 uint32_t CP0_TCStatus_rw_bitmask;
585 int insn_flags;
586
587 CPU_COMMON
588
589
590 CPUMIPSMVPContext *mvp;
591#if !defined(CONFIG_USER_ONLY)
592 CPUMIPSTLBContext *tlb;
593#endif
594
595 const mips_def_t *cpu_model;
596 void *irq[8];
597 QEMUTimer *timer;
598};
599
600#include "cpu-qom.h"
601
602#if !defined(CONFIG_USER_ONLY)
603int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
604 target_ulong address, int rw, int access_type);
605int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
606 target_ulong address, int rw, int access_type);
607int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
608 target_ulong address, int rw, int access_type);
609void r4k_helper_tlbwi(CPUMIPSState *env);
610void r4k_helper_tlbwr(CPUMIPSState *env);
611void r4k_helper_tlbp(CPUMIPSState *env);
612void r4k_helper_tlbr(CPUMIPSState *env);
613void r4k_helper_tlbinv(CPUMIPSState *env);
614void r4k_helper_tlbinvf(CPUMIPSState *env);
615
616void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
617 bool is_write, bool is_exec, int unused,
618 unsigned size);
619#endif
620
621void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
622
623#define cpu_exec cpu_mips_exec
624#define cpu_signal_handler cpu_mips_signal_handler
625#define cpu_list mips_cpu_list
626
627extern void cpu_wrdsp(uint32_t rs, uint32_t mask_num, CPUMIPSState *env);
628extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
629
630
631
632#define MMU_MODE0_SUFFIX _kernel
633#define MMU_MODE1_SUFFIX _super
634#define MMU_MODE2_SUFFIX _user
635#define MMU_USER_IDX 2
636static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch)
637{
638 return env->hflags & MIPS_HFLAG_KSU;
639}
640
641static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env)
642{
643 return (env->CP0_Status & (1 << CP0St_IE)) &&
644 !(env->CP0_Status & (1 << CP0St_EXL)) &&
645 !(env->CP0_Status & (1 << CP0St_ERL)) &&
646 !(env->hflags & MIPS_HFLAG_DM) &&
647
648
649
650 !(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT));
651}
652
653
654static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
655{
656 int32_t pending;
657 int32_t status;
658 bool r;
659
660 pending = env->CP0_Cause & CP0Ca_IP_mask;
661 status = env->CP0_Status & CP0Ca_IP_mask;
662
663 if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
664
665
666
667 r = pending > status;
668 } else {
669
670
671
672 r = (pending & status) != 0;
673 }
674 return r;
675}
676
677#include "exec/cpu-all.h"
678
679
680
681
682enum {
683
684 ACCESS_USER = 0x00,
685 ACCESS_SUPER = 0x01,
686
687 ACCESS_STORE = 0x02,
688
689 ACCESS_CODE = 0x10,
690 ACCESS_INT = 0x20,
691 ACCESS_FLOAT = 0x30,
692};
693
694
695enum {
696 EXCP_NONE = -1,
697 EXCP_RESET = 0,
698 EXCP_SRESET,
699 EXCP_DSS,
700 EXCP_DINT,
701 EXCP_DDBL,
702 EXCP_DDBS,
703 EXCP_NMI,
704 EXCP_MCHECK,
705 EXCP_EXT_INTERRUPT,
706 EXCP_DFWATCH,
707 EXCP_DIB,
708 EXCP_IWATCH,
709 EXCP_AdEL,
710 EXCP_AdES,
711 EXCP_TLBF,
712 EXCP_IBE,
713 EXCP_DBp,
714 EXCP_SYSCALL,
715 EXCP_BREAK,
716 EXCP_CpU,
717 EXCP_RI,
718 EXCP_OVERFLOW,
719 EXCP_TRAP,
720 EXCP_FPE,
721 EXCP_DWATCH,
722 EXCP_LTLBL,
723 EXCP_TLBL,
724 EXCP_TLBS,
725 EXCP_DBE,
726 EXCP_THREAD,
727 EXCP_MDMX,
728 EXCP_C2E,
729 EXCP_CACHE,
730 EXCP_DSPDIS,
731 EXCP_MSADIS,
732 EXCP_MSAFPE,
733 EXCP_TLBXI,
734 EXCP_TLBRI,
735
736 EXCP_LAST = EXCP_TLBRI,
737};
738
739#define EXCP_SC 0x100
740
741
742
743
744
745
746
747#define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0
748
749int cpu_mips_exec(CPUState *cpu);
750void mips_tcg_init(void);
751MIPSCPU *cpu_mips_init(const char *cpu_model);
752int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
753
754#define cpu_init(cpu_model) CPU(cpu_mips_init(cpu_model))
755
756
757void cpu_state_reset(CPUMIPSState *s);
758
759
760uint32_t cpu_mips_get_random (CPUMIPSState *env);
761uint32_t cpu_mips_get_count (CPUMIPSState *env);
762void cpu_mips_store_count (CPUMIPSState *env, uint32_t value);
763void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value);
764void cpu_mips_start_count(CPUMIPSState *env);
765void cpu_mips_stop_count(CPUMIPSState *env);
766
767
768void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level);
769
770
771int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
772 int mmu_idx);
773#if !defined(CONFIG_USER_ONLY)
774void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra);
775hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address,
776 int rw);
777#endif
778target_ulong exception_resume_pc (CPUMIPSState *env);
779
780
781extern unsigned int ieee_rm[];
782int ieee_ex_to_mips(int xcpt);
783
784static inline void restore_rounding_mode(CPUMIPSState *env)
785{
786 set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3],
787 &env->active_fpu.fp_status);
788}
789
790static inline void restore_flush_mode(CPUMIPSState *env)
791{
792 set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0,
793 &env->active_fpu.fp_status);
794}
795
796static inline void restore_fp_status(CPUMIPSState *env)
797{
798 restore_rounding_mode(env);
799 restore_flush_mode(env);
800}
801
802static inline void restore_msa_fp_status(CPUMIPSState *env)
803{
804 float_status *status = &env->active_tc.msa_fp_status;
805 int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM;
806 bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0;
807
808 set_float_rounding_mode(ieee_rm[rounding_mode], status);
809 set_flush_to_zero(flush_to_zero, status);
810 set_flush_inputs_to_zero(flush_to_zero, status);
811}
812
813static inline void restore_pamask(CPUMIPSState *env)
814{
815 if (env->hflags & MIPS_HFLAG_ELPA) {
816 env->PAMask = (1ULL << env->PABITS) - 1;
817 } else {
818 env->PAMask = PAMASK_BASE;
819 }
820}
821
822static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
823 target_ulong *cs_base, int *flags)
824{
825 *pc = env->active_tc.PC;
826 *cs_base = 0;
827 *flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK |
828 MIPS_HFLAG_HWRENA_ULR);
829}
830
831static inline int mips_vpe_active(CPUMIPSState *env)
832{
833 int active = 1;
834
835
836 if (!(env->mvp->CP0_MVPControl & (1 << CP0MVPCo_EVP))) {
837 active = 0;
838 }
839
840 if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))) {
841 active = 0;
842 }
843
844
845
846
847
848
849
850 if (!(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_A))) {
851
852 active = 0;
853 }
854 if (env->active_tc.CP0_TCHalt & 1) {
855
856 active = 0;
857 }
858
859 return active;
860}
861
862#include "exec/exec-all.h"
863
864static inline void compute_hflags(CPUMIPSState *env)
865{
866 env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
867 MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
868 MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
869 MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE |
870 MIPS_HFLAG_ELPA);
871 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
872 !(env->CP0_Status & (1 << CP0St_ERL)) &&
873 !(env->hflags & MIPS_HFLAG_DM)) {
874 env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
875 }
876#if defined(TARGET_MIPS64)
877 if ((env->insn_flags & ISA_MIPS3) &&
878 (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
879 (env->CP0_Status & (1 << CP0St_PX)) ||
880 (env->CP0_Status & (1 << CP0St_UX)))) {
881 env->hflags |= MIPS_HFLAG_64;
882 }
883
884 if (!(env->insn_flags & ISA_MIPS3)) {
885 env->hflags |= MIPS_HFLAG_AWRAP;
886 } else if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
887 !(env->CP0_Status & (1 << CP0St_UX))) {
888 env->hflags |= MIPS_HFLAG_AWRAP;
889 } else if (env->insn_flags & ISA_MIPS64R6) {
890
891 if ((((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_SM) &&
892 !(env->CP0_Status & (1 << CP0St_SX))) ||
893 (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_KM) &&
894 !(env->CP0_Status & (1 << CP0St_KX)))) {
895 env->hflags |= MIPS_HFLAG_AWRAP;
896 }
897 }
898#endif
899 if (((env->CP0_Status & (1 << CP0St_CU0)) &&
900 !(env->insn_flags & ISA_MIPS32R6)) ||
901 !(env->hflags & MIPS_HFLAG_KSU)) {
902 env->hflags |= MIPS_HFLAG_CP0;
903 }
904 if (env->CP0_Status & (1 << CP0St_CU1)) {
905 env->hflags |= MIPS_HFLAG_FPU;
906 }
907 if (env->CP0_Status & (1 << CP0St_FR)) {
908 env->hflags |= MIPS_HFLAG_F64;
909 }
910 if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_KM) &&
911 (env->CP0_Config5 & (1 << CP0C5_SBRI))) {
912 env->hflags |= MIPS_HFLAG_SBRI;
913 }
914 if (env->insn_flags & ASE_DSPR2) {
915
916
917 if (env->CP0_Status & (1 << CP0St_MX)) {
918 env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2;
919 }
920
921 } else if (env->insn_flags & ASE_DSP) {
922
923
924 if (env->CP0_Status & (1 << CP0St_MX)) {
925 env->hflags |= MIPS_HFLAG_DSP;
926 }
927
928 }
929 if (env->insn_flags & ISA_MIPS32R2) {
930 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
931 env->hflags |= MIPS_HFLAG_COP1X;
932 }
933 } else if (env->insn_flags & ISA_MIPS32) {
934 if (env->hflags & MIPS_HFLAG_64) {
935 env->hflags |= MIPS_HFLAG_COP1X;
936 }
937 } else if (env->insn_flags & ISA_MIPS4) {
938
939
940
941
942 if (env->CP0_Status & (1U << CP0St_CU3)) {
943 env->hflags |= MIPS_HFLAG_COP1X;
944 }
945 }
946 if (env->insn_flags & ASE_MSA) {
947 if (env->CP0_Config5 & (1 << CP0C5_MSAEn)) {
948 env->hflags |= MIPS_HFLAG_MSA;
949 }
950 }
951 if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
952 if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
953 env->hflags |= MIPS_HFLAG_FRE;
954 }
955 }
956 if (env->CP0_Config3 & (1 << CP0C3_LPA)) {
957 if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) {
958 env->hflags |= MIPS_HFLAG_ELPA;
959 }
960 }
961}
962
963#ifndef CONFIG_USER_ONLY
964static inline void cpu_mips_tlb_flush(CPUMIPSState *env, int flush_global)
965{
966 MIPSCPU *cpu = mips_env_get_cpu(env);
967
968
969 tlb_flush(CPU(cpu), flush_global);
970 env->tlb->tlb_in_use = env->tlb->nb_tlb;
971}
972
973
974static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc)
975{
976 int32_t tcstatus, *tcst;
977 uint32_t v = cpu->CP0_Status;
978 uint32_t cu, mx, asid, ksu;
979 uint32_t mask = ((1 << CP0TCSt_TCU3)
980 | (1 << CP0TCSt_TCU2)
981 | (1 << CP0TCSt_TCU1)
982 | (1 << CP0TCSt_TCU0)
983 | (1 << CP0TCSt_TMX)
984 | (3 << CP0TCSt_TKSU)
985 | (0xff << CP0TCSt_TASID));
986
987 cu = (v >> CP0St_CU0) & 0xf;
988 mx = (v >> CP0St_MX) & 0x1;
989 ksu = (v >> CP0St_KSU) & 0x3;
990 asid = env->CP0_EntryHi & 0xff;
991
992 tcstatus = cu << CP0TCSt_TCU0;
993 tcstatus |= mx << CP0TCSt_TMX;
994 tcstatus |= ksu << CP0TCSt_TKSU;
995 tcstatus |= asid;
996
997 if (tc == cpu->current_tc) {
998 tcst = &cpu->active_tc.CP0_TCStatus;
999 } else {
1000 tcst = &cpu->tcs[tc].CP0_TCStatus;
1001 }
1002
1003 *tcst &= ~mask;
1004 *tcst |= tcstatus;
1005 compute_hflags(cpu);
1006}
1007
1008static inline void cpu_mips_store_status(CPUMIPSState *env, target_ulong val)
1009{
1010 uint32_t mask = env->CP0_Status_rw_bitmask;
1011 target_ulong old = env->CP0_Status;
1012
1013 if (env->insn_flags & ISA_MIPS32R6) {
1014 bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3;
1015#if defined(TARGET_MIPS64)
1016 uint32_t ksux = (1 << CP0St_KX) & val;
1017 ksux |= (ksux >> 1) & val;
1018 ksux |= (ksux >> 1) & val;
1019 val = (val & ~(7 << CP0St_UX)) | ksux;
1020#endif
1021 if (has_supervisor && extract32(val, CP0St_KSU, 2) == 0x3) {
1022 mask &= ~(3 << CP0St_KSU);
1023 }
1024 mask &= ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & val);
1025 }
1026
1027 env->CP0_Status = (old & ~mask) | (val & mask);
1028#if defined(TARGET_MIPS64)
1029 if ((env->CP0_Status ^ old) & (old & (7 << CP0St_UX))) {
1030
1031 cpu_mips_tlb_flush(env, 1);
1032 }
1033#endif
1034 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1035 sync_c0_status(env, env, env->current_tc);
1036 } else {
1037 compute_hflags(env);
1038 }
1039}
1040
1041static inline void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val)
1042{
1043 uint32_t mask = 0x00C00300;
1044 uint32_t old = env->CP0_Cause;
1045 int i;
1046
1047 if (env->insn_flags & ISA_MIPS32R2) {
1048 mask |= 1 << CP0Ca_DC;
1049 }
1050 if (env->insn_flags & ISA_MIPS32R6) {
1051 mask &= ~((1 << CP0Ca_WP) & val);
1052 }
1053
1054 env->CP0_Cause = (env->CP0_Cause & ~mask) | (val & mask);
1055
1056 if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1057 if (env->CP0_Cause & (1 << CP0Ca_DC)) {
1058 cpu_mips_stop_count(env);
1059 } else {
1060 cpu_mips_start_count(env);
1061 }
1062 }
1063
1064
1065 for (i = 0 ; i < 2 ; i++) {
1066 if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) {
1067 cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i)));
1068 }
1069 }
1070}
1071#endif
1072
1073static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env,
1074 uint32_t exception,
1075 int error_code,
1076 uintptr_t pc)
1077{
1078 CPUState *cs = CPU(mips_env_get_cpu(env));
1079
1080 if (exception < EXCP_SC) {
1081 qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n",
1082 __func__, exception, error_code);
1083 }
1084 cs->exception_index = exception;
1085 env->error_code = error_code;
1086
1087 cpu_loop_exit_restore(cs, pc);
1088}
1089
1090static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env,
1091 uint32_t exception,
1092 uintptr_t pc)
1093{
1094 do_raise_exception_err(env, exception, 0, pc);
1095}
1096
1097#endif
1098