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 | 17 | * License along with this library; if not, write to the Free Software |
| 18 | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | 19 | */ |
| 20 | +#include "config.h" | |
| 21 | +#ifdef TARGET_I386 | |
| 20 | 22 | #include "exec-i386.h" |
| 23 | +#endif | |
| 24 | +#ifdef TARGET_ARM | |
| 25 | +#include "exec-arm.h" | |
| 26 | +#endif | |
| 27 | + | |
| 21 | 28 | #include "disas.h" |
| 22 | 29 | |
| 23 | 30 | //#define DEBUG_EXEC |
| 24 | 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 | 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 | 47 | #ifdef reg_EAX |
| 33 | 48 | int saved_EAX; |
| 34 | 49 | #endif |
| ... | ... | @@ -65,9 +80,15 @@ int cpu_x86_exec(CPUX86State *env1) |
| 65 | 80 | /* first we save global registers */ |
| 66 | 81 | saved_T0 = T0; |
| 67 | 82 | saved_T1 = T1; |
| 68 | - saved_A0 = A0; | |
| 83 | + saved_T2 = T2; | |
| 69 | 84 | saved_env = env; |
| 70 | 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 | 92 | #ifdef reg_EAX |
| 72 | 93 | saved_EAX = EAX; |
| 73 | 94 | EAX = env->regs[R_EAX]; |
| ... | ... | @@ -100,16 +121,24 @@ int cpu_x86_exec(CPUX86State *env1) |
| 100 | 121 | saved_EDI = EDI; |
| 101 | 122 | EDI = env->regs[R_EDI]; |
| 102 | 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 | 125 | /* put eflags in CPU temporary format */ |
| 109 | 126 | CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
| 110 | 127 | DF = 1 - (2 * ((env->eflags >> 10) & 1)); |
| 111 | 128 | CC_OP = CC_OP_EFLAGS; |
| 112 | 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 | 142 | env->interrupt_request = 0; |
| 114 | 143 | |
| 115 | 144 | /* prepare setjmp context for exception handling */ |
| ... | ... | @@ -126,7 +155,7 @@ int cpu_x86_exec(CPUX86State *env1) |
| 126 | 155 | } |
| 127 | 156 | #ifdef DEBUG_EXEC |
| 128 | 157 | if (loglevel) { |
| 129 | - /* XXX: save all volatile state in cpu state */ | |
| 158 | +#if defined(TARGET_I386) | |
| 130 | 159 | /* restore flags in standard format */ |
| 131 | 160 | env->regs[R_EAX] = EAX; |
| 132 | 161 | env->regs[R_EBX] = EBX; |
| ... | ... | @@ -139,10 +168,16 @@ int cpu_x86_exec(CPUX86State *env1) |
| 139 | 168 | env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); |
| 140 | 169 | cpu_x86_dump_state(env, logfile, 0); |
| 141 | 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 | 177 | #endif |
| 144 | 178 | /* we compute the CPU state. We assume it will not |
| 145 | 179 | change during the whole generated block. */ |
| 180 | +#if defined(TARGET_I386) | |
| 146 | 181 | flags = env->seg_cache[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT; |
| 147 | 182 | flags |= env->seg_cache[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT; |
| 148 | 183 | flags |= (((unsigned long)env->seg_cache[R_DS].base | |
| ... | ... | @@ -159,6 +194,13 @@ int cpu_x86_exec(CPUX86State *env1) |
| 159 | 194 | flags |= (env->eflags & (IOPL_MASK | TF_MASK)); |
| 160 | 195 | cs_base = env->seg_cache[R_CS].base; |
| 161 | 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 | 204 | tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base, |
| 163 | 205 | flags); |
| 164 | 206 | if (!tb) { |
| ... | ... | @@ -178,7 +220,9 @@ int cpu_x86_exec(CPUX86State *env1) |
| 178 | 220 | tb->tc_ptr = tc_ptr; |
| 179 | 221 | tb->cs_base = (unsigned long)cs_base; |
| 180 | 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 | 226 | /* if invalid instruction, signal it */ |
| 183 | 227 | if (ret != 0) { |
| 184 | 228 | /* NOTE: the tb is allocated but not linked, so we |
| ... | ... | @@ -186,6 +230,7 @@ int cpu_x86_exec(CPUX86State *env1) |
| 186 | 230 | spin_unlock(&tb_lock); |
| 187 | 231 | raise_exception(EXCP06_ILLOP); |
| 188 | 232 | } |
| 233 | +#endif | |
| 189 | 234 | *ptb = tb; |
| 190 | 235 | tb->hash_next = NULL; |
| 191 | 236 | tb_link(tb); |
| ... | ... | @@ -202,8 +247,12 @@ int cpu_x86_exec(CPUX86State *env1) |
| 202 | 247 | #ifdef __sparc__ |
| 203 | 248 | T0 = tmp_T0; |
| 204 | 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 | 256 | spin_lock(&tb_lock); |
| 208 | 257 | tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb); |
| 209 | 258 | spin_unlock(&tb_lock); |
| ... | ... | @@ -232,6 +281,7 @@ int cpu_x86_exec(CPUX86State *env1) |
| 232 | 281 | } |
| 233 | 282 | ret = env->exception_index; |
| 234 | 283 | |
| 284 | +#if defined(TARGET_I386) | |
| 235 | 285 | /* restore flags in standard format */ |
| 236 | 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 | 310 | #ifdef reg_EDI |
| 261 | 311 | EDI = saved_EDI; |
| 262 | 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 | 323 | #ifdef __sparc__ |
| 264 | 324 | asm volatile ("mov %0, %%i7" : : "r" (saved_i7)); |
| 265 | 325 | #endif |
| 266 | 326 | T0 = saved_T0; |
| 267 | 327 | T1 = saved_T1; |
| 268 | - A0 = saved_A0; | |
| 328 | + T2 = saved_T2; | |
| 269 | 329 | env = saved_env; |
| 270 | 330 | return ret; |
| 271 | 331 | } |
| 272 | 332 | |
| 273 | -void cpu_x86_interrupt(CPUX86State *s) | |
| 333 | +void cpu_interrupt(CPUState *s) | |
| 274 | 334 | { |
| 275 | 335 | s->interrupt_request = 1; |
| 276 | 336 | } |
| 277 | 337 | |
| 278 | 338 | |
| 339 | +#if defined(TARGET_I386) | |
| 340 | + | |
| 279 | 341 | void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) |
| 280 | 342 | { |
| 281 | 343 | CPUX86State *saved_env; |
| ... | ... | @@ -322,6 +384,8 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32) |
| 322 | 384 | env = saved_env; |
| 323 | 385 | } |
| 324 | 386 | |
| 387 | +#endif /* TARGET_I386 */ | |
| 388 | + | |
| 325 | 389 | #undef EAX |
| 326 | 390 | #undef ECX |
| 327 | 391 | #undef EDX |
| ... | ... | @@ -357,15 +421,22 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
| 357 | 421 | if (tb) { |
| 358 | 422 | /* the PC is inside the translated code. It means that we have |
| 359 | 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 | 425 | if (ret < 0) |
| 362 | 426 | return 0; |
| 427 | +#if defined(TARGET_I386) | |
| 363 | 428 | env->eip = found_pc - tb->cs_base; |
| 364 | 429 | env->cr2 = address; |
| 365 | 430 | /* we restore the process signal mask as the sigreturn should |
| 366 | 431 | do it (XXX: use sigsetjmp) */ |
| 367 | 432 | sigprocmask(SIG_SETMASK, old_set, NULL); |
| 368 | 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 | 440 | /* never comes here */ |
| 370 | 441 | return 1; |
| 371 | 442 | } else { |
| ... | ... | @@ -375,8 +446,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
| 375 | 446 | |
| 376 | 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 | 452 | struct ucontext *uc = puc; |
| 382 | 453 | unsigned long pc; |
| ... | ... | @@ -396,8 +467,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, |
| 396 | 467 | |
| 397 | 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 | 473 | struct ucontext *uc = puc; |
| 403 | 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 | 491 | |
| 421 | 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 | 495 | void *puc) |
| 425 | 496 | { |
| 426 | 497 | struct ucontext *uc = puc; |
| ... | ... | @@ -449,8 +520,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, |
| 449 | 520 | } |
| 450 | 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 | 526 | uint32_t *regs = (uint32_t *)(info + 1); |
| 456 | 527 | void *sigmask = (regs + 20); |
| ... | ... | @@ -482,8 +553,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, |
| 482 | 553 | |
| 483 | 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 | 559 | struct ucontext *uc = puc; |
| 489 | 560 | unsigned long pc; | ... | ... |