Statistics
| Branch: | Revision:

root / cpu-exec.c @ 42bc608b

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