Statistics
| Branch: | Revision:

root / cpu-exec.c @ 3d834c78

History | View | Annotate | Download (50.3 kB)

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