Implement missing MIPS supervisor mode bits.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 28 Oct 2007 19:45:05 +0000 (19:45 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 28 Oct 2007 19:45:05 +0000 (19:45 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3472 c046a42c-6fe2-441c-8c8c-71466251a162

cpu-defs.h
linux-user/elfload.c
target-mips/cpu.h
target-mips/exec.h
target-mips/helper.c
target-mips/op.c
target-mips/op_helper.c
target-mips/translate.c

index 86557e4..8414aca 100644 (file)
@@ -122,7 +122,7 @@ typedef struct CPUTLBEntry {
                                    written */                           \
     target_ulong mem_write_vaddr; /* target virtual addr at which the   \
                                      memory was written */              \
-    /* 0 = kernel, 1 = user */                                          \
+    /* The meaning of the MMU modes is defined in the target code. */   \
     CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE];                  \
     struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];           \
                                                                         \
index ab5a74e..2d758de 100644 (file)
@@ -374,7 +374,7 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
 
 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
 {
-    regs->cp0_status = CP0St_UM;
+    regs->cp0_status = 2 << CP0St_KSU;
     regs->cp0_epc = infop->entry;
     regs->regs[29] = infop->start_stack;
 }
index 363fcd8..5fbb90e 100644 (file)
@@ -107,7 +107,7 @@ struct CPUMIPSFPUContext {
 #define FP_UNIMPLEMENTED  32
 };
 
-#define NB_MMU_MODES 2
+#define NB_MMU_MODES 3
 
 typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
 struct CPUMIPSMVPContext {
@@ -285,8 +285,7 @@ struct CPUMIPSState {
 #define CP0St_KX    7
 #define CP0St_SX    6
 #define CP0St_UX    5
-#define CP0St_UM    4
-#define CP0St_R0    3
+#define CP0St_KSU   3
 #define CP0St_ERL   2
 #define CP0St_EXL   1
 #define CP0St_IE    0
@@ -418,9 +417,14 @@ struct CPUMIPSState {
     /* TMASK defines different execution modes */
 #define MIPS_HFLAG_TMASK  0x00FF
 #define MIPS_HFLAG_MODE   0x0007 /* execution modes                    */
-#define MIPS_HFLAG_UM     0x0001 /* user mode                          */
-#define MIPS_HFLAG_DM     0x0002 /* Debug mode                         */
-#define MIPS_HFLAG_SM     0x0004 /* Supervisor mode                    */
+    /* 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                        */
@@ -489,13 +493,15 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
 #define cpu_signal_handler cpu_mips_signal_handler
 #define cpu_list mips_cpu_list
 
-/* MMU modes definitions */
+/* MMU modes definitions. We carefully match the indices with our
+   hflags layout. */
 #define MMU_MODE0_SUFFIX _kernel
-#define MMU_MODE1_SUFFIX _user
-#define MMU_USER_IDX 1
+#define MMU_MODE1_SUFFIX _super
+#define MMU_MODE2_SUFFIX _user
+#define MMU_USER_IDX 2
 static inline int cpu_mmu_index (CPUState *env)
 {
-    return (env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM ? 1 : 0;
+    return env->hflags & MIPS_HFLAG_KSU;
 }
 
 #include "cpu-all.h"
index 61c09ac..529306f 100644 (file)
@@ -230,24 +230,20 @@ static always_inline int cpu_halted(CPUState *env)
 static always_inline void compute_hflags(CPUState *env)
 {
     env->hflags &= ~(MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 |
-                     MIPS_HFLAG_FPU | MIPS_HFLAG_UM);
+                     MIPS_HFLAG_FPU | MIPS_HFLAG_KSU);
     if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
         !(env->CP0_Status & (1 << CP0St_ERL)) &&
         !(env->hflags & MIPS_HFLAG_DM)) {
-        if (env->CP0_Status & (1 << CP0St_UM))
-            env->hflags |= MIPS_HFLAG_UM;
-        if (env->CP0_Status & (1 << CP0St_R0))
-            env->hflags |= MIPS_HFLAG_SM;
+        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
     }
 #if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
-    if (!(env->hflags & MIPS_HFLAG_UM) ||
+    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
         (env->CP0_Status & (1 << CP0St_PX)) ||
         (env->CP0_Status & (1 << CP0St_UX)))
         env->hflags |= MIPS_HFLAG_64;
 #endif
     if ((env->CP0_Status & (1 << CP0St_CU0)) ||
-        (!(env->hflags & MIPS_HFLAG_UM) &&
-         !(env->hflags & MIPS_HFLAG_SM)))
+        !(env->hflags & MIPS_HFLAG_KSU))
         env->hflags |= MIPS_HFLAG_CP0;
     if (env->CP0_Status & (1 << CP0St_CU1))
         env->hflags |= MIPS_HFLAG_FPU;
index 45874d4..708641c 100644 (file)
@@ -373,7 +373,7 @@ void do_interrupt (CPUState *env)
         }
     enter_debug_mode:
         env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
-        env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
+        env->hflags &= ~(MIPS_HFLAG_KSU);
         /* EJTAG probe trap enable is not implemented... */
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
             env->CP0_Cause &= ~(1 << CP0Ca_BD);
@@ -399,7 +399,7 @@ void do_interrupt (CPUState *env)
         }
         env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
         env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
-        env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
+        env->hflags &= ~(MIPS_HFLAG_KSU);
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
             env->CP0_Cause &= ~(1 << CP0Ca_BD);
         env->PC[env->current_tc] = (int32_t)0xBFC00000;
@@ -501,7 +501,7 @@ void do_interrupt (CPUState *env)
             }
             env->CP0_Status |= (1 << CP0St_EXL);
             env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
-            env->hflags &= ~(MIPS_HFLAG_SM | MIPS_HFLAG_UM);
+            env->hflags &= ~(MIPS_HFLAG_KSU);
         }
         env->hflags &= ~MIPS_HFLAG_BMASK;
         if (env->CP0_Status & (1 << CP0St_BEV)) {
index 9e8324d..f291345 100644 (file)
@@ -286,6 +286,10 @@ void op_store_LO (void)
 #include "op_mem.c"
 #undef MEMSUFFIX
 
+#define MEMSUFFIX _super
+#include "op_mem.c"
+#undef MEMSUFFIX
+
 #define MEMSUFFIX _kernel
 #include "op_mem.c"
 #undef MEMSUFFIX
@@ -298,7 +302,7 @@ void op_addr_add (void)
    with Status_UX = 0 should be casted to 32-bit and sign extended.
    See the MIPS64 PRA manual, section 4.10. */
 #if defined(TARGET_MIPSN32) || defined(TARGET_MIPS64)
-    if ((env->hflags & MIPS_HFLAG_UM) &&
+    if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
         !(env->CP0_Status & (1 << CP0St_UX)))
         T0 = (int64_t)(int32_t)(T0 + T1);
     else
@@ -1269,7 +1273,7 @@ void op_mftc0_status(void)
     T0 = env->CP0_Status & ~0xf1000018;
     T0 |= tcstatus & (0xf << CP0TCSt_TCU0);
     T0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
-    T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_R0);
+    T0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
     RETURN();
 }
 
@@ -1833,7 +1837,7 @@ void op_mttc0_status(void)
     env->CP0_Status = T0 & ~0xf1000018;
     tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (T0 & (0xf << CP0St_CU0));
     tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((T0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
-    tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_R0)) << (CP0TCSt_TKSU - CP0St_R0));
+    tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((T0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
     env->CP0_TCStatus[other_tc] = tcstatus;
     RETURN();
 }
index ff26ab5..3c04c55 100644 (file)
@@ -315,8 +315,12 @@ void do_mtc0_status_debug(uint32_t old, uint32_t val)
             old, old & env->CP0_Cause & CP0Ca_IP_mask,
             val, val & env->CP0_Cause & CP0Ca_IP_mask,
             env->CP0_Cause);
-    (env->hflags & MIPS_HFLAG_UM) ? fputs(", UM\n", logfile)
-                                  : fputs("\n", logfile);
+    switch (env->hflags & MIPS_HFLAG_KSU) {
+    case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
+    case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
+    case MIPS_HFLAG_KM: fputs("\n", logfile); break;
+    default: cpu_abort(env, "Invalid MMU mode!\n"); break;
+    }
 }
 
 void do_mtc0_status_irqraise_debug(void)
@@ -518,10 +522,12 @@ void debug_post_eret (void)
         fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
     if (env->hflags & MIPS_HFLAG_DM)
         fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
-    if (env->hflags & MIPS_HFLAG_UM)
-        fputs(", UM\n", logfile);
-    else
-        fputs("\n", logfile);
+    switch (env->hflags & MIPS_HFLAG_KSU) {
+    case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
+    case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
+    case MIPS_HFLAG_KM: fputs("\n", logfile); break;
+    default: cpu_abort(env, "Invalid MMU mode!\n"); break;
+    }
 }
 
 void do_pmon (int function)
index 89fe5fe..ce0b4dc 100644 (file)
@@ -790,13 +790,15 @@ static always_inline void check_mips_64(DisasContext *ctx)
 #define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()
 #define OP_LD_TABLE(width)                                                    \
 static GenOpFunc *gen_op_l##width[] = {                                       \
-    &gen_op_l##width##_user,                                                  \
     &gen_op_l##width##_kernel,                                                \
+    &gen_op_l##width##_super,                                                 \
+    &gen_op_l##width##_user,                                                  \
 }
 #define OP_ST_TABLE(width)                                                    \
 static GenOpFunc *gen_op_s##width[] = {                                       \
-    &gen_op_s##width##_user,                                                  \
     &gen_op_s##width##_kernel,                                                \
+    &gen_op_s##width##_super,                                                 \
+    &gen_op_s##width##_user,                                                  \
 }
 #endif
 
@@ -6494,9 +6496,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
     ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
     restore_cpu_state(env, &ctx);
 #if defined(CONFIG_USER_ONLY)
-    ctx.mem_idx = 0;
+    ctx.mem_idx = MIPS_HFLAG_UM;
 #else
-    ctx.mem_idx = !((ctx.hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
+    ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
 #endif
 #ifdef DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_CPU) {
@@ -6507,7 +6509,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
 #endif
 #ifdef MIPS_DEBUG_DISAS
     if (loglevel & CPU_LOG_TB_IN_ASM)
-        fprintf(logfile, "\ntb %p super %d cond %04x\n",
+        fprintf(logfile, "\ntb %p idx %d hflags %04x\n",
                 tb, ctx.mem_idx, ctx.hflags);
 #endif
     while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {