Statistics
| Branch: | Revision:

root / cpu-exec.c @ a7037b29

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