Statistics
| Branch: | Revision:

root / cpu-exec.c @ 3b46e624

History | View | Annotate | Download (49.7 kB)

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