Commit e4533c7a8cdcc79ccdf695f0aaa2e23a5b926ed0
1 parent
1e5ffbed
main cpu loop is target independent
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@238 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
95 additions
and
24 deletions
exec-i386.c renamed to cpu-exec.c
| @@ -17,18 +17,33 @@ | @@ -17,18 +17,33 @@ | ||
| 17 | * License along with this library; if not, write to the Free Software | 17 | * License along with this library; if not, write to the Free Software |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ | 19 | */ |
| 20 | +#include "config.h" | ||
| 21 | +#ifdef TARGET_I386 | ||
| 20 | #include "exec-i386.h" | 22 | #include "exec-i386.h" |
| 23 | +#endif | ||
| 24 | +#ifdef TARGET_ARM | ||
| 25 | +#include "exec-arm.h" | ||
| 26 | +#endif | ||
| 27 | + | ||
| 21 | #include "disas.h" | 28 | #include "disas.h" |
| 22 | 29 | ||
| 23 | //#define DEBUG_EXEC | 30 | //#define DEBUG_EXEC |
| 24 | //#define DEBUG_SIGNAL | 31 | //#define DEBUG_SIGNAL |
| 25 | 32 | ||
| 33 | +#if defined(TARGET_ARM) | ||
| 34 | +/* XXX: unify with i386 target */ | ||
| 35 | +void cpu_loop_exit(void) | ||
| 36 | +{ | ||
| 37 | + longjmp(env->jmp_env, 1); | ||
| 38 | +} | ||
| 39 | +#endif | ||
| 40 | + | ||
| 26 | /* main execution loop */ | 41 | /* main execution loop */ |
| 27 | 42 | ||
| 28 | -int cpu_x86_exec(CPUX86State *env1) | 43 | +int cpu_exec(CPUState *env1) |
| 29 | { | 44 | { |
| 30 | - int saved_T0, saved_T1, saved_A0; | ||
| 31 | - CPUX86State *saved_env; | 45 | + int saved_T0, saved_T1, saved_T2; |
| 46 | + CPUState *saved_env; | ||
| 32 | #ifdef reg_EAX | 47 | #ifdef reg_EAX |
| 33 | int saved_EAX; | 48 | int saved_EAX; |
| 34 | #endif | 49 | #endif |
| @@ -65,9 +80,15 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -65,9 +80,15 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 65 | /* first we save global registers */ | 80 | /* first we save global registers */ |
| 66 | saved_T0 = T0; | 81 | saved_T0 = T0; |
| 67 | saved_T1 = T1; | 82 | saved_T1 = T1; |
| 68 | - saved_A0 = A0; | 83 | + saved_T2 = T2; |
| 69 | saved_env = env; | 84 | saved_env = env; |
| 70 | env = env1; | 85 | env = env1; |
| 86 | +#ifdef __sparc__ | ||
| 87 | + /* we also save i7 because longjmp may not restore it */ | ||
| 88 | + asm volatile ("mov %%i7, %0" : "=r" (saved_i7)); | ||
| 89 | +#endif | ||
| 90 | + | ||
| 91 | +#if defined(TARGET_I386) | ||
| 71 | #ifdef reg_EAX | 92 | #ifdef reg_EAX |
| 72 | saved_EAX = EAX; | 93 | saved_EAX = EAX; |
| 73 | EAX = env->regs[R_EAX]; | 94 | EAX = env->regs[R_EAX]; |
| @@ -100,16 +121,24 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -100,16 +121,24 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 100 | saved_EDI = EDI; | 121 | saved_EDI = EDI; |
| 101 | EDI = env->regs[R_EDI]; | 122 | EDI = env->regs[R_EDI]; |
| 102 | #endif | 123 | #endif |
| 103 | -#ifdef __sparc__ | ||
| 104 | - /* we also save i7 because longjmp may not restore it */ | ||
| 105 | - asm volatile ("mov %%i7, %0" : "=r" (saved_i7)); | ||
| 106 | -#endif | ||
| 107 | 124 | ||
| 108 | /* put eflags in CPU temporary format */ | 125 | /* put eflags in CPU temporary format */ |
| 109 | CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | 126 | CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
| 110 | DF = 1 - (2 * ((env->eflags >> 10) & 1)); | 127 | DF = 1 - (2 * ((env->eflags >> 10) & 1)); |
| 111 | CC_OP = CC_OP_EFLAGS; | 128 | CC_OP = CC_OP_EFLAGS; |
| 112 | env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | 129 | env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
| 130 | +#elif defined(TARGET_ARM) | ||
| 131 | + { | ||
| 132 | + unsigned int psr; | ||
| 133 | + psr = env->cpsr; | ||
| 134 | + env->CF = (psr >> 29) & 1; | ||
| 135 | + env->NZF = (psr & 0xc0000000) ^ 0x40000000; | ||
| 136 | + env->VF = (psr << 3) & 0x80000000; | ||
| 137 | + env->cpsr = psr & ~0xf0000000; | ||
| 138 | + } | ||
| 139 | +#else | ||
| 140 | +#error unsupported target CPU | ||
| 141 | +#endif | ||
| 113 | env->interrupt_request = 0; | 142 | env->interrupt_request = 0; |
| 114 | 143 | ||
| 115 | /* prepare setjmp context for exception handling */ | 144 | /* prepare setjmp context for exception handling */ |
| @@ -126,7 +155,7 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -126,7 +155,7 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 126 | } | 155 | } |
| 127 | #ifdef DEBUG_EXEC | 156 | #ifdef DEBUG_EXEC |
| 128 | if (loglevel) { | 157 | if (loglevel) { |
| 129 | - /* XXX: save all volatile state in cpu state */ | 158 | +#if defined(TARGET_I386) |
| 130 | /* restore flags in standard format */ | 159 | /* restore flags in standard format */ |
| 131 | env->regs[R_EAX] = EAX; | 160 | env->regs[R_EAX] = EAX; |
| 132 | env->regs[R_EBX] = EBX; | 161 | env->regs[R_EBX] = EBX; |
| @@ -139,10 +168,16 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -139,10 +168,16 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 139 | env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); | 168 | env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); |
| 140 | cpu_x86_dump_state(env, logfile, 0); | 169 | cpu_x86_dump_state(env, logfile, 0); |
| 141 | env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | 170 | env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
| 171 | +#elif defined(TARGET_ARM) | ||
| 172 | + cpu_arm_dump_state(env, logfile, 0); | ||
| 173 | +#else | ||
| 174 | +#error unsupported target CPU | ||
| 175 | +#endif | ||
| 142 | } | 176 | } |
| 143 | #endif | 177 | #endif |
| 144 | /* we compute the CPU state. We assume it will not | 178 | /* we compute the CPU state. We assume it will not |
| 145 | change during the whole generated block. */ | 179 | change during the whole generated block. */ |
| 180 | +#if defined(TARGET_I386) | ||
| 146 | flags = env->seg_cache[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT; | 181 | flags = env->seg_cache[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT; |
| 147 | flags |= env->seg_cache[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT; | 182 | flags |= env->seg_cache[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT; |
| 148 | flags |= (((unsigned long)env->seg_cache[R_DS].base | | 183 | flags |= (((unsigned long)env->seg_cache[R_DS].base | |
| @@ -159,6 +194,13 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -159,6 +194,13 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 159 | flags |= (env->eflags & (IOPL_MASK | TF_MASK)); | 194 | flags |= (env->eflags & (IOPL_MASK | TF_MASK)); |
| 160 | cs_base = env->seg_cache[R_CS].base; | 195 | cs_base = env->seg_cache[R_CS].base; |
| 161 | pc = cs_base + env->eip; | 196 | pc = cs_base + env->eip; |
| 197 | +#elif defined(TARGET_ARM) | ||
| 198 | + flags = 0; | ||
| 199 | + cs_base = 0; | ||
| 200 | + pc = (uint8_t *)env->regs[15]; | ||
| 201 | +#else | ||
| 202 | +#error unsupported CPU | ||
| 203 | +#endif | ||
| 162 | tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base, | 204 | tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base, |
| 163 | flags); | 205 | flags); |
| 164 | if (!tb) { | 206 | if (!tb) { |
| @@ -178,7 +220,9 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -178,7 +220,9 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 178 | tb->tc_ptr = tc_ptr; | 220 | tb->tc_ptr = tc_ptr; |
| 179 | tb->cs_base = (unsigned long)cs_base; | 221 | tb->cs_base = (unsigned long)cs_base; |
| 180 | tb->flags = flags; | 222 | tb->flags = flags; |
| 181 | - ret = cpu_x86_gen_code(tb, CODE_GEN_MAX_SIZE, &code_gen_size); | 223 | + ret = cpu_gen_code(tb, CODE_GEN_MAX_SIZE, &code_gen_size); |
| 224 | +#if defined(TARGET_I386) | ||
| 225 | + /* XXX: suppress that, this is incorrect */ | ||
| 182 | /* if invalid instruction, signal it */ | 226 | /* if invalid instruction, signal it */ |
| 183 | if (ret != 0) { | 227 | if (ret != 0) { |
| 184 | /* NOTE: the tb is allocated but not linked, so we | 228 | /* NOTE: the tb is allocated but not linked, so we |
| @@ -186,6 +230,7 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -186,6 +230,7 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 186 | spin_unlock(&tb_lock); | 230 | spin_unlock(&tb_lock); |
| 187 | raise_exception(EXCP06_ILLOP); | 231 | raise_exception(EXCP06_ILLOP); |
| 188 | } | 232 | } |
| 233 | +#endif | ||
| 189 | *ptb = tb; | 234 | *ptb = tb; |
| 190 | tb->hash_next = NULL; | 235 | tb->hash_next = NULL; |
| 191 | tb_link(tb); | 236 | tb_link(tb); |
| @@ -202,8 +247,12 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -202,8 +247,12 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 202 | #ifdef __sparc__ | 247 | #ifdef __sparc__ |
| 203 | T0 = tmp_T0; | 248 | T0 = tmp_T0; |
| 204 | #endif | 249 | #endif |
| 205 | - /* see if we can patch the calling TB */ | ||
| 206 | - if (T0 != 0 && !(env->eflags & TF_MASK)) { | 250 | + /* see if we can patch the calling TB. XXX: remove TF test */ |
| 251 | + if (T0 != 0 | ||
| 252 | +#if defined(TARGET_I386) | ||
| 253 | + && !(env->eflags & TF_MASK) | ||
| 254 | +#endif | ||
| 255 | + ) { | ||
| 207 | spin_lock(&tb_lock); | 256 | spin_lock(&tb_lock); |
| 208 | tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb); | 257 | tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb); |
| 209 | spin_unlock(&tb_lock); | 258 | spin_unlock(&tb_lock); |
| @@ -232,6 +281,7 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -232,6 +281,7 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 232 | } | 281 | } |
| 233 | ret = env->exception_index; | 282 | ret = env->exception_index; |
| 234 | 283 | ||
| 284 | +#if defined(TARGET_I386) | ||
| 235 | /* restore flags in standard format */ | 285 | /* restore flags in standard format */ |
| 236 | env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); | 286 | env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); |
| 237 | 287 | ||
| @@ -260,22 +310,34 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -260,22 +310,34 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 260 | #ifdef reg_EDI | 310 | #ifdef reg_EDI |
| 261 | EDI = saved_EDI; | 311 | EDI = saved_EDI; |
| 262 | #endif | 312 | #endif |
| 313 | +#elif defined(TARGET_ARM) | ||
| 314 | + { | ||
| 315 | + int ZF; | ||
| 316 | + ZF = (env->NZF == 0); | ||
| 317 | + env->cpsr = env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) | | ||
| 318 | + (env->CF << 29) | ((env->VF & 0x80000000) >> 3); | ||
| 319 | + } | ||
| 320 | +#else | ||
| 321 | +#error unsupported target CPU | ||
| 322 | +#endif | ||
| 263 | #ifdef __sparc__ | 323 | #ifdef __sparc__ |
| 264 | asm volatile ("mov %0, %%i7" : : "r" (saved_i7)); | 324 | asm volatile ("mov %0, %%i7" : : "r" (saved_i7)); |
| 265 | #endif | 325 | #endif |
| 266 | T0 = saved_T0; | 326 | T0 = saved_T0; |
| 267 | T1 = saved_T1; | 327 | T1 = saved_T1; |
| 268 | - A0 = saved_A0; | 328 | + T2 = saved_T2; |
| 269 | env = saved_env; | 329 | env = saved_env; |
| 270 | return ret; | 330 | return ret; |
| 271 | } | 331 | } |
| 272 | 332 | ||
| 273 | -void cpu_x86_interrupt(CPUX86State *s) | 333 | +void cpu_interrupt(CPUState *s) |
| 274 | { | 334 | { |
| 275 | s->interrupt_request = 1; | 335 | s->interrupt_request = 1; |
| 276 | } | 336 | } |
| 277 | 337 | ||
| 278 | 338 | ||
| 339 | +#if defined(TARGET_I386) | ||
| 340 | + | ||
| 279 | void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) | 341 | void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) |
| 280 | { | 342 | { |
| 281 | CPUX86State *saved_env; | 343 | CPUX86State *saved_env; |
| @@ -322,6 +384,8 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32) | @@ -322,6 +384,8 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32) | ||
| 322 | env = saved_env; | 384 | env = saved_env; |
| 323 | } | 385 | } |
| 324 | 386 | ||
| 387 | +#endif /* TARGET_I386 */ | ||
| 388 | + | ||
| 325 | #undef EAX | 389 | #undef EAX |
| 326 | #undef ECX | 390 | #undef ECX |
| 327 | #undef EDX | 391 | #undef EDX |
| @@ -357,15 +421,22 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | @@ -357,15 +421,22 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | ||
| 357 | if (tb) { | 421 | if (tb) { |
| 358 | /* the PC is inside the translated code. It means that we have | 422 | /* the PC is inside the translated code. It means that we have |
| 359 | a virtual CPU fault */ | 423 | a virtual CPU fault */ |
| 360 | - ret = cpu_x86_search_pc(tb, &found_pc, pc); | 424 | + ret = cpu_search_pc(tb, &found_pc, pc); |
| 361 | if (ret < 0) | 425 | if (ret < 0) |
| 362 | return 0; | 426 | return 0; |
| 427 | +#if defined(TARGET_I386) | ||
| 363 | env->eip = found_pc - tb->cs_base; | 428 | env->eip = found_pc - tb->cs_base; |
| 364 | env->cr2 = address; | 429 | env->cr2 = address; |
| 365 | /* we restore the process signal mask as the sigreturn should | 430 | /* we restore the process signal mask as the sigreturn should |
| 366 | do it (XXX: use sigsetjmp) */ | 431 | do it (XXX: use sigsetjmp) */ |
| 367 | sigprocmask(SIG_SETMASK, old_set, NULL); | 432 | sigprocmask(SIG_SETMASK, old_set, NULL); |
| 368 | raise_exception_err(EXCP0E_PAGE, 4 | (is_write << 1)); | 433 | raise_exception_err(EXCP0E_PAGE, 4 | (is_write << 1)); |
| 434 | +#elif defined(TARGET_ARM) | ||
| 435 | + env->regs[15] = found_pc; | ||
| 436 | + /* XXX: do more */ | ||
| 437 | +#else | ||
| 438 | +#error unsupported target CPU | ||
| 439 | +#endif | ||
| 369 | /* never comes here */ | 440 | /* never comes here */ |
| 370 | return 1; | 441 | return 1; |
| 371 | } else { | 442 | } else { |
| @@ -375,8 +446,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | @@ -375,8 +446,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, | ||
| 375 | 446 | ||
| 376 | #if defined(__i386__) | 447 | #if defined(__i386__) |
| 377 | 448 | ||
| 378 | -int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
| 379 | - void *puc) | 449 | +int cpu_signal_handler(int host_signum, struct siginfo *info, |
| 450 | + void *puc) | ||
| 380 | { | 451 | { |
| 381 | struct ucontext *uc = puc; | 452 | struct ucontext *uc = puc; |
| 382 | unsigned long pc; | 453 | unsigned long pc; |
| @@ -396,8 +467,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | @@ -396,8 +467,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
| 396 | 467 | ||
| 397 | #elif defined(__powerpc) | 468 | #elif defined(__powerpc) |
| 398 | 469 | ||
| 399 | -int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
| 400 | - void *puc) | 470 | +int cpu_signal_handler(int host_signum, struct siginfo *info, |
| 471 | + void *puc) | ||
| 401 | { | 472 | { |
| 402 | struct ucontext *uc = puc; | 473 | struct ucontext *uc = puc; |
| 403 | struct pt_regs *regs = uc->uc_mcontext.regs; | 474 | struct pt_regs *regs = uc->uc_mcontext.regs; |
| @@ -420,7 +491,7 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | @@ -420,7 +491,7 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
| 420 | 491 | ||
| 421 | #elif defined(__alpha__) | 492 | #elif defined(__alpha__) |
| 422 | 493 | ||
| 423 | -int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | 494 | +int cpu_signal_handler(int host_signum, struct siginfo *info, |
| 424 | void *puc) | 495 | void *puc) |
| 425 | { | 496 | { |
| 426 | struct ucontext *uc = puc; | 497 | struct ucontext *uc = puc; |
| @@ -449,8 +520,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | @@ -449,8 +520,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
| 449 | } | 520 | } |
| 450 | #elif defined(__sparc__) | 521 | #elif defined(__sparc__) |
| 451 | 522 | ||
| 452 | -int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
| 453 | - void *puc) | 523 | +int cpu_signal_handler(int host_signum, struct siginfo *info, |
| 524 | + void *puc) | ||
| 454 | { | 525 | { |
| 455 | uint32_t *regs = (uint32_t *)(info + 1); | 526 | uint32_t *regs = (uint32_t *)(info + 1); |
| 456 | void *sigmask = (regs + 20); | 527 | void *sigmask = (regs + 20); |
| @@ -482,8 +553,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | @@ -482,8 +553,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
| 482 | 553 | ||
| 483 | #elif defined(__arm__) | 554 | #elif defined(__arm__) |
| 484 | 555 | ||
| 485 | -int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
| 486 | - void *puc) | 556 | +int cpu_signal_handler(int host_signum, struct siginfo *info, |
| 557 | + void *puc) | ||
| 487 | { | 558 | { |
| 488 | struct ucontext *uc = puc; | 559 | struct ucontext *uc = puc; |
| 489 | unsigned long pc; | 560 | unsigned long pc; |