Statistics
| Branch: | Revision:

root / cpu-exec.c @ 474ea849

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