Statistics
| Branch: | Revision:

root / cpu-exec.c @ 6dfd59d6

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