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,58 +25,6 @@ | ||
| 25 | 25 | ||
| 26 | /* main execution loop */ | 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 | int cpu_x86_exec(CPUX86State *env1) | 28 | int cpu_x86_exec(CPUX86State *env1) |
| 81 | { | 29 | { |
| 82 | int saved_T0, saved_T1, saved_A0; | 30 | int saved_T0, saved_T1, saved_A0; |
| @@ -105,12 +53,15 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -105,12 +53,15 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 105 | #ifdef reg_EDI | 53 | #ifdef reg_EDI |
| 106 | int saved_EDI; | 54 | int saved_EDI; |
| 107 | #endif | 55 | #endif |
| 56 | +#ifdef __sparc__ | ||
| 57 | + int saved_i7, tmp_T0; | ||
| 58 | +#endif | ||
| 108 | int code_gen_size, ret; | 59 | int code_gen_size, ret; |
| 109 | void (*gen_func)(void); | 60 | void (*gen_func)(void); |
| 110 | TranslationBlock *tb, **ptb; | 61 | TranslationBlock *tb, **ptb; |
| 111 | uint8_t *tc_ptr, *cs_base, *pc; | 62 | uint8_t *tc_ptr, *cs_base, *pc; |
| 112 | unsigned int flags; | 63 | unsigned int flags; |
| 113 | - | 64 | + |
| 114 | /* first we save global registers */ | 65 | /* first we save global registers */ |
| 115 | saved_T0 = T0; | 66 | saved_T0 = T0; |
| 116 | saved_T1 = T1; | 67 | saved_T1 = T1; |
| @@ -149,6 +100,10 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -149,6 +100,10 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 149 | saved_EDI = EDI; | 100 | saved_EDI = EDI; |
| 150 | EDI = env->regs[R_EDI]; | 101 | EDI = env->regs[R_EDI]; |
| 151 | #endif | 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 | /* put eflags in CPU temporary format */ | 108 | /* put eflags in CPU temporary format */ |
| 154 | CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | 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,6 +116,10 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 161 | if (setjmp(env->jmp_env) == 0) { | 116 | if (setjmp(env->jmp_env) == 0) { |
| 162 | T0 = 0; /* force lookup of first TB */ | 117 | T0 = 0; /* force lookup of first TB */ |
| 163 | for(;;) { | 118 | for(;;) { |
| 119 | +#ifdef __sparc__ | ||
| 120 | + /* g1 can be modified by some libc? functions */ | ||
| 121 | + tmp_T0 = T0; | ||
| 122 | +#endif | ||
| 164 | if (env->interrupt_request) { | 123 | if (env->interrupt_request) { |
| 165 | env->exception_index = EXCP_INTERRUPT; | 124 | env->exception_index = EXCP_INTERRUPT; |
| 166 | cpu_loop_exit(); | 125 | cpu_loop_exit(); |
| @@ -240,23 +199,32 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -240,23 +199,32 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 240 | lookup_symbol((void *)tb->pc)); | 199 | lookup_symbol((void *)tb->pc)); |
| 241 | } | 200 | } |
| 242 | #endif | 201 | #endif |
| 202 | +#ifdef __sparc__ | ||
| 203 | + T0 = tmp_T0; | ||
| 204 | +#endif | ||
| 243 | /* see if we can patch the calling TB */ | 205 | /* see if we can patch the calling TB */ |
| 244 | if (T0 != 0 && !(env->eflags & TF_MASK)) { | 206 | if (T0 != 0 && !(env->eflags & TF_MASK)) { |
| 245 | spin_lock(&tb_lock); | 207 | spin_lock(&tb_lock); |
| 246 | tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb); | 208 | tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb); |
| 247 | spin_unlock(&tb_lock); | 209 | spin_unlock(&tb_lock); |
| 248 | } | 210 | } |
| 249 | - | ||
| 250 | tc_ptr = tb->tc_ptr; | 211 | tc_ptr = tb->tc_ptr; |
| 251 | 212 | ||
| 252 | /* execute the generated code */ | 213 | /* execute the generated code */ |
| 253 | gen_func = (void *)tc_ptr; | 214 | gen_func = (void *)tc_ptr; |
| 254 | -#ifdef __sparc__ | 215 | +#if defined(__sparc__) |
| 255 | __asm__ __volatile__("call %0\n\t" | 216 | __asm__ __volatile__("call %0\n\t" |
| 256 | - " mov %%o7,%%i0" | 217 | + "mov %%o7,%%i0" |
| 257 | : /* no outputs */ | 218 | : /* no outputs */ |
| 258 | : "r" (gen_func) | 219 | : "r" (gen_func) |
| 259 | : "i0", "i1", "i2", "i3", "i4", "i5"); | 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 | #else | 228 | #else |
| 261 | gen_func(); | 229 | gen_func(); |
| 262 | #endif | 230 | #endif |
| @@ -292,6 +260,9 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -292,6 +260,9 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 292 | #ifdef reg_EDI | 260 | #ifdef reg_EDI |
| 293 | EDI = saved_EDI; | 261 | EDI = saved_EDI; |
| 294 | #endif | 262 | #endif |
| 263 | +#ifdef __sparc__ | ||
| 264 | + asm volatile ("mov %0, %%i7" : : "r" (saved_i7)); | ||
| 265 | +#endif | ||
| 295 | T0 = saved_T0; | 266 | T0 = saved_T0; |
| 296 | T1 = saved_T1; | 267 | T1 = saved_T1; |
| 297 | A0 = saved_A0; | 268 | A0 = saved_A0; |
| @@ -457,6 +428,7 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | @@ -457,6 +428,7 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
| 457 | uint32_t insn = *pc; | 428 | uint32_t insn = *pc; |
| 458 | int is_write = 0; | 429 | int is_write = 0; |
| 459 | 430 | ||
| 431 | + /* XXX: need kernel patch to get write flag faster */ | ||
| 460 | switch (insn >> 26) { | 432 | switch (insn >> 26) { |
| 461 | case 0x0d: // stw | 433 | case 0x0d: // stw |
| 462 | case 0x0e: // stb | 434 | case 0x0e: // stb |
| @@ -475,6 +447,56 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | @@ -475,6 +447,56 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
| 475 | return handle_cpu_signal(pc, (unsigned long)info->si_addr, | 447 | return handle_cpu_signal(pc, (unsigned long)info->si_addr, |
| 476 | is_write, &uc->uc_sigmask); | 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 | #else | 500 | #else |
| 479 | 501 | ||
| 480 | #error CPU specific signal handler needed | 502 | #error CPU specific signal handler needed |