Statistics
| Branch: | Revision:

root / cpu-exec.c @ 4ad5b06d

History | View | Annotate | Download (48.3 kB)

1 7d13299d bellard
/*
2 7d13299d bellard
 *  i386 emulator main execution loop
3 7d13299d bellard
 * 
4 66321a11 bellard
 *  Copyright (c) 2003-2005 Fabrice Bellard
5 7d13299d bellard
 *
6 3ef693a0 bellard
 * This library is free software; you can redistribute it and/or
7 3ef693a0 bellard
 * modify it under the terms of the GNU Lesser General Public
8 3ef693a0 bellard
 * License as published by the Free Software Foundation; either
9 3ef693a0 bellard
 * version 2 of the License, or (at your option) any later version.
10 7d13299d bellard
 *
11 3ef693a0 bellard
 * This library is distributed in the hope that it will be useful,
12 3ef693a0 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 3ef693a0 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 3ef693a0 bellard
 * Lesser General Public License for more details.
15 7d13299d bellard
 *
16 3ef693a0 bellard
 * You should have received a copy of the GNU Lesser General Public
17 3ef693a0 bellard
 * License along with this library; if not, write to the Free Software
18 3ef693a0 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 7d13299d bellard
 */
20 e4533c7a bellard
#include "config.h"
21 93ac68bc bellard
#include "exec.h"
22 956034d7 bellard
#include "disas.h"
23 7d13299d bellard
24 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
25 fbf9eeb3 bellard
#undef EAX
26 fbf9eeb3 bellard
#undef ECX
27 fbf9eeb3 bellard
#undef EDX
28 fbf9eeb3 bellard
#undef EBX
29 fbf9eeb3 bellard
#undef ESP
30 fbf9eeb3 bellard
#undef EBP
31 fbf9eeb3 bellard
#undef ESI
32 fbf9eeb3 bellard
#undef EDI
33 fbf9eeb3 bellard
#undef EIP
34 fbf9eeb3 bellard
#include <signal.h>
35 fbf9eeb3 bellard
#include <sys/ucontext.h>
36 fbf9eeb3 bellard
#endif
37 fbf9eeb3 bellard
38 36bdbe54 bellard
int tb_invalidated_flag;
39 36bdbe54 bellard
40 dc99065b bellard
//#define DEBUG_EXEC
41 9de5e440 bellard
//#define DEBUG_SIGNAL
42 7d13299d bellard
43 e6e5906b pbrook
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K)
44 e4533c7a bellard
/* XXX: unify with i386 target */
45 e4533c7a bellard
void cpu_loop_exit(void)
46 e4533c7a bellard
{
47 e4533c7a bellard
    longjmp(env->jmp_env, 1);
48 e4533c7a bellard
}
49 e4533c7a bellard
#endif
50 e6e5906b pbrook
#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
51 3475187d bellard
#define reg_T2
52 3475187d bellard
#endif
53 e4533c7a bellard
54 fbf9eeb3 bellard
/* exit the current TB from a signal handler. The host registers are
55 fbf9eeb3 bellard
   restored in a state compatible with the CPU emulator
56 fbf9eeb3 bellard
 */
57 fbf9eeb3 bellard
void cpu_resume_from_signal(CPUState *env1, void *puc) 
58 fbf9eeb3 bellard
{
59 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
60 fbf9eeb3 bellard
    struct ucontext *uc = puc;
61 fbf9eeb3 bellard
#endif
62 fbf9eeb3 bellard
63 fbf9eeb3 bellard
    env = env1;
64 fbf9eeb3 bellard
65 fbf9eeb3 bellard
    /* XXX: restore cpu registers saved in host registers */
66 fbf9eeb3 bellard
67 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
68 fbf9eeb3 bellard
    if (puc) {
69 fbf9eeb3 bellard
        /* XXX: use siglongjmp ? */
70 fbf9eeb3 bellard
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
71 fbf9eeb3 bellard
    }
72 fbf9eeb3 bellard
#endif
73 fbf9eeb3 bellard
    longjmp(env->jmp_env, 1);
74 fbf9eeb3 bellard
}
75 fbf9eeb3 bellard
76 8a40a180 bellard
77 8a40a180 bellard
static TranslationBlock *tb_find_slow(target_ulong pc,
78 8a40a180 bellard
                                      target_ulong cs_base,
79 8a40a180 bellard
                                      unsigned int flags)
80 8a40a180 bellard
{
81 8a40a180 bellard
    TranslationBlock *tb, **ptb1;
82 8a40a180 bellard
    int code_gen_size;
83 8a40a180 bellard
    unsigned int h;
84 8a40a180 bellard
    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
85 8a40a180 bellard
    uint8_t *tc_ptr;
86 8a40a180 bellard
    
87 8a40a180 bellard
    spin_lock(&tb_lock);
88 8a40a180 bellard
89 8a40a180 bellard
    tb_invalidated_flag = 0;
90 8a40a180 bellard
    
91 8a40a180 bellard
    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
92 8a40a180 bellard
    
93 8a40a180 bellard
    /* find translated block using physical mappings */
94 8a40a180 bellard
    phys_pc = get_phys_addr_code(env, pc);
95 8a40a180 bellard
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
96 8a40a180 bellard
    phys_page2 = -1;
97 8a40a180 bellard
    h = tb_phys_hash_func(phys_pc);
98 8a40a180 bellard
    ptb1 = &tb_phys_hash[h];
99 8a40a180 bellard
    for(;;) {
100 8a40a180 bellard
        tb = *ptb1;
101 8a40a180 bellard
        if (!tb)
102 8a40a180 bellard
            goto not_found;
103 8a40a180 bellard
        if (tb->pc == pc && 
104 8a40a180 bellard
            tb->page_addr[0] == phys_page1 &&
105 8a40a180 bellard
            tb->cs_base == cs_base && 
106 8a40a180 bellard
            tb->flags == flags) {
107 8a40a180 bellard
            /* check next page if needed */
108 8a40a180 bellard
            if (tb->page_addr[1] != -1) {
109 8a40a180 bellard
                virt_page2 = (pc & TARGET_PAGE_MASK) + 
110 8a40a180 bellard
                    TARGET_PAGE_SIZE;
111 8a40a180 bellard
                phys_page2 = get_phys_addr_code(env, virt_page2);
112 8a40a180 bellard
                if (tb->page_addr[1] == phys_page2)
113 8a40a180 bellard
                    goto found;
114 8a40a180 bellard
            } else {
115 8a40a180 bellard
                goto found;
116 8a40a180 bellard
            }
117 8a40a180 bellard
        }
118 8a40a180 bellard
        ptb1 = &tb->phys_hash_next;
119 8a40a180 bellard
    }
120 8a40a180 bellard
 not_found:
121 8a40a180 bellard
    /* if no translated code available, then translate it now */
122 8a40a180 bellard
    tb = tb_alloc(pc);
123 8a40a180 bellard
    if (!tb) {
124 8a40a180 bellard
        /* flush must be done */
125 8a40a180 bellard
        tb_flush(env);
126 8a40a180 bellard
        /* cannot fail at this point */
127 8a40a180 bellard
        tb = tb_alloc(pc);
128 8a40a180 bellard
        /* don't forget to invalidate previous TB info */
129 15388002 bellard
        tb_invalidated_flag = 1;
130 8a40a180 bellard
    }
131 8a40a180 bellard
    tc_ptr = code_gen_ptr;
132 8a40a180 bellard
    tb->tc_ptr = tc_ptr;
133 8a40a180 bellard
    tb->cs_base = cs_base;
134 8a40a180 bellard
    tb->flags = flags;
135 8a40a180 bellard
    cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
136 8a40a180 bellard
    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
137 8a40a180 bellard
    
138 8a40a180 bellard
    /* check next page if needed */
139 8a40a180 bellard
    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
140 8a40a180 bellard
    phys_page2 = -1;
141 8a40a180 bellard
    if ((pc & TARGET_PAGE_MASK) != virt_page2) {
142 8a40a180 bellard
        phys_page2 = get_phys_addr_code(env, virt_page2);
143 8a40a180 bellard
    }
144 8a40a180 bellard
    tb_link_phys(tb, phys_pc, phys_page2);
145 8a40a180 bellard
    
146 8a40a180 bellard
 found:
147 8a40a180 bellard
    /* we add the TB in the virtual pc hash table */
148 8a40a180 bellard
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
149 8a40a180 bellard
    spin_unlock(&tb_lock);
150 8a40a180 bellard
    return tb;
151 8a40a180 bellard
}
152 8a40a180 bellard
153 8a40a180 bellard
static inline TranslationBlock *tb_find_fast(void)
154 8a40a180 bellard
{
155 8a40a180 bellard
    TranslationBlock *tb;
156 8a40a180 bellard
    target_ulong cs_base, pc;
157 8a40a180 bellard
    unsigned int flags;
158 8a40a180 bellard
159 8a40a180 bellard
    /* we record a subset of the CPU state. It will
160 8a40a180 bellard
       always be the same before a given translated block
161 8a40a180 bellard
       is executed. */
162 8a40a180 bellard
#if defined(TARGET_I386)
163 8a40a180 bellard
    flags = env->hflags;
164 8a40a180 bellard
    flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
165 8a40a180 bellard
    cs_base = env->segs[R_CS].base;
166 8a40a180 bellard
    pc = cs_base + env->eip;
167 8a40a180 bellard
#elif defined(TARGET_ARM)
168 8a40a180 bellard
    flags = env->thumb | (env->vfp.vec_len << 1)
169 b5ff1b31 bellard
            | (env->vfp.vec_stride << 4);
170 b5ff1b31 bellard
    if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
171 b5ff1b31 bellard
        flags |= (1 << 6);
172 40f137e1 pbrook
    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
173 40f137e1 pbrook
        flags |= (1 << 7);
174 8a40a180 bellard
    cs_base = 0;
175 8a40a180 bellard
    pc = env->regs[15];
176 8a40a180 bellard
#elif defined(TARGET_SPARC)
177 8a40a180 bellard
#ifdef TARGET_SPARC64
178 a80dde08 bellard
    // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
179 a80dde08 bellard
    flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
180 a80dde08 bellard
        | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
181 8a40a180 bellard
#else
182 a80dde08 bellard
    // FPU enable . MMU enabled . MMU no-fault . Supervisor
183 a80dde08 bellard
    flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
184 a80dde08 bellard
        | env->psrs;
185 8a40a180 bellard
#endif
186 8a40a180 bellard
    cs_base = env->npc;
187 8a40a180 bellard
    pc = env->pc;
188 8a40a180 bellard
#elif defined(TARGET_PPC)
189 8a40a180 bellard
    flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) |
190 8a40a180 bellard
        (msr_se << MSR_SE) | (msr_le << MSR_LE);
191 8a40a180 bellard
    cs_base = 0;
192 8a40a180 bellard
    pc = env->nip;
193 8a40a180 bellard
#elif defined(TARGET_MIPS)
194 56b19403 pbrook
    flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
195 cc9442b9 bellard
    cs_base = 0;
196 8a40a180 bellard
    pc = env->PC;
197 e6e5906b pbrook
#elif defined(TARGET_M68K)
198 e6e5906b pbrook
    flags = env->fpcr & M68K_FPCR_PREC;
199 e6e5906b pbrook
    cs_base = 0;
200 e6e5906b pbrook
    pc = env->pc;
201 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
202 fdf9b3e8 bellard
    flags = env->sr & (SR_MD | SR_RB);
203 fdf9b3e8 bellard
    cs_base = 0;         /* XXXXX */
204 fdf9b3e8 bellard
    pc = env->pc;
205 8a40a180 bellard
#else
206 8a40a180 bellard
#error unsupported CPU
207 8a40a180 bellard
#endif
208 8a40a180 bellard
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
209 8a40a180 bellard
    if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||
210 8a40a180 bellard
                         tb->flags != flags, 0)) {
211 8a40a180 bellard
        tb = tb_find_slow(pc, cs_base, flags);
212 15388002 bellard
        /* Note: we do it here to avoid a gcc bug on Mac OS X when
213 15388002 bellard
           doing it in tb_find_slow */
214 15388002 bellard
        if (tb_invalidated_flag) {
215 15388002 bellard
            /* as some TB could have been invalidated because
216 15388002 bellard
               of memory exceptions while generating the code, we
217 15388002 bellard
               must recompute the hash index here */
218 15388002 bellard
            T0 = 0;
219 15388002 bellard
        }
220 8a40a180 bellard
    }
221 8a40a180 bellard
    return tb;
222 8a40a180 bellard
}
223 8a40a180 bellard
224 8a40a180 bellard
225 7d13299d bellard
/* main execution loop */
226 7d13299d bellard
227 e4533c7a bellard
int cpu_exec(CPUState *env1)
228 7d13299d bellard
{
229 1057eaa7 pbrook
#define DECLARE_HOST_REGS 1
230 1057eaa7 pbrook
#include "hostregs_helper.h"
231 1057eaa7 pbrook
#if defined(TARGET_SPARC)
232 3475187d bellard
#if defined(reg_REGWPTR)
233 3475187d bellard
    uint32_t *saved_regwptr;
234 3475187d bellard
#endif
235 3475187d bellard
#endif
236 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
237 b49d07ba ths
    int saved_i7;
238 b49d07ba ths
    target_ulong tmp_T0;
239 8c6939c0 bellard
#endif
240 8a40a180 bellard
    int ret, interrupt_request;
241 7d13299d bellard
    void (*gen_func)(void);
242 8a40a180 bellard
    TranslationBlock *tb;
243 c27004ec bellard
    uint8_t *tc_ptr;
244 8c6939c0 bellard
245 5a1e3cfc bellard
#if defined(TARGET_I386)
246 5a1e3cfc bellard
    /* handle exit of HALTED state */
247 5a1e3cfc bellard
    if (env1->hflags & HF_HALTED_MASK) {
248 5a1e3cfc bellard
        /* disable halt condition */
249 5a1e3cfc bellard
        if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
250 5a1e3cfc bellard
            (env1->eflags & IF_MASK)) {
251 5a1e3cfc bellard
            env1->hflags &= ~HF_HALTED_MASK;
252 5a1e3cfc bellard
        } else {
253 5a1e3cfc bellard
            return EXCP_HALTED;
254 e80e1cc4 bellard
        }
255 e80e1cc4 bellard
    }
256 e80e1cc4 bellard
#elif defined(TARGET_PPC)
257 50443c98 bellard
    if (env1->halted) {
258 e80e1cc4 bellard
        if (env1->msr[MSR_EE] && 
259 e80e1cc4 bellard
            (env1->interrupt_request & 
260 e80e1cc4 bellard
             (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) {
261 50443c98 bellard
            env1->halted = 0;
262 e80e1cc4 bellard
        } else {
263 e80e1cc4 bellard
            return EXCP_HALTED;
264 5a1e3cfc bellard
        }
265 5a1e3cfc bellard
    }
266 ba3c64fb bellard
#elif defined(TARGET_SPARC)
267 ba3c64fb bellard
    if (env1->halted) {
268 ba3c64fb bellard
        if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
269 ba3c64fb bellard
            (env1->psret != 0)) {
270 ba3c64fb bellard
            env1->halted = 0;
271 ba3c64fb bellard
        } else {
272 ba3c64fb bellard
            return EXCP_HALTED;
273 ba3c64fb bellard
        }
274 ba3c64fb bellard
    }
275 9332f9da bellard
#elif defined(TARGET_ARM)
276 9332f9da bellard
    if (env1->halted) {
277 9332f9da bellard
        /* An interrupt wakes the CPU even if the I and F CPSR bits are
278 9332f9da bellard
           set.  */
279 9332f9da bellard
        if (env1->interrupt_request
280 9332f9da bellard
            & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) {
281 9332f9da bellard
            env1->halted = 0;
282 9332f9da bellard
        } else {
283 9332f9da bellard
            return EXCP_HALTED;
284 9332f9da bellard
        }
285 9332f9da bellard
    }
286 6810e154 bellard
#elif defined(TARGET_MIPS)
287 6810e154 bellard
    if (env1->halted) {
288 6810e154 bellard
        if (env1->interrupt_request &
289 6810e154 bellard
            (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) {
290 6810e154 bellard
            env1->halted = 0;
291 6810e154 bellard
        } else {
292 6810e154 bellard
            return EXCP_HALTED;
293 6810e154 bellard
        }
294 6810e154 bellard
    }
295 5a1e3cfc bellard
#endif
296 5a1e3cfc bellard
297 6a00d601 bellard
    cpu_single_env = env1; 
298 6a00d601 bellard
299 7d13299d bellard
    /* first we save global registers */
300 1057eaa7 pbrook
#define SAVE_HOST_REGS 1
301 1057eaa7 pbrook
#include "hostregs_helper.h"
302 c27004ec bellard
    env = env1;
303 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
304 e4533c7a bellard
    /* we also save i7 because longjmp may not restore it */
305 e4533c7a bellard
    asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
306 e4533c7a bellard
#endif
307 e4533c7a bellard
308 e4533c7a bellard
#if defined(TARGET_I386)
309 0d1a29f9 bellard
    env_to_regs();
310 9de5e440 bellard
    /* put eflags in CPU temporary format */
311 fc2b4c48 bellard
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
312 fc2b4c48 bellard
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
313 9de5e440 bellard
    CC_OP = CC_OP_EFLAGS;
314 fc2b4c48 bellard
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
315 e4533c7a bellard
#elif defined(TARGET_ARM)
316 93ac68bc bellard
#elif defined(TARGET_SPARC)
317 3475187d bellard
#if defined(reg_REGWPTR)
318 3475187d bellard
    saved_regwptr = REGWPTR;
319 3475187d bellard
#endif
320 67867308 bellard
#elif defined(TARGET_PPC)
321 e6e5906b pbrook
#elif defined(TARGET_M68K)
322 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
323 e6e5906b pbrook
    env->cc_dest = env->sr & 0xf;
324 e6e5906b pbrook
    env->cc_x = (env->sr >> 4) & 1;
325 6af0bf9c bellard
#elif defined(TARGET_MIPS)
326 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
327 fdf9b3e8 bellard
    /* XXXXX */
328 e4533c7a bellard
#else
329 e4533c7a bellard
#error unsupported target CPU
330 e4533c7a bellard
#endif
331 3fb2ded1 bellard
    env->exception_index = -1;
332 9d27abd9 bellard
333 7d13299d bellard
    /* prepare setjmp context for exception handling */
334 3fb2ded1 bellard
    for(;;) {
335 3fb2ded1 bellard
        if (setjmp(env->jmp_env) == 0) {
336 ee8b7021 bellard
            env->current_tb = NULL;
337 3fb2ded1 bellard
            /* if an exception is pending, we execute it here */
338 3fb2ded1 bellard
            if (env->exception_index >= 0) {
339 3fb2ded1 bellard
                if (env->exception_index >= EXCP_INTERRUPT) {
340 3fb2ded1 bellard
                    /* exit request from the cpu execution loop */
341 3fb2ded1 bellard
                    ret = env->exception_index;
342 3fb2ded1 bellard
                    break;
343 3fb2ded1 bellard
                } else if (env->user_mode_only) {
344 3fb2ded1 bellard
                    /* if user mode only, we simulate a fake exception
345 9f083493 ths
                       which will be handled outside the cpu execution
346 3fb2ded1 bellard
                       loop */
347 83479e77 bellard
#if defined(TARGET_I386)
348 3fb2ded1 bellard
                    do_interrupt_user(env->exception_index, 
349 3fb2ded1 bellard
                                      env->exception_is_int, 
350 3fb2ded1 bellard
                                      env->error_code, 
351 3fb2ded1 bellard
                                      env->exception_next_eip);
352 83479e77 bellard
#endif
353 3fb2ded1 bellard
                    ret = env->exception_index;
354 3fb2ded1 bellard
                    break;
355 3fb2ded1 bellard
                } else {
356 83479e77 bellard
#if defined(TARGET_I386)
357 3fb2ded1 bellard
                    /* simulate a real cpu exception. On i386, it can
358 3fb2ded1 bellard
                       trigger new exceptions, but we do not handle
359 3fb2ded1 bellard
                       double or triple faults yet. */
360 3fb2ded1 bellard
                    do_interrupt(env->exception_index, 
361 3fb2ded1 bellard
                                 env->exception_is_int, 
362 3fb2ded1 bellard
                                 env->error_code, 
363 d05e66d2 bellard
                                 env->exception_next_eip, 0);
364 ce09776b bellard
#elif defined(TARGET_PPC)
365 ce09776b bellard
                    do_interrupt(env);
366 6af0bf9c bellard
#elif defined(TARGET_MIPS)
367 6af0bf9c bellard
                    do_interrupt(env);
368 e95c8d51 bellard
#elif defined(TARGET_SPARC)
369 1a0c3292 bellard
                    do_interrupt(env->exception_index);
370 b5ff1b31 bellard
#elif defined(TARGET_ARM)
371 b5ff1b31 bellard
                    do_interrupt(env);
372 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
373 fdf9b3e8 bellard
                    do_interrupt(env);
374 83479e77 bellard
#endif
375 3fb2ded1 bellard
                }
376 3fb2ded1 bellard
                env->exception_index = -1;
377 9df217a3 bellard
            } 
378 9df217a3 bellard
#ifdef USE_KQEMU
379 9df217a3 bellard
            if (kqemu_is_ok(env) && env->interrupt_request == 0) {
380 9df217a3 bellard
                int ret;
381 9df217a3 bellard
                env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
382 9df217a3 bellard
                ret = kqemu_cpu_exec(env);
383 9df217a3 bellard
                /* put eflags in CPU temporary format */
384 9df217a3 bellard
                CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
385 9df217a3 bellard
                DF = 1 - (2 * ((env->eflags >> 10) & 1));
386 9df217a3 bellard
                CC_OP = CC_OP_EFLAGS;
387 9df217a3 bellard
                env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
388 9df217a3 bellard
                if (ret == 1) {
389 9df217a3 bellard
                    /* exception */
390 9df217a3 bellard
                    longjmp(env->jmp_env, 1);
391 9df217a3 bellard
                } else if (ret == 2) {
392 9df217a3 bellard
                    /* softmmu execution needed */
393 9df217a3 bellard
                } else {
394 9df217a3 bellard
                    if (env->interrupt_request != 0) {
395 9df217a3 bellard
                        /* hardware interrupt will be executed just after */
396 9df217a3 bellard
                    } else {
397 9df217a3 bellard
                        /* otherwise, we restart */
398 9df217a3 bellard
                        longjmp(env->jmp_env, 1);
399 9df217a3 bellard
                    }
400 9df217a3 bellard
                }
401 3fb2ded1 bellard
            }
402 9df217a3 bellard
#endif
403 9df217a3 bellard
404 3fb2ded1 bellard
            T0 = 0; /* force lookup of first TB */
405 3fb2ded1 bellard
            for(;;) {
406 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
407 3fb2ded1 bellard
                /* g1 can be modified by some libc? functions */ 
408 3fb2ded1 bellard
                tmp_T0 = T0;
409 8c6939c0 bellard
#endif            
410 68a79315 bellard
                interrupt_request = env->interrupt_request;
411 2e255c6b bellard
                if (__builtin_expect(interrupt_request, 0)) {
412 68a79315 bellard
#if defined(TARGET_I386)
413 3b21e03e bellard
                    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
414 3b21e03e bellard
                        !(env->hflags & HF_SMM_MASK)) {
415 3b21e03e bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_SMI;
416 3b21e03e bellard
                        do_smm_enter();
417 3b21e03e bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
418 3b21e03e bellard
                        tmp_T0 = 0;
419 3b21e03e bellard
#else
420 3b21e03e bellard
                        T0 = 0;
421 3b21e03e bellard
#endif
422 3b21e03e bellard
                    } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
423 3f337316 bellard
                        (env->eflags & IF_MASK) && 
424 3f337316 bellard
                        !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
425 68a79315 bellard
                        int intno;
426 fbf9eeb3 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
427 a541f297 bellard
                        intno = cpu_get_pic_interrupt(env);
428 f193c797 bellard
                        if (loglevel & CPU_LOG_TB_IN_ASM) {
429 68a79315 bellard
                            fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
430 68a79315 bellard
                        }
431 d05e66d2 bellard
                        do_interrupt(intno, 0, 0, 0, 1);
432 907a5b26 bellard
                        /* ensure that no TB jump will be modified as
433 907a5b26 bellard
                           the program flow was changed */
434 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
435 907a5b26 bellard
                        tmp_T0 = 0;
436 907a5b26 bellard
#else
437 907a5b26 bellard
                        T0 = 0;
438 907a5b26 bellard
#endif
439 68a79315 bellard
                    }
440 ce09776b bellard
#elif defined(TARGET_PPC)
441 9fddaa0c bellard
#if 0
442 9fddaa0c bellard
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
443 9fddaa0c bellard
                        cpu_ppc_reset(env);
444 9fddaa0c bellard
                    }
445 9fddaa0c bellard
#endif
446 9fddaa0c bellard
                    if (msr_ee != 0) {
447 8a40a180 bellard
                        if ((interrupt_request & CPU_INTERRUPT_HARD)) {
448 9fddaa0c bellard
                            /* Raise it */
449 9fddaa0c bellard
                            env->exception_index = EXCP_EXTERNAL;
450 9fddaa0c bellard
                            env->error_code = 0;
451 ce09776b bellard
                            do_interrupt(env);
452 8a40a180 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
453 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
454 8a40a180 bellard
                            tmp_T0 = 0;
455 8a40a180 bellard
#else
456 8a40a180 bellard
                            T0 = 0;
457 8a40a180 bellard
#endif
458 8a40a180 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
459 8a40a180 bellard
                            /* Raise it */
460 8a40a180 bellard
                            env->exception_index = EXCP_DECR;
461 8a40a180 bellard
                            env->error_code = 0;
462 8a40a180 bellard
                            do_interrupt(env);
463 9fddaa0c bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
464 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
465 8a40a180 bellard
                            tmp_T0 = 0;
466 8a40a180 bellard
#else
467 8a40a180 bellard
                            T0 = 0;
468 8a40a180 bellard
#endif
469 8a40a180 bellard
                        }
470 ce09776b bellard
                    }
471 6af0bf9c bellard
#elif defined(TARGET_MIPS)
472 6af0bf9c bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
473 6af0bf9c bellard
                        (env->CP0_Status & (1 << CP0St_IE)) &&
474 7ebab699 bellard
                        (env->CP0_Status & env->CP0_Cause & 0x0000FF00) &&
475 6af0bf9c bellard
                        !(env->hflags & MIPS_HFLAG_EXL) &&
476 6af0bf9c bellard
                        !(env->hflags & MIPS_HFLAG_ERL) &&
477 6af0bf9c bellard
                        !(env->hflags & MIPS_HFLAG_DM)) {
478 6af0bf9c bellard
                        /* Raise it */
479 6af0bf9c bellard
                        env->exception_index = EXCP_EXT_INTERRUPT;
480 6af0bf9c bellard
                        env->error_code = 0;
481 6af0bf9c bellard
                        do_interrupt(env);
482 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
483 8a40a180 bellard
                        tmp_T0 = 0;
484 8a40a180 bellard
#else
485 8a40a180 bellard
                        T0 = 0;
486 8a40a180 bellard
#endif
487 6af0bf9c bellard
                    }
488 e95c8d51 bellard
#elif defined(TARGET_SPARC)
489 66321a11 bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
490 66321a11 bellard
                        (env->psret != 0)) {
491 66321a11 bellard
                        int pil = env->interrupt_index & 15;
492 66321a11 bellard
                        int type = env->interrupt_index & 0xf0;
493 66321a11 bellard
494 66321a11 bellard
                        if (((type == TT_EXTINT) &&
495 66321a11 bellard
                             (pil == 15 || pil > env->psrpil)) ||
496 66321a11 bellard
                            type != TT_EXTINT) {
497 66321a11 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
498 66321a11 bellard
                            do_interrupt(env->interrupt_index);
499 66321a11 bellard
                            env->interrupt_index = 0;
500 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
501 8a40a180 bellard
                            tmp_T0 = 0;
502 8a40a180 bellard
#else
503 8a40a180 bellard
                            T0 = 0;
504 8a40a180 bellard
#endif
505 66321a11 bellard
                        }
506 e95c8d51 bellard
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
507 e95c8d51 bellard
                        //do_interrupt(0, 0, 0, 0, 0);
508 e95c8d51 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
509 ba3c64fb bellard
                    } else if (interrupt_request & CPU_INTERRUPT_HALT) {
510 df52b000 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
511 df52b000 bellard
                        env->halted = 1;
512 df52b000 bellard
                        env->exception_index = EXCP_HLT;
513 df52b000 bellard
                        cpu_loop_exit();
514 ba3c64fb bellard
                    }
515 b5ff1b31 bellard
#elif defined(TARGET_ARM)
516 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_FIQ
517 b5ff1b31 bellard
                        && !(env->uncached_cpsr & CPSR_F)) {
518 b5ff1b31 bellard
                        env->exception_index = EXCP_FIQ;
519 b5ff1b31 bellard
                        do_interrupt(env);
520 b5ff1b31 bellard
                    }
521 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_HARD
522 b5ff1b31 bellard
                        && !(env->uncached_cpsr & CPSR_I)) {
523 b5ff1b31 bellard
                        env->exception_index = EXCP_IRQ;
524 b5ff1b31 bellard
                        do_interrupt(env);
525 b5ff1b31 bellard
                    }
526 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
527 fdf9b3e8 bellard
                    /* XXXXX */
528 68a79315 bellard
#endif
529 9d05095e bellard
                   /* Don't use the cached interupt_request value,
530 9d05095e bellard
                      do_interrupt may have updated the EXITTB flag. */
531 b5ff1b31 bellard
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
532 bf3e8bf1 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
533 bf3e8bf1 bellard
                        /* ensure that no TB jump will be modified as
534 bf3e8bf1 bellard
                           the program flow was changed */
535 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
536 bf3e8bf1 bellard
                        tmp_T0 = 0;
537 bf3e8bf1 bellard
#else
538 bf3e8bf1 bellard
                        T0 = 0;
539 bf3e8bf1 bellard
#endif
540 bf3e8bf1 bellard
                    }
541 68a79315 bellard
                    if (interrupt_request & CPU_INTERRUPT_EXIT) {
542 68a79315 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
543 68a79315 bellard
                        env->exception_index = EXCP_INTERRUPT;
544 68a79315 bellard
                        cpu_loop_exit();
545 68a79315 bellard
                    }
546 3fb2ded1 bellard
                }
547 7d13299d bellard
#ifdef DEBUG_EXEC
548 b5ff1b31 bellard
                if ((loglevel & CPU_LOG_TB_CPU)) {
549 e4533c7a bellard
#if defined(TARGET_I386)
550 3fb2ded1 bellard
                    /* restore flags in standard format */
551 fc9f715d bellard
#ifdef reg_EAX
552 3fb2ded1 bellard
                    env->regs[R_EAX] = EAX;
553 fc9f715d bellard
#endif
554 fc9f715d bellard
#ifdef reg_EBX
555 3fb2ded1 bellard
                    env->regs[R_EBX] = EBX;
556 fc9f715d bellard
#endif
557 fc9f715d bellard
#ifdef reg_ECX
558 3fb2ded1 bellard
                    env->regs[R_ECX] = ECX;
559 fc9f715d bellard
#endif
560 fc9f715d bellard
#ifdef reg_EDX
561 3fb2ded1 bellard
                    env->regs[R_EDX] = EDX;
562 fc9f715d bellard
#endif
563 fc9f715d bellard
#ifdef reg_ESI
564 3fb2ded1 bellard
                    env->regs[R_ESI] = ESI;
565 fc9f715d bellard
#endif
566 fc9f715d bellard
#ifdef reg_EDI
567 3fb2ded1 bellard
                    env->regs[R_EDI] = EDI;
568 fc9f715d bellard
#endif
569 fc9f715d bellard
#ifdef reg_EBP
570 3fb2ded1 bellard
                    env->regs[R_EBP] = EBP;
571 fc9f715d bellard
#endif
572 fc9f715d bellard
#ifdef reg_ESP
573 3fb2ded1 bellard
                    env->regs[R_ESP] = ESP;
574 fc9f715d bellard
#endif
575 3fb2ded1 bellard
                    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
576 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
577 3fb2ded1 bellard
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
578 e4533c7a bellard
#elif defined(TARGET_ARM)
579 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
580 93ac68bc bellard
#elif defined(TARGET_SPARC)
581 3475187d bellard
                    REGWPTR = env->regbase + (env->cwp * 16);
582 3475187d bellard
                    env->regwptr = REGWPTR;
583 3475187d bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
584 67867308 bellard
#elif defined(TARGET_PPC)
585 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
586 e6e5906b pbrook
#elif defined(TARGET_M68K)
587 e6e5906b pbrook
                    cpu_m68k_flush_flags(env, env->cc_op);
588 e6e5906b pbrook
                    env->cc_op = CC_OP_FLAGS;
589 e6e5906b pbrook
                    env->sr = (env->sr & 0xffe0)
590 e6e5906b pbrook
                              | env->cc_dest | (env->cc_x << 4);
591 e6e5906b pbrook
                    cpu_dump_state(env, logfile, fprintf, 0);
592 6af0bf9c bellard
#elif defined(TARGET_MIPS)
593 6af0bf9c bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
594 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
595 fdf9b3e8 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
596 e4533c7a bellard
#else
597 e4533c7a bellard
#error unsupported target CPU 
598 e4533c7a bellard
#endif
599 3fb2ded1 bellard
                }
600 7d13299d bellard
#endif
601 8a40a180 bellard
                tb = tb_find_fast();
602 9d27abd9 bellard
#ifdef DEBUG_EXEC
603 c1135f61 bellard
                if ((loglevel & CPU_LOG_EXEC)) {
604 c27004ec bellard
                    fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
605 c27004ec bellard
                            (long)tb->tc_ptr, tb->pc,
606 c27004ec bellard
                            lookup_symbol(tb->pc));
607 3fb2ded1 bellard
                }
608 9d27abd9 bellard
#endif
609 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
610 3fb2ded1 bellard
                T0 = tmp_T0;
611 8c6939c0 bellard
#endif            
612 8a40a180 bellard
                /* see if we can patch the calling TB. When the TB
613 8a40a180 bellard
                   spans two pages, we cannot safely do a direct
614 8a40a180 bellard
                   jump. */
615 c27004ec bellard
                {
616 8a40a180 bellard
                    if (T0 != 0 &&
617 f32fc648 bellard
#if USE_KQEMU
618 f32fc648 bellard
                        (env->kqemu_enabled != 2) &&
619 f32fc648 bellard
#endif
620 8a40a180 bellard
                        tb->page_addr[1] == -1
621 bf3e8bf1 bellard
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
622 bf3e8bf1 bellard
                    && (tb->cflags & CF_CODE_COPY) == 
623 bf3e8bf1 bellard
                    (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
624 bf3e8bf1 bellard
#endif
625 bf3e8bf1 bellard
                    ) {
626 3fb2ded1 bellard
                    spin_lock(&tb_lock);
627 c27004ec bellard
                    tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
628 97eb5b14 bellard
#if defined(USE_CODE_COPY)
629 97eb5b14 bellard
                    /* propagates the FP use info */
630 97eb5b14 bellard
                    ((TranslationBlock *)(T0 & ~3))->cflags |= 
631 97eb5b14 bellard
                        (tb->cflags & CF_FP_USED);
632 97eb5b14 bellard
#endif
633 3fb2ded1 bellard
                    spin_unlock(&tb_lock);
634 3fb2ded1 bellard
                }
635 c27004ec bellard
                }
636 3fb2ded1 bellard
                tc_ptr = tb->tc_ptr;
637 83479e77 bellard
                env->current_tb = tb;
638 3fb2ded1 bellard
                /* execute the generated code */
639 3fb2ded1 bellard
                gen_func = (void *)tc_ptr;
640 8c6939c0 bellard
#if defined(__sparc__)
641 3fb2ded1 bellard
                __asm__ __volatile__("call        %0\n\t"
642 3fb2ded1 bellard
                                     "mov        %%o7,%%i0"
643 3fb2ded1 bellard
                                     : /* no outputs */
644 3fb2ded1 bellard
                                     : "r" (gen_func) 
645 fdbb4691 bellard
                                     : "i0", "i1", "i2", "i3", "i4", "i5",
646 fdbb4691 bellard
                                       "l0", "l1", "l2", "l3", "l4", "l5",
647 fdbb4691 bellard
                                       "l6", "l7");
648 8c6939c0 bellard
#elif defined(__arm__)
649 3fb2ded1 bellard
                asm volatile ("mov pc, %0\n\t"
650 3fb2ded1 bellard
                              ".global exec_loop\n\t"
651 3fb2ded1 bellard
                              "exec_loop:\n\t"
652 3fb2ded1 bellard
                              : /* no outputs */
653 3fb2ded1 bellard
                              : "r" (gen_func)
654 3fb2ded1 bellard
                              : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
655 bf3e8bf1 bellard
#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
656 bf3e8bf1 bellard
{
657 bf3e8bf1 bellard
    if (!(tb->cflags & CF_CODE_COPY)) {
658 97eb5b14 bellard
        if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
659 97eb5b14 bellard
            save_native_fp_state(env);
660 97eb5b14 bellard
        }
661 bf3e8bf1 bellard
        gen_func();
662 bf3e8bf1 bellard
    } else {
663 97eb5b14 bellard
        if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
664 97eb5b14 bellard
            restore_native_fp_state(env);
665 97eb5b14 bellard
        }
666 bf3e8bf1 bellard
        /* we work with native eflags */
667 bf3e8bf1 bellard
        CC_SRC = cc_table[CC_OP].compute_all();
668 bf3e8bf1 bellard
        CC_OP = CC_OP_EFLAGS;
669 bf3e8bf1 bellard
        asm(".globl exec_loop\n"
670 bf3e8bf1 bellard
            "\n"
671 bf3e8bf1 bellard
            "debug1:\n"
672 bf3e8bf1 bellard
            "    pushl %%ebp\n"
673 bf3e8bf1 bellard
            "    fs movl %10, %9\n"
674 bf3e8bf1 bellard
            "    fs movl %11, %%eax\n"
675 bf3e8bf1 bellard
            "    andl $0x400, %%eax\n"
676 bf3e8bf1 bellard
            "    fs orl %8, %%eax\n"
677 bf3e8bf1 bellard
            "    pushl %%eax\n"
678 bf3e8bf1 bellard
            "    popf\n"
679 bf3e8bf1 bellard
            "    fs movl %%esp, %12\n"
680 bf3e8bf1 bellard
            "    fs movl %0, %%eax\n"
681 bf3e8bf1 bellard
            "    fs movl %1, %%ecx\n"
682 bf3e8bf1 bellard
            "    fs movl %2, %%edx\n"
683 bf3e8bf1 bellard
            "    fs movl %3, %%ebx\n"
684 bf3e8bf1 bellard
            "    fs movl %4, %%esp\n"
685 bf3e8bf1 bellard
            "    fs movl %5, %%ebp\n"
686 bf3e8bf1 bellard
            "    fs movl %6, %%esi\n"
687 bf3e8bf1 bellard
            "    fs movl %7, %%edi\n"
688 bf3e8bf1 bellard
            "    fs jmp *%9\n"
689 bf3e8bf1 bellard
            "exec_loop:\n"
690 bf3e8bf1 bellard
            "    fs movl %%esp, %4\n"
691 bf3e8bf1 bellard
            "    fs movl %12, %%esp\n"
692 bf3e8bf1 bellard
            "    fs movl %%eax, %0\n"
693 bf3e8bf1 bellard
            "    fs movl %%ecx, %1\n"
694 bf3e8bf1 bellard
            "    fs movl %%edx, %2\n"
695 bf3e8bf1 bellard
            "    fs movl %%ebx, %3\n"
696 bf3e8bf1 bellard
            "    fs movl %%ebp, %5\n"
697 bf3e8bf1 bellard
            "    fs movl %%esi, %6\n"
698 bf3e8bf1 bellard
            "    fs movl %%edi, %7\n"
699 bf3e8bf1 bellard
            "    pushf\n"
700 bf3e8bf1 bellard
            "    popl %%eax\n"
701 bf3e8bf1 bellard
            "    movl %%eax, %%ecx\n"
702 bf3e8bf1 bellard
            "    andl $0x400, %%ecx\n"
703 bf3e8bf1 bellard
            "    shrl $9, %%ecx\n"
704 bf3e8bf1 bellard
            "    andl $0x8d5, %%eax\n"
705 bf3e8bf1 bellard
            "    fs movl %%eax, %8\n"
706 bf3e8bf1 bellard
            "    movl $1, %%eax\n"
707 bf3e8bf1 bellard
            "    subl %%ecx, %%eax\n"
708 bf3e8bf1 bellard
            "    fs movl %%eax, %11\n"
709 bf3e8bf1 bellard
            "    fs movl %9, %%ebx\n" /* get T0 value */
710 bf3e8bf1 bellard
            "    popl %%ebp\n"
711 bf3e8bf1 bellard
            :
712 bf3e8bf1 bellard
            : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
713 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[1])),
714 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[2])),
715 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[3])),
716 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[4])),
717 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
718 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[6])),
719 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[7])),
720 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, cc_src)),
721 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, tmp0)),
722 bf3e8bf1 bellard
            "a" (gen_func),
723 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, df)),
724 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, saved_esp))
725 bf3e8bf1 bellard
            : "%ecx", "%edx"
726 bf3e8bf1 bellard
            );
727 bf3e8bf1 bellard
    }
728 bf3e8bf1 bellard
}
729 b8076a74 bellard
#elif defined(__ia64)
730 b8076a74 bellard
                struct fptr {
731 b8076a74 bellard
                        void *ip;
732 b8076a74 bellard
                        void *gp;
733 b8076a74 bellard
                } fp;
734 b8076a74 bellard
735 b8076a74 bellard
                fp.ip = tc_ptr;
736 b8076a74 bellard
                fp.gp = code_gen_buffer + 2 * (1 << 20);
737 b8076a74 bellard
                (*(void (*)(void)) &fp)();
738 ae228531 bellard
#else
739 3fb2ded1 bellard
                gen_func();
740 ae228531 bellard
#endif
741 83479e77 bellard
                env->current_tb = NULL;
742 4cbf74b6 bellard
                /* reset soft MMU for next block (it can currently
743 4cbf74b6 bellard
                   only be set by a memory fault) */
744 4cbf74b6 bellard
#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
745 3f337316 bellard
                if (env->hflags & HF_SOFTMMU_MASK) {
746 3f337316 bellard
                    env->hflags &= ~HF_SOFTMMU_MASK;
747 4cbf74b6 bellard
                    /* do not allow linking to another block */
748 4cbf74b6 bellard
                    T0 = 0;
749 4cbf74b6 bellard
                }
750 4cbf74b6 bellard
#endif
751 f32fc648 bellard
#if defined(USE_KQEMU)
752 f32fc648 bellard
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
753 f32fc648 bellard
                if (kqemu_is_ok(env) &&
754 f32fc648 bellard
                    (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
755 f32fc648 bellard
                    cpu_loop_exit();
756 f32fc648 bellard
                }
757 f32fc648 bellard
#endif
758 3fb2ded1 bellard
            }
759 3fb2ded1 bellard
        } else {
760 0d1a29f9 bellard
            env_to_regs();
761 7d13299d bellard
        }
762 3fb2ded1 bellard
    } /* for(;;) */
763 3fb2ded1 bellard
764 7d13299d bellard
765 e4533c7a bellard
#if defined(TARGET_I386)
766 97eb5b14 bellard
#if defined(USE_CODE_COPY)
767 97eb5b14 bellard
    if (env->native_fp_regs) {
768 97eb5b14 bellard
        save_native_fp_state(env);
769 97eb5b14 bellard
    }
770 97eb5b14 bellard
#endif
771 9de5e440 bellard
    /* restore flags in standard format */
772 fc2b4c48 bellard
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
773 e4533c7a bellard
#elif defined(TARGET_ARM)
774 b7bcbe95 bellard
    /* XXX: Save/restore host fpu exception state?.  */
775 93ac68bc bellard
#elif defined(TARGET_SPARC)
776 3475187d bellard
#if defined(reg_REGWPTR)
777 3475187d bellard
    REGWPTR = saved_regwptr;
778 3475187d bellard
#endif
779 67867308 bellard
#elif defined(TARGET_PPC)
780 e6e5906b pbrook
#elif defined(TARGET_M68K)
781 e6e5906b pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
782 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
783 e6e5906b pbrook
    env->sr = (env->sr & 0xffe0)
784 e6e5906b pbrook
              | env->cc_dest | (env->cc_x << 4);
785 6af0bf9c bellard
#elif defined(TARGET_MIPS)
786 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
787 fdf9b3e8 bellard
    /* XXXXX */
788 e4533c7a bellard
#else
789 e4533c7a bellard
#error unsupported target CPU
790 e4533c7a bellard
#endif
791 1057eaa7 pbrook
792 1057eaa7 pbrook
    /* restore global registers */
793 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
794 8c6939c0 bellard
    asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
795 8c6939c0 bellard
#endif
796 1057eaa7 pbrook
#include "hostregs_helper.h"
797 1057eaa7 pbrook
798 6a00d601 bellard
    /* fail safe : never use cpu_single_env outside cpu_exec() */
799 6a00d601 bellard
    cpu_single_env = NULL; 
800 7d13299d bellard
    return ret;
801 7d13299d bellard
}
802 6dbad63e bellard
803 fbf9eeb3 bellard
/* must only be called from the generated code as an exception can be
804 fbf9eeb3 bellard
   generated */
805 fbf9eeb3 bellard
void tb_invalidate_page_range(target_ulong start, target_ulong end)
806 fbf9eeb3 bellard
{
807 dc5d0b3d bellard
    /* XXX: cannot enable it yet because it yields to MMU exception
808 dc5d0b3d bellard
       where NIP != read address on PowerPC */
809 dc5d0b3d bellard
#if 0
810 fbf9eeb3 bellard
    target_ulong phys_addr;
811 fbf9eeb3 bellard
    phys_addr = get_phys_addr_code(env, start);
812 fbf9eeb3 bellard
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
813 dc5d0b3d bellard
#endif
814 fbf9eeb3 bellard
}
815 fbf9eeb3 bellard
816 1a18c71b bellard
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
817 e4533c7a bellard
818 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
819 6dbad63e bellard
{
820 6dbad63e bellard
    CPUX86State *saved_env;
821 6dbad63e bellard
822 6dbad63e bellard
    saved_env = env;
823 6dbad63e bellard
    env = s;
824 a412ac57 bellard
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
825 a513fe19 bellard
        selector &= 0xffff;
826 2e255c6b bellard
        cpu_x86_load_seg_cache(env, seg_reg, selector, 
827 c27004ec bellard
                               (selector << 4), 0xffff, 0);
828 a513fe19 bellard
    } else {
829 b453b70b bellard
        load_seg(seg_reg, selector);
830 a513fe19 bellard
    }
831 6dbad63e bellard
    env = saved_env;
832 6dbad63e bellard
}
833 9de5e440 bellard
834 d0a1ffc9 bellard
void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)
835 d0a1ffc9 bellard
{
836 d0a1ffc9 bellard
    CPUX86State *saved_env;
837 d0a1ffc9 bellard
838 d0a1ffc9 bellard
    saved_env = env;
839 d0a1ffc9 bellard
    env = s;
840 d0a1ffc9 bellard
    
841 c27004ec bellard
    helper_fsave((target_ulong)ptr, data32);
842 d0a1ffc9 bellard
843 d0a1ffc9 bellard
    env = saved_env;
844 d0a1ffc9 bellard
}
845 d0a1ffc9 bellard
846 d0a1ffc9 bellard
void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
847 d0a1ffc9 bellard
{
848 d0a1ffc9 bellard
    CPUX86State *saved_env;
849 d0a1ffc9 bellard
850 d0a1ffc9 bellard
    saved_env = env;
851 d0a1ffc9 bellard
    env = s;
852 d0a1ffc9 bellard
    
853 c27004ec bellard
    helper_frstor((target_ulong)ptr, data32);
854 d0a1ffc9 bellard
855 d0a1ffc9 bellard
    env = saved_env;
856 d0a1ffc9 bellard
}
857 d0a1ffc9 bellard
858 e4533c7a bellard
#endif /* TARGET_I386 */
859 e4533c7a bellard
860 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
861 67b915a5 bellard
862 3fb2ded1 bellard
#if defined(TARGET_I386)
863 3fb2ded1 bellard
864 b56dad1c bellard
/* 'pc' is the host PC at which the exception was raised. 'address' is
865 fd6ce8f6 bellard
   the effective address of the memory exception. 'is_write' is 1 if a
866 fd6ce8f6 bellard
   write caused the exception and otherwise 0'. 'old_set' is the
867 fd6ce8f6 bellard
   signal set which should be restored */
868 2b413144 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
869 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set, 
870 bf3e8bf1 bellard
                                    void *puc)
871 9de5e440 bellard
{
872 a513fe19 bellard
    TranslationBlock *tb;
873 a513fe19 bellard
    int ret;
874 68a79315 bellard
875 83479e77 bellard
    if (cpu_single_env)
876 83479e77 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
877 fd6ce8f6 bellard
#if defined(DEBUG_SIGNAL)
878 bf3e8bf1 bellard
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
879 bf3e8bf1 bellard
                pc, address, is_write, *(unsigned long *)old_set);
880 9de5e440 bellard
#endif
881 25eb4484 bellard
    /* XXX: locking issue */
882 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
883 fd6ce8f6 bellard
        return 1;
884 fd6ce8f6 bellard
    }
885 fbf9eeb3 bellard
886 3fb2ded1 bellard
    /* see if it is an MMU fault */
887 93a40ea9 bellard
    ret = cpu_x86_handle_mmu_fault(env, address, is_write, 
888 93a40ea9 bellard
                                   ((env->hflags & HF_CPL_MASK) == 3), 0);
889 3fb2ded1 bellard
    if (ret < 0)
890 3fb2ded1 bellard
        return 0; /* not an MMU fault */
891 3fb2ded1 bellard
    if (ret == 0)
892 3fb2ded1 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
893 3fb2ded1 bellard
    /* now we have a real cpu fault */
894 a513fe19 bellard
    tb = tb_find_pc(pc);
895 a513fe19 bellard
    if (tb) {
896 9de5e440 bellard
        /* the PC is inside the translated code. It means that we have
897 9de5e440 bellard
           a virtual CPU fault */
898 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, puc);
899 3fb2ded1 bellard
    }
900 4cbf74b6 bellard
    if (ret == 1) {
901 3fb2ded1 bellard
#if 0
902 4cbf74b6 bellard
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n", 
903 4cbf74b6 bellard
               env->eip, env->cr[2], env->error_code);
904 3fb2ded1 bellard
#endif
905 4cbf74b6 bellard
        /* we restore the process signal mask as the sigreturn should
906 4cbf74b6 bellard
           do it (XXX: use sigsetjmp) */
907 4cbf74b6 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
908 54ca9095 bellard
        raise_exception_err(env->exception_index, env->error_code);
909 4cbf74b6 bellard
    } else {
910 4cbf74b6 bellard
        /* activate soft MMU for this block */
911 3f337316 bellard
        env->hflags |= HF_SOFTMMU_MASK;
912 fbf9eeb3 bellard
        cpu_resume_from_signal(env, puc);
913 4cbf74b6 bellard
    }
914 3fb2ded1 bellard
    /* never comes here */
915 3fb2ded1 bellard
    return 1;
916 3fb2ded1 bellard
}
917 3fb2ded1 bellard
918 e4533c7a bellard
#elif defined(TARGET_ARM)
919 3fb2ded1 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
920 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
921 bf3e8bf1 bellard
                                    void *puc)
922 3fb2ded1 bellard
{
923 68016c62 bellard
    TranslationBlock *tb;
924 68016c62 bellard
    int ret;
925 68016c62 bellard
926 68016c62 bellard
    if (cpu_single_env)
927 68016c62 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
928 68016c62 bellard
#if defined(DEBUG_SIGNAL)
929 68016c62 bellard
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
930 68016c62 bellard
           pc, address, is_write, *(unsigned long *)old_set);
931 68016c62 bellard
#endif
932 9f0777ed bellard
    /* XXX: locking issue */
933 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
934 9f0777ed bellard
        return 1;
935 9f0777ed bellard
    }
936 68016c62 bellard
    /* see if it is an MMU fault */
937 68016c62 bellard
    ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0);
938 68016c62 bellard
    if (ret < 0)
939 68016c62 bellard
        return 0; /* not an MMU fault */
940 68016c62 bellard
    if (ret == 0)
941 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
942 68016c62 bellard
    /* now we have a real cpu fault */
943 68016c62 bellard
    tb = tb_find_pc(pc);
944 68016c62 bellard
    if (tb) {
945 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
946 68016c62 bellard
           a virtual CPU fault */
947 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
948 68016c62 bellard
    }
949 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
950 68016c62 bellard
       do it (XXX: use sigsetjmp) */
951 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
952 68016c62 bellard
    cpu_loop_exit();
953 3fb2ded1 bellard
}
954 93ac68bc bellard
#elif defined(TARGET_SPARC)
955 93ac68bc bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
956 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
957 bf3e8bf1 bellard
                                    void *puc)
958 93ac68bc bellard
{
959 68016c62 bellard
    TranslationBlock *tb;
960 68016c62 bellard
    int ret;
961 68016c62 bellard
962 68016c62 bellard
    if (cpu_single_env)
963 68016c62 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
964 68016c62 bellard
#if defined(DEBUG_SIGNAL)
965 68016c62 bellard
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
966 68016c62 bellard
           pc, address, is_write, *(unsigned long *)old_set);
967 68016c62 bellard
#endif
968 b453b70b bellard
    /* XXX: locking issue */
969 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
970 b453b70b bellard
        return 1;
971 b453b70b bellard
    }
972 68016c62 bellard
    /* see if it is an MMU fault */
973 68016c62 bellard
    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0);
974 68016c62 bellard
    if (ret < 0)
975 68016c62 bellard
        return 0; /* not an MMU fault */
976 68016c62 bellard
    if (ret == 0)
977 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
978 68016c62 bellard
    /* now we have a real cpu fault */
979 68016c62 bellard
    tb = tb_find_pc(pc);
980 68016c62 bellard
    if (tb) {
981 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
982 68016c62 bellard
           a virtual CPU fault */
983 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
984 68016c62 bellard
    }
985 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
986 68016c62 bellard
       do it (XXX: use sigsetjmp) */
987 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
988 68016c62 bellard
    cpu_loop_exit();
989 93ac68bc bellard
}
990 67867308 bellard
#elif defined (TARGET_PPC)
991 67867308 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
992 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
993 bf3e8bf1 bellard
                                    void *puc)
994 67867308 bellard
{
995 67867308 bellard
    TranslationBlock *tb;
996 ce09776b bellard
    int ret;
997 67867308 bellard
    
998 67867308 bellard
    if (cpu_single_env)
999 67867308 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1000 67867308 bellard
#if defined(DEBUG_SIGNAL)
1001 67867308 bellard
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
1002 67867308 bellard
           pc, address, is_write, *(unsigned long *)old_set);
1003 67867308 bellard
#endif
1004 67867308 bellard
    /* XXX: locking issue */
1005 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1006 67867308 bellard
        return 1;
1007 67867308 bellard
    }
1008 67867308 bellard
1009 ce09776b bellard
    /* see if it is an MMU fault */
1010 7f957d28 bellard
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
1011 ce09776b bellard
    if (ret < 0)
1012 ce09776b bellard
        return 0; /* not an MMU fault */
1013 ce09776b bellard
    if (ret == 0)
1014 ce09776b bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1015 ce09776b bellard
1016 67867308 bellard
    /* now we have a real cpu fault */
1017 67867308 bellard
    tb = tb_find_pc(pc);
1018 67867308 bellard
    if (tb) {
1019 67867308 bellard
        /* the PC is inside the translated code. It means that we have
1020 67867308 bellard
           a virtual CPU fault */
1021 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, puc);
1022 67867308 bellard
    }
1023 ce09776b bellard
    if (ret == 1) {
1024 67867308 bellard
#if 0
1025 ce09776b bellard
        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
1026 ce09776b bellard
               env->nip, env->error_code, tb);
1027 67867308 bellard
#endif
1028 67867308 bellard
    /* we restore the process signal mask as the sigreturn should
1029 67867308 bellard
       do it (XXX: use sigsetjmp) */
1030 bf3e8bf1 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
1031 9fddaa0c bellard
        do_raise_exception_err(env->exception_index, env->error_code);
1032 ce09776b bellard
    } else {
1033 ce09776b bellard
        /* activate soft MMU for this block */
1034 fbf9eeb3 bellard
        cpu_resume_from_signal(env, puc);
1035 ce09776b bellard
    }
1036 67867308 bellard
    /* never comes here */
1037 e6e5906b pbrook
    return 1;
1038 e6e5906b pbrook
}
1039 e6e5906b pbrook
1040 e6e5906b pbrook
#elif defined(TARGET_M68K)
1041 e6e5906b pbrook
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1042 e6e5906b pbrook
                                    int is_write, sigset_t *old_set,
1043 e6e5906b pbrook
                                    void *puc)
1044 e6e5906b pbrook
{
1045 e6e5906b pbrook
    TranslationBlock *tb;
1046 e6e5906b pbrook
    int ret;
1047 e6e5906b pbrook
1048 e6e5906b pbrook
    if (cpu_single_env)
1049 e6e5906b pbrook
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1050 e6e5906b pbrook
#if defined(DEBUG_SIGNAL)
1051 e6e5906b pbrook
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
1052 e6e5906b pbrook
           pc, address, is_write, *(unsigned long *)old_set);
1053 e6e5906b pbrook
#endif
1054 e6e5906b pbrook
    /* XXX: locking issue */
1055 e6e5906b pbrook
    if (is_write && page_unprotect(address, pc, puc)) {
1056 e6e5906b pbrook
        return 1;
1057 e6e5906b pbrook
    }
1058 e6e5906b pbrook
    /* see if it is an MMU fault */
1059 e6e5906b pbrook
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0);
1060 e6e5906b pbrook
    if (ret < 0)
1061 e6e5906b pbrook
        return 0; /* not an MMU fault */
1062 e6e5906b pbrook
    if (ret == 0)
1063 e6e5906b pbrook
        return 1; /* the MMU fault was handled without causing real CPU fault */
1064 e6e5906b pbrook
    /* now we have a real cpu fault */
1065 e6e5906b pbrook
    tb = tb_find_pc(pc);
1066 e6e5906b pbrook
    if (tb) {
1067 e6e5906b pbrook
        /* the PC is inside the translated code. It means that we have
1068 e6e5906b pbrook
           a virtual CPU fault */
1069 e6e5906b pbrook
        cpu_restore_state(tb, env, pc, puc);
1070 e6e5906b pbrook
    }
1071 e6e5906b pbrook
    /* we restore the process signal mask as the sigreturn should
1072 e6e5906b pbrook
       do it (XXX: use sigsetjmp) */
1073 e6e5906b pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
1074 e6e5906b pbrook
    cpu_loop_exit();
1075 e6e5906b pbrook
    /* never comes here */
1076 67867308 bellard
    return 1;
1077 67867308 bellard
}
1078 6af0bf9c bellard
1079 6af0bf9c bellard
#elif defined (TARGET_MIPS)
1080 6af0bf9c bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1081 6af0bf9c bellard
                                    int is_write, sigset_t *old_set,
1082 6af0bf9c bellard
                                    void *puc)
1083 6af0bf9c bellard
{
1084 6af0bf9c bellard
    TranslationBlock *tb;
1085 6af0bf9c bellard
    int ret;
1086 6af0bf9c bellard
    
1087 6af0bf9c bellard
    if (cpu_single_env)
1088 6af0bf9c bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1089 6af0bf9c bellard
#if defined(DEBUG_SIGNAL)
1090 6af0bf9c bellard
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
1091 6af0bf9c bellard
           pc, address, is_write, *(unsigned long *)old_set);
1092 6af0bf9c bellard
#endif
1093 6af0bf9c bellard
    /* XXX: locking issue */
1094 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1095 6af0bf9c bellard
        return 1;
1096 6af0bf9c bellard
    }
1097 6af0bf9c bellard
1098 6af0bf9c bellard
    /* see if it is an MMU fault */
1099 cc9442b9 bellard
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, 1, 0);
1100 6af0bf9c bellard
    if (ret < 0)
1101 6af0bf9c bellard
        return 0; /* not an MMU fault */
1102 6af0bf9c bellard
    if (ret == 0)
1103 6af0bf9c bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1104 6af0bf9c bellard
1105 6af0bf9c bellard
    /* now we have a real cpu fault */
1106 6af0bf9c bellard
    tb = tb_find_pc(pc);
1107 6af0bf9c bellard
    if (tb) {
1108 6af0bf9c bellard
        /* the PC is inside the translated code. It means that we have
1109 6af0bf9c bellard
           a virtual CPU fault */
1110 6af0bf9c bellard
        cpu_restore_state(tb, env, pc, puc);
1111 6af0bf9c bellard
    }
1112 6af0bf9c bellard
    if (ret == 1) {
1113 6af0bf9c bellard
#if 0
1114 6af0bf9c bellard
        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
1115 6af0bf9c bellard
               env->nip, env->error_code, tb);
1116 6af0bf9c bellard
#endif
1117 6af0bf9c bellard
    /* we restore the process signal mask as the sigreturn should
1118 6af0bf9c bellard
       do it (XXX: use sigsetjmp) */
1119 6af0bf9c bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
1120 6af0bf9c bellard
        do_raise_exception_err(env->exception_index, env->error_code);
1121 6af0bf9c bellard
    } else {
1122 6af0bf9c bellard
        /* activate soft MMU for this block */
1123 6af0bf9c bellard
        cpu_resume_from_signal(env, puc);
1124 6af0bf9c bellard
    }
1125 6af0bf9c bellard
    /* never comes here */
1126 6af0bf9c bellard
    return 1;
1127 6af0bf9c bellard
}
1128 6af0bf9c bellard
1129 fdf9b3e8 bellard
#elif defined (TARGET_SH4)
1130 fdf9b3e8 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1131 fdf9b3e8 bellard
                                    int is_write, sigset_t *old_set,
1132 fdf9b3e8 bellard
                                    void *puc)
1133 fdf9b3e8 bellard
{
1134 fdf9b3e8 bellard
    TranslationBlock *tb;
1135 fdf9b3e8 bellard
    int ret;
1136 fdf9b3e8 bellard
    
1137 fdf9b3e8 bellard
    if (cpu_single_env)
1138 fdf9b3e8 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1139 fdf9b3e8 bellard
#if defined(DEBUG_SIGNAL)
1140 fdf9b3e8 bellard
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
1141 fdf9b3e8 bellard
           pc, address, is_write, *(unsigned long *)old_set);
1142 fdf9b3e8 bellard
#endif
1143 fdf9b3e8 bellard
    /* XXX: locking issue */
1144 fdf9b3e8 bellard
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1145 fdf9b3e8 bellard
        return 1;
1146 fdf9b3e8 bellard
    }
1147 fdf9b3e8 bellard
1148 fdf9b3e8 bellard
    /* see if it is an MMU fault */
1149 fdf9b3e8 bellard
    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, 1, 0);
1150 fdf9b3e8 bellard
    if (ret < 0)
1151 fdf9b3e8 bellard
        return 0; /* not an MMU fault */
1152 fdf9b3e8 bellard
    if (ret == 0)
1153 fdf9b3e8 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1154 fdf9b3e8 bellard
1155 fdf9b3e8 bellard
    /* now we have a real cpu fault */
1156 fdf9b3e8 bellard
    tb = tb_find_pc(pc);
1157 fdf9b3e8 bellard
    if (tb) {
1158 fdf9b3e8 bellard
        /* the PC is inside the translated code. It means that we have
1159 fdf9b3e8 bellard
           a virtual CPU fault */
1160 fdf9b3e8 bellard
        cpu_restore_state(tb, env, pc, puc);
1161 fdf9b3e8 bellard
    }
1162 fdf9b3e8 bellard
#if 0
1163 fdf9b3e8 bellard
        printf("PF exception: NIP=0x%08x error=0x%x %p\n", 
1164 fdf9b3e8 bellard
               env->nip, env->error_code, tb);
1165 fdf9b3e8 bellard
#endif
1166 fdf9b3e8 bellard
    /* we restore the process signal mask as the sigreturn should
1167 fdf9b3e8 bellard
       do it (XXX: use sigsetjmp) */
1168 355fb23d pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
1169 355fb23d pbrook
    cpu_loop_exit();
1170 fdf9b3e8 bellard
    /* never comes here */
1171 fdf9b3e8 bellard
    return 1;
1172 fdf9b3e8 bellard
}
1173 e4533c7a bellard
#else
1174 e4533c7a bellard
#error unsupported target CPU
1175 e4533c7a bellard
#endif
1176 9de5e440 bellard
1177 2b413144 bellard
#if defined(__i386__)
1178 2b413144 bellard
1179 d8ecc0b9 bellard
#if defined(__APPLE__)
1180 d8ecc0b9 bellard
# include <sys/ucontext.h>
1181 d8ecc0b9 bellard
1182 d8ecc0b9 bellard
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1183 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1184 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1185 d8ecc0b9 bellard
#else
1186 d8ecc0b9 bellard
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1187 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1188 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1189 d8ecc0b9 bellard
#endif
1190 d8ecc0b9 bellard
1191 bf3e8bf1 bellard
#if defined(USE_CODE_COPY)
1192 bf3e8bf1 bellard
static void cpu_send_trap(unsigned long pc, int trap, 
1193 bf3e8bf1 bellard
                          struct ucontext *uc)
1194 bf3e8bf1 bellard
{
1195 bf3e8bf1 bellard
    TranslationBlock *tb;
1196 bf3e8bf1 bellard
1197 bf3e8bf1 bellard
    if (cpu_single_env)
1198 bf3e8bf1 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1199 bf3e8bf1 bellard
    /* now we have a real cpu fault */
1200 bf3e8bf1 bellard
    tb = tb_find_pc(pc);
1201 bf3e8bf1 bellard
    if (tb) {
1202 bf3e8bf1 bellard
        /* the PC is inside the translated code. It means that we have
1203 bf3e8bf1 bellard
           a virtual CPU fault */
1204 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, uc);
1205 bf3e8bf1 bellard
    }
1206 bf3e8bf1 bellard
    sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
1207 bf3e8bf1 bellard
    raise_exception_err(trap, env->error_code);
1208 bf3e8bf1 bellard
}
1209 bf3e8bf1 bellard
#endif
1210 bf3e8bf1 bellard
1211 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, 
1212 e4533c7a bellard
                       void *puc)
1213 9de5e440 bellard
{
1214 5a7b542b ths
    siginfo_t *info = pinfo;
1215 9de5e440 bellard
    struct ucontext *uc = puc;
1216 9de5e440 bellard
    unsigned long pc;
1217 bf3e8bf1 bellard
    int trapno;
1218 97eb5b14 bellard
1219 d691f669 bellard
#ifndef REG_EIP
1220 d691f669 bellard
/* for glibc 2.1 */
1221 fd6ce8f6 bellard
#define REG_EIP    EIP
1222 fd6ce8f6 bellard
#define REG_ERR    ERR
1223 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
1224 d691f669 bellard
#endif
1225 d8ecc0b9 bellard
    pc = EIP_sig(uc);
1226 d8ecc0b9 bellard
    trapno = TRAP_sig(uc);
1227 bf3e8bf1 bellard
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
1228 bf3e8bf1 bellard
    if (trapno == 0x00 || trapno == 0x05) {
1229 bf3e8bf1 bellard
        /* send division by zero or bound exception */
1230 bf3e8bf1 bellard
        cpu_send_trap(pc, trapno, uc);
1231 bf3e8bf1 bellard
        return 1;
1232 bf3e8bf1 bellard
    } else
1233 bf3e8bf1 bellard
#endif
1234 bf3e8bf1 bellard
        return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1235 bf3e8bf1 bellard
                                 trapno == 0xe ? 
1236 d8ecc0b9 bellard
                                 (ERROR_sig(uc) >> 1) & 1 : 0,
1237 bf3e8bf1 bellard
                                 &uc->uc_sigmask, puc);
1238 2b413144 bellard
}
1239 2b413144 bellard
1240 bc51c5c9 bellard
#elif defined(__x86_64__)
1241 bc51c5c9 bellard
1242 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo,
1243 bc51c5c9 bellard
                       void *puc)
1244 bc51c5c9 bellard
{
1245 5a7b542b ths
    siginfo_t *info = pinfo;
1246 bc51c5c9 bellard
    struct ucontext *uc = puc;
1247 bc51c5c9 bellard
    unsigned long pc;
1248 bc51c5c9 bellard
1249 bc51c5c9 bellard
    pc = uc->uc_mcontext.gregs[REG_RIP];
1250 bc51c5c9 bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1251 bc51c5c9 bellard
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? 
1252 bc51c5c9 bellard
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1253 bc51c5c9 bellard
                             &uc->uc_sigmask, puc);
1254 bc51c5c9 bellard
}
1255 bc51c5c9 bellard
1256 83fb7adf bellard
#elif defined(__powerpc__)
1257 2b413144 bellard
1258 83fb7adf bellard
/***********************************************************************
1259 83fb7adf bellard
 * signal context platform-specific definitions
1260 83fb7adf bellard
 * From Wine
1261 83fb7adf bellard
 */
1262 83fb7adf bellard
#ifdef linux
1263 83fb7adf bellard
/* All Registers access - only for local access */
1264 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1265 83fb7adf bellard
/* Gpr Registers access  */
1266 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1267 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1268 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1269 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1270 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1271 83fb7adf bellard
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1272 83fb7adf bellard
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1273 83fb7adf bellard
/* Float Registers access  */
1274 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1275 83fb7adf bellard
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1276 83fb7adf bellard
/* Exception Registers access */
1277 83fb7adf bellard
# define DAR_sig(context)                        REG_sig(dar, context)
1278 83fb7adf bellard
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1279 83fb7adf bellard
# define TRAP_sig(context)                        REG_sig(trap, context)
1280 83fb7adf bellard
#endif /* linux */
1281 83fb7adf bellard
1282 83fb7adf bellard
#ifdef __APPLE__
1283 83fb7adf bellard
# include <sys/ucontext.h>
1284 83fb7adf bellard
typedef struct ucontext SIGCONTEXT;
1285 83fb7adf bellard
/* All Registers access - only for local access */
1286 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1287 83fb7adf bellard
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1288 83fb7adf bellard
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1289 83fb7adf bellard
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1290 83fb7adf bellard
/* Gpr Registers access */
1291 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1292 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1293 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1294 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)
1295 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1296 83fb7adf bellard
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1297 83fb7adf bellard
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1298 83fb7adf bellard
/* Float Registers access */
1299 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1300 83fb7adf bellard
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1301 83fb7adf bellard
/* Exception Registers access */
1302 83fb7adf bellard
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1303 83fb7adf bellard
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1304 83fb7adf bellard
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1305 83fb7adf bellard
#endif /* __APPLE__ */
1306 83fb7adf bellard
1307 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, 
1308 e4533c7a bellard
                       void *puc)
1309 2b413144 bellard
{
1310 5a7b542b ths
    siginfo_t *info = pinfo;
1311 25eb4484 bellard
    struct ucontext *uc = puc;
1312 25eb4484 bellard
    unsigned long pc;
1313 25eb4484 bellard
    int is_write;
1314 25eb4484 bellard
1315 83fb7adf bellard
    pc = IAR_sig(uc);
1316 25eb4484 bellard
    is_write = 0;
1317 25eb4484 bellard
#if 0
1318 25eb4484 bellard
    /* ppc 4xx case */
1319 83fb7adf bellard
    if (DSISR_sig(uc) & 0x00800000)
1320 25eb4484 bellard
        is_write = 1;
1321 25eb4484 bellard
#else
1322 83fb7adf bellard
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1323 25eb4484 bellard
        is_write = 1;
1324 25eb4484 bellard
#endif
1325 25eb4484 bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1326 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1327 2b413144 bellard
}
1328 2b413144 bellard
1329 2f87c607 bellard
#elif defined(__alpha__)
1330 2f87c607 bellard
1331 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, 
1332 2f87c607 bellard
                           void *puc)
1333 2f87c607 bellard
{
1334 5a7b542b ths
    siginfo_t *info = pinfo;
1335 2f87c607 bellard
    struct ucontext *uc = puc;
1336 2f87c607 bellard
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1337 2f87c607 bellard
    uint32_t insn = *pc;
1338 2f87c607 bellard
    int is_write = 0;
1339 2f87c607 bellard
1340 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1341 2f87c607 bellard
    switch (insn >> 26) {
1342 2f87c607 bellard
    case 0x0d: // stw
1343 2f87c607 bellard
    case 0x0e: // stb
1344 2f87c607 bellard
    case 0x0f: // stq_u
1345 2f87c607 bellard
    case 0x24: // stf
1346 2f87c607 bellard
    case 0x25: // stg
1347 2f87c607 bellard
    case 0x26: // sts
1348 2f87c607 bellard
    case 0x27: // stt
1349 2f87c607 bellard
    case 0x2c: // stl
1350 2f87c607 bellard
    case 0x2d: // stq
1351 2f87c607 bellard
    case 0x2e: // stl_c
1352 2f87c607 bellard
    case 0x2f: // stq_c
1353 2f87c607 bellard
        is_write = 1;
1354 2f87c607 bellard
    }
1355 2f87c607 bellard
1356 2f87c607 bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1357 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1358 2f87c607 bellard
}
1359 8c6939c0 bellard
#elif defined(__sparc__)
1360 8c6939c0 bellard
1361 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, 
1362 e4533c7a bellard
                       void *puc)
1363 8c6939c0 bellard
{
1364 5a7b542b ths
    siginfo_t *info = pinfo;
1365 8c6939c0 bellard
    uint32_t *regs = (uint32_t *)(info + 1);
1366 8c6939c0 bellard
    void *sigmask = (regs + 20);
1367 8c6939c0 bellard
    unsigned long pc;
1368 8c6939c0 bellard
    int is_write;
1369 8c6939c0 bellard
    uint32_t insn;
1370 8c6939c0 bellard
    
1371 8c6939c0 bellard
    /* XXX: is there a standard glibc define ? */
1372 8c6939c0 bellard
    pc = regs[1];
1373 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1374 8c6939c0 bellard
    is_write = 0;
1375 8c6939c0 bellard
    insn = *(uint32_t *)pc;
1376 8c6939c0 bellard
    if ((insn >> 30) == 3) {
1377 8c6939c0 bellard
      switch((insn >> 19) & 0x3f) {
1378 8c6939c0 bellard
      case 0x05: // stb
1379 8c6939c0 bellard
      case 0x06: // sth
1380 8c6939c0 bellard
      case 0x04: // st
1381 8c6939c0 bellard
      case 0x07: // std
1382 8c6939c0 bellard
      case 0x24: // stf
1383 8c6939c0 bellard
      case 0x27: // stdf
1384 8c6939c0 bellard
      case 0x25: // stfsr
1385 8c6939c0 bellard
        is_write = 1;
1386 8c6939c0 bellard
        break;
1387 8c6939c0 bellard
      }
1388 8c6939c0 bellard
    }
1389 8c6939c0 bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1390 bf3e8bf1 bellard
                             is_write, sigmask, NULL);
1391 8c6939c0 bellard
}
1392 8c6939c0 bellard
1393 8c6939c0 bellard
#elif defined(__arm__)
1394 8c6939c0 bellard
1395 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, 
1396 e4533c7a bellard
                       void *puc)
1397 8c6939c0 bellard
{
1398 5a7b542b ths
    siginfo_t *info = pinfo;
1399 8c6939c0 bellard
    struct ucontext *uc = puc;
1400 8c6939c0 bellard
    unsigned long pc;
1401 8c6939c0 bellard
    int is_write;
1402 8c6939c0 bellard
    
1403 8c6939c0 bellard
    pc = uc->uc_mcontext.gregs[R15];
1404 8c6939c0 bellard
    /* XXX: compute is_write */
1405 8c6939c0 bellard
    is_write = 0;
1406 8c6939c0 bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1407 8c6939c0 bellard
                             is_write,
1408 f3a9676a pbrook
                             &uc->uc_sigmask, puc);
1409 8c6939c0 bellard
}
1410 8c6939c0 bellard
1411 38e584a0 bellard
#elif defined(__mc68000)
1412 38e584a0 bellard
1413 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, 
1414 38e584a0 bellard
                       void *puc)
1415 38e584a0 bellard
{
1416 5a7b542b ths
    siginfo_t *info = pinfo;
1417 38e584a0 bellard
    struct ucontext *uc = puc;
1418 38e584a0 bellard
    unsigned long pc;
1419 38e584a0 bellard
    int is_write;
1420 38e584a0 bellard
    
1421 38e584a0 bellard
    pc = uc->uc_mcontext.gregs[16];
1422 38e584a0 bellard
    /* XXX: compute is_write */
1423 38e584a0 bellard
    is_write = 0;
1424 38e584a0 bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1425 38e584a0 bellard
                             is_write,
1426 bf3e8bf1 bellard
                             &uc->uc_sigmask, puc);
1427 38e584a0 bellard
}
1428 38e584a0 bellard
1429 b8076a74 bellard
#elif defined(__ia64)
1430 b8076a74 bellard
1431 b8076a74 bellard
#ifndef __ISR_VALID
1432 b8076a74 bellard
  /* This ought to be in <bits/siginfo.h>... */
1433 b8076a74 bellard
# define __ISR_VALID        1
1434 b8076a74 bellard
#endif
1435 b8076a74 bellard
1436 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1437 b8076a74 bellard
{
1438 5a7b542b ths
    siginfo_t *info = pinfo;
1439 b8076a74 bellard
    struct ucontext *uc = puc;
1440 b8076a74 bellard
    unsigned long ip;
1441 b8076a74 bellard
    int is_write = 0;
1442 b8076a74 bellard
1443 b8076a74 bellard
    ip = uc->uc_mcontext.sc_ip;
1444 b8076a74 bellard
    switch (host_signum) {
1445 b8076a74 bellard
      case SIGILL:
1446 b8076a74 bellard
      case SIGFPE:
1447 b8076a74 bellard
      case SIGSEGV:
1448 b8076a74 bellard
      case SIGBUS:
1449 b8076a74 bellard
      case SIGTRAP:
1450 fd4a43e4 bellard
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1451 b8076a74 bellard
              /* ISR.W (write-access) is bit 33:  */
1452 b8076a74 bellard
              is_write = (info->si_isr >> 33) & 1;
1453 b8076a74 bellard
          break;
1454 b8076a74 bellard
1455 b8076a74 bellard
      default:
1456 b8076a74 bellard
          break;
1457 b8076a74 bellard
    }
1458 b8076a74 bellard
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1459 b8076a74 bellard
                             is_write,
1460 b8076a74 bellard
                             &uc->uc_sigmask, puc);
1461 b8076a74 bellard
}
1462 b8076a74 bellard
1463 90cb9493 bellard
#elif defined(__s390__)
1464 90cb9493 bellard
1465 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, 
1466 90cb9493 bellard
                       void *puc)
1467 90cb9493 bellard
{
1468 5a7b542b ths
    siginfo_t *info = pinfo;
1469 90cb9493 bellard
    struct ucontext *uc = puc;
1470 90cb9493 bellard
    unsigned long pc;
1471 90cb9493 bellard
    int is_write;
1472 90cb9493 bellard
    
1473 90cb9493 bellard
    pc = uc->uc_mcontext.psw.addr;
1474 90cb9493 bellard
    /* XXX: compute is_write */
1475 90cb9493 bellard
    is_write = 0;
1476 90cb9493 bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1477 90cb9493 bellard
                             is_write,
1478 90cb9493 bellard
                             &uc->uc_sigmask, puc);
1479 90cb9493 bellard
}
1480 90cb9493 bellard
1481 9de5e440 bellard
#else
1482 2b413144 bellard
1483 3fb2ded1 bellard
#error host CPU specific signal handler needed
1484 2b413144 bellard
1485 9de5e440 bellard
#endif
1486 67b915a5 bellard
1487 67b915a5 bellard
#endif /* !defined(CONFIG_SOFTMMU) */