Statistics
| Branch: | Revision:

root / cpu-exec.c @ 1eec614b

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