Statistics
| Branch: | Revision:

root / cpu-exec.c @ 562183de

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