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