Statistics
| Branch: | Revision:

root / cpu-exec.c @ 2c277908

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