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