Statistics
| Branch: | Revision:

root / cpu-exec.c @ 6e473128

History | View | Annotate | Download (51.7 kB)

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