Statistics
| Branch: | Revision:

root / cpu-exec.c @ f4918804

History | View | Annotate | Download (41.3 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 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_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 f0667e66 Juan Quintela
//#define CONFIG_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 72cf2d4f Blue Swirl
        QTAILQ_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 10ec5117 Alexander Graf
#elif defined(TARGET_S390X)
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 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_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 9df217a3 bellard
326 7ba1e619 aliguori
            if (kvm_enabled()) {
327 becfc390 aliguori
                kvm_cpu_exec(env);
328 becfc390 aliguori
                longjmp(env->jmp_env, 1);
329 7ba1e619 aliguori
            }
330 7ba1e619 aliguori
331 b5fc09ae blueswir1
            next_tb = 0; /* force lookup of first TB */
332 3fb2ded1 bellard
            for(;;) {
333 68a79315 bellard
                interrupt_request = env->interrupt_request;
334 e1638bd8 malc
                if (unlikely(interrupt_request)) {
335 e1638bd8 malc
                    if (unlikely(env->singlestep_enabled & SSTEP_NOIRQ)) {
336 e1638bd8 malc
                        /* Mask out external interrupts for this step. */
337 e1638bd8 malc
                        interrupt_request &= ~(CPU_INTERRUPT_HARD |
338 e1638bd8 malc
                                               CPU_INTERRUPT_FIQ |
339 e1638bd8 malc
                                               CPU_INTERRUPT_SMI |
340 e1638bd8 malc
                                               CPU_INTERRUPT_NMI);
341 e1638bd8 malc
                    }
342 6658ffb8 pbrook
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
343 6658ffb8 pbrook
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
344 6658ffb8 pbrook
                        env->exception_index = EXCP_DEBUG;
345 6658ffb8 pbrook
                        cpu_loop_exit();
346 6658ffb8 pbrook
                    }
347 a90b7318 balrog
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
348 b779e29e Edgar E. Iglesias
    defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) || \
349 b779e29e Edgar E. Iglesias
    defined(TARGET_MICROBLAZE)
350 a90b7318 balrog
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
351 a90b7318 balrog
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
352 a90b7318 balrog
                        env->halted = 1;
353 a90b7318 balrog
                        env->exception_index = EXCP_HLT;
354 a90b7318 balrog
                        cpu_loop_exit();
355 a90b7318 balrog
                    }
356 a90b7318 balrog
#endif
357 68a79315 bellard
#if defined(TARGET_I386)
358 b09ea7d5 Gleb Natapov
                    if (interrupt_request & CPU_INTERRUPT_INIT) {
359 b09ea7d5 Gleb Natapov
                            svm_check_intercept(SVM_EXIT_INIT);
360 b09ea7d5 Gleb Natapov
                            do_cpu_init(env);
361 b09ea7d5 Gleb Natapov
                            env->exception_index = EXCP_HALTED;
362 b09ea7d5 Gleb Natapov
                            cpu_loop_exit();
363 b09ea7d5 Gleb Natapov
                    } else if (interrupt_request & CPU_INTERRUPT_SIPI) {
364 b09ea7d5 Gleb Natapov
                            do_cpu_sipi(env);
365 b09ea7d5 Gleb Natapov
                    } else if (env->hflags2 & HF2_GIF_MASK) {
366 db620f46 bellard
                        if ((interrupt_request & CPU_INTERRUPT_SMI) &&
367 db620f46 bellard
                            !(env->hflags & HF_SMM_MASK)) {
368 db620f46 bellard
                            svm_check_intercept(SVM_EXIT_SMI);
369 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_SMI;
370 db620f46 bellard
                            do_smm_enter();
371 db620f46 bellard
                            next_tb = 0;
372 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_NMI) &&
373 db620f46 bellard
                                   !(env->hflags2 & HF2_NMI_MASK)) {
374 db620f46 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_NMI;
375 db620f46 bellard
                            env->hflags2 |= HF2_NMI_MASK;
376 db620f46 bellard
                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
377 db620f46 bellard
                            next_tb = 0;
378 79c4f6b0 Huang Ying
                        } else if (interrupt_request & CPU_INTERRUPT_MCE) {
379 79c4f6b0 Huang Ying
                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
380 79c4f6b0 Huang Ying
                            do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
381 79c4f6b0 Huang Ying
                            next_tb = 0;
382 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
383 db620f46 bellard
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
384 db620f46 bellard
                                     (env->hflags2 & HF2_HIF_MASK)) ||
385 db620f46 bellard
                                    (!(env->hflags2 & HF2_VINTR_MASK) && 
386 db620f46 bellard
                                     (env->eflags & IF_MASK && 
387 db620f46 bellard
                                      !(env->hflags & HF_INHIBIT_IRQ_MASK))))) {
388 db620f46 bellard
                            int intno;
389 db620f46 bellard
                            svm_check_intercept(SVM_EXIT_INTR);
390 db620f46 bellard
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
391 db620f46 bellard
                            intno = cpu_get_pic_interrupt(env);
392 93fcfe39 aliguori
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
393 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
394 9ddff3d2 blueswir1
#undef env
395 9ddff3d2 blueswir1
                    env = cpu_single_env;
396 9ddff3d2 blueswir1
#define env cpu_single_env
397 9ddff3d2 blueswir1
#endif
398 db620f46 bellard
                            do_interrupt(intno, 0, 0, 0, 1);
399 db620f46 bellard
                            /* ensure that no TB jump will be modified as
400 db620f46 bellard
                               the program flow was changed */
401 db620f46 bellard
                            next_tb = 0;
402 0573fbfc ths
#if !defined(CONFIG_USER_ONLY)
403 db620f46 bellard
                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
404 db620f46 bellard
                                   (env->eflags & IF_MASK) && 
405 db620f46 bellard
                                   !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
406 db620f46 bellard
                            int intno;
407 db620f46 bellard
                            /* FIXME: this should respect TPR */
408 db620f46 bellard
                            svm_check_intercept(SVM_EXIT_VINTR);
409 db620f46 bellard
                            intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
410 93fcfe39 aliguori
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing virtual hardware INT=0x%02x\n", intno);
411 db620f46 bellard
                            do_interrupt(intno, 0, 0, 0, 1);
412 d40c54d6 aurel32
                            env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
413 db620f46 bellard
                            next_tb = 0;
414 0573fbfc ths
#endif
415 db620f46 bellard
                        }
416 68a79315 bellard
                    }
417 ce09776b bellard
#elif defined(TARGET_PPC)
418 9fddaa0c bellard
#if 0
419 9fddaa0c bellard
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
420 d84bda46 Blue Swirl
                        cpu_reset(env);
421 9fddaa0c bellard
                    }
422 9fddaa0c bellard
#endif
423 47103572 j_mayer
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
424 e9df014c j_mayer
                        ppc_hw_interrupt(env);
425 e9df014c j_mayer
                        if (env->pending_interrupts == 0)
426 e9df014c j_mayer
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
427 b5fc09ae blueswir1
                        next_tb = 0;
428 ce09776b bellard
                    }
429 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
430 b779e29e Edgar E. Iglesias
                    if ((interrupt_request & CPU_INTERRUPT_HARD)
431 b779e29e Edgar E. Iglesias
                        && (env->sregs[SR_MSR] & MSR_IE)
432 b779e29e Edgar E. Iglesias
                        && !(env->sregs[SR_MSR] & (MSR_EIP | MSR_BIP))
433 b779e29e Edgar E. Iglesias
                        && !(env->iflags & (D_FLAG | IMM_FLAG))) {
434 b779e29e Edgar E. Iglesias
                        env->exception_index = EXCP_IRQ;
435 b779e29e Edgar E. Iglesias
                        do_interrupt(env);
436 b779e29e Edgar E. Iglesias
                        next_tb = 0;
437 b779e29e Edgar E. Iglesias
                    }
438 6af0bf9c bellard
#elif defined(TARGET_MIPS)
439 6af0bf9c bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
440 24c7b0e3 ths
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
441 6af0bf9c bellard
                        (env->CP0_Status & (1 << CP0St_IE)) &&
442 24c7b0e3 ths
                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
443 24c7b0e3 ths
                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
444 6af0bf9c bellard
                        !(env->hflags & MIPS_HFLAG_DM)) {
445 6af0bf9c bellard
                        /* Raise it */
446 6af0bf9c bellard
                        env->exception_index = EXCP_EXT_INTERRUPT;
447 6af0bf9c bellard
                        env->error_code = 0;
448 6af0bf9c bellard
                        do_interrupt(env);
449 b5fc09ae blueswir1
                        next_tb = 0;
450 6af0bf9c bellard
                    }
451 e95c8d51 bellard
#elif defined(TARGET_SPARC)
452 66321a11 bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
453 5210977a Igor Kovalenko
                        cpu_interrupts_enabled(env)) {
454 66321a11 bellard
                        int pil = env->interrupt_index & 15;
455 66321a11 bellard
                        int type = env->interrupt_index & 0xf0;
456 66321a11 bellard
457 66321a11 bellard
                        if (((type == TT_EXTINT) &&
458 66321a11 bellard
                             (pil == 15 || pil > env->psrpil)) ||
459 66321a11 bellard
                            type != TT_EXTINT) {
460 66321a11 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
461 f2bc7e7f blueswir1
                            env->exception_index = env->interrupt_index;
462 f2bc7e7f blueswir1
                            do_interrupt(env);
463 66321a11 bellard
                            env->interrupt_index = 0;
464 b5fc09ae blueswir1
                        next_tb = 0;
465 66321a11 bellard
                        }
466 e95c8d51 bellard
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
467 e95c8d51 bellard
                        //do_interrupt(0, 0, 0, 0, 0);
468 e95c8d51 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
469 a90b7318 balrog
                    }
470 b5ff1b31 bellard
#elif defined(TARGET_ARM)
471 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_FIQ
472 b5ff1b31 bellard
                        && !(env->uncached_cpsr & CPSR_F)) {
473 b5ff1b31 bellard
                        env->exception_index = EXCP_FIQ;
474 b5ff1b31 bellard
                        do_interrupt(env);
475 b5fc09ae blueswir1
                        next_tb = 0;
476 b5ff1b31 bellard
                    }
477 9ee6e8bb pbrook
                    /* ARMv7-M interrupt return works by loading a magic value
478 9ee6e8bb pbrook
                       into the PC.  On real hardware the load causes the
479 9ee6e8bb pbrook
                       return to occur.  The qemu implementation performs the
480 9ee6e8bb pbrook
                       jump normally, then does the exception return when the
481 9ee6e8bb pbrook
                       CPU tries to execute code at the magic address.
482 9ee6e8bb pbrook
                       This will cause the magic PC value to be pushed to
483 9ee6e8bb pbrook
                       the stack if an interrupt occured at the wrong time.
484 9ee6e8bb pbrook
                       We avoid this by disabling interrupts when
485 9ee6e8bb pbrook
                       pc contains a magic address.  */
486 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_HARD
487 9ee6e8bb pbrook
                        && ((IS_M(env) && env->regs[15] < 0xfffffff0)
488 9ee6e8bb pbrook
                            || !(env->uncached_cpsr & CPSR_I))) {
489 b5ff1b31 bellard
                        env->exception_index = EXCP_IRQ;
490 b5ff1b31 bellard
                        do_interrupt(env);
491 b5fc09ae blueswir1
                        next_tb = 0;
492 b5ff1b31 bellard
                    }
493 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
494 e96e2044 ths
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
495 e96e2044 ths
                        do_interrupt(env);
496 b5fc09ae blueswir1
                        next_tb = 0;
497 e96e2044 ths
                    }
498 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
499 eddf68a6 j_mayer
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
500 eddf68a6 j_mayer
                        do_interrupt(env);
501 b5fc09ae blueswir1
                        next_tb = 0;
502 eddf68a6 j_mayer
                    }
503 f1ccf904 ths
#elif defined(TARGET_CRIS)
504 1b1a38b0 edgar_igl
                    if (interrupt_request & CPU_INTERRUPT_HARD
505 1b1a38b0 edgar_igl
                        && (env->pregs[PR_CCS] & I_FLAG)) {
506 1b1a38b0 edgar_igl
                        env->exception_index = EXCP_IRQ;
507 1b1a38b0 edgar_igl
                        do_interrupt(env);
508 1b1a38b0 edgar_igl
                        next_tb = 0;
509 1b1a38b0 edgar_igl
                    }
510 1b1a38b0 edgar_igl
                    if (interrupt_request & CPU_INTERRUPT_NMI
511 1b1a38b0 edgar_igl
                        && (env->pregs[PR_CCS] & M_FLAG)) {
512 1b1a38b0 edgar_igl
                        env->exception_index = EXCP_NMI;
513 f1ccf904 ths
                        do_interrupt(env);
514 b5fc09ae blueswir1
                        next_tb = 0;
515 f1ccf904 ths
                    }
516 0633879f pbrook
#elif defined(TARGET_M68K)
517 0633879f pbrook
                    if (interrupt_request & CPU_INTERRUPT_HARD
518 0633879f pbrook
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
519 0633879f pbrook
                            < env->pending_level) {
520 0633879f pbrook
                        /* Real hardware gets the interrupt vector via an
521 0633879f pbrook
                           IACK cycle at this point.  Current emulated
522 0633879f pbrook
                           hardware doesn't rely on this, so we
523 0633879f pbrook
                           provide/save the vector when the interrupt is
524 0633879f pbrook
                           first signalled.  */
525 0633879f pbrook
                        env->exception_index = env->pending_vector;
526 0633879f pbrook
                        do_interrupt(1);
527 b5fc09ae blueswir1
                        next_tb = 0;
528 0633879f pbrook
                    }
529 68a79315 bellard
#endif
530 9d05095e bellard
                   /* Don't use the cached interupt_request value,
531 9d05095e bellard
                      do_interrupt may have updated the EXITTB flag. */
532 b5ff1b31 bellard
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
533 bf3e8bf1 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
534 bf3e8bf1 bellard
                        /* ensure that no TB jump will be modified as
535 bf3e8bf1 bellard
                           the program flow was changed */
536 b5fc09ae blueswir1
                        next_tb = 0;
537 bf3e8bf1 bellard
                    }
538 be214e6c aurel32
                }
539 be214e6c aurel32
                if (unlikely(env->exit_request)) {
540 be214e6c aurel32
                    env->exit_request = 0;
541 be214e6c aurel32
                    env->exception_index = EXCP_INTERRUPT;
542 be214e6c aurel32
                    cpu_loop_exit();
543 3fb2ded1 bellard
                }
544 f0667e66 Juan Quintela
#ifdef CONFIG_DEBUG_EXEC
545 8fec2b8c aliguori
                if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
546 3fb2ded1 bellard
                    /* restore flags in standard format */
547 ecb644f4 ths
                    regs_to_env();
548 ecb644f4 ths
#if defined(TARGET_I386)
549 a7812ae4 pbrook
                    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
550 93fcfe39 aliguori
                    log_cpu_state(env, X86_DUMP_CCOP);
551 3fb2ded1 bellard
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
552 e4533c7a bellard
#elif defined(TARGET_ARM)
553 93fcfe39 aliguori
                    log_cpu_state(env, 0);
554 93ac68bc bellard
#elif defined(TARGET_SPARC)
555 93fcfe39 aliguori
                    log_cpu_state(env, 0);
556 67867308 bellard
#elif defined(TARGET_PPC)
557 93fcfe39 aliguori
                    log_cpu_state(env, 0);
558 e6e5906b pbrook
#elif defined(TARGET_M68K)
559 e6e5906b pbrook
                    cpu_m68k_flush_flags(env, env->cc_op);
560 e6e5906b pbrook
                    env->cc_op = CC_OP_FLAGS;
561 e6e5906b pbrook
                    env->sr = (env->sr & 0xffe0)
562 e6e5906b pbrook
                              | env->cc_dest | (env->cc_x << 4);
563 93fcfe39 aliguori
                    log_cpu_state(env, 0);
564 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
565 b779e29e Edgar E. Iglesias
                    log_cpu_state(env, 0);
566 6af0bf9c bellard
#elif defined(TARGET_MIPS)
567 93fcfe39 aliguori
                    log_cpu_state(env, 0);
568 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
569 93fcfe39 aliguori
                    log_cpu_state(env, 0);
570 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
571 93fcfe39 aliguori
                    log_cpu_state(env, 0);
572 f1ccf904 ths
#elif defined(TARGET_CRIS)
573 93fcfe39 aliguori
                    log_cpu_state(env, 0);
574 e4533c7a bellard
#else
575 5fafdf24 ths
#error unsupported target CPU
576 e4533c7a bellard
#endif
577 3fb2ded1 bellard
                }
578 7d13299d bellard
#endif
579 d5975363 pbrook
                spin_lock(&tb_lock);
580 8a40a180 bellard
                tb = tb_find_fast();
581 d5975363 pbrook
                /* Note: we do it here to avoid a gcc bug on Mac OS X when
582 d5975363 pbrook
                   doing it in tb_find_slow */
583 d5975363 pbrook
                if (tb_invalidated_flag) {
584 d5975363 pbrook
                    /* as some TB could have been invalidated because
585 d5975363 pbrook
                       of memory exceptions while generating the code, we
586 d5975363 pbrook
                       must recompute the hash index here */
587 d5975363 pbrook
                    next_tb = 0;
588 2e70f6ef pbrook
                    tb_invalidated_flag = 0;
589 d5975363 pbrook
                }
590 f0667e66 Juan Quintela
#ifdef CONFIG_DEBUG_EXEC
591 93fcfe39 aliguori
                qemu_log_mask(CPU_LOG_EXEC, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
592 93fcfe39 aliguori
                             (long)tb->tc_ptr, tb->pc,
593 93fcfe39 aliguori
                             lookup_symbol(tb->pc));
594 9d27abd9 bellard
#endif
595 8a40a180 bellard
                /* see if we can patch the calling TB. When the TB
596 8a40a180 bellard
                   spans two pages, we cannot safely do a direct
597 8a40a180 bellard
                   jump. */
598 c27004ec bellard
                {
599 4a1418e0 Anthony Liguori
                    if (next_tb != 0 && tb->page_addr[1] == -1) {
600 b5fc09ae blueswir1
                    tb_add_jump((TranslationBlock *)(next_tb & ~3), next_tb & 3, tb);
601 3fb2ded1 bellard
                }
602 c27004ec bellard
                }
603 d5975363 pbrook
                spin_unlock(&tb_lock);
604 83479e77 bellard
                env->current_tb = tb;
605 55e8b85e malc
606 55e8b85e malc
                /* cpu_interrupt might be called while translating the
607 55e8b85e malc
                   TB, but before it is linked into a potentially
608 55e8b85e malc
                   infinite loop and becomes env->current_tb. Avoid
609 55e8b85e malc
                   starting execution if there is a pending interrupt. */
610 be214e6c aurel32
                if (unlikely (env->exit_request))
611 55e8b85e malc
                    env->current_tb = NULL;
612 55e8b85e malc
613 2e70f6ef pbrook
                while (env->current_tb) {
614 2e70f6ef pbrook
                    tc_ptr = tb->tc_ptr;
615 3fb2ded1 bellard
                /* execute the generated code */
616 dfe5fff3 Juan Quintela
#if defined(__sparc__) && !defined(CONFIG_SOLARIS)
617 572a9d4a blueswir1
#undef env
618 2e70f6ef pbrook
                    env = cpu_single_env;
619 572a9d4a blueswir1
#define env cpu_single_env
620 572a9d4a blueswir1
#endif
621 2e70f6ef pbrook
                    next_tb = tcg_qemu_tb_exec(tc_ptr);
622 2e70f6ef pbrook
                    env->current_tb = NULL;
623 2e70f6ef pbrook
                    if ((next_tb & 3) == 2) {
624 bf20dc07 ths
                        /* Instruction counter expired.  */
625 2e70f6ef pbrook
                        int insns_left;
626 2e70f6ef pbrook
                        tb = (TranslationBlock *)(long)(next_tb & ~3);
627 2e70f6ef pbrook
                        /* Restore PC.  */
628 622ed360 aliguori
                        cpu_pc_from_tb(env, tb);
629 2e70f6ef pbrook
                        insns_left = env->icount_decr.u32;
630 2e70f6ef pbrook
                        if (env->icount_extra && insns_left >= 0) {
631 2e70f6ef pbrook
                            /* Refill decrementer and continue execution.  */
632 2e70f6ef pbrook
                            env->icount_extra += insns_left;
633 2e70f6ef pbrook
                            if (env->icount_extra > 0xffff) {
634 2e70f6ef pbrook
                                insns_left = 0xffff;
635 2e70f6ef pbrook
                            } else {
636 2e70f6ef pbrook
                                insns_left = env->icount_extra;
637 2e70f6ef pbrook
                            }
638 2e70f6ef pbrook
                            env->icount_extra -= insns_left;
639 2e70f6ef pbrook
                            env->icount_decr.u16.low = insns_left;
640 2e70f6ef pbrook
                        } else {
641 2e70f6ef pbrook
                            if (insns_left > 0) {
642 2e70f6ef pbrook
                                /* Execute remaining instructions.  */
643 2e70f6ef pbrook
                                cpu_exec_nocache(insns_left, tb);
644 2e70f6ef pbrook
                            }
645 2e70f6ef pbrook
                            env->exception_index = EXCP_INTERRUPT;
646 2e70f6ef pbrook
                            next_tb = 0;
647 2e70f6ef pbrook
                            cpu_loop_exit();
648 2e70f6ef pbrook
                        }
649 2e70f6ef pbrook
                    }
650 2e70f6ef pbrook
                }
651 4cbf74b6 bellard
                /* reset soft MMU for next block (it can currently
652 4cbf74b6 bellard
                   only be set by a memory fault) */
653 50a518e3 ths
            } /* for(;;) */
654 3fb2ded1 bellard
        } else {
655 0d1a29f9 bellard
            env_to_regs();
656 7d13299d bellard
        }
657 3fb2ded1 bellard
    } /* for(;;) */
658 3fb2ded1 bellard
659 7d13299d bellard
660 e4533c7a bellard
#if defined(TARGET_I386)
661 9de5e440 bellard
    /* restore flags in standard format */
662 a7812ae4 pbrook
    env->eflags = env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
663 e4533c7a bellard
#elif defined(TARGET_ARM)
664 b7bcbe95 bellard
    /* XXX: Save/restore host fpu exception state?.  */
665 93ac68bc bellard
#elif defined(TARGET_SPARC)
666 67867308 bellard
#elif defined(TARGET_PPC)
667 e6e5906b pbrook
#elif defined(TARGET_M68K)
668 e6e5906b pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
669 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
670 e6e5906b pbrook
    env->sr = (env->sr & 0xffe0)
671 e6e5906b pbrook
              | env->cc_dest | (env->cc_x << 4);
672 b779e29e Edgar E. Iglesias
#elif defined(TARGET_MICROBLAZE)
673 6af0bf9c bellard
#elif defined(TARGET_MIPS)
674 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
675 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
676 f1ccf904 ths
#elif defined(TARGET_CRIS)
677 10ec5117 Alexander Graf
#elif defined(TARGET_S390X)
678 fdf9b3e8 bellard
    /* XXXXX */
679 e4533c7a bellard
#else
680 e4533c7a bellard
#error unsupported target CPU
681 e4533c7a bellard
#endif
682 1057eaa7 pbrook
683 1057eaa7 pbrook
    /* restore global registers */
684 1057eaa7 pbrook
#include "hostregs_helper.h"
685 1057eaa7 pbrook
686 6a00d601 bellard
    /* fail safe : never use cpu_single_env outside cpu_exec() */
687 5fafdf24 ths
    cpu_single_env = NULL;
688 7d13299d bellard
    return ret;
689 7d13299d bellard
}
690 6dbad63e bellard
691 fbf9eeb3 bellard
/* must only be called from the generated code as an exception can be
692 fbf9eeb3 bellard
   generated */
693 fbf9eeb3 bellard
void tb_invalidate_page_range(target_ulong start, target_ulong end)
694 fbf9eeb3 bellard
{
695 dc5d0b3d bellard
    /* XXX: cannot enable it yet because it yields to MMU exception
696 dc5d0b3d bellard
       where NIP != read address on PowerPC */
697 dc5d0b3d bellard
#if 0
698 fbf9eeb3 bellard
    target_ulong phys_addr;
699 fbf9eeb3 bellard
    phys_addr = get_phys_addr_code(env, start);
700 fbf9eeb3 bellard
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
701 dc5d0b3d bellard
#endif
702 fbf9eeb3 bellard
}
703 fbf9eeb3 bellard
704 1a18c71b bellard
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
705 e4533c7a bellard
706 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
707 6dbad63e bellard
{
708 6dbad63e bellard
    CPUX86State *saved_env;
709 6dbad63e bellard
710 6dbad63e bellard
    saved_env = env;
711 6dbad63e bellard
    env = s;
712 a412ac57 bellard
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
713 a513fe19 bellard
        selector &= 0xffff;
714 5fafdf24 ths
        cpu_x86_load_seg_cache(env, seg_reg, selector,
715 c27004ec bellard
                               (selector << 4), 0xffff, 0);
716 a513fe19 bellard
    } else {
717 5d97559d bellard
        helper_load_seg(seg_reg, selector);
718 a513fe19 bellard
    }
719 6dbad63e bellard
    env = saved_env;
720 6dbad63e bellard
}
721 9de5e440 bellard
722 6f12a2a6 bellard
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
723 d0a1ffc9 bellard
{
724 d0a1ffc9 bellard
    CPUX86State *saved_env;
725 d0a1ffc9 bellard
726 d0a1ffc9 bellard
    saved_env = env;
727 d0a1ffc9 bellard
    env = s;
728 3b46e624 ths
729 6f12a2a6 bellard
    helper_fsave(ptr, data32);
730 d0a1ffc9 bellard
731 d0a1ffc9 bellard
    env = saved_env;
732 d0a1ffc9 bellard
}
733 d0a1ffc9 bellard
734 6f12a2a6 bellard
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
735 d0a1ffc9 bellard
{
736 d0a1ffc9 bellard
    CPUX86State *saved_env;
737 d0a1ffc9 bellard
738 d0a1ffc9 bellard
    saved_env = env;
739 d0a1ffc9 bellard
    env = s;
740 3b46e624 ths
741 6f12a2a6 bellard
    helper_frstor(ptr, data32);
742 d0a1ffc9 bellard
743 d0a1ffc9 bellard
    env = saved_env;
744 d0a1ffc9 bellard
}
745 d0a1ffc9 bellard
746 e4533c7a bellard
#endif /* TARGET_I386 */
747 e4533c7a bellard
748 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
749 67b915a5 bellard
750 3fb2ded1 bellard
#if defined(TARGET_I386)
751 0b5c1ce8 Nathan Froyd
#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
752 0b5c1ce8 Nathan Froyd
#else
753 0b5c1ce8 Nathan Froyd
#define EXCEPTION_ACTION cpu_loop_exit()
754 0b5c1ce8 Nathan Froyd
#endif
755 3fb2ded1 bellard
756 b56dad1c bellard
/* 'pc' is the host PC at which the exception was raised. 'address' is
757 fd6ce8f6 bellard
   the effective address of the memory exception. 'is_write' is 1 if a
758 fd6ce8f6 bellard
   write caused the exception and otherwise 0'. 'old_set' is the
759 fd6ce8f6 bellard
   signal set which should be restored */
760 2b413144 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
761 5fafdf24 ths
                                    int is_write, sigset_t *old_set,
762 bf3e8bf1 bellard
                                    void *puc)
763 9de5e440 bellard
{
764 a513fe19 bellard
    TranslationBlock *tb;
765 a513fe19 bellard
    int ret;
766 68a79315 bellard
767 83479e77 bellard
    if (cpu_single_env)
768 83479e77 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
769 fd6ce8f6 bellard
#if defined(DEBUG_SIGNAL)
770 5fafdf24 ths
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
771 bf3e8bf1 bellard
                pc, address, is_write, *(unsigned long *)old_set);
772 9de5e440 bellard
#endif
773 25eb4484 bellard
    /* XXX: locking issue */
774 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
775 fd6ce8f6 bellard
        return 1;
776 fd6ce8f6 bellard
    }
777 fbf9eeb3 bellard
778 3fb2ded1 bellard
    /* see if it is an MMU fault */
779 0b5c1ce8 Nathan Froyd
    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
780 68016c62 bellard
    if (ret < 0)
781 68016c62 bellard
        return 0; /* not an MMU fault */
782 68016c62 bellard
    if (ret == 0)
783 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
784 68016c62 bellard
    /* now we have a real cpu fault */
785 68016c62 bellard
    tb = tb_find_pc(pc);
786 68016c62 bellard
    if (tb) {
787 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
788 68016c62 bellard
           a virtual CPU fault */
789 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
790 68016c62 bellard
    }
791 68016c62 bellard
792 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
793 68016c62 bellard
       do it (XXX: use sigsetjmp) */
794 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
795 0b5c1ce8 Nathan Froyd
    EXCEPTION_ACTION;
796 e6e5906b pbrook
797 e6e5906b pbrook
    /* never comes here */
798 67867308 bellard
    return 1;
799 67867308 bellard
}
800 6af0bf9c bellard
801 2b413144 bellard
#if defined(__i386__)
802 2b413144 bellard
803 d8ecc0b9 bellard
#if defined(__APPLE__)
804 d8ecc0b9 bellard
# include <sys/ucontext.h>
805 d8ecc0b9 bellard
806 d8ecc0b9 bellard
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
807 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
808 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
809 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->uc_sigmask)
810 78cfb07f Juergen Lock
#elif defined (__NetBSD__)
811 78cfb07f Juergen Lock
# include <ucontext.h>
812 78cfb07f Juergen Lock
813 78cfb07f Juergen Lock
# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
814 78cfb07f Juergen Lock
# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
815 78cfb07f Juergen Lock
# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
816 78cfb07f Juergen Lock
# define MASK_sig(context)    ((context)->uc_sigmask)
817 78cfb07f Juergen Lock
#elif defined (__FreeBSD__) || defined(__DragonFly__)
818 78cfb07f Juergen Lock
# include <ucontext.h>
819 78cfb07f Juergen Lock
820 78cfb07f Juergen Lock
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
821 78cfb07f Juergen Lock
# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
822 78cfb07f Juergen Lock
# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
823 78cfb07f Juergen Lock
# define MASK_sig(context)    ((context)->uc_sigmask)
824 d39bb24a blueswir1
#elif defined(__OpenBSD__)
825 d39bb24a blueswir1
# define EIP_sig(context)     ((context)->sc_eip)
826 d39bb24a blueswir1
# define TRAP_sig(context)    ((context)->sc_trapno)
827 d39bb24a blueswir1
# define ERROR_sig(context)   ((context)->sc_err)
828 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->sc_mask)
829 d8ecc0b9 bellard
#else
830 d8ecc0b9 bellard
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
831 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
832 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
833 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->uc_sigmask)
834 d8ecc0b9 bellard
#endif
835 d8ecc0b9 bellard
836 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
837 e4533c7a bellard
                       void *puc)
838 9de5e440 bellard
{
839 5a7b542b ths
    siginfo_t *info = pinfo;
840 78cfb07f Juergen Lock
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
841 78cfb07f Juergen Lock
    ucontext_t *uc = puc;
842 78cfb07f Juergen Lock
#elif defined(__OpenBSD__)
843 d39bb24a blueswir1
    struct sigcontext *uc = puc;
844 d39bb24a blueswir1
#else
845 9de5e440 bellard
    struct ucontext *uc = puc;
846 d39bb24a blueswir1
#endif
847 9de5e440 bellard
    unsigned long pc;
848 bf3e8bf1 bellard
    int trapno;
849 97eb5b14 bellard
850 d691f669 bellard
#ifndef REG_EIP
851 d691f669 bellard
/* for glibc 2.1 */
852 fd6ce8f6 bellard
#define REG_EIP    EIP
853 fd6ce8f6 bellard
#define REG_ERR    ERR
854 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
855 d691f669 bellard
#endif
856 d8ecc0b9 bellard
    pc = EIP_sig(uc);
857 d8ecc0b9 bellard
    trapno = TRAP_sig(uc);
858 ec6338ba bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
859 ec6338ba bellard
                             trapno == 0xe ?
860 ec6338ba bellard
                             (ERROR_sig(uc) >> 1) & 1 : 0,
861 d39bb24a blueswir1
                             &MASK_sig(uc), puc);
862 2b413144 bellard
}
863 2b413144 bellard
864 bc51c5c9 bellard
#elif defined(__x86_64__)
865 bc51c5c9 bellard
866 b3efe5c8 blueswir1
#ifdef __NetBSD__
867 d397abbd blueswir1
#define PC_sig(context)       _UC_MACHINE_PC(context)
868 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
869 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
870 d397abbd blueswir1
#define MASK_sig(context)     ((context)->uc_sigmask)
871 d397abbd blueswir1
#elif defined(__OpenBSD__)
872 d397abbd blueswir1
#define PC_sig(context)       ((context)->sc_rip)
873 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->sc_trapno)
874 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->sc_err)
875 d397abbd blueswir1
#define MASK_sig(context)     ((context)->sc_mask)
876 78cfb07f Juergen Lock
#elif defined (__FreeBSD__) || defined(__DragonFly__)
877 78cfb07f Juergen Lock
#include <ucontext.h>
878 78cfb07f Juergen Lock
879 78cfb07f Juergen Lock
#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
880 78cfb07f Juergen Lock
#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
881 78cfb07f Juergen Lock
#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
882 78cfb07f Juergen Lock
#define MASK_sig(context)     ((context)->uc_sigmask)
883 b3efe5c8 blueswir1
#else
884 d397abbd blueswir1
#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
885 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
886 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
887 d397abbd blueswir1
#define MASK_sig(context)     ((context)->uc_sigmask)
888 b3efe5c8 blueswir1
#endif
889 b3efe5c8 blueswir1
890 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo,
891 bc51c5c9 bellard
                       void *puc)
892 bc51c5c9 bellard
{
893 5a7b542b ths
    siginfo_t *info = pinfo;
894 bc51c5c9 bellard
    unsigned long pc;
895 78cfb07f Juergen Lock
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
896 b3efe5c8 blueswir1
    ucontext_t *uc = puc;
897 d397abbd blueswir1
#elif defined(__OpenBSD__)
898 d397abbd blueswir1
    struct sigcontext *uc = puc;
899 b3efe5c8 blueswir1
#else
900 b3efe5c8 blueswir1
    struct ucontext *uc = puc;
901 b3efe5c8 blueswir1
#endif
902 bc51c5c9 bellard
903 d397abbd blueswir1
    pc = PC_sig(uc);
904 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
905 d397abbd blueswir1
                             TRAP_sig(uc) == 0xe ?
906 d397abbd blueswir1
                             (ERROR_sig(uc) >> 1) & 1 : 0,
907 d397abbd blueswir1
                             &MASK_sig(uc), puc);
908 bc51c5c9 bellard
}
909 bc51c5c9 bellard
910 e58ffeb3 malc
#elif defined(_ARCH_PPC)
911 2b413144 bellard
912 83fb7adf bellard
/***********************************************************************
913 83fb7adf bellard
 * signal context platform-specific definitions
914 83fb7adf bellard
 * From Wine
915 83fb7adf bellard
 */
916 83fb7adf bellard
#ifdef linux
917 83fb7adf bellard
/* All Registers access - only for local access */
918 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
919 83fb7adf bellard
/* Gpr Registers access  */
920 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
921 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
922 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
923 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
924 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
925 83fb7adf bellard
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
926 83fb7adf bellard
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
927 83fb7adf bellard
/* Float Registers access  */
928 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
929 83fb7adf bellard
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
930 83fb7adf bellard
/* Exception Registers access */
931 83fb7adf bellard
# define DAR_sig(context)                        REG_sig(dar, context)
932 83fb7adf bellard
# define DSISR_sig(context)                        REG_sig(dsisr, context)
933 83fb7adf bellard
# define TRAP_sig(context)                        REG_sig(trap, context)
934 83fb7adf bellard
#endif /* linux */
935 83fb7adf bellard
936 83fb7adf bellard
#ifdef __APPLE__
937 83fb7adf bellard
# include <sys/ucontext.h>
938 83fb7adf bellard
typedef struct ucontext SIGCONTEXT;
939 83fb7adf bellard
/* All Registers access - only for local access */
940 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
941 83fb7adf bellard
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
942 83fb7adf bellard
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
943 83fb7adf bellard
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
944 83fb7adf bellard
/* Gpr Registers access */
945 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
946 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
947 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
948 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)
949 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
950 83fb7adf bellard
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
951 83fb7adf bellard
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
952 83fb7adf bellard
/* Float Registers access */
953 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
954 83fb7adf bellard
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
955 83fb7adf bellard
/* Exception Registers access */
956 83fb7adf bellard
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
957 83fb7adf bellard
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
958 83fb7adf bellard
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
959 83fb7adf bellard
#endif /* __APPLE__ */
960 83fb7adf bellard
961 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
962 e4533c7a bellard
                       void *puc)
963 2b413144 bellard
{
964 5a7b542b ths
    siginfo_t *info = pinfo;
965 25eb4484 bellard
    struct ucontext *uc = puc;
966 25eb4484 bellard
    unsigned long pc;
967 25eb4484 bellard
    int is_write;
968 25eb4484 bellard
969 83fb7adf bellard
    pc = IAR_sig(uc);
970 25eb4484 bellard
    is_write = 0;
971 25eb4484 bellard
#if 0
972 25eb4484 bellard
    /* ppc 4xx case */
973 83fb7adf bellard
    if (DSISR_sig(uc) & 0x00800000)
974 25eb4484 bellard
        is_write = 1;
975 25eb4484 bellard
#else
976 83fb7adf bellard
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
977 25eb4484 bellard
        is_write = 1;
978 25eb4484 bellard
#endif
979 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
980 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
981 2b413144 bellard
}
982 2b413144 bellard
983 2f87c607 bellard
#elif defined(__alpha__)
984 2f87c607 bellard
985 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
986 2f87c607 bellard
                           void *puc)
987 2f87c607 bellard
{
988 5a7b542b ths
    siginfo_t *info = pinfo;
989 2f87c607 bellard
    struct ucontext *uc = puc;
990 2f87c607 bellard
    uint32_t *pc = uc->uc_mcontext.sc_pc;
991 2f87c607 bellard
    uint32_t insn = *pc;
992 2f87c607 bellard
    int is_write = 0;
993 2f87c607 bellard
994 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
995 2f87c607 bellard
    switch (insn >> 26) {
996 2f87c607 bellard
    case 0x0d: // stw
997 2f87c607 bellard
    case 0x0e: // stb
998 2f87c607 bellard
    case 0x0f: // stq_u
999 2f87c607 bellard
    case 0x24: // stf
1000 2f87c607 bellard
    case 0x25: // stg
1001 2f87c607 bellard
    case 0x26: // sts
1002 2f87c607 bellard
    case 0x27: // stt
1003 2f87c607 bellard
    case 0x2c: // stl
1004 2f87c607 bellard
    case 0x2d: // stq
1005 2f87c607 bellard
    case 0x2e: // stl_c
1006 2f87c607 bellard
    case 0x2f: // stq_c
1007 2f87c607 bellard
        is_write = 1;
1008 2f87c607 bellard
    }
1009 2f87c607 bellard
1010 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1011 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1012 2f87c607 bellard
}
1013 8c6939c0 bellard
#elif defined(__sparc__)
1014 8c6939c0 bellard
1015 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1016 e4533c7a bellard
                       void *puc)
1017 8c6939c0 bellard
{
1018 5a7b542b ths
    siginfo_t *info = pinfo;
1019 8c6939c0 bellard
    int is_write;
1020 8c6939c0 bellard
    uint32_t insn;
1021 dfe5fff3 Juan Quintela
#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
1022 c9e1e2b0 blueswir1
    uint32_t *regs = (uint32_t *)(info + 1);
1023 c9e1e2b0 blueswir1
    void *sigmask = (regs + 20);
1024 8c6939c0 bellard
    /* XXX: is there a standard glibc define ? */
1025 c9e1e2b0 blueswir1
    unsigned long pc = regs[1];
1026 c9e1e2b0 blueswir1
#else
1027 84778508 blueswir1
#ifdef __linux__
1028 c9e1e2b0 blueswir1
    struct sigcontext *sc = puc;
1029 c9e1e2b0 blueswir1
    unsigned long pc = sc->sigc_regs.tpc;
1030 c9e1e2b0 blueswir1
    void *sigmask = (void *)sc->sigc_mask;
1031 84778508 blueswir1
#elif defined(__OpenBSD__)
1032 84778508 blueswir1
    struct sigcontext *uc = puc;
1033 84778508 blueswir1
    unsigned long pc = uc->sc_pc;
1034 84778508 blueswir1
    void *sigmask = (void *)(long)uc->sc_mask;
1035 84778508 blueswir1
#endif
1036 c9e1e2b0 blueswir1
#endif
1037 c9e1e2b0 blueswir1
1038 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1039 8c6939c0 bellard
    is_write = 0;
1040 8c6939c0 bellard
    insn = *(uint32_t *)pc;
1041 8c6939c0 bellard
    if ((insn >> 30) == 3) {
1042 8c6939c0 bellard
      switch((insn >> 19) & 0x3f) {
1043 8c6939c0 bellard
      case 0x05: // stb
1044 d877fa5a Blue Swirl
      case 0x15: // stba
1045 8c6939c0 bellard
      case 0x06: // sth
1046 d877fa5a Blue Swirl
      case 0x16: // stha
1047 8c6939c0 bellard
      case 0x04: // st
1048 d877fa5a Blue Swirl
      case 0x14: // sta
1049 8c6939c0 bellard
      case 0x07: // std
1050 d877fa5a Blue Swirl
      case 0x17: // stda
1051 d877fa5a Blue Swirl
      case 0x0e: // stx
1052 d877fa5a Blue Swirl
      case 0x1e: // stxa
1053 8c6939c0 bellard
      case 0x24: // stf
1054 d877fa5a Blue Swirl
      case 0x34: // stfa
1055 8c6939c0 bellard
      case 0x27: // stdf
1056 d877fa5a Blue Swirl
      case 0x37: // stdfa
1057 d877fa5a Blue Swirl
      case 0x26: // stqf
1058 d877fa5a Blue Swirl
      case 0x36: // stqfa
1059 8c6939c0 bellard
      case 0x25: // stfsr
1060 d877fa5a Blue Swirl
      case 0x3c: // casa
1061 d877fa5a Blue Swirl
      case 0x3e: // casxa
1062 8c6939c0 bellard
        is_write = 1;
1063 8c6939c0 bellard
        break;
1064 8c6939c0 bellard
      }
1065 8c6939c0 bellard
    }
1066 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1067 bf3e8bf1 bellard
                             is_write, sigmask, NULL);
1068 8c6939c0 bellard
}
1069 8c6939c0 bellard
1070 8c6939c0 bellard
#elif defined(__arm__)
1071 8c6939c0 bellard
1072 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1073 e4533c7a bellard
                       void *puc)
1074 8c6939c0 bellard
{
1075 5a7b542b ths
    siginfo_t *info = pinfo;
1076 8c6939c0 bellard
    struct ucontext *uc = puc;
1077 8c6939c0 bellard
    unsigned long pc;
1078 8c6939c0 bellard
    int is_write;
1079 3b46e624 ths
1080 48bbf11b blueswir1
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1081 5c49b363 balrog
    pc = uc->uc_mcontext.gregs[R15];
1082 5c49b363 balrog
#else
1083 4eee57f5 balrog
    pc = uc->uc_mcontext.arm_pc;
1084 5c49b363 balrog
#endif
1085 8c6939c0 bellard
    /* XXX: compute is_write */
1086 8c6939c0 bellard
    is_write = 0;
1087 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1088 8c6939c0 bellard
                             is_write,
1089 f3a9676a pbrook
                             &uc->uc_sigmask, puc);
1090 8c6939c0 bellard
}
1091 8c6939c0 bellard
1092 38e584a0 bellard
#elif defined(__mc68000)
1093 38e584a0 bellard
1094 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1095 38e584a0 bellard
                       void *puc)
1096 38e584a0 bellard
{
1097 5a7b542b ths
    siginfo_t *info = pinfo;
1098 38e584a0 bellard
    struct ucontext *uc = puc;
1099 38e584a0 bellard
    unsigned long pc;
1100 38e584a0 bellard
    int is_write;
1101 3b46e624 ths
1102 38e584a0 bellard
    pc = uc->uc_mcontext.gregs[16];
1103 38e584a0 bellard
    /* XXX: compute is_write */
1104 38e584a0 bellard
    is_write = 0;
1105 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1106 38e584a0 bellard
                             is_write,
1107 bf3e8bf1 bellard
                             &uc->uc_sigmask, puc);
1108 38e584a0 bellard
}
1109 38e584a0 bellard
1110 b8076a74 bellard
#elif defined(__ia64)
1111 b8076a74 bellard
1112 b8076a74 bellard
#ifndef __ISR_VALID
1113 b8076a74 bellard
  /* This ought to be in <bits/siginfo.h>... */
1114 b8076a74 bellard
# define __ISR_VALID        1
1115 b8076a74 bellard
#endif
1116 b8076a74 bellard
1117 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1118 b8076a74 bellard
{
1119 5a7b542b ths
    siginfo_t *info = pinfo;
1120 b8076a74 bellard
    struct ucontext *uc = puc;
1121 b8076a74 bellard
    unsigned long ip;
1122 b8076a74 bellard
    int is_write = 0;
1123 b8076a74 bellard
1124 b8076a74 bellard
    ip = uc->uc_mcontext.sc_ip;
1125 b8076a74 bellard
    switch (host_signum) {
1126 b8076a74 bellard
      case SIGILL:
1127 b8076a74 bellard
      case SIGFPE:
1128 b8076a74 bellard
      case SIGSEGV:
1129 b8076a74 bellard
      case SIGBUS:
1130 b8076a74 bellard
      case SIGTRAP:
1131 fd4a43e4 bellard
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1132 b8076a74 bellard
              /* ISR.W (write-access) is bit 33:  */
1133 b8076a74 bellard
              is_write = (info->si_isr >> 33) & 1;
1134 b8076a74 bellard
          break;
1135 b8076a74 bellard
1136 b8076a74 bellard
      default:
1137 b8076a74 bellard
          break;
1138 b8076a74 bellard
    }
1139 b8076a74 bellard
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1140 b8076a74 bellard
                             is_write,
1141 b8076a74 bellard
                             &uc->uc_sigmask, puc);
1142 b8076a74 bellard
}
1143 b8076a74 bellard
1144 90cb9493 bellard
#elif defined(__s390__)
1145 90cb9493 bellard
1146 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1147 90cb9493 bellard
                       void *puc)
1148 90cb9493 bellard
{
1149 5a7b542b ths
    siginfo_t *info = pinfo;
1150 90cb9493 bellard
    struct ucontext *uc = puc;
1151 90cb9493 bellard
    unsigned long pc;
1152 90cb9493 bellard
    int is_write;
1153 3b46e624 ths
1154 90cb9493 bellard
    pc = uc->uc_mcontext.psw.addr;
1155 90cb9493 bellard
    /* XXX: compute is_write */
1156 90cb9493 bellard
    is_write = 0;
1157 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1158 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1159 c4b89d18 ths
}
1160 c4b89d18 ths
1161 c4b89d18 ths
#elif defined(__mips__)
1162 c4b89d18 ths
1163 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1164 c4b89d18 ths
                       void *puc)
1165 c4b89d18 ths
{
1166 9617efe8 ths
    siginfo_t *info = pinfo;
1167 c4b89d18 ths
    struct ucontext *uc = puc;
1168 c4b89d18 ths
    greg_t pc = uc->uc_mcontext.pc;
1169 c4b89d18 ths
    int is_write;
1170 3b46e624 ths
1171 c4b89d18 ths
    /* XXX: compute is_write */
1172 c4b89d18 ths
    is_write = 0;
1173 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1174 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1175 90cb9493 bellard
}
1176 90cb9493 bellard
1177 f54b3f92 aurel32
#elif defined(__hppa__)
1178 f54b3f92 aurel32
1179 f54b3f92 aurel32
int cpu_signal_handler(int host_signum, void *pinfo,
1180 f54b3f92 aurel32
                       void *puc)
1181 f54b3f92 aurel32
{
1182 f54b3f92 aurel32
    struct siginfo *info = pinfo;
1183 f54b3f92 aurel32
    struct ucontext *uc = puc;
1184 f54b3f92 aurel32
    unsigned long pc;
1185 f54b3f92 aurel32
    int is_write;
1186 f54b3f92 aurel32
1187 f54b3f92 aurel32
    pc = uc->uc_mcontext.sc_iaoq[0];
1188 f54b3f92 aurel32
    /* FIXME: compute is_write */
1189 f54b3f92 aurel32
    is_write = 0;
1190 f54b3f92 aurel32
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1191 f54b3f92 aurel32
                             is_write,
1192 f54b3f92 aurel32
                             &uc->uc_sigmask, puc);
1193 f54b3f92 aurel32
}
1194 f54b3f92 aurel32
1195 9de5e440 bellard
#else
1196 2b413144 bellard
1197 3fb2ded1 bellard
#error host CPU specific signal handler needed
1198 2b413144 bellard
1199 9de5e440 bellard
#endif
1200 67b915a5 bellard
1201 67b915a5 bellard
#endif /* !defined(CONFIG_SOFTMMU) */