Statistics
| Branch: | Revision:

root / cpu-exec.c @ 39d51eb8

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