Commit 8c6939c0b010003cd3e66a240c3d5867ebd8044e
1 parent
2d0e9143
arm support - modified sparc to work with direct chaining
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@218 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
78 additions
and
56 deletions
exec-i386.c
| ... | ... | @@ -25,58 +25,6 @@ |
| 25 | 25 | |
| 26 | 26 | /* main execution loop */ |
| 27 | 27 | |
| 28 | -/* thread support */ | |
| 29 | - | |
| 30 | -spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED; | |
| 31 | - | |
| 32 | -void cpu_lock(void) | |
| 33 | -{ | |
| 34 | - spin_lock(&global_cpu_lock); | |
| 35 | -} | |
| 36 | - | |
| 37 | -void cpu_unlock(void) | |
| 38 | -{ | |
| 39 | - spin_unlock(&global_cpu_lock); | |
| 40 | -} | |
| 41 | - | |
| 42 | -void cpu_loop_exit(void) | |
| 43 | -{ | |
| 44 | - /* NOTE: the register at this point must be saved by hand because | |
| 45 | - longjmp restore them */ | |
| 46 | -#ifdef __sparc__ | |
| 47 | - /* We have to stay in the same register window as our caller, | |
| 48 | - * thus this trick. | |
| 49 | - */ | |
| 50 | - __asm__ __volatile__("restore\n\t" | |
| 51 | - "mov\t%o0, %i0"); | |
| 52 | -#endif | |
| 53 | -#ifdef reg_EAX | |
| 54 | - env->regs[R_EAX] = EAX; | |
| 55 | -#endif | |
| 56 | -#ifdef reg_ECX | |
| 57 | - env->regs[R_ECX] = ECX; | |
| 58 | -#endif | |
| 59 | -#ifdef reg_EDX | |
| 60 | - env->regs[R_EDX] = EDX; | |
| 61 | -#endif | |
| 62 | -#ifdef reg_EBX | |
| 63 | - env->regs[R_EBX] = EBX; | |
| 64 | -#endif | |
| 65 | -#ifdef reg_ESP | |
| 66 | - env->regs[R_ESP] = ESP; | |
| 67 | -#endif | |
| 68 | -#ifdef reg_EBP | |
| 69 | - env->regs[R_EBP] = EBP; | |
| 70 | -#endif | |
| 71 | -#ifdef reg_ESI | |
| 72 | - env->regs[R_ESI] = ESI; | |
| 73 | -#endif | |
| 74 | -#ifdef reg_EDI | |
| 75 | - env->regs[R_EDI] = EDI; | |
| 76 | -#endif | |
| 77 | - longjmp(env->jmp_env, 1); | |
| 78 | -} | |
| 79 | - | |
| 80 | 28 | int cpu_x86_exec(CPUX86State *env1) |
| 81 | 29 | { |
| 82 | 30 | int saved_T0, saved_T1, saved_A0; |
| ... | ... | @@ -105,12 +53,15 @@ int cpu_x86_exec(CPUX86State *env1) |
| 105 | 53 | #ifdef reg_EDI |
| 106 | 54 | int saved_EDI; |
| 107 | 55 | #endif |
| 56 | +#ifdef __sparc__ | |
| 57 | + int saved_i7, tmp_T0; | |
| 58 | +#endif | |
| 108 | 59 | int code_gen_size, ret; |
| 109 | 60 | void (*gen_func)(void); |
| 110 | 61 | TranslationBlock *tb, **ptb; |
| 111 | 62 | uint8_t *tc_ptr, *cs_base, *pc; |
| 112 | 63 | unsigned int flags; |
| 113 | - | |
| 64 | + | |
| 114 | 65 | /* first we save global registers */ |
| 115 | 66 | saved_T0 = T0; |
| 116 | 67 | saved_T1 = T1; |
| ... | ... | @@ -149,6 +100,10 @@ int cpu_x86_exec(CPUX86State *env1) |
| 149 | 100 | saved_EDI = EDI; |
| 150 | 101 | EDI = env->regs[R_EDI]; |
| 151 | 102 | #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 | |
| 152 | 107 | |
| 153 | 108 | /* put eflags in CPU temporary format */ |
| 154 | 109 | CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); |
| ... | ... | @@ -161,6 +116,10 @@ int cpu_x86_exec(CPUX86State *env1) |
| 161 | 116 | if (setjmp(env->jmp_env) == 0) { |
| 162 | 117 | T0 = 0; /* force lookup of first TB */ |
| 163 | 118 | for(;;) { |
| 119 | +#ifdef __sparc__ | |
| 120 | + /* g1 can be modified by some libc? functions */ | |
| 121 | + tmp_T0 = T0; | |
| 122 | +#endif | |
| 164 | 123 | if (env->interrupt_request) { |
| 165 | 124 | env->exception_index = EXCP_INTERRUPT; |
| 166 | 125 | cpu_loop_exit(); |
| ... | ... | @@ -240,23 +199,32 @@ int cpu_x86_exec(CPUX86State *env1) |
| 240 | 199 | lookup_symbol((void *)tb->pc)); |
| 241 | 200 | } |
| 242 | 201 | #endif |
| 202 | +#ifdef __sparc__ | |
| 203 | + T0 = tmp_T0; | |
| 204 | +#endif | |
| 243 | 205 | /* see if we can patch the calling TB */ |
| 244 | 206 | if (T0 != 0 && !(env->eflags & TF_MASK)) { |
| 245 | 207 | spin_lock(&tb_lock); |
| 246 | 208 | tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb); |
| 247 | 209 | spin_unlock(&tb_lock); |
| 248 | 210 | } |
| 249 | - | |
| 250 | 211 | tc_ptr = tb->tc_ptr; |
| 251 | 212 | |
| 252 | 213 | /* execute the generated code */ |
| 253 | 214 | gen_func = (void *)tc_ptr; |
| 254 | -#ifdef __sparc__ | |
| 215 | +#if defined(__sparc__) | |
| 255 | 216 | __asm__ __volatile__("call %0\n\t" |
| 256 | - " mov %%o7,%%i0" | |
| 217 | + "mov %%o7,%%i0" | |
| 257 | 218 | : /* no outputs */ |
| 258 | 219 | : "r" (gen_func) |
| 259 | 220 | : "i0", "i1", "i2", "i3", "i4", "i5"); |
| 221 | +#elif defined(__arm__) | |
| 222 | + asm volatile ("mov pc, %0\n\t" | |
| 223 | + ".global exec_loop\n\t" | |
| 224 | + "exec_loop:\n\t" | |
| 225 | + : /* no outputs */ | |
| 226 | + : "r" (gen_func) | |
| 227 | + : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14"); | |
| 260 | 228 | #else |
| 261 | 229 | gen_func(); |
| 262 | 230 | #endif |
| ... | ... | @@ -292,6 +260,9 @@ int cpu_x86_exec(CPUX86State *env1) |
| 292 | 260 | #ifdef reg_EDI |
| 293 | 261 | EDI = saved_EDI; |
| 294 | 262 | #endif |
| 263 | +#ifdef __sparc__ | |
| 264 | + asm volatile ("mov %0, %%i7" : : "r" (saved_i7)); | |
| 265 | +#endif | |
| 295 | 266 | T0 = saved_T0; |
| 296 | 267 | T1 = saved_T1; |
| 297 | 268 | A0 = saved_A0; |
| ... | ... | @@ -457,6 +428,7 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, |
| 457 | 428 | uint32_t insn = *pc; |
| 458 | 429 | int is_write = 0; |
| 459 | 430 | |
| 431 | + /* XXX: need kernel patch to get write flag faster */ | |
| 460 | 432 | switch (insn >> 26) { |
| 461 | 433 | case 0x0d: // stw |
| 462 | 434 | case 0x0e: // stb |
| ... | ... | @@ -475,6 +447,56 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, |
| 475 | 447 | return handle_cpu_signal(pc, (unsigned long)info->si_addr, |
| 476 | 448 | is_write, &uc->uc_sigmask); |
| 477 | 449 | } |
| 450 | +#elif defined(__sparc__) | |
| 451 | + | |
| 452 | +int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | |
| 453 | + void *puc) | |
| 454 | +{ | |
| 455 | + uint32_t *regs = (uint32_t *)(info + 1); | |
| 456 | + void *sigmask = (regs + 20); | |
| 457 | + unsigned long pc; | |
| 458 | + int is_write; | |
| 459 | + uint32_t insn; | |
| 460 | + | |
| 461 | + /* XXX: is there a standard glibc define ? */ | |
| 462 | + pc = regs[1]; | |
| 463 | + /* XXX: need kernel patch to get write flag faster */ | |
| 464 | + is_write = 0; | |
| 465 | + insn = *(uint32_t *)pc; | |
| 466 | + if ((insn >> 30) == 3) { | |
| 467 | + switch((insn >> 19) & 0x3f) { | |
| 468 | + case 0x05: // stb | |
| 469 | + case 0x06: // sth | |
| 470 | + case 0x04: // st | |
| 471 | + case 0x07: // std | |
| 472 | + case 0x24: // stf | |
| 473 | + case 0x27: // stdf | |
| 474 | + case 0x25: // stfsr | |
| 475 | + is_write = 1; | |
| 476 | + break; | |
| 477 | + } | |
| 478 | + } | |
| 479 | + return handle_cpu_signal(pc, (unsigned long)info->si_addr, | |
| 480 | + is_write, sigmask); | |
| 481 | +} | |
| 482 | + | |
| 483 | +#elif defined(__arm__) | |
| 484 | + | |
| 485 | +int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | |
| 486 | + void *puc) | |
| 487 | +{ | |
| 488 | + struct ucontext *uc = puc; | |
| 489 | + unsigned long pc; | |
| 490 | + int is_write; | |
| 491 | + | |
| 492 | + pc = uc->uc_mcontext.gregs[R15]; | |
| 493 | + /* XXX: compute is_write */ | |
| 494 | + is_write = 0; | |
| 495 | + return handle_cpu_signal(pc, (unsigned long)info->si_addr, | |
| 496 | + is_write, | |
| 497 | + &uc->uc_sigmask); | |
| 498 | +} | |
| 499 | + | |
| 478 | 500 | #else |
| 479 | 501 | |
| 480 | 502 | #error CPU specific signal handler needed | ... | ... |