linux-user: getpriority errno fix
[qemu] / target-mips / cpu.h
index cf7043a..c27738a 100644 (file)
@@ -5,6 +5,8 @@
 
 #define ELF_MACHINE    EM_MIPS
 
+#define CPUState struct CPUMIPSState
+
 #include "config.h"
 #include "mips-defs.h"
 #include "cpu-defs.h"
@@ -12,7 +14,7 @@
 
 // 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
@@ -39,10 +41,10 @@ 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);
+    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];
@@ -60,7 +62,7 @@ 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
@@ -84,9 +86,9 @@ struct CPUMIPSFPUContext {
 #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)
@@ -132,38 +134,55 @@ typedef struct mips_def_t mips_def_t;
 
 #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;
@@ -209,28 +228,6 @@ struct CPUMIPSState {
 #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;
@@ -378,6 +375,9 @@ struct CPUMIPSState {
     int32_t CP0_Config7;
     /* XXX: Maybe make LLAddr per-TC? */
     target_ulong CP0_LLAddr;
+    target_ulong llval;
+    target_ulong llnewval;
+    target_ulong llreg;
     target_ulong CP0_WatchLo[8];
     int32_t CP0_WatchHi[8];
     target_ulong CP0_XContext;
@@ -401,7 +401,6 @@ struct CPUMIPSState {
 #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;
@@ -410,13 +409,14 @@ struct CPUMIPSState {
     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_TMASK  0x03FF
 #define MIPS_HFLAG_MODE   0x0007 /* 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
@@ -435,17 +435,18 @@ struct CPUMIPSState {
        and RSQRT.D.  */
 #define MIPS_HFLAG_COP1X  0x0080 /* COP1X instructions enabled         */
 #define MIPS_HFLAG_RE     0x0100 /* Reversed endianness                */
+#define MIPS_HFLAG_UX     0x0200 /* 64-bit user mode                   */
     /* 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  0x1C00
+#define MIPS_HFLAG_B      0x0400 /* Unconditional branch               */
+#define MIPS_HFLAG_BC     0x0800 /* Conditional branch                 */
+#define MIPS_HFLAG_BL     0x0C00 /* Likely branch                      */
+#define MIPS_HFLAG_BR     0x1000 /* branch to register (can't link TB) */
     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 */
@@ -453,17 +454,12 @@ struct CPUMIPSState {
     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];
-#endif
-
     struct QEMUTimer *timer; /* Internal timer */
 };
 
@@ -473,22 +469,23 @@ int fixed_mmu_map_address (CPUMIPSState *env, target_ulong *physical, int *prot,
                            target_ulong address, int rw, int access_type);
 int r4k_map_address (CPUMIPSState *env, target_ulong *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 r4k_helper_tlbwi (void);
+void r4k_helper_tlbwr (void);
+void r4k_helper_tlbp (void);
+void r4k_helper_tlbr (void);
 void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
 
 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
-                          int unused);
+                          int unused, int size);
 
-#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
@@ -500,17 +497,16 @@ static inline int cpu_mmu_index (CPUState *env)
     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.
@@ -566,10 +562,50 @@ enum {
 
     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);
+void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra);
+
+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__) */