0.7.0-alt1
[qemu] / qemu / cpu-exec.c
1 /*
2  *  i386 emulator main execution loop
3  * 
4  *  Copyright (c) 2003-2005 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "config.h"
21 #include "exec.h"
22 #include "disas.h"
23
24 #if !defined(CONFIG_SOFTMMU)
25 #undef EAX
26 #undef ECX
27 #undef EDX
28 #undef EBX
29 #undef ESP
30 #undef EBP
31 #undef ESI
32 #undef EDI
33 #undef EIP
34 #include <signal.h>
35 #include <sys/ucontext.h>
36 #endif
37
38 int tb_invalidated_flag;
39
40 //#define DEBUG_EXEC
41 //#define DEBUG_SIGNAL
42
43 #if defined(TARGET_ARM) || defined(TARGET_SPARC)
44 /* XXX: unify with i386 target */
45 void cpu_loop_exit(void)
46 {
47     longjmp(env->jmp_env, 1);
48 }
49 #endif
50
51 /* exit the current TB from a signal handler. The host registers are
52    restored in a state compatible with the CPU emulator
53  */
54 void cpu_resume_from_signal(CPUState *env1, void *puc) 
55 {
56 #if !defined(CONFIG_SOFTMMU)
57     struct ucontext *uc = puc;
58 #endif
59
60     env = env1;
61
62     /* XXX: restore cpu registers saved in host registers */
63
64 #if !defined(CONFIG_SOFTMMU)
65     if (puc) {
66         /* XXX: use siglongjmp ? */
67         sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
68     }
69 #endif
70     longjmp(env->jmp_env, 1);
71 }
72
73 /* main execution loop */
74
75 int cpu_exec(CPUState *env1)
76 {
77     int saved_T0, saved_T1, saved_T2;
78     CPUState *saved_env;
79 #ifdef reg_EAX
80     int saved_EAX;
81 #endif
82 #ifdef reg_ECX
83     int saved_ECX;
84 #endif
85 #ifdef reg_EDX
86     int saved_EDX;
87 #endif
88 #ifdef reg_EBX
89     int saved_EBX;
90 #endif
91 #ifdef reg_ESP
92     int saved_ESP;
93 #endif
94 #ifdef reg_EBP
95     int saved_EBP;
96 #endif
97 #ifdef reg_ESI
98     int saved_ESI;
99 #endif
100 #ifdef reg_EDI
101     int saved_EDI;
102 #endif
103 #ifdef __sparc__
104     int saved_i7, tmp_T0;
105 #endif
106     int code_gen_size, ret, interrupt_request;
107     void (*gen_func)(void);
108     TranslationBlock *tb, **ptb;
109     target_ulong cs_base, pc;
110     uint8_t *tc_ptr;
111     unsigned int flags;
112
113     /* first we save global registers */
114     saved_env = env;
115     env = env1;
116     saved_T0 = T0;
117     saved_T1 = T1;
118     saved_T2 = T2;
119 #ifdef __sparc__
120     /* we also save i7 because longjmp may not restore it */
121     asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
122 #endif
123
124 #if defined(TARGET_I386)
125 #ifdef reg_EAX
126     saved_EAX = EAX;
127 #endif
128 #ifdef reg_ECX
129     saved_ECX = ECX;
130 #endif
131 #ifdef reg_EDX
132     saved_EDX = EDX;
133 #endif
134 #ifdef reg_EBX
135     saved_EBX = EBX;
136 #endif
137 #ifdef reg_ESP
138     saved_ESP = ESP;
139 #endif
140 #ifdef reg_EBP
141     saved_EBP = EBP;
142 #endif
143 #ifdef reg_ESI
144     saved_ESI = ESI;
145 #endif
146 #ifdef reg_EDI
147     saved_EDI = EDI;
148 #endif
149
150     env_to_regs();
151     /* put eflags in CPU temporary format */
152     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
153     DF = 1 - (2 * ((env->eflags >> 10) & 1));
154     CC_OP = CC_OP_EFLAGS;
155     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
156 #elif defined(TARGET_ARM)
157     {
158         unsigned int psr;
159         psr = env->cpsr;
160         env->CF = (psr >> 29) & 1;
161         env->NZF = (psr & 0xc0000000) ^ 0x40000000;
162         env->VF = (psr << 3) & 0x80000000;
163         env->QF = (psr >> 27) & 1;
164         env->cpsr = psr & ~CACHED_CPSR_BITS;
165     }
166 #elif defined(TARGET_SPARC)
167 #elif defined(TARGET_PPC)
168 #else
169 #error unsupported target CPU
170 #endif
171     env->exception_index = -1;
172
173     /* prepare setjmp context for exception handling */
174     for(;;) {
175         if (setjmp(env->jmp_env) == 0) {
176             env->current_tb = NULL;
177             /* if an exception is pending, we execute it here */
178             if (env->exception_index >= 0) {
179                 if (env->exception_index >= EXCP_INTERRUPT) {
180                     /* exit request from the cpu execution loop */
181                     ret = env->exception_index;
182                     break;
183                 } else if (env->user_mode_only) {
184                     /* if user mode only, we simulate a fake exception
185                        which will be hanlded outside the cpu execution
186                        loop */
187 #if defined(TARGET_I386)
188                     do_interrupt_user(env->exception_index, 
189                                       env->exception_is_int, 
190                                       env->error_code, 
191                                       env->exception_next_eip);
192 #endif
193                     ret = env->exception_index;
194                     break;
195                 } else {
196 #if defined(TARGET_I386)
197                     /* simulate a real cpu exception. On i386, it can
198                        trigger new exceptions, but we do not handle
199                        double or triple faults yet. */
200                     do_interrupt(env->exception_index, 
201                                  env->exception_is_int, 
202                                  env->error_code, 
203                                  env->exception_next_eip, 0);
204 #elif defined(TARGET_PPC)
205                     do_interrupt(env);
206 #elif defined(TARGET_SPARC)
207                     do_interrupt(env->exception_index);
208 #endif
209                 }
210                 env->exception_index = -1;
211             } 
212 #ifdef USE_KQEMU
213             if (kqemu_is_ok(env) && env->interrupt_request == 0) {
214                 int ret;
215                 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
216                 ret = kqemu_cpu_exec(env);
217                 /* put eflags in CPU temporary format */
218                 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
219                 DF = 1 - (2 * ((env->eflags >> 10) & 1));
220                 CC_OP = CC_OP_EFLAGS;
221                 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
222                 if (ret == 1) {
223                     /* exception */
224                     longjmp(env->jmp_env, 1);
225                 } else if (ret == 2) {
226                     /* softmmu execution needed */
227                 } else {
228                     if (env->interrupt_request != 0) {
229                         /* hardware interrupt will be executed just after */
230                     } else {
231                         /* otherwise, we restart */
232                         longjmp(env->jmp_env, 1);
233                     }
234                 }
235             }
236 #endif
237
238             T0 = 0; /* force lookup of first TB */
239             for(;;) {
240 #ifdef __sparc__
241                 /* g1 can be modified by some libc? functions */ 
242                 tmp_T0 = T0;
243 #endif      
244                 interrupt_request = env->interrupt_request;
245                 if (__builtin_expect(interrupt_request, 0)) {
246 #if defined(TARGET_I386)
247                     /* if hardware interrupt pending, we execute it */
248                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
249                         (env->eflags & IF_MASK) && 
250                         !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
251                         int intno;
252                         env->interrupt_request &= ~CPU_INTERRUPT_HARD;
253                         intno = cpu_get_pic_interrupt(env);
254                         if (loglevel & CPU_LOG_TB_IN_ASM) {
255                             fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
256                         }
257                         do_interrupt(intno, 0, 0, 0, 1);
258                         /* ensure that no TB jump will be modified as
259                            the program flow was changed */
260 #ifdef __sparc__
261                         tmp_T0 = 0;
262 #else
263                         T0 = 0;
264 #endif
265                     }
266 #elif defined(TARGET_PPC)
267 #if 0
268                     if ((interrupt_request & CPU_INTERRUPT_RESET)) {
269                         cpu_ppc_reset(env);
270                     }
271 #endif
272                     if (msr_ee != 0) {
273                     if ((interrupt_request & CPU_INTERRUPT_HARD)) {
274                             /* Raise it */
275                             env->exception_index = EXCP_EXTERNAL;
276                             env->error_code = 0;
277                             do_interrupt(env);
278                         env->interrupt_request &= ~CPU_INTERRUPT_HARD;
279                         } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
280                             /* Raise it */
281                             env->exception_index = EXCP_DECR;
282                             env->error_code = 0;
283                             do_interrupt(env);
284                             env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
285                         }
286                     }
287 #elif defined(TARGET_SPARC)
288                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
289                         (env->psret != 0)) {
290                         int pil = env->interrupt_index & 15;
291                         int type = env->interrupt_index & 0xf0;
292
293                         if (((type == TT_EXTINT) &&
294                              (pil == 15 || pil > env->psrpil)) ||
295                             type != TT_EXTINT) {
296                             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
297                             do_interrupt(env->interrupt_index);
298                             env->interrupt_index = 0;
299                         }
300                     } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
301                         //do_interrupt(0, 0, 0, 0, 0);
302                         env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
303                     }
304 #endif
305                     if (interrupt_request & CPU_INTERRUPT_EXITTB) {
306                         env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
307                         /* ensure that no TB jump will be modified as
308                            the program flow was changed */
309 #ifdef __sparc__
310                         tmp_T0 = 0;
311 #else
312                         T0 = 0;
313 #endif
314                     }
315                     if (interrupt_request & CPU_INTERRUPT_EXIT) {
316                         env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
317                         env->exception_index = EXCP_INTERRUPT;
318                         cpu_loop_exit();
319                     }
320                 }
321 #ifdef DEBUG_EXEC
322                 if ((loglevel & CPU_LOG_EXEC)) {
323 #if defined(TARGET_I386)
324                     /* restore flags in standard format */
325 #ifdef reg_EAX
326                     env->regs[R_EAX] = EAX;
327 #endif
328 #ifdef reg_EBX
329                     env->regs[R_EBX] = EBX;
330 #endif
331 #ifdef reg_ECX
332                     env->regs[R_ECX] = ECX;
333 #endif
334 #ifdef reg_EDX
335                     env->regs[R_EDX] = EDX;
336 #endif
337 #ifdef reg_ESI
338                     env->regs[R_ESI] = ESI;
339 #endif
340 #ifdef reg_EDI
341                     env->regs[R_EDI] = EDI;
342 #endif
343 #ifdef reg_EBP
344                     env->regs[R_EBP] = EBP;
345 #endif
346 #ifdef reg_ESP
347                     env->regs[R_ESP] = ESP;
348 #endif
349                     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
350                     cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
351                     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
352 #elif defined(TARGET_ARM)
353                     env->cpsr = compute_cpsr();
354                     cpu_dump_state(env, logfile, fprintf, 0);
355                     env->cpsr &= ~CACHED_CPSR_BITS;
356 #elif defined(TARGET_SPARC)
357                     cpu_dump_state (env, logfile, fprintf, 0);
358 #elif defined(TARGET_PPC)
359                     cpu_dump_state(env, logfile, fprintf, 0);
360 #else
361 #error unsupported target CPU 
362 #endif
363                 }
364 #endif
365                 /* we record a subset of the CPU state. It will
366                    always be the same before a given translated block
367                    is executed. */
368 #if defined(TARGET_I386)
369                 flags = env->hflags;
370                 flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
371                 cs_base = env->segs[R_CS].base;
372                 pc = cs_base + env->eip;
373 #elif defined(TARGET_ARM)
374                 flags = env->thumb | (env->vfp.vec_len << 1)
375                         | (env->vfp.vec_stride << 4);
376                 cs_base = 0;
377                 pc = env->regs[15];
378 #elif defined(TARGET_SPARC)
379                 flags = 0;
380                 cs_base = env->npc;
381                 pc = env->pc;
382 #elif defined(TARGET_PPC)
383                 flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) |
384                     (msr_se << MSR_SE) | (msr_le << MSR_LE);
385                 cs_base = 0;
386                 pc = env->nip;
387 #else
388 #error unsupported CPU
389 #endif
390                 tb = tb_find(&ptb, pc, cs_base, 
391                              flags);
392                 if (!tb) {
393                     TranslationBlock **ptb1;
394                     unsigned int h;
395                     target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
396                     
397                     
398                     spin_lock(&tb_lock);
399
400                     tb_invalidated_flag = 0;
401                     
402                     regs_to_env(); /* XXX: do it just before cpu_gen_code() */
403
404                     /* find translated block using physical mappings */
405                     phys_pc = get_phys_addr_code(env, pc);
406                     phys_page1 = phys_pc & TARGET_PAGE_MASK;
407                     phys_page2 = -1;
408                     h = tb_phys_hash_func(phys_pc);
409                     ptb1 = &tb_phys_hash[h];
410                     for(;;) {
411                         tb = *ptb1;
412                         if (!tb)
413                             goto not_found;
414                         if (tb->pc == pc && 
415                             tb->page_addr[0] == phys_page1 &&
416                             tb->cs_base == cs_base && 
417                             tb->flags == flags) {
418                             /* check next page if needed */
419                             if (tb->page_addr[1] != -1) {
420                                 virt_page2 = (pc & TARGET_PAGE_MASK) + 
421                                     TARGET_PAGE_SIZE;
422                                 phys_page2 = get_phys_addr_code(env, virt_page2);
423                                 if (tb->page_addr[1] == phys_page2)
424                                     goto found;
425                             } else {
426                                 goto found;
427                             }
428                         }
429                         ptb1 = &tb->phys_hash_next;
430                     }
431                 not_found:
432                     /* if no translated code available, then translate it now */
433                     tb = tb_alloc(pc);
434                     if (!tb) {
435                         /* flush must be done */
436                         tb_flush(env);
437                         /* cannot fail at this point */
438                         tb = tb_alloc(pc);
439                         /* don't forget to invalidate previous TB info */
440                         ptb = &tb_hash[tb_hash_func(pc)];
441                         T0 = 0;
442                     }
443                     tc_ptr = code_gen_ptr;
444                     tb->tc_ptr = tc_ptr;
445                     tb->cs_base = cs_base;
446                     tb->flags = flags;
447                     cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
448                     code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
449                     
450                     /* check next page if needed */
451                     virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
452                     phys_page2 = -1;
453                     if ((pc & TARGET_PAGE_MASK) != virt_page2) {
454                         phys_page2 = get_phys_addr_code(env, virt_page2);
455                     }
456                     tb_link_phys(tb, phys_pc, phys_page2);
457
458                 found:
459                     if (tb_invalidated_flag) {
460                         /* as some TB could have been invalidated because
461                            of memory exceptions while generating the code, we
462                            must recompute the hash index here */
463                         ptb = &tb_hash[tb_hash_func(pc)];
464                         while (*ptb != NULL)
465                             ptb = &(*ptb)->hash_next;
466                         T0 = 0;
467                     }
468                     /* we add the TB in the virtual pc hash table */
469                     *ptb = tb;
470                     tb->hash_next = NULL;
471                     tb_link(tb);
472                     spin_unlock(&tb_lock);
473                 }
474 #ifdef DEBUG_EXEC
475                 if ((loglevel & CPU_LOG_EXEC)) {
476                     fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
477                             (long)tb->tc_ptr, tb->pc,
478                             lookup_symbol(tb->pc));
479                 }
480 #endif
481 #ifdef __sparc__
482                 T0 = tmp_T0;
483 #endif      
484                 /* see if we can patch the calling TB. */
485                 {
486                     if (T0 != 0
487 #if defined(TARGET_I386) && defined(USE_CODE_COPY)
488                     && (tb->cflags & CF_CODE_COPY) == 
489                     (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
490 #endif
491                     ) {
492                     spin_lock(&tb_lock);
493                     tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
494 #if defined(USE_CODE_COPY)
495                     /* propagates the FP use info */
496                     ((TranslationBlock *)(T0 & ~3))->cflags |= 
497                         (tb->cflags & CF_FP_USED);
498 #endif
499                     spin_unlock(&tb_lock);
500                 }
501                 }
502                 tc_ptr = tb->tc_ptr;
503                 env->current_tb = tb;
504                 /* execute the generated code */
505                 gen_func = (void *)tc_ptr;
506 #if defined(__sparc__)
507                 __asm__ __volatile__("call      %0\n\t"
508                                      "mov       %%o7,%%i0"
509                                      : /* no outputs */
510                                      : "r" (gen_func) 
511                                      : "i0", "i1", "i2", "i3", "i4", "i5");
512 #elif defined(__arm__)
513                 asm volatile ("mov pc, %0\n\t"
514                               ".global exec_loop\n\t"
515                               "exec_loop:\n\t"
516                               : /* no outputs */
517                               : "r" (gen_func)
518                               : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
519 #elif defined(TARGET_I386) && defined(USE_CODE_COPY)
520 {
521     if (!(tb->cflags & CF_CODE_COPY)) {
522         if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
523             save_native_fp_state(env);
524         }
525         gen_func();
526     } else {
527         if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
528             restore_native_fp_state(env);
529         }
530         /* we work with native eflags */
531         CC_SRC = cc_table[CC_OP].compute_all();
532         CC_OP = CC_OP_EFLAGS;
533         asm(".globl exec_loop\n"
534             "\n"
535             "debug1:\n"
536             "    pushl %%ebp\n"
537             "    fs movl %10, %9\n"
538             "    fs movl %11, %%eax\n"
539             "    andl $0x400, %%eax\n"
540             "    fs orl %8, %%eax\n"
541             "    pushl %%eax\n"
542             "    popf\n"
543             "    fs movl %%esp, %12\n"
544             "    fs movl %0, %%eax\n"
545             "    fs movl %1, %%ecx\n"
546             "    fs movl %2, %%edx\n"
547             "    fs movl %3, %%ebx\n"
548             "    fs movl %4, %%esp\n"
549             "    fs movl %5, %%ebp\n"
550             "    fs movl %6, %%esi\n"
551             "    fs movl %7, %%edi\n"
552             "    fs jmp *%9\n"
553             "exec_loop:\n"
554             "    fs movl %%esp, %4\n"
555             "    fs movl %12, %%esp\n"
556             "    fs movl %%eax, %0\n"
557             "    fs movl %%ecx, %1\n"
558             "    fs movl %%edx, %2\n"
559             "    fs movl %%ebx, %3\n"
560             "    fs movl %%ebp, %5\n"
561             "    fs movl %%esi, %6\n"
562             "    fs movl %%edi, %7\n"
563             "    pushf\n"
564             "    popl %%eax\n"
565             "    movl %%eax, %%ecx\n"
566             "    andl $0x400, %%ecx\n"
567             "    shrl $9, %%ecx\n"
568             "    andl $0x8d5, %%eax\n"
569             "    fs movl %%eax, %8\n"
570             "    movl $1, %%eax\n"
571             "    subl %%ecx, %%eax\n"
572             "    fs movl %%eax, %11\n"
573             "    fs movl %9, %%ebx\n" /* get T0 value */
574             "    popl %%ebp\n"
575             :
576             : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
577             "m" (*(uint8_t *)offsetof(CPUState, regs[1])),
578             "m" (*(uint8_t *)offsetof(CPUState, regs[2])),
579             "m" (*(uint8_t *)offsetof(CPUState, regs[3])),
580             "m" (*(uint8_t *)offsetof(CPUState, regs[4])),
581             "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
582             "m" (*(uint8_t *)offsetof(CPUState, regs[6])),
583             "m" (*(uint8_t *)offsetof(CPUState, regs[7])),
584             "m" (*(uint8_t *)offsetof(CPUState, cc_src)),
585             "m" (*(uint8_t *)offsetof(CPUState, tmp0)),
586             "a" (gen_func),
587             "m" (*(uint8_t *)offsetof(CPUState, df)),
588             "m" (*(uint8_t *)offsetof(CPUState, saved_esp))
589             : "%ecx", "%edx"
590             );
591     }
592 }
593 #elif defined(__ia64)
594                 struct fptr {
595                         void *ip;
596                         void *gp;
597                 } fp;
598
599                 fp.ip = tc_ptr;
600                 fp.gp = code_gen_buffer + 2 * (1 << 20);
601                 (*(void (*)(void)) &fp)();
602 #else
603                 gen_func();
604 #endif
605                 env->current_tb = NULL;
606                 /* reset soft MMU for next block (it can currently
607                    only be set by a memory fault) */
608 #if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
609                 if (env->hflags & HF_SOFTMMU_MASK) {
610                     env->hflags &= ~HF_SOFTMMU_MASK;
611                     /* do not allow linking to another block */
612                     T0 = 0;
613                 }
614 #endif
615             }
616         } else {
617             env_to_regs();
618         }
619     } /* for(;;) */
620
621
622 #if defined(TARGET_I386)
623 #if defined(USE_CODE_COPY)
624     if (env->native_fp_regs) {
625         save_native_fp_state(env);
626     }
627 #endif
628     /* restore flags in standard format */
629     env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
630
631     /* restore global registers */
632 #ifdef reg_EAX
633     EAX = saved_EAX;
634 #endif
635 #ifdef reg_ECX
636     ECX = saved_ECX;
637 #endif
638 #ifdef reg_EDX
639     EDX = saved_EDX;
640 #endif
641 #ifdef reg_EBX
642     EBX = saved_EBX;
643 #endif
644 #ifdef reg_ESP
645     ESP = saved_ESP;
646 #endif
647 #ifdef reg_EBP
648     EBP = saved_EBP;
649 #endif
650 #ifdef reg_ESI
651     ESI = saved_ESI;
652 #endif
653 #ifdef reg_EDI
654     EDI = saved_EDI;
655 #endif
656 #elif defined(TARGET_ARM)
657     env->cpsr = compute_cpsr();
658     /* XXX: Save/restore host fpu exception state?.  */
659 #elif defined(TARGET_SPARC)
660 #elif defined(TARGET_PPC)
661 #else
662 #error unsupported target CPU
663 #endif
664 #ifdef __sparc__
665     asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
666 #endif
667     T0 = saved_T0;
668     T1 = saved_T1;
669     T2 = saved_T2;
670     env = saved_env;
671     return ret;
672 }
673
674 /* must only be called from the generated code as an exception can be
675    generated */
676 void tb_invalidate_page_range(target_ulong start, target_ulong end)
677 {
678     /* XXX: cannot enable it yet because it yields to MMU exception
679        where NIP != read address on PowerPC */
680 #if 0
681     target_ulong phys_addr;
682     phys_addr = get_phys_addr_code(env, start);
683     tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
684 #endif
685 }
686
687 #if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
688
689 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
690 {
691     CPUX86State *saved_env;
692
693     saved_env = env;
694     env = s;
695     if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
696         selector &= 0xffff;
697         cpu_x86_load_seg_cache(env, seg_reg, selector, 
698                                (selector << 4), 0xffff, 0);
699     } else {
700         load_seg(seg_reg, selector);
701     }
702     env = saved_env;
703 }
704
705 void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)
706 {
707     CPUX86State *saved_env;
708
709     saved_env = env;
710     env = s;
711     
712     helper_fsave((target_ulong)ptr, data32);
713
714     env = saved_env;
715 }
716
717 void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
718 {
719     CPUX86State *saved_env;
720
721     saved_env = env;
722     env = s;
723     
724     helper_frstor((target_ulong)ptr, data32);
725
726     env = saved_env;
727 }
728
729 #endif /* TARGET_I386 */
730
731 #if !defined(CONFIG_SOFTMMU)
732
733 #if defined(TARGET_I386)
734
735 /* 'pc' is the host PC at which the exception was raised. 'address' is
736    the effective address of the memory exception. 'is_write' is 1 if a
737    write caused the exception and otherwise 0'. 'old_set' is the
738    signal set which should be restored */
739 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
740                                     int is_write, sigset_t *old_set, 
741                                     void *puc)
742 {
743     TranslationBlock *tb;
744     int ret;
745
746     if (cpu_single_env)
747         env = cpu_single_env; /* XXX: find a correct solution for multithread */
748 #if defined(DEBUG_SIGNAL)
749     qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
750                 pc, address, is_write, *(unsigned long *)old_set);
751 #endif
752     /* XXX: locking issue */
753     if (is_write && page_unprotect(address, pc, puc)) {
754         return 1;
755     }
756
757     /* see if it is an MMU fault */
758     ret = cpu_x86_handle_mmu_fault(env, address, is_write, 
759                                    ((env->hflags & HF_CPL_MASK) == 3), 0);
760     if (ret < 0)
761         return 0; /* not an MMU fault */
762     if (ret == 0)
763         return 1; /* the MMU fault was handled without causing real CPU fault */
764     /* now we have a real cpu fault */
765     tb = tb_find_pc(pc);
766     if (tb) {
767         /* the PC is inside the translated code. It means that we have
768            a virtual CPU fault */
769         cpu_restore_state(tb, env, pc, puc);
770     }
771     if (ret == 1) {
772 #if 0
773         printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n", 
774                env->eip, env->cr[2], env->error_code);
775 #endif
776         /* we restore the process signal mask as the sigreturn should
777            do it (XXX: use sigsetjmp) */
778         sigprocmask(SIG_SETMASK, old_set, NULL);
779         raise_exception_err(EXCP0E_PAGE, env->error_code);
780     } else {
781         /* activate soft MMU for this block */
782         env->hflags |= HF_SOFTMMU_MASK;
783         cpu_resume_from_signal(env, puc);
784     }
785     /* never comes here */
786     return 1;
787 }
788
789 #elif defined(TARGET_ARM)
790 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
791                                     int is_write, sigset_t *old_set,
792                                     void *puc)
793 {
794     TranslationBlock *tb;
795     int ret;
796
797     if (cpu_single_env)
798         env = cpu_single_env; /* XXX: find a correct solution for multithread */
799 #if defined(DEBUG_SIGNAL)
800     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
801            pc, address, is_write, *(unsigned long *)old_set);
802 #endif
803     /* XXX: locking issue */
804     if (is_write && page_unprotect(address, pc, puc)) {
805         return 1;
806     }
807     /* see if it is an MMU fault */
808     ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0);
809     if (ret < 0)
810         return 0; /* not an MMU fault */
811     if (ret == 0)
812         return 1; /* the MMU fault was handled without causing real CPU fault */
813     /* now we have a real cpu fault */
814     tb = tb_find_pc(pc);
815     if (tb) {
816         /* the PC is inside the translated code. It means that we have
817            a virtual CPU fault */
818         cpu_restore_state(tb, env, pc, puc);
819     }
820     /* we restore the process signal mask as the sigreturn should
821        do it (XXX: use sigsetjmp) */
822     sigprocmask(SIG_SETMASK, old_set, NULL);
823     cpu_loop_exit();
824 }
825 #elif defined(TARGET_SPARC)
826 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
827                                     int is_write, sigset_t *old_set,
828                                     void *puc)
829 {
830     TranslationBlock *tb;
831     int ret;
832
833     if (cpu_single_env)
834         env = cpu_single_env; /* XXX: find a correct solution for multithread */
835 #if defined(DEBUG_SIGNAL)
836     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
837            pc, address, is_write, *(unsigned long *)old_set);
838 #endif
839     /* XXX: locking issue */
840     if (is_write && page_unprotect(address, pc, puc)) {
841         return 1;
842     }
843     /* see if it is an MMU fault */
844     ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0);
845     if (ret < 0)
846         return 0; /* not an MMU fault */
847     if (ret == 0)
848         return 1; /* the MMU fault was handled without causing real CPU fault */
849     /* now we have a real cpu fault */
850     tb = tb_find_pc(pc);
851     if (tb) {
852         /* the PC is inside the translated code. It means that we have
853            a virtual CPU fault */
854         cpu_restore_state(tb, env, pc, puc);
855     }
856     /* we restore the process signal mask as the sigreturn should
857        do it (XXX: use sigsetjmp) */
858     sigprocmask(SIG_SETMASK, old_set, NULL);
859     cpu_loop_exit();
860 }
861 #elif defined (TARGET_PPC)
862 static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
863                                     int is_write, sigset_t *old_set,
864                                     void *puc)
865 {
866     TranslationBlock *tb;
867     int ret;
868     
869     if (cpu_single_env)
870         env = cpu_single_env; /* XXX: find a correct solution for multithread */
871 #if defined(DEBUG_SIGNAL)
872     printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
873            pc, address, is_write, *(unsigned long *)old_set);
874 #endif
875     /* XXX: locking issue */
876     if (is_write && page_unprotect(address, pc, puc)) {
877         return 1;
878     }
879
880     /* see if it is an MMU fault */
881     ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
882     if (ret < 0)
883         return 0; /* not an MMU fault */
884     if (ret == 0)
885         return 1; /* the MMU fault was handled without causing real CPU fault */
886
887     /* now we have a real cpu fault */
888     tb = tb_find_pc(pc);
889     if (tb) {
890         /* the PC is inside the translated code. It means that we have
891            a virtual CPU fault */
892         cpu_restore_state(tb, env, pc, puc);
893     }
894     if (ret == 1) {
895 #if 0
896         printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
897                env->nip, env->error_code, tb);
898 #endif
899     /* we restore the process signal mask as the sigreturn should
900        do it (XXX: use sigsetjmp) */
901         sigprocmask(SIG_SETMASK, old_set, NULL);
902         do_raise_exception_err(env->exception_index, env->error_code);
903     } else {
904         /* activate soft MMU for this block */
905         cpu_resume_from_signal(env, puc);
906     }
907     /* never comes here */
908     return 1;
909 }
910 #else
911 #error unsupported target CPU
912 #endif
913
914 #if defined(__i386__)
915
916 #if defined(USE_CODE_COPY)
917 static void cpu_send_trap(unsigned long pc, int trap, 
918                           struct ucontext *uc)
919 {
920     TranslationBlock *tb;
921
922     if (cpu_single_env)
923         env = cpu_single_env; /* XXX: find a correct solution for multithread */
924     /* now we have a real cpu fault */
925     tb = tb_find_pc(pc);
926     if (tb) {
927         /* the PC is inside the translated code. It means that we have
928            a virtual CPU fault */
929         cpu_restore_state(tb, env, pc, uc);
930     }
931     sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
932     raise_exception_err(trap, env->error_code);
933 }
934 #endif
935
936 int cpu_signal_handler(int host_signum, struct siginfo *info, 
937                        void *puc)
938 {
939     struct ucontext *uc = puc;
940     unsigned long pc;
941     int trapno;
942
943 #ifndef REG_EIP
944 /* for glibc 2.1 */
945 #define REG_EIP    EIP
946 #define REG_ERR    ERR
947 #define REG_TRAPNO TRAPNO
948 #endif
949     pc = uc->uc_mcontext.gregs[REG_EIP];
950     trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
951 #if defined(TARGET_I386) && defined(USE_CODE_COPY)
952     if (trapno == 0x00 || trapno == 0x05) {
953         /* send division by zero or bound exception */
954         cpu_send_trap(pc, trapno, uc);
955         return 1;
956     } else
957 #endif
958         return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
959                                  trapno == 0xe ? 
960                                  (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
961                                  &uc->uc_sigmask, puc);
962 }
963
964 #elif defined(__x86_64__)
965
966 int cpu_signal_handler(int host_signum, struct siginfo *info,
967                        void *puc)
968 {
969     struct ucontext *uc = puc;
970     unsigned long pc;
971
972     pc = uc->uc_mcontext.gregs[REG_RIP];
973     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
974                              uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? 
975                              (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
976                              &uc->uc_sigmask, puc);
977 }
978
979 #elif defined(__powerpc__)
980
981 /***********************************************************************
982  * signal context platform-specific definitions
983  * From Wine
984  */
985 #ifdef linux
986 /* All Registers access - only for local access */
987 # define REG_sig(reg_name, context)             ((context)->uc_mcontext.regs->reg_name)
988 /* Gpr Registers access  */
989 # define GPR_sig(reg_num, context)              REG_sig(gpr[reg_num], context)
990 # define IAR_sig(context)                       REG_sig(nip, context)   /* Program counter */
991 # define MSR_sig(context)                       REG_sig(msr, context)   /* Machine State Register (Supervisor) */
992 # define CTR_sig(context)                       REG_sig(ctr, context)   /* Count register */
993 # define XER_sig(context)                       REG_sig(xer, context) /* User's integer exception register */
994 # define LR_sig(context)                        REG_sig(link, context) /* Link register */
995 # define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
996 /* Float Registers access  */
997 # define FLOAT_sig(reg_num, context)            (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
998 # define FPSCR_sig(context)                     (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
999 /* Exception Registers access */
1000 # define DAR_sig(context)                       REG_sig(dar, context)
1001 # define DSISR_sig(context)                     REG_sig(dsisr, context)
1002 # define TRAP_sig(context)                      REG_sig(trap, context)
1003 #endif /* linux */
1004
1005 #ifdef __APPLE__
1006 # include <sys/ucontext.h>
1007 typedef struct ucontext SIGCONTEXT;
1008 /* All Registers access - only for local access */
1009 # define REG_sig(reg_name, context)             ((context)->uc_mcontext->ss.reg_name)
1010 # define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1011 # define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1012 # define VECREG_sig(reg_name, context)          ((context)->uc_mcontext->vs.reg_name)
1013 /* Gpr Registers access */
1014 # define GPR_sig(reg_num, context)              REG_sig(r##reg_num, context)
1015 # define IAR_sig(context)                       REG_sig(srr0, context)  /* Program counter */
1016 # define MSR_sig(context)                       REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1017 # define CTR_sig(context)                       REG_sig(ctr, context)
1018 # define XER_sig(context)                       REG_sig(xer, context) /* Link register */
1019 # define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1020 # define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1021 /* Float Registers access */
1022 # define FLOAT_sig(reg_num, context)            FLOATREG_sig(fpregs[reg_num], context)
1023 # define FPSCR_sig(context)                     ((double)FLOATREG_sig(fpscr, context))
1024 /* Exception Registers access */
1025 # define DAR_sig(context)                       EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1026 # define DSISR_sig(context)                     EXCEPREG_sig(dsisr, context)
1027 # define TRAP_sig(context)                      EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1028 #endif /* __APPLE__ */
1029
1030 int cpu_signal_handler(int host_signum, struct siginfo *info, 
1031                        void *puc)
1032 {
1033     struct ucontext *uc = puc;
1034     unsigned long pc;
1035     int is_write;
1036
1037     pc = IAR_sig(uc);
1038     is_write = 0;
1039 #if 0
1040     /* ppc 4xx case */
1041     if (DSISR_sig(uc) & 0x00800000)
1042         is_write = 1;
1043 #else
1044     if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1045         is_write = 1;
1046 #endif
1047     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1048                              is_write, &uc->uc_sigmask, puc);
1049 }
1050
1051 #elif defined(__alpha__)
1052
1053 int cpu_signal_handler(int host_signum, struct siginfo *info, 
1054                            void *puc)
1055 {
1056     struct ucontext *uc = puc;
1057     uint32_t *pc = uc->uc_mcontext.sc_pc;
1058     uint32_t insn = *pc;
1059     int is_write = 0;
1060
1061     /* XXX: need kernel patch to get write flag faster */
1062     switch (insn >> 26) {
1063     case 0x0d: // stw
1064     case 0x0e: // stb
1065     case 0x0f: // stq_u
1066     case 0x24: // stf
1067     case 0x25: // stg
1068     case 0x26: // sts
1069     case 0x27: // stt
1070     case 0x2c: // stl
1071     case 0x2d: // stq
1072     case 0x2e: // stl_c
1073     case 0x2f: // stq_c
1074         is_write = 1;
1075     }
1076
1077     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1078                              is_write, &uc->uc_sigmask, puc);
1079 }
1080 #elif defined(__sparc__)
1081
1082 int cpu_signal_handler(int host_signum, struct siginfo *info, 
1083                        void *puc)
1084 {
1085     uint32_t *regs = (uint32_t *)(info + 1);
1086     void *sigmask = (regs + 20);
1087     unsigned long pc;
1088     int is_write;
1089     uint32_t insn;
1090     
1091     /* XXX: is there a standard glibc define ? */
1092     pc = regs[1];
1093     /* XXX: need kernel patch to get write flag faster */
1094     is_write = 0;
1095     insn = *(uint32_t *)pc;
1096     if ((insn >> 30) == 3) {
1097       switch((insn >> 19) & 0x3f) {
1098       case 0x05: // stb
1099       case 0x06: // sth
1100       case 0x04: // st
1101       case 0x07: // std
1102       case 0x24: // stf
1103       case 0x27: // stdf
1104       case 0x25: // stfsr
1105         is_write = 1;
1106         break;
1107       }
1108     }
1109     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1110                              is_write, sigmask, NULL);
1111 }
1112
1113 #elif defined(__arm__)
1114
1115 int cpu_signal_handler(int host_signum, struct siginfo *info, 
1116                        void *puc)
1117 {
1118     struct ucontext *uc = puc;
1119     unsigned long pc;
1120     int is_write;
1121     
1122     pc = uc->uc_mcontext.gregs[R15];
1123     /* XXX: compute is_write */
1124     is_write = 0;
1125     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1126                              is_write,
1127                              &uc->uc_sigmask);
1128 }
1129
1130 #elif defined(__mc68000)
1131
1132 int cpu_signal_handler(int host_signum, struct siginfo *info, 
1133                        void *puc)
1134 {
1135     struct ucontext *uc = puc;
1136     unsigned long pc;
1137     int is_write;
1138     
1139     pc = uc->uc_mcontext.gregs[16];
1140     /* XXX: compute is_write */
1141     is_write = 0;
1142     return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1143                              is_write,
1144                              &uc->uc_sigmask, puc);
1145 }
1146
1147 #elif defined(__ia64)
1148
1149 #ifndef __ISR_VALID
1150   /* This ought to be in <bits/siginfo.h>... */
1151 # define __ISR_VALID    1
1152 # define si_flags       _sifields._sigfault._si_pad0
1153 #endif
1154
1155 int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
1156 {
1157     struct ucontext *uc = puc;
1158     unsigned long ip;
1159     int is_write = 0;
1160
1161     ip = uc->uc_mcontext.sc_ip;
1162     switch (host_signum) {
1163       case SIGILL:
1164       case SIGFPE:
1165       case SIGSEGV:
1166       case SIGBUS:
1167       case SIGTRAP:
1168           if (info->si_code && (info->si_flags & __ISR_VALID))
1169               /* ISR.W (write-access) is bit 33:  */
1170               is_write = (info->si_isr >> 33) & 1;
1171           break;
1172
1173       default:
1174           break;
1175     }
1176     return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1177                              is_write,
1178                              &uc->uc_sigmask, puc);
1179 }
1180
1181 #else
1182
1183 #error host CPU specific signal handler needed
1184
1185 #endif
1186
1187 #endif /* !defined(CONFIG_SOFTMMU) */