Statistics
| Branch: | Revision:

root / cpu-exec.c @ 46dc3881

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