Statistics
| Branch: | Revision:

root / cpu-exec.c @ c6df7102

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