Statistics
| Branch: | Revision:

root / cpu-exec.c @ 3d575329

History | View | Annotate | Download (50 kB)

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