Statistics
| Branch: | Revision:

root / cpu-exec.c @ c3d2689d

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