Statistics
| Branch: | Revision:

root / cpu-exec.c @ 52621688

History | View | Annotate | Download (51 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 3ef693a0 bellard
 * License along with this library; if not, write to the Free Software
18 3ef693a0 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 7d13299d bellard
 */
20 e4533c7a bellard
#include "config.h"
21 93ac68bc bellard
#include "exec.h"
22 956034d7 bellard
#include "disas.h"
23 7d13299d bellard
24 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
25 fbf9eeb3 bellard
#undef EAX
26 fbf9eeb3 bellard
#undef ECX
27 fbf9eeb3 bellard
#undef EDX
28 fbf9eeb3 bellard
#undef EBX
29 fbf9eeb3 bellard
#undef ESP
30 fbf9eeb3 bellard
#undef EBP
31 fbf9eeb3 bellard
#undef ESI
32 fbf9eeb3 bellard
#undef EDI
33 fbf9eeb3 bellard
#undef EIP
34 fbf9eeb3 bellard
#include <signal.h>
35 fbf9eeb3 bellard
#include <sys/ucontext.h>
36 fbf9eeb3 bellard
#endif
37 fbf9eeb3 bellard
38 36bdbe54 bellard
int tb_invalidated_flag;
39 36bdbe54 bellard
40 dc99065b bellard
//#define DEBUG_EXEC
41 9de5e440 bellard
//#define DEBUG_SIGNAL
42 7d13299d bellard
43 e4533c7a bellard
void cpu_loop_exit(void)
44 e4533c7a bellard
{
45 bfed01fc ths
    /* NOTE: the register at this point must be saved by hand because
46 bfed01fc ths
       longjmp restore them */
47 bfed01fc ths
    regs_to_env();
48 e4533c7a bellard
    longjmp(env->jmp_env, 1);
49 e4533c7a bellard
}
50 bfed01fc ths
51 e6e5906b pbrook
#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
52 3475187d bellard
#define reg_T2
53 3475187d bellard
#endif
54 e4533c7a bellard
55 fbf9eeb3 bellard
/* exit the current TB from a signal handler. The host registers are
56 fbf9eeb3 bellard
   restored in a state compatible with the CPU emulator
57 fbf9eeb3 bellard
 */
58 5fafdf24 ths
void cpu_resume_from_signal(CPUState *env1, void *puc)
59 fbf9eeb3 bellard
{
60 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
61 fbf9eeb3 bellard
    struct ucontext *uc = puc;
62 fbf9eeb3 bellard
#endif
63 fbf9eeb3 bellard
64 fbf9eeb3 bellard
    env = env1;
65 fbf9eeb3 bellard
66 fbf9eeb3 bellard
    /* XXX: restore cpu registers saved in host registers */
67 fbf9eeb3 bellard
68 fbf9eeb3 bellard
#if !defined(CONFIG_SOFTMMU)
69 fbf9eeb3 bellard
    if (puc) {
70 fbf9eeb3 bellard
        /* XXX: use siglongjmp ? */
71 fbf9eeb3 bellard
        sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
72 fbf9eeb3 bellard
    }
73 fbf9eeb3 bellard
#endif
74 fbf9eeb3 bellard
    longjmp(env->jmp_env, 1);
75 fbf9eeb3 bellard
}
76 fbf9eeb3 bellard
77 8a40a180 bellard
78 8a40a180 bellard
static TranslationBlock *tb_find_slow(target_ulong pc,
79 8a40a180 bellard
                                      target_ulong cs_base,
80 c068688b j_mayer
                                      uint64_t flags)
81 8a40a180 bellard
{
82 8a40a180 bellard
    TranslationBlock *tb, **ptb1;
83 8a40a180 bellard
    int code_gen_size;
84 8a40a180 bellard
    unsigned int h;
85 8a40a180 bellard
    target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
86 8a40a180 bellard
    uint8_t *tc_ptr;
87 3b46e624 ths
88 8a40a180 bellard
    spin_lock(&tb_lock);
89 8a40a180 bellard
90 8a40a180 bellard
    tb_invalidated_flag = 0;
91 3b46e624 ths
92 8a40a180 bellard
    regs_to_env(); /* XXX: do it just before cpu_gen_code() */
93 3b46e624 ths
94 8a40a180 bellard
    /* find translated block using physical mappings */
95 8a40a180 bellard
    phys_pc = get_phys_addr_code(env, pc);
96 8a40a180 bellard
    phys_page1 = phys_pc & TARGET_PAGE_MASK;
97 8a40a180 bellard
    phys_page2 = -1;
98 8a40a180 bellard
    h = tb_phys_hash_func(phys_pc);
99 8a40a180 bellard
    ptb1 = &tb_phys_hash[h];
100 8a40a180 bellard
    for(;;) {
101 8a40a180 bellard
        tb = *ptb1;
102 8a40a180 bellard
        if (!tb)
103 8a40a180 bellard
            goto not_found;
104 5fafdf24 ths
        if (tb->pc == pc &&
105 8a40a180 bellard
            tb->page_addr[0] == phys_page1 &&
106 5fafdf24 ths
            tb->cs_base == cs_base &&
107 8a40a180 bellard
            tb->flags == flags) {
108 8a40a180 bellard
            /* check next page if needed */
109 8a40a180 bellard
            if (tb->page_addr[1] != -1) {
110 5fafdf24 ths
                virt_page2 = (pc & TARGET_PAGE_MASK) +
111 8a40a180 bellard
                    TARGET_PAGE_SIZE;
112 8a40a180 bellard
                phys_page2 = get_phys_addr_code(env, virt_page2);
113 8a40a180 bellard
                if (tb->page_addr[1] == phys_page2)
114 8a40a180 bellard
                    goto found;
115 8a40a180 bellard
            } else {
116 8a40a180 bellard
                goto found;
117 8a40a180 bellard
            }
118 8a40a180 bellard
        }
119 8a40a180 bellard
        ptb1 = &tb->phys_hash_next;
120 8a40a180 bellard
    }
121 8a40a180 bellard
 not_found:
122 8a40a180 bellard
    /* if no translated code available, then translate it now */
123 8a40a180 bellard
    tb = tb_alloc(pc);
124 8a40a180 bellard
    if (!tb) {
125 8a40a180 bellard
        /* flush must be done */
126 8a40a180 bellard
        tb_flush(env);
127 8a40a180 bellard
        /* cannot fail at this point */
128 8a40a180 bellard
        tb = tb_alloc(pc);
129 8a40a180 bellard
        /* don't forget to invalidate previous TB info */
130 15388002 bellard
        tb_invalidated_flag = 1;
131 8a40a180 bellard
    }
132 8a40a180 bellard
    tc_ptr = code_gen_ptr;
133 8a40a180 bellard
    tb->tc_ptr = tc_ptr;
134 8a40a180 bellard
    tb->cs_base = cs_base;
135 8a40a180 bellard
    tb->flags = flags;
136 8a40a180 bellard
    cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
137 8a40a180 bellard
    code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
138 3b46e624 ths
139 8a40a180 bellard
    /* check next page if needed */
140 8a40a180 bellard
    virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
141 8a40a180 bellard
    phys_page2 = -1;
142 8a40a180 bellard
    if ((pc & TARGET_PAGE_MASK) != virt_page2) {
143 8a40a180 bellard
        phys_page2 = get_phys_addr_code(env, virt_page2);
144 8a40a180 bellard
    }
145 8a40a180 bellard
    tb_link_phys(tb, phys_pc, phys_page2);
146 3b46e624 ths
147 8a40a180 bellard
 found:
148 8a40a180 bellard
    /* we add the TB in the virtual pc hash table */
149 8a40a180 bellard
    env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
150 8a40a180 bellard
    spin_unlock(&tb_lock);
151 8a40a180 bellard
    return tb;
152 8a40a180 bellard
}
153 8a40a180 bellard
154 8a40a180 bellard
static inline TranslationBlock *tb_find_fast(void)
155 8a40a180 bellard
{
156 8a40a180 bellard
    TranslationBlock *tb;
157 8a40a180 bellard
    target_ulong cs_base, pc;
158 c068688b j_mayer
    uint64_t flags;
159 8a40a180 bellard
160 8a40a180 bellard
    /* we record a subset of the CPU state. It will
161 8a40a180 bellard
       always be the same before a given translated block
162 8a40a180 bellard
       is executed. */
163 8a40a180 bellard
#if defined(TARGET_I386)
164 8a40a180 bellard
    flags = env->hflags;
165 8a40a180 bellard
    flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
166 0573fbfc ths
    flags |= env->intercept;
167 8a40a180 bellard
    cs_base = env->segs[R_CS].base;
168 8a40a180 bellard
    pc = cs_base + env->eip;
169 8a40a180 bellard
#elif defined(TARGET_ARM)
170 8a40a180 bellard
    flags = env->thumb | (env->vfp.vec_len << 1)
171 b5ff1b31 bellard
            | (env->vfp.vec_stride << 4);
172 b5ff1b31 bellard
    if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
173 b5ff1b31 bellard
        flags |= (1 << 6);
174 40f137e1 pbrook
    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
175 40f137e1 pbrook
        flags |= (1 << 7);
176 8a40a180 bellard
    cs_base = 0;
177 8a40a180 bellard
    pc = env->regs[15];
178 8a40a180 bellard
#elif defined(TARGET_SPARC)
179 8a40a180 bellard
#ifdef TARGET_SPARC64
180 a80dde08 bellard
    // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
181 a80dde08 bellard
    flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
182 a80dde08 bellard
        | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
183 8a40a180 bellard
#else
184 40ce0a9a blueswir1
    // FPU enable . MMU Boot . MMU enabled . MMU no-fault . Supervisor
185 40ce0a9a blueswir1
    flags = (env->psref << 4) | (((env->mmuregs[0] & MMU_BM) >> 14) << 3)
186 40ce0a9a blueswir1
        | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
187 a80dde08 bellard
        | env->psrs;
188 8a40a180 bellard
#endif
189 8a40a180 bellard
    cs_base = env->npc;
190 8a40a180 bellard
    pc = env->pc;
191 8a40a180 bellard
#elif defined(TARGET_PPC)
192 1527c87e j_mayer
    flags = env->hflags;
193 8a40a180 bellard
    cs_base = 0;
194 8a40a180 bellard
    pc = env->nip;
195 8a40a180 bellard
#elif defined(TARGET_MIPS)
196 56b19403 pbrook
    flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
197 cc9442b9 bellard
    cs_base = 0;
198 ead9360e ths
    pc = env->PC[env->current_tc];
199 e6e5906b pbrook
#elif defined(TARGET_M68K)
200 acf930aa pbrook
    flags = (env->fpcr & M68K_FPCR_PREC)  /* Bit  6 */
201 acf930aa pbrook
            | (env->sr & SR_S)            /* Bit  13 */
202 acf930aa pbrook
            | ((env->macsr >> 4) & 0xf);  /* Bits 0-3 */
203 e6e5906b pbrook
    cs_base = 0;
204 e6e5906b pbrook
    pc = env->pc;
205 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
206 fdf9b3e8 bellard
    flags = env->sr & (SR_MD | SR_RB);
207 fdf9b3e8 bellard
    cs_base = 0;         /* XXXXX */
208 fdf9b3e8 bellard
    pc = env->pc;
209 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
210 eddf68a6 j_mayer
    flags = env->ps;
211 eddf68a6 j_mayer
    cs_base = 0;
212 eddf68a6 j_mayer
    pc = env->pc;
213 8a40a180 bellard
#else
214 8a40a180 bellard
#error unsupported CPU
215 8a40a180 bellard
#endif
216 8a40a180 bellard
    tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
217 8a40a180 bellard
    if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||
218 8a40a180 bellard
                         tb->flags != flags, 0)) {
219 8a40a180 bellard
        tb = tb_find_slow(pc, cs_base, flags);
220 15388002 bellard
        /* Note: we do it here to avoid a gcc bug on Mac OS X when
221 15388002 bellard
           doing it in tb_find_slow */
222 15388002 bellard
        if (tb_invalidated_flag) {
223 15388002 bellard
            /* as some TB could have been invalidated because
224 15388002 bellard
               of memory exceptions while generating the code, we
225 15388002 bellard
               must recompute the hash index here */
226 15388002 bellard
            T0 = 0;
227 15388002 bellard
        }
228 8a40a180 bellard
    }
229 8a40a180 bellard
    return tb;
230 8a40a180 bellard
}
231 8a40a180 bellard
232 8a40a180 bellard
233 7d13299d bellard
/* main execution loop */
234 7d13299d bellard
235 e4533c7a bellard
int cpu_exec(CPUState *env1)
236 7d13299d bellard
{
237 1057eaa7 pbrook
#define DECLARE_HOST_REGS 1
238 1057eaa7 pbrook
#include "hostregs_helper.h"
239 1057eaa7 pbrook
#if defined(TARGET_SPARC)
240 3475187d bellard
#if defined(reg_REGWPTR)
241 3475187d bellard
    uint32_t *saved_regwptr;
242 3475187d bellard
#endif
243 3475187d bellard
#endif
244 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
245 b49d07ba ths
    int saved_i7;
246 b49d07ba ths
    target_ulong tmp_T0;
247 8c6939c0 bellard
#endif
248 8a40a180 bellard
    int ret, interrupt_request;
249 7d13299d bellard
    void (*gen_func)(void);
250 8a40a180 bellard
    TranslationBlock *tb;
251 c27004ec bellard
    uint8_t *tc_ptr;
252 8c6939c0 bellard
253 bfed01fc ths
    if (cpu_halted(env1) == EXCP_HALTED)
254 bfed01fc ths
        return EXCP_HALTED;
255 5a1e3cfc bellard
256 5fafdf24 ths
    cpu_single_env = env1;
257 6a00d601 bellard
258 7d13299d bellard
    /* first we save global registers */
259 1057eaa7 pbrook
#define SAVE_HOST_REGS 1
260 1057eaa7 pbrook
#include "hostregs_helper.h"
261 c27004ec bellard
    env = env1;
262 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
263 e4533c7a bellard
    /* we also save i7 because longjmp may not restore it */
264 e4533c7a bellard
    asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
265 e4533c7a bellard
#endif
266 e4533c7a bellard
267 0d1a29f9 bellard
    env_to_regs();
268 ecb644f4 ths
#if defined(TARGET_I386)
269 9de5e440 bellard
    /* put eflags in CPU temporary format */
270 fc2b4c48 bellard
    CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
271 fc2b4c48 bellard
    DF = 1 - (2 * ((env->eflags >> 10) & 1));
272 9de5e440 bellard
    CC_OP = CC_OP_EFLAGS;
273 fc2b4c48 bellard
    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
274 93ac68bc bellard
#elif defined(TARGET_SPARC)
275 3475187d bellard
#if defined(reg_REGWPTR)
276 3475187d bellard
    saved_regwptr = REGWPTR;
277 3475187d bellard
#endif
278 e6e5906b pbrook
#elif defined(TARGET_M68K)
279 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
280 e6e5906b pbrook
    env->cc_dest = env->sr & 0xf;
281 e6e5906b pbrook
    env->cc_x = (env->sr >> 4) & 1;
282 ecb644f4 ths
#elif defined(TARGET_ALPHA)
283 ecb644f4 ths
#elif defined(TARGET_ARM)
284 ecb644f4 ths
#elif defined(TARGET_PPC)
285 6af0bf9c bellard
#elif defined(TARGET_MIPS)
286 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
287 fdf9b3e8 bellard
    /* XXXXX */
288 e4533c7a bellard
#else
289 e4533c7a bellard
#error unsupported target CPU
290 e4533c7a bellard
#endif
291 3fb2ded1 bellard
    env->exception_index = -1;
292 9d27abd9 bellard
293 7d13299d bellard
    /* prepare setjmp context for exception handling */
294 3fb2ded1 bellard
    for(;;) {
295 3fb2ded1 bellard
        if (setjmp(env->jmp_env) == 0) {
296 ee8b7021 bellard
            env->current_tb = NULL;
297 3fb2ded1 bellard
            /* if an exception is pending, we execute it here */
298 3fb2ded1 bellard
            if (env->exception_index >= 0) {
299 3fb2ded1 bellard
                if (env->exception_index >= EXCP_INTERRUPT) {
300 3fb2ded1 bellard
                    /* exit request from the cpu execution loop */
301 3fb2ded1 bellard
                    ret = env->exception_index;
302 3fb2ded1 bellard
                    break;
303 3fb2ded1 bellard
                } else if (env->user_mode_only) {
304 3fb2ded1 bellard
                    /* if user mode only, we simulate a fake exception
305 9f083493 ths
                       which will be handled outside the cpu execution
306 3fb2ded1 bellard
                       loop */
307 83479e77 bellard
#if defined(TARGET_I386)
308 5fafdf24 ths
                    do_interrupt_user(env->exception_index,
309 5fafdf24 ths
                                      env->exception_is_int,
310 5fafdf24 ths
                                      env->error_code,
311 3fb2ded1 bellard
                                      env->exception_next_eip);
312 83479e77 bellard
#endif
313 3fb2ded1 bellard
                    ret = env->exception_index;
314 3fb2ded1 bellard
                    break;
315 3fb2ded1 bellard
                } else {
316 83479e77 bellard
#if defined(TARGET_I386)
317 3fb2ded1 bellard
                    /* simulate a real cpu exception. On i386, it can
318 3fb2ded1 bellard
                       trigger new exceptions, but we do not handle
319 3fb2ded1 bellard
                       double or triple faults yet. */
320 5fafdf24 ths
                    do_interrupt(env->exception_index,
321 5fafdf24 ths
                                 env->exception_is_int,
322 5fafdf24 ths
                                 env->error_code,
323 d05e66d2 bellard
                                 env->exception_next_eip, 0);
324 678dde13 ths
                    /* successfully delivered */
325 678dde13 ths
                    env->old_exception = -1;
326 ce09776b bellard
#elif defined(TARGET_PPC)
327 ce09776b bellard
                    do_interrupt(env);
328 6af0bf9c bellard
#elif defined(TARGET_MIPS)
329 6af0bf9c bellard
                    do_interrupt(env);
330 e95c8d51 bellard
#elif defined(TARGET_SPARC)
331 1a0c3292 bellard
                    do_interrupt(env->exception_index);
332 b5ff1b31 bellard
#elif defined(TARGET_ARM)
333 b5ff1b31 bellard
                    do_interrupt(env);
334 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
335 fdf9b3e8 bellard
                    do_interrupt(env);
336 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
337 eddf68a6 j_mayer
                    do_interrupt(env);
338 0633879f pbrook
#elif defined(TARGET_M68K)
339 0633879f pbrook
                    do_interrupt(0);
340 83479e77 bellard
#endif
341 3fb2ded1 bellard
                }
342 3fb2ded1 bellard
                env->exception_index = -1;
343 5fafdf24 ths
            }
344 9df217a3 bellard
#ifdef USE_KQEMU
345 9df217a3 bellard
            if (kqemu_is_ok(env) && env->interrupt_request == 0) {
346 9df217a3 bellard
                int ret;
347 9df217a3 bellard
                env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
348 9df217a3 bellard
                ret = kqemu_cpu_exec(env);
349 9df217a3 bellard
                /* put eflags in CPU temporary format */
350 9df217a3 bellard
                CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
351 9df217a3 bellard
                DF = 1 - (2 * ((env->eflags >> 10) & 1));
352 9df217a3 bellard
                CC_OP = CC_OP_EFLAGS;
353 9df217a3 bellard
                env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
354 9df217a3 bellard
                if (ret == 1) {
355 9df217a3 bellard
                    /* exception */
356 9df217a3 bellard
                    longjmp(env->jmp_env, 1);
357 9df217a3 bellard
                } else if (ret == 2) {
358 9df217a3 bellard
                    /* softmmu execution needed */
359 9df217a3 bellard
                } else {
360 9df217a3 bellard
                    if (env->interrupt_request != 0) {
361 9df217a3 bellard
                        /* hardware interrupt will be executed just after */
362 9df217a3 bellard
                    } else {
363 9df217a3 bellard
                        /* otherwise, we restart */
364 9df217a3 bellard
                        longjmp(env->jmp_env, 1);
365 9df217a3 bellard
                    }
366 9df217a3 bellard
                }
367 3fb2ded1 bellard
            }
368 9df217a3 bellard
#endif
369 9df217a3 bellard
370 3fb2ded1 bellard
            T0 = 0; /* force lookup of first TB */
371 3fb2ded1 bellard
            for(;;) {
372 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
373 5fafdf24 ths
                /* g1 can be modified by some libc? functions */
374 3fb2ded1 bellard
                tmp_T0 = T0;
375 3b46e624 ths
#endif
376 68a79315 bellard
                interrupt_request = env->interrupt_request;
377 0573fbfc ths
                if (__builtin_expect(interrupt_request, 0)
378 0573fbfc ths
#if defined(TARGET_I386)
379 0573fbfc ths
                        && env->hflags & HF_GIF_MASK
380 0573fbfc ths
#endif
381 0573fbfc ths
                                ) {
382 6658ffb8 pbrook
                    if (interrupt_request & CPU_INTERRUPT_DEBUG) {
383 6658ffb8 pbrook
                        env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
384 6658ffb8 pbrook
                        env->exception_index = EXCP_DEBUG;
385 6658ffb8 pbrook
                        cpu_loop_exit();
386 6658ffb8 pbrook
                    }
387 a90b7318 balrog
#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
388 a90b7318 balrog
    defined(TARGET_PPC) || defined(TARGET_ALPHA)
389 a90b7318 balrog
                    if (interrupt_request & CPU_INTERRUPT_HALT) {
390 a90b7318 balrog
                        env->interrupt_request &= ~CPU_INTERRUPT_HALT;
391 a90b7318 balrog
                        env->halted = 1;
392 a90b7318 balrog
                        env->exception_index = EXCP_HLT;
393 a90b7318 balrog
                        cpu_loop_exit();
394 a90b7318 balrog
                    }
395 a90b7318 balrog
#endif
396 68a79315 bellard
#if defined(TARGET_I386)
397 3b21e03e bellard
                    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
398 3b21e03e bellard
                        !(env->hflags & HF_SMM_MASK)) {
399 0573fbfc ths
                        svm_check_intercept(SVM_EXIT_SMI);
400 3b21e03e bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_SMI;
401 3b21e03e bellard
                        do_smm_enter();
402 3b21e03e bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
403 3b21e03e bellard
                        tmp_T0 = 0;
404 3b21e03e bellard
#else
405 3b21e03e bellard
                        T0 = 0;
406 3b21e03e bellard
#endif
407 3b21e03e bellard
                    } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
408 0573fbfc ths
                        (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
409 3f337316 bellard
                        !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
410 68a79315 bellard
                        int intno;
411 0573fbfc ths
                        svm_check_intercept(SVM_EXIT_INTR);
412 52621688 ths
                        env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
413 a541f297 bellard
                        intno = cpu_get_pic_interrupt(env);
414 f193c797 bellard
                        if (loglevel & CPU_LOG_TB_IN_ASM) {
415 68a79315 bellard
                            fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
416 68a79315 bellard
                        }
417 d05e66d2 bellard
                        do_interrupt(intno, 0, 0, 0, 1);
418 907a5b26 bellard
                        /* ensure that no TB jump will be modified as
419 907a5b26 bellard
                           the program flow was changed */
420 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
421 907a5b26 bellard
                        tmp_T0 = 0;
422 907a5b26 bellard
#else
423 907a5b26 bellard
                        T0 = 0;
424 907a5b26 bellard
#endif
425 0573fbfc ths
#if !defined(CONFIG_USER_ONLY)
426 0573fbfc ths
                    } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
427 0573fbfc ths
                        (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
428 0573fbfc ths
                         int intno;
429 0573fbfc ths
                         /* FIXME: this should respect TPR */
430 0573fbfc ths
                         env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
431 52621688 ths
                         svm_check_intercept(SVM_EXIT_VINTR);
432 0573fbfc ths
                         intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
433 0573fbfc ths
                         if (loglevel & CPU_LOG_TB_IN_ASM)
434 0573fbfc ths
                             fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
435 0573fbfc ths
                         do_interrupt(intno, 0, 0, -1, 1);
436 52621688 ths
                         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
437 52621688 ths
                                  ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
438 0573fbfc ths
#if defined(__sparc__) && !defined(HOST_SOLARIS)
439 0573fbfc ths
                         tmp_T0 = 0;
440 0573fbfc ths
#else
441 0573fbfc ths
                         T0 = 0;
442 0573fbfc ths
#endif
443 0573fbfc ths
#endif
444 68a79315 bellard
                    }
445 ce09776b bellard
#elif defined(TARGET_PPC)
446 9fddaa0c bellard
#if 0
447 9fddaa0c bellard
                    if ((interrupt_request & CPU_INTERRUPT_RESET)) {
448 9fddaa0c bellard
                        cpu_ppc_reset(env);
449 9fddaa0c bellard
                    }
450 9fddaa0c bellard
#endif
451 47103572 j_mayer
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
452 e9df014c j_mayer
                        ppc_hw_interrupt(env);
453 e9df014c j_mayer
                        if (env->pending_interrupts == 0)
454 e9df014c j_mayer
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
455 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
456 e9df014c j_mayer
                        tmp_T0 = 0;
457 8a40a180 bellard
#else
458 e9df014c j_mayer
                        T0 = 0;
459 8a40a180 bellard
#endif
460 ce09776b bellard
                    }
461 6af0bf9c bellard
#elif defined(TARGET_MIPS)
462 6af0bf9c bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
463 24c7b0e3 ths
                        (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
464 6af0bf9c bellard
                        (env->CP0_Status & (1 << CP0St_IE)) &&
465 24c7b0e3 ths
                        !(env->CP0_Status & (1 << CP0St_EXL)) &&
466 24c7b0e3 ths
                        !(env->CP0_Status & (1 << CP0St_ERL)) &&
467 6af0bf9c bellard
                        !(env->hflags & MIPS_HFLAG_DM)) {
468 6af0bf9c bellard
                        /* Raise it */
469 6af0bf9c bellard
                        env->exception_index = EXCP_EXT_INTERRUPT;
470 6af0bf9c bellard
                        env->error_code = 0;
471 6af0bf9c bellard
                        do_interrupt(env);
472 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
473 8a40a180 bellard
                        tmp_T0 = 0;
474 8a40a180 bellard
#else
475 8a40a180 bellard
                        T0 = 0;
476 8a40a180 bellard
#endif
477 6af0bf9c bellard
                    }
478 e95c8d51 bellard
#elif defined(TARGET_SPARC)
479 66321a11 bellard
                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
480 66321a11 bellard
                        (env->psret != 0)) {
481 66321a11 bellard
                        int pil = env->interrupt_index & 15;
482 66321a11 bellard
                        int type = env->interrupt_index & 0xf0;
483 66321a11 bellard
484 66321a11 bellard
                        if (((type == TT_EXTINT) &&
485 66321a11 bellard
                             (pil == 15 || pil > env->psrpil)) ||
486 66321a11 bellard
                            type != TT_EXTINT) {
487 66321a11 bellard
                            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
488 66321a11 bellard
                            do_interrupt(env->interrupt_index);
489 66321a11 bellard
                            env->interrupt_index = 0;
490 327ac2e7 blueswir1
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
491 327ac2e7 blueswir1
                            cpu_check_irqs(env);
492 327ac2e7 blueswir1
#endif
493 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
494 8a40a180 bellard
                            tmp_T0 = 0;
495 8a40a180 bellard
#else
496 8a40a180 bellard
                            T0 = 0;
497 8a40a180 bellard
#endif
498 66321a11 bellard
                        }
499 e95c8d51 bellard
                    } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
500 e95c8d51 bellard
                        //do_interrupt(0, 0, 0, 0, 0);
501 e95c8d51 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
502 a90b7318 balrog
                    }
503 b5ff1b31 bellard
#elif defined(TARGET_ARM)
504 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_FIQ
505 b5ff1b31 bellard
                        && !(env->uncached_cpsr & CPSR_F)) {
506 b5ff1b31 bellard
                        env->exception_index = EXCP_FIQ;
507 b5ff1b31 bellard
                        do_interrupt(env);
508 b5ff1b31 bellard
                    }
509 b5ff1b31 bellard
                    if (interrupt_request & CPU_INTERRUPT_HARD
510 b5ff1b31 bellard
                        && !(env->uncached_cpsr & CPSR_I)) {
511 b5ff1b31 bellard
                        env->exception_index = EXCP_IRQ;
512 b5ff1b31 bellard
                        do_interrupt(env);
513 b5ff1b31 bellard
                    }
514 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
515 fdf9b3e8 bellard
                    /* XXXXX */
516 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
517 eddf68a6 j_mayer
                    if (interrupt_request & CPU_INTERRUPT_HARD) {
518 eddf68a6 j_mayer
                        do_interrupt(env);
519 eddf68a6 j_mayer
                    }
520 0633879f pbrook
#elif defined(TARGET_M68K)
521 0633879f pbrook
                    if (interrupt_request & CPU_INTERRUPT_HARD
522 0633879f pbrook
                        && ((env->sr & SR_I) >> SR_I_SHIFT)
523 0633879f pbrook
                            < env->pending_level) {
524 0633879f pbrook
                        /* Real hardware gets the interrupt vector via an
525 0633879f pbrook
                           IACK cycle at this point.  Current emulated
526 0633879f pbrook
                           hardware doesn't rely on this, so we
527 0633879f pbrook
                           provide/save the vector when the interrupt is
528 0633879f pbrook
                           first signalled.  */
529 0633879f pbrook
                        env->exception_index = env->pending_vector;
530 0633879f pbrook
                        do_interrupt(1);
531 0633879f pbrook
                    }
532 68a79315 bellard
#endif
533 9d05095e bellard
                   /* Don't use the cached interupt_request value,
534 9d05095e bellard
                      do_interrupt may have updated the EXITTB flag. */
535 b5ff1b31 bellard
                    if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
536 bf3e8bf1 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
537 bf3e8bf1 bellard
                        /* ensure that no TB jump will be modified as
538 bf3e8bf1 bellard
                           the program flow was changed */
539 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
540 bf3e8bf1 bellard
                        tmp_T0 = 0;
541 bf3e8bf1 bellard
#else
542 bf3e8bf1 bellard
                        T0 = 0;
543 bf3e8bf1 bellard
#endif
544 bf3e8bf1 bellard
                    }
545 68a79315 bellard
                    if (interrupt_request & CPU_INTERRUPT_EXIT) {
546 68a79315 bellard
                        env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
547 68a79315 bellard
                        env->exception_index = EXCP_INTERRUPT;
548 68a79315 bellard
                        cpu_loop_exit();
549 68a79315 bellard
                    }
550 3fb2ded1 bellard
                }
551 7d13299d bellard
#ifdef DEBUG_EXEC
552 b5ff1b31 bellard
                if ((loglevel & CPU_LOG_TB_CPU)) {
553 3fb2ded1 bellard
                    /* restore flags in standard format */
554 ecb644f4 ths
                    regs_to_env();
555 ecb644f4 ths
#if defined(TARGET_I386)
556 3fb2ded1 bellard
                    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
557 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
558 3fb2ded1 bellard
                    env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
559 e4533c7a bellard
#elif defined(TARGET_ARM)
560 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
561 93ac68bc bellard
#elif defined(TARGET_SPARC)
562 3475187d bellard
                    REGWPTR = env->regbase + (env->cwp * 16);
563 3475187d bellard
                    env->regwptr = REGWPTR;
564 3475187d bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
565 67867308 bellard
#elif defined(TARGET_PPC)
566 7fe48483 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
567 e6e5906b pbrook
#elif defined(TARGET_M68K)
568 e6e5906b pbrook
                    cpu_m68k_flush_flags(env, env->cc_op);
569 e6e5906b pbrook
                    env->cc_op = CC_OP_FLAGS;
570 e6e5906b pbrook
                    env->sr = (env->sr & 0xffe0)
571 e6e5906b pbrook
                              | env->cc_dest | (env->cc_x << 4);
572 e6e5906b pbrook
                    cpu_dump_state(env, logfile, fprintf, 0);
573 6af0bf9c bellard
#elif defined(TARGET_MIPS)
574 6af0bf9c bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
575 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
576 fdf9b3e8 bellard
                    cpu_dump_state(env, logfile, fprintf, 0);
577 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
578 eddf68a6 j_mayer
                    cpu_dump_state(env, logfile, fprintf, 0);
579 e4533c7a bellard
#else
580 5fafdf24 ths
#error unsupported target CPU
581 e4533c7a bellard
#endif
582 3fb2ded1 bellard
                }
583 7d13299d bellard
#endif
584 8a40a180 bellard
                tb = tb_find_fast();
585 9d27abd9 bellard
#ifdef DEBUG_EXEC
586 c1135f61 bellard
                if ((loglevel & CPU_LOG_EXEC)) {
587 c27004ec bellard
                    fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
588 c27004ec bellard
                            (long)tb->tc_ptr, tb->pc,
589 c27004ec bellard
                            lookup_symbol(tb->pc));
590 3fb2ded1 bellard
                }
591 9d27abd9 bellard
#endif
592 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
593 3fb2ded1 bellard
                T0 = tmp_T0;
594 3b46e624 ths
#endif
595 8a40a180 bellard
                /* see if we can patch the calling TB. When the TB
596 8a40a180 bellard
                   spans two pages, we cannot safely do a direct
597 8a40a180 bellard
                   jump. */
598 c27004ec bellard
                {
599 8a40a180 bellard
                    if (T0 != 0 &&
600 f32fc648 bellard
#if USE_KQEMU
601 f32fc648 bellard
                        (env->kqemu_enabled != 2) &&
602 f32fc648 bellard
#endif
603 8a40a180 bellard
                        tb->page_addr[1] == -1
604 bf3e8bf1 bellard
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
605 5fafdf24 ths
                    && (tb->cflags & CF_CODE_COPY) ==
606 bf3e8bf1 bellard
                    (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
607 bf3e8bf1 bellard
#endif
608 bf3e8bf1 bellard
                    ) {
609 3fb2ded1 bellard
                    spin_lock(&tb_lock);
610 c27004ec bellard
                    tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
611 97eb5b14 bellard
#if defined(USE_CODE_COPY)
612 97eb5b14 bellard
                    /* propagates the FP use info */
613 5fafdf24 ths
                    ((TranslationBlock *)(T0 & ~3))->cflags |=
614 97eb5b14 bellard
                        (tb->cflags & CF_FP_USED);
615 97eb5b14 bellard
#endif
616 3fb2ded1 bellard
                    spin_unlock(&tb_lock);
617 3fb2ded1 bellard
                }
618 c27004ec bellard
                }
619 3fb2ded1 bellard
                tc_ptr = tb->tc_ptr;
620 83479e77 bellard
                env->current_tb = tb;
621 3fb2ded1 bellard
                /* execute the generated code */
622 3fb2ded1 bellard
                gen_func = (void *)tc_ptr;
623 8c6939c0 bellard
#if defined(__sparc__)
624 3fb2ded1 bellard
                __asm__ __volatile__("call        %0\n\t"
625 3fb2ded1 bellard
                                     "mov        %%o7,%%i0"
626 3fb2ded1 bellard
                                     : /* no outputs */
627 5fafdf24 ths
                                     : "r" (gen_func)
628 fdbb4691 bellard
                                     : "i0", "i1", "i2", "i3", "i4", "i5",
629 faab7592 ths
                                       "o0", "o1", "o2", "o3", "o4", "o5",
630 fdbb4691 bellard
                                       "l0", "l1", "l2", "l3", "l4", "l5",
631 fdbb4691 bellard
                                       "l6", "l7");
632 8c6939c0 bellard
#elif defined(__arm__)
633 3fb2ded1 bellard
                asm volatile ("mov pc, %0\n\t"
634 3fb2ded1 bellard
                              ".global exec_loop\n\t"
635 3fb2ded1 bellard
                              "exec_loop:\n\t"
636 3fb2ded1 bellard
                              : /* no outputs */
637 3fb2ded1 bellard
                              : "r" (gen_func)
638 3fb2ded1 bellard
                              : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
639 bf3e8bf1 bellard
#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
640 bf3e8bf1 bellard
{
641 bf3e8bf1 bellard
    if (!(tb->cflags & CF_CODE_COPY)) {
642 97eb5b14 bellard
        if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
643 97eb5b14 bellard
            save_native_fp_state(env);
644 97eb5b14 bellard
        }
645 bf3e8bf1 bellard
        gen_func();
646 bf3e8bf1 bellard
    } else {
647 97eb5b14 bellard
        if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
648 97eb5b14 bellard
            restore_native_fp_state(env);
649 97eb5b14 bellard
        }
650 bf3e8bf1 bellard
        /* we work with native eflags */
651 bf3e8bf1 bellard
        CC_SRC = cc_table[CC_OP].compute_all();
652 bf3e8bf1 bellard
        CC_OP = CC_OP_EFLAGS;
653 bf3e8bf1 bellard
        asm(".globl exec_loop\n"
654 bf3e8bf1 bellard
            "\n"
655 bf3e8bf1 bellard
            "debug1:\n"
656 bf3e8bf1 bellard
            "    pushl %%ebp\n"
657 bf3e8bf1 bellard
            "    fs movl %10, %9\n"
658 bf3e8bf1 bellard
            "    fs movl %11, %%eax\n"
659 bf3e8bf1 bellard
            "    andl $0x400, %%eax\n"
660 bf3e8bf1 bellard
            "    fs orl %8, %%eax\n"
661 bf3e8bf1 bellard
            "    pushl %%eax\n"
662 bf3e8bf1 bellard
            "    popf\n"
663 bf3e8bf1 bellard
            "    fs movl %%esp, %12\n"
664 bf3e8bf1 bellard
            "    fs movl %0, %%eax\n"
665 bf3e8bf1 bellard
            "    fs movl %1, %%ecx\n"
666 bf3e8bf1 bellard
            "    fs movl %2, %%edx\n"
667 bf3e8bf1 bellard
            "    fs movl %3, %%ebx\n"
668 bf3e8bf1 bellard
            "    fs movl %4, %%esp\n"
669 bf3e8bf1 bellard
            "    fs movl %5, %%ebp\n"
670 bf3e8bf1 bellard
            "    fs movl %6, %%esi\n"
671 bf3e8bf1 bellard
            "    fs movl %7, %%edi\n"
672 bf3e8bf1 bellard
            "    fs jmp *%9\n"
673 bf3e8bf1 bellard
            "exec_loop:\n"
674 bf3e8bf1 bellard
            "    fs movl %%esp, %4\n"
675 bf3e8bf1 bellard
            "    fs movl %12, %%esp\n"
676 bf3e8bf1 bellard
            "    fs movl %%eax, %0\n"
677 bf3e8bf1 bellard
            "    fs movl %%ecx, %1\n"
678 bf3e8bf1 bellard
            "    fs movl %%edx, %2\n"
679 bf3e8bf1 bellard
            "    fs movl %%ebx, %3\n"
680 bf3e8bf1 bellard
            "    fs movl %%ebp, %5\n"
681 bf3e8bf1 bellard
            "    fs movl %%esi, %6\n"
682 bf3e8bf1 bellard
            "    fs movl %%edi, %7\n"
683 bf3e8bf1 bellard
            "    pushf\n"
684 bf3e8bf1 bellard
            "    popl %%eax\n"
685 bf3e8bf1 bellard
            "    movl %%eax, %%ecx\n"
686 bf3e8bf1 bellard
            "    andl $0x400, %%ecx\n"
687 bf3e8bf1 bellard
            "    shrl $9, %%ecx\n"
688 bf3e8bf1 bellard
            "    andl $0x8d5, %%eax\n"
689 bf3e8bf1 bellard
            "    fs movl %%eax, %8\n"
690 bf3e8bf1 bellard
            "    movl $1, %%eax\n"
691 bf3e8bf1 bellard
            "    subl %%ecx, %%eax\n"
692 bf3e8bf1 bellard
            "    fs movl %%eax, %11\n"
693 bf3e8bf1 bellard
            "    fs movl %9, %%ebx\n" /* get T0 value */
694 bf3e8bf1 bellard
            "    popl %%ebp\n"
695 bf3e8bf1 bellard
            :
696 bf3e8bf1 bellard
            : "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
697 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[1])),
698 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[2])),
699 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[3])),
700 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[4])),
701 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
702 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[6])),
703 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, regs[7])),
704 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, cc_src)),
705 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, tmp0)),
706 bf3e8bf1 bellard
            "a" (gen_func),
707 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, df)),
708 bf3e8bf1 bellard
            "m" (*(uint8_t *)offsetof(CPUState, saved_esp))
709 bf3e8bf1 bellard
            : "%ecx", "%edx"
710 bf3e8bf1 bellard
            );
711 bf3e8bf1 bellard
    }
712 bf3e8bf1 bellard
}
713 b8076a74 bellard
#elif defined(__ia64)
714 b8076a74 bellard
                struct fptr {
715 b8076a74 bellard
                        void *ip;
716 b8076a74 bellard
                        void *gp;
717 b8076a74 bellard
                } fp;
718 b8076a74 bellard
719 b8076a74 bellard
                fp.ip = tc_ptr;
720 b8076a74 bellard
                fp.gp = code_gen_buffer + 2 * (1 << 20);
721 b8076a74 bellard
                (*(void (*)(void)) &fp)();
722 ae228531 bellard
#else
723 3fb2ded1 bellard
                gen_func();
724 ae228531 bellard
#endif
725 83479e77 bellard
                env->current_tb = NULL;
726 4cbf74b6 bellard
                /* reset soft MMU for next block (it can currently
727 4cbf74b6 bellard
                   only be set by a memory fault) */
728 4cbf74b6 bellard
#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
729 3f337316 bellard
                if (env->hflags & HF_SOFTMMU_MASK) {
730 3f337316 bellard
                    env->hflags &= ~HF_SOFTMMU_MASK;
731 4cbf74b6 bellard
                    /* do not allow linking to another block */
732 4cbf74b6 bellard
                    T0 = 0;
733 4cbf74b6 bellard
                }
734 4cbf74b6 bellard
#endif
735 f32fc648 bellard
#if defined(USE_KQEMU)
736 f32fc648 bellard
#define MIN_CYCLE_BEFORE_SWITCH (100 * 1000)
737 f32fc648 bellard
                if (kqemu_is_ok(env) &&
738 f32fc648 bellard
                    (cpu_get_time_fast() - env->last_io_time) >= MIN_CYCLE_BEFORE_SWITCH) {
739 f32fc648 bellard
                    cpu_loop_exit();
740 f32fc648 bellard
                }
741 f32fc648 bellard
#endif
742 50a518e3 ths
            } /* for(;;) */
743 3fb2ded1 bellard
        } else {
744 0d1a29f9 bellard
            env_to_regs();
745 7d13299d bellard
        }
746 3fb2ded1 bellard
    } /* for(;;) */
747 3fb2ded1 bellard
748 7d13299d bellard
749 e4533c7a bellard
#if defined(TARGET_I386)
750 97eb5b14 bellard
#if defined(USE_CODE_COPY)
751 97eb5b14 bellard
    if (env->native_fp_regs) {
752 97eb5b14 bellard
        save_native_fp_state(env);
753 97eb5b14 bellard
    }
754 97eb5b14 bellard
#endif
755 9de5e440 bellard
    /* restore flags in standard format */
756 fc2b4c48 bellard
    env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
757 e4533c7a bellard
#elif defined(TARGET_ARM)
758 b7bcbe95 bellard
    /* XXX: Save/restore host fpu exception state?.  */
759 93ac68bc bellard
#elif defined(TARGET_SPARC)
760 3475187d bellard
#if defined(reg_REGWPTR)
761 3475187d bellard
    REGWPTR = saved_regwptr;
762 3475187d bellard
#endif
763 67867308 bellard
#elif defined(TARGET_PPC)
764 e6e5906b pbrook
#elif defined(TARGET_M68K)
765 e6e5906b pbrook
    cpu_m68k_flush_flags(env, env->cc_op);
766 e6e5906b pbrook
    env->cc_op = CC_OP_FLAGS;
767 e6e5906b pbrook
    env->sr = (env->sr & 0xffe0)
768 e6e5906b pbrook
              | env->cc_dest | (env->cc_x << 4);
769 6af0bf9c bellard
#elif defined(TARGET_MIPS)
770 fdf9b3e8 bellard
#elif defined(TARGET_SH4)
771 eddf68a6 j_mayer
#elif defined(TARGET_ALPHA)
772 fdf9b3e8 bellard
    /* XXXXX */
773 e4533c7a bellard
#else
774 e4533c7a bellard
#error unsupported target CPU
775 e4533c7a bellard
#endif
776 1057eaa7 pbrook
777 1057eaa7 pbrook
    /* restore global registers */
778 fdbb4691 bellard
#if defined(__sparc__) && !defined(HOST_SOLARIS)
779 8c6939c0 bellard
    asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
780 8c6939c0 bellard
#endif
781 1057eaa7 pbrook
#include "hostregs_helper.h"
782 1057eaa7 pbrook
783 6a00d601 bellard
    /* fail safe : never use cpu_single_env outside cpu_exec() */
784 5fafdf24 ths
    cpu_single_env = NULL;
785 7d13299d bellard
    return ret;
786 7d13299d bellard
}
787 6dbad63e bellard
788 fbf9eeb3 bellard
/* must only be called from the generated code as an exception can be
789 fbf9eeb3 bellard
   generated */
790 fbf9eeb3 bellard
void tb_invalidate_page_range(target_ulong start, target_ulong end)
791 fbf9eeb3 bellard
{
792 dc5d0b3d bellard
    /* XXX: cannot enable it yet because it yields to MMU exception
793 dc5d0b3d bellard
       where NIP != read address on PowerPC */
794 dc5d0b3d bellard
#if 0
795 fbf9eeb3 bellard
    target_ulong phys_addr;
796 fbf9eeb3 bellard
    phys_addr = get_phys_addr_code(env, start);
797 fbf9eeb3 bellard
    tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
798 dc5d0b3d bellard
#endif
799 fbf9eeb3 bellard
}
800 fbf9eeb3 bellard
801 1a18c71b bellard
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
802 e4533c7a bellard
803 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
804 6dbad63e bellard
{
805 6dbad63e bellard
    CPUX86State *saved_env;
806 6dbad63e bellard
807 6dbad63e bellard
    saved_env = env;
808 6dbad63e bellard
    env = s;
809 a412ac57 bellard
    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
810 a513fe19 bellard
        selector &= 0xffff;
811 5fafdf24 ths
        cpu_x86_load_seg_cache(env, seg_reg, selector,
812 c27004ec bellard
                               (selector << 4), 0xffff, 0);
813 a513fe19 bellard
    } else {
814 b453b70b bellard
        load_seg(seg_reg, selector);
815 a513fe19 bellard
    }
816 6dbad63e bellard
    env = saved_env;
817 6dbad63e bellard
}
818 9de5e440 bellard
819 d0a1ffc9 bellard
void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)
820 d0a1ffc9 bellard
{
821 d0a1ffc9 bellard
    CPUX86State *saved_env;
822 d0a1ffc9 bellard
823 d0a1ffc9 bellard
    saved_env = env;
824 d0a1ffc9 bellard
    env = s;
825 3b46e624 ths
826 c27004ec bellard
    helper_fsave((target_ulong)ptr, data32);
827 d0a1ffc9 bellard
828 d0a1ffc9 bellard
    env = saved_env;
829 d0a1ffc9 bellard
}
830 d0a1ffc9 bellard
831 d0a1ffc9 bellard
void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
832 d0a1ffc9 bellard
{
833 d0a1ffc9 bellard
    CPUX86State *saved_env;
834 d0a1ffc9 bellard
835 d0a1ffc9 bellard
    saved_env = env;
836 d0a1ffc9 bellard
    env = s;
837 3b46e624 ths
838 c27004ec bellard
    helper_frstor((target_ulong)ptr, data32);
839 d0a1ffc9 bellard
840 d0a1ffc9 bellard
    env = saved_env;
841 d0a1ffc9 bellard
}
842 d0a1ffc9 bellard
843 e4533c7a bellard
#endif /* TARGET_I386 */
844 e4533c7a bellard
845 67b915a5 bellard
#if !defined(CONFIG_SOFTMMU)
846 67b915a5 bellard
847 3fb2ded1 bellard
#if defined(TARGET_I386)
848 3fb2ded1 bellard
849 b56dad1c bellard
/* 'pc' is the host PC at which the exception was raised. 'address' is
850 fd6ce8f6 bellard
   the effective address of the memory exception. 'is_write' is 1 if a
851 fd6ce8f6 bellard
   write caused the exception and otherwise 0'. 'old_set' is the
852 fd6ce8f6 bellard
   signal set which should be restored */
853 2b413144 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
854 5fafdf24 ths
                                    int is_write, sigset_t *old_set,
855 bf3e8bf1 bellard
                                    void *puc)
856 9de5e440 bellard
{
857 a513fe19 bellard
    TranslationBlock *tb;
858 a513fe19 bellard
    int ret;
859 68a79315 bellard
860 83479e77 bellard
    if (cpu_single_env)
861 83479e77 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
862 fd6ce8f6 bellard
#if defined(DEBUG_SIGNAL)
863 5fafdf24 ths
    qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
864 bf3e8bf1 bellard
                pc, address, is_write, *(unsigned long *)old_set);
865 9de5e440 bellard
#endif
866 25eb4484 bellard
    /* XXX: locking issue */
867 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
868 fd6ce8f6 bellard
        return 1;
869 fd6ce8f6 bellard
    }
870 fbf9eeb3 bellard
871 3fb2ded1 bellard
    /* see if it is an MMU fault */
872 5fafdf24 ths
    ret = cpu_x86_handle_mmu_fault(env, address, is_write,
873 93a40ea9 bellard
                                   ((env->hflags & HF_CPL_MASK) == 3), 0);
874 3fb2ded1 bellard
    if (ret < 0)
875 3fb2ded1 bellard
        return 0; /* not an MMU fault */
876 3fb2ded1 bellard
    if (ret == 0)
877 3fb2ded1 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
878 3fb2ded1 bellard
    /* now we have a real cpu fault */
879 a513fe19 bellard
    tb = tb_find_pc(pc);
880 a513fe19 bellard
    if (tb) {
881 9de5e440 bellard
        /* the PC is inside the translated code. It means that we have
882 9de5e440 bellard
           a virtual CPU fault */
883 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, puc);
884 3fb2ded1 bellard
    }
885 4cbf74b6 bellard
    if (ret == 1) {
886 3fb2ded1 bellard
#if 0
887 5fafdf24 ths
        printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
888 4cbf74b6 bellard
               env->eip, env->cr[2], env->error_code);
889 3fb2ded1 bellard
#endif
890 4cbf74b6 bellard
        /* we restore the process signal mask as the sigreturn should
891 4cbf74b6 bellard
           do it (XXX: use sigsetjmp) */
892 4cbf74b6 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
893 54ca9095 bellard
        raise_exception_err(env->exception_index, env->error_code);
894 4cbf74b6 bellard
    } else {
895 4cbf74b6 bellard
        /* activate soft MMU for this block */
896 3f337316 bellard
        env->hflags |= HF_SOFTMMU_MASK;
897 fbf9eeb3 bellard
        cpu_resume_from_signal(env, puc);
898 4cbf74b6 bellard
    }
899 3fb2ded1 bellard
    /* never comes here */
900 3fb2ded1 bellard
    return 1;
901 3fb2ded1 bellard
}
902 3fb2ded1 bellard
903 e4533c7a bellard
#elif defined(TARGET_ARM)
904 3fb2ded1 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
905 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
906 bf3e8bf1 bellard
                                    void *puc)
907 3fb2ded1 bellard
{
908 68016c62 bellard
    TranslationBlock *tb;
909 68016c62 bellard
    int ret;
910 68016c62 bellard
911 68016c62 bellard
    if (cpu_single_env)
912 68016c62 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
913 68016c62 bellard
#if defined(DEBUG_SIGNAL)
914 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
915 68016c62 bellard
           pc, address, is_write, *(unsigned long *)old_set);
916 68016c62 bellard
#endif
917 9f0777ed bellard
    /* XXX: locking issue */
918 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
919 9f0777ed bellard
        return 1;
920 9f0777ed bellard
    }
921 68016c62 bellard
    /* see if it is an MMU fault */
922 68016c62 bellard
    ret = cpu_arm_handle_mmu_fault(env, address, is_write, 1, 0);
923 68016c62 bellard
    if (ret < 0)
924 68016c62 bellard
        return 0; /* not an MMU fault */
925 68016c62 bellard
    if (ret == 0)
926 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
927 68016c62 bellard
    /* now we have a real cpu fault */
928 68016c62 bellard
    tb = tb_find_pc(pc);
929 68016c62 bellard
    if (tb) {
930 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
931 68016c62 bellard
           a virtual CPU fault */
932 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
933 68016c62 bellard
    }
934 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
935 68016c62 bellard
       do it (XXX: use sigsetjmp) */
936 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
937 68016c62 bellard
    cpu_loop_exit();
938 3fb2ded1 bellard
}
939 93ac68bc bellard
#elif defined(TARGET_SPARC)
940 93ac68bc bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
941 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
942 bf3e8bf1 bellard
                                    void *puc)
943 93ac68bc bellard
{
944 68016c62 bellard
    TranslationBlock *tb;
945 68016c62 bellard
    int ret;
946 68016c62 bellard
947 68016c62 bellard
    if (cpu_single_env)
948 68016c62 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
949 68016c62 bellard
#if defined(DEBUG_SIGNAL)
950 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
951 68016c62 bellard
           pc, address, is_write, *(unsigned long *)old_set);
952 68016c62 bellard
#endif
953 b453b70b bellard
    /* XXX: locking issue */
954 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
955 b453b70b bellard
        return 1;
956 b453b70b bellard
    }
957 68016c62 bellard
    /* see if it is an MMU fault */
958 68016c62 bellard
    ret = cpu_sparc_handle_mmu_fault(env, address, is_write, 1, 0);
959 68016c62 bellard
    if (ret < 0)
960 68016c62 bellard
        return 0; /* not an MMU fault */
961 68016c62 bellard
    if (ret == 0)
962 68016c62 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
963 68016c62 bellard
    /* now we have a real cpu fault */
964 68016c62 bellard
    tb = tb_find_pc(pc);
965 68016c62 bellard
    if (tb) {
966 68016c62 bellard
        /* the PC is inside the translated code. It means that we have
967 68016c62 bellard
           a virtual CPU fault */
968 68016c62 bellard
        cpu_restore_state(tb, env, pc, puc);
969 68016c62 bellard
    }
970 68016c62 bellard
    /* we restore the process signal mask as the sigreturn should
971 68016c62 bellard
       do it (XXX: use sigsetjmp) */
972 68016c62 bellard
    sigprocmask(SIG_SETMASK, old_set, NULL);
973 68016c62 bellard
    cpu_loop_exit();
974 93ac68bc bellard
}
975 67867308 bellard
#elif defined (TARGET_PPC)
976 67867308 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
977 bf3e8bf1 bellard
                                    int is_write, sigset_t *old_set,
978 bf3e8bf1 bellard
                                    void *puc)
979 67867308 bellard
{
980 67867308 bellard
    TranslationBlock *tb;
981 ce09776b bellard
    int ret;
982 3b46e624 ths
983 67867308 bellard
    if (cpu_single_env)
984 67867308 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
985 67867308 bellard
#if defined(DEBUG_SIGNAL)
986 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
987 67867308 bellard
           pc, address, is_write, *(unsigned long *)old_set);
988 67867308 bellard
#endif
989 67867308 bellard
    /* XXX: locking issue */
990 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
991 67867308 bellard
        return 1;
992 67867308 bellard
    }
993 67867308 bellard
994 ce09776b bellard
    /* see if it is an MMU fault */
995 7f957d28 bellard
    ret = cpu_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 0);
996 ce09776b bellard
    if (ret < 0)
997 ce09776b bellard
        return 0; /* not an MMU fault */
998 ce09776b bellard
    if (ret == 0)
999 ce09776b bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1000 ce09776b bellard
1001 67867308 bellard
    /* now we have a real cpu fault */
1002 67867308 bellard
    tb = tb_find_pc(pc);
1003 67867308 bellard
    if (tb) {
1004 67867308 bellard
        /* the PC is inside the translated code. It means that we have
1005 67867308 bellard
           a virtual CPU fault */
1006 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, puc);
1007 67867308 bellard
    }
1008 ce09776b bellard
    if (ret == 1) {
1009 67867308 bellard
#if 0
1010 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1011 ce09776b bellard
               env->nip, env->error_code, tb);
1012 67867308 bellard
#endif
1013 67867308 bellard
    /* we restore the process signal mask as the sigreturn should
1014 67867308 bellard
       do it (XXX: use sigsetjmp) */
1015 bf3e8bf1 bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
1016 9fddaa0c bellard
        do_raise_exception_err(env->exception_index, env->error_code);
1017 ce09776b bellard
    } else {
1018 ce09776b bellard
        /* activate soft MMU for this block */
1019 fbf9eeb3 bellard
        cpu_resume_from_signal(env, puc);
1020 ce09776b bellard
    }
1021 67867308 bellard
    /* never comes here */
1022 e6e5906b pbrook
    return 1;
1023 e6e5906b pbrook
}
1024 e6e5906b pbrook
1025 e6e5906b pbrook
#elif defined(TARGET_M68K)
1026 e6e5906b pbrook
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1027 e6e5906b pbrook
                                    int is_write, sigset_t *old_set,
1028 e6e5906b pbrook
                                    void *puc)
1029 e6e5906b pbrook
{
1030 e6e5906b pbrook
    TranslationBlock *tb;
1031 e6e5906b pbrook
    int ret;
1032 e6e5906b pbrook
1033 e6e5906b pbrook
    if (cpu_single_env)
1034 e6e5906b pbrook
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1035 e6e5906b pbrook
#if defined(DEBUG_SIGNAL)
1036 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1037 e6e5906b pbrook
           pc, address, is_write, *(unsigned long *)old_set);
1038 e6e5906b pbrook
#endif
1039 e6e5906b pbrook
    /* XXX: locking issue */
1040 e6e5906b pbrook
    if (is_write && page_unprotect(address, pc, puc)) {
1041 e6e5906b pbrook
        return 1;
1042 e6e5906b pbrook
    }
1043 e6e5906b pbrook
    /* see if it is an MMU fault */
1044 e6e5906b pbrook
    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0);
1045 e6e5906b pbrook
    if (ret < 0)
1046 e6e5906b pbrook
        return 0; /* not an MMU fault */
1047 e6e5906b pbrook
    if (ret == 0)
1048 e6e5906b pbrook
        return 1; /* the MMU fault was handled without causing real CPU fault */
1049 e6e5906b pbrook
    /* now we have a real cpu fault */
1050 e6e5906b pbrook
    tb = tb_find_pc(pc);
1051 e6e5906b pbrook
    if (tb) {
1052 e6e5906b pbrook
        /* the PC is inside the translated code. It means that we have
1053 e6e5906b pbrook
           a virtual CPU fault */
1054 e6e5906b pbrook
        cpu_restore_state(tb, env, pc, puc);
1055 e6e5906b pbrook
    }
1056 e6e5906b pbrook
    /* we restore the process signal mask as the sigreturn should
1057 e6e5906b pbrook
       do it (XXX: use sigsetjmp) */
1058 e6e5906b pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
1059 e6e5906b pbrook
    cpu_loop_exit();
1060 e6e5906b pbrook
    /* never comes here */
1061 67867308 bellard
    return 1;
1062 67867308 bellard
}
1063 6af0bf9c bellard
1064 6af0bf9c bellard
#elif defined (TARGET_MIPS)
1065 6af0bf9c bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1066 6af0bf9c bellard
                                    int is_write, sigset_t *old_set,
1067 6af0bf9c bellard
                                    void *puc)
1068 6af0bf9c bellard
{
1069 6af0bf9c bellard
    TranslationBlock *tb;
1070 6af0bf9c bellard
    int ret;
1071 3b46e624 ths
1072 6af0bf9c bellard
    if (cpu_single_env)
1073 6af0bf9c bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1074 6af0bf9c bellard
#if defined(DEBUG_SIGNAL)
1075 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1076 6af0bf9c bellard
           pc, address, is_write, *(unsigned long *)old_set);
1077 6af0bf9c bellard
#endif
1078 6af0bf9c bellard
    /* XXX: locking issue */
1079 53a5960a pbrook
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1080 6af0bf9c bellard
        return 1;
1081 6af0bf9c bellard
    }
1082 6af0bf9c bellard
1083 6af0bf9c bellard
    /* see if it is an MMU fault */
1084 cc9442b9 bellard
    ret = cpu_mips_handle_mmu_fault(env, address, is_write, 1, 0);
1085 6af0bf9c bellard
    if (ret < 0)
1086 6af0bf9c bellard
        return 0; /* not an MMU fault */
1087 6af0bf9c bellard
    if (ret == 0)
1088 6af0bf9c bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1089 6af0bf9c bellard
1090 6af0bf9c bellard
    /* now we have a real cpu fault */
1091 6af0bf9c bellard
    tb = tb_find_pc(pc);
1092 6af0bf9c bellard
    if (tb) {
1093 6af0bf9c bellard
        /* the PC is inside the translated code. It means that we have
1094 6af0bf9c bellard
           a virtual CPU fault */
1095 6af0bf9c bellard
        cpu_restore_state(tb, env, pc, puc);
1096 6af0bf9c bellard
    }
1097 6af0bf9c bellard
    if (ret == 1) {
1098 6af0bf9c bellard
#if 0
1099 5fafdf24 ths
        printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
1100 1eb5207b ths
               env->PC, env->error_code, tb);
1101 6af0bf9c bellard
#endif
1102 6af0bf9c bellard
    /* we restore the process signal mask as the sigreturn should
1103 6af0bf9c bellard
       do it (XXX: use sigsetjmp) */
1104 6af0bf9c bellard
        sigprocmask(SIG_SETMASK, old_set, NULL);
1105 6af0bf9c bellard
        do_raise_exception_err(env->exception_index, env->error_code);
1106 6af0bf9c bellard
    } else {
1107 6af0bf9c bellard
        /* activate soft MMU for this block */
1108 6af0bf9c bellard
        cpu_resume_from_signal(env, puc);
1109 6af0bf9c bellard
    }
1110 6af0bf9c bellard
    /* never comes here */
1111 6af0bf9c bellard
    return 1;
1112 6af0bf9c bellard
}
1113 6af0bf9c bellard
1114 fdf9b3e8 bellard
#elif defined (TARGET_SH4)
1115 fdf9b3e8 bellard
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1116 fdf9b3e8 bellard
                                    int is_write, sigset_t *old_set,
1117 fdf9b3e8 bellard
                                    void *puc)
1118 fdf9b3e8 bellard
{
1119 fdf9b3e8 bellard
    TranslationBlock *tb;
1120 fdf9b3e8 bellard
    int ret;
1121 3b46e624 ths
1122 fdf9b3e8 bellard
    if (cpu_single_env)
1123 fdf9b3e8 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1124 fdf9b3e8 bellard
#if defined(DEBUG_SIGNAL)
1125 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1126 fdf9b3e8 bellard
           pc, address, is_write, *(unsigned long *)old_set);
1127 fdf9b3e8 bellard
#endif
1128 fdf9b3e8 bellard
    /* XXX: locking issue */
1129 fdf9b3e8 bellard
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1130 fdf9b3e8 bellard
        return 1;
1131 fdf9b3e8 bellard
    }
1132 fdf9b3e8 bellard
1133 fdf9b3e8 bellard
    /* see if it is an MMU fault */
1134 fdf9b3e8 bellard
    ret = cpu_sh4_handle_mmu_fault(env, address, is_write, 1, 0);
1135 fdf9b3e8 bellard
    if (ret < 0)
1136 fdf9b3e8 bellard
        return 0; /* not an MMU fault */
1137 fdf9b3e8 bellard
    if (ret == 0)
1138 fdf9b3e8 bellard
        return 1; /* the MMU fault was handled without causing real CPU fault */
1139 fdf9b3e8 bellard
1140 fdf9b3e8 bellard
    /* now we have a real cpu fault */
1141 eddf68a6 j_mayer
    tb = tb_find_pc(pc);
1142 eddf68a6 j_mayer
    if (tb) {
1143 eddf68a6 j_mayer
        /* the PC is inside the translated code. It means that we have
1144 eddf68a6 j_mayer
           a virtual CPU fault */
1145 eddf68a6 j_mayer
        cpu_restore_state(tb, env, pc, puc);
1146 eddf68a6 j_mayer
    }
1147 eddf68a6 j_mayer
#if 0
1148 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1149 eddf68a6 j_mayer
               env->nip, env->error_code, tb);
1150 eddf68a6 j_mayer
#endif
1151 eddf68a6 j_mayer
    /* we restore the process signal mask as the sigreturn should
1152 eddf68a6 j_mayer
       do it (XXX: use sigsetjmp) */
1153 eddf68a6 j_mayer
    sigprocmask(SIG_SETMASK, old_set, NULL);
1154 eddf68a6 j_mayer
    cpu_loop_exit();
1155 eddf68a6 j_mayer
    /* never comes here */
1156 eddf68a6 j_mayer
    return 1;
1157 eddf68a6 j_mayer
}
1158 eddf68a6 j_mayer
1159 eddf68a6 j_mayer
#elif defined (TARGET_ALPHA)
1160 eddf68a6 j_mayer
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
1161 eddf68a6 j_mayer
                                    int is_write, sigset_t *old_set,
1162 eddf68a6 j_mayer
                                    void *puc)
1163 eddf68a6 j_mayer
{
1164 eddf68a6 j_mayer
    TranslationBlock *tb;
1165 eddf68a6 j_mayer
    int ret;
1166 3b46e624 ths
1167 eddf68a6 j_mayer
    if (cpu_single_env)
1168 eddf68a6 j_mayer
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1169 eddf68a6 j_mayer
#if defined(DEBUG_SIGNAL)
1170 5fafdf24 ths
    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
1171 eddf68a6 j_mayer
           pc, address, is_write, *(unsigned long *)old_set);
1172 eddf68a6 j_mayer
#endif
1173 eddf68a6 j_mayer
    /* XXX: locking issue */
1174 eddf68a6 j_mayer
    if (is_write && page_unprotect(h2g(address), pc, puc)) {
1175 eddf68a6 j_mayer
        return 1;
1176 eddf68a6 j_mayer
    }
1177 eddf68a6 j_mayer
1178 eddf68a6 j_mayer
    /* see if it is an MMU fault */
1179 eddf68a6 j_mayer
    ret = cpu_alpha_handle_mmu_fault(env, address, is_write, 1, 0);
1180 eddf68a6 j_mayer
    if (ret < 0)
1181 eddf68a6 j_mayer
        return 0; /* not an MMU fault */
1182 eddf68a6 j_mayer
    if (ret == 0)
1183 eddf68a6 j_mayer
        return 1; /* the MMU fault was handled without causing real CPU fault */
1184 eddf68a6 j_mayer
1185 eddf68a6 j_mayer
    /* now we have a real cpu fault */
1186 fdf9b3e8 bellard
    tb = tb_find_pc(pc);
1187 fdf9b3e8 bellard
    if (tb) {
1188 fdf9b3e8 bellard
        /* the PC is inside the translated code. It means that we have
1189 fdf9b3e8 bellard
           a virtual CPU fault */
1190 fdf9b3e8 bellard
        cpu_restore_state(tb, env, pc, puc);
1191 fdf9b3e8 bellard
    }
1192 fdf9b3e8 bellard
#if 0
1193 5fafdf24 ths
        printf("PF exception: NIP=0x%08x error=0x%x %p\n",
1194 fdf9b3e8 bellard
               env->nip, env->error_code, tb);
1195 fdf9b3e8 bellard
#endif
1196 fdf9b3e8 bellard
    /* we restore the process signal mask as the sigreturn should
1197 fdf9b3e8 bellard
       do it (XXX: use sigsetjmp) */
1198 355fb23d pbrook
    sigprocmask(SIG_SETMASK, old_set, NULL);
1199 355fb23d pbrook
    cpu_loop_exit();
1200 fdf9b3e8 bellard
    /* never comes here */
1201 fdf9b3e8 bellard
    return 1;
1202 fdf9b3e8 bellard
}
1203 e4533c7a bellard
#else
1204 e4533c7a bellard
#error unsupported target CPU
1205 e4533c7a bellard
#endif
1206 9de5e440 bellard
1207 2b413144 bellard
#if defined(__i386__)
1208 2b413144 bellard
1209 d8ecc0b9 bellard
#if defined(__APPLE__)
1210 d8ecc0b9 bellard
# include <sys/ucontext.h>
1211 d8ecc0b9 bellard
1212 d8ecc0b9 bellard
# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
1213 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
1214 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
1215 d8ecc0b9 bellard
#else
1216 d8ecc0b9 bellard
# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
1217 d8ecc0b9 bellard
# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
1218 d8ecc0b9 bellard
# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
1219 d8ecc0b9 bellard
#endif
1220 d8ecc0b9 bellard
1221 bf3e8bf1 bellard
#if defined(USE_CODE_COPY)
1222 5fafdf24 ths
static void cpu_send_trap(unsigned long pc, int trap,
1223 bf3e8bf1 bellard
                          struct ucontext *uc)
1224 bf3e8bf1 bellard
{
1225 bf3e8bf1 bellard
    TranslationBlock *tb;
1226 bf3e8bf1 bellard
1227 bf3e8bf1 bellard
    if (cpu_single_env)
1228 bf3e8bf1 bellard
        env = cpu_single_env; /* XXX: find a correct solution for multithread */
1229 bf3e8bf1 bellard
    /* now we have a real cpu fault */
1230 bf3e8bf1 bellard
    tb = tb_find_pc(pc);
1231 bf3e8bf1 bellard
    if (tb) {
1232 bf3e8bf1 bellard
        /* the PC is inside the translated code. It means that we have
1233 bf3e8bf1 bellard
           a virtual CPU fault */
1234 bf3e8bf1 bellard
        cpu_restore_state(tb, env, pc, uc);
1235 bf3e8bf1 bellard
    }
1236 bf3e8bf1 bellard
    sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
1237 bf3e8bf1 bellard
    raise_exception_err(trap, env->error_code);
1238 bf3e8bf1 bellard
}
1239 bf3e8bf1 bellard
#endif
1240 bf3e8bf1 bellard
1241 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1242 e4533c7a bellard
                       void *puc)
1243 9de5e440 bellard
{
1244 5a7b542b ths
    siginfo_t *info = pinfo;
1245 9de5e440 bellard
    struct ucontext *uc = puc;
1246 9de5e440 bellard
    unsigned long pc;
1247 bf3e8bf1 bellard
    int trapno;
1248 97eb5b14 bellard
1249 d691f669 bellard
#ifndef REG_EIP
1250 d691f669 bellard
/* for glibc 2.1 */
1251 fd6ce8f6 bellard
#define REG_EIP    EIP
1252 fd6ce8f6 bellard
#define REG_ERR    ERR
1253 fd6ce8f6 bellard
#define REG_TRAPNO TRAPNO
1254 d691f669 bellard
#endif
1255 d8ecc0b9 bellard
    pc = EIP_sig(uc);
1256 d8ecc0b9 bellard
    trapno = TRAP_sig(uc);
1257 bf3e8bf1 bellard
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
1258 bf3e8bf1 bellard
    if (trapno == 0x00 || trapno == 0x05) {
1259 bf3e8bf1 bellard
        /* send division by zero or bound exception */
1260 bf3e8bf1 bellard
        cpu_send_trap(pc, trapno, uc);
1261 bf3e8bf1 bellard
        return 1;
1262 bf3e8bf1 bellard
    } else
1263 bf3e8bf1 bellard
#endif
1264 5fafdf24 ths
        return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1265 5fafdf24 ths
                                 trapno == 0xe ?
1266 d8ecc0b9 bellard
                                 (ERROR_sig(uc) >> 1) & 1 : 0,
1267 bf3e8bf1 bellard
                                 &uc->uc_sigmask, puc);
1268 2b413144 bellard
}
1269 2b413144 bellard
1270 bc51c5c9 bellard
#elif defined(__x86_64__)
1271 bc51c5c9 bellard
1272 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo,
1273 bc51c5c9 bellard
                       void *puc)
1274 bc51c5c9 bellard
{
1275 5a7b542b ths
    siginfo_t *info = pinfo;
1276 bc51c5c9 bellard
    struct ucontext *uc = puc;
1277 bc51c5c9 bellard
    unsigned long pc;
1278 bc51c5c9 bellard
1279 bc51c5c9 bellard
    pc = uc->uc_mcontext.gregs[REG_RIP];
1280 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1281 5fafdf24 ths
                             uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
1282 bc51c5c9 bellard
                             (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
1283 bc51c5c9 bellard
                             &uc->uc_sigmask, puc);
1284 bc51c5c9 bellard
}
1285 bc51c5c9 bellard
1286 83fb7adf bellard
#elif defined(__powerpc__)
1287 2b413144 bellard
1288 83fb7adf bellard
/***********************************************************************
1289 83fb7adf bellard
 * signal context platform-specific definitions
1290 83fb7adf bellard
 * From Wine
1291 83fb7adf bellard
 */
1292 83fb7adf bellard
#ifdef linux
1293 83fb7adf bellard
/* All Registers access - only for local access */
1294 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext.regs->reg_name)
1295 83fb7adf bellard
/* Gpr Registers access  */
1296 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(gpr[reg_num], context)
1297 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(nip, context)        /* Program counter */
1298 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(msr, context)   /* Machine State Register (Supervisor) */
1299 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)   /* Count register */
1300 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* User's integer exception register */
1301 83fb7adf bellard
# define LR_sig(context)                        REG_sig(link, context) /* Link register */
1302 83fb7adf bellard
# define CR_sig(context)                        REG_sig(ccr, context) /* Condition register */
1303 83fb7adf bellard
/* Float Registers access  */
1304 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
1305 83fb7adf bellard
# define FPSCR_sig(context)                        (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
1306 83fb7adf bellard
/* Exception Registers access */
1307 83fb7adf bellard
# define DAR_sig(context)                        REG_sig(dar, context)
1308 83fb7adf bellard
# define DSISR_sig(context)                        REG_sig(dsisr, context)
1309 83fb7adf bellard
# define TRAP_sig(context)                        REG_sig(trap, context)
1310 83fb7adf bellard
#endif /* linux */
1311 83fb7adf bellard
1312 83fb7adf bellard
#ifdef __APPLE__
1313 83fb7adf bellard
# include <sys/ucontext.h>
1314 83fb7adf bellard
typedef struct ucontext SIGCONTEXT;
1315 83fb7adf bellard
/* All Registers access - only for local access */
1316 83fb7adf bellard
# define REG_sig(reg_name, context)                ((context)->uc_mcontext->ss.reg_name)
1317 83fb7adf bellard
# define FLOATREG_sig(reg_name, context)        ((context)->uc_mcontext->fs.reg_name)
1318 83fb7adf bellard
# define EXCEPREG_sig(reg_name, context)        ((context)->uc_mcontext->es.reg_name)
1319 83fb7adf bellard
# define VECREG_sig(reg_name, context)                ((context)->uc_mcontext->vs.reg_name)
1320 83fb7adf bellard
/* Gpr Registers access */
1321 83fb7adf bellard
# define GPR_sig(reg_num, context)                REG_sig(r##reg_num, context)
1322 83fb7adf bellard
# define IAR_sig(context)                        REG_sig(srr0, context)        /* Program counter */
1323 83fb7adf bellard
# define MSR_sig(context)                        REG_sig(srr1, context)  /* Machine State Register (Supervisor) */
1324 83fb7adf bellard
# define CTR_sig(context)                        REG_sig(ctr, context)
1325 83fb7adf bellard
# define XER_sig(context)                        REG_sig(xer, context) /* Link register */
1326 83fb7adf bellard
# define LR_sig(context)                        REG_sig(lr, context)  /* User's integer exception register */
1327 83fb7adf bellard
# define CR_sig(context)                        REG_sig(cr, context)  /* Condition register */
1328 83fb7adf bellard
/* Float Registers access */
1329 83fb7adf bellard
# define FLOAT_sig(reg_num, context)                FLOATREG_sig(fpregs[reg_num], context)
1330 83fb7adf bellard
# define FPSCR_sig(context)                        ((double)FLOATREG_sig(fpscr, context))
1331 83fb7adf bellard
/* Exception Registers access */
1332 83fb7adf bellard
# define DAR_sig(context)                        EXCEPREG_sig(dar, context)     /* Fault registers for coredump */
1333 83fb7adf bellard
# define DSISR_sig(context)                        EXCEPREG_sig(dsisr, context)
1334 83fb7adf bellard
# define TRAP_sig(context)                        EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
1335 83fb7adf bellard
#endif /* __APPLE__ */
1336 83fb7adf bellard
1337 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1338 e4533c7a bellard
                       void *puc)
1339 2b413144 bellard
{
1340 5a7b542b ths
    siginfo_t *info = pinfo;
1341 25eb4484 bellard
    struct ucontext *uc = puc;
1342 25eb4484 bellard
    unsigned long pc;
1343 25eb4484 bellard
    int is_write;
1344 25eb4484 bellard
1345 83fb7adf bellard
    pc = IAR_sig(uc);
1346 25eb4484 bellard
    is_write = 0;
1347 25eb4484 bellard
#if 0
1348 25eb4484 bellard
    /* ppc 4xx case */
1349 83fb7adf bellard
    if (DSISR_sig(uc) & 0x00800000)
1350 25eb4484 bellard
        is_write = 1;
1351 25eb4484 bellard
#else
1352 83fb7adf bellard
    if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
1353 25eb4484 bellard
        is_write = 1;
1354 25eb4484 bellard
#endif
1355 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1356 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1357 2b413144 bellard
}
1358 2b413144 bellard
1359 2f87c607 bellard
#elif defined(__alpha__)
1360 2f87c607 bellard
1361 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1362 2f87c607 bellard
                           void *puc)
1363 2f87c607 bellard
{
1364 5a7b542b ths
    siginfo_t *info = pinfo;
1365 2f87c607 bellard
    struct ucontext *uc = puc;
1366 2f87c607 bellard
    uint32_t *pc = uc->uc_mcontext.sc_pc;
1367 2f87c607 bellard
    uint32_t insn = *pc;
1368 2f87c607 bellard
    int is_write = 0;
1369 2f87c607 bellard
1370 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1371 2f87c607 bellard
    switch (insn >> 26) {
1372 2f87c607 bellard
    case 0x0d: // stw
1373 2f87c607 bellard
    case 0x0e: // stb
1374 2f87c607 bellard
    case 0x0f: // stq_u
1375 2f87c607 bellard
    case 0x24: // stf
1376 2f87c607 bellard
    case 0x25: // stg
1377 2f87c607 bellard
    case 0x26: // sts
1378 2f87c607 bellard
    case 0x27: // stt
1379 2f87c607 bellard
    case 0x2c: // stl
1380 2f87c607 bellard
    case 0x2d: // stq
1381 2f87c607 bellard
    case 0x2e: // stl_c
1382 2f87c607 bellard
    case 0x2f: // stq_c
1383 2f87c607 bellard
        is_write = 1;
1384 2f87c607 bellard
    }
1385 2f87c607 bellard
1386 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1387 bf3e8bf1 bellard
                             is_write, &uc->uc_sigmask, puc);
1388 2f87c607 bellard
}
1389 8c6939c0 bellard
#elif defined(__sparc__)
1390 8c6939c0 bellard
1391 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1392 e4533c7a bellard
                       void *puc)
1393 8c6939c0 bellard
{
1394 5a7b542b ths
    siginfo_t *info = pinfo;
1395 8c6939c0 bellard
    uint32_t *regs = (uint32_t *)(info + 1);
1396 8c6939c0 bellard
    void *sigmask = (regs + 20);
1397 8c6939c0 bellard
    unsigned long pc;
1398 8c6939c0 bellard
    int is_write;
1399 8c6939c0 bellard
    uint32_t insn;
1400 3b46e624 ths
1401 8c6939c0 bellard
    /* XXX: is there a standard glibc define ? */
1402 8c6939c0 bellard
    pc = regs[1];
1403 8c6939c0 bellard
    /* XXX: need kernel patch to get write flag faster */
1404 8c6939c0 bellard
    is_write = 0;
1405 8c6939c0 bellard
    insn = *(uint32_t *)pc;
1406 8c6939c0 bellard
    if ((insn >> 30) == 3) {
1407 8c6939c0 bellard
      switch((insn >> 19) & 0x3f) {
1408 8c6939c0 bellard
      case 0x05: // stb
1409 8c6939c0 bellard
      case 0x06: // sth
1410 8c6939c0 bellard
      case 0x04: // st
1411 8c6939c0 bellard
      case 0x07: // std
1412 8c6939c0 bellard
      case 0x24: // stf
1413 8c6939c0 bellard
      case 0x27: // stdf
1414 8c6939c0 bellard
      case 0x25: // stfsr
1415 8c6939c0 bellard
        is_write = 1;
1416 8c6939c0 bellard
        break;
1417 8c6939c0 bellard
      }
1418 8c6939c0 bellard
    }
1419 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1420 bf3e8bf1 bellard
                             is_write, sigmask, NULL);
1421 8c6939c0 bellard
}
1422 8c6939c0 bellard
1423 8c6939c0 bellard
#elif defined(__arm__)
1424 8c6939c0 bellard
1425 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1426 e4533c7a bellard
                       void *puc)
1427 8c6939c0 bellard
{
1428 5a7b542b ths
    siginfo_t *info = pinfo;
1429 8c6939c0 bellard
    struct ucontext *uc = puc;
1430 8c6939c0 bellard
    unsigned long pc;
1431 8c6939c0 bellard
    int is_write;
1432 3b46e624 ths
1433 8c6939c0 bellard
    pc = uc->uc_mcontext.gregs[R15];
1434 8c6939c0 bellard
    /* XXX: compute is_write */
1435 8c6939c0 bellard
    is_write = 0;
1436 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1437 8c6939c0 bellard
                             is_write,
1438 f3a9676a pbrook
                             &uc->uc_sigmask, puc);
1439 8c6939c0 bellard
}
1440 8c6939c0 bellard
1441 38e584a0 bellard
#elif defined(__mc68000)
1442 38e584a0 bellard
1443 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1444 38e584a0 bellard
                       void *puc)
1445 38e584a0 bellard
{
1446 5a7b542b ths
    siginfo_t *info = pinfo;
1447 38e584a0 bellard
    struct ucontext *uc = puc;
1448 38e584a0 bellard
    unsigned long pc;
1449 38e584a0 bellard
    int is_write;
1450 3b46e624 ths
1451 38e584a0 bellard
    pc = uc->uc_mcontext.gregs[16];
1452 38e584a0 bellard
    /* XXX: compute is_write */
1453 38e584a0 bellard
    is_write = 0;
1454 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1455 38e584a0 bellard
                             is_write,
1456 bf3e8bf1 bellard
                             &uc->uc_sigmask, puc);
1457 38e584a0 bellard
}
1458 38e584a0 bellard
1459 b8076a74 bellard
#elif defined(__ia64)
1460 b8076a74 bellard
1461 b8076a74 bellard
#ifndef __ISR_VALID
1462 b8076a74 bellard
  /* This ought to be in <bits/siginfo.h>... */
1463 b8076a74 bellard
# define __ISR_VALID        1
1464 b8076a74 bellard
#endif
1465 b8076a74 bellard
1466 5a7b542b ths
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
1467 b8076a74 bellard
{
1468 5a7b542b ths
    siginfo_t *info = pinfo;
1469 b8076a74 bellard
    struct ucontext *uc = puc;
1470 b8076a74 bellard
    unsigned long ip;
1471 b8076a74 bellard
    int is_write = 0;
1472 b8076a74 bellard
1473 b8076a74 bellard
    ip = uc->uc_mcontext.sc_ip;
1474 b8076a74 bellard
    switch (host_signum) {
1475 b8076a74 bellard
      case SIGILL:
1476 b8076a74 bellard
      case SIGFPE:
1477 b8076a74 bellard
      case SIGSEGV:
1478 b8076a74 bellard
      case SIGBUS:
1479 b8076a74 bellard
      case SIGTRAP:
1480 fd4a43e4 bellard
          if (info->si_code && (info->si_segvflags & __ISR_VALID))
1481 b8076a74 bellard
              /* ISR.W (write-access) is bit 33:  */
1482 b8076a74 bellard
              is_write = (info->si_isr >> 33) & 1;
1483 b8076a74 bellard
          break;
1484 b8076a74 bellard
1485 b8076a74 bellard
      default:
1486 b8076a74 bellard
          break;
1487 b8076a74 bellard
    }
1488 b8076a74 bellard
    return handle_cpu_signal(ip, (unsigned long)info->si_addr,
1489 b8076a74 bellard
                             is_write,
1490 b8076a74 bellard
                             &uc->uc_sigmask, puc);
1491 b8076a74 bellard
}
1492 b8076a74 bellard
1493 90cb9493 bellard
#elif defined(__s390__)
1494 90cb9493 bellard
1495 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1496 90cb9493 bellard
                       void *puc)
1497 90cb9493 bellard
{
1498 5a7b542b ths
    siginfo_t *info = pinfo;
1499 90cb9493 bellard
    struct ucontext *uc = puc;
1500 90cb9493 bellard
    unsigned long pc;
1501 90cb9493 bellard
    int is_write;
1502 3b46e624 ths
1503 90cb9493 bellard
    pc = uc->uc_mcontext.psw.addr;
1504 90cb9493 bellard
    /* XXX: compute is_write */
1505 90cb9493 bellard
    is_write = 0;
1506 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1507 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1508 c4b89d18 ths
}
1509 c4b89d18 ths
1510 c4b89d18 ths
#elif defined(__mips__)
1511 c4b89d18 ths
1512 5fafdf24 ths
int cpu_signal_handler(int host_signum, void *pinfo,
1513 c4b89d18 ths
                       void *puc)
1514 c4b89d18 ths
{
1515 9617efe8 ths
    siginfo_t *info = pinfo;
1516 c4b89d18 ths
    struct ucontext *uc = puc;
1517 c4b89d18 ths
    greg_t pc = uc->uc_mcontext.pc;
1518 c4b89d18 ths
    int is_write;
1519 3b46e624 ths
1520 c4b89d18 ths
    /* XXX: compute is_write */
1521 c4b89d18 ths
    is_write = 0;
1522 5fafdf24 ths
    return handle_cpu_signal(pc, (unsigned long)info->si_addr,
1523 c4b89d18 ths
                             is_write, &uc->uc_sigmask, puc);
1524 90cb9493 bellard
}
1525 90cb9493 bellard
1526 9de5e440 bellard
#else
1527 2b413144 bellard
1528 3fb2ded1 bellard
#error host CPU specific signal handler needed
1529 2b413144 bellard
1530 9de5e440 bellard
#endif
1531 67b915a5 bellard
1532 67b915a5 bellard
#endif /* !defined(CONFIG_SOFTMMU) */