#define ELF_MACHINE EM_MIPS
+#define CPUState struct CPUMIPSState
+
#include "config.h"
#include "mips-defs.h"
#include "cpu-defs.h"
// uint_fast8_t and uint_fast16_t not in <sys/int_types.h>
// XXX: move that elsewhere
-#if defined(HOST_SOLARIS) && HOST_SOLARIS < 10
+#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
typedef unsigned char uint_fast8_t;
typedef unsigned int uint_fast16_t;
#endif
target_ulong PFN[2];
};
+#if !defined(CONFIG_USER_ONLY)
typedef struct CPUMIPSTLBContext CPUMIPSTLBContext;
struct CPUMIPSTLBContext {
uint32_t nb_tlb;
uint32_t tlb_in_use;
- int (*map_address) (struct CPUMIPSState *env, target_ulong *physical, int *prot, target_ulong address, int rw, int access_type);
- void (*do_tlbwi) (void);
- void (*do_tlbwr) (void);
- void (*do_tlbp) (void);
- void (*do_tlbr) (void);
+ int (*map_address) (struct CPUMIPSState *env, target_phys_addr_t *physical, int *prot, target_ulong address, int rw, int access_type);
+ void (*helper_tlbwi) (void);
+ void (*helper_tlbwr) (void);
+ void (*helper_tlbp) (void);
+ void (*helper_tlbr) (void);
union {
struct {
r4k_tlb_t tlb[MIPS_TLB_MAX];
} r4k;
} mmu;
};
+#endif
typedef union fpr_t fpr_t;
union fpr_t {
/* define FP_ENDIAN_IDX to access the same location
* in the fpr_t union regardless of the host endianess
*/
-#if defined(WORDS_BIGENDIAN)
+#if defined(HOST_WORDS_BIGENDIAN)
# define FP_ENDIAN_IDX 1
#else
# define FP_ENDIAN_IDX 0
#define FCR0_REV 0
/* fcsr */
uint32_t fcr31;
-#define SET_FP_COND(num,env) do { ((env)->fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
-#define CLEAR_FP_COND(num,env) do { ((env)->fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
-#define GET_FP_COND(env) ((((env)->fcr31 >> 24) & 0xfe) | (((env)->fcr31 >> 23) & 0x1))
+#define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
+#define CLEAR_FP_COND(num,env) do { ((env).fcr31) &= ~((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0)
+#define GET_FP_COND(env) ((((env).fcr31 >> 24) & 0xfe) | (((env).fcr31 >> 23) & 0x1))
#define GET_FP_CAUSE(reg) (((reg) >> 12) & 0x3f)
#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
#define GET_FP_FLAGS(reg) (((reg) >> 2) & 0x1f)
#define MIPS_SHADOW_SET_MAX 16
#define MIPS_TC_MAX 5
+#define MIPS_FPU_MAX 1
#define MIPS_DSP_ACC 4
+typedef struct TCState TCState;
+struct TCState {
+ target_ulong gpr[32];
+ target_ulong PC;
+ target_ulong HI[MIPS_DSP_ACC];
+ target_ulong LO[MIPS_DSP_ACC];
+ target_ulong ACX[MIPS_DSP_ACC];
+ target_ulong DSPControl;
+ int32_t CP0_TCStatus;
+#define CP0TCSt_TCU3 31
+#define CP0TCSt_TCU2 30
+#define CP0TCSt_TCU1 29
+#define CP0TCSt_TCU0 28
+#define CP0TCSt_TMX 27
+#define CP0TCSt_RNST 23
+#define CP0TCSt_TDS 21
+#define CP0TCSt_DT 20
+#define CP0TCSt_DA 15
+#define CP0TCSt_A 13
+#define CP0TCSt_TKSU 11
+#define CP0TCSt_IXMT 10
+#define CP0TCSt_TASID 0
+ int32_t CP0_TCBind;
+#define CP0TCBd_CurTC 21
+#define CP0TCBd_TBE 17
+#define CP0TCBd_CurVPE 0
+ target_ulong CP0_TCHalt;
+ target_ulong CP0_TCContext;
+ target_ulong CP0_TCSchedule;
+ target_ulong CP0_TCScheFBack;
+ int32_t CP0_Debug_tcstatus;
+};
+
typedef struct CPUMIPSState CPUMIPSState;
struct CPUMIPSState {
- /* General integer registers */
- target_ulong gpr[MIPS_SHADOW_SET_MAX][32];
- /* Special registers */
- target_ulong PC[MIPS_TC_MAX];
-#if TARGET_LONG_BITS > HOST_LONG_BITS
- target_ulong t0;
-#endif
- /* temporary hack for FP globals */
-#ifndef USE_HOST_FLOAT_REGS
- fpr_t ft0;
- fpr_t ft1;
- fpr_t ft2;
-#endif
- target_ulong HI[MIPS_TC_MAX][MIPS_DSP_ACC];
- target_ulong LO[MIPS_TC_MAX][MIPS_DSP_ACC];
- target_ulong ACX[MIPS_TC_MAX][MIPS_DSP_ACC];
- target_ulong DSPControl[MIPS_TC_MAX];
+ TCState active_tc;
+ CPUMIPSFPUContext active_fpu;
- CPUMIPSMVPContext *mvp;
- CPUMIPSTLBContext *tlb;
- CPUMIPSFPUContext *fpu;
uint32_t current_tc;
- target_ulong *current_tc_gprs;
- target_ulong *current_tc_hi;
+ uint32_t current_fpu;
uint32_t SEGBITS;
- target_ulong SEGMask;
uint32_t PABITS;
+ target_ulong SEGMask;
target_ulong PAMask;
int32_t CP0_Index;
#define CP0VPEOpt_DWX1 1
#define CP0VPEOpt_DWX0 0
target_ulong CP0_EntryLo0;
- int32_t CP0_TCStatus[MIPS_TC_MAX];
-#define CP0TCSt_TCU3 31
-#define CP0TCSt_TCU2 30
-#define CP0TCSt_TCU1 29
-#define CP0TCSt_TCU0 28
-#define CP0TCSt_TMX 27
-#define CP0TCSt_RNST 23
-#define CP0TCSt_TDS 21
-#define CP0TCSt_DT 20
-#define CP0TCSt_DA 15
-#define CP0TCSt_A 13
-#define CP0TCSt_TKSU 11
-#define CP0TCSt_IXMT 10
-#define CP0TCSt_TASID 0
- int32_t CP0_TCBind[MIPS_TC_MAX];
-#define CP0TCBd_CurTC 21
-#define CP0TCBd_TBE 17
-#define CP0TCBd_CurVPE 0
- target_ulong CP0_TCHalt[MIPS_TC_MAX];
- target_ulong CP0_TCContext[MIPS_TC_MAX];
- target_ulong CP0_TCSchedule[MIPS_TC_MAX];
- target_ulong CP0_TCScheFBack[MIPS_TC_MAX];
target_ulong CP0_EntryLo1;
target_ulong CP0_Context;
int32_t CP0_PageMask;
#define CP0C2_SA 0
int32_t CP0_Config3;
#define CP0C3_M 31
+#define CP0C3_ISA_ON_EXC 16
#define CP0C3_DSPP 10
#define CP0C3_LPA 7
#define CP0C3_VEIC 6
int32_t CP0_Config6;
int32_t CP0_Config7;
/* XXX: Maybe make LLAddr per-TC? */
- target_ulong CP0_LLAddr;
+ target_ulong lladdr;
+ target_ulong llval;
+ target_ulong llnewval;
+ target_ulong llreg;
+ target_ulong CP0_LLAddr_rw_bitmask;
+ int CP0_LLAddr_shift;
target_ulong CP0_WatchLo[8];
int32_t CP0_WatchHi[8];
target_ulong CP0_XContext;
#define CP0DB_DDBL 2
#define CP0DB_DBp 1
#define CP0DB_DSS 0
- int32_t CP0_Debug_tcstatus[MIPS_TC_MAX];
target_ulong CP0_DEPC;
int32_t CP0_Performance0;
int32_t CP0_TagLo;
int32_t CP0_DataHi;
target_ulong CP0_ErrorEPC;
int32_t CP0_DESAVE;
+ /* We waste some space so we can handle shadow registers like TCs. */
+ TCState tcs[MIPS_SHADOW_SET_MAX];
+ CPUMIPSFPUContext fpus[MIPS_FPU_MAX];
/* Qemu */
- int interrupt_request;
int error_code;
- int user_mode_only; /* user mode only simulation */
uint32_t hflags; /* CPU State */
/* TMASK defines different execution modes */
-#define MIPS_HFLAG_TMASK 0x01FF
-#define MIPS_HFLAG_MODE 0x0007 /* execution modes */
+#define MIPS_HFLAG_TMASK 0x007FF
+#define MIPS_HFLAG_MODE 0x00007 /* execution modes */
/* The KSU flags must be the lowest bits in hflags. The flag order
must be the same as defined for CP0 Status. This allows to use
the bits as the value of mmu_idx. */
-#define MIPS_HFLAG_KSU 0x0003 /* kernel/supervisor/user mode mask */
-#define MIPS_HFLAG_UM 0x0002 /* user mode flag */
-#define MIPS_HFLAG_SM 0x0001 /* supervisor mode flag */
-#define MIPS_HFLAG_KM 0x0000 /* kernel mode flag */
-#define MIPS_HFLAG_DM 0x0004 /* Debug mode */
-#define MIPS_HFLAG_64 0x0008 /* 64-bit instructions enabled */
-#define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */
-#define MIPS_HFLAG_FPU 0x0020 /* FPU enabled */
-#define MIPS_HFLAG_F64 0x0040 /* 64-bit FPU enabled */
+#define MIPS_HFLAG_KSU 0x00003 /* kernel/supervisor/user mode mask */
+#define MIPS_HFLAG_UM 0x00002 /* user mode flag */
+#define MIPS_HFLAG_SM 0x00001 /* supervisor mode flag */
+#define MIPS_HFLAG_KM 0x00000 /* kernel mode flag */
+#define MIPS_HFLAG_DM 0x00004 /* Debug mode */
+#define MIPS_HFLAG_64 0x00008 /* 64-bit instructions enabled */
+#define MIPS_HFLAG_CP0 0x00010 /* CP0 enabled */
+#define MIPS_HFLAG_FPU 0x00020 /* FPU enabled */
+#define MIPS_HFLAG_F64 0x00040 /* 64-bit FPU enabled */
/* True if the MIPS IV COP1X instructions can be used. This also
controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S
and RSQRT.D. */
-#define MIPS_HFLAG_COP1X 0x0080 /* COP1X instructions enabled */
-#define MIPS_HFLAG_RE 0x0100 /* Reversed endianness */
+#define MIPS_HFLAG_COP1X 0x00080 /* COP1X instructions enabled */
+#define MIPS_HFLAG_RE 0x00100 /* Reversed endianness */
+#define MIPS_HFLAG_UX 0x00200 /* 64-bit user mode */
+#define MIPS_HFLAG_M16 0x00400 /* MIPS16 mode flag */
+#define MIPS_HFLAG_M16_SHIFT 10
/* If translation is interrupted between the branch instruction and
* the delay slot, record what type of branch it is so that we can
* resume translation properly. It might be possible to reduce
* this from three bits to two. */
-#define MIPS_HFLAG_BMASK 0x0e00
-#define MIPS_HFLAG_B 0x0200 /* Unconditional branch */
-#define MIPS_HFLAG_BC 0x0400 /* Conditional branch */
-#define MIPS_HFLAG_BL 0x0600 /* Likely branch */
-#define MIPS_HFLAG_BR 0x0800 /* branch to register (can't link TB) */
+#define MIPS_HFLAG_BMASK_BASE 0x03800
+#define MIPS_HFLAG_B 0x00800 /* Unconditional branch */
+#define MIPS_HFLAG_BC 0x01000 /* Conditional branch */
+#define MIPS_HFLAG_BL 0x01800 /* Likely branch */
+#define MIPS_HFLAG_BR 0x02000 /* branch to register (can't link TB) */
+ /* Extra flags about the current pending branch. */
+#define MIPS_HFLAG_BMASK_EXT 0x3C000
+#define MIPS_HFLAG_B16 0x04000 /* branch instruction was 16 bits */
+#define MIPS_HFLAG_BDS16 0x08000 /* branch requires 16-bit delay slot */
+#define MIPS_HFLAG_BDS32 0x10000 /* branch requires 32-bit delay slot */
+#define MIPS_HFLAG_BX 0x20000 /* branch exchanges execution mode */
+#define MIPS_HFLAG_BMASK (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT)
target_ulong btarget; /* Jump / branch target */
- int bcond; /* Branch condition (if needed) */
+ target_ulong bcond; /* Branch condition (if needed) */
int SYNCI_Step; /* Address step size for SYNCI */
int CCRes; /* Cycle count resolution/divisor */
uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */
int insn_flags; /* Supported instruction set */
-#ifdef CONFIG_USER_ONLY
- target_ulong tls_value;
-#endif
+ target_ulong tls_value; /* For usermode emulation */
CPU_COMMON
- const mips_def_t *cpu_model;
-#ifndef CONFIG_USER_ONLY
- void *irq[8];
+ CPUMIPSMVPContext *mvp;
+#if !defined(CONFIG_USER_ONLY)
+ CPUMIPSTLBContext *tlb;
#endif
+ const mips_def_t *cpu_model;
+ void *irq[8];
struct QEMUTimer *timer; /* Internal timer */
};
-int no_mmu_map_address (CPUMIPSState *env, target_ulong *physical, int *prot,
+#if !defined(CONFIG_USER_ONLY)
+int no_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
target_ulong address, int rw, int access_type);
-int fixed_mmu_map_address (CPUMIPSState *env, target_ulong *physical, int *prot,
+int fixed_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
target_ulong address, int rw, int access_type);
-int r4k_map_address (CPUMIPSState *env, target_ulong *physical, int *prot,
+int r4k_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
target_ulong address, int rw, int access_type);
-void r4k_do_tlbwi (void);
-void r4k_do_tlbwr (void);
-void r4k_do_tlbp (void);
-void r4k_do_tlbr (void);
-void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
+void r4k_helper_tlbwi (void);
+void r4k_helper_tlbwr (void);
+void r4k_helper_tlbp (void);
+void r4k_helper_tlbr (void);
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
- int unused);
+ int unused, int size);
+#endif
+
+void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
-#define CPUState CPUMIPSState
#define cpu_init cpu_mips_init
#define cpu_exec cpu_mips_exec
#define cpu_gen_code cpu_mips_gen_code
#define cpu_signal_handler cpu_mips_signal_handler
#define cpu_list mips_cpu_list
+#define CPU_SAVE_VERSION 3
+
/* MMU modes definitions. We carefully match the indices with our
hflags layout. */
#define MMU_MODE0_SUFFIX _kernel
return env->hflags & MIPS_HFLAG_KSU;
}
-#if defined(CONFIG_USER_ONLY)
static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
{
if (newsp)
- env->gpr[env->current_tc][29] = newsp;
- env->gpr[env->current_tc][7] = 0;
- env->gpr[env->current_tc][2] = 0;
+ env->active_tc.gpr[29] = newsp;
+ env->active_tc.gpr[7] = 0;
+ env->active_tc.gpr[2] = 0;
}
-#endif
#include "cpu-all.h"
+#include "exec-all.h"
/* Memory access type :
* may be needed for precise access rights control and precise exceptions.
EXCP_LAST = EXCP_CACHE,
};
+/* Dummy exception for conditional stores. */
+#define EXCP_SC 0x100
int cpu_mips_exec(CPUMIPSState *s);
CPUMIPSState *cpu_mips_init(const char *cpu_model);
-uint32_t cpu_mips_get_clock (void);
+//~ uint32_t cpu_mips_get_clock (void);
int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
+/* mips_timer.c */
+uint32_t cpu_mips_get_random (CPUState *env);
+uint32_t cpu_mips_get_count (CPUState *env);
+void cpu_mips_store_count (CPUState *env, uint32_t value);
+void cpu_mips_store_compare (CPUState *env, uint32_t value);
+void cpu_mips_start_count(CPUState *env);
+void cpu_mips_stop_count(CPUState *env);
+
+/* mips_int.c */
+void cpu_mips_update_irq (CPUState *env);
+
+/* helper.c */
+int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
+ int mmu_idx, int is_softmmu);
+#define cpu_handle_mmu_fault cpu_mips_handle_mmu_fault
+void do_interrupt (CPUState *env);
+#if !defined(CONFIG_USER_ONLY)
+void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra);
+target_phys_addr_t cpu_mips_translate_address (CPUState *env, target_ulong address,
+ int rw);
+#endif
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->active_tc.PC = tb->pc;
+ env->hflags &= ~MIPS_HFLAG_BMASK;
+ env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+ target_ulong *cs_base, int *flags)
+{
+ *pc = env->active_tc.PC;
+ *cs_base = 0;
+ *flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
+}
+
+static inline void cpu_set_tls(CPUState *env, target_ulong newtls)
+{
+ env->tls_value = newtls;
+}
+
#endif /* !defined (__MIPS_CPU_H__) */