Commit 0d1a29f9fcd161b07a02b9256446235208d379ca
1 parent
b8b5ac63
correct handling of saved host registers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1122 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
129 additions
and
47 deletions
cpu-exec.c
... | ... | @@ -123,37 +123,30 @@ int cpu_exec(CPUState *env1) |
123 | 123 | #if defined(TARGET_I386) |
124 | 124 | #ifdef reg_EAX |
125 | 125 | saved_EAX = EAX; |
126 | - EAX = env->regs[R_EAX]; | |
127 | 126 | #endif |
128 | 127 | #ifdef reg_ECX |
129 | 128 | saved_ECX = ECX; |
130 | - ECX = env->regs[R_ECX]; | |
131 | 129 | #endif |
132 | 130 | #ifdef reg_EDX |
133 | 131 | saved_EDX = EDX; |
134 | - EDX = env->regs[R_EDX]; | |
135 | 132 | #endif |
136 | 133 | #ifdef reg_EBX |
137 | 134 | saved_EBX = EBX; |
138 | - EBX = env->regs[R_EBX]; | |
139 | 135 | #endif |
140 | 136 | #ifdef reg_ESP |
141 | 137 | saved_ESP = ESP; |
142 | - ESP = env->regs[R_ESP]; | |
143 | 138 | #endif |
144 | 139 | #ifdef reg_EBP |
145 | 140 | saved_EBP = EBP; |
146 | - EBP = env->regs[R_EBP]; | |
147 | 141 | #endif |
148 | 142 | #ifdef reg_ESI |
149 | 143 | saved_ESI = ESI; |
150 | - ESI = env->regs[R_ESI]; | |
151 | 144 | #endif |
152 | 145 | #ifdef reg_EDI |
153 | 146 | saved_EDI = EDI; |
154 | - EDI = env->regs[R_EDI]; | |
155 | 147 | #endif |
156 | - | |
148 | + | |
149 | + env_to_regs(); | |
157 | 150 | /* put eflags in CPU temporary format */ |
158 | 151 | CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
159 | 152 | DF = 1 - (2 * ((env->eflags >> 10) & 1)); |
... | ... | @@ -353,6 +346,8 @@ int cpu_exec(CPUState *env1) |
353 | 346 | spin_lock(&tb_lock); |
354 | 347 | |
355 | 348 | tb_invalidated_flag = 0; |
349 | + | |
350 | + regs_to_env(); /* XXX: do it just before cpu_gen_code() */ | |
356 | 351 | |
357 | 352 | /* find translated block using physical mappings */ |
358 | 353 | phys_pc = get_phys_addr_code(env, (unsigned long)pc); |
... | ... | @@ -556,6 +551,7 @@ int cpu_exec(CPUState *env1) |
556 | 551 | #endif |
557 | 552 | } |
558 | 553 | } else { |
554 | + env_to_regs(); | |
559 | 555 | } |
560 | 556 | } /* for(;;) */ |
561 | 557 | ... | ... |
dyngen-exec.h
... | ... | @@ -93,8 +93,6 @@ extern int printf(const char *, ...); |
93 | 93 | #define AREG1 "r24" |
94 | 94 | #define AREG2 "r25" |
95 | 95 | #define AREG3 "r26" |
96 | -/* XXX: suppress this hack */ | |
97 | -#if defined(CONFIG_USER_ONLY) | |
98 | 96 | #define AREG4 "r16" |
99 | 97 | #define AREG5 "r17" |
100 | 98 | #define AREG6 "r18" |
... | ... | @@ -103,7 +101,6 @@ extern int printf(const char *, ...); |
103 | 101 | #define AREG9 "r21" |
104 | 102 | #define AREG10 "r22" |
105 | 103 | #define AREG11 "r23" |
106 | -#endif | |
107 | 104 | #define USE_INT_TO_FLOAT_HELPERS |
108 | 105 | #define BUGGY_GCC_DIV64 |
109 | 106 | #endif | ... | ... |
target-arm/exec.h
... | ... | @@ -38,3 +38,11 @@ static inline int compute_cpsr(void) |
38 | 38 | return env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) | |
39 | 39 | (env->CF << 29) | ((env->VF & 0x80000000) >> 3); |
40 | 40 | } |
41 | + | |
42 | +static inline void env_to_regs(void) | |
43 | +{ | |
44 | +} | |
45 | + | |
46 | +static inline void regs_to_env(void) | |
47 | +{ | |
48 | +} | ... | ... |
target-i386/exec.h
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | #include "config.h" |
21 | 21 | #include "dyngen-exec.h" |
22 | 22 | |
23 | -/* at least 4 register variables are defines */ | |
23 | +/* at least 4 register variables are defined */ | |
24 | 24 | register struct CPUX86State *env asm(AREG0); |
25 | 25 | register uint32_t T0 asm(AREG1); |
26 | 26 | register uint32_t T1 asm(AREG2); |
... | ... | @@ -546,3 +546,58 @@ static inline void load_eflags(int eflags, int update_mask) |
546 | 546 | (eflags & update_mask); |
547 | 547 | } |
548 | 548 | |
549 | +static inline void env_to_regs(void) | |
550 | +{ | |
551 | +#ifdef reg_EAX | |
552 | + EAX = env->regs[R_EAX]; | |
553 | +#endif | |
554 | +#ifdef reg_ECX | |
555 | + ECX = env->regs[R_ECX]; | |
556 | +#endif | |
557 | +#ifdef reg_EDX | |
558 | + EDX = env->regs[R_EDX]; | |
559 | +#endif | |
560 | +#ifdef reg_EBX | |
561 | + EBX = env->regs[R_EBX]; | |
562 | +#endif | |
563 | +#ifdef reg_ESP | |
564 | + ESP = env->regs[R_ESP]; | |
565 | +#endif | |
566 | +#ifdef reg_EBP | |
567 | + EBP = env->regs[R_EBP]; | |
568 | +#endif | |
569 | +#ifdef reg_ESI | |
570 | + ESI = env->regs[R_ESI]; | |
571 | +#endif | |
572 | +#ifdef reg_EDI | |
573 | + EDI = env->regs[R_EDI]; | |
574 | +#endif | |
575 | +} | |
576 | + | |
577 | +static inline void regs_to_env(void) | |
578 | +{ | |
579 | +#ifdef reg_EAX | |
580 | + env->regs[R_EAX] = EAX; | |
581 | +#endif | |
582 | +#ifdef reg_ECX | |
583 | + env->regs[R_ECX] = ECX; | |
584 | +#endif | |
585 | +#ifdef reg_EDX | |
586 | + env->regs[R_EDX] = EDX; | |
587 | +#endif | |
588 | +#ifdef reg_EBX | |
589 | + env->regs[R_EBX] = EBX; | |
590 | +#endif | |
591 | +#ifdef reg_ESP | |
592 | + env->regs[R_ESP] = ESP; | |
593 | +#endif | |
594 | +#ifdef reg_EBP | |
595 | + env->regs[R_EBP] = EBP; | |
596 | +#endif | |
597 | +#ifdef reg_ESI | |
598 | + env->regs[R_ESI] = ESI; | |
599 | +#endif | |
600 | +#ifdef reg_EDI | |
601 | + env->regs[R_EDI] = EDI; | |
602 | +#endif | |
603 | +} | ... | ... |
target-i386/helper.c
... | ... | @@ -109,30 +109,7 @@ void cpu_loop_exit(void) |
109 | 109 | { |
110 | 110 | /* NOTE: the register at this point must be saved by hand because |
111 | 111 | longjmp restore them */ |
112 | -#ifdef reg_EAX | |
113 | - env->regs[R_EAX] = EAX; | |
114 | -#endif | |
115 | -#ifdef reg_ECX | |
116 | - env->regs[R_ECX] = ECX; | |
117 | -#endif | |
118 | -#ifdef reg_EDX | |
119 | - env->regs[R_EDX] = EDX; | |
120 | -#endif | |
121 | -#ifdef reg_EBX | |
122 | - env->regs[R_EBX] = EBX; | |
123 | -#endif | |
124 | -#ifdef reg_ESP | |
125 | - env->regs[R_ESP] = ESP; | |
126 | -#endif | |
127 | -#ifdef reg_EBP | |
128 | - env->regs[R_EBP] = EBP; | |
129 | -#endif | |
130 | -#ifdef reg_ESI | |
131 | - env->regs[R_ESI] = ESI; | |
132 | -#endif | |
133 | -#ifdef reg_EDI | |
134 | - env->regs[R_EDI] = EDI; | |
135 | -#endif | |
112 | + regs_to_env(); | |
136 | 113 | longjmp(env->jmp_env, 1); |
137 | 114 | } |
138 | 115 | |
... | ... | @@ -384,16 +361,28 @@ static void switch_tss(int tss_selector, |
384 | 361 | /* 32 bit */ |
385 | 362 | stl_kernel(env->tr.base + 0x20, next_eip); |
386 | 363 | stl_kernel(env->tr.base + 0x24, old_eflags); |
387 | - for(i = 0; i < 8; i++) | |
388 | - stl_kernel(env->tr.base + (0x28 + i * 4), env->regs[i]); | |
364 | + stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX); | |
365 | + stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX); | |
366 | + stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX); | |
367 | + stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX); | |
368 | + stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP); | |
369 | + stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP); | |
370 | + stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI); | |
371 | + stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI); | |
389 | 372 | for(i = 0; i < 6; i++) |
390 | 373 | stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector); |
391 | 374 | } else { |
392 | 375 | /* 16 bit */ |
393 | 376 | stw_kernel(env->tr.base + 0x0e, next_eip); |
394 | 377 | stw_kernel(env->tr.base + 0x10, old_eflags); |
395 | - for(i = 0; i < 8; i++) | |
396 | - stw_kernel(env->tr.base + (0x12 + i * 2), env->regs[i]); | |
378 | + stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX); | |
379 | + stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX); | |
380 | + stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX); | |
381 | + stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX); | |
382 | + stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP); | |
383 | + stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP); | |
384 | + stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI); | |
385 | + stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI); | |
397 | 386 | for(i = 0; i < 4; i++) |
398 | 387 | stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector); |
399 | 388 | } |
... | ... | @@ -437,8 +426,15 @@ static void switch_tss(int tss_selector, |
437 | 426 | if (!(type & 8)) |
438 | 427 | eflags_mask &= 0xffff; |
439 | 428 | load_eflags(new_eflags, eflags_mask); |
440 | - for(i = 0; i < 8; i++) | |
441 | - env->regs[i] = new_regs[i]; | |
429 | + /* XXX: what to do in 16 bit case ? */ | |
430 | + EAX = new_regs[0]; | |
431 | + ECX = new_regs[1]; | |
432 | + EDX = new_regs[2]; | |
433 | + EBX = new_regs[3]; | |
434 | + ESP = new_regs[4]; | |
435 | + EBP = new_regs[5]; | |
436 | + ESI = new_regs[6]; | |
437 | + EDI = new_regs[7]; | |
442 | 438 | if (new_eflags & VM_MASK) { |
443 | 439 | for(i = 0; i < 6; i++) |
444 | 440 | load_seg_vm(i, new_segs[i]); |
... | ... | @@ -633,13 +629,13 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, |
633 | 629 | mask = 0xffffffff; |
634 | 630 | else |
635 | 631 | mask = 0xffff; |
636 | - esp = (env->regs[R_ESP] - (2 << shift)) & mask; | |
632 | + esp = (ESP - (2 << shift)) & mask; | |
637 | 633 | ssp = env->segs[R_SS].base + esp; |
638 | 634 | if (shift) |
639 | 635 | stl_kernel(ssp, error_code); |
640 | 636 | else |
641 | 637 | stw_kernel(ssp, error_code); |
642 | - env->regs[R_ESP] = (esp & mask) | (env->regs[R_ESP] & ~mask); | |
638 | + ESP = (esp & mask) | (ESP & ~mask); | |
643 | 639 | } |
644 | 640 | return; |
645 | 641 | case 6: /* 286 interrupt gate */ |
... | ... | @@ -868,7 +864,7 @@ void do_interrupt(int intno, int is_int, int error_code, |
868 | 864 | if (intno == 0x0e) { |
869 | 865 | fprintf(logfile, " CR2=%08x", env->cr[2]); |
870 | 866 | } else { |
871 | - fprintf(logfile, " EAX=%08x", env->regs[R_EAX]); | |
867 | + fprintf(logfile, " EAX=%08x", EAX); | |
872 | 868 | } |
873 | 869 | fprintf(logfile, "\n"); |
874 | 870 | #if 0 |
... | ... | @@ -911,6 +907,16 @@ void raise_interrupt(int intno, int is_int, int error_code, |
911 | 907 | cpu_loop_exit(); |
912 | 908 | } |
913 | 909 | |
910 | +/* same as raise_exception_err, but do not restore global registers */ | |
911 | +static void raise_exception_err_norestore(int exception_index, int error_code) | |
912 | +{ | |
913 | + env->exception_index = exception_index; | |
914 | + env->error_code = error_code; | |
915 | + env->exception_is_int = 0; | |
916 | + env->exception_next_eip = 0; | |
917 | + longjmp(env->jmp_env, 1); | |
918 | +} | |
919 | + | |
914 | 920 | /* shortcuts to generate exceptions */ |
915 | 921 | |
916 | 922 | 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) |
2584 | 2590 | cpu_restore_state(tb, env, pc, NULL); |
2585 | 2591 | } |
2586 | 2592 | } |
2587 | - raise_exception_err(EXCP0E_PAGE, env->error_code); | |
2593 | + if (retaddr) | |
2594 | + raise_exception_err(EXCP0E_PAGE, env->error_code); | |
2595 | + else | |
2596 | + raise_exception_err_norestore(EXCP0E_PAGE, env->error_code); | |
2588 | 2597 | } |
2589 | 2598 | env = saved_env; |
2590 | 2599 | } | ... | ... |
target-ppc/exec.h
... | ... | @@ -165,4 +165,12 @@ void dump_store_dbat (int ul, int nr); |
165 | 165 | void dump_store_tb (int ul); |
166 | 166 | void dump_update_tb(uint32_t param); |
167 | 167 | |
168 | +static inline void env_to_regs(void) | |
169 | +{ | |
170 | +} | |
171 | + | |
172 | +static inline void regs_to_env(void) | |
173 | +{ | |
174 | +} | |
175 | + | |
168 | 176 | #endif /* !defined (__PPC_H__) */ | ... | ... |
target-sparc/exec.h
... | ... | @@ -109,4 +109,13 @@ void memcpy32(uint32_t *dst, const uint32_t *src); |
109 | 109 | #define stq(p, v) stq_data(p, v) |
110 | 110 | |
111 | 111 | #endif /* !defined(CONFIG_USER_ONLY) */ |
112 | + | |
113 | +static inline void env_to_regs(void) | |
114 | +{ | |
115 | +} | |
116 | + | |
117 | +static inline void regs_to_env(void) | |
118 | +{ | |
119 | +} | |
120 | + | |
112 | 121 | #endif | ... | ... |