Statistics
| Branch: | Revision:

root / cpu-exec.c @ e62b5b13

History | View | Annotate | Download (49.9 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 3fb2ded1 bellard
}
886 93ac68bc bellard
#elif defined(TARGET_SPARC)
887 93ac68bc bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
888 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
889 bf3e8bf1 bellard
                                    void *puc)
890 93ac68bc bellard
{
891 68016c62 bellard
    TranslationBlock *tb;
892 68016c62 bellard
    int ret;
893 68016c62 bellard
894 68016c62 bellard
    if (cpu_single_env)
895 68016c62 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
896 68016c62 bellard
#if defined(DEBUG_SIGNAL)
897 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
898 68016c62 bellard
           pc, address, is_write, *(unsigned long *)old_set);
899 68016c62 bellard
#endif
900 b453b70b bellard
    /* XXX: locking issue */
901 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
902 b453b70b bellard
        return 1;
903 b453b70b bellard
    }
904 68016c62 bellard
    /* see if it is an MMU fault */
905 6ebbf390 j_mayer
    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
906 68016c62 bellard
    if (ret < 0)
907 68016c62 bellard
        return 0; /* not an MMU fault */
908 68016c62 bellard
    if (ret == 0)
909 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
910 68016c62 bellard
    /* now we have a real cpu fault */
911 68016c62 bellard
    tb = tb_find_pc(pc);
912 68016c62 bellard
    if (tb) {
913 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
914 68016c62 bellard
           a virtual CPU fault */
915 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
916 68016c62 bellard
    }
917 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
918 68016c62 bellard
       do it (XXX: use sigsetjmp) */
919 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
920 68016c62 bellard
    cpu_loop_exit();
921 93ac68bc bellard
}
922 67867308 bellard
#elif defined (TARGET_PPC)
923 67867308 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
924 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
925 bf3e8bf1 bellard
                                    void *puc)
926 67867308 bellard
{
927 67867308 bellard
    TranslationBlock *tb;
928 ce09776b bellard
    int ret;
929 3b46e624 ths
930 67867308 bellard
    if (cpu_single_env)
931 67867308 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
932 67867308 bellard
#if defined(DEBUG_SIGNAL)
933 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
934 67867308 bellard
           pc, address, is_write, *(unsigned long *)old_set);
935 67867308 bellard
#endif
936 67867308 bellard
    /* XXX: locking issue */
937 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
938 67867308 bellard
        return 1;
939 67867308 bellard
    }
940 67867308 bellard
941 ce09776b bellard
    /* see if it is an MMU fault */
942 6ebbf390 j_mayer
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
943 ce09776b bellard
    if (ret < 0)
944 ce09776b bellard
        return 0; /* not an MMU fault */
945 ce09776b bellard
    if (ret == 0)
946 ce09776b bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
947 ce09776b bellard
948 67867308 bellard
    /* now we have a real cpu fault */
949 67867308 bellard
    tb = tb_find_pc(pc);
950 67867308 bellard
    if (tb) {
951 67867308 bellard
        /* the PC is inside the translated code. It means that we have
952 67867308 bellard
           a virtual CPU fault */
953 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, puc);
954 67867308 bellard
    }
955 ce09776b bellard
    if (ret == 1) {
956 67867308 bellard
#if 0
957 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
958 ce09776b bellard
               env->nip, env->error_code, tb);
959 67867308 bellard
#endif
960 67867308 bellard
    /* we restore the process signal mask as the sigreturn should
961 67867308 bellard
       do it (XXX: use sigsetjmp) */
962 bf3e8bf1 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
963 9fddaa0c bellard
        do_raise_exception_err(env->exception_index, env->error_code);
964 ce09776b bellard
    } else {
965 ce09776b bellard
        /* activate soft MMU for this block */
966 fbf9eeb3 bellard
        cpu_resume_from_signal(env, puc);
967 ce09776b bellard
    }
968 67867308 bellard
    /* never comes here */
969 e6e5906b pbrook
    return 1;
970 e6e5906b pbrook
}
971 e6e5906b pbrook
972 e6e5906b pbrook
#elif defined(TARGET_M68K)
973 e6e5906b pbrook
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
974 e6e5906b pbrook
                                    int is_write, sigset_t *old_set,
975 e6e5906b pbrook
                                    void *puc)
976 e6e5906b pbrook
{
977 e6e5906b pbrook
    TranslationBlock *tb;
978 e6e5906b pbrook
    int ret;
979 e6e5906b pbrook
980 e6e5906b pbrook
    if (cpu_single_env)
981 e6e5906b pbrook
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
982 e6e5906b pbrook
#if defined(DEBUG_SIGNAL)
983 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
984 e6e5906b pbrook
           pc, address, is_write, *(unsigned long *)old_set);
985 e6e5906b pbrook
#endif
986 e6e5906b pbrook
    /* XXX: locking issue */
987 e6e5906b pbrook
    if (is_write && page_unprotect(address, pc, puc)) {
988 e6e5906b pbrook
        return 1;
989 e6e5906b pbrook
    }
990 e6e5906b pbrook
    /* see if it is an MMU fault */
991 6ebbf390 j_mayer
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
992 e6e5906b pbrook
    if (ret < 0)
993 e6e5906b pbrook
        return 0; /* not an MMU fault */
994 e6e5906b pbrook
    if (ret == 0)
995 e6e5906b pbrook
        return 1; /* the MMU fault was handled without causing real CPU fault */
996 e6e5906b pbrook
    /* now we have a real cpu fault */
997 e6e5906b pbrook
    tb = tb_find_pc(pc);
998 e6e5906b pbrook
    if (tb) {
999 e6e5906b pbrook
        /* the PC is inside the translated code. It means that we have
1000 e6e5906b pbrook
           a virtual CPU fault */
1001 e6e5906b pbrook
        cpu_restore_state(tb, env, pc, puc);
1002 e6e5906b pbrook
    }
1003 e6e5906b pbrook
    /* we restore the process signal mask as the sigreturn should
1004 e6e5906b pbrook
       do it (XXX: use sigsetjmp) */
1005 e6e5906b pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
1006 e6e5906b pbrook
    cpu_loop_exit();
1007 e6e5906b pbrook
    /* never comes here */
1008 67867308 bellard
    return 1;
1009 67867308 bellard
}
1010 6af0bf9c bellard
1011 6af0bf9c bellard
#elif defined (TARGET_MIPS)
1012 6af0bf9c bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1013 6af0bf9c bellard
                                    int is_write, sigset_t *old_set,
1014 6af0bf9c bellard
                                    void *puc)
1015 6af0bf9c bellard
{
1016 6af0bf9c bellard
    TranslationBlock *tb;
1017 6af0bf9c bellard
    int ret;
1018 3b46e624 ths
1019 6af0bf9c bellard
    if (cpu_single_env)
1020 6af0bf9c bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1021 6af0bf9c bellard
#if defined(DEBUG_SIGNAL)
1022 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1023 6af0bf9c bellard
           pc, address, is_write, *(unsigned long *)old_set);
1024 6af0bf9c bellard
#endif
1025 6af0bf9c bellard
    /* XXX: locking issue */
1026 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1027 6af0bf9c bellard
        return 1;
1028 6af0bf9c bellard
    }
1029 6af0bf9c bellard
1030 6af0bf9c bellard
    /* see if it is an MMU fault */
1031 6ebbf390 j_mayer
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1032 6af0bf9c bellard
    if (ret < 0)
1033 6af0bf9c bellard
        return 0; /* not an MMU fault */
1034 6af0bf9c bellard
    if (ret == 0)
1035 6af0bf9c bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1036 6af0bf9c bellard
1037 6af0bf9c bellard
    /* now we have a real cpu fault */
1038 6af0bf9c bellard
    tb = tb_find_pc(pc);
1039 6af0bf9c bellard
    if (tb) {
1040 6af0bf9c bellard
        /* the PC is inside the translated code. It means that we have
1041 6af0bf9c bellard
           a virtual CPU fault */
1042 6af0bf9c bellard
        cpu_restore_state(tb, env, pc, puc);
1043 6af0bf9c bellard
    }
1044 6af0bf9c bellard
    if (ret == 1) {
1045 6af0bf9c bellard
#if 0
1046 5fafdf24 ths
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1047 1eb5207b ths
               env->PC, env->error_code, tb);
1048 6af0bf9c bellard
#endif
1049 6af0bf9c bellard
    /* we restore the process signal mask as the sigreturn should
1050 6af0bf9c bellard
       do it (XXX: use sigsetjmp) */
1051 6af0bf9c bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
1052 6af0bf9c bellard
        do_raise_exception_err(env->exception_index, env->error_code);
1053 6af0bf9c bellard
    } else {
1054 6af0bf9c bellard
        /* activate soft MMU for this block */
1055 6af0bf9c bellard
        cpu_resume_from_signal(env, puc);
1056 6af0bf9c bellard
    }
1057 6af0bf9c bellard
    /* never comes here */
1058 6af0bf9c bellard
    return 1;
1059 6af0bf9c bellard
}
1060 6af0bf9c bellard
1061 fdf9b3e8 bellard
#elif defined (TARGET_SH4)
1062 fdf9b3e8 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1063 fdf9b3e8 bellard
                                    int is_write, sigset_t *old_set,
1064 fdf9b3e8 bellard
                                    void *puc)
1065 fdf9b3e8 bellard
{
1066 fdf9b3e8 bellard
    TranslationBlock *tb;
1067 fdf9b3e8 bellard
    int ret;
1068 3b46e624 ths
1069 fdf9b3e8 bellard
    if (cpu_single_env)
1070 fdf9b3e8 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1071 fdf9b3e8 bellard
#if defined(DEBUG_SIGNAL)
1072 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1073 fdf9b3e8 bellard
           pc, address, is_write, *(unsigned long *)old_set);
1074 fdf9b3e8 bellard
#endif
1075 fdf9b3e8 bellard
    /* XXX: locking issue */
1076 fdf9b3e8 bellard
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1077 fdf9b3e8 bellard
        return 1;
1078 fdf9b3e8 bellard
    }
1079 fdf9b3e8 bellard
1080 fdf9b3e8 bellard
    /* see if it is an MMU fault */
1081 6ebbf390 j_mayer
    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1082 fdf9b3e8 bellard
    if (ret < 0)
1083 fdf9b3e8 bellard
        return 0; /* not an MMU fault */
1084 fdf9b3e8 bellard
    if (ret == 0)
1085 fdf9b3e8 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1086 fdf9b3e8 bellard
1087 fdf9b3e8 bellard
    /* now we have a real cpu fault */
1088 eddf68a6 j_mayer
    tb = tb_find_pc(pc);
1089 eddf68a6 j_mayer
    if (tb) {
1090 eddf68a6 j_mayer
        /* the PC is inside the translated code. It means that we have
1091 eddf68a6 j_mayer
           a virtual CPU fault */
1092 eddf68a6 j_mayer
        cpu_restore_state(tb, env, pc, puc);
1093 eddf68a6 j_mayer
    }
1094 eddf68a6 j_mayer
#if 0
1095 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1096 eddf68a6 j_mayer
               env->nip, env->error_code, tb);
1097 eddf68a6 j_mayer
#endif
1098 eddf68a6 j_mayer
    /* we restore the process signal mask as the sigreturn should
1099 eddf68a6 j_mayer
       do it (XXX: use sigsetjmp) */
1100 eddf68a6 j_mayer
    sigprocmask(SIG_SETMASK, old_set, NULL);
1101 eddf68a6 j_mayer
    cpu_loop_exit();
1102 eddf68a6 j_mayer
    /* never comes here */
1103 eddf68a6 j_mayer
    return 1;
1104 eddf68a6 j_mayer
}
1105 eddf68a6 j_mayer
1106 eddf68a6 j_mayer
#elif defined (TARGET_ALPHA)
1107 eddf68a6 j_mayer
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1108 eddf68a6 j_mayer
                                    int is_write, sigset_t *old_set,
1109 eddf68a6 j_mayer
                                    void *puc)
1110 eddf68a6 j_mayer
{
1111 eddf68a6 j_mayer
    TranslationBlock *tb;
1112 eddf68a6 j_mayer
    int ret;
1113 3b46e624 ths
1114 eddf68a6 j_mayer
    if (cpu_single_env)
1115 eddf68a6 j_mayer
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1116 eddf68a6 j_mayer
#if defined(DEBUG_SIGNAL)
1117 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1118 eddf68a6 j_mayer
           pc, address, is_write, *(unsigned long *)old_set);
1119 eddf68a6 j_mayer
#endif
1120 eddf68a6 j_mayer
    /* XXX: locking issue */
1121 eddf68a6 j_mayer
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1122 eddf68a6 j_mayer
        return 1;
1123 eddf68a6 j_mayer
    }
1124 eddf68a6 j_mayer
1125 eddf68a6 j_mayer
    /* see if it is an MMU fault */
1126 6ebbf390 j_mayer
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1127 eddf68a6 j_mayer
    if (ret < 0)
1128 eddf68a6 j_mayer
        return 0; /* not an MMU fault */
1129 eddf68a6 j_mayer
    if (ret == 0)
1130 eddf68a6 j_mayer
        return 1; /* the MMU fault was handled without causing real CPU fault */
1131 eddf68a6 j_mayer
1132 eddf68a6 j_mayer
    /* now we have a real cpu fault */
1133 fdf9b3e8 bellard
    tb = tb_find_pc(pc);
1134 fdf9b3e8 bellard
    if (tb) {
1135 fdf9b3e8 bellard
        /* the PC is inside the translated code. It means that we have
1136 fdf9b3e8 bellard
           a virtual CPU fault */
1137 fdf9b3e8 bellard
        cpu_restore_state(tb, env, pc, puc);
1138 fdf9b3e8 bellard
    }
1139 fdf9b3e8 bellard
#if 0
1140 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1141 fdf9b3e8 bellard
               env->nip, env->error_code, tb);
1142 fdf9b3e8 bellard
#endif
1143 fdf9b3e8 bellard
    /* we restore the process signal mask as the sigreturn should
1144 fdf9b3e8 bellard
       do it (XXX: use sigsetjmp) */
1145 355fb23d pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
1146 355fb23d pbrook
    cpu_loop_exit();
1147 fdf9b3e8 bellard
    /* never comes here */
1148 fdf9b3e8 bellard
    return 1;
1149 fdf9b3e8 bellard
}
1150 f1ccf904 ths
#elif defined (TARGET_CRIS)
1151 f1ccf904 ths
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1152 f1ccf904 ths
                                    int is_write, sigset_t *old_set,
1153 f1ccf904 ths
                                    void *puc)
1154 f1ccf904 ths
{
1155 f1ccf904 ths
    TranslationBlock *tb;
1156 f1ccf904 ths
    int ret;
1157 f1ccf904 ths
1158 f1ccf904 ths
    if (cpu_single_env)
1159 f1ccf904 ths
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1160 f1ccf904 ths
#if defined(DEBUG_SIGNAL)
1161 f1ccf904 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1162 f1ccf904 ths
           pc, address, is_write, *(unsigned long *)old_set);
1163 f1ccf904 ths
#endif
1164 f1ccf904 ths
    /* XXX: locking issue */
1165 f1ccf904 ths
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1166 f1ccf904 ths
        return 1;
1167 f1ccf904 ths
    }
1168 f1ccf904 ths
1169 f1ccf904 ths
    /* see if it is an MMU fault */
1170 6ebbf390 j_mayer
    ret = cpu_cris_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
1171 f1ccf904 ths
    if (ret < 0)
1172 f1ccf904 ths
        return 0; /* not an MMU fault */
1173 f1ccf904 ths
    if (ret == 0)
1174 f1ccf904 ths
        return 1; /* the MMU fault was handled without causing real CPU fault */
1175 f1ccf904 ths
1176 f1ccf904 ths
    /* now we have a real cpu fault */
1177 f1ccf904 ths
    tb = tb_find_pc(pc);
1178 f1ccf904 ths
    if (tb) {
1179 f1ccf904 ths
        /* the PC is inside the translated code. It means that we have
1180 f1ccf904 ths
           a virtual CPU fault */
1181 f1ccf904 ths
        cpu_restore_state(tb, env, pc, puc);
1182 f1ccf904 ths
    }
1183 f1ccf904 ths
    /* we restore the process signal mask as the sigreturn should
1184 f1ccf904 ths
       do it (XXX: use sigsetjmp) */
1185 f1ccf904 ths
    sigprocmask(SIG_SETMASK, old_set, NULL);
1186 f1ccf904 ths
    cpu_loop_exit();
1187 f1ccf904 ths
    /* never comes here */
1188 f1ccf904 ths
    return 1;
1189 f1ccf904 ths
}
1190 f1ccf904 ths
1191 e4533c7a bellard
#else
1192 e4533c7a bellard
#error unsupported target CPU
1193 e4533c7a bellard
#endif
1194 9de5e440 bellard
1195 2b413144 bellard
#if defined(__i386__)
1196 2b413144 bellard
1197 d8ecc0b9 bellard
#if defined(__APPLE__)
1198 d8ecc0b9 bellard
# include <sys/ucontext.h>
1199 d8ecc0b9 bellard
1200 d8ecc0b9 bellard
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1201 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1202 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1203 d8ecc0b9 bellard
#else
1204 d8ecc0b9 bellard
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1205 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1206 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1207 d8ecc0b9 bellard
#endif
1208 d8ecc0b9 bellard
1209 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1210 e4533c7a bellard
                       void *puc)
1211 9de5e440 bellard
{
1212 5a7b542b ths
    siginfo_t *info = pinfo;
1213 9de5e440 bellard
    struct ucontext *uc = puc;
1214 9de5e440 bellard
    unsigned long pc;
1215 bf3e8bf1 bellard
    int trapno;
1216 97eb5b14 bellard
1217 d691f669 bellard
#ifndef REG_EIP
1218 d691f669 bellard
/* for glibc 2.1 */
1219 fd6ce8f6 bellard
#define REG_EIP    EIP
1220 fd6ce8f6 bellard
#define REG_ERR    ERR
1221 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
1222 d691f669 bellard
#endif
1223 d8ecc0b9 bellard
    pc = EIP_sig(uc);
1224 d8ecc0b9 bellard
    trapno = TRAP_sig(uc);
1225 ec6338ba bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1226 ec6338ba bellard
                             trapno == 0xe ?
1227 ec6338ba bellard
                             (ERROR_sig(uc) >> 1) & 1 : 0,
1228 ec6338ba bellard
                             &uc->uc_sigmask, puc);
1229 2b413144 bellard
}
1230 2b413144 bellard
1231 bc51c5c9 bellard
#elif defined(__x86_64__)
1232 bc51c5c9 bellard
1233 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo,
1234 bc51c5c9 bellard
                       void *puc)
1235 bc51c5c9 bellard
{
1236 5a7b542b ths
    siginfo_t *info = pinfo;
1237 bc51c5c9 bellard
    struct ucontext *uc = puc;
1238 bc51c5c9 bellard
    unsigned long pc;
1239 bc51c5c9 bellard
1240 bc51c5c9 bellard
    pc = uc->uc_mcontext.gregs[REG_RIP];
1241 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1242 5fafdf24 ths
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1243 bc51c5c9 bellard
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1244 bc51c5c9 bellard
                             &uc->uc_sigmask, puc);
1245 bc51c5c9 bellard
}
1246 bc51c5c9 bellard
1247 83fb7adf bellard
#elif defined(__powerpc__)
1248 2b413144 bellard
1249 83fb7adf bellard
/***********************************************************************
1250 83fb7adf bellard
 * signal context platform-specific definitions
1251 83fb7adf bellard
 * From Wine
1252 83fb7adf bellard
 */
1253 83fb7adf bellard
#ifdef linux
1254 83fb7adf bellard
/* All Registers access - only for local access */
1255 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1256 83fb7adf bellard
/* Gpr Registers access  */
1257 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1258 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1259 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1260 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1261 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1262 83fb7adf bellard
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1263 83fb7adf bellard
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1264 83fb7adf bellard
/* Float Registers access  */
1265 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1266 83fb7adf bellard
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1267 83fb7adf bellard
/* Exception Registers access */
1268 83fb7adf bellard
# define DAR_sig(context)                        REG_sig(dar, context)
1269 83fb7adf bellard
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1270 83fb7adf bellard
# define TRAP_sig(context)                        REG_sig(trap, context)
1271 83fb7adf bellard
#endif /* linux */
1272 83fb7adf bellard
1273 83fb7adf bellard
#ifdef __APPLE__
1274 83fb7adf bellard
# include <sys/ucontext.h>
1275 83fb7adf bellard
typedef struct ucontext SIGCONTEXT;
1276 83fb7adf bellard
/* All Registers access - only for local access */
1277 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1278 83fb7adf bellard
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1279 83fb7adf bellard
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1280 83fb7adf bellard
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1281 83fb7adf bellard
/* Gpr Registers access */
1282 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1283 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1284 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1285 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)
1286 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1287 83fb7adf bellard
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1288 83fb7adf bellard
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1289 83fb7adf bellard
/* Float Registers access */
1290 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1291 83fb7adf bellard
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1292 83fb7adf bellard
/* Exception Registers access */
1293 83fb7adf bellard
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1294 83fb7adf bellard
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1295 83fb7adf bellard
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1296 83fb7adf bellard
#endif /* __APPLE__ */
1297 83fb7adf bellard
1298 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1299 e4533c7a bellard
                       void *puc)
1300 2b413144 bellard
{
1301 5a7b542b ths
    siginfo_t *info = pinfo;
1302 25eb4484 bellard
    struct ucontext *uc = puc;
1303 25eb4484 bellard
    unsigned long pc;
1304 25eb4484 bellard
    int is_write;
1305 25eb4484 bellard
1306 83fb7adf bellard
    pc = IAR_sig(uc);
1307 25eb4484 bellard
    is_write = 0;
1308 25eb4484 bellard
#if 0
1309 25eb4484 bellard
    /* ppc 4xx case */
1310 83fb7adf bellard
    if (DSISR_sig(uc) & 0x00800000)
1311 25eb4484 bellard
        is_write = 1;
1312 25eb4484 bellard
#else
1313 83fb7adf bellard
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1314 25eb4484 bellard
        is_write = 1;
1315 25eb4484 bellard
#endif
1316 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1317 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1318 2b413144 bellard
}
1319 2b413144 bellard
1320 2f87c607 bellard
#elif defined(__alpha__)
1321 2f87c607 bellard
1322 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1323 2f87c607 bellard
                           void *puc)
1324 2f87c607 bellard
{
1325 5a7b542b ths
    siginfo_t *info = pinfo;
1326 2f87c607 bellard
    struct ucontext *uc = puc;
1327 2f87c607 bellard
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1328 2f87c607 bellard
    uint32_t insn = *pc;
1329 2f87c607 bellard
    int is_write = 0;
1330 2f87c607 bellard
1331 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1332 2f87c607 bellard
    switch (insn >> 26) {
1333 2f87c607 bellard
    case 0x0d: // stw
1334 2f87c607 bellard
    case 0x0e: // stb
1335 2f87c607 bellard
    case 0x0f: // stq_u
1336 2f87c607 bellard
    case 0x24: // stf
1337 2f87c607 bellard
    case 0x25: // stg
1338 2f87c607 bellard
    case 0x26: // sts
1339 2f87c607 bellard
    case 0x27: // stt
1340 2f87c607 bellard
    case 0x2c: // stl
1341 2f87c607 bellard
    case 0x2d: // stq
1342 2f87c607 bellard
    case 0x2e: // stl_c
1343 2f87c607 bellard
    case 0x2f: // stq_c
1344 2f87c607 bellard
        is_write = 1;
1345 2f87c607 bellard
    }
1346 2f87c607 bellard
1347 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1348 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1349 2f87c607 bellard
}
1350 8c6939c0 bellard
#elif defined(__sparc__)
1351 8c6939c0 bellard
1352 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1353 e4533c7a bellard
                       void *puc)
1354 8c6939c0 bellard
{
1355 5a7b542b ths
    siginfo_t *info = pinfo;
1356 8c6939c0 bellard
    uint32_t *regs = (uint32_t *)(info + 1);
1357 8c6939c0 bellard
    void *sigmask = (regs + 20);
1358 8c6939c0 bellard
    unsigned long pc;
1359 8c6939c0 bellard
    int is_write;
1360 8c6939c0 bellard
    uint32_t insn;
1361 3b46e624 ths
1362 8c6939c0 bellard
    /* XXX: is there a standard glibc define ? */
1363 8c6939c0 bellard
    pc = regs[1];
1364 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1365 8c6939c0 bellard
    is_write = 0;
1366 8c6939c0 bellard
    insn = *(uint32_t *)pc;
1367 8c6939c0 bellard
    if ((insn >> 30) == 3) {
1368 8c6939c0 bellard
      switch((insn >> 19) & 0x3f) {
1369 8c6939c0 bellard
      case 0x05: // stb
1370 8c6939c0 bellard
      case 0x06: // sth
1371 8c6939c0 bellard
      case 0x04: // st
1372 8c6939c0 bellard
      case 0x07: // std
1373 8c6939c0 bellard
      case 0x24: // stf
1374 8c6939c0 bellard
      case 0x27: // stdf
1375 8c6939c0 bellard
      case 0x25: // stfsr
1376 8c6939c0 bellard
        is_write = 1;
1377 8c6939c0 bellard
        break;
1378 8c6939c0 bellard
      }
1379 8c6939c0 bellard
    }
1380 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1381 bf3e8bf1 bellard
                             is_write, sigmask, NULL);
1382 8c6939c0 bellard
}
1383 8c6939c0 bellard
1384 8c6939c0 bellard
#elif defined(__arm__)
1385 8c6939c0 bellard
1386 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1387 e4533c7a bellard
                       void *puc)
1388 8c6939c0 bellard
{
1389 5a7b542b ths
    siginfo_t *info = pinfo;
1390 8c6939c0 bellard
    struct ucontext *uc = puc;
1391 8c6939c0 bellard
    unsigned long pc;
1392 8c6939c0 bellard
    int is_write;
1393 3b46e624 ths
1394 8c6939c0 bellard
    pc = uc->uc_mcontext.gregs[R15];
1395 8c6939c0 bellard
    /* XXX: compute is_write */
1396 8c6939c0 bellard
    is_write = 0;
1397 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1398 8c6939c0 bellard
                             is_write,
1399 f3a9676a pbrook
                             &uc->uc_sigmask, puc);
1400 8c6939c0 bellard
}
1401 8c6939c0 bellard
1402 38e584a0 bellard
#elif defined(__mc68000)
1403 38e584a0 bellard
1404 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1405 38e584a0 bellard
                       void *puc)
1406 38e584a0 bellard
{
1407 5a7b542b ths
    siginfo_t *info = pinfo;
1408 38e584a0 bellard
    struct ucontext *uc = puc;
1409 38e584a0 bellard
    unsigned long pc;
1410 38e584a0 bellard
    int is_write;
1411 3b46e624 ths
1412 38e584a0 bellard
    pc = uc->uc_mcontext.gregs[16];
1413 38e584a0 bellard
    /* XXX: compute is_write */
1414 38e584a0 bellard
    is_write = 0;
1415 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1416 38e584a0 bellard
                             is_write,
1417 bf3e8bf1 bellard
                             &uc->uc_sigmask, puc);
1418 38e584a0 bellard
}
1419 38e584a0 bellard
1420 b8076a74 bellard
#elif defined(__ia64)
1421 b8076a74 bellard
1422 b8076a74 bellard
#ifndef __ISR_VALID
1423 b8076a74 bellard
  /* This ought to be in <bits/siginfo.h>... */
1424 b8076a74 bellard
# define __ISR_VALID        1
1425 b8076a74 bellard
#endif
1426 b8076a74 bellard
1427 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1428 b8076a74 bellard
{
1429 5a7b542b ths
    siginfo_t *info = pinfo;
1430 b8076a74 bellard
    struct ucontext *uc = puc;
1431 b8076a74 bellard
    unsigned long ip;
1432 b8076a74 bellard
    int is_write = 0;
1433 b8076a74 bellard
1434 b8076a74 bellard
    ip = uc->uc_mcontext.sc_ip;
1435 b8076a74 bellard
    switch (host_signum) {
1436 b8076a74 bellard
      case SIGILL:
1437 b8076a74 bellard
      case SIGFPE:
1438 b8076a74 bellard
      case SIGSEGV:
1439 b8076a74 bellard
      case SIGBUS:
1440 b8076a74 bellard
      case SIGTRAP:
1441 fd4a43e4 bellard
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1442 b8076a74 bellard
              /* ISR.W (write-access) is bit 33:  */
1443 b8076a74 bellard
              is_write = (info->si_isr >> 33) & 1;
1444 b8076a74 bellard
          break;
1445 b8076a74 bellard
1446 b8076a74 bellard
      default:
1447 b8076a74 bellard
          break;
1448 b8076a74 bellard
    }
1449 b8076a74 bellard
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1450 b8076a74 bellard
                             is_write,
1451 b8076a74 bellard
                             &uc->uc_sigmask, puc);
1452 b8076a74 bellard
}
1453 b8076a74 bellard
1454 90cb9493 bellard
#elif defined(__s390__)
1455 90cb9493 bellard
1456 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1457 90cb9493 bellard
                       void *puc)
1458 90cb9493 bellard
{
1459 5a7b542b ths
    siginfo_t *info = pinfo;
1460 90cb9493 bellard
    struct ucontext *uc = puc;
1461 90cb9493 bellard
    unsigned long pc;
1462 90cb9493 bellard
    int is_write;
1463 3b46e624 ths
1464 90cb9493 bellard
    pc = uc->uc_mcontext.psw.addr;
1465 90cb9493 bellard
    /* XXX: compute is_write */
1466 90cb9493 bellard
    is_write = 0;
1467 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1468 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1469 c4b89d18 ths
}
1470 c4b89d18 ths
1471 c4b89d18 ths
#elif defined(__mips__)
1472 c4b89d18 ths
1473 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1474 c4b89d18 ths
                       void *puc)
1475 c4b89d18 ths
{
1476 9617efe8 ths
    siginfo_t *info = pinfo;
1477 c4b89d18 ths
    struct ucontext *uc = puc;
1478 c4b89d18 ths
    greg_t pc = uc->uc_mcontext.pc;
1479 c4b89d18 ths
    int is_write;
1480 3b46e624 ths
1481 c4b89d18 ths
    /* XXX: compute is_write */
1482 c4b89d18 ths
    is_write = 0;
1483 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1484 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1485 90cb9493 bellard
}
1486 90cb9493 bellard
1487 9de5e440 bellard
#else
1488 2b413144 bellard
1489 3fb2ded1 bellard
#error host CPU specific signal handler needed
1490 2b413144 bellard
1491 9de5e440 bellard
#endif
1492 67b915a5 bellard
1493 67b915a5 bellard
#endif /* !defined(CONFIG_SOFTMMU) */