Statistics
| Branch: | Revision:

root / cpu-exec.c @ 50443c98

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