Statistics
| Branch: | Revision:

root / cpu-exec.c @ 86cc1ce0

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