Commit 8c6939c0b010003cd3e66a240c3d5867ebd8044e

Authored by bellard
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
... ...