Statistics
| Branch: | Revision:

root / cpu-exec.c @ a13d7523

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