Statistics
| Branch: | Revision:

root / cpu-exec.c @ a74cdab4

History | View | Annotate | Download (44.5 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 fbf9eeb3 bellard
/* must only be called from the generated code as an exception can be
708 fbf9eeb3 bellard
   generated */
709 fbf9eeb3 bellard
void tb_invalidate_page_range(target_ulong start, target_ulong end)
710 fbf9eeb3 bellard
{
711 dc5d0b3d bellard
    /* XXX: cannot enable it yet because it yields to MMU exception
712 dc5d0b3d bellard
       where NIP != read address on PowerPC */
713 dc5d0b3d bellard
#if 0
714 fbf9eeb3 bellard
    target_ulong phys_addr;
715 fbf9eeb3 bellard
    phys_addr = get_phys_addr_code(env, start);
716 fbf9eeb3 bellard
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
717 dc5d0b3d bellard
#endif
718 fbf9eeb3 bellard
}
719 fbf9eeb3 bellard
720 1a18c71b bellard
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
721 e4533c7a bellard
722 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
723 6dbad63e bellard
{
724 6dbad63e bellard
    CPUX86State *saved_env;
725 6dbad63e bellard
726 6dbad63e bellard
    saved_env = env;
727 6dbad63e bellard
    env = s;
728 a412ac57 bellard
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
729 a513fe19 bellard
        selector &= 0xffff;
730 5fafdf24 ths
        cpu_x86_load_seg_cache(env, seg_reg, selector,
731 c27004ec bellard
                               (selector << 4), 0xffff, 0);
732 a513fe19 bellard
    } else {
733 5d97559d bellard
        helper_load_seg(seg_reg, selector);
734 a513fe19 bellard
    }
735 6dbad63e bellard
    env = saved_env;
736 6dbad63e bellard
}
737 9de5e440 bellard
738 6f12a2a6 bellard
void cpu_x86_fsave(CPUX86State *s, target_ulong ptr, int data32)
739 d0a1ffc9 bellard
{
740 d0a1ffc9 bellard
    CPUX86State *saved_env;
741 d0a1ffc9 bellard
742 d0a1ffc9 bellard
    saved_env = env;
743 d0a1ffc9 bellard
    env = s;
744 3b46e624 ths
745 6f12a2a6 bellard
    helper_fsave(ptr, data32);
746 d0a1ffc9 bellard
747 d0a1ffc9 bellard
    env = saved_env;
748 d0a1ffc9 bellard
}
749 d0a1ffc9 bellard
750 6f12a2a6 bellard
void cpu_x86_frstor(CPUX86State *s, target_ulong ptr, int data32)
751 d0a1ffc9 bellard
{
752 d0a1ffc9 bellard
    CPUX86State *saved_env;
753 d0a1ffc9 bellard
754 d0a1ffc9 bellard
    saved_env = env;
755 d0a1ffc9 bellard
    env = s;
756 3b46e624 ths
757 6f12a2a6 bellard
    helper_frstor(ptr, data32);
758 d0a1ffc9 bellard
759 d0a1ffc9 bellard
    env = saved_env;
760 d0a1ffc9 bellard
}
761 d0a1ffc9 bellard
762 e4533c7a bellard
#endif /* TARGET_I386 */
763 e4533c7a bellard
764 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
765 67b915a5 bellard
766 3fb2ded1 bellard
#if defined(TARGET_I386)
767 0b5c1ce8 Nathan Froyd
#define EXCEPTION_ACTION raise_exception_err(env->exception_index, env->error_code)
768 0b5c1ce8 Nathan Froyd
#else
769 0b5c1ce8 Nathan Froyd
#define EXCEPTION_ACTION cpu_loop_exit()
770 0b5c1ce8 Nathan Froyd
#endif
771 3fb2ded1 bellard
772 b56dad1c bellard
/* 'pc' is the host PC at which the exception was raised. 'address' is
773 fd6ce8f6 bellard
   the effective address of the memory exception. 'is_write' is 1 if a
774 fd6ce8f6 bellard
   write caused the exception and otherwise 0'. 'old_set' is the
775 fd6ce8f6 bellard
   signal set which should be restored */
776 2b413144 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
777 5fafdf24 ths
                                    int is_write, sigset_t *old_set,
778 bf3e8bf1 bellard
                                    void *puc)
779 9de5e440 bellard
{
780 a513fe19 bellard
    TranslationBlock *tb;
781 a513fe19 bellard
    int ret;
782 68a79315 bellard
783 83479e77 bellard
    if (cpu_single_env)
784 83479e77 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
785 fd6ce8f6 bellard
#if defined(DEBUG_SIGNAL)
786 5fafdf24 ths
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
787 bf3e8bf1 bellard
                pc, address, is_write, *(unsigned long *)old_set);
788 9de5e440 bellard
#endif
789 25eb4484 bellard
    /* XXX: locking issue */
790 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
791 fd6ce8f6 bellard
        return 1;
792 fd6ce8f6 bellard
    }
793 fbf9eeb3 bellard
794 3fb2ded1 bellard
    /* see if it is an MMU fault */
795 0b5c1ce8 Nathan Froyd
    ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX, 0);
796 68016c62 bellard
    if (ret < 0)
797 68016c62 bellard
        return 0; /* not an MMU fault */
798 68016c62 bellard
    if (ret == 0)
799 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
800 68016c62 bellard
    /* now we have a real cpu fault */
801 68016c62 bellard
    tb = tb_find_pc(pc);
802 68016c62 bellard
    if (tb) {
803 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
804 68016c62 bellard
           a virtual CPU fault */
805 618ba8e6 Stefan Weil
        cpu_restore_state(tb, env, pc);
806 68016c62 bellard
    }
807 68016c62 bellard
808 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
809 68016c62 bellard
       do it (XXX: use sigsetjmp) */
810 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
811 0b5c1ce8 Nathan Froyd
    EXCEPTION_ACTION;
812 e6e5906b pbrook
813 e6e5906b pbrook
    /* never comes here */
814 67867308 bellard
    return 1;
815 67867308 bellard
}
816 6af0bf9c bellard
817 2b413144 bellard
#if defined(__i386__)
818 2b413144 bellard
819 d8ecc0b9 bellard
#if defined(__APPLE__)
820 d8ecc0b9 bellard
# include <sys/ucontext.h>
821 d8ecc0b9 bellard
822 d8ecc0b9 bellard
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
823 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
824 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
825 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->uc_sigmask)
826 78cfb07f Juergen Lock
#elif defined (__NetBSD__)
827 78cfb07f Juergen Lock
# include <ucontext.h>
828 78cfb07f Juergen Lock
829 78cfb07f Juergen Lock
# define EIP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_EIP])
830 78cfb07f Juergen Lock
# define TRAP_sig(context)    ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
831 78cfb07f Juergen Lock
# define ERROR_sig(context)   ((context)->uc_mcontext.__gregs[_REG_ERR])
832 78cfb07f Juergen Lock
# define MASK_sig(context)    ((context)->uc_sigmask)
833 78cfb07f Juergen Lock
#elif defined (__FreeBSD__) || defined(__DragonFly__)
834 78cfb07f Juergen Lock
# include <ucontext.h>
835 78cfb07f Juergen Lock
836 78cfb07f Juergen Lock
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_eip))
837 78cfb07f Juergen Lock
# define TRAP_sig(context)    ((context)->uc_mcontext.mc_trapno)
838 78cfb07f Juergen Lock
# define ERROR_sig(context)   ((context)->uc_mcontext.mc_err)
839 78cfb07f Juergen Lock
# define MASK_sig(context)    ((context)->uc_sigmask)
840 d39bb24a blueswir1
#elif defined(__OpenBSD__)
841 d39bb24a blueswir1
# define EIP_sig(context)     ((context)->sc_eip)
842 d39bb24a blueswir1
# define TRAP_sig(context)    ((context)->sc_trapno)
843 d39bb24a blueswir1
# define ERROR_sig(context)   ((context)->sc_err)
844 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->sc_mask)
845 d8ecc0b9 bellard
#else
846 d8ecc0b9 bellard
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
847 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
848 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
849 d39bb24a blueswir1
# define MASK_sig(context)    ((context)->uc_sigmask)
850 d8ecc0b9 bellard
#endif
851 d8ecc0b9 bellard
852 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
853 e4533c7a bellard
                       void *puc)
854 9de5e440 bellard
{
855 5a7b542b ths
    siginfo_t *info = pinfo;
856 78cfb07f Juergen Lock
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
857 78cfb07f Juergen Lock
    ucontext_t *uc = puc;
858 78cfb07f Juergen Lock
#elif defined(__OpenBSD__)
859 d39bb24a blueswir1
    struct sigcontext *uc = puc;
860 d39bb24a blueswir1
#else
861 9de5e440 bellard
    struct ucontext *uc = puc;
862 d39bb24a blueswir1
#endif
863 9de5e440 bellard
    unsigned long pc;
864 bf3e8bf1 bellard
    int trapno;
865 97eb5b14 bellard
866 d691f669 bellard
#ifndef REG_EIP
867 d691f669 bellard
/* for glibc 2.1 */
868 fd6ce8f6 bellard
#define REG_EIP    EIP
869 fd6ce8f6 bellard
#define REG_ERR    ERR
870 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
871 d691f669 bellard
#endif
872 d8ecc0b9 bellard
    pc = EIP_sig(uc);
873 d8ecc0b9 bellard
    trapno = TRAP_sig(uc);
874 ec6338ba bellard
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
875 ec6338ba bellard
                             trapno == 0xe ?
876 ec6338ba bellard
                             (ERROR_sig(uc) >> 1) & 1 : 0,
877 d39bb24a blueswir1
                             &MASK_sig(uc), puc);
878 2b413144 bellard
}
879 2b413144 bellard
880 bc51c5c9 bellard
#elif defined(__x86_64__)
881 bc51c5c9 bellard
882 b3efe5c8 blueswir1
#ifdef __NetBSD__
883 d397abbd blueswir1
#define PC_sig(context)       _UC_MACHINE_PC(context)
884 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->uc_mcontext.__gregs[_REG_TRAPNO])
885 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->uc_mcontext.__gregs[_REG_ERR])
886 d397abbd blueswir1
#define MASK_sig(context)     ((context)->uc_sigmask)
887 d397abbd blueswir1
#elif defined(__OpenBSD__)
888 d397abbd blueswir1
#define PC_sig(context)       ((context)->sc_rip)
889 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->sc_trapno)
890 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->sc_err)
891 d397abbd blueswir1
#define MASK_sig(context)     ((context)->sc_mask)
892 78cfb07f Juergen Lock
#elif defined (__FreeBSD__) || defined(__DragonFly__)
893 78cfb07f Juergen Lock
#include <ucontext.h>
894 78cfb07f Juergen Lock
895 78cfb07f Juergen Lock
#define PC_sig(context)  (*((unsigned long*)&(context)->uc_mcontext.mc_rip))
896 78cfb07f Juergen Lock
#define TRAP_sig(context)     ((context)->uc_mcontext.mc_trapno)
897 78cfb07f Juergen Lock
#define ERROR_sig(context)    ((context)->uc_mcontext.mc_err)
898 78cfb07f Juergen Lock
#define MASK_sig(context)     ((context)->uc_sigmask)
899 b3efe5c8 blueswir1
#else
900 d397abbd blueswir1
#define PC_sig(context)       ((context)->uc_mcontext.gregs[REG_RIP])
901 d397abbd blueswir1
#define TRAP_sig(context)     ((context)->uc_mcontext.gregs[REG_TRAPNO])
902 d397abbd blueswir1
#define ERROR_sig(context)    ((context)->uc_mcontext.gregs[REG_ERR])
903 d397abbd blueswir1
#define MASK_sig(context)     ((context)->uc_sigmask)
904 b3efe5c8 blueswir1
#endif
905 b3efe5c8 blueswir1
906 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo,
907 bc51c5c9 bellard
                       void *puc)
908 bc51c5c9 bellard
{
909 5a7b542b ths
    siginfo_t *info = pinfo;
910 bc51c5c9 bellard
    unsigned long pc;
911 78cfb07f Juergen Lock
#if defined(__NetBSD__) || defined (__FreeBSD__) || defined(__DragonFly__)
912 b3efe5c8 blueswir1
    ucontext_t *uc = puc;
913 d397abbd blueswir1
#elif defined(__OpenBSD__)
914 d397abbd blueswir1
    struct sigcontext *uc = puc;
915 b3efe5c8 blueswir1
#else
916 b3efe5c8 blueswir1
    struct ucontext *uc = puc;
917 b3efe5c8 blueswir1
#endif
918 bc51c5c9 bellard
919 d397abbd blueswir1
    pc = PC_sig(uc);
920 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
921 d397abbd blueswir1
                             TRAP_sig(uc) == 0xe ?
922 d397abbd blueswir1
                             (ERROR_sig(uc) >> 1) & 1 : 0,
923 d397abbd blueswir1
                             &MASK_sig(uc), puc);
924 bc51c5c9 bellard
}
925 bc51c5c9 bellard
926 e58ffeb3 malc
#elif defined(_ARCH_PPC)
927 2b413144 bellard
928 83fb7adf bellard
/***********************************************************************
929 83fb7adf bellard
 * signal context platform-specific definitions
930 83fb7adf bellard
 * From Wine
931 83fb7adf bellard
 */
932 83fb7adf bellard
#ifdef linux
933 83fb7adf bellard
/* All Registers access - only for local access */
934 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
935 83fb7adf bellard
/* Gpr Registers access  */
936 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
937 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
938 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
939 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
940 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
941 83fb7adf bellard
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
942 83fb7adf bellard
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
943 83fb7adf bellard
/* Float Registers access  */
944 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
945 83fb7adf bellard
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
946 83fb7adf bellard
/* Exception Registers access */
947 83fb7adf bellard
# define DAR_sig(context)                        REG_sig(dar, context)
948 83fb7adf bellard
# define DSISR_sig(context)                        REG_sig(dsisr, context)
949 83fb7adf bellard
# define TRAP_sig(context)                        REG_sig(trap, context)
950 83fb7adf bellard
#endif /* linux */
951 83fb7adf bellard
952 58d9b1e0 Juergen Lock
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
953 58d9b1e0 Juergen Lock
#include <ucontext.h>
954 58d9b1e0 Juergen Lock
# define IAR_sig(context)                ((context)->uc_mcontext.mc_srr0)
955 58d9b1e0 Juergen Lock
# define MSR_sig(context)                ((context)->uc_mcontext.mc_srr1)
956 58d9b1e0 Juergen Lock
# define CTR_sig(context)                ((context)->uc_mcontext.mc_ctr)
957 58d9b1e0 Juergen Lock
# define XER_sig(context)                ((context)->uc_mcontext.mc_xer)
958 58d9b1e0 Juergen Lock
# define LR_sig(context)                ((context)->uc_mcontext.mc_lr)
959 58d9b1e0 Juergen Lock
# define CR_sig(context)                ((context)->uc_mcontext.mc_cr)
960 58d9b1e0 Juergen Lock
/* Exception Registers access */
961 58d9b1e0 Juergen Lock
# define DAR_sig(context)                ((context)->uc_mcontext.mc_dar)
962 58d9b1e0 Juergen Lock
# define DSISR_sig(context)                ((context)->uc_mcontext.mc_dsisr)
963 58d9b1e0 Juergen Lock
# define TRAP_sig(context)                ((context)->uc_mcontext.mc_exc)
964 58d9b1e0 Juergen Lock
#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
965 58d9b1e0 Juergen Lock
966 83fb7adf bellard
#ifdef __APPLE__
967 83fb7adf bellard
# include <sys/ucontext.h>
968 83fb7adf bellard
typedef struct ucontext SIGCONTEXT;
969 83fb7adf bellard
/* All Registers access - only for local access */
970 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
971 83fb7adf bellard
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
972 83fb7adf bellard
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
973 83fb7adf bellard
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
974 83fb7adf bellard
/* Gpr Registers access */
975 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
976 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
977 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
978 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)
979 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
980 83fb7adf bellard
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
981 83fb7adf bellard
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
982 83fb7adf bellard
/* Float Registers access */
983 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
984 83fb7adf bellard
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
985 83fb7adf bellard
/* Exception Registers access */
986 83fb7adf bellard
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
987 83fb7adf bellard
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
988 83fb7adf bellard
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
989 83fb7adf bellard
#endif /* __APPLE__ */
990 83fb7adf bellard
991 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
992 e4533c7a bellard
                       void *puc)
993 2b413144 bellard
{
994 5a7b542b ths
    siginfo_t *info = pinfo;
995 58d9b1e0 Juergen Lock
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
996 58d9b1e0 Juergen Lock
    ucontext_t *uc = puc;
997 58d9b1e0 Juergen Lock
#else
998 25eb4484 bellard
    struct ucontext *uc = puc;
999 58d9b1e0 Juergen Lock
#endif
1000 25eb4484 bellard
    unsigned long pc;
1001 25eb4484 bellard
    int is_write;
1002 25eb4484 bellard
1003 83fb7adf bellard
    pc = IAR_sig(uc);
1004 25eb4484 bellard
    is_write = 0;
1005 25eb4484 bellard
#if 0
1006 25eb4484 bellard
    /* ppc 4xx case */
1007 83fb7adf bellard
    if (DSISR_sig(uc) & 0x00800000)
1008 25eb4484 bellard
        is_write = 1;
1009 25eb4484 bellard
#else
1010 83fb7adf bellard
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1011 25eb4484 bellard
        is_write = 1;
1012 25eb4484 bellard
#endif
1013 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1014 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1015 2b413144 bellard
}
1016 2b413144 bellard
1017 2f87c607 bellard
#elif defined(__alpha__)
1018 2f87c607 bellard
1019 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1020 2f87c607 bellard
                           void *puc)
1021 2f87c607 bellard
{
1022 5a7b542b ths
    siginfo_t *info = pinfo;
1023 2f87c607 bellard
    struct ucontext *uc = puc;
1024 2f87c607 bellard
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1025 2f87c607 bellard
    uint32_t insn = *pc;
1026 2f87c607 bellard
    int is_write = 0;
1027 2f87c607 bellard
1028 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1029 2f87c607 bellard
    switch (insn >> 26) {
1030 2f87c607 bellard
    case 0x0d: // stw
1031 2f87c607 bellard
    case 0x0e: // stb
1032 2f87c607 bellard
    case 0x0f: // stq_u
1033 2f87c607 bellard
    case 0x24: // stf
1034 2f87c607 bellard
    case 0x25: // stg
1035 2f87c607 bellard
    case 0x26: // sts
1036 2f87c607 bellard
    case 0x27: // stt
1037 2f87c607 bellard
    case 0x2c: // stl
1038 2f87c607 bellard
    case 0x2d: // stq
1039 2f87c607 bellard
    case 0x2e: // stl_c
1040 2f87c607 bellard
    case 0x2f: // stq_c
1041 2f87c607 bellard
        is_write = 1;
1042 2f87c607 bellard
    }
1043 2f87c607 bellard
1044 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1045 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1046 2f87c607 bellard
}
1047 8c6939c0 bellard
#elif defined(__sparc__)
1048 8c6939c0 bellard
1049 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1050 e4533c7a bellard
                       void *puc)
1051 8c6939c0 bellard
{
1052 5a7b542b ths
    siginfo_t *info = pinfo;
1053 8c6939c0 bellard
    int is_write;
1054 8c6939c0 bellard
    uint32_t insn;
1055 dfe5fff3 Juan Quintela
#if !defined(__arch64__) || defined(CONFIG_SOLARIS)
1056 c9e1e2b0 blueswir1
    uint32_t *regs = (uint32_t *)(info + 1);
1057 c9e1e2b0 blueswir1
    void *sigmask = (regs + 20);
1058 8c6939c0 bellard
    /* XXX: is there a standard glibc define ? */
1059 c9e1e2b0 blueswir1
    unsigned long pc = regs[1];
1060 c9e1e2b0 blueswir1
#else
1061 84778508 blueswir1
#ifdef __linux__
1062 c9e1e2b0 blueswir1
    struct sigcontext *sc = puc;
1063 c9e1e2b0 blueswir1
    unsigned long pc = sc->sigc_regs.tpc;
1064 c9e1e2b0 blueswir1
    void *sigmask = (void *)sc->sigc_mask;
1065 84778508 blueswir1
#elif defined(__OpenBSD__)
1066 84778508 blueswir1
    struct sigcontext *uc = puc;
1067 84778508 blueswir1
    unsigned long pc = uc->sc_pc;
1068 84778508 blueswir1
    void *sigmask = (void *)(long)uc->sc_mask;
1069 84778508 blueswir1
#endif
1070 c9e1e2b0 blueswir1
#endif
1071 c9e1e2b0 blueswir1
1072 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1073 8c6939c0 bellard
    is_write = 0;
1074 8c6939c0 bellard
    insn = *(uint32_t *)pc;
1075 8c6939c0 bellard
    if ((insn >> 30) == 3) {
1076 8c6939c0 bellard
      switch((insn >> 19) & 0x3f) {
1077 8c6939c0 bellard
      case 0x05: // stb
1078 d877fa5a Blue Swirl
      case 0x15: // stba
1079 8c6939c0 bellard
      case 0x06: // sth
1080 d877fa5a Blue Swirl
      case 0x16: // stha
1081 8c6939c0 bellard
      case 0x04: // st
1082 d877fa5a Blue Swirl
      case 0x14: // sta
1083 8c6939c0 bellard
      case 0x07: // std
1084 d877fa5a Blue Swirl
      case 0x17: // stda
1085 d877fa5a Blue Swirl
      case 0x0e: // stx
1086 d877fa5a Blue Swirl
      case 0x1e: // stxa
1087 8c6939c0 bellard
      case 0x24: // stf
1088 d877fa5a Blue Swirl
      case 0x34: // stfa
1089 8c6939c0 bellard
      case 0x27: // stdf
1090 d877fa5a Blue Swirl
      case 0x37: // stdfa
1091 d877fa5a Blue Swirl
      case 0x26: // stqf
1092 d877fa5a Blue Swirl
      case 0x36: // stqfa
1093 8c6939c0 bellard
      case 0x25: // stfsr
1094 d877fa5a Blue Swirl
      case 0x3c: // casa
1095 d877fa5a Blue Swirl
      case 0x3e: // casxa
1096 8c6939c0 bellard
        is_write = 1;
1097 8c6939c0 bellard
        break;
1098 8c6939c0 bellard
      }
1099 8c6939c0 bellard
    }
1100 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1101 bf3e8bf1 bellard
                             is_write, sigmask, NULL);
1102 8c6939c0 bellard
}
1103 8c6939c0 bellard
1104 8c6939c0 bellard
#elif defined(__arm__)
1105 8c6939c0 bellard
1106 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1107 e4533c7a bellard
                       void *puc)
1108 8c6939c0 bellard
{
1109 5a7b542b ths
    siginfo_t *info = pinfo;
1110 8c6939c0 bellard
    struct ucontext *uc = puc;
1111 8c6939c0 bellard
    unsigned long pc;
1112 8c6939c0 bellard
    int is_write;
1113 3b46e624 ths
1114 48bbf11b blueswir1
#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1115 5c49b363 balrog
    pc = uc->uc_mcontext.gregs[R15];
1116 5c49b363 balrog
#else
1117 4eee57f5 balrog
    pc = uc->uc_mcontext.arm_pc;
1118 5c49b363 balrog
#endif
1119 8c6939c0 bellard
    /* XXX: compute is_write */
1120 8c6939c0 bellard
    is_write = 0;
1121 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1122 8c6939c0 bellard
                             is_write,
1123 f3a9676a pbrook
                             &uc->uc_sigmask, puc);
1124 8c6939c0 bellard
}
1125 8c6939c0 bellard
1126 38e584a0 bellard
#elif defined(__mc68000)
1127 38e584a0 bellard
1128 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1129 38e584a0 bellard
                       void *puc)
1130 38e584a0 bellard
{
1131 5a7b542b ths
    siginfo_t *info = pinfo;
1132 38e584a0 bellard
    struct ucontext *uc = puc;
1133 38e584a0 bellard
    unsigned long pc;
1134 38e584a0 bellard
    int is_write;
1135 3b46e624 ths
1136 38e584a0 bellard
    pc = uc->uc_mcontext.gregs[16];
1137 38e584a0 bellard
    /* XXX: compute is_write */
1138 38e584a0 bellard
    is_write = 0;
1139 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1140 38e584a0 bellard
                             is_write,
1141 bf3e8bf1 bellard
                             &uc->uc_sigmask, puc);
1142 38e584a0 bellard
}
1143 38e584a0 bellard
1144 b8076a74 bellard
#elif defined(__ia64)
1145 b8076a74 bellard
1146 b8076a74 bellard
#ifndef __ISR_VALID
1147 b8076a74 bellard
  /* This ought to be in <bits/siginfo.h>... */
1148 b8076a74 bellard
# define __ISR_VALID        1
1149 b8076a74 bellard
#endif
1150 b8076a74 bellard
1151 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1152 b8076a74 bellard
{
1153 5a7b542b ths
    siginfo_t *info = pinfo;
1154 b8076a74 bellard
    struct ucontext *uc = puc;
1155 b8076a74 bellard
    unsigned long ip;
1156 b8076a74 bellard
    int is_write = 0;
1157 b8076a74 bellard
1158 b8076a74 bellard
    ip = uc->uc_mcontext.sc_ip;
1159 b8076a74 bellard
    switch (host_signum) {
1160 b8076a74 bellard
      case SIGILL:
1161 b8076a74 bellard
      case SIGFPE:
1162 b8076a74 bellard
      case SIGSEGV:
1163 b8076a74 bellard
      case SIGBUS:
1164 b8076a74 bellard
      case SIGTRAP:
1165 fd4a43e4 bellard
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1166 b8076a74 bellard
              /* ISR.W (write-access) is bit 33:  */
1167 b8076a74 bellard
              is_write = (info->si_isr >> 33) & 1;
1168 b8076a74 bellard
          break;
1169 b8076a74 bellard
1170 b8076a74 bellard
      default:
1171 b8076a74 bellard
          break;
1172 b8076a74 bellard
    }
1173 b8076a74 bellard
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1174 b8076a74 bellard
                             is_write,
1175 60e99246 Aurelien Jarno
                             (sigset_t *)&uc->uc_sigmask, puc);
1176 b8076a74 bellard
}
1177 b8076a74 bellard
1178 90cb9493 bellard
#elif defined(__s390__)
1179 90cb9493 bellard
1180 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1181 90cb9493 bellard
                       void *puc)
1182 90cb9493 bellard
{
1183 5a7b542b ths
    siginfo_t *info = pinfo;
1184 90cb9493 bellard
    struct ucontext *uc = puc;
1185 90cb9493 bellard
    unsigned long pc;
1186 6a1621b9 Richard Henderson
    uint16_t *pinsn;
1187 6a1621b9 Richard Henderson
    int is_write = 0;
1188 3b46e624 ths
1189 90cb9493 bellard
    pc = uc->uc_mcontext.psw.addr;
1190 6a1621b9 Richard Henderson
1191 6a1621b9 Richard Henderson
    /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
1192 6a1621b9 Richard Henderson
       of the normal 2 arguments.  The 3rd argument contains the "int_code"
1193 6a1621b9 Richard Henderson
       from the hardware which does in fact contain the is_write value.
1194 6a1621b9 Richard Henderson
       The rt signal handler, as far as I can tell, does not give this value
1195 6a1621b9 Richard Henderson
       at all.  Not that we could get to it from here even if it were.  */
1196 6a1621b9 Richard Henderson
    /* ??? This is not even close to complete, since it ignores all
1197 6a1621b9 Richard Henderson
       of the read-modify-write instructions.  */
1198 6a1621b9 Richard Henderson
    pinsn = (uint16_t *)pc;
1199 6a1621b9 Richard Henderson
    switch (pinsn[0] >> 8) {
1200 6a1621b9 Richard Henderson
    case 0x50: /* ST */
1201 6a1621b9 Richard Henderson
    case 0x42: /* STC */
1202 6a1621b9 Richard Henderson
    case 0x40: /* STH */
1203 6a1621b9 Richard Henderson
        is_write = 1;
1204 6a1621b9 Richard Henderson
        break;
1205 6a1621b9 Richard Henderson
    case 0xc4: /* RIL format insns */
1206 6a1621b9 Richard Henderson
        switch (pinsn[0] & 0xf) {
1207 6a1621b9 Richard Henderson
        case 0xf: /* STRL */
1208 6a1621b9 Richard Henderson
        case 0xb: /* STGRL */
1209 6a1621b9 Richard Henderson
        case 0x7: /* STHRL */
1210 6a1621b9 Richard Henderson
            is_write = 1;
1211 6a1621b9 Richard Henderson
        }
1212 6a1621b9 Richard Henderson
        break;
1213 6a1621b9 Richard Henderson
    case 0xe3: /* RXY format insns */
1214 6a1621b9 Richard Henderson
        switch (pinsn[2] & 0xff) {
1215 6a1621b9 Richard Henderson
        case 0x50: /* STY */
1216 6a1621b9 Richard Henderson
        case 0x24: /* STG */
1217 6a1621b9 Richard Henderson
        case 0x72: /* STCY */
1218 6a1621b9 Richard Henderson
        case 0x70: /* STHY */
1219 6a1621b9 Richard Henderson
        case 0x8e: /* STPQ */
1220 6a1621b9 Richard Henderson
        case 0x3f: /* STRVH */
1221 6a1621b9 Richard Henderson
        case 0x3e: /* STRV */
1222 6a1621b9 Richard Henderson
        case 0x2f: /* STRVG */
1223 6a1621b9 Richard Henderson
            is_write = 1;
1224 6a1621b9 Richard Henderson
        }
1225 6a1621b9 Richard Henderson
        break;
1226 6a1621b9 Richard Henderson
    }
1227 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1228 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1229 c4b89d18 ths
}
1230 c4b89d18 ths
1231 c4b89d18 ths
#elif defined(__mips__)
1232 c4b89d18 ths
1233 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1234 c4b89d18 ths
                       void *puc)
1235 c4b89d18 ths
{
1236 9617efe8 ths
    siginfo_t *info = pinfo;
1237 c4b89d18 ths
    struct ucontext *uc = puc;
1238 c4b89d18 ths
    greg_t pc = uc->uc_mcontext.pc;
1239 c4b89d18 ths
    int is_write;
1240 3b46e624 ths
1241 c4b89d18 ths
    /* XXX: compute is_write */
1242 c4b89d18 ths
    is_write = 0;
1243 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1244 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1245 90cb9493 bellard
}
1246 90cb9493 bellard
1247 f54b3f92 aurel32
#elif defined(__hppa__)
1248 f54b3f92 aurel32
1249 f54b3f92 aurel32
int cpu_signal_handler(int host_signum, void *pinfo,
1250 f54b3f92 aurel32
                       void *puc)
1251 f54b3f92 aurel32
{
1252 f54b3f92 aurel32
    struct siginfo *info = pinfo;
1253 f54b3f92 aurel32
    struct ucontext *uc = puc;
1254 f57040be Richard Henderson
    unsigned long pc = uc->uc_mcontext.sc_iaoq[0];
1255 f57040be Richard Henderson
    uint32_t insn = *(uint32_t *)pc;
1256 f57040be Richard Henderson
    int is_write = 0;
1257 f57040be Richard Henderson
1258 f57040be Richard Henderson
    /* XXX: need kernel patch to get write flag faster.  */
1259 f57040be Richard Henderson
    switch (insn >> 26) {
1260 f57040be Richard Henderson
    case 0x1a: /* STW */
1261 f57040be Richard Henderson
    case 0x19: /* STH */
1262 f57040be Richard Henderson
    case 0x18: /* STB */
1263 f57040be Richard Henderson
    case 0x1b: /* STWM */
1264 f57040be Richard Henderson
        is_write = 1;
1265 f57040be Richard Henderson
        break;
1266 f57040be Richard Henderson
1267 f57040be Richard Henderson
    case 0x09: /* CSTWX, FSTWX, FSTWS */
1268 f57040be Richard Henderson
    case 0x0b: /* CSTDX, FSTDX, FSTDS */
1269 f57040be Richard Henderson
        /* Distinguish from coprocessor load ... */
1270 f57040be Richard Henderson
        is_write = (insn >> 9) & 1;
1271 f57040be Richard Henderson
        break;
1272 f57040be Richard Henderson
1273 f57040be Richard Henderson
    case 0x03:
1274 f57040be Richard Henderson
        switch ((insn >> 6) & 15) {
1275 f57040be Richard Henderson
        case 0xa: /* STWS */
1276 f57040be Richard Henderson
        case 0x9: /* STHS */
1277 f57040be Richard Henderson
        case 0x8: /* STBS */
1278 f57040be Richard Henderson
        case 0xe: /* STWAS */
1279 f57040be Richard Henderson
        case 0xc: /* STBYS */
1280 f57040be Richard Henderson
            is_write = 1;
1281 f57040be Richard Henderson
        }
1282 f57040be Richard Henderson
        break;
1283 f57040be Richard Henderson
    }
1284 f54b3f92 aurel32
1285 f54b3f92 aurel32
    return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
1286 f57040be Richard Henderson
                             is_write, &uc->uc_sigmask, puc);
1287 f54b3f92 aurel32
}
1288 f54b3f92 aurel32
1289 9de5e440 bellard
#else
1290 2b413144 bellard
1291 3fb2ded1 bellard
#error host CPU specific signal handler needed
1292 2b413144 bellard
1293 9de5e440 bellard
#endif
1294 67b915a5 bellard
1295 67b915a5 bellard
#endif /* !defined(CONFIG_SOFTMMU) */