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 | ... | ... |