Statistics
| Branch: | Revision:

root / cpu-exec.c @ aa0bf00b

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