Statistics
| Branch: | Revision:

root / cpu-exec.c @ 34dec6a5

History | View | Annotate | Download (41.4 kB)

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