Statistics
| Branch: | Revision:

root / cpu-exec.c @ 551bd27f

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