1#if !defined (__MIPS_CPU_H__)
2#define __MIPS_CPU_H__
3
4#define TARGET_HAS_ICE 1
5
6#define ELF_MACHINE EM_MIPS
7
8#define CPUState struct CPUMIPSState
9
10#include "config.h"
11#include "qemu-common.h"
12#include "mips-defs.h"
13#include "cpu-defs.h"
14#include "softfloat.h"
15
16
17
18#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
19typedef unsigned char uint_fast8_t;
20typedef unsigned int uint_fast16_t;
21#endif
22
23struct CPUMIPSState;
24
25typedef struct r4k_tlb_t r4k_tlb_t;
26struct r4k_tlb_t {
27 target_ulong VPN;
28 uint32_t PageMask;
29 uint_fast8_t ASID;
30 uint_fast16_t G:1;
31 uint_fast16_t C0:3;
32 uint_fast16_t C1:3;
33 uint_fast16_t V0:1;
34 uint_fast16_t V1:1;
35 uint_fast16_t D0:1;
36 uint_fast16_t D1:1;
37 target_ulong PFN[2];
38};
39
40#if !defined(CONFIG_USER_ONLY)
41typedef struct CPUMIPSTLBContext CPUMIPSTLBContext;
42struct CPUMIPSTLBContext {
43 uint32_t nb_tlb;
44 uint32_t tlb_in_use;
45 int (*map_address) (struct CPUMIPSState *env, target_phys_addr_t *physical, int *prot, target_ulong address, int rw, int access_type);
46 void (*helper_tlbwi) (void);
47 void (*helper_tlbwr) (void);
48 void (*helper_tlbp) (void);
49 void (*helper_tlbr) (void);
50 union {
51 struct {
52 r4k_tlb_t tlb[MIPS_TLB_MAX];
53 } r4k;
54 } mmu;
55};
56#endif
57
58typedef union fpr_t fpr_t;
59union fpr_t {
60 float64 fd;
61 float32 fs[2];
62 uint64_t d;
63 uint32_t w[2];
64};
65
66
67
68#if defined(HOST_WORDS_BIGENDIAN)
69# define FP_ENDIAN_IDX 1
70#else
71# define FP_ENDIAN_IDX 0
72#endif
73
74typedef struct CPUMIPSFPUContext CPUMIPSFPUContext;
75struct CPUMIPSFPUContext {
76
77 fpr_t fpr[32];
78 float_status fp_status;
79
80 uint32_t fcr0;
81#define FCR0_F64 22
82#define FCR0_L 21
83#define FCR0_W 20
84#define FCR0_3D 19
85#define FCR0_PS 18
86#define FCR0_D 17
87#define FCR0_S 16
88#define FCR0_PRID 8
89#define FCR0_REV 0
90
91 uint32_t fcr31;
92#define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
93#define CLEAR_FP_COND(num,env) do { ((env).fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
94#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1))
95#define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f)
96#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
97#define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f)
98#define SET_FP_CAUSE(reg,v) do { (reg) = ((reg) & ~(0x3f << 12)) | ((v & 0x3f) << 12); } while(0)
99#define SET_FP_ENABLE(reg,v) do { (reg) = ((reg) & ~(0x1f << 7)) | ((v & 0x1f) << 7); } while(0)
100#define SET_FP_FLAGS(reg,v) do { (reg) = ((reg) & ~(0x1f << 2)) | ((v & 0x1f) << 2); } while(0)
101#define UPDATE_FP_FLAGS(reg,v) do { (reg) |= ((v & 0x1f) << 2); } while(0)
102#define FP_INEXACT 1
103#define FP_UNDERFLOW 2
104#define FP_OVERFLOW 4
105#define FP_DIV0 8
106#define FP_INVALID 16
107#define FP_UNIMPLEMENTED 32
108};
109
110#define NB_MMU_MODES 3
111
112typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
113struct CPUMIPSMVPContext {
114 int32_t CP0_MVPControl;
115#define CP0MVPCo_CPA 3
116#define CP0MVPCo_STLB 2
117#define CP0MVPCo_VPC 1
118#define CP0MVPCo_EVP 0
119 int32_t CP0_MVPConf0;
120#define CP0MVPC0_M 31
121#define CP0MVPC0_TLBS 29
122#define CP0MVPC0_GS 28
123#define CP0MVPC0_PCP 27
124#define CP0MVPC0_PTLBE 16
125#define CP0MVPC0_TCA 15
126#define CP0MVPC0_PVPE 10
127#define CP0MVPC0_PTC 0
128 int32_t CP0_MVPConf1;
129#define CP0MVPC1_CIM 31
130#define CP0MVPC1_CIF 30
131#define CP0MVPC1_PCX 20
132#define CP0MVPC1_PCP2 10
133#define CP0MVPC1_PCP1 0
134};
135
136typedef struct mips_def_t mips_def_t;
137
138#define MIPS_SHADOW_SET_MAX 16
139#define MIPS_TC_MAX 5
140#define MIPS_FPU_MAX 1
141#define MIPS_DSP_ACC 4
142
143typedef struct TCState TCState;
144struct TCState {
145 target_ulong gpr[32];
146 target_ulong PC;
147 target_ulong HI[MIPS_DSP_ACC];
148 target_ulong LO[MIPS_DSP_ACC];
149 target_ulong ACX[MIPS_DSP_ACC];
150 target_ulong DSPControl;
151 int32_t CP0_TCStatus;
152#define CP0TCSt_TCU3 31
153#define CP0TCSt_TCU2 30
154#define CP0TCSt_TCU1 29
155#define CP0TCSt_TCU0 28
156#define CP0TCSt_TMX 27
157#define CP0TCSt_RNST 23
158#define CP0TCSt_TDS 21
159#define CP0TCSt_DT 20
160#define CP0TCSt_DA 15
161#define CP0TCSt_A 13
162#define CP0TCSt_TKSU 11
163#define CP0TCSt_IXMT 10
164#define CP0TCSt_TASID 0
165 int32_t CP0_TCBind;
166#define CP0TCBd_CurTC 21
167#define CP0TCBd_TBE 17
168#define CP0TCBd_CurVPE 0
169 target_ulong CP0_TCHalt;
170 target_ulong CP0_TCContext;
171 target_ulong CP0_TCSchedule;
172 target_ulong CP0_TCScheFBack;
173 int32_t CP0_Debug_tcstatus;
174};
175
176typedef struct CPUMIPSState CPUMIPSState;
177struct CPUMIPSState {
178 TCState active_tc;
179 CPUMIPSFPUContext active_fpu;
180
181 uint32_t current_tc;
182 uint32_t current_fpu;
183
184 uint32_t SEGBITS;
185 uint32_t PABITS;
186 target_ulong SEGMask;
187 target_ulong PAMask;
188
189 int32_t CP0_Index;
190
191 int32_t CP0_Random;
192 int32_t CP0_VPEControl;
193#define CP0VPECo_YSI 21
194#define CP0VPECo_GSI 20
195#define CP0VPECo_EXCPT 16
196#define CP0VPECo_TE 15
197#define CP0VPECo_TargTC 0
198 int32_t CP0_VPEConf0;
199#define CP0VPEC0_M 31
200#define CP0VPEC0_XTC 21
201#define CP0VPEC0_TCS 19
202#define CP0VPEC0_SCS 18
203#define CP0VPEC0_DSC 17
204#define CP0VPEC0_ICS 16
205#define CP0VPEC0_MVP 1
206#define CP0VPEC0_VPA 0
207 int32_t CP0_VPEConf1;
208#define CP0VPEC1_NCX 20
209#define CP0VPEC1_NCP2 10
210#define CP0VPEC1_NCP1 0
211 target_ulong CP0_YQMask;
212 target_ulong CP0_VPESchedule;
213 target_ulong CP0_VPEScheFBack;
214 int32_t CP0_VPEOpt;
215#define CP0VPEOpt_IWX7 15
216#define CP0VPEOpt_IWX6 14
217#define CP0VPEOpt_IWX5 13
218#define CP0VPEOpt_IWX4 12
219#define CP0VPEOpt_IWX3 11
220#define CP0VPEOpt_IWX2 10
221#define CP0VPEOpt_IWX1 9
222#define CP0VPEOpt_IWX0 8
223#define CP0VPEOpt_DWX7 7
224#define CP0VPEOpt_DWX6 6
225#define CP0VPEOpt_DWX5 5
226#define CP0VPEOpt_DWX4 4
227#define CP0VPEOpt_DWX3 3
228#define CP0VPEOpt_DWX2 2
229#define CP0VPEOpt_DWX1 1
230#define CP0VPEOpt_DWX0 0
231 target_ulong CP0_EntryLo0;
232 target_ulong CP0_EntryLo1;
233 target_ulong CP0_Context;
234 int32_t CP0_PageMask;
235 int32_t CP0_PageGrain;
236 int32_t CP0_Wired;
237 int32_t CP0_SRSConf0_rw_bitmask;
238 int32_t CP0_SRSConf0;
239#define CP0SRSC0_M 31
240#define CP0SRSC0_SRS3 20
241#define CP0SRSC0_SRS2 10
242#define CP0SRSC0_SRS1 0
243 int32_t CP0_SRSConf1_rw_bitmask;
244 int32_t CP0_SRSConf1;
245#define CP0SRSC1_M 31
246#define CP0SRSC1_SRS6 20
247#define CP0SRSC1_SRS5 10
248#define CP0SRSC1_SRS4 0
249 int32_t CP0_SRSConf2_rw_bitmask;
250 int32_t CP0_SRSConf2;
251#define CP0SRSC2_M 31
252#define CP0SRSC2_SRS9 20
253#define CP0SRSC2_SRS8 10
254#define CP0SRSC2_SRS7 0
255 int32_t CP0_SRSConf3_rw_bitmask;
256 int32_t CP0_SRSConf3;
257#define CP0SRSC3_M 31
258#define CP0SRSC3_SRS12 20
259#define CP0SRSC3_SRS11 10
260#define CP0SRSC3_SRS10 0
261 int32_t CP0_SRSConf4_rw_bitmask;
262 int32_t CP0_SRSConf4;
263#define CP0SRSC4_SRS15 20
264#define CP0SRSC4_SRS14 10
265#define CP0SRSC4_SRS13 0
266 int32_t CP0_HWREna;
267 target_ulong CP0_BadVAddr;
268 int32_t CP0_Count;
269 target_ulong CP0_EntryHi;
270 int32_t CP0_Compare;
271 int32_t CP0_Status;
272#define CP0St_CU3 31
273#define CP0St_CU2 30
274#define CP0St_CU1 29
275#define CP0St_CU0 28
276#define CP0St_RP 27
277#define CP0St_FR 26
278#define CP0St_RE 25
279#define CP0St_MX 24
280#define CP0St_PX 23
281#define CP0St_BEV 22
282#define CP0St_TS 21
283#define CP0St_SR 20
284#define CP0St_NMI 19
285#define CP0St_IM 8
286#define CP0St_KX 7
287#define CP0St_SX 6
288#define CP0St_UX 5
289#define CP0St_KSU 3
290#define CP0St_ERL 2
291#define CP0St_EXL 1
292#define CP0St_IE 0
293 int32_t CP0_IntCtl;
294#define CP0IntCtl_IPTI 29
295#define CP0IntCtl_IPPC1 26
296#define CP0IntCtl_VS 5
297 int32_t CP0_SRSCtl;
298#define CP0SRSCtl_HSS 26
299#define CP0SRSCtl_EICSS 18
300#define CP0SRSCtl_ESS 12
301#define CP0SRSCtl_PSS 6
302#define CP0SRSCtl_CSS 0
303 int32_t CP0_SRSMap;
304#define CP0SRSMap_SSV7 28
305#define CP0SRSMap_SSV6 24
306#define CP0SRSMap_SSV5 20
307#define CP0SRSMap_SSV4 16
308#define CP0SRSMap_SSV3 12
309#define CP0SRSMap_SSV2 8
310#define CP0SRSMap_SSV1 4
311#define CP0SRSMap_SSV0 0
312 int32_t CP0_Cause;
313#define CP0Ca_BD 31
314#define CP0Ca_TI 30
315#define CP0Ca_CE 28
316#define CP0Ca_DC 27
317#define CP0Ca_PCI 26
318#define CP0Ca_IV 23
319#define CP0Ca_WP 22
320#define CP0Ca_IP 8
321#define CP0Ca_IP_mask 0x0000FF00
322#define CP0Ca_EC 2
323 target_ulong CP0_EPC;
324 int32_t CP0_PRid;
325 int32_t CP0_EBase;
326 int32_t CP0_Config0;
327#define CP0C0_M 31
328#define CP0C0_K23 28
329#define CP0C0_KU 25
330#define CP0C0_MDU 20
331#define CP0C0_MM 17
332#define CP0C0_BM 16
333#define CP0C0_BE 15
334#define CP0C0_AT 13
335#define CP0C0_AR 10
336#define CP0C0_MT 7
337#define CP0C0_VI 3
338#define CP0C0_K0 0
339 int32_t CP0_Config1;
340#define CP0C1_M 31
341#define CP0C1_MMU 25
342#define CP0C1_IS 22
343#define CP0C1_IL 19
344#define CP0C1_IA 16
345#define CP0C1_DS 13
346#define CP0C1_DL 10
347#define CP0C1_DA 7
348#define CP0C1_C2 6
349#define CP0C1_MD 5
350#define CP0C1_PC 4
351#define CP0C1_WR 3
352#define CP0C1_CA 2
353#define CP0C1_EP 1
354#define CP0C1_FP 0
355 int32_t CP0_Config2;
356#define CP0C2_M 31
357#define CP0C2_TU 28
358#define CP0C2_TS 24
359#define CP0C2_TL 20
360#define CP0C2_TA 16
361#define CP0C2_SU 12
362#define CP0C2_SS 8
363#define CP0C2_SL 4
364#define CP0C2_SA 0
365 int32_t CP0_Config3;
366#define CP0C3_M 31
367#define CP0C3_ISA_ON_EXC 16
368#define CP0C3_DSPP 10
369#define CP0C3_LPA 7
370#define CP0C3_VEIC 6
371#define CP0C3_VInt 5
372#define CP0C3_SP 4
373#define CP0C3_MT 2
374#define CP0C3_SM 1
375#define CP0C3_TL 0
376 int32_t CP0_Config6;
377 int32_t CP0_Config7;
378
379 target_ulong lladdr;
380 target_ulong llval;
381 target_ulong llnewval;
382 target_ulong llreg;
383 target_ulong CP0_LLAddr_rw_bitmask;
384 int CP0_LLAddr_shift;
385 target_ulong CP0_WatchLo[8];
386 int32_t CP0_WatchHi[8];
387 target_ulong CP0_XContext;
388 int32_t CP0_Framemask;
389 int32_t CP0_Debug;
390#define CP0DB_DBD 31
391#define CP0DB_DM 30
392#define CP0DB_LSNM 28
393#define CP0DB_Doze 27
394#define CP0DB_Halt 26
395#define CP0DB_CNT 25
396#define CP0DB_IBEP 24
397#define CP0DB_DBEP 21
398#define CP0DB_IEXI 20
399#define CP0DB_VER 15
400#define CP0DB_DEC 10
401#define CP0DB_SSt 8
402#define CP0DB_DINT 5
403#define CP0DB_DIB 4
404#define CP0DB_DDBS 3
405#define CP0DB_DDBL 2
406#define CP0DB_DBp 1
407#define CP0DB_DSS 0
408 target_ulong CP0_DEPC;
409 int32_t CP0_Performance0;
410 int32_t CP0_TagLo;
411 int32_t CP0_DataLo;
412 int32_t CP0_TagHi;
413 int32_t CP0_DataHi;
414 target_ulong CP0_ErrorEPC;
415 int32_t CP0_DESAVE;
416
417 TCState tcs[MIPS_SHADOW_SET_MAX];
418 CPUMIPSFPUContext fpus[MIPS_FPU_MAX];
419
420 int error_code;
421 uint32_t hflags;
422
423#define MIPS_HFLAG_TMASK 0x007FF
424#define MIPS_HFLAG_MODE 0x00007
425
426
427
428#define MIPS_HFLAG_KSU 0x00003
429#define MIPS_HFLAG_UM 0x00002
430#define MIPS_HFLAG_SM 0x00001
431#define MIPS_HFLAG_KM 0x00000
432#define MIPS_HFLAG_DM 0x00004
433#define MIPS_HFLAG_64 0x00008
434#define MIPS_HFLAG_CP0 0x00010
435#define MIPS_HFLAG_FPU 0x00020
436#define MIPS_HFLAG_F64 0x00040
437
438
439
440#define MIPS_HFLAG_COP1X 0x00080
441#define MIPS_HFLAG_RE 0x00100
442#define MIPS_HFLAG_UX 0x00200
443#define MIPS_HFLAG_M16 0x00400
444#define MIPS_HFLAG_M16_SHIFT 10
445
446
447
448
449#define MIPS_HFLAG_BMASK_BASE 0x03800
450#define MIPS_HFLAG_B 0x00800
451#define MIPS_HFLAG_BC 0x01000
452#define MIPS_HFLAG_BL 0x01800
453#define MIPS_HFLAG_BR 0x02000
454
455#define MIPS_HFLAG_BMASK_EXT 0x3C000
456#define MIPS_HFLAG_B16 0x04000
457#define MIPS_HFLAG_BDS16 0x08000
458#define MIPS_HFLAG_BDS32 0x10000
459#define MIPS_HFLAG_BX 0x20000
460#define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT)
461 target_ulong btarget;
462 target_ulong bcond;
463
464 int SYNCI_Step;
465 int CCRes;
466 uint32_t CP0_Status_rw_bitmask;
467 uint32_t CP0_TCStatus_rw_bitmask;
468 int insn_flags;
469
470 target_ulong tls_value;
471
472 CPU_COMMON
473
474 CPUMIPSMVPContext *mvp;
475#if !defined(CONFIG_USER_ONLY)
476 CPUMIPSTLBContext *tlb;
477#endif
478
479 const mips_def_t *cpu_model;
480 void *irq[8];
481 struct QEMUTimer *timer;
482};
483
484#if !defined(CONFIG_USER_ONLY)
485int no_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
486 target_ulong address, int rw, int access_type);
487int fixed_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
488 target_ulong address, int rw, int access_type);
489int r4k_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
490 target_ulong address, int rw, int access_type);
491void r4k_helper_tlbwi (void);
492void r4k_helper_tlbwr (void);
493void r4k_helper_tlbp (void);
494void r4k_helper_tlbr (void);
495
496void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
497 int unused, int size);
498#endif
499
500void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
501
502#define cpu_init cpu_mips_init
503#define cpu_exec cpu_mips_exec
504#define cpu_gen_code cpu_mips_gen_code
505#define cpu_signal_handler cpu_mips_signal_handler
506#define cpu_list mips_cpu_list
507
508#define CPU_SAVE_VERSION 3
509
510
511
512#define MMU_MODE0_SUFFIX _kernel
513#define MMU_MODE1_SUFFIX _super
514#define MMU_MODE2_SUFFIX _user
515#define MMU_USER_IDX 2
516static inline int cpu_mmu_index (CPUState *env)
517{
518 return env->hflags & MIPS_HFLAG_KSU;
519}
520
521static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
522{
523 if (newsp)
524 env->active_tc.gpr[29] = newsp;
525 env->active_tc.gpr[7] = 0;
526 env->active_tc.gpr[2] = 0;
527}
528
529static inline int cpu_mips_hw_interrupts_pending(CPUState *env)
530{
531 int32_t pending;
532 int32_t status;
533 int r;
534
535 if (!(env->CP0_Status & (1 << CP0St_IE)) ||
536 (env->CP0_Status & (1 << CP0St_EXL)) ||
537 (env->CP0_Status & (1 << CP0St_ERL)) ||
538 (env->hflags & MIPS_HFLAG_DM)) {
539
540 return 0;
541 }
542
543 pending = env->CP0_Cause & CP0Ca_IP_mask;
544 status = env->CP0_Status & CP0Ca_IP_mask;
545
546 if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
547
548
549
550 r = pending > status;
551 } else {
552
553
554
555 r = pending & status;
556 }
557 return r;
558}
559
560#include "cpu-all.h"
561
562
563
564
565enum {
566
567 ACCESS_USER = 0x00,
568 ACCESS_SUPER = 0x01,
569
570 ACCESS_STORE = 0x02,
571
572 ACCESS_CODE = 0x10,
573 ACCESS_INT = 0x20,
574 ACCESS_FLOAT = 0x30,
575};
576
577
578enum {
579 EXCP_NONE = -1,
580 EXCP_RESET = 0,
581 EXCP_SRESET,
582 EXCP_DSS,
583 EXCP_DINT,
584 EXCP_DDBL,
585 EXCP_DDBS,
586 EXCP_NMI,
587 EXCP_MCHECK,
588 EXCP_EXT_INTERRUPT,
589 EXCP_DFWATCH,
590 EXCP_DIB,
591 EXCP_IWATCH,
592 EXCP_AdEL,
593 EXCP_AdES,
594 EXCP_TLBF,
595 EXCP_IBE,
596 EXCP_DBp,
597 EXCP_SYSCALL,
598 EXCP_BREAK,
599 EXCP_CpU,
600 EXCP_RI,
601 EXCP_OVERFLOW,
602 EXCP_TRAP,
603 EXCP_FPE,
604 EXCP_DWATCH,
605 EXCP_LTLBL,
606 EXCP_TLBL,
607 EXCP_TLBS,
608 EXCP_DBE,
609 EXCP_THREAD,
610 EXCP_MDMX,
611 EXCP_C2E,
612 EXCP_CACHE,
613
614 EXCP_LAST = EXCP_CACHE,
615};
616
617#define EXCP_SC 0x100
618
619int cpu_mips_exec(CPUMIPSState *s);
620CPUMIPSState *cpu_mips_init(const char *cpu_model);
621
622int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
623
624
625uint32_t cpu_mips_get_random (CPUState *env);
626uint32_t cpu_mips_get_count (CPUState *env);
627void cpu_mips_store_count (CPUState *env, uint32_t value);
628void cpu_mips_store_compare (CPUState *env, uint32_t value);
629void cpu_mips_start_count(CPUState *env);
630void cpu_mips_stop_count(CPUState *env);
631
632
633void cpu_mips_soft_irq(CPUState *env, int irq, int level);
634
635
636int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
637 int mmu_idx, int is_softmmu);
638#define cpu_handle_mmu_fault cpu_mips_handle_mmu_fault
639void do_interrupt (CPUState *env);
640#if !defined(CONFIG_USER_ONLY)
641void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra);
642target_phys_addr_t cpu_mips_translate_address (CPUState *env, target_ulong address,
643 int rw);
644#endif
645
646static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
647 target_ulong *cs_base, int *flags)
648{
649 *pc = env->active_tc.PC;
650 *cs_base = 0;
651 *flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
652}
653
654static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
655{
656 env->tls_value = newtls;
657}
658
659#endif
660