correct handling of saved host registers
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 12 Oct 2004 22:01:28 +0000 (22:01 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 12 Oct 2004 22:01:28 +0000 (22:01 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1122 c046a42c-6fe2-441c-8c8c-71466251a162

cpu-exec.c
dyngen-exec.h
target-arm/exec.h
target-i386/exec.h
target-i386/helper.c
target-ppc/exec.h
target-sparc/exec.h

index 5229eaa..b98c22c 100644 (file)
@@ -123,37 +123,30 @@ int cpu_exec(CPUState *env1)
 #if defined(TARGET_I386)
 #ifdef reg_EAX
     saved_EAX = EAX;
-    EAX = env->regs[R_EAX];
 #endif
 #ifdef reg_ECX
     saved_ECX = ECX;
-    ECX = env->regs[R_ECX];
 #endif
 #ifdef reg_EDX
     saved_EDX = EDX;
-    EDX = env->regs[R_EDX];
 #endif
 #ifdef reg_EBX
     saved_EBX = EBX;
-    EBX = env->regs[R_EBX];
 #endif
 #ifdef reg_ESP
     saved_ESP = ESP;
-    ESP = env->regs[R_ESP];
 #endif
 #ifdef reg_EBP
     saved_EBP = EBP;
-    EBP = env->regs[R_EBP];
 #endif
 #ifdef reg_ESI
     saved_ESI = ESI;
-    ESI = env->regs[R_ESI];
 #endif
 #ifdef reg_EDI
     saved_EDI = EDI;
-    EDI = env->regs[R_EDI];
 #endif
-    
+
+    env_to_regs();
     /* put eflags in CPU temporary format */
     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
     DF = 1 - (2 * ((env->eflags >> 10) & 1));
@@ -353,6 +346,8 @@ int cpu_exec(CPUState *env1)
                     spin_lock(&tb_lock);
 
                     tb_invalidated_flag = 0;
+                    
+                    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
 
                     /* find translated block using physical mappings */
                     phys_pc = get_phys_addr_code(env, (unsigned long)pc);
@@ -556,6 +551,7 @@ int cpu_exec(CPUState *env1)
 #endif
             }
         } else {
+            env_to_regs();
         }
     } /* for(;;) */
 
index 86087ca..1a3bb2a 100644 (file)
@@ -93,8 +93,6 @@ extern int printf(const char *, ...);
 #define AREG1 "r24"
 #define AREG2 "r25"
 #define AREG3 "r26"
-/* XXX: suppress this hack */
-#if defined(CONFIG_USER_ONLY)
 #define AREG4 "r16"
 #define AREG5 "r17"
 #define AREG6 "r18"
@@ -103,7 +101,6 @@ extern int printf(const char *, ...);
 #define AREG9 "r21"
 #define AREG10 "r22"
 #define AREG11 "r23"
-#endif
 #define USE_INT_TO_FLOAT_HELPERS
 #define BUGGY_GCC_DIV64
 #endif
index 70afdc5..14e2072 100644 (file)
@@ -38,3 +38,11 @@ static inline int compute_cpsr(void)
     return env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) | 
         (env->CF << 29) | ((env->VF & 0x80000000) >> 3);
 }
+
+static inline void env_to_regs(void)
+{
+}
+
+static inline void regs_to_env(void)
+{
+}
index 680e580..61af546 100644 (file)
@@ -20,7 +20,7 @@
 #include "config.h"
 #include "dyngen-exec.h"
 
-/* at least 4 register variables are defines */
+/* at least 4 register variables are defined */
 register struct CPUX86State *env asm(AREG0);
 register uint32_t T0 asm(AREG1);
 register uint32_t T1 asm(AREG2);
@@ -546,3 +546,58 @@ static inline void load_eflags(int eflags, int update_mask)
         (eflags & update_mask);
 }
 
+static inline void env_to_regs(void)
+{
+#ifdef reg_EAX
+    EAX = env->regs[R_EAX];
+#endif
+#ifdef reg_ECX
+    ECX = env->regs[R_ECX];
+#endif
+#ifdef reg_EDX
+    EDX = env->regs[R_EDX];
+#endif
+#ifdef reg_EBX
+    EBX = env->regs[R_EBX];
+#endif
+#ifdef reg_ESP
+    ESP = env->regs[R_ESP];
+#endif
+#ifdef reg_EBP
+    EBP = env->regs[R_EBP];
+#endif
+#ifdef reg_ESI
+    ESI = env->regs[R_ESI];
+#endif
+#ifdef reg_EDI
+    EDI = env->regs[R_EDI];
+#endif
+}
+
+static inline void regs_to_env(void)
+{
+#ifdef reg_EAX
+    env->regs[R_EAX] = EAX;
+#endif
+#ifdef reg_ECX
+    env->regs[R_ECX] = ECX;
+#endif
+#ifdef reg_EDX
+    env->regs[R_EDX] = EDX;
+#endif
+#ifdef reg_EBX
+    env->regs[R_EBX] = EBX;
+#endif
+#ifdef reg_ESP
+    env->regs[R_ESP] = ESP;
+#endif
+#ifdef reg_EBP
+    env->regs[R_EBP] = EBP;
+#endif
+#ifdef reg_ESI
+    env->regs[R_ESI] = ESI;
+#endif
+#ifdef reg_EDI
+    env->regs[R_EDI] = EDI;
+#endif
+}
index 7035e1c..41ebaf2 100644 (file)
@@ -109,30 +109,7 @@ void cpu_loop_exit(void)
 {
     /* NOTE: the register at this point must be saved by hand because
        longjmp restore them */
-#ifdef reg_EAX
-    env->regs[R_EAX] = EAX;
-#endif
-#ifdef reg_ECX
-    env->regs[R_ECX] = ECX;
-#endif
-#ifdef reg_EDX
-    env->regs[R_EDX] = EDX;
-#endif
-#ifdef reg_EBX
-    env->regs[R_EBX] = EBX;
-#endif
-#ifdef reg_ESP
-    env->regs[R_ESP] = ESP;
-#endif
-#ifdef reg_EBP
-    env->regs[R_EBP] = EBP;
-#endif
-#ifdef reg_ESI
-    env->regs[R_ESI] = ESI;
-#endif
-#ifdef reg_EDI
-    env->regs[R_EDI] = EDI;
-#endif
+    regs_to_env();
     longjmp(env->jmp_env, 1);
 }
 
@@ -384,16 +361,28 @@ static void switch_tss(int tss_selector,
         /* 32 bit */
         stl_kernel(env->tr.base + 0x20, next_eip);
         stl_kernel(env->tr.base + 0x24, old_eflags);
-        for(i = 0; i < 8; i++)
-            stl_kernel(env->tr.base + (0x28 + i * 4), env->regs[i]);
+        stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX);
+        stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX);
+        stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX);
+        stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX);
+        stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP);
+        stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP);
+        stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI);
+        stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI);
         for(i = 0; i < 6; i++)
             stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector);
     } else {
         /* 16 bit */
         stw_kernel(env->tr.base + 0x0e, next_eip);
         stw_kernel(env->tr.base + 0x10, old_eflags);
-        for(i = 0; i < 8; i++)
-            stw_kernel(env->tr.base + (0x12 + i * 2), env->regs[i]);
+        stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX);
+        stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX);
+        stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX);
+        stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX);
+        stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP);
+        stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP);
+        stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI);
+        stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI);
         for(i = 0; i < 4; i++)
             stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector);
     }
@@ -437,8 +426,15 @@ static void switch_tss(int tss_selector,
     if (!(type & 8))
         eflags_mask &= 0xffff;
     load_eflags(new_eflags, eflags_mask);
-    for(i = 0; i < 8; i++)
-        env->regs[i] = new_regs[i];
+    /* XXX: what to do in 16 bit case ? */
+    EAX = new_regs[0];
+    ECX = new_regs[1];
+    EDX = new_regs[2];
+    EBX = new_regs[3];
+    ESP = new_regs[4];
+    EBP = new_regs[5];
+    ESI = new_regs[6];
+    EDI = new_regs[7];
     if (new_eflags & VM_MASK) {
         for(i = 0; i < 6; i++) 
             load_seg_vm(i, new_segs[i]);
@@ -633,13 +629,13 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
                 mask = 0xffffffff;
             else
                 mask = 0xffff;
-            esp = (env->regs[R_ESP] - (2 << shift)) & mask;
+            esp = (ESP - (2 << shift)) & mask;
             ssp = env->segs[R_SS].base + esp;
             if (shift)
                 stl_kernel(ssp, error_code);
             else
                 stw_kernel(ssp, error_code);
-            env->regs[R_ESP] = (esp & mask) | (env->regs[R_ESP] & ~mask);
+            ESP = (esp & mask) | (ESP & ~mask);
         }
         return;
     case 6: /* 286 interrupt gate */
@@ -868,7 +864,7 @@ void do_interrupt(int intno, int is_int, int error_code,
             if (intno == 0x0e) {
                 fprintf(logfile, " CR2=%08x", env->cr[2]);
             } else {
-                fprintf(logfile, " EAX=%08x", env->regs[R_EAX]);
+                fprintf(logfile, " EAX=%08x", EAX);
             }
             fprintf(logfile, "\n");
 #if 0
@@ -911,6 +907,16 @@ void raise_interrupt(int intno, int is_int, int error_code,
     cpu_loop_exit();
 }
 
+/* same as raise_exception_err, but do not restore global registers */
+static void raise_exception_err_norestore(int exception_index, int error_code)
+{
+    env->exception_index = exception_index;
+    env->error_code = error_code;
+    env->exception_is_int = 0;
+    env->exception_next_eip = 0;
+    longjmp(env->jmp_env, 1);
+}
+
 /* shortcuts to generate exceptions */
 
 void (raise_exception_err)(int exception_index, int error_code)
@@ -2584,7 +2590,10 @@ void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr)
                 cpu_restore_state(tb, env, pc, NULL);
             }
         }
-        raise_exception_err(EXCP0E_PAGE, env->error_code);
+        if (retaddr)
+            raise_exception_err(EXCP0E_PAGE, env->error_code);
+        else
+            raise_exception_err_norestore(EXCP0E_PAGE, env->error_code);
     }
     env = saved_env;
 }
index 6377907..50c5150 100644 (file)
@@ -165,4 +165,12 @@ void dump_store_dbat (int ul, int nr);
 void dump_store_tb (int ul);
 void dump_update_tb(uint32_t param);
 
+static inline void env_to_regs(void)
+{
+}
+
+static inline void regs_to_env(void)
+{
+}
+
 #endif /* !defined (__PPC_H__) */
index 941b22a..1b3d9a0 100644 (file)
@@ -109,4 +109,13 @@ void memcpy32(uint32_t *dst, const uint32_t *src);
 #define stq(p, v) stq_data(p, v)
 
 #endif /* !defined(CONFIG_USER_ONLY) */
+
+static inline void env_to_regs(void)
+{
+}
+
+static inline void regs_to_env(void)
+{
+}
+
 #endif