Statistics
| Branch: | Revision:

root / cpu-exec.c @ 21b20814

History | View | Annotate | Download (49.7 kB)

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