Statistics
| Branch: | Revision:

root / cpu-exec.c @ 18f1c729

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