Statistics
| Branch: | Revision:

root / cpu-exec.c @ 40d0591e

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