Statistics
| Branch: | Revision:

root / cpu-exec.c @ a7812ae4

History | View | Annotate | Download (52.1 kB)

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