Statistics
| Branch: | Revision:

root / cpu-exec.c @ 968c74da

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 497ad68c pbrook
                        BREAK_CHAIN;
560 f1ccf904 ths
                    }
561 0633879f pbrook
#elif defined(TARGET_M68K)
562 0633879f pbrook
                    if (interrupt_request & CPU_INTERRUPT_HARD
563 0633879f pbrook
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
564 0633879f pbrook
                            < env->pending_level) {
565 0633879f pbrook
                        /* Real hardware gets the interrupt vector via an
566 0633879f pbrook
                           IACK cycle at this point.  Current emulated
567 0633879f pbrook
                           hardware doesn't rely on this, so we
568 0633879f pbrook
                           provide/save the vector when the interrupt is
569 0633879f pbrook
                           first signalled.  */
570 0633879f pbrook
                        env->exception_index = env->pending_vector;
571 0633879f pbrook
                        do_interrupt(1);
572 497ad68c pbrook
                        BREAK_CHAIN;
573 0633879f pbrook
                    }
574 68a79315 bellard
#endif
575 9d05095e bellard
                   /* Don't use the cached interupt_request value,
576 9d05095e bellard
                      do_interrupt may have updated the EXITTB flag. */
577 b5ff1b31 bellard
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
578 bf3e8bf1 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
579 bf3e8bf1 bellard
                        /* ensure that no TB jump will be modified as
580 bf3e8bf1 bellard
                           the program flow was changed */
581 497ad68c pbrook
                        BREAK_CHAIN;
582 bf3e8bf1 bellard
                    }
583 68a79315 bellard
                    if (interrupt_request & CPU_INTERRUPT_EXIT) {
584 68a79315 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
585 68a79315 bellard
                        env->exception_index = EXCP_INTERRUPT;
586 68a79315 bellard
                        cpu_loop_exit();
587 68a79315 bellard
                    }
588 3fb2ded1 bellard
                }
589 7d13299d bellard
#ifdef DEBUG_EXEC
590 b5ff1b31 bellard
                if ((loglevel & CPU_LOG_TB_CPU)) {
591 3fb2ded1 bellard
                    /* restore flags in standard format */
592 ecb644f4 ths
                    regs_to_env();
593 ecb644f4 ths
#if defined(TARGET_I386)
594 3fb2ded1 bellard
                    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
595 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
596 3fb2ded1 bellard
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
597 e4533c7a bellard
#elif defined(TARGET_ARM)
598 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
599 93ac68bc bellard
#elif defined(TARGET_SPARC)
600 3475187d bellard
                    REGWPTR = env->regbase + (env->cwp * 16);
601 3475187d bellard
                    env->regwptr = REGWPTR;
602 3475187d bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
603 67867308 bellard
#elif defined(TARGET_PPC)
604 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
605 e6e5906b pbrook
#elif defined(TARGET_M68K)
606 e6e5906b pbrook
                    cpu_m68k_flush_flags(env, env->cc_op);
607 e6e5906b pbrook
                    env->cc_op = CC_OP_FLAGS;
608 e6e5906b pbrook
                    env->sr = (env->sr & 0xffe0)
609 e6e5906b pbrook
                              | env->cc_dest | (env->cc_x << 4);
610 e6e5906b pbrook
                    cpu_dump_state(env, logfile, fprintf, 0);
611 6af0bf9c bellard
#elif defined(TARGET_MIPS)
612 6af0bf9c bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
613 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
614 fdf9b3e8 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
615 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
616 eddf68a6 j_mayer
                    cpu_dump_state(env, logfile, fprintf, 0);
617 f1ccf904 ths
#elif defined(TARGET_CRIS)
618 f1ccf904 ths
                    cpu_dump_state(env, logfile, fprintf, 0);
619 e4533c7a bellard
#else
620 5fafdf24 ths
#error unsupported target CPU
621 e4533c7a bellard
#endif
622 3fb2ded1 bellard
                }
623 7d13299d bellard
#endif
624 8a40a180 bellard
                tb = tb_find_fast();
625 9d27abd9 bellard
#ifdef DEBUG_EXEC
626 c1135f61 bellard
                if ((loglevel & CPU_LOG_EXEC)) {
627 c27004ec bellard
                    fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
628 c27004ec bellard
                            (long)tb->tc_ptr, tb->pc,
629 c27004ec bellard
                            lookup_symbol(tb->pc));
630 3fb2ded1 bellard
                }
631 9d27abd9 bellard
#endif
632 66f1cdbd blueswir1
                RESTORE_GLOBALS();
633 8a40a180 bellard
                /* see if we can patch the calling TB. When the TB
634 8a40a180 bellard
                   spans two pages, we cannot safely do a direct
635 8a40a180 bellard
                   jump. */
636 c27004ec bellard
                {
637 8a40a180 bellard
                    if (T0 != 0 &&
638 f32fc648 bellard
#if USE_KQEMU
639 f32fc648 bellard
                        (env->kqemu_enabled != 2) &&
640 f32fc648 bellard
#endif
641 ec6338ba bellard
                        tb->page_addr[1] == -1) {
642 3fb2ded1 bellard
                    spin_lock(&tb_lock);
643 c27004ec bellard
                    tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
644 3fb2ded1 bellard
                    spin_unlock(&tb_lock);
645 3fb2ded1 bellard
                }
646 c27004ec bellard
                }
647 3fb2ded1 bellard
                tc_ptr = tb->tc_ptr;
648 83479e77 bellard
                env->current_tb = tb;
649 3fb2ded1 bellard
                /* execute the generated code */
650 3fb2ded1 bellard
                gen_func = (void *)tc_ptr;
651 8c6939c0 bellard
#if defined(__sparc__)
652 3fb2ded1 bellard
                __asm__ __volatile__("call        %0\n\t"
653 3fb2ded1 bellard
                                     "mov        %%o7,%%i0"
654 3fb2ded1 bellard
                                     : /* no outputs */
655 5fafdf24 ths
                                     : "r" (gen_func)
656 fdbb4691 bellard
                                     : "i0", "i1", "i2", "i3", "i4", "i5",
657 faab7592 ths
                                       "o0", "o1", "o2", "o3", "o4", "o5",
658 fdbb4691 bellard
                                       "l0", "l1", "l2", "l3", "l4", "l5",
659 fdbb4691 bellard
                                       "l6", "l7");
660 8c6939c0 bellard
#elif defined(__arm__)
661 3fb2ded1 bellard
                asm volatile ("mov pc, %0\n\t"
662 3fb2ded1 bellard
                              ".global exec_loop\n\t"
663 3fb2ded1 bellard
                              "exec_loop:\n\t"
664 3fb2ded1 bellard
                              : /* no outputs */
665 3fb2ded1 bellard
                              : "r" (gen_func)
666 3fb2ded1 bellard
                              : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
667 b8076a74 bellard
#elif defined(__ia64)
668 b8076a74 bellard
                struct fptr {
669 b8076a74 bellard
                        void *ip;
670 b8076a74 bellard
                        void *gp;
671 b8076a74 bellard
                } fp;
672 b8076a74 bellard
673 b8076a74 bellard
                fp.ip = tc_ptr;
674 b8076a74 bellard
                fp.gp = code_gen_buffer + 2 * (1 << 20);
675 b8076a74 bellard
                (*(void (*)(void)) &fp)();
676 ae228531 bellard
#else
677 57fec1fe bellard
                T0 = gen_func();
678 ae228531 bellard
#endif
679 83479e77 bellard
                env->current_tb = NULL;
680 4cbf74b6 bellard
                /* reset soft MMU for next block (it can currently
681 4cbf74b6 bellard
                   only be set by a memory fault) */
682 4cbf74b6 bellard
#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
683 3f337316 bellard
                if (env->hflags & HF_SOFTMMU_MASK) {
684 3f337316 bellard
                    env->hflags &= ~HF_SOFTMMU_MASK;
685 4cbf74b6 bellard
                    /* do not allow linking to another block */
686 4cbf74b6 bellard
                    T0 = 0;
687 4cbf74b6 bellard
                }
688 4cbf74b6 bellard
#endif
689 f32fc648 bellard
#if defined(USE_KQEMU)
690 f32fc648 bellard
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
691 f32fc648 bellard
                if (kqemu_is_ok(env) &&
692 f32fc648 bellard
                    (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
693 f32fc648 bellard
                    cpu_loop_exit();
694 f32fc648 bellard
                }
695 f32fc648 bellard
#endif
696 50a518e3 ths
            } /* for(;;) */
697 3fb2ded1 bellard
        } else {
698 0d1a29f9 bellard
            env_to_regs();
699 7d13299d bellard
        }
700 3fb2ded1 bellard
    } /* for(;;) */
701 3fb2ded1 bellard
702 7d13299d bellard
703 e4533c7a bellard
#if defined(TARGET_I386)
704 9de5e440 bellard
    /* restore flags in standard format */
705 fc2b4c48 bellard
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
706 e4533c7a bellard
#elif defined(TARGET_ARM)
707 b7bcbe95 bellard
    /* XXX: Save/restore host fpu exception state?.  */
708 93ac68bc bellard
#elif defined(TARGET_SPARC)
709 3475187d bellard
#if defined(reg_REGWPTR)
710 3475187d bellard
    REGWPTR = saved_regwptr;
711 3475187d bellard
#endif
712 67867308 bellard
#elif defined(TARGET_PPC)
713 e6e5906b pbrook
#elif defined(TARGET_M68K)
714 e6e5906b pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
715 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
716 e6e5906b pbrook
    env->sr = (env->sr & 0xffe0)
717 e6e5906b pbrook
              | env->cc_dest | (env->cc_x << 4);
718 6af0bf9c bellard
#elif defined(TARGET_MIPS)
719 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
720 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
721 f1ccf904 ths
#elif defined(TARGET_CRIS)
722 fdf9b3e8 bellard
    /* XXXXX */
723 e4533c7a bellard
#else
724 e4533c7a bellard
#error unsupported target CPU
725 e4533c7a bellard
#endif
726 1057eaa7 pbrook
727 1057eaa7 pbrook
    /* restore global registers */
728 66f1cdbd blueswir1
    RESTORE_GLOBALS();
729 1057eaa7 pbrook
#include "hostregs_helper.h"
730 1057eaa7 pbrook
731 6a00d601 bellard
    /* fail safe : never use cpu_single_env outside cpu_exec() */
732 5fafdf24 ths
    cpu_single_env = NULL;
733 7d13299d bellard
    return ret;
734 7d13299d bellard
}
735 6dbad63e bellard
736 fbf9eeb3 bellard
/* must only be called from the generated code as an exception can be
737 fbf9eeb3 bellard
   generated */
738 fbf9eeb3 bellard
void tb_invalidate_page_range(target_ulong start, target_ulong end)
739 fbf9eeb3 bellard
{
740 dc5d0b3d bellard
    /* XXX: cannot enable it yet because it yields to MMU exception
741 dc5d0b3d bellard
       where NIP != read address on PowerPC */
742 dc5d0b3d bellard
#if 0
743 fbf9eeb3 bellard
    target_ulong phys_addr;
744 fbf9eeb3 bellard
    phys_addr = get_phys_addr_code(env, start);
745 fbf9eeb3 bellard
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
746 dc5d0b3d bellard
#endif
747 fbf9eeb3 bellard
}
748 fbf9eeb3 bellard
749 1a18c71b bellard
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
750 e4533c7a bellard
751 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
752 6dbad63e bellard
{
753 6dbad63e bellard
    CPUX86State *saved_env;
754 6dbad63e bellard
755 6dbad63e bellard
    saved_env = env;
756 6dbad63e bellard
    env = s;
757 a412ac57 bellard
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
758 a513fe19 bellard
        selector &= 0xffff;
759 5fafdf24 ths
        cpu_x86_load_seg_cache(env, seg_reg, selector,
760 c27004ec bellard
                               (selector << 4), 0xffff, 0);
761 a513fe19 bellard
    } else {
762 b453b70b bellard
        load_seg(seg_reg, selector);
763 a513fe19 bellard
    }
764 6dbad63e bellard
    env = saved_env;
765 6dbad63e bellard
}
766 9de5e440 bellard
767 6f12a2a6 bellard
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
768 d0a1ffc9 bellard
{
769 d0a1ffc9 bellard
    CPUX86State *saved_env;
770 d0a1ffc9 bellard
771 d0a1ffc9 bellard
    saved_env = env;
772 d0a1ffc9 bellard
    env = s;
773 3b46e624 ths
774 6f12a2a6 bellard
    helper_fsave(ptr, data32);
775 d0a1ffc9 bellard
776 d0a1ffc9 bellard
    env = saved_env;
777 d0a1ffc9 bellard
}
778 d0a1ffc9 bellard
779 6f12a2a6 bellard
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
780 d0a1ffc9 bellard
{
781 d0a1ffc9 bellard
    CPUX86State *saved_env;
782 d0a1ffc9 bellard
783 d0a1ffc9 bellard
    saved_env = env;
784 d0a1ffc9 bellard
    env = s;
785 3b46e624 ths
786 6f12a2a6 bellard
    helper_frstor(ptr, data32);
787 d0a1ffc9 bellard
788 d0a1ffc9 bellard
    env = saved_env;
789 d0a1ffc9 bellard
}
790 d0a1ffc9 bellard
791 e4533c7a bellard
#endif /* TARGET_I386 */
792 e4533c7a bellard
793 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
794 67b915a5 bellard
795 3fb2ded1 bellard
#if defined(TARGET_I386)
796 3fb2ded1 bellard
797 b56dad1c bellard
/* 'pc' is the host PC at which the exception was raised. 'address' is
798 fd6ce8f6 bellard
   the effective address of the memory exception. 'is_write' is 1 if a
799 fd6ce8f6 bellard
   write caused the exception and otherwise 0'. 'old_set' is the
800 fd6ce8f6 bellard
   signal set which should be restored */
801 2b413144 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
802 5fafdf24 ths
                                    int is_write, sigset_t *old_set,
803 bf3e8bf1 bellard
                                    void *puc)
804 9de5e440 bellard
{
805 a513fe19 bellard
    TranslationBlock *tb;
806 a513fe19 bellard
    int ret;
807 68a79315 bellard
808 83479e77 bellard
    if (cpu_single_env)
809 83479e77 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
810 fd6ce8f6 bellard
#if defined(DEBUG_SIGNAL)
811 5fafdf24 ths
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
812 bf3e8bf1 bellard
                pc, address, is_write, *(unsigned long *)old_set);
813 9de5e440 bellard
#endif
814 25eb4484 bellard
    /* XXX: locking issue */
815 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
816 fd6ce8f6 bellard
        return 1;
817 fd6ce8f6 bellard
    }
818 fbf9eeb3 bellard
819 3fb2ded1 bellard
    /* see if it is an MMU fault */
820 6ebbf390 j_mayer
    ret = cpu_x86_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
821 3fb2ded1 bellard
    if (ret < 0)
822 3fb2ded1 bellard
        return 0; /* not an MMU fault */
823 3fb2ded1 bellard
    if (ret == 0)
824 3fb2ded1 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
825 3fb2ded1 bellard
    /* now we have a real cpu fault */
826 a513fe19 bellard
    tb = tb_find_pc(pc);
827 a513fe19 bellard
    if (tb) {
828 9de5e440 bellard
        /* the PC is inside the translated code. It means that we have
829 9de5e440 bellard
           a virtual CPU fault */
830 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, puc);
831 3fb2ded1 bellard
    }
832 4cbf74b6 bellard
    if (ret == 1) {
833 3fb2ded1 bellard
#if 0
834 5fafdf24 ths
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
835 4cbf74b6 bellard
               env->eip, env->cr[2], env->error_code);
836 3fb2ded1 bellard
#endif
837 4cbf74b6 bellard
        /* we restore the process signal mask as the sigreturn should
838 4cbf74b6 bellard
           do it (XXX: use sigsetjmp) */
839 4cbf74b6 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
840 54ca9095 bellard
        raise_exception_err(env->exception_index, env->error_code);
841 4cbf74b6 bellard
    } else {
842 4cbf74b6 bellard
        /* activate soft MMU for this block */
843 3f337316 bellard
        env->hflags |= HF_SOFTMMU_MASK;
844 fbf9eeb3 bellard
        cpu_resume_from_signal(env, puc);
845 4cbf74b6 bellard
    }
846 3fb2ded1 bellard
    /* never comes here */
847 3fb2ded1 bellard
    return 1;
848 3fb2ded1 bellard
}
849 3fb2ded1 bellard
850 e4533c7a bellard
#elif defined(TARGET_ARM)
851 3fb2ded1 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
852 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
853 bf3e8bf1 bellard
                                    void *puc)
854 3fb2ded1 bellard
{
855 68016c62 bellard
    TranslationBlock *tb;
856 68016c62 bellard
    int ret;
857 68016c62 bellard
858 68016c62 bellard
    if (cpu_single_env)
859 68016c62 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
860 68016c62 bellard
#if defined(DEBUG_SIGNAL)
861 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
862 68016c62 bellard
           pc, address, is_write, *(unsigned long *)old_set);
863 68016c62 bellard
#endif
864 9f0777ed bellard
    /* XXX: locking issue */
865 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
866 9f0777ed bellard
        return 1;
867 9f0777ed bellard
    }
868 68016c62 bellard
    /* see if it is an MMU fault */
869 6ebbf390 j_mayer
    ret = cpu_arm_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
870 68016c62 bellard
    if (ret < 0)
871 68016c62 bellard
        return 0; /* not an MMU fault */
872 68016c62 bellard
    if (ret == 0)
873 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
874 68016c62 bellard
    /* now we have a real cpu fault */
875 68016c62 bellard
    tb = tb_find_pc(pc);
876 68016c62 bellard
    if (tb) {
877 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
878 68016c62 bellard
           a virtual CPU fault */
879 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
880 68016c62 bellard
    }
881 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
882 68016c62 bellard
       do it (XXX: use sigsetjmp) */
883 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
884 68016c62 bellard
    cpu_loop_exit();
885 968c74da aurel32
    /* never comes here */
886 968c74da aurel32
    return 1;
887 3fb2ded1 bellard
}
888 93ac68bc bellard
#elif defined(TARGET_SPARC)
889 93ac68bc bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
890 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
891 bf3e8bf1 bellard
                                    void *puc)
892 93ac68bc bellard
{
893 68016c62 bellard
    TranslationBlock *tb;
894 68016c62 bellard
    int ret;
895 68016c62 bellard
896 68016c62 bellard
    if (cpu_single_env)
897 68016c62 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
898 68016c62 bellard
#if defined(DEBUG_SIGNAL)
899 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
900 68016c62 bellard
           pc, address, is_write, *(unsigned long *)old_set);
901 68016c62 bellard
#endif
902 b453b70b bellard
    /* XXX: locking issue */
903 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
904 b453b70b bellard
        return 1;
905 b453b70b bellard
    }
906 68016c62 bellard
    /* see if it is an MMU fault */
907 6ebbf390 j_mayer
    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
908 68016c62 bellard
    if (ret < 0)
909 68016c62 bellard
        return 0; /* not an MMU fault */
910 68016c62 bellard
    if (ret == 0)
911 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
912 68016c62 bellard
    /* now we have a real cpu fault */
913 68016c62 bellard
    tb = tb_find_pc(pc);
914 68016c62 bellard
    if (tb) {
915 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
916 68016c62 bellard
           a virtual CPU fault */
917 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
918 68016c62 bellard
    }
919 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
920 68016c62 bellard
       do it (XXX: use sigsetjmp) */
921 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
922 68016c62 bellard
    cpu_loop_exit();
923 968c74da aurel32
    /* never comes here */
924 968c74da aurel32
    return 1;
925 93ac68bc bellard
}
926 67867308 bellard
#elif defined (TARGET_PPC)
927 67867308 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
928 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
929 bf3e8bf1 bellard
                                    void *puc)
930 67867308 bellard
{
931 67867308 bellard
    TranslationBlock *tb;
932 ce09776b bellard
    int ret;
933 3b46e624 ths
934 67867308 bellard
    if (cpu_single_env)
935 67867308 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
936 67867308 bellard
#if defined(DEBUG_SIGNAL)
937 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
938 67867308 bellard
           pc, address, is_write, *(unsigned long *)old_set);
939 67867308 bellard
#endif
940 67867308 bellard
    /* XXX: locking issue */
941 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
942 67867308 bellard
        return 1;
943 67867308 bellard
    }
944 67867308 bellard
945 ce09776b bellard
    /* see if it is an MMU fault */
946 6ebbf390 j_mayer
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
947 ce09776b bellard
    if (ret < 0)
948 ce09776b bellard
        return 0; /* not an MMU fault */
949 ce09776b bellard
    if (ret == 0)
950 ce09776b bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
951 ce09776b bellard
952 67867308 bellard
    /* now we have a real cpu fault */
953 67867308 bellard
    tb = tb_find_pc(pc);
954 67867308 bellard
    if (tb) {
955 67867308 bellard
        /* the PC is inside the translated code. It means that we have
956 67867308 bellard
           a virtual CPU fault */
957 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, puc);
958 67867308 bellard
    }
959 ce09776b bellard
    if (ret == 1) {
960 67867308 bellard
#if 0
961 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
962 ce09776b bellard
               env->nip, env->error_code, tb);
963 67867308 bellard
#endif
964 67867308 bellard
    /* we restore the process signal mask as the sigreturn should
965 67867308 bellard
       do it (XXX: use sigsetjmp) */
966 bf3e8bf1 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
967 9fddaa0c bellard
        do_raise_exception_err(env->exception_index, env->error_code);
968 ce09776b bellard
    } else {
969 ce09776b bellard
        /* activate soft MMU for this block */
970 fbf9eeb3 bellard
        cpu_resume_from_signal(env, puc);
971 ce09776b bellard
    }
972 67867308 bellard
    /* never comes here */
973 e6e5906b pbrook
    return 1;
974 e6e5906b pbrook
}
975 e6e5906b pbrook
976 e6e5906b pbrook
#elif defined(TARGET_M68K)
977 e6e5906b pbrook
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
978 e6e5906b pbrook
                                    int is_write, sigset_t *old_set,
979 e6e5906b pbrook
                                    void *puc)
980 e6e5906b pbrook
{
981 e6e5906b pbrook
    TranslationBlock *tb;
982 e6e5906b pbrook
    int ret;
983 e6e5906b pbrook
984 e6e5906b pbrook
    if (cpu_single_env)
985 e6e5906b pbrook
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
986 e6e5906b pbrook
#if defined(DEBUG_SIGNAL)
987 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
988 e6e5906b pbrook
           pc, address, is_write, *(unsigned long *)old_set);
989 e6e5906b pbrook
#endif
990 e6e5906b pbrook
    /* XXX: locking issue */
991 e6e5906b pbrook
    if (is_write && page_unprotect(address, pc, puc)) {
992 e6e5906b pbrook
        return 1;
993 e6e5906b pbrook
    }
994 e6e5906b pbrook
    /* see if it is an MMU fault */
995 6ebbf390 j_mayer
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
996 e6e5906b pbrook
    if (ret < 0)
997 e6e5906b pbrook
        return 0; /* not an MMU fault */
998 e6e5906b pbrook
    if (ret == 0)
999 e6e5906b pbrook
        return 1; /* the MMU fault was handled without causing real CPU fault */
1000 e6e5906b pbrook
    /* now we have a real cpu fault */
1001 e6e5906b pbrook
    tb = tb_find_pc(pc);
1002 e6e5906b pbrook
    if (tb) {
1003 e6e5906b pbrook
        /* the PC is inside the translated code. It means that we have
1004 e6e5906b pbrook
           a virtual CPU fault */
1005 e6e5906b pbrook
        cpu_restore_state(tb, env, pc, puc);
1006 e6e5906b pbrook
    }
1007 e6e5906b pbrook
    /* we restore the process signal mask as the sigreturn should
1008 e6e5906b pbrook
       do it (XXX: use sigsetjmp) */
1009 e6e5906b pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
1010 e6e5906b pbrook
    cpu_loop_exit();
1011 e6e5906b pbrook
    /* never comes here */
1012 67867308 bellard
    return 1;
1013 67867308 bellard
}
1014 6af0bf9c bellard
1015 6af0bf9c bellard
#elif defined (TARGET_MIPS)
1016 6af0bf9c bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1017 6af0bf9c bellard
                                    int is_write, sigset_t *old_set,
1018 6af0bf9c bellard
                                    void *puc)
1019 6af0bf9c bellard
{
1020 6af0bf9c bellard
    TranslationBlock *tb;
1021 6af0bf9c bellard
    int ret;
1022 3b46e624 ths
1023 6af0bf9c bellard
    if (cpu_single_env)
1024 6af0bf9c bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1025 6af0bf9c bellard
#if defined(DEBUG_SIGNAL)
1026 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1027 6af0bf9c bellard
           pc, address, is_write, *(unsigned long *)old_set);
1028 6af0bf9c bellard
#endif
1029 6af0bf9c bellard
    /* XXX: locking issue */
1030 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1031 6af0bf9c bellard
        return 1;
1032 6af0bf9c bellard
    }
1033 6af0bf9c bellard
1034 6af0bf9c bellard
    /* see if it is an MMU fault */
1035 6ebbf390 j_mayer
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1036 6af0bf9c bellard
    if (ret < 0)
1037 6af0bf9c bellard
        return 0; /* not an MMU fault */
1038 6af0bf9c bellard
    if (ret == 0)
1039 6af0bf9c bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1040 6af0bf9c bellard
1041 6af0bf9c bellard
    /* now we have a real cpu fault */
1042 6af0bf9c bellard
    tb = tb_find_pc(pc);
1043 6af0bf9c bellard
    if (tb) {
1044 6af0bf9c bellard
        /* the PC is inside the translated code. It means that we have
1045 6af0bf9c bellard
           a virtual CPU fault */
1046 6af0bf9c bellard
        cpu_restore_state(tb, env, pc, puc);
1047 6af0bf9c bellard
    }
1048 6af0bf9c bellard
    if (ret == 1) {
1049 6af0bf9c bellard
#if 0
1050 5fafdf24 ths
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1051 1eb5207b ths
               env->PC, env->error_code, tb);
1052 6af0bf9c bellard
#endif
1053 6af0bf9c bellard
    /* we restore the process signal mask as the sigreturn should
1054 6af0bf9c bellard
       do it (XXX: use sigsetjmp) */
1055 6af0bf9c bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
1056 6af0bf9c bellard
        do_raise_exception_err(env->exception_index, env->error_code);
1057 6af0bf9c bellard
    } else {
1058 6af0bf9c bellard
        /* activate soft MMU for this block */
1059 6af0bf9c bellard
        cpu_resume_from_signal(env, puc);
1060 6af0bf9c bellard
    }
1061 6af0bf9c bellard
    /* never comes here */
1062 6af0bf9c bellard
    return 1;
1063 6af0bf9c bellard
}
1064 6af0bf9c bellard
1065 fdf9b3e8 bellard
#elif defined (TARGET_SH4)
1066 fdf9b3e8 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1067 fdf9b3e8 bellard
                                    int is_write, sigset_t *old_set,
1068 fdf9b3e8 bellard
                                    void *puc)
1069 fdf9b3e8 bellard
{
1070 fdf9b3e8 bellard
    TranslationBlock *tb;
1071 fdf9b3e8 bellard
    int ret;
1072 3b46e624 ths
1073 fdf9b3e8 bellard
    if (cpu_single_env)
1074 fdf9b3e8 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1075 fdf9b3e8 bellard
#if defined(DEBUG_SIGNAL)
1076 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1077 fdf9b3e8 bellard
           pc, address, is_write, *(unsigned long *)old_set);
1078 fdf9b3e8 bellard
#endif
1079 fdf9b3e8 bellard
    /* XXX: locking issue */
1080 fdf9b3e8 bellard
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1081 fdf9b3e8 bellard
        return 1;
1082 fdf9b3e8 bellard
    }
1083 fdf9b3e8 bellard
1084 fdf9b3e8 bellard
    /* see if it is an MMU fault */
1085 6ebbf390 j_mayer
    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1086 fdf9b3e8 bellard
    if (ret < 0)
1087 fdf9b3e8 bellard
        return 0; /* not an MMU fault */
1088 fdf9b3e8 bellard
    if (ret == 0)
1089 fdf9b3e8 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1090 fdf9b3e8 bellard
1091 fdf9b3e8 bellard
    /* now we have a real cpu fault */
1092 eddf68a6 j_mayer
    tb = tb_find_pc(pc);
1093 eddf68a6 j_mayer
    if (tb) {
1094 eddf68a6 j_mayer
        /* the PC is inside the translated code. It means that we have
1095 eddf68a6 j_mayer
           a virtual CPU fault */
1096 eddf68a6 j_mayer
        cpu_restore_state(tb, env, pc, puc);
1097 eddf68a6 j_mayer
    }
1098 eddf68a6 j_mayer
#if 0
1099 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1100 eddf68a6 j_mayer
               env->nip, env->error_code, tb);
1101 eddf68a6 j_mayer
#endif
1102 eddf68a6 j_mayer
    /* we restore the process signal mask as the sigreturn should
1103 eddf68a6 j_mayer
       do it (XXX: use sigsetjmp) */
1104 eddf68a6 j_mayer
    sigprocmask(SIG_SETMASK, old_set, NULL);
1105 eddf68a6 j_mayer
    cpu_loop_exit();
1106 eddf68a6 j_mayer
    /* never comes here */
1107 eddf68a6 j_mayer
    return 1;
1108 eddf68a6 j_mayer
}
1109 eddf68a6 j_mayer
1110 eddf68a6 j_mayer
#elif defined (TARGET_ALPHA)
1111 eddf68a6 j_mayer
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1112 eddf68a6 j_mayer
                                    int is_write, sigset_t *old_set,
1113 eddf68a6 j_mayer
                                    void *puc)
1114 eddf68a6 j_mayer
{
1115 eddf68a6 j_mayer
    TranslationBlock *tb;
1116 eddf68a6 j_mayer
    int ret;
1117 3b46e624 ths
1118 eddf68a6 j_mayer
    if (cpu_single_env)
1119 eddf68a6 j_mayer
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1120 eddf68a6 j_mayer
#if defined(DEBUG_SIGNAL)
1121 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1122 eddf68a6 j_mayer
           pc, address, is_write, *(unsigned long *)old_set);
1123 eddf68a6 j_mayer
#endif
1124 eddf68a6 j_mayer
    /* XXX: locking issue */
1125 eddf68a6 j_mayer
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1126 eddf68a6 j_mayer
        return 1;
1127 eddf68a6 j_mayer
    }
1128 eddf68a6 j_mayer
1129 eddf68a6 j_mayer
    /* see if it is an MMU fault */
1130 6ebbf390 j_mayer
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1131 eddf68a6 j_mayer
    if (ret < 0)
1132 eddf68a6 j_mayer
        return 0; /* not an MMU fault */
1133 eddf68a6 j_mayer
    if (ret == 0)
1134 eddf68a6 j_mayer
        return 1; /* the MMU fault was handled without causing real CPU fault */
1135 eddf68a6 j_mayer
1136 eddf68a6 j_mayer
    /* now we have a real cpu fault */
1137 fdf9b3e8 bellard
    tb = tb_find_pc(pc);
1138 fdf9b3e8 bellard
    if (tb) {
1139 fdf9b3e8 bellard
        /* the PC is inside the translated code. It means that we have
1140 fdf9b3e8 bellard
           a virtual CPU fault */
1141 fdf9b3e8 bellard
        cpu_restore_state(tb, env, pc, puc);
1142 fdf9b3e8 bellard
    }
1143 fdf9b3e8 bellard
#if 0
1144 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1145 fdf9b3e8 bellard
               env->nip, env->error_code, tb);
1146 fdf9b3e8 bellard
#endif
1147 fdf9b3e8 bellard
    /* we restore the process signal mask as the sigreturn should
1148 fdf9b3e8 bellard
       do it (XXX: use sigsetjmp) */
1149 355fb23d pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
1150 355fb23d pbrook
    cpu_loop_exit();
1151 fdf9b3e8 bellard
    /* never comes here */
1152 fdf9b3e8 bellard
    return 1;
1153 fdf9b3e8 bellard
}
1154 f1ccf904 ths
#elif defined (TARGET_CRIS)
1155 f1ccf904 ths
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1156 f1ccf904 ths
                                    int is_write, sigset_t *old_set,
1157 f1ccf904 ths
                                    void *puc)
1158 f1ccf904 ths
{
1159 f1ccf904 ths
    TranslationBlock *tb;
1160 f1ccf904 ths
    int ret;
1161 f1ccf904 ths
1162 f1ccf904 ths
    if (cpu_single_env)
1163 f1ccf904 ths
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1164 f1ccf904 ths
#if defined(DEBUG_SIGNAL)
1165 f1ccf904 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1166 f1ccf904 ths
           pc, address, is_write, *(unsigned long *)old_set);
1167 f1ccf904 ths
#endif
1168 f1ccf904 ths
    /* XXX: locking issue */
1169 f1ccf904 ths
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1170 f1ccf904 ths
        return 1;
1171 f1ccf904 ths
    }
1172 f1ccf904 ths
1173 f1ccf904 ths
    /* see if it is an MMU fault */
1174 6ebbf390 j_mayer
    ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1175 f1ccf904 ths
    if (ret < 0)
1176 f1ccf904 ths
        return 0; /* not an MMU fault */
1177 f1ccf904 ths
    if (ret == 0)
1178 f1ccf904 ths
        return 1; /* the MMU fault was handled without causing real CPU fault */
1179 f1ccf904 ths
1180 f1ccf904 ths
    /* now we have a real cpu fault */
1181 f1ccf904 ths
    tb = tb_find_pc(pc);
1182 f1ccf904 ths
    if (tb) {
1183 f1ccf904 ths
        /* the PC is inside the translated code. It means that we have
1184 f1ccf904 ths
           a virtual CPU fault */
1185 f1ccf904 ths
        cpu_restore_state(tb, env, pc, puc);
1186 f1ccf904 ths
    }
1187 f1ccf904 ths
    /* we restore the process signal mask as the sigreturn should
1188 f1ccf904 ths
       do it (XXX: use sigsetjmp) */
1189 f1ccf904 ths
    sigprocmask(SIG_SETMASK, old_set, NULL);
1190 f1ccf904 ths
    cpu_loop_exit();
1191 f1ccf904 ths
    /* never comes here */
1192 f1ccf904 ths
    return 1;
1193 f1ccf904 ths
}
1194 f1ccf904 ths
1195 e4533c7a bellard
#else
1196 e4533c7a bellard
#error unsupported target CPU
1197 e4533c7a bellard
#endif
1198 9de5e440 bellard
1199 2b413144 bellard
#if defined(__i386__)
1200 2b413144 bellard
1201 d8ecc0b9 bellard
#if defined(__APPLE__)
1202 d8ecc0b9 bellard
# include <sys/ucontext.h>
1203 d8ecc0b9 bellard
1204 d8ecc0b9 bellard
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1205 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1206 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1207 d8ecc0b9 bellard
#else
1208 d8ecc0b9 bellard
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1209 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1210 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1211 d8ecc0b9 bellard
#endif
1212 d8ecc0b9 bellard
1213 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1214 e4533c7a bellard
                       void *puc)
1215 9de5e440 bellard
{
1216 5a7b542b ths
    siginfo_t *info = pinfo;
1217 9de5e440 bellard
    struct ucontext *uc = puc;
1218 9de5e440 bellard
    unsigned long pc;
1219 bf3e8bf1 bellard
    int trapno;
1220 97eb5b14 bellard
1221 d691f669 bellard
#ifndef REG_EIP
1222 d691f669 bellard
/* for glibc 2.1 */
1223 fd6ce8f6 bellard
#define REG_EIP    EIP
1224 fd6ce8f6 bellard
#define REG_ERR    ERR
1225 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
1226 d691f669 bellard
#endif
1227 d8ecc0b9 bellard
    pc = EIP_sig(uc);
1228 d8ecc0b9 bellard
    trapno = TRAP_sig(uc);
1229 ec6338ba bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1230 ec6338ba bellard
                             trapno == 0xe ?
1231 ec6338ba bellard
                             (ERROR_sig(uc) >> 1) & 1 : 0,
1232 ec6338ba bellard
                             &uc->uc_sigmask, puc);
1233 2b413144 bellard
}
1234 2b413144 bellard
1235 bc51c5c9 bellard
#elif defined(__x86_64__)
1236 bc51c5c9 bellard
1237 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo,
1238 bc51c5c9 bellard
                       void *puc)
1239 bc51c5c9 bellard
{
1240 5a7b542b ths
    siginfo_t *info = pinfo;
1241 bc51c5c9 bellard
    struct ucontext *uc = puc;
1242 bc51c5c9 bellard
    unsigned long pc;
1243 bc51c5c9 bellard
1244 bc51c5c9 bellard
    pc = uc->uc_mcontext.gregs[REG_RIP];
1245 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1246 5fafdf24 ths
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1247 bc51c5c9 bellard
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1248 bc51c5c9 bellard
                             &uc->uc_sigmask, puc);
1249 bc51c5c9 bellard
}
1250 bc51c5c9 bellard
1251 83fb7adf bellard
#elif defined(__powerpc__)
1252 2b413144 bellard
1253 83fb7adf bellard
/***********************************************************************
1254 83fb7adf bellard
 * signal context platform-specific definitions
1255 83fb7adf bellard
 * From Wine
1256 83fb7adf bellard
 */
1257 83fb7adf bellard
#ifdef linux
1258 83fb7adf bellard
/* All Registers access - only for local access */
1259 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1260 83fb7adf bellard
/* Gpr Registers access  */
1261 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1262 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1263 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1264 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1265 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1266 83fb7adf bellard
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1267 83fb7adf bellard
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1268 83fb7adf bellard
/* Float Registers access  */
1269 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1270 83fb7adf bellard
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1271 83fb7adf bellard
/* Exception Registers access */
1272 83fb7adf bellard
# define DAR_sig(context)                        REG_sig(dar, context)
1273 83fb7adf bellard
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1274 83fb7adf bellard
# define TRAP_sig(context)                        REG_sig(trap, context)
1275 83fb7adf bellard
#endif /* linux */
1276 83fb7adf bellard
1277 83fb7adf bellard
#ifdef __APPLE__
1278 83fb7adf bellard
# include <sys/ucontext.h>
1279 83fb7adf bellard
typedef struct ucontext SIGCONTEXT;
1280 83fb7adf bellard
/* All Registers access - only for local access */
1281 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1282 83fb7adf bellard
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1283 83fb7adf bellard
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1284 83fb7adf bellard
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1285 83fb7adf bellard
/* Gpr Registers access */
1286 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1287 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1288 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1289 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)
1290 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1291 83fb7adf bellard
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1292 83fb7adf bellard
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1293 83fb7adf bellard
/* Float Registers access */
1294 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1295 83fb7adf bellard
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1296 83fb7adf bellard
/* Exception Registers access */
1297 83fb7adf bellard
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1298 83fb7adf bellard
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1299 83fb7adf bellard
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1300 83fb7adf bellard
#endif /* __APPLE__ */
1301 83fb7adf bellard
1302 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1303 e4533c7a bellard
                       void *puc)
1304 2b413144 bellard
{
1305 5a7b542b ths
    siginfo_t *info = pinfo;
1306 25eb4484 bellard
    struct ucontext *uc = puc;
1307 25eb4484 bellard
    unsigned long pc;
1308 25eb4484 bellard
    int is_write;
1309 25eb4484 bellard
1310 83fb7adf bellard
    pc = IAR_sig(uc);
1311 25eb4484 bellard
    is_write = 0;
1312 25eb4484 bellard
#if 0
1313 25eb4484 bellard
    /* ppc 4xx case */
1314 83fb7adf bellard
    if (DSISR_sig(uc) & 0x00800000)
1315 25eb4484 bellard
        is_write = 1;
1316 25eb4484 bellard
#else
1317 83fb7adf bellard
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1318 25eb4484 bellard
        is_write = 1;
1319 25eb4484 bellard
#endif
1320 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1321 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1322 2b413144 bellard
}
1323 2b413144 bellard
1324 2f87c607 bellard
#elif defined(__alpha__)
1325 2f87c607 bellard
1326 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1327 2f87c607 bellard
                           void *puc)
1328 2f87c607 bellard
{
1329 5a7b542b ths
    siginfo_t *info = pinfo;
1330 2f87c607 bellard
    struct ucontext *uc = puc;
1331 2f87c607 bellard
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1332 2f87c607 bellard
    uint32_t insn = *pc;
1333 2f87c607 bellard
    int is_write = 0;
1334 2f87c607 bellard
1335 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1336 2f87c607 bellard
    switch (insn >> 26) {
1337 2f87c607 bellard
    case 0x0d: // stw
1338 2f87c607 bellard
    case 0x0e: // stb
1339 2f87c607 bellard
    case 0x0f: // stq_u
1340 2f87c607 bellard
    case 0x24: // stf
1341 2f87c607 bellard
    case 0x25: // stg
1342 2f87c607 bellard
    case 0x26: // sts
1343 2f87c607 bellard
    case 0x27: // stt
1344 2f87c607 bellard
    case 0x2c: // stl
1345 2f87c607 bellard
    case 0x2d: // stq
1346 2f87c607 bellard
    case 0x2e: // stl_c
1347 2f87c607 bellard
    case 0x2f: // stq_c
1348 2f87c607 bellard
        is_write = 1;
1349 2f87c607 bellard
    }
1350 2f87c607 bellard
1351 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1352 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1353 2f87c607 bellard
}
1354 8c6939c0 bellard
#elif defined(__sparc__)
1355 8c6939c0 bellard
1356 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1357 e4533c7a bellard
                       void *puc)
1358 8c6939c0 bellard
{
1359 5a7b542b ths
    siginfo_t *info = pinfo;
1360 8c6939c0 bellard
    uint32_t *regs = (uint32_t *)(info + 1);
1361 8c6939c0 bellard
    void *sigmask = (regs + 20);
1362 8c6939c0 bellard
    unsigned long pc;
1363 8c6939c0 bellard
    int is_write;
1364 8c6939c0 bellard
    uint32_t insn;
1365 3b46e624 ths
1366 8c6939c0 bellard
    /* XXX: is there a standard glibc define ? */
1367 8c6939c0 bellard
    pc = regs[1];
1368 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1369 8c6939c0 bellard
    is_write = 0;
1370 8c6939c0 bellard
    insn = *(uint32_t *)pc;
1371 8c6939c0 bellard
    if ((insn >> 30) == 3) {
1372 8c6939c0 bellard
      switch((insn >> 19) & 0x3f) {
1373 8c6939c0 bellard
      case 0x05: // stb
1374 8c6939c0 bellard
      case 0x06: // sth
1375 8c6939c0 bellard
      case 0x04: // st
1376 8c6939c0 bellard
      case 0x07: // std
1377 8c6939c0 bellard
      case 0x24: // stf
1378 8c6939c0 bellard
      case 0x27: // stdf
1379 8c6939c0 bellard
      case 0x25: // stfsr
1380 8c6939c0 bellard
        is_write = 1;
1381 8c6939c0 bellard
        break;
1382 8c6939c0 bellard
      }
1383 8c6939c0 bellard
    }
1384 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1385 bf3e8bf1 bellard
                             is_write, sigmask, NULL);
1386 8c6939c0 bellard
}
1387 8c6939c0 bellard
1388 8c6939c0 bellard
#elif defined(__arm__)
1389 8c6939c0 bellard
1390 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1391 e4533c7a bellard
                       void *puc)
1392 8c6939c0 bellard
{
1393 5a7b542b ths
    siginfo_t *info = pinfo;
1394 8c6939c0 bellard
    struct ucontext *uc = puc;
1395 8c6939c0 bellard
    unsigned long pc;
1396 8c6939c0 bellard
    int is_write;
1397 3b46e624 ths
1398 8c6939c0 bellard
    pc = uc->uc_mcontext.gregs[R15];
1399 8c6939c0 bellard
    /* XXX: compute is_write */
1400 8c6939c0 bellard
    is_write = 0;
1401 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1402 8c6939c0 bellard
                             is_write,
1403 f3a9676a pbrook
                             &uc->uc_sigmask, puc);
1404 8c6939c0 bellard
}
1405 8c6939c0 bellard
1406 38e584a0 bellard
#elif defined(__mc68000)
1407 38e584a0 bellard
1408 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1409 38e584a0 bellard
                       void *puc)
1410 38e584a0 bellard
{
1411 5a7b542b ths
    siginfo_t *info = pinfo;
1412 38e584a0 bellard
    struct ucontext *uc = puc;
1413 38e584a0 bellard
    unsigned long pc;
1414 38e584a0 bellard
    int is_write;
1415 3b46e624 ths
1416 38e584a0 bellard
    pc = uc->uc_mcontext.gregs[16];
1417 38e584a0 bellard
    /* XXX: compute is_write */
1418 38e584a0 bellard
    is_write = 0;
1419 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1420 38e584a0 bellard
                             is_write,
1421 bf3e8bf1 bellard
                             &uc->uc_sigmask, puc);
1422 38e584a0 bellard
}
1423 38e584a0 bellard
1424 b8076a74 bellard
#elif defined(__ia64)
1425 b8076a74 bellard
1426 b8076a74 bellard
#ifndef __ISR_VALID
1427 b8076a74 bellard
  /* This ought to be in <bits/siginfo.h>... */
1428 b8076a74 bellard
# define __ISR_VALID        1
1429 b8076a74 bellard
#endif
1430 b8076a74 bellard
1431 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1432 b8076a74 bellard
{
1433 5a7b542b ths
    siginfo_t *info = pinfo;
1434 b8076a74 bellard
    struct ucontext *uc = puc;
1435 b8076a74 bellard
    unsigned long ip;
1436 b8076a74 bellard
    int is_write = 0;
1437 b8076a74 bellard
1438 b8076a74 bellard
    ip = uc->uc_mcontext.sc_ip;
1439 b8076a74 bellard
    switch (host_signum) {
1440 b8076a74 bellard
      case SIGILL:
1441 b8076a74 bellard
      case SIGFPE:
1442 b8076a74 bellard
      case SIGSEGV:
1443 b8076a74 bellard
      case SIGBUS:
1444 b8076a74 bellard
      case SIGTRAP:
1445 fd4a43e4 bellard
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1446 b8076a74 bellard
              /* ISR.W (write-access) is bit 33:  */
1447 b8076a74 bellard
              is_write = (info->si_isr >> 33) & 1;
1448 b8076a74 bellard
          break;
1449 b8076a74 bellard
1450 b8076a74 bellard
      default:
1451 b8076a74 bellard
          break;
1452 b8076a74 bellard
    }
1453 b8076a74 bellard
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1454 b8076a74 bellard
                             is_write,
1455 b8076a74 bellard
                             &uc->uc_sigmask, puc);
1456 b8076a74 bellard
}
1457 b8076a74 bellard
1458 90cb9493 bellard
#elif defined(__s390__)
1459 90cb9493 bellard
1460 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1461 90cb9493 bellard
                       void *puc)
1462 90cb9493 bellard
{
1463 5a7b542b ths
    siginfo_t *info = pinfo;
1464 90cb9493 bellard
    struct ucontext *uc = puc;
1465 90cb9493 bellard
    unsigned long pc;
1466 90cb9493 bellard
    int is_write;
1467 3b46e624 ths
1468 90cb9493 bellard
    pc = uc->uc_mcontext.psw.addr;
1469 90cb9493 bellard
    /* XXX: compute is_write */
1470 90cb9493 bellard
    is_write = 0;
1471 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1472 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1473 c4b89d18 ths
}
1474 c4b89d18 ths
1475 c4b89d18 ths
#elif defined(__mips__)
1476 c4b89d18 ths
1477 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1478 c4b89d18 ths
                       void *puc)
1479 c4b89d18 ths
{
1480 9617efe8 ths
    siginfo_t *info = pinfo;
1481 c4b89d18 ths
    struct ucontext *uc = puc;
1482 c4b89d18 ths
    greg_t pc = uc->uc_mcontext.pc;
1483 c4b89d18 ths
    int is_write;
1484 3b46e624 ths
1485 c4b89d18 ths
    /* XXX: compute is_write */
1486 c4b89d18 ths
    is_write = 0;
1487 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1488 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1489 90cb9493 bellard
}
1490 90cb9493 bellard
1491 9de5e440 bellard
#else
1492 2b413144 bellard
1493 3fb2ded1 bellard
#error host CPU specific signal handler needed
1494 2b413144 bellard
1495 9de5e440 bellard
#endif
1496 67b915a5 bellard
1497 67b915a5 bellard
#endif /* !defined(CONFIG_SOFTMMU) */